Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Send/Receive Messages in TagData/ObjectData plugins

    Cinema 4D SDK
    python
    2
    5
    711
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • bacaB
      baca
      last edited by

      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...

      ferdinandF 1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand @baca
        last edited by

        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 a BaseObject 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 message MSG_DO_STUFF: int = 1061999. We can send this message as much we want to an Ocube 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 to Ocube 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

        MAXON SDK Specialist
        developers.maxon.net

        bacaB 1 Reply Last reply Reply Quote 1
        • bacaB
          baca @ferdinand
          last edited by

          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

          ferdinandF 1 Reply Last reply Reply Quote 0
          • ferdinandF
            ferdinand @baca
            last edited by ferdinand

            Hey @baca,

            myNode would be here an instance of BaseObject since the class MyNode implements ObjectData. So, myNode is what you get passed in in MyNode.Message(self, node, ...) as node, 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 a BaseObject) linked in the data container of myTagInstance. To make sensible use of this, you would have to own the implemenation of the linked object ID_OBJECT_LINK as described above.

            Cheers,
            Ferdinand

            MAXON SDK Specialist
            developers.maxon.net

            bacaB 1 Reply Last reply Reply Quote 1
            • bacaB
              baca @ferdinand
              last edited by

              @ferdinand Thanks again

              I'll have time to check it later today.
              But it seems clear.

              1 Reply Last reply Reply Quote 0
              • First post
                Last post