Feature Request: Additional programmatic Grasshopper plugin loading options

Hi there @stevebaer, @scottd, and @kike!! It has been a few moments since we covered this topic at the last TT AEC, but I finally got around to trying to automate silent loading of a GH script with a HumanUI using the methods we talked about. Will document my attempts here and I’m hoping we can get something to work so people can build slick apps on top of Rhino/GH with killer UX.

So… I’ve been playing around with the Rhinoscript interface for Grasshopper and it looks like so far my hopes have been dashed on what I’d like to accomplish. To recap, here is the goal:

  • Create a Rhino Plugin that contains 1 command, which can be run via command line or via a button in an RUI toolbar
  • The command launches Grasshopper (with absolutely no visible evidence of Grasshopper) and opens a Grasshopper script with a HumanUI interface (again, without triggering any visible instance of Grasshopper)
  • The script nonetheless executes when operating the HumanUI (this is the hard part, as we will see), despite there being no GH window

I’ve been using the API doc methods here:
https://developer.rhino3d.com/api/grasshopper/html/M_Grasshopper_Plugin_GH_RhinoScriptInterface_HideEditor.htm

I’ve noticed several problems with the methods in the API, with respect to what I’d like to accomplish:

  • DisableBanner(): This is great and a welcome method – however, I would like to also be able to enable silent loading (no echo in the Rhino Command Line). Even better (amazing, actually) would be providing an overload that would allow me to define my own custom splash screen (Waaaaaaat!)
  • LoadEditor(): Again, love that the Load function is separate from the Show function, and simple tests show that it is possible o “Load” grasshopper without the window appearing. However, the behavior of other methods crushes the hopes and dreams that I had when looking at the documentation
  • OpenDocument(): And here’s where the tears start to flow. From the API docs: “Open a Grasshopper document. The editor will be loaded if necessary, but it will not be automatically shown.” Well in my case, using this method on a script that I have built with full HumanUI (no GH interaction necessary), regardless of whether I call LoadEditor() first, it does indeed automatically show the editor.
  • HideEditor(): There’s hope still! Perhaps if I hide the editor first, before opening the document! Nope, disappointment ensues. Okay, so maybe I’m disappointed that the Editor does in fact show during the load process, but I do have a script within my GH definition that automatically minimizes the editor so it’s not blocking my UI. At least I can use HideEditor() to get rid of that pesky GH window minimized at the bottom of the Rhino UI, right? A flicker of joy, as I successfully hide the GH window entirely – “this is it!!!” I think, and then deep sadness sets in as I push a button and nothing happens, as it appears that when the GH editor is hidden, it no longer functions (at least with my intensely insane script)
  • EnableSolver(): Perhaps I can enable the solver on a hidden GH instance! Nope.

:slight_smile: :slight_smile: :slight_smile:

Anyway, just thought I would do a dramatic retelling of my last 20 minutes for fun. H’s a sample of the code I’m using so you can point out any stupid mistakes I’m making:

        dynamic gh = RhinoApp.GetPlugInObject("Grasshopper");
        gh.DisableBanner();
        gh.LoadEditor();
        gh.HideEditor();
        gh.OpenDocument(appGhFilePath);
        //gh.HideEditor();

Tried various combinations and orderings here. Main fixes would seem to include:

  • HideEditor(): Not disabling the GH execution context in this state (easier said than done?)
  • OpenDocument(): overload with a flag to prevent editor from showing automatically, or fixing the bug that does force it to show, or document in which cases it will automatically show, etc – also good compromise would be the ability to load in minimized state (never seeing the full GH window), a function not currently provided by the API (and would get me almost all the way to my goal)
  • DisableBanner(): overload that allows silent load (no Rhino command line echo)

Cheers,
Marc

In personal projects, I use Harmony as a workaround to hook window-related functions (System.Windows.Forms and now Eto) to prevent Grasshopper from being shown. Generally, it’s a complicated procedure.

HideEditor doesn’t hide the editor alone, it also closes the window, that’s what may prevent the execution context. Maybe try Visible = false?

As for Human UI, I forget whether Human UI uses GH or Rhino as its parent window. If its parent is GH, you would need more adjustments.

Interesting, I’d love to see a project where you’ve accomplished that, if you don’t mind sharing.

Yes, indeed “Hide” appears to simply close the window. Regarding Visible = false – the RS interface doesn’t implement Property accessors directly, AFAICT, only methods, and I am inferring that “Visible” in this context refers to whether the window is Hidden or not.

HumanUI can be set to Always on Top, or to use GH or Rhino as a parent (I usually tend to use the latter, so WPF parent relationships shouldn’t be an issue if I muck with GH)…

All that said, I would hope that a few strategic tweaks to the provided Interface could solve these challenges without having to dig in at Harmony’s level…

Cheers,
Marc

You can show any window you like for whatever period you like if your command is triggered.

1 Like

I’ll run your example code to see what function is trying to be too clever for its own good.

1 Like

I suppose that’s true – of course, would be nice to have a convenience method, but there are more important things for you all to worry about. :slight_smile:

Any thoughts on this? Still looking to clean up the GH launch routine for my applications.

Thanks!

Marc

is there a command to minimize the window?

I am using a macro like this:
_NoEcho
-_Grasshopper
: Banner
: Disable
-_Grasshopper _Document
: Close
: Enter
-_Grasshopper _Document _Open “C:.****.gh”
: Enter

This minimize grasshopper window:
Grasshopper.Instances.DocumentEditor.WindowState = System.Windows.Forms.FormWindowState.Minimized;

this show grasshopper window:
Grasshopper.Instances.DocumentEditor.WindowState = System.Windows.Forms.FormWindowState.Normal;

and how to integrate into the button?

many thanks . almost perfect.

@taraskydon ~ This looks like what I am looking for. I would be grateful if you could share the exact code under the Pave and Hinge buttons on your toolbar. It also looks like you have some functionality built into the .gh to make this work. If true, could you share just that bit as well. I am unfamiliar with what I am seeing in the second image.

TIA ~ Robb

these are not my scripts found on the forum.
tester.gh (7.7 KB)

_NoEcho
-_Grasshopper
: Banner
: Disable
-_Grasshopper _Document
: Close
: Enter
-_Grasshopper _Document _Open “C:****.gh”
: Enter

In Rhino 7 we added a Grasshopper Player command that might make this easier: Write Rhino Commands in Grasshopper

1 Like

Thank you.
-_GrasshopperPlayer
not what i want. it works in a stealth mode and it is not possible to modify the algorithm in real time.
but I probably didn’t understand. :slight_smile:

Thanks for this - I got it working well now. As you say, it is not perfect but it does work.

There was a quirk when I copy and pasted your button code. Your quotation marks did not work on my machine. I had to retype the quotation marks to get the command to run without wanting to browse for the file. Odd that…

There’s several kinds of quotation marks. Programming always requires the straight ones, regular typography prefers the angle ones. Since the script wasn’t placed inside a code block, Discourse probably replaced the correct marks with visually pleasing ones.

And I have never seen those colons (?) used in a macro. I would have expected underscores.

The big help was your .gh sample. I haven’t done anything in C# and those bits really do the heavy lifting. Thanks again for your input.

this is not my. I found on the forum.