Hi everyone,
I am looking for some open source code examples for setting up pass-through components in Grasshopper. Many of the Rhino.Inside.Revit components and new components for Rhino8 are abandoning the old construct/deconstruct paradigm in favor of the pass-through model, but I can’t seem to find any examples of this implemented in C#. Any tips would be appreciated, thanks!
@AndyPayne @kike can you help out?
There isn’t all that much to any of these pass-through components. The main thing to remember is that the main data type is usually reserved for the first input and output. Then, all of the attributes that make up that data type follow as inputs/outputs. So, let’s look at a Model Layer
component.
I’m going to skip the setup of the setup of the parameters (ie. inputs/outputs) since that’s pretty straightforward and I assume you already know how to do that. Instead, let’s look at the solve instance method.
protected override void SolveInstance(IGH_DataAccess DA)
{
//init all variables as null or empty
ModelLayer layer = null;
string name = string.Empty;
bool? hidden = null;
bool? locked = null;
Color? displayColor = null;
ModelRenderMaterial material = null;
ModelLinetype linetype = null;
Color? printColor = null;
double? printWidth = null;
//retrieve all data from the inputs
DA.GetData(0, ref layer);
DA.GetData(1, ref name);
DA.GetData(2, ref hidden);
DA.GetData(3, ref locked);
DA.GetData(4, ref displayColor);
DA.GetData(5, ref material);
DA.GetData(6, ref linetype);
DA.GetData(7, ref printColor);
DA.GetData(8, ref printWidth);
//Layer names must be unique, so check if the name is valid before proceeding
if (name is object && !Rhino.DocObjects.ModelComponent.IsValidComponentName(name))
{
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, $"'{name}' is not a valid layer name.");
return;
}
//here we look to see if the incoming layer (from the input parameter) is null.
//if it's not null, we use it. If it is null, we create a new instance.
//We use the ToAttributes method because otherwise the underlying attributes are immutable.
var layerAttributes = layer?.ToAttributes() ?? new ModelLayer.Attributes();
{
if (!string.IsNullOrEmpty(name)) layerAttributes.Name = name;
if (hidden is object) layerAttributes.Hidden = hidden;
if (locked is object) layerAttributes.Locked = locked;
if (displayColor is object) layerAttributes.DisplayColor = displayColor;
if (material is object) layerAttributes.Material = material;
if (linetype is object) layerAttributes.Linetype = linetype;
if (printColor is object) layerAttributes.DraftingColor = printColor;
if (printWidth is object) layerAttributes.LineWeight = printWidth;
}
//after we have set all of the attributes of the data type, we call
//ToModelData to return the Model Data
layer = layerAttributes.ToModelData() as ModelLayer;
//Finally we set all of the outputs to the correct data
DA.SetData(0, layer ?? default);
DA.SetData(1, layer?.Name);
DA.SetData(2, layer?.Hidden);
DA.SetData(3, layer?.Locked);
DA.SetData(4, layer?.DisplayColor);
DA.SetData(5, layer?.Material);
DA.SetData(6, layer?.Linetype);
DA.SetData(7, layer?.DraftingColor);
DA.SetData(8, layer?.LineWeight);
}
Does this help? The pattern where we create the attributes of the data type and then call ToModelData
to return the base type is pretty much what we do for all of these passthrough data type components.
Great, thanks very much. This is quite clear and helpful. I’ll try it out myself!