Click or drag to resize

Simple Component (C#)

This article contains an exhaustive, step by step explanation of how to build your first component in C#. It will skip over any complicated issues (such as mathematics, geometry and data handling) in order to reduce the totality of new concepts. You will however need to have a good understanding of basic OOP concepts such as classes, types and inheritance. If you do not understand these DotNET essentials, we recommend you start with some other reading material first.

Grasshopper.Kernel.GH_Component

All you need to do in order to define a new component is to inherit from the GH_Component base class in Grasshopper. Assuming you've set up your project correctly, create a new, blank class in your project:

At this point a new file should be created (MyFirstComponent.cs) with the following content:

C#
using System;
using System.Collections.Generic;
using System.Text;

namespace MyFirstProject
{
  public class MyFirstComponent
  {
  }
}
Since we'll be using primarily types from the Grasshopper.Kernel namespace. We'll import this namespace so that we have easy access to all types contained within it (unless otherwise specified, all further types discussed in this topic belong to Grasshopper.Kernel). We can also remove some unnecessary using statements while we're at it:
C#
using System;
using Grasshopper.Kernel;

namespace MyFirstProject
{
  public class MyFirstComponent
  {
  }
}
The idea is that this class will be loaded by Grasshopper whenever this component library is loaded, but in order for that to happen we must make sure that this class is 'visible' from outside this project. I.e., we need to make the accessor public:
C#
using System;
using Grasshopper.Kernel;

namespace MyFirstProject
{
  // If a class is not public, it won't be visible 
  // from where Grasshopper is sitting.
  public class MyFirstComponent
  {
  }
}
Now, we need to derive our MyFirstComponent class from the GH_Component base class defined inside Grasshopper. GH_Component takes care of almost all the complicated actions and mannerisms that constitute a component. It will handle data conversion, GUI, menus, file Input/Output, Error trapping and much, much more. This allows us to focus only on the unique aspects of our component. In order to derive from GH_Component, add the following line directly underneath the class declarator:
C#
using System;
using Grasshopper.Kernel;

namespace MyFirstProject
{
  public class MyFirstComponent : GH_Component
  {
  }
}
Deriving (inheriting) from GH_Component requires you to implement a number of methods. Visual Studio can insert default implementations for all of these via the Implement Abstract Class menu option:

At this point you should see the following:

C#
using System;
using Grasshopper.Kernel;

namespace MyFirstProject
{
  public class MyFirstComponent : GH_Component
  {
    protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
    {
      throw new NotImplementedException();
    }

    protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
    {
      throw new NotImplementedException();
    }

    protected override void SolveInstance(IGH_DataAccess DA)
    {
      throw new NotImplementedException();
    }

    public override Guid ComponentGuid
    {
      get { throw new NotImplementedException(); }
    }
  }
}

The Component Constructor

As we've seen in the previous section, Visual Studio will populate the MyFirstComponent class with a collection of properties and methods that we need to implement. There is however another method that requires our attention that is missing. This is the constructor. The constructor is a special method inside each class which gets called when the class is instantiated (or "constructed"). This can happen only once (we feeble humans can only be born once as well after all) and it necessarily happens before anything else is allowed to happen. The GH_Component base class has a constructor which is not empty, so we have to call that constructor from within our constructor and supply it with all the information it needs. Add the following code near the top of the MyFirstComponent class:

C#
using System;
using Grasshopper.Kernel;

namespace MyFirstProject
{
  public class MyFirstComponent : GH_Component
  {
    public MyFirstComponent() : base("MyFirst", "MFC", "My first component", "Extra", "Simple")
    {
    }
  ...
As you can see we need to supply a set of text constants, which are used to name and identify our component within the Grasshopper GUI. The text fields are:

ParameterPurpose
nameThe name of our component. The name is what appears on tooltips and panel dropdowns.
abbreviationThe abbreviation of our component. The abbreviation is what is written on the component once it appears on the canvas.
descriptionA description of our component. The description is used on tooltips to provide users with a more detailed idea about what this component is for.
categoryThe tab category for the component. The category equals the name of the tab onto which the component will appear. If a non-existing category is supplied, a new Tab will be added to the Grasshopper GUI.
subCategoryThe panel category for the component. The sub-category equals the name of the panel onto which the component will appear. If a non-existing sub-category is supplied, a new Panel will be added to the Category Tab.

Component Guids

Every type of object inside a Grasshopper document must have a ComponentGuid associated with it. When a Grasshopper file (*.gh or *.ghx) is written these Guids are used as markers, so it becomes clear what portions of the file belong to which object. When the file is read back in, that marker is compared against the list of all cached components and if a match is found the appropriate component is asked to deserialize itself from the appropriate file portion. When no matching component can be found it is assumed that whoever wrote the file had access to certain components that are not available locally, and that portion of the file is dutifully skipped.

So, long story short, we need to invent a Guid (Globally Unique IDentifier) that will positively and unerringly indicate this component. You can generate new Guids using an Online Guid Generator or Microsofts popular guidgen.exe. Never re-use a Guid and never edit one by hand. Always generate a proper one using an official tool.

Once you have a new Guid standing by, modify the ComponentGuid property to return it:

C#
...
public override Guid ComponentGuid
{
  get { return new Guid("419c3a3a-cc48-4717-8cef-5f5647a5ecfc"); }
}
...

Parameter Registration

Components have unique input and output parameters which are most often fixed. We are ignoring those rare cases where a component either has no inputs or no outputs, or where there is a variable number of parameters. There are two methods that allow you to define (or "register") these parameters. These routines are called from within the base class constructor and they are only called once. Let's have a look at the default implementation that Visual Studio generated again:

C#
...
protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
{
  throw new NotImplementedException();
}

protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
{
  throw new NotImplementedException();
}
...
Although it would technically be possible to manually register parameters, we highly recommend you use the methods on pManager. pManager has methods for adding all the basic parameter types and it often even allows you to specify default values:

In this example we'll only create two parameters (one input, one output) and they will both be of type String.

C#
...
protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
{
  pManager.AddTextParameter("String", "S", "String to reverse", GH_ParamAccess.item); 
}

protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
{
  pManager.AddTextParameter("Reverse", "R", "Reversed string", GH_ParamAccess.item);
}
...
When we compile this project (assuming it has been setup correctly), the component will already be available on the Grasshopper tabs and it can be placed onto the canvas:

The Solver Routine

Our new component sure looks perky and expensive, but it doesn't do anything yet. We still need to write the contents of the SolveInstance() subroutine, which is where all the action takes place. The SolveInstance() function is called upon whenever the component needs to handle input data. In this particular example, if we plug a list of twelve strings into the [S] parameter, SolveInstance() will be called twelve times.

As you may already have guessed, the component we're writing will reverse a given textual string from [S] and output the result to [R]. Since we're operating on individual items of data (the default behaviour), all we need to do inside the SolveInstance() function is retrieve the current String from [S], reverse it and assign it to [R]. Now, String reversal is not a function that is directly available in the framework String type, so we need to actually do some thinking:

C#
...
protected override void SolveInstance(IGH_DataAccess DA)
{
  // Declare a variable for the input String
  string data = null;

  // Use the DA object to retrieve the data inside the first input parameter.
  // If the retieval fails (for example if there is no data) we need to abort.
  if (!DA.GetData(0, ref data)) { return; }

  // If the retrieved data is Nothing, we need to abort.
  // We're also going to abort on a zero-length String.
  if (data == null) { return; }
  if (data.Length == 0) { return; }

  // Convert the String to a character array.
  char[] chars = data.ToCharArray();

  // Reverse the array of character.
  System.Array.Reverse(chars);

  // Use the DA object to assign a new String to the first output parameter.
  DA.SetData(0, new string(chars));
}
...