Execute script on file opening

I know there is the possibility to execute scripts when Rhino opens. *
What I want is to execute a script every time I open a file.
Is this already possible and I’m just overlooking it?

(Possibly not.)
Before somebody asks, why on earth I’d want this feature :smiley::
I want to open any associated Grasshopper file [if existing] to a Rhino file – and as good programmer I am lazy :stuck_out_tongue:

Thinking about it: maybe a button with a script is just good enough. **

Hi

At Options General. There is an entry for startup scripts.

HTH
-Willem

Hey Willem, thanks! I am aware of that option. But this works just when you freshly open Rhino, which I do not talk about. I explicitly meant when opening a file, but Rhino is already open.

Hi @runxel,

image you have assigned document user text with a custom key and a value which contains the file path to your gh definition for each Rhino file you have. If you now create a script which sets up an event which subcribes to one of these:

RhinoDoc.EndOpenDocumentInitialPreviewUpdate 
RhinoDoc.RhinoDoc.EndOpenDocument 

The event handler can check for existance of the document user text key, when found, the associated file path (the gh definition) is opened in GH. To make this always work, add the script which sets up the event, to your startup commands.

_
c.

2 Likes

nice!

1 Like

Oh wow, thanks @clement, that looks promising.
But wait: Are event handlers even possible in RhinoScript? I only found C# examples.

Yes, you’ll only need to store them in scriptcontext.sticky if you want to get hold of them or disable them after they have been started. Otherwise they run forever. The good thing is that scriptcontext.sticky survives between sessions unless you use Reset Script Engine from the EditPythonScript Tools menu.

There are many examples if you search for python and events here is one using the idle event and this one is called when an object is added.

_
c.

1 Like

This seems to work quite okay.
Only problem is, that when using either

Rhino.RhinoDoc.EndOpenDocumentInitialPreviewUpdate 
Rhino.RhinoDoc.EndOpenDocument

rs.DocumentName() will give None as resut. :confused:

So between those events and the possibility of using rs.DocumentName() still something seems to happen in the background…

I encountered a similar problem with a form opening multiple documents for analysis, the whole scriptcontext.doc namespace and many rs methods failed. Your script was probably started in the document context of the previous document and the new one is not found. One workaround i know is using e.Document.ActiveDoc.Path from the event itself or Rhino.RhinoDoc.ActiveDoc.Path .

My guess is that as long as there can only be one doc opened (windows) this is less problematic. In very early rhino python days @stevebaer fixed a related issue and managed to re-initialize the doc after a new one has been opened. I tried that (from my modeless form) but it did not work. Maybe he can enlighten us on how to do it properly.

_
c.

You’re answering lightning fast! :exploding_head:

Haha, thats somehow pretty obvious after someone points it out!

I tried both of the mentioned workarounds, but no luck.
They still will give both None – which is kinda weird, because e.Document.ActiveDoc will give the right reference. Just all its attributes are somehow “empty” (=None).

Let’s wait for @stevebaer :smiley:

Hi @runxel, i’ve just tried e.FileName instead. It seems to work and you can get the name from the full path using this in the delegate:

    if e.FileName:
        head, tail = os.path.split(e.FileName)
        print "EventCall: {}".format(tail)

But as you wrote, the real problem remains.

Same here. Maybe steve can help us, it can be repeated by eg. this from the delegate:

rs.SelectObjects(rs.ObjectsByType(0, True))

i just returns below error:

ERROR: 46d70ded-b885-445d-9069-f79cd1906a09 does not exist in ObjectTable

but when i add this one line before i try the selection, the object(s) are selected:

scriptcontext.doc = Rhino.RhinoDoc.ActiveDoc

???
_
c.

Oh yeah @clement, that works like a charm! Thank you so much for all your help.

I’m really close, but a last thing which is getting me completely off guard:
Commands are not doing anything inside the event handler; they are getting “blocked”?
(Using rs.Command())

So I can see that the command gets executed in the command line but nothing acutally happens.
Try it with rs.Command("_-SellAll _Delete")
The command line says it selected all and deleted them… but nope! Still there untouched. Sigh :frowning:

Hi @runxel, yes, i would call it a “same shit different day” problem. Nothing is initialized after opening a new file, or better the previously initialized modules are invalid in the delegate. My guess is, you want to script the _Grasshopper command in order to pass the file path and open the definition ?

I found a possible workaround without using rs.Command():

def OpenDefinition(file_path):
    print "OpenDefinition: {}".format(file_path)
    
    Grasshopper = Rhino.RhinoApp.GetPlugInObject("Grasshopper")
    if not Grasshopper: return False
    
    Grasshopper.OpenDocument(file_path)

call it from your delegate, send the document user text value (the file path to the gh definition), validate the path before or in above function.

_
c.

1 Like

I am truly amazed how you can just keep coming up with 'nother workaround. How are you doing this?! Where do you get all this mad wisdom?

Anyway. Thanks a bunch for your incredible help, @clement!


For everyone whos’s interested here is the final script:

2 Likes