Grabbing and Dragging Conduit objects

Hello,

I am trying to display some geometries in the Conduit and I want to be able to select them. So far I managed to do that. Learning from this example: http://wiki.mcneel.com/developer/sdksamples/pickobjects
I simply got my point with CRhinoGetPoint gp; and then retrieved the FrustrumLine from the viewport and checked if the line intersects the BoundingBox of my object…if it does - bingo!

However this method is pretty slow…Rhino objects can be instantly grabbed and dragged just by clicking on them and holding the mouse button. Is there a way for me to control
a mouse event in the same way for my conduit objects? To basically recognize the mouse event when the user presses somewhere on the viewport and find out which viewport was it and what were the screen coordinates?

P.S. I am programming in C++

Thank you.

Hi Sonja,

It is always much easier to pick (and drag) objects that are in the document. Most of the SDK samples show how to add objects to the document.

Why do you need to pick objects you are drawing in a conduit?

– Dale

Hi Dale,

I want to create some interactive “tools” that will help me with different methods I am using in a day to day work. Here is an example:

I have a surface and a polyline (or curve) on it that I can use to split that surface. But I want a lot of stuff “attached” to that curve. I can display it like a polygon, then draw markers on the corners, then calculate and display the two areas with text dots, and some other things. All of that I want to do in the Conduit, so I though why not have everything there, so when I move the polyline around (or its points) everything gets updated.

Maybe I could “attach” my data to a Polyline that is in the Rhino Document (?) but then I am left with the exact same problem. I have to be able to read a mouse event (?) to know when the user moved the Polyline from the Document so that I instantly update everything in the Conduit that goes with it.

I thought there is an easier solution…and I think it is possible because Gumball is a perfect example of what I want to do. Something drawn in the conduit but can be grabbed and dragged.

Thanks!

Looking at your requirements, why not make a command that registers the GUID of the surface and the curve, and subsequently listens to replacement/delete/add events.

Each time the user moves the curve, these events are fired for the GUID. Then, upon receiving the events, your code finds the updated objects and calculates the values and positions of the decoration points and text-dots and updates them in the display conduit.

That sounds like it can work. I am assuming that GUID = UUID and that I can retrieve it like this:

I would be grateful if you could give me an advice on how to “listen” to these events. I see that there is a CRhinoEventWatcherEx class…is that class used? Do I make my own class derived from it, and then call ::Enable(TRUE), and then simply override functions like OnReplaceObject, etc…? If yes I have two questions:

  1. at what point and how do I recognize if my object (with my UUID) has been replaced? I am guessing inside those overriden functions? If yes, then the only question is how.

  2. Once I made the object of my class (derived from the watcher class), and enabled it, the “gates are open all the time?” Whenever something changes in the document the overridden functions will perform? Until I disable it?

P.S. Is this really easier than finding out if the user pressed the mouse button and retrieve screen coordinates? At the beginning I thought it is a matter of a single existing function, or few lines of code…since it is used for all rhino geometries, and even the coundit ones (like gumball).

  1. Inside the OnReplaceObject, you will get a reference to the old and new objects. These have the same GUID (the GUID’s don’t change on replacement), so you can check if that id was registered.

  2. Yes. You will get all changes in your OnReplaceObject. So that needs to be fast.

  3. You can disable the conduit and then stop listening. This can be done in a command.

As the document gets a re-draw after the object has been added, any changes you make to the configuration of the display conduit, will automatically be updated on the screen.

Easier? I don’t know. To me, personally, this way is more along the lines of “good practice”.

Hi,

in the meantime I have managed to set up my CRhinoEventWatcher derived class and it works fine, but I have two unresolved issues:

  1. OnDeleteObject and OnReplaceObject “colide”. I want to track an object and do one action if it is deleted and another if it is moved. But the moment I move it, rhino actually deletes and redraws the object (I presume)…so both OnDeleteObject and OnReplaceObject are executed. Can I separate that somehow? Can I move an object (and execute OnReplaceObject) without executing OnDeleteObject?

2 .I am having a problem catching a copy event. Is that possible? I realize that I can use OnAddObject, but I also need the information about the object that is being copied…in a way that OnReplaceObject has the old and the new object…can I do that?

Thanks!

1.) Your RhinoDoc.ReplaceRhinoObject handler will be called if an object is about to be replaced.

If either RhinoDoc.UndoActive or RhinoDoc::RedoActive is true, then immediately after RhinoDoc.ReplaceRhinoObject is called there will be a call to RhinoDoc.DeleteRhinoObject and then a call to RhinoDoc.AddRhinoObject.

If both RhinoDoc.UndoActive and RhinoDoc.RedoActive are false, then immediately after RhinoDoc.ReplaceRhinoObject is called there will be a call to RhinoDoc.DeleteRhinoObject and then a call to RhinoDoc.UndeleteRhinoObject.

2.) To catch copy events, try handling the RhinoDoc.BeforeTransformObjects event. There is an example of this in this sample project:

https://github.com/dalefugier/SampleCsEventWatcher

1 Like

Thanks.

So if i want to handle Replace without Delete, the only way is to disable CRhinoDoc::UndoActive and CRhinodoc::RedoActive?
I am working with c++, so I am not finding the BeforeTransformObjects alternative…?

In C++

If both CRhinoDoc::UndoActive() or CRhinoDoc::RedoActive() are false, then immediately after CRhinoEventWatcher::OnReplaceObject() is called there will be a call to CRhinoEventWatcher::OnDeleteObject() and then a call to CRhinoEventWatcher::OnAddObject().

If either CRhinoDoc::UndoActive() and CRhinoDoc::RedoActive() are true, then immediately after CRhinoEventWatcher::OnReplaceObject() is called there will be a call to CRhinoEventWatcher::OnDeleteObject() and then a call to CRhinoEventWatcher::OnUnDeleteObject().

All of the above is in place to support Undo and Redo, which the user expect to be able to do.

If you want to know when an object is being transformed, then create a CRhinoOnTransformObject event handler. See rhinoSdkEventWatcher.h for details.