algorithmic modeling for Rhino
I'm working on a RhinoCommon-based plugin for a client that is intended to automate processing of a Grasshopper project. I know next to nothing about Rhino or Grasshopper, but have been pouring through all the documentation and code samples I can find. I'm running the latest build of Rhino 5, 64-bit, with the latest Grasshopper plugin installed.
To get the Grasshopper plugin object, I call the following:
dynamic gh = RhinoApp.GetPlugInObject("Grasshopper");
My code then uses the plugin object instance to open a Grasshopper project file, bind data to parameters, run the solver and bake the resulting data. No problem (well, no problem after I spent a couple of hours trying to guess the method names and parameters exposed by Grasshopper plugin object....)
I'm a software engineer and despise the lack of strongly-typed variables at design time so I figured there must be a better way...
At runtime, I see that the dynamic plugin object is actually an instance of Grasshopper.Plugin.GH_RhinoScriptInterface. So I added a reference to the Grashopper assembly to my plugin project and tried doing a cast of the dynamic gh variable to a GH_RhinoScriptInterface instance like this:
Grasshopper.Plugin.GH_RhinoScriptInterface ghInterface = gh as Grasshopper.Plugin.GH_RhinoScriptInterface;
However, after adding just this one single line of code without changing anything else (i.e., my code still references the dynamic gh variable everywhere), I get an error about a bunch of "Unrecognized Objects" when I call gh.OpenDocument():
No idea what I might be doing wrong, but this sure seems like something that should work correctly.
Tags:
Hi Marty,
calling into Grasshopper out of the blue will mean none of the component caches are created. Creating these caches takes a long time (usually the Grasshopper banner is displayed during this interval) which is why it only happens on command.
My guess is that loading Grasshopper via this reference somehow short-circuits the caching routines and therefore Grasshopper is unaware of any components which is why even standard ones like [Curve Frames] and [End Points] will fail to be loaded.
Can you post some code I can use to duplicate this problem?
--
David Rutten
david@mcneel.com
Poprad, Slovakia
Btw. the GH_RhinoScriptInterface class has been documented and is part of the Grasshopper SDK documentation. Did you download the docs? You can do so via the Grasshopper Help menu.
--
David Rutten
david@mcneel.com
Poprad, Slovakia
here's a snippet - create a new plugin command and use this as the RunCommand() method. (Sorry about the formatting...)
protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
dynamic gh = RhinoApp.GetPlugInObject("Grasshopper");
// use the plugin object interface to open a file, assign some data and run the solver
// you'll get an "Unrecognized Objects" error message when this line executes if you've uncommented the cast above
if (gh.OpenDocument(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), @"Grasshopper\Foo.gh")))
{
gh.AssignDataToParameter("_SomeParameter", 15);
gh.RunSolver(true);
gh.BakeDataInObject("Xyz");
doc.Views.Redraw();
}
// Cast the dynamic gh instance to a GH_RhinoScriptInterface instance so we can use strong-typing at design time.
//
// uncomment the next line and you will get an error on the gh.OpenDocument() call above, before the next line even executes!
//Grasshopper.Plugin.GH_RhinoScriptInterface ghInterface = gh as Grasshopper.Plugin.GH_RhinoScriptInterface;
// Ideally, the following code should work exactly like the code above, if not for the error
//
//if (ghInterface.OpenDocument(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), @"Grasshopper\Foo.gh")))
//{
// ghInterface.AssignDataToParameter("_SomeParameter", 15);
// ghInterface.RunSolver(true);
//
// ghInterface.BakeDataInObject("Xyz");
//
// doc.Views.Redraw();
//}
return Result.Success;
}
As a quick followup, I think you may be right that it's an initialization issue with Grasshopper.
If I execute "Grasshopper" first and let it fully start up, then go run my plugin command that performs the code steps above, everything works great.
Is there a way to know whether Grasshopper is done initializing?
Grasshopper.Instances.IsComponentServer will tell you whether all components have been loaded. You can also call Grasshopper.Instances.ComponentServer to get an instance of the server. This method will cache all components if they haven't been already.
--
David Rutten
david@mcneel.com
Poprad, Slovakia
No joy. I tried several variations on getting the ComponentServer, waiting for IscomponenetServer to become true, getting the Grasshopper PluginObject from Rhino, etc.
The only way I can get the code that uses the GH_RhinoScriptInterface cast to work correctly is to ensure that I've already started Grasshopper via the command line. So apparently there is some difference in initialization between getting the PluginObject() from Rhino and actually running the "_Grasshopper" command.
The _Grasshopper command does the following things:
1 and 3 are clearly not needed for you to get it to work, so all the important stuff must happen in step #2. When showing the Grasshopper main window, the following things happen:
To answer your earlier question: "Is there a way to know whether Grasshopper is done initializing?" the answer is yes. Grasshopper initialized on the main UI thread so unless your code is running in a thread you created, you will not be able to do anything while I initialize. You call Instances.ComponentServer and by the time the function returns initialization is over and done with.
"waiting for IscomponenetServer to become true" This is not useful. Either IsComponentServer is false, in which case you need to call Instances.ComponentServer to make it true, or it is already true in which case calling Instances.ComponentServer just returns the already existing server. So you might as well call Instances.ComponentServer directly and cut out the middle man.
However, if you plan to open files, you will also need the main editor window up and running or there will be no place to put these files.
So I think ultimately you're right in calling the _Grasshopper command, as it does both things that need to be done in order for you to open files and run solutions. However, you should be able to use LoadEditor() or ShowEditor() from the RhinoScriptInterface object as well, they do the same thing.
--
David Rutten
david@mcneel.com
Poprad, Slovakia
Welcome to
Grasshopper
© 2025 Created by Scott Davidson.
Powered by