How to pass custom data between Grasshopper components

Grasshopper is designed to work with components that handle specific functions, rather than components which try to do an ‘all-in-one’ approach. When designing your own custom Grasshopper components, there might be a need to pass custom data along the wires between components. This is easy enough to do when you know how, but getting to that point might be a bit tricky. Hopefully this post will enlighten some, and serve as a reminder for me, on how we can pass custom data between Grasshopper components.

Generic Parameters

Generic Parameters are our friend in this endeavour. They allow us to make use of the inheritance structure available in C# (and to a certain extent, Grasshopper) to wrap our custom data up and pass it along. Using generic parameters is fairly easy, you simply register them with the Grasshopper param manager (either input or output) like so:

protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
{
    pManager.AddGenericParameter("Param Name", "Param Nickname", "Param description", GH_ParamAccess.item); //Or list or tree as appropriate
}

protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
{
    pManager.AddGenericParameter("Param Name", "Param Nickname", "Param Description", GH_ParamAccess.item); //Or list or tree as appropriate
}

Passing custom data out of a component

To pass custom data out of a component you need to register a generic parameter as one of the output parameters. As the name suggests, the generic parameter will accept any data (it’ll cast it up to a data type it can work with, most likely System.Object or Grasshopper equivalent). For the purpose of demonstration, let’s assume we have a class Foo with some data types, as below.

public class Foo
{
    int age = 10;
    double bankBalance = 123.321;
    String name = "Me";
}

Assuming we have an object of type Foo in our Grasshopper component that we can access, we can perform the following operation:

protected override void SolveInstance(IGH_DataAccess DA)
{
    Foo myFoo = new Foo();
    DA.SetData(0, myFoo);
}

We now have our data wrapped up in Foo being sent as an output of a Grasshopper component. If you plug a panel into this, you’ll get the type of data, like below.

Passing Foo out as a parameter of the component

Passing Foo out as a parameter of the component

Receiving custom data into a component

Receiving custom data passed into a component is a similar process to outputting it. First you need to register the generic parameter as an input. Then you need to read that input, and cast it as the data type you expect it to be.

GH_ObjectWrapper

The data which comes in through a generic parameter, while accessible as a System.Object, is better accessed as a GH_ObjectWrapper (part of the Kernel.Types). This gives you access to a data member ‘value’ which you can then use to cast your data back into the type it should be.

protected override void SolveInstance(IGH_DataAccess DA)
{
    Grasshopper.Kernel.Types.GH_ObjectWrapper obj = new Grasshopper.Kernel.Types.GH_ObjectWrapper();
    DA.GetData(0, ref obj);

    if(obj != null)
        myFoo = obj.Value as Foo;

    if(myFoo != null)
    {
        //Output data relating to Foo here
        DA.SetData(0, myFoo.Age);
        DA.SetData(1, myFoo.BankBalance);
        DA.SetData(2, myFoo.Name);
    }
    
}

We can now question Foo about its data, and obtain its age, bank balance and name (see below).

Custom Data being read in

Custom Data being read in

Things to be careful of

As it is using generic objects, anything might be accepted into your component. You do therefore need to put checks around what the object being passed in is to avoid a runtime exception being thrown. Some if statements might suffice, but obviously this will be up to you depending on the data your passing and reading in.

Now you can pass custom data along Grasshopper components, allowing you to produce a ‘set-up’ component that does some initial calculations, and pass those results on to components which require it without hassle.

Leave a Reply

Your email address will not be published. Required fields are marked *