Send/Receive Messages in TagData/ObjectData plugins
-
Hi Maxon team,
Is it possible to send/receive message event for example from tag plugin instance to object plugin instance?
I found some topics, but those related to CommandData and MessageData...
-
Hey @baca,
Thank you for reaching out to us. In general, I would recommend having a look at the Message Manual as it explains the basics of the message system in Cinema 4D.
In principle, you can send as many messages from a
BaseTag
to aBaseObject
as you want. The means to do so would be c4d.C4DAtom.Message to send data only to that object or .MultiMessage to broadcast the message also to the descendants of that object.What might be worth pointing out, is that the
NodeData
message stream is effectively sealed. So, imagine we invented the messageMSG_DO_STUFF: int = 1061999
. We can send this message as much we want to anOcube
instance, it won't be able to do anything with it, because the cube object obviously never implemented this message. And there is also no way for us to attach a delegate toOcube
which would be invoked when it gets that message. This effectively means that the node message stream is sealed, we can only implement messages for scene elements whose implementation we own.In Python there is the added difficulty that the node message stream is also filtered, so we cannot just invent a message as we can in C++, Cinema 4D will just filter out such custom message. Here we must make do with the existing message types. A good choice is
MSG_BASECONTAINER
as it not only allows us to send data but also to signify the purpose with the container ID.import c4d myNode: c4d.C4DAtom # Always register a plugin ID for new message types. MSG_MY_EVENT: int = 1061999 MSG_MY_EVENT_NUMBER: int = 0 MSG_MY_EVENT_STRING: int = 1 # Sending the message # -------------------------------------------------------------------------------------------------- # Create a container with the message ID as the container ID and populate it with data, we could # also send more complex data such as scene element links or custom data types. data: c4d.BaseContainer = c4d.BaseContainer(MSG_MY_EVENT) data[MSG_MY_EVENT_NUMBER] = 42 data[MSG_MY_EVENT_STRING] = "Bob is your uncle" # Send the message to #myNode alone. myNode.Message(c4d.MSG_BASECONTAINER, data) # Or broadcast it into all branches of #myNode as a multi message. So, when there would be a tag # on myNode which you have implemented too which can handle this message, it would receive it too. myNode.MultiMessage(c4d.MULTIMSG_ROUTE_BROADCAST, c4d.MSG_BASECONTAINER, data) # Receiving the message # -------------------------------------------------------------------------------------------------- class MyNode (c4d.plugins.ObjectData): """The node implementation which supports #MSG_MY_EVENT. """ def Message(self, node: c4d.GeListNode, mtype: int, data: any) -> bool: """ """ # This is a MSG_MY_EVENT event. if mtype == c4d.MSG_BASECONTAINER and data.GetId() == MSG_MY_EVENT: # Ensure that our message data contains all the data we expect it to have. if (data.FindIndex(MSG_MY_EVENT_NUMBER) == c4d.NOTOK or data.FindIndex(MSG_MY_EVENT_NUMBER) == c4d.NOTOK): raise KeyError("Malformed message data for 'MSG_MY_EVENT'.") num: int = data.GetInt32(MSG_MY_EVENT_NUMBER) string: int = data.GetString(MSG_MY_EVENT_STRING) print (num, string)
Cheers,
Ferdinand -
Thanks @ferdinand ,
What's
myNode
in the example above — that's object instance?I'll have a tag with ObjectLink entry which point to object in OM.
So I can just send message that simple?myTagInstance[ID_OBJECT_LINK].Message(c4d.MSG_BASECONTAINER, data)
obviously need to create variable, and check existence
-
Hey @baca,
myNode
would be here an instance ofBaseObject
since the classMyNode
implementsObjectData
. So,myNode
is what you get passed in inMyNode.Message(self, node, ...)
asnode
, the frontend entity that represents the plugin hook instance.And, yes, your code snippet seems to be correct, in case you intend to send a message to a
BaseList2D
(probably aBaseObject
) linked in the data container ofmyTagInstance
. To make sensible use of this, you would have to own the implemenation of the linked objectID_OBJECT_LINK
as described above.Cheers,
Ferdinand -
@ferdinand Thanks again
I'll have time to check it later today.
But it seems clear.