Opening gha in c#

Hi all,

Hi everyone,

I’m trying to use Grasshopper plugins inside a standalone C# application (Visual Studio 2019) by running Grasshopper in a headless Rhino.Inside / RhinoCore environment. As a test case, I’m attempting to call the Dendro plugin programmatically. I wrote the following test code:

// New GH document
var ghDoc = new GH_Document();
Instances.DocumentServer.AddDocument(ghDoc);

// Instantiate Dendro components
var curveToVolume = _curveToVolumeProxy.CreateInstance() as GH_Component;
var volumeToMesh = _volumeToMeshProxy.CreateInstance() as GH_Component;

if (curveToVolume == null || volumeToMesh == null)
throw new Exception("Could not instantiate Dendro components.");

ghDoc.AddObject(curveToVolume, false);
ghDoc.AddObject(volumeToMesh, false);

// --------------------------------------------------
// 1) Create DendroSettings instance via reflection
// --------------------------------------------------
object settings = Activator.CreateInstance(_dendroSettingsType);
SetDendroDoubleProperty(settings, "VoxelSize", radius / 3.0);
SetDendroDoubleProperty(settings, "Bandwidth", 1.0);
SetDendroDoubleProperty(settings, "IsoValue", 0.01);
SetDendroDoubleProperty(settings, "Adaptivity", 0.1);

var settingsGoo = new GH_ObjectWrapper(settings);
var path = new GH_Path(0);

// --------------------------------------------------
// 2) Feed CurveToVolume
// --------------------------------------------------
curveToVolume.Params.Input[0].AddVolatileData(path, 0, new GH_Curve(curve)); // C
curveToVolume.Params.Input[1].AddVolatileData(path, 0, new GH_Number(radius)); // R
curveToVolume.Params.Input[2].AddVolatileData(path, 0, settingsGoo); // S (settings)

here I can set curve and radius values. But, somehow the code doesn’t see my definition for settings. Has anyone successfully passed settings into a Dendro component programmatically?

Hi,

I would avoid creating DendroSettings manually through reflection here.

The settings input is probably not expecting a plain CLR object wrapped in GH_ObjectWrapper. It is more likely expecting the same Grasshopper data/Goo produced by Dendro’s own Create Settings component.

So instead of doing this:

new GH_ObjectWrapper(settings)

I would let Dendro create the settings object and then pass that output directly into CurveToVolume.

Example:

var doc = new GH_Document();
Instances.DocumentServer.AddDocument(doc);

var path = new GH_Path(0);

var settings = _createSettingsProxy.CreateInstance() as GH_Component;
var curveToVolume = _curveToVolumeProxy.CreateInstance() as GH_Component;

if (settings == null || curveToVolume == null)
    throw new InvalidOperationException("Could not create Dendro components.");

doc.AddObject(settings, false);
doc.AddObject(curveToVolume, false);

// Create Dendro settings using Dendro's own component
settings.Params.Input[0].AddVolatileData(path, 0, new GH_Number(radius / 3.0)); // Voxel size
settings.Params.Input[1].AddVolatileData(path, 0, new GH_Number(1.0));          // Bandwidth
settings.Params.Input[2].AddVolatileData(path, 0, new GH_Number(0.01));         // Iso value
settings.Params.Input[3].AddVolatileData(path, 0, new GH_Number(0.1));          // Adaptivity

settings.ExpireSolution(true);

// Feed Curve To Volume
curveToVolume.Params.Input[0].AddVolatileData(path, 0, new GH_Curve(curve));
curveToVolume.Params.Input[1].AddVolatileData(path, 0, new GH_Number(radius));

// Reuse the exact settings object produced by Dendro
var settingsOutput = settings.Params.Output[0].VolatileData;

foreach (var branchPath in settingsOutput.Paths)
{
    var branch = settingsOutput.get_Branch(branchPath);

    for (int i = 0; i < branch.Count; i++)
        curveToVolume.Params.Input[2].AddVolatileData(branchPath, i, branch[i]);
}

curveToVolume.ExpireSolution(true);

This keeps the code closer to what happens on the GH canvas and avoids depending on Dendro internals. Reflection might set the properties correctly, but it can still bypass the custom GH type/wrapper that the component expects.