Using doc in plugin constructor (rhincommon)

When I run a command, doc is passed to the runcommand function. But outside of this situation, how can I get access to doc? I thought perhaps rhinodoc.activedoc, but this doesn’t seem to work for me. In particular, I am trying to get access to doc in my plugin class constructor as in the code below.

Thanks,
Sam

Public Sub New()
Instance = Me

        Dim doc = RhinoDoc.ActiveDoc
        doc.Objects.AddPoint(New Rhino.Geometry.Point3d(0, 0, 0))

end sub

Your class constructor should have parameter accepting RhinoDoc object. When you are constructing your class inside Command you just pass doc to you class constructor.

You should only use doc pass to you from Command and you should not use AcriveDoc

I’ve added “byval doc as rhino.rhinodoc” to my plugin class constructor as shown below. When I try this the plugin fails to load when I run a command (error below). Just to make sure we are on the same page, it is the plugin class constructor I am referring to, not a command class constructor. Any thoughts?

Thanks,
Sam

Public Sub New(ByVal doc As Rhino.RhinoDoc)
_instance = Me
doc.Objects.AddPoint(0, 0, 0)
End Sub

System.Exception: No PlugIn subclass found.
at RMA.Rhino.MRhinoPlugIn.CreateFromAssembly(Assembly assembly, Boolean display_debug_info)Unable to load PodoCAD.rhp plug-in: initialization failed.

where do you put this?

Not in your PodoCadPlugin.vb I hope?

Public Sub New(ByVal doc As Rhino.RhinoDoc)
            _instance = Me
            doc.Objects.AddPoint(0, 0, 0)
End Sub

That’s what I was trying to do, but I take it I’m not supposed to… I’ve found a way around having to do this.

Thanks,
Sam

Hi Sam,
There are many cases where a document does not actually exist when your plug-in is being constructed. I would also recommend that you only do things like add geometry to the document when inside of a command.

Hi Steve,

OK, I understand. I think what I was going for was to be able to do stuff to the document when things get started, which I now realize, for my plugin anyway, is when new or saved documents are opened rather than the plugin being loaded. So instead of using the class constructor sub, I am now trying to use handlers for when new or saved documents open. And because I can’t access doc directly in the plugin class, I instead have the handler run a script to call a command. My aim is for this command to setup layers, display settings, stuff like that.

The curious problem I’m having is that, while the OnNewDocument handler seems to work when rhino first opens, it doesn’t when a new document is created after rhino is already open. I’ve attached a sample project. Any idea what is going on? Maybe there is a better way to do this?

One other quick question: is there a way to force my plugin to load when Rhino opens?

Thanks,
Sam

HandlerTest.zip (42.4 KB)

Hi Sam,

You can do this to load your plugin when Rhino open:

 Public Overrides ReadOnly Property LoadTime As Rhino.PlugIns.PlugInLoadTime
            Get
                Return Rhino.PlugIns.PlugInLoadTime.AtStartup
            End Get
        End Property

Maybe use Rhino.RhinoDoc.EndOpenDocument instead of OnNewDocument. This way it will first open your file and then run the handdler.

-Jordy

Hi Jordy,

That code worked to force the plugin to load on startup, thanks.

As far as calling a sub when a new document is created, I’m still having issues. EndOpenDocument only seems to work when a saved document is opened while OnNewDocument only works when a new Rhino session first opens. When Rhino is already open and a new document is started, neither of these is called. Any thoughts?

Thanks,
Sam

it seems to work here… the NewDocumt one:

 AddHandler Rhino.RhinoDoc.NewDocument, AddressOf OnNewDocument

Private Sub OnNewDocument(ByVal sender As Object, ByVal e As Rhino.DocumentEventArgs)
        MsgBox("New")
End Sub

I open Rhino. Do some modifications and go to file> new file then a msgbox pops up. So that means its triggered.

Hi Jordy,

This is odd, MsgBox works for me too, but what I am trying to do doesn’t work:
Rhino.RhinoApp.RunScript("Testing ", True)

note that I have put scriptrunner before the class:
<Rhino.Commands.CommandStyle(Commands.Style.ScriptRunner)> _

In summary, MsgBox works both when rhino starts and when a new document is opened, while runscript only works when rhino first opens.

Thanks,
Sam

There is almost no reason to configure your plug-in to load when Rhino loads. First, when a user runs one of your command and your command is not loaded, Rhino will load your plug-in (on demand) and then run your command. Also, if Rhino is opening a 3dm file that contains user data that you plug-in has written (either object or document), then Rhino will automatically load your plug-in (so it can read the user data).

Setting a plug-in to load when Rhino loads delay’s Rhino’s loading time. Imagine how long it would take for Rhino to load if every develop did this…

Also if you want to “play” with event watchers, see the following example:

https://github.com/dalefugier/SampleCsEventWatcher

Hi Dale,

Many of the users for my plugin will be new to Rhino, so for their benefit I want to control the experience as much as possible and make it tailored to my plugin, from the moment they open Rhino. Perhaps I will have a version intended more for existing rhino users that doesn’t load on startup…

Can you think of any reason why the NewDocument handler, when a new document is created in an already open session of rhino, will not run a script?

Thanks,
Sam

When using our event watchers, when you detect an event, you should set a flag of some kind (denoting that the event has occurred) and then quickly return out of your handler, keeping in mind that your plug-in is not the only think watching for the event.

Then at an appropriate time, such as when one of your commands run, our UI updates, or Rhino is idle, check the flag and, if dirty, take the appropriate action. This is referred to as lazy evaluation. By doing this, Rhino will run quickly (as others might be watching the event too) and the risk of crashing Rhino will be reduced (again, as other might be watching the event and, thus, also incorrectly modifying the document).

I’ve updated your project to demonstrate this.

HandlerTest.zip (8.9 KB)

Got it, that makes sense to me.

I’ve also been watching for commands to end to determine what stage my plugin is in. So I thought I’d incorporate that into the same structure. But it won’t work for some reason.

Perhaps one issue, though I have no clue why, is that I had to pass CommandEventArgs to the OnIdle sub instead of EventArgs, so as to check which command has been run and whether or not it was successful. Do I need to use a separate idler sub? What is the proper way to do this?

I’ve attached the project.

Thanks,
Sam

HandlerTest2.zip (43.2 KB)

Hi Sam,

The signature of delegate functions must match that of the event declaration. Thus, you cannot simply change the parameters. Keep in mind that it is Rhino that is calling into your plug-in’s event handlers.

For watching commands, you have two options. Either your handler can determine whether or not the command is important, or your Idle handler can by checking some other variable that indicates what command has just finished. I’ve updated the sample to show the first option.

HandlerTest.zip (9.1 KB)

Hi Dale,

OK, works great.

Thank you for taking the time to explain all this to me, I should be good for a while now!

Sam