I use doc.Objects.Replaced event to update attributes (weight, length) in the Object’s User Text and fix the geometry if the user change has resulted in a geometry invalid for my use.
I accomplish this by listening to the OnObjectsReplaced event and then making document changes on the next RhinoIdle.
This is where my issue comes in, as when the user only changes a single object (e.g. control point drag) it executes fine. But when mutliple control points of different objects are dragged, the event does in my case not fire for every object that has changed, but only fires for the first one, and the Agrs only contain a single Id.
This is my current OnObjectsReplaced event handler:
private void OnObjectReplaced(object sender, Rhino.DocObjects.RhinoReplaceObjectEventArgs e)
{
if (!RhinoDoc.ActiveDoc.UndoActive)
{
UpdateEventSubscriptions(false);
var doc = RhinoDoc.ActiveDoc;
if (doc == null)
return;
Guid replacedId = e.ObjectId;
if (!_oldGeometryById.ContainsKey(replacedId))
{
var oldObj = doc.Objects.Find(replacedId);
if (oldObj != null && oldObj.Geometry != null)
{
GeometryBase oldCopy = oldObj.Geometry.Duplicate();
_oldGeometryById[replacedId] = oldCopy;
}
}
_pendingReplacedGeoms.Add(replacedId);
RhinoApp.Idle += OnIdleRecalculate;
}
Does the Replaced event actually not fire per object?
We probably need to see more of your setup to be able to help more, but off the top of my head RhinoApp.Idle += OnIdleRecalculate looks like it is being subscribed too every time OnObjectReplaced is fired, which could cause you grief. You could do something like this instead:
//track whether RhinoApp.Idle has been subscribed to
private bool _isSubscribed;
//add check in OnObjectReplaced to see if idle event is already setup
if(!_isSubscribed)
{
RhinoApp.Idle += OnIdleRecalculate;
_isSubscribed = true;
}
//at the end of OnIdleRecalculate remove event hook and reset _isSubscribed
private void OnIdleRecalculate()
{
//your processing logic
RhinoApp.Idle -= OnIdleRecalculate;
_isSubscribed = false;
}
Thank you Luke, I myself was ofc responsible for this headache, I now use your boolean to not subscribe every time and took out the call to UpdateEventSubscriptions, which I use on many occasions to hook/unhook all handlers, to isolate the behaviour of a Command or Handler. For this Handler I now only unsubscribe from Delete, because it would otherwise fire in the Handler, and resubscribe after execution of OnIdleRecalculate.
This is my first time working with Rhinocommon Events, therefore I wonder if there is maybe a pattern which I should follow to avoid my Plugin getting too crowded with individual and therefore confusing singular event unhooks/reehooks?
Sometimes I think that what Im attempting here is generally not intended to be done and therefore so sketchy.
It really depends on what you’re trying to achieve and how you’re doing it – the above approach can be good if you’re working within a command, but if you’re trying to do more “global” event watching then it might not be ideal.