Register to object change
- 
 Can an ObjectDataplugin react to the change of an object it created? I'm working in C++ on 2023.2.0.SituationMy ObjectDataplugin creates a null and an IK-Spline tag among many other objects. The tag is not attached to the null in question.RequirementWhenever the user changes the size of the null I need to update the Handle Depth of one of the handles in the IK-Spline tag. Is it possible to register to the change of an object? What I've triedThe Messagemethod of myObjectDatadoes not receive a relevant message upon changing the size of the null.I inspected the BaseObjectinstance of my null and found theAddEventNoficationfunction. However this function is only documented as "Private" in the online documentation.DisclaimerPlease note that I've read up on creating additional objects in an ObjectData plugin and I'm already aware of the fallpits and risks. 
- 
 Hello @CJtheTiger, thank you for reaching out to us. Is it possible to register to the change of an object? [...] The Message method of my ObjectData does not receive a relevant message upon changing the size of the null. NodeData::Message only receives messages sent to that node, as it is just the counter part to C4DAtom::Message. So, if you implement aFooobject, you will receive messages sent toFooinstances. There is an exception to that rule,C4DAtom::MultiMessage. When a caller decides to use it instead of::Message, also the children and branches of the node upon which::MultiMessageis being invoked will be informed. Multi message events are rare and nothing one can rely on as a principle.Node messages, i.e., C4DAtom::Message/NodeData::Message, are intrinsically bound to a singular node. Broad scene or system wide messages are the so called core messages. It is however not possible to receive core messages in a node.[...] and found the AddEventNofication function. However this function is only documented as "Private" in the online documentation. There are some examples on the forum here, but you first of all must register for each node yourself. So, you cannot say 'broadcast all Onull data container changes to me', and there is also no data container event (see NOTIFY_EVENT for details). What can I do?You are running here into the well known problem that the classic API has no meaningful dependency graph/information, and as a root cause for that also only a very coarse scene update event system. - Simple Solution: Use the built-in dependency mechanism for object plugins, the flag OBJECT_INPUT. When you flag your plugin as such a direct child of your plugin node which has become data dirty will also cause your plugin's GetVirtualObjects(and similar methods) to be invoked. ButOBJECT_INPUTis indeed limited to direct children, everything else will be ignored. So, it depends on where your null objects live.
- Tag Solution : Another pattern to solve problems such as this are tags. The idea is to mark the thing you want to be notified about with a custom tag of yours. Because a tag qualifies for ::MultiMessagemessages sent to its hosting object, and because tags are executed on each scene pass, they can be a clever solution to the problem. The tags are then usually hidden and carry a base link to the node they should inform about changes of their host object. Either in their::Messageor::Executemethod they then carry out the information propagation. Problems can be here threading restrictions and feedback or delay effects.
- Complex Solution: You can solve all these problems with a MessageDataplugin. With it you can hook in the core message stream, and onEVMSG_CHANGEevents traverse/analyze a scene graph to decide if an event X has happened. Then you can inform specific nodes of that event you have detected. To inform your nodes, you should then useC4DAtom::Messagewith the message IDMSG_BASECONTAINER, sending the relevant data in aBaseContainer. Efficiently doing all of this, especially gracefully traversing and analyzing the scene graph, can be tricky.
 Cheers, 
 Ferdinand
- Simple Solution: Use the built-in dependency mechanism for object plugins, the flag OBJECT_INPUT. When you flag your plugin as such a direct child of your plugin node which has become data dirty will also cause your plugin's 
- 
 Hey @ferdinand, thank you for your response! And a very involved one at that, as expected from you. Thanks! Simple solution usingOBJECT_INPUTI tried the solution using OBJECT_INPUT. To verify whether it works I created a breakpoint inGetVirtualObjectsand tried it both with and without theOBJECT_INPUTflag. What I found was that the flag does not make a difference, the function will still be called oh so many times. Also you mentioned "direct children". I tested this both with children directly under my generator as well as with nested children of the generator. All of them triggerGVO. And since I don't get information about which children exactly has changed and what property I'd have to re-evaluate all of them which doesn't sit quite right with me. They're only nulls but still.Complex solution usingMessageDataAs for the complex solution (and this is very theoretical so feel free to skip it) I'd have to register a MessageDataplugin and hook into the messaging pipeline, just to ignore all messages except this very specific one. And then I'd also have to identify whether the issuing object is indeed one of my desired nulls so I'd have to mark those in some way. Which then makes me think "mark it with a tag". And at that point I can just use a custom tag anyways.Tag SolutionPerformance-wise this sounds the cleanest to me. It doesn't bloat the messaging pipeline, it won't require any fancy evaluation logic to see whether this is my desired null, it's very explicit in its definition. So this is the one I'll use. But feel free to correct me in my theories about performance. 
- 
 I would like to add the solution I chose to close this topic. The Tag Solution did indeed work very well. Executegot called plenty of times and I was easily able to filter for the change of the object I was looking for.But what I actually did was create a whole new class deriving from ObjectDataand listen to the messageMSG_DESCRIPTION_POSTSETPARAMETERto perform my actions right then. In the first post I said that my plugin creates a null. I replaced all those nulls with my newObjectDataclass. So my object hierarchy is similiar to this:- MainPluginObject : ObjectData-> Needs to be accessed by- HelperObject.- HelperObject : ObjectData-> Accesses- MainPluginObjectin its- Messagefunction.
 
 Also note that thread awareness is required. The reason I chose this structure this is the following: I would like the user to Current State to ObjectmyMainPluginObject. Before that theHelperObjectmight not be visible in the object manager depending on the values of some properties inMainPluginObject. But onceCSTOis called I want all objects to be shown in the object manager. If I had chosen the Tag Solution the user might delete the tag by accident and break everything. Now of course the user can still break things by deleting or moving theHelperObjectout of the hierarchy ofMainPluginObjectbut this I already have to validate anyways. Having a similiar check in a tag just adds another point of error which I'd like to avoid.So I'll mark this as my answer after taking everything @ferdinand said into consideration. Again, thank you very much for your assistance! You never let us down!  
- 
 Hey @CJtheTiger, sorry for my radio silence here and thank you for updating the thread. In short: you drew all the right conclusions for the general case. A MessageDatasolution can be quite performant when you know exactly what you are doing and when you must monitor either every object (in the sense of geometry) in the scene graph or at least many of them. For something like monitoring materials, shaders, or tags, the solution is mandatory anyways.The tag solution on the other hand can become a bottle neck when the information flow becomes too expensive. Imagine such dependency propagation tag called DataTag, and you have 1000's of them in a scene. Each tag not only informs then one but multiple other nodes about changes of its host. Due to that there is also overlap, i.e., bothDataTag DAandDataTag DBinform a target objectTabout changes of their host objectsHAandHB. But forTthis might be the "same" event and it then might be doing work twice. So, when stuff is getting complicated, you. are often better off with aMessageDatasolution, as you can consolidate things there.Cheers, 
 Ferdinand

