Best way to detect an object has been deleted?
-
I have a plugin that created a Cloner and insert planes as children of that cloner. After that I update the Cloner Count.
However, when the user deletes a plane ( a child of that cloner), the Cloner count must be updated.What is the best way to detect an object has been deleted and I can update the Cloner count?
-
You could keep a BaseLink to the object.
But, shouldn't the Cloner notice anyway that its child objects are gone?
-
I am not sure what you mean with a Baselink?
A Cloner, imo, does not notice when a child is added or deleted.
I guess there is (somewhere) a message that signals a deletion?
-
Hello @pim,
thank you for reaching out to us. The proposed solution of @fwilleke80 sort of works, but has its problems in Python. There is no type
BaseLink
in Python and you can therefore not use it directly. You can add a parameter of typeDTYPE_BASELISTLINK
to aBaseList2D
of your choice and then store there the reference to the node. But that always requires a node where you are okay with "polluting" its GUI in this manner. You could of course hide these parameters in the UI, but that all could come a bit messy, especially when it is more than one parameter to reference.There are two alternative solutions:
- EVMSG_CHANGE: This core message is being sent when a document has changed. This includes, but is not limited to, objects being removed. You get here no further information except for the fact that
EVMSG_CHANGE
has occurred. You must determine yourself if an eventx
, e.g., the object with the name "foo" has been deleted, has occurred. One usually must deal with the UUID markers of nodes when doing something like this. We talked often about UUID markers on this forum, for example here I went over the whole approach. - BaseList2D.AddEventNotification: With this method you can let yourself be informed about events that happen to a specific node, including
NOTIFY_EVENT_REMOVE
. I showed how to use this internal method here.
When we compare the two approaches, we can note a few drawbacks for each of them:
EVMSG_CHANGE
:- Requires a
MessageData
plugin, or aGeDialog/GeUserArea
to receive the core message in the first place. - The message itself is very broad, and one must do substantial work to narrow down an event. If done naively, this can become a substantial bottleneck.
- So, when you want to be informed inside an
ObjectData
implementation O if a node n has been removed, you would implement aMessageData
M, which listens forEVMSG_CHANGE
, then traverses the scene to check if N is still there, and finally informs all instances of O by sending aMSG_BASECONTAINER
to them with the event data. - All in all, this can be quite a bit of work, but it is the most robust approach when executed properly.
- Requires a
AddEventNotification
:- Requires access to some kind of
NodeData
, e.g., anObjectData
, implementation because without access to aNodeData.Message
to receive the event notification, adding an event notification is meaningless. - This method family is internal for a reason. When used improperly, it is easy to crash or freeze Cinema 4D with it.
NOTIFY_EVENT_REMOVE
is unfortunately very literal in its event handling. When we have the element hierarchyroot->a->b
and we register forNOTIFY_EVENT_REMOVE
forb
, we will only be informed whenb.Remove()
is being called, but not whena.Remove()
is being called, although both events have effectively the result thatb
is not part of the element treeroot
anymore.
- Requires access to some kind of
What to do concretely depends on your plugin. Please share code and details about your project, as answering your question will otherwise be speculative.
Cheers,
Ferdinand - EVMSG_CHANGE: This core message is being sent when a document has changed. This includes, but is not limited to, objects being removed. You get here no further information except for the fact that
-
Thanks again for the great explanation.
I guess I will go for a different workflow then.