mcneel / rhinocommon

RhinoCommon is the .NET SDK for Rhino5 / Grasshopper
http://wiki.mcneel.com/developer/rhinocommon
244 stars 93 forks source link

Rhino does not reflect objects were selected #144

Closed locivir closed 11 years ago

locivir commented 11 years ago

I have a problem with selecting objects. I'm writing a c# plugin with an adjusted layer panel. The selection of object works through Rhinocommon, but in Rhino the Gumball does not get updated after selecting items. Also, if I'm in a command which requires selection of objects (e.g. BooleanDifference), it does not "see" that new object were selected. When I select multiple objects like this and add another object to the selection (or with shift select an selected object again) rhino acts normally. The gumball shows up and running command takes the selection.

Below is the function to select objects on a specific layer.

private void ActionSelectAddObjects(object sender) { // Get the layer that got clicked upon Layer l = LocivirRhinoLayerPanel_GetLayer(sender); // Do nothing if we could not get the layer if (l == null) return; // Get all objects on the layer Rhino.DocObjects.RhinoObject[] objs = RhinoDoc.ActiveDoc.Objects.FindByLayer(l); // If [Control] is pressed, unselect all object before selecting new objects if (Control.ModifierKeys == Keys.Control) RhinoDoc.ActiveDoc.Objects.UnselectAll(); // Check if there we got any objects returned if (objs != null) { // Rotate through the objects and select them if they are selectable foreach (RhinoObject obj in objs) RhinoDoc.ActiveDoc.Objects.Select(obj.Id, true); } // Reflect the selection changes in the viewports RhinoDoc.ActiveDoc.Views.Redraw(); // Reset the focus to the main window RhinoApp.SetFocusToMainWindow(); }

dalefugier commented 11 years ago

Hi Ernest,

I believe the gumball's auto-update is tied to the running of commands. And since your panel is modeless, the gumball does not know it should update. You can get yourself in the same situation if you select objects with RhinoScript, for example.

Try this: create a command and have it to the object selection for you. It will need a public data member, which is the layer index of the objects you want selected. Then, from your panel, just script the running of your command using Rhino.RhinoApp.RunScript.

http://wiki.mcneel.com/developer/runrhinocommandfromplugincommand

Does this help?

-- Dale

locivir commented 11 years ago

I guess that could do the job, I'll need a couple of days before I can look into it as I'm busy for work.

I'm just wondering... does a work-around like this not defy the purpose of having the functions directly available through Rhinocommon? And will calling RunScript cancel an active command on the command line of Rhino? If I run an empty command as a placeholder wherever Rhino does not update, would Rhino react on the changes?

After I bake objects through the script-interface of Grasshopper (a different part of my plugin) and type the _SelLast command in the command line, the first time it will select the objects (if any) that were the last to be adjusted before the bake command and after that it will select the newly created objects. Do you think that is related too?

Thank you for your time,

-- Ernst Plaatsman

dalefugier commented 11 years ago

Hi Ernst,

does a work-around like this not defy the purpose of having the functions directly available through Rhinocommon?

That depends on what you are doing and if it is even possible to provide a function. There is a lot of function in Rhino that is not easily wrapped for .NET.

Specific to the issue you've reported, if my suggestion helps, then we can dig through Rhino to see if there is some API we can provide that would alleviate the work around. I should mention that my suggestion is a very common approach for modeles ui - the Layer dialog does this extensively, for example. There are a number of good reasons why do this this, including undo and command scripting support.

And will calling RunScript cancel an active command on the command line of Rhino?

No, command can be nestable.

If I run an empty command as a placeholder wherever Rhino does not update, would Rhino react on the changes?

I don't quite understand this, Perhaps you could elaborate?

Do you think that is related too?

Yes.

-- Dale

locivir commented 11 years ago

Dale,

Last weekend was the first time since we talked I had time to continue programming my plugin. I think I found a solution for my problem. In Rhino a user can run a script without updating the viewports by using the command setredrawoff. by asking for a redraw inside the script or using the command setredrawon after running the script the viewports update. using the three lines below, this seems to be working for c# too. It did save me a lot of adjustments in my code :) just wanted follow up and ask for your opinion if this a proper way to work.

Rhino.RhinoApp.RunScript("'SetRedrawOff", false); RhinoDoc.ActiveDoc.Views.Redraw(); Rhino.RhinoApp.RunScript("'SetRedrawOn", false);

-- Ernst

dalefugier commented 11 years ago

Hi Ernst,

That will work. This might be simpler:

protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
  doc.Views.RedrawEnabled = false;

  // to do...

  doc.Views.RedrawEnabled = true;
  doc.Views.Redraw();

-- Dale

marcsyp commented 6 years ago

Incidentally, I had the same issue recently in a C# component inside grasshopper, and Ernst's workaround worked while Dale your code didn't. Is there a better way to approach it in Grasshopper?

Cheers, Marc

dalefugier commented 6 years ago

Hey @marcsyp, the two code samples call the same underlying C++ code. If you have something that isn't working for you, feel free to send your code my way.

-- Dale