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

    Detecting Rename

    Cinema 4D SDK
    python
    4
    11
    1.8k
    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.
    • ferdinandF
      ferdinand
      last edited by ferdinand

      Hi,

      I am not the biggest expert on Cinema's core message system, but AFAIK EVMSG_CHANGE is only being broadcasted for modification of the scene graph or similar events, not the modification of nodes.

      Messages for the modification of nodes are being sent as atom messages (C4DAtom.Message) and there is unfortunately currently no way in Cinema to subscribe to such events from the outside. Cinema's closest thing to that would be C4DAtom.GetDirty, which will, among other things, allow you to track the dirty state of the data container (a.k.a. the attributes) of the node, but would have to be checked regularly by yourself.

      But this all seems overly complicated for such a simple task, simply design an object that regularly checks the names of the nodes that it is meant to monitor. One solution could be a MessageData plugin with its timer method.

      Also: I am also not quite sure what you are trying to do there with the PyCObject in your code. It just holds a void pointer, i.e. an address and a block size for a memory region. The type is mostly useless in Python itself and only comes in handy when you use Python as a glue-language between two C(++) applications (i.e. is heavily used by Python itself internally). You can technically parse some basic C-types with Python's struct if you know their memory location, but that won't work with anything more complicated.

      Cheers,
      zipit

      MAXON SDK Specialist
      developers.maxon.net

      1 Reply Last reply Reply Quote 1
      • M
        m_adam
        last edited by

        Hi @blastframe

        To be more precise EVMSG_CHANGE is called when an EventAdd is processed, which is normally done after a SetName but not mandatory.

        SetName actually set the dirty c4d.DIRTYFLAGS_DATA on the renamed element. Moreover, the MSG_NOTIFY_EVENT is also sent so that means any BaseList2D can receive a notification when the other object is renamed.
        Here a short example with a Tag listening for the renaming of its host object.

        import c4d
        
        def message(msgType, data):
            if msgType == c4d.MSG_NOTIFY_EVENT:
                if data["eventid"] == c4d.NOTIFY_EVENT_SETNAME:
                    renamedObj = data["bl"]
        
                    print(renamedObj.GetName())
        
        
        def main():
            obj = op.GetObject()
        
            if not obj.FindEventNotification(doc, op, c4d.NOTIFY_EVENT_SETNAME):
                obj.AddEventNotification(op, c4d.NOTIFY_EVENT_SETNAME, 0, c4d.BaseContainer())
        
        if __name__=='__main__':
            main()
        

        Note that AddEventNotification is to be used with extreme care as you can screw up the Cinema 4D message system. so please only read the data and don't do infinite change (aka renaming the initial object, since it will trigger another MSG_NOTIFY_EVENT message and you can easily end with an infinite loop).

        Finally, another way to achieve what you want is to have a list of tuples of object and associate name.
        Then within a Timer check if the name changed by iterating this list.

        Cheers,
        Maxime

        MAXON SDK Specialist

        Development Blog, MAXON Registered Developer

        1 Reply Last reply Reply Quote 0
        • ?
          A Former User
          last edited by A Former User

          @zipit and @m_adam , thank you for the replies.

          @zipit , I have no clue what the PyCObject code is doing: I found that code in a few threads on this forum for deciphering BFM_CORE_PAR1 and BFM_CORE_PAR2 from the CoreMessage. It doesn't seem to find any information.

          @m_adam , is there a way to listen to NOTIFY_EVENT_SETNAME from a GeDialog? Sorry, I forgot to mention that I'd be doing this from a Command Plugin and a GeDialog.

          Thank you!

          1 Reply Last reply Reply Quote 0
          • indexofrefractionI
            indexofrefraction
            last edited by

            Can I ask if it is possible to get a notification when

            • the generator bit gets changed?
            • the visibility / render bits get changed?

            there doesnt seem to be a NOTIFY_EVENT for these actions...

            1 Reply Last reply Reply Quote 0
            • M
              m_adam
              last edited by

              For the generator bit, this can be somehow done via

              import c4d
              
              def message(msgType, data):
                  if msgType == c4d.MSG_NOTIFY_EVENT:
                      if data["event_data"]["msg_id"] == c4d.MSG_DEFORMMODECHANGED:
                          print(data)
              
              
              
              def main():
                  obj = doc.GetFirstObject()
              
                  if not obj.FindEventNotification(doc, op, c4d.NOTIFY_EVENT_MESSAGE):
                      obj.AddEventNotification(op, c4d.NOTIFY_EVENT_MESSAGE , 0, c4d.BaseContainer())
              
              if __name__=='__main__':
                  main()
              

              The main issue is it's triggered only after an EventAdd so this means most of the time you will not get the change immediately.

              Regarding the visibility, this is unfortunately not possible, since SetEditorMode/SetRenderMode only do a SetDirty(DIRTYFLAGS::MATRIX) internally. And the dirty state is not monitored by the Event Notification system.

              One side note it's possible to use MSG_DESCRIPTION_POSTSETPARAMETER like in the snippet bellow, but this message is sent by the Attribute Manager when a parameter is set, so that means if you change the value within the Attribute Manager of the Editor display mode, the change will be monitored, but if you change the mode via the Object Manager, which directly use SetEditorMode, then the message is not sent.

              import c4d
              
              def message(msgType, data):
                  if msgType == c4d.MSG_NOTIFY_EVENT:
                      if data["event_data"]["msg_id"] == c4d.MSG_DESCRIPTION_POSTSETPARAMETER:
                          if data["event_data"]["msg_data"]["descid"] == c4d.DescID(c4d.ID_BASEOBJECT_VISIBILITY_EDITOR):
                              print("changed editor")
                          elif data["event_data"]["msg_data"]["descid"] == c4d.DescID(c4d.ID_BASEOBJECT_VISIBILITY_RENDER):
                              print("changed render")
                          elif data["event_data"]["msg_data"]["descid"] == c4d.DescID(c4d.ID_BASEOBJECT_GENERATOR_FLAG):
                              print("changed generator")
              
              
              def main():
                  obj = doc.GetFirstObject()
              
                  if not obj.FindEventNotification(doc, op, c4d.NOTIFY_EVENT_MESSAGE):
                      obj.AddEventNotification(op, c4d.NOTIFY_EVENT_MESSAGE , 0, c4d.BaseContainer())
              
              if __name__=='__main__':
                  main()
              

              Cheers,
              Maxime.

              MAXON SDK Specialist

              Development Blog, MAXON Registered Developer

              ? 1 Reply Last reply Reply Quote 0
              • ?
                A Former User @m_adam
                last edited by

                @m_adam Hi Maxime, any notes on the GeDialog question prior to the generator question: Is it possible to listen to a rename event from a GeDialog in a Command Plugin?

                1 Reply Last reply Reply Quote 1
                • indexofrefractionI
                  indexofrefraction
                  last edited by indexofrefraction

                  @m_adam :

                  thanks, i need it to work when editing live in the object manager. i found a little hack for the generator flag snippet:
                  like this, i immediately get a msg if i change the generator flag in the object manager. without the print statement it does not work.
                  do you understand this? i guess its not recommended? .-)

                  just put that script in a python tag on an object with a generator switch (instance for example)

                  import c4d
                  
                  def message(msgType, data):
                      if msgType == c4d.MSG_NOTIFY_EVENT:
                          if data["event_data"]["msg_id"] == c4d.MSG_DEFORMMODECHANGED:
                              obj = op.GetObject()
                              print(obj.GetName(), obj[c4d.ID_BASEOBJECT_GENERATOR_FLAG])
                  
                  def main():
                      obj = op.GetObject()
                      if not obj.FindEventNotification(doc, op, c4d.NOTIFY_EVENT_MESSAGE):
                          obj.AddEventNotification(op, c4d.NOTIFY_EVENT_MESSAGE , 0, c4d.BaseContainer())
                      print(""), # DIRTY HACK :)
                  
                  if __name__=='__main__':
                      main()
                  
                  1 Reply Last reply Reply Quote 0
                  • M
                    m_adam
                    last edited by

                    @blastframe sorry no there is nothing for a GeDialog, if you are in a GeDialog, your best bet is within the GeDialog's CoreMessage, listen for EVMSG_CHANGE and figured out if the generator changed or not.

                    @indexofrefraction print will require a redraw as soon as possible, and most important this will consume all messages.
                    So is it nice? Not really but I guess you don't have other choices.

                    Cheers,
                    Maxime.

                    MAXON SDK Specialist

                    Development Blog, MAXON Registered Developer

                    ? 1 Reply Last reply Reply Quote 0
                    • ?
                      A Former User @m_adam
                      last edited by A Former User

                      This post is deleted!
                      1 Reply Last reply Reply Quote 0
                      • ferdinandF
                        ferdinand
                        last edited by

                        Hello @blastframe,

                        without any further questions or replies, we will consider this topic to be solved by Monday and flag it accordingly.

                        Thank you for your understanding,
                        Ferdinand

                        MAXON SDK Specialist
                        developers.maxon.net

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