set GvNode value via python
-
Hey community,
This my first dive into graphview node, sorry if this is a stupid basic question.
I want to set condition node input port (GvPort) value, but it seems I can not do this via
__settitem__/SetParameter, is this is a limit or I do it in wrong way?Cheers~
DunHou

import c4d def iterateNodes(node): while node: description = node.GetDescription(c4d.DESCFLAGS_DESC_0) data: c4d.BaseContainer pid: c4d.DescID for data, pid, _ in description: value: any | None = None try: value = node[pid] except: value = "Inaccessible in Python" if str(data[c4d.DESC_NAME]).startswith("Input"): print(f"\tInput '{data[c4d.DESC_NAME]}'(c4d.{data[c4d.DESC_IDENT]}) = {value} type: {type(value)}") node[2000, 1001] = 2 # TypeError: __setitem__ got unexpected type 'int'. node.SetParameter([2000, 1002],2,0) # no error but not worrk. print(node[2000, 1001].GetDataInstance()) # AttributeError: parameter access failed if node.IsGroupNode(): iterateNodes(node.GetDown()) node = node.GetNext() def main(): # Checks if selected object is valid if op is None: raise ValueError("op is none, please select one object.") # Retrieves the xpresso Tag xpressoTag = op.GetTag(c4d.Texpresso) if xpressoTag is None: raise ValueError("Make sure the selected object get an Xpresso Tag.") # Retrieves the node master gvNodeMaster = xpressoTag.GetNodeMaster() if gvNodeMaster is None: raise RuntimeError("Failed to retrieve the Node Master.") # Retrieves the Root node (the Main XGroup) that holds all others nodes gvRoot = gvNodeMaster.GetRoot() if gvRoot is None: raise RuntimeError("Failed to retrieve the Root Node.") # Iterates overs all nodes of this root node. iterateNodes(gvRoot) if __name__ == '__main__': main() -
Hey @Dunhou,
Thank you for reaching out to us. This is probably possible, but I'll have to check with a debugger myself. These are dynamically generated ports which tend to be a pain in the butt in Xpresso, as pretty much every node type handles them slightly differently, and even by looking at our source code you often do not get any wiser. My guess would have been that it is something like
c4d.DescID(c4d.DescLevel(c4d.GV_CONDITION_INPUT, c4d.DTYPE_SUBCONTAINER, condNode.GetType()), c4d.DescLevel(0, c4d.DTYPE_REAL, 0))or the same but other values for the second desc level such as 1000, 2000, etc. instead of0.GV_CONDITION_INPUTis defined in the description as the input group.I will have to attach a debugger to see what is going on, but where I am currently working from, I have no compiled version of Cinema 4D. Will check in the next days from my Mac, where I do have a compiled version. You can check this thread for context, the function
PythonNodeLayerShaderAccessgoes into some details (a Python node also has a dynamic/variadic number of in- and output ports).Cheers,
Ferdinand"""My attempt in setting the dynamic ID_OPERATOR_CONDITION operator in ports (does not work). """ import c4d from c4d.modules.graphview import GvNodeMaster, GvNode, GvPort, XPressoTag from mxutils import CheckType doc: c4d.documents.BaseDocument # The currently active document. op: c4d.BaseObject | None # The primary selected object in `doc`. Can be `None`. def main() -> None: """Called by Cinema 4D when the script is being executed. """ null: c4d.BaseObject = CheckType(c4d.BaseObject(c4d.Onull)) tag: XPressoTag = CheckType(null.MakeTag(c4d.Texpresso)) master: GvNodeMaster = CheckType(tag.GetNodeMaster()) doc.InsertObject(null) root: GvNode = CheckType(master.GetRoot()) condNode: GvNode = CheckType(master.CreateNode(root, c4d.ID_OPERATOR_CONDITION, x=200, y=200)) # Set values: did_1: c4d.DescID = c4d.DescID( c4d.DescLevel(c4d.GV_CONDITION_INPUT, c4d.DTYPE_SUBCONTAINER, condNode.GetType()), c4d.DescLevel(0, c4d.DTYPE_REAL, 0) ) did_2: c4d.DescID = c4d.DescID( c4d.DescLevel(c4d.GV_CONDITION_INPUT, c4d.DTYPE_SUBCONTAINER, condNode.GetType()), c4d.DescLevel(1, c4d.DTYPE_REAL, 0) ) a = condNode.SetParameter(did_1, 10.0, c4d.DESCFLAGS_SET_0) b = condNode.SetParameter(did_2, 20.0, c4d.DESCFLAGS_SET_0) print(a, b) c4d.EventAdd() if __name__ == '__main__': main()