Getting Started with Grasshopper 2 Plugins

This guide is for anyone who wants to write a Grasshopper 2 plugin, whether you have written Grasshopper 1 components or plugins before or not. There is no code in here. This guide should help you get started, and aims at filling gaps by pointing you at hard-to-find places in the rest of the documentation.

Prerequisites

Grasshopper 2 requires Rhino 9 and the C# development tools. See Installing Tools (Windows, Mac).

Templates

There are project templates for Visual Studio, Visual Studio Code, and the command line:

  • Visual Studio: install the Rhino Visual Studio Extension. Look for the Grasshopper 2 Plug-In for Rhino (C#) template.
  • Visual Studio Code and the command line: run dotnet new install Rhino.Templates, then dotnet new gh2.

Both templates reference the Grasshopper2 NuGet package. It contains the reference assemblies and the API documentation. Please note that your plugin won’t load on any Rhino version prior to that NuGet package’s version. To address the largest audience, we recommend targeting the 9.0 version. Choose a later version only if you are sure you need features that are not in 9.0.

Do You Need a Plugin?

Not every developer needs to ship a plugin. Grasshopper 2 has script components for C# and Python. For a one-off tool, or to try an idea, a script component can be faster. In some cases, a Grasshopper 2 snippet might be sufficient to share your functionality. See Grasshopper 2 Scripting (C#, Python).

Write a plugin when you want to share your components, give them icons and documentation, or ship them with a Rhino plugin.

Learn Grasshopper 2 First

Grasshopper 2 ships with plenty of documentation written for users. It is also the best place to learn the concepts the SDK is built on: the solution, components, parameters, data trees, and preview geometry.

To open it:

  1. In Grasshopper 2, click Help > Documentation…, or press F1.
  2. In Rhino, run the GH2Docs command.

The documentation is live in the sense that many pages contain live Grasshopper documents. You can drag them onto the canvas and try them out.

A read-only copy is available on the web at rhino3d.com/docs/grasshopper2.

Open Your Grasshopper 1 Files

Grasshopper 2 opens Grasshopper 1 files, both .gh and .ghx. Try it on your own existing files. It is a quick way to see how familiar things look in Grasshopper 2.

Copy and paste works from Grasshopper 1 to Grasshopper 2. Select any part of a Grasshopper 1 definition containing one or more components and wires, copy it, and paste it onto the Grasshopper 2 canvas. The wires between the pasted components come along. Wires to components you did not copy are dropped. Use the plain Paste command for this; the Paste in Place and other paste variants do not understand Grasshopper 1 content. The other direction, from Grasshopper 2 to Grasshopper 1, does not work.

Dragging works too, from the Grasshopper 1 tool panels onto the Grasshopper 2 canvas.

Behind this is a migration framework. Each Grasshopper 1 component is either migrated to its Grasshopper 2 counterpart, or hosted in an interop component that still runs on Grasshopper 1. If you have a Grasshopper 1 plugin, you can supply migrations for your own components. Implement IMigrateComponent or IMigrateParameter from the Grasshopper2.Doc.Migration namespace, or use Gh1MigrationRule for simple one-to-one cases. Grasshopper 2 finds these types in your plugin on its own.

Document Your Components

Your users will expect documentation for your components too. You write it with the same tools we use. Run the GH2DocsAuthoring command in Rhino to get started. Documentation shipped with your plugin will get loaded automatically by Grasshopper 2 and be available to your users. While you author documentation, it is helpful to know about the Help > Custom Folders… menu to point at your working folder.

Icons

Grasshopper 2 icons are 2D drawings, but the recommended way to design them is in Rhino, which is a 3D editor. This may sound intimidating, but it is not. The icons stay sharp at any size, and they follow the light and dark themes on their own.

The tool is the GH2 Icon panel in Rhino. It appears once Grasshopper 2 has been loaded, for example after running the GH2 command. To try it:

  1. Run GH2IconSetup to set the icon size.
  2. Draw some curves. Select them. Set edges and fills in the GH2 Icon panel.
  3. Click Save in the panel’s preview to export a .ghicon file.
  4. Embed the .ghicon file in your project as a resource. Name it after your component class, for example MyComponent.ghicon.

That is all. You do not need to write any icon code. Grasshopper 2 looks for an embedded resource with the name of the class and loads it. Almost all of Grasshopper 2’s own components get their icons this way. Only the plugin icon needs one line of code, in your plugin class: Icon = AbstractIcon.FromResource("MyPlugin", typeof(MyPluginInfo));.

Colours have a meaning in Grasshopper 2. You do not pick an RGB value. You pick a role, such as Input, Output, or Analysis. Grasshopper 2 picks the actual colour for the current theme. The GH2 Icon panel offers these roles.

There are two other ways to supply an icon. Both need an override of the IconInternal property in your component class.

  • SVG. SVG icons use the same colour roles. Write fill="gh:Input" instead of a fixed colour, for example. Embed the .svg file as a resource and return SvgIcon.FromResource(GetType().Assembly, "MyComponent.svg"). SvgIcon lives in the Grasshopper2.UI.Icon.Vector namespace, not in AbstractIcon.
  • Bitmap. An existing PNG or other bitmap becomes an icon with AbstractIcon.FromBitmap. Treat this as an emergency fallback only. Bitmap icons are not sharp at every size, and they ignore the colour roles, so they look out of place next to the others.

Six Rules for Component Code

Grasshopper 2 looks a lot like Grasshopper 1 from the outside. Inside, it is a different machine. Six habits from Grasshopper 1 will not carry over immediately. If you are new to Grasshopper altogether, the same six rules will save you the most time. They are easy to miss, and experience shows that many developers, including the author, miss one or more of them even repeatedly.

  1. Inputs are immutable. Neither in Grasshopper 1 nor in Grasshopper 2 can you modify input data in place. However, doing so often had no bad consequences in Grasshopper 1. In Grasshopper 2 it can have much more dire consequences because it is inherently multi-threaded. Components solve in parallel by default, so several components may read the same data at the same time. This could lead to data corruption and hard-to-debug crashes.

    Duplicate before you modify, to prevent those. This applies to geometry too: duplicate a curve, mesh, or Brep before you transform or edit it. When in doubt, duplicate.

  2. Long loops must be cancellable. The user can interrupt the solver at any time. Check access.Solution.Token for cancellation frequently, and let the exception it throws propagate, or simply return early without throwing. Doing so is very fast and won’t affect your plugin’s performance considerably. Any component whose solver does anything non-trivial must periodically check its cancellation token.

  3. The access level is a contract. Each parameter is declared as Item, Twig, or Tree. That decides which access.Get... and access.Set... methods you call on it. The wrong one may compile and fail at run time. This is similar to how Grasshopper 1 operates, but is still easy to miss.

  4. Not every type comes from RhinoCommon. Some types that look like RhinoCommon types are Grasshopper 2 types, for example Angle, Colour, and Grasshopper2.Types.Shapes.Triangle. Check the namespace before you reach for the Rhino version.

  5. Look it up before you write it. The Grasshopper2 NuGet package ships the full XML documentation. Your IDE shows it as you type. The API is new. Guessing a name from Grasshopper 1 is the most common cause of code that does not compile.

  6. Every component needs two constructors. Next to the usual parameterless constructor, a component class must have a constructor that takes an IReader. In most cases it only forwards to the base class:

    public MyComponent(IReader reader) : base(reader) { }
    

    Grasshopper 2 uses it to restore your component from a file. Without it, the component compiles, shows up, and runs, but it cannot be read back from a saved file, and copy, paste, and undo fail for it. The Grasshopper > Plugins… window lists the class as a problem, with the reason “No accessible constructor with a single IReader argument.” The project template includes this constructor. Do not delete it.

See Component Processing in the migration guide for the details on threading and cancellation.

Meta Data

Every value in Grasshopper 2 can carry meta data, such as a colour or a layer name. You will read about this in the documentation and in the migration guide. You do not need to understand it before you write your first component. In simple components, Grasshopper 2 passes meta data from inputs to outputs for you. Learn about it when you need it.

Styling Your Components

Grasshopper 2 lets you change how your component looks and behaves on the canvas. The entry point is the IAttributes interface. Every document object has one. It handles layout, drawing, and mouse interaction, like GH_ComponentAttributes did in Grasshopper 1.

To customise a component, override CreateAttributes() in your component class and return your own subclass of Grasshopper2.Doc.Attributes.ComponentAttributes. Then override the drawing methods you need, such as DrawBackground, DrawContent, or DrawOutputs. Colours come from the Skin passed to every drawing method. Do not hard-code them.

Start reading in the API documentation at Grasshopper2.Doc.IAttributes and Grasshopper2.Doc.Attributes.ComponentAttributes.

Note: All custom drawing uses Eto, not WinForms or GDI+. It must work on both Windows and Mac.

Preview Geometry

Grasshopper 2 previews the geometry on your outputs on its own. You do not write any display code for that. So the simple rule is: put everything you want to see in the viewport on an output.

If you need extra preview geometry that is not an output, override PopulateDisplay. It hands you a DisplayBag, and you add points, curves, vectors, planes, and text to it. Grasshopper 2 caches the bag and draws it. This replaces DrawViewportWires from Grasshopper 1, and it is not called once per frame, so do not try to animate with it.

Note: There is no replacement for DrawViewportMeshes yet. The DisplayBag has no method for shaded meshes, and the per-frame DisplayFaces override is not finished for plugin use. Until that changes, put your meshes on an output and let Grasshopper 2 preview them.

Your Plugin’s Id

Rhino identifies your plugin by the GUID of its assembly. This is the [assembly: Guid("...")] attribute in your project. The template generates one for you. Keep it. Never change it once you have shipped.

[assembly: Guid("88888888-4444-4444-4444-121212121212")]

If you ship more than one assembly:

  • Assemblies that replace each other share the same id. For example, a build for .NET 8 and a build for another .NET version. Only one of them is ever loaded.
  • Assemblies that are loaded at the same time need different ids.

Rhino Commands in Your Plugin

Your assembly may also contain a Rhino plugin class and Rhino commands. A Rhino plugin class is one that derives from Rhino.PlugIns.PlugIn. Both share the assembly’s id.

Note: If such a Rhino command uses Grasshopper 2, Grasshopper 2 must be running first. It is not enough that the assembly is loaded. The GH2 command has to have run at least once. Make sure of this in your command before you call into Grasshopper 2.

Writing to the Rhino Document

Most components never touch the Rhino document, and that is how it should be. If yours needs to, read this.

Note: Never modify the Rhino document from your solver. Access to the Rhino document is not thread-safe, and your Process method runs on a worker thread, often several at once. Do not add objects to the document, do not edit the layer table, and do not change document settings from inside Process. Compute your results and set them on your outputs. If your plugin has to write to the document, do it from a Rhino command, a menu action, or a bake, where Grasshopper 2 and Rhino control the timing.

Native Code

You can call C or C++ code from your plugin. See Wrapping Native Libraries and the Moose sample on GitHub. Moose shares one C++ library between a Rhino C++ plugin, a RhinoCommon plugin, and a Grasshopper component.

Note: Compile your native code against the Rhino C/C++ SDK, not against the public openNURBS toolkit. The SDK exists for Mac too; see Installing Tools (Mac) for the C++ side. The two are not binary compatible. A library built on public openNURBS cannot exchange geometry with Rhino in memory.

Testing Your Plugin

The templates set up debugging for you. Press F5 and Rhino starts with your plugin.

To see whether your plugin loaded, run the GH2Plugins command in Rhino. It opens the plugin window, the same one as Grasshopper > Plugins… in Grasshopper 2. The window lists every plugin Grasshopper 2 found, whether it loaded, and why not if it failed. It also lists problems in loaded plugins under Invalid types, such as a component class without the IReader constructor.

To load a build by hand, click Install… in that window and pick your .rhp file. Grasshopper 2 remembers it and loads it again next time.

Note: Grasshopper 2 autosaves. After an edit, it writes a .ghautosave file next to the open file, or into the UnnamedFiles folder under your local application data for unsaved documents. There is currently no setting to turn this off. Keep it in mind when you debug: every autosave serialises the document, so your component’s Store method runs after many edits, not only when the user saves.

Publishing Your Plugin

Publish your plugin with the Package Manager. The yak build command recognises Grasshopper 2 plugins. The Yak guides were written for Rhino and Grasshopper 1 plugins, but the steps are the same.

Working With an AI Assistant

Many developers write Grasshopper 2 code with an AI assistant. These models were trained on Grasshopper 1 code. Left alone, they will write Grasshopper 1 code with new names, and it will not compile or not behave.

The six rules above apply to your assistant as much as to you. Put them in a short instruction file in your project, and point the assistant to this page and to the migration guide.

Next Steps

Start with Your First Component (Windows, Mac). It takes you from the project template to a running component.

Then read Migrating Components to Grasshopper 2. Despite the title, it is the most complete description of the Grasshopper 2 SDK so far. It is long. You do not need to read it in one go. Keep it as a reference.