Introduction
Grasshopper2ɑ now ships as a pre-alpha package that can be installed in Rhino 8 using the package manager. While it’s way too early to expect any kind of SDK, documentation or development support from McNeel for GH2, it’s still exciting to see the differences behind the curtains. If you’re inclined to do so, it’s also possible to develop plugins for it already. While the APIs will likely change very frequently with every release, it might be useful to some developers who might be considering porting their Grasshopper 1 plugins to GH2.
This guide will walk you through setting up a C# project in Visual Studio to get started with plugin development for GH2. Since there are no templates, tutorials or official documentation, some manual setup and fiddling is required. The goal is to simply get you started - any advanced development is beyond the scope for this guide.
Moving forward, this guide will presume that you have sufficient knowledge of C#, Visual Studio, GH & GH2 and have some experience with developing GH plugins.
It's not recommended to rely on early versions of any software for production or business purposes. Developing a GH2 plugin at this stage is a cool experiment or a way to prepare your original Grasshopper plugins for the day GH2 gets a full release.
Prerequisites should be pretty obvious if you know what you’re doing; Rhino 8 with GH2 installed and Visual Studio.
Project Setup
To begin, create a new empty C# project in Visual Studio, and modify the .csproj to make it match the code shown below:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<TargetExt>.rhp</TargetExt>
</PropertyGroup>
<PropertyGroup>
<GH2Version>2.0.8951-wip.36351</GH2Version>
</PropertyGroup>
<ItemGroup>
<Reference Include="Grasshopper2"> <HintPath>$(AppData)\McNeel\Rhinoceros\packages\8.0\Grasshopper2\$(GH2Version)\Grasshopper2.dll</HintPath>
</Reference>
<Reference Include="GrasshopperIO"> <HintPath>$(AppData)\McNeel\Rhinoceros\packages\8.0\Grasshopper2\$(GH2Version)\GrasshopperIO.dll</HintPath>
</Reference>
<Reference Include="Rhino.UI">
<HintPath>C:\Program Files\Rhino 8\System\Rhino.UI.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<PropertyGroup> <PluginsDir>$(AppData)\McNeel\Rhinoceros\packages\8.0\Grasshopper2\$(GH2Version)\Components\TestGH2Plugin\</PluginsDir>
</PropertyGroup>
<Target Name="InstallPlugin" AfterTargets="PostBuildEvent" Condition=" '$(Configuration)' == 'Debug' ">
<Copy SourceFiles="$(OutputPath)TestGH2Plugin.rhp" DestinationFiles="$(PluginsDir)TestGH2Plugin.rhp" SkipUnchangedFiles="true" />
</Target>
<PropertyGroup Condition="$(Configuration) == 'Debug' AND $([MSBuild]::IsOSPlatform(Windows))">
<StartProgram>C:\Program Files\Rhino 8\System\Rhino.exe</StartProgram>
<StartArguments>/runscript="_G2"</StartArguments>
<StartAction>Program</StartAction>
</PropertyGroup>
</Project>
Your .csproj may look different, but all the crucial components must be present from this snippet - especially the references. Note that unlike old Grasshopper plugins, GH2 plugins are no longer .gha files but instead load as .rhp files. The directory for installing plugins is also different, but this is likely to change once GH2 gets a full release.
The GH2Version variable (highlighted in orange) is a useful utility to keep up with the latest update of GH2. It's still in active development, so updates and changes are to be expected with reasonable frequency. Sometimes, this may mean breaking changes for your plugin as well; Beware. Be sure to update this version number every time GH2 is updated on your machine. To get the currently installed version number, navigate to the "%APPDATA%\McNeel\Rhinoceros\packages\8.0\Grasshopper2\" directory and check the "manifest.txt" file.
Once the .csproj file is set up, add a new .cs class file called TestGH2PluginInfo.cs. Similar to GH1, this Info class will contain all the basic info about the plugin, such as the name, author, contact, icon, etc. There are many differences from the old API to take care of here. Also, the Icon system in GH2 has been revamped with a vector-based system. If you are inclined to do so, you can set vector icons for your plugin and components.
using Grasshopper.Framework;
namespace TestGH2Plugin
{
public class TestGH2PluginInfo : Plugin
{
public TestGH2PluginInfo()
: base(
new Guid("da3daa94-946a-49c2-bb6d-468d0ded7669"),
new Grasshopper.UI.Nomen(
"GH2Test", "GH2Test", "GH2Test", "GH2Test", 0,
Grasshopper.UI.Rank.Important),
new Version("1.0.0.0"))
{
}
public override string Author => "Praneet Mathur";
public override string Contact => "contact@praneetmathur.com";
public override string Copyright => $"Copyright ©
{DateTime.UtcNow.Year} Praneet Mathur";
}
}
First Component
With the Info class set up, we can move on to creating our first component.
There are many differences between the API for components in GH1 and GH2. Highlighting each difference is beyond the scope of this guide. Below is a boilerplate snippet for an empty component.
using Grasshopper.Components;
using GrasshopperIO;
namespace TestGH2Plugin
{
[IoId("b08b9671-d77b-45c3-92a2-xxxxxxxxxxxx")]
public class GH2Component : Component
{
/// <summary>
/// Each implementation of Component must provide a public
/// constructor without any arguments.
/// The Nomen object contains component information to be displayed.
/// </summary>
public GH2Component()
: base(new Grasshopper.UI.Nomen(
"GH2Component",
"GH2Comp",
"TestGH2Plugin",
"GH2Plugin"))
{
}
/// <summary>
/// Registers all the input parameters for this component.
/// </summary>
protected override void AddInputs(InputAdder inputs)
{
}
/// <summary>
/// Registers all the output parameters for this component.
/// </summary>
protected override void AddOutputs(OutputAdder outputs)
{
}
/// <summary>
/// This is the method that actually does the work.
/// </summary>
/// <param name="access">The access object can be used to retrieve data from
input parameters and
/// to store data in output parameters.</param>
protected override void Process(IDataAccess access)
{
}
}
}
Ensure that the class is given an 'IoId' attribute (enclosed in square brackets above the class) to determine the component's unique Guid - you can use a Guid generator to get one. Components without this attribute will not be loaded in GH2. The three methods are structured very similar to the three implemented in GH1 components.
The first AddInputs method is where the input parameters are initialized. The second AddOutputs method is where the output parameters are initialized and the third Process method is the computation logic of the component.
Finishing up
You can continue adding all the components needed for your plugin.
Building the project will automatically copy the built .rhp file to the GH2 Components folder and debugging the plugin should automatically open GH2 with the plugin loaded.
Building custom parameters, modifying the UI elements of components and more advanced development is beyond the scope of this guide, but if that's something you're interested in doing - use the button at the bottom to reach out!
If this guide helped you build something cool, share it with your colleagues and network!
If you're a computational designer using Grasshopper,
Share your opinion about GH2
Haven't tried it, not enough interest yet
Tried it, not very impressed
It has a long way to go still
Love it, very excited
If you'd like to know more about GH2 and how you can develop advanced computational design tools for your business, reach out using the button below: