Is there a "msgId" when I add a child to an object?
-
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". -
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.