Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python 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

    Is there a "msgId" when I add a child to an object?

    Cinema 4D SDK
    python
    2
    2
    386
    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.
    • L
      LingZA
      last edited by

      Is there a "msgId" in the function "GetDParameter(self, node, id, flags)" in the class "c4d.plugins.ObjectData" when I add a child to an object?
      The object is a deformer.
      I want to update the function "GetDDescription(self, node, description, flags)" via the function "GetDParameter(self, node, id, flags)" when I add a child to the deformer in the "Object Manager".

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

        Hi @LingZA there is not such event in Cinema 4D object system. Moreover if there would be one it will be on the Message method which is responsible to receive various event rather than GetDParameter which have the duty to override the value when C4DAtom.GetParameter is called.

        With that said the way to do that is to let Cinema 4D handle it for you, as Cinema 4D will call GetDDescription when it is needed. So you should check directly in GetDDescription if the object have a child. But it does not work when the attribute manager is locked with a specific object since GetDDescription is called only at the beginning when the object should be displayed. So to workaround this issue you can set the description of the object to be dirty, this will force Cinema 4D to update the description and therefor call GetDDescription.

        A concrete example bellow where a Float parameter is added if there is no child

        class DynamicParametersObjectData(c4d.plugins.ObjectData):
        
            def __init__(self):
                self.has_children = False
        
            def GetDDescription(self, node, description, flags):
                """Called by Cinema 4D when the description (UI) is queried.
        
                Args:
                    node (c4d.GeListNode): The instance of the ObjectData.
                    description (c4d.Description): The description to modify.
                    flags: return: The success status or the data to be returned.
        
                Returns:
                    Union[Bool, tuple(bool, Any, DESCFLAGS_DESC)]: The success status or the data to be returned.
                """
                # Loads the parameters from the description resource before adding dynamic parameters.
                if not description.LoadDescription(node.GetType()):
                    return False
        
                # If there is a child just return and don't add the float parameter
                if node.GetDown():
                    return True
        
                # Add a Float Parameter 
                bc = c4d.GetCustomDataTypeDefault(c4d.DTYPE_REAL)
                bc.SetString(c4d.DESC_NAME, "Dynamic REAL")
                descid = c4d.DescID(c4d.DescLevel(1100, c4d.DTYPE_REAL, node.GetType()))
                description.SetParameter(descid, bc, c4d.DescID(c4d.DescLevel((c4d.ID_OBJECTPROPERTIES))))
        
                # After dynamic parameters have been added successfully, return True and c4d.DESCFLAGS_DESC_LOADED with the input flags
                return True, flags | c4d.DESCFLAGS_DESC_LOADED
        
            def GetVirtualObjects(self, op, hh):
                """This method is called automatically when Cinema 4D ask for the cache of an object. 
        
                Args:
                    op (c4d.BaseObject): The Python Generator c4d.BaseObject.
                    hh (c4d.HierarchyHelp): Not implemented.
        
                Returns:
                    c4d.BaseObject: The newly allocated object chain, or None if a memory error occurred.
                """
                if op is None or hh is None:
                    raise RuntimeError("Failed to retrieve op or hh.")
        
                # Force Cinema 4D to call GetDDescription and therefor update the description if there is a child and the saved state is not in sync with scene state
                has_children = bool(op.GetDown())
                if (self.has_children) != has_children:
                    op.SetDirty(c4d.DIRTYFLAGS_DESCRIPTION)
                    self.has_children = has_children
        
                returnObj = c4d.BaseObject(c4d.Osphere)
                if returnObj is None:
                    raise MemoryError("Failed to create a sphere.")
        
                return returnObj
        
        
        
        if __name__ == "__main__":
            c4d.plugins.RegisterObjectPlugin(id=PLUGIN_ID,
                                             str="Py-DynamicParametersObject",
                                             g=DynamicParametersObjectData,
                                             description="opydynamicparametersobject",
                                             icon=c4d.bitmaps.InitResourceBitmap(c4d.Onull),
                                             info=c4d.OBJECT_GENERATOR)
        

        Cheers,
        Maxime.

        MAXON SDK Specialist

        Development Blog, MAXON Registered Developer

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