How to access animation tracks for a GraphNode in a capsule
-
Hi,
I don't see how to access the animation track for a node in a node-based object such as Particle Node Modifier and Distribution object.
I've seen several examples of obtaining tracks for nodes in a Redshift material, and it seems possible to access them using NodeMaterial.GetBaseListForNode. However, this is for materials and cannot be applied to capsules.
Similarly, I assume that obtaining the BaseList2D linked to the GraphNode would allow access to the animation track, but how can this be achieved?
If anyone knows how to do this, it would be appreciated.
Thank you. -
Hello @kng_ito,
thank you for reaching out to us. The answer to your question is
BaseList2Dand NimbusBaseInterface, as they both in tandem realize the relationship between Cinema and Maxon API scene elements. What node materials offer is just a convenience interface which is also offered in a more generic way via the mentioned classes.A
BaseList2Dis the base type for a generic Cinema API scene element that holds a data container. It also offers methods to retrieve one or manyNimbusBaseInterfacereferences for that element, each associating this element of a Cinema API scene with a Maxon API nodes graph. A node material will for example have oneNimbusBaseInterfacereference for each material node space (i.e., render engine and with that node graph) it supports.I actually thought there were already forum posts or even a code example about this subject, but I could not find any. So, I created a small code example addressing exactly this topic, as this is probably something people want to do commonly. It will be part of an upcoming Python SDK, but you can find a draft version below. The code is not that complicated, but the subject/theory around it is not entirely trivial. So, it is one of these code examples which is more words than code. I hope this helps you to understand the relationship between Cinema API scene elements and Maxon API nodes graphs better.
Cheers,
FerdinandResult

'' (BaseDocument: Tbasedocument) ├── [Branch] 'Render Settings' (Rbase) │ └── 'My Render Setting' (RenderData: Rbase) │ ├── [Branch] 'Post Effects' (VPbase) │ │ ├── 'Magic Bullet Looks' (BaseVideoPost: VPMagicBulletLooks) │ │ └── 'Redshift' (BaseVideoPost: VPrsrenderer) │ └── [Branch] 'Multi-Pass' (Zmultipass) │ └── 'Post Effects' (BaseList2D: Zmultipass) ├── [Branch] 'Scene Hooks' (SHplugin) │ ├── 'STHOOK' (BaseList2D: 1012061) │ ├── 'Python Embedded Change Monitor' (BaseList2D: 1058422) │ ├── 'SceneHook' (BaseList2D: 1028481) │ ├── 'CmSceneHook' (BaseList2D: 1026839) │ ├── 'CameraMorphDrawSceneHook' (BaseList2D: 1029281) │ ├── 'MotionCameraDrawSceneHook' (BaseList2D: 1029338) │ ├── 'USD Scene Hook' (BaseList2D: 1055307) │ ├── 'Substance Assets' (BaseList2D: 1032107) │ ├── 'Alembic Archive Hook' (BaseList2D: 1028458) │ ├── 'UpdateMerge Hook' (BaseList2D: 465001602) │ ├── 'ArchiExchangeCADHook' (BaseList2D: 200000216) │ ├── 'Paint Brush' (BaseList2D: 1031368) │ ├── 'SLA wave scene hook' (BaseList2D: REG_EXP_PARSER) │ ├── 'Thinking Particles' (TP_MasterSystem: ID_THINKINGPARTICLES) │ ├── '' (BaseList2D: 1035577) │ ├── 'Bullet' (BaseList2D: 180000100) │ ├── 'XRefs' (BaseList2D: 1025807) │ ├── 'CAManagerHook' (BaseList2D: 1019636) │ │ └── [Branch] 'Weights Handler Head' (Tbaselist2d) │ │ └── 'Weights Handler' (BaseList2D: 1037891) │ ├── 'Volume Save Manager Hook' (BaseList2D: 1040459) │ ├── 'UV Display 3D SceneHook' (BaseList2D: 1054166) │ ├── 'uvhook' (BaseList2D: 1053309) │ ├── 'ScatterPlacementHook' (BaseList2D: 1058060) │ ├── 'Tool System Hook' (BaseList2D: ID_TOOL_SYSTEM_HOOK) │ │ └── [Branch] 'SBM' (431000215) │ │ └── 'Symmetry node' (BaseList2D: 431000215) │ │ └── [Branch] 'C4DCoreWrapper' (200001044) │ │ └── 'Symmetry node - net.maxon.symmetry.context.modeling' (BaseList2D: 300001078) │ ├── 'MoGraphSceneHook' (BaseList2D: 1019525) │ ├── 'gozScenehook' (BaseList2D: 1059748) │ ├── 'Octane X' (BaseList2D: 1030798) │ ├── 'Simulation' (BaseList2D: ID_SIMULATIONSCENE_HOOK) │ │ └── [Branch] 'Simulation World' (Obase) │ │ └── 'Default Simulation Scene' (BaseObject: Osimulationscene) │ ├── 'PersistentHook' (BaseList2D: 180420202) │ ├── 'Scene Nodes' (BaseList2D: SCENENODES_IDS_SCENEHOOK_ID) │ │ └── [Branch] 'Nodes' (300001078) │ │ ├── 'Group' (BaseList2D: 300001078) │ │ ├── 'Group' (BaseList2D: 300001078) │ │ ├── 'Group' (BaseList2D: 300001078) │ │ ├── 'Geometry Op' (BaseList2D: 300001078) │ │ ├── 'Scene Root' (BaseList2D: 300001078) │ │ └── 'Cube' (BaseList2D: 300001078) │ │ └── [Branch] 'Tracks' (CTbase) │ │ ├── 'Size . X' (CTrack: CTbase) │ │ │ └── [Branch] 'Sequences' (CSbase) │ │ │ └── '' (CCurve: CSbase) │ │ ├── 'Size . Y' (CTrack: CTbase) │ │ │ └── [Branch] 'Sequences' (CSbase) │ │ │ └── '' (CCurve: CSbase) │ │ └── 'Size . Z' (CTrack: CTbase) │ │ └── [Branch] 'Sequences' (CSbase) │ │ └── '' (CCurve: CSbase) │ ├── 'NE_SceneHook' (BaseList2D: 465002367) │ ├── 'Take Hook' (BaseList2D: 431000055) │ │ └── [Branch] 'Take System Branch' (TakeBase) │ │ └── 'Main' (BaseTake: TakeBase) │ │ └── [Branch] 'Override Folders' (431000073) │ │ └── 'Overrides' (BaseList2D: 431000073) │ │ ├── 'Others' (BaseList2D: 431000073) │ │ ├── 'Layers' (BaseList2D: 431000073) │ │ ├── 'Materials' (BaseList2D: 431000073) │ │ ├── 'Shaders' (BaseList2D: 431000073) │ │ ├── 'Tags' (BaseList2D: 431000073) │ │ └── 'Objects' (BaseList2D: 431000073) │ ├── 'CombineAc18_AutoCombine_SceneHook' (BaseList2D: 1032178) │ ├── 'PLKHUD' (BaseList2D: 1020132) │ │ └── [Branch] 'PSUNDOHEAD' (Obase) │ │ └── 'PKHOP' (BaseObject: 1020120) │ ├── 'RenderManager Hook' (BaseList2D: 465003509) │ ├── 'Sound Scrubbing Hook' (BaseList2D: 100004815) │ ├── 'To Do' (BaseList2D: 465001536) │ ├── 'Animation' (BaseList2D: 465001535) │ ├── 'BaseSettings Hook' (BaseList2D: ID_BS_HOOK) │ ├── '' (BaseList2D: 1060457) │ ├── 'SculptBrushModifierSceneHook' (BaseList2D: 1030499) │ ├── 'Sculpt Objects' (BaseList2D: 1024182) │ ├── 'HairHighlightHook' (BaseList2D: 1018870) │ ├── 'MeshObject Scene Hook' (BaseList2D: 1037041) │ ├── 'Lod Hook' (BaseList2D: 431000182) │ ├── 'Annotation Tag SceneHook' (BaseList2D: 1030679) │ ├── 'Sniper' (BaseList2D: 430000000) │ ├── 'Mesh Check Hook' (BaseList2D: 431000027) │ ├── 'Modeling Objects Hook' (BaseList2D: 431000032) │ │ └── [Branch] 'Modeling Objects Branch' (431000031) │ │ ├── 'Pattern Direction Manipulator' (BaseObject: Opatternmanipulator) │ │ ├── 'Plane Manipulator' (BaseObject: Oplanemanipulator) │ │ ├── 'Pivot Manipulator' (BaseObject: Opivotmanipulator) │ │ ├── 'Knife Line Manipulator' (BaseObject: 431000168) │ │ ├── 'Subdivision Manipulator' (BaseObject: 431000172) │ │ └── 'PolyPenObject' (BaseObject: 431000031) │ ├── 'Snap Scenehook' (BaseList2D: 440000111) │ │ ├── [Branch] 'WpSH' (440000111) │ │ │ └── 'WorkPlane' (BaseObject: Oworkplane) │ │ └── [Branch] 'MdSH' (Tbase) │ │ └── 'Modeling Settings' (BaseList2D: 440000140) │ ├── 'Doodle Hook' (BaseList2D: 1022212) │ ├── 'Stereoscopic' (BaseList2D: 450000226) │ ├── 'ViewportExtHookHUD' (BaseList2D: ID_VIEW_SCENEHOOKHUD) │ ├── 'ViewportExtHookhighlight' (BaseList2D: ID_VIEW_SCENEHOOKHIGHLIGHT) │ ├── 'MeasureSceneHook' (BaseList2D: ID_MEASURE_SCENEHOOK) │ ├── 'Redshift' (BaseList2D: 1036748) │ ├── 'GvHook' (BaseList2D: ID_SCENEHOOK_PLUGIN) │ ├── 'Material Scene Hook' (BaseList2D: 300001077) │ ├── 'TargetDistancePicker' (BaseList2D: 1028063) │ └── 'BodyPaint SceneHook' (BaseList2D: 1036428) └── [Branch] '' (Tbasedraw) └── '' (BaseList2D: 110306) --- Maxon API Scene Nodes Data --- Maxon API node: net.maxon.neutron.scene.root -> Cinema API surrogate node: <c4d.BaseList2D object called Scene Root with ID 300001078 at 22186209472> Input port: net.maxon.neutron.scene.root/_0<in -> DescID: ((1768816640, 5, 0), (1, 133, 0)) Input port: net.maxon.neutron.scene.root/_0<in/flags -> DescID: ((1768828774, 5, 0), (1818322803, 12, 0)) Input port: net.maxon.neutron.scene.root/_0<filter -> DescID: ((1718185076, 5, 0), (1701969920, 5, 0), (1, 400006001, 0)) Input port: net.maxon.neutron.scene.root/_0/rot<in -> DescID: ((1768816640, 5, 0), (1, 133, 0)) Input port: net.maxon.neutron.scene.root/_0/rot<datatype -> DescID: ((1684108385, 5, 0), (1954115685, 5, 0), (1, 15, 0)) Input port: net.maxon.neutron.scene.root/net.maxon.neutron.corenode.multransform_0<datatype -> DescID: ((1684108385, 5, 0), (1954115685, 5, 0), (1, 15, 0)) Input port: net.maxon.neutron.scene.root/net.maxon.neutron.corenode.multransform_0<in2 -> DescID: ((1768829440, 5, 0), (1, 133, 0)) Input port: net.maxon.neutron.scene.root/net.maxon.neutron.corenode.multransform_0<in1 -> DescID: ((1768829184, 5, 0), (1, 133, 0)) Input port: net.maxon.neutron.scene.root<net.maxon.neutron.op.objectbase.children -> DescID: ((1852142638, 5, 0), (1835104367, 5, 0), (1848536677, 5, 0), (1970565743, 5, 0), (1848536944, 5, 0), (779051626, 5, 0), (1701016674, 5, 0), (1634952494, 5, 0), (1667787116, 5, 0), (1685218670, 5, 0), (593719149, 5, 0), (1835101796, 5, 0), (593585252, 5, 0), (1986097769, 5, 0), (1633970531, 5, 0), (1886351988, 8, 0)) Input port: net.maxon.neutron.scene.root<net.maxon.neutron.op.objectbase.children/_0 -> DescID: ((1852142638, 5, 0), (1835104367, 5, 0), (1848536677, 5, 0), (1970565743, 5, 0), (1848536944, 5, 0), (779051626, 5, 0), (1701016674, 5, 0), (1634952494, 5, 0), (1667787116, 5, 0), (1685218670, 5, 0), (774975086, 5, 0), (1702112877, 5, 0), (1635282798, 5, 0), (778986869, 5, 0), (1953656686, 5, 0), (779055150, 5, 0), (1868720741, 5, 0), (1668571745, 5, 0), (1936010851, 5, 0), (1751739492, 5, 0), (1919249920, 5, 0), (1, 133, 0)) Maxon API node: net.maxon.neutron.scene.root/_0 -> Cinema API surrogate node: <c4d.BaseList2D object called Group with ID 300001078 at 22186202432> Input port: net.maxon.neutron.scene.root/_0<in -> DescID: ((1768816640, 5, 0), (1, 133, 0)) Input port: net.maxon.neutron.scene.root/_0<in/flags -> DescID: ((1768828774, 5, 0), (1818322803, 12, 0)) Input port: net.maxon.neutron.scene.root/_0<filter -> DescID: ((1718185076, 5, 0), (1701969920, 5, 0), (1, 400006001, 0)) Input port: net.maxon.neutron.scene.root/_0/rot<in -> DescID: ((1768816640, 5, 0), (1, 133, 0)) Input port: net.maxon.neutron.scene.root/_0/rot<datatype -> DescID: ((1684108385, 5, 0), (1954115685, 5, 0), (1, 15, 0)) Maxon API node: net.maxon.neutron.scene.root/_0/rot -> Cinema API surrogate node: <c4d.BaseList2D object called Group with ID 300001078 at 22186170048> Input port: net.maxon.neutron.scene.root/_0/rot<in -> DescID: ((1768816640, 5, 0), (1, 133, 0)) Input port: net.maxon.neutron.scene.root/_0/rot<datatype -> DescID: ((1684108385, 5, 0), (1954115685, 5, 0), (1, 15, 0)) Maxon API node: net.maxon.neutron.scene.root/concat -> Cinema API surrogate node: None Maxon API node: net.maxon.neutron.scene.root/net.maxon.neutron.corenode.multransform_0 -> Cinema API surrogate node: <c4d.BaseList2D object called Group with ID 300001078 at 22186170048> Input port: net.maxon.neutron.scene.root/net.maxon.neutron.corenode.multransform_0<datatype -> DescID: ((1684108385, 5, 0), (1954115685, 5, 0), (1, 15, 0)) Input port: net.maxon.neutron.scene.root/net.maxon.neutron.corenode.multransform_0<in2 -> DescID: ((1768829440, 5, 0), (1, 133, 0)) Input port: net.maxon.neutron.scene.root/net.maxon.neutron.corenode.multransform_0<in1 -> DescID: ((1768829184, 5, 0), (1, 133, 0)) Maxon API node: geometry@WCuZ0OX$L9brZcIW8Vdmn6 -> Cinema API surrogate node: <c4d.BaseList2D object called Geometry Op with ID 300001078 at 22186209472> Input port: geometry@WCuZ0OX$L9brZcIW8Vdmn6<geometry -> DescID: ((1734700909, 5, 0), (1702130297, 5, 0), (1, 133, 0)) Input port: geometry@WCuZ0OX$L9brZcIW8Vdmn6<net.maxon.node.bypassable.bypass -> DescID: ((1852142638, 5, 0), (1835104367, 5, 0), (1848536687, 5, 0), (1684352610, 5, 0), (2037408115, 5, 0), (1935762028, 5, 0), (1697538681, 5, 0), (1885434739, 5, 0), (1, 400006001, 0)) Maxon API node: cube@MJo3tkcbJ1Zgd2oqJzGis5 -> Cinema API surrogate node: <c4d.BaseList2D object called Cube with ID 300001078 at 22186170048> Input port: cube@MJo3tkcbJ1Zgd2oqJzGis5<net.maxon.command.modeling.primitive.cube.subz -> DescID: ((1852142638, 5, 0), (1835104367, 5, 0), (1848533871, 5, 0), (1835884910, 5, 0), (1680764271, 5, 0), (1684368489, 5, 0), (1852255856, 5, 0), (1919511913, 5, 0), (1953068645, 5, 0), (778270050, 5, 0), (1697543029, 5, 0), (1652162560, 5, 0), (1, 15, 0)) Input port: cube@MJo3tkcbJ1Zgd2oqJzGis5<net.maxon.command.modeling.primitive.cube.suby -> DescID: ((1852142638, 5, 0), (1835104367, 5, 0), (1848533871, 5, 0), (1835884910, 5, 0), (1680764271, 5, 0), (1684368489, 5, 0), (1852255856, 5, 0), (1919511913, 5, 0), (1953068645, 5, 0), (778270050, 5, 0), (1697543029, 5, 0), (1652097024, 5, 0), (1, 15, 0)) Input port: cube@MJo3tkcbJ1Zgd2oqJzGis5<net.maxon.command.modeling.primitive.cube.subx -> DescID: ((1852142638, 5, 0), (1835104367, 5, 0), (1848533871, 5, 0), (1835884910, 5, 0), (1680764271, 5, 0), (1684368489, 5, 0), (1852255856, 5, 0), (1919511913, 5, 0), (1953068645, 5, 0), (778270050, 5, 0), (1697543029, 5, 0), (1652031488, 5, 0), (1, 15, 0)) Input port: cube@MJo3tkcbJ1Zgd2oqJzGis5<net.maxon.command.modeling.primitive.fillets.segment -> DescID: ((1852142638, 5, 0), (1835104367, 5, 0), (1848533871, 5, 0), (1835884910, 5, 0), (1680764271, 5, 0), (1684368489, 5, 0), (1852255856, 5, 0), (1919511913, 5, 0), (1953068645, 5, 0), (778463596, 5, 0), (1818588275, 5, 0), (779314535, 5, 0), (1835363956, 5, 0), (1, 15, 0)) Input port: cube@MJo3tkcbJ1Zgd2oqJzGis5<net.maxon.command.modeling.primitive.fillets.radius -> DescID: ((1852142638, 5, 0), (1835104367, 5, 0), (1848533871, 5, 0), (1835884910, 5, 0), (1680764271, 5, 0), (1684368489, 5, 0), (1852255856, 5, 0), (1919511913, 5, 0), (1953068645, 5, 0), (778463596, 5, 0), (1818588275, 5, 0), (779247972, 5, 0), (1769304832, 5, 0), (1, 19, 0)) Input port: cube@MJo3tkcbJ1Zgd2oqJzGis5<net.maxon.command.modeling.primitive.fillets.enable -> DescID: ((1852142638, 5, 0), (1835104367, 5, 0), (1848533871, 5, 0), (1835884910, 5, 0), (1680764271, 5, 0), (1684368489, 5, 0), (1852255856, 5, 0), (1919511913, 5, 0), (1953068645, 5, 0), (778463596, 5, 0), (1818588275, 5, 0), (778399329, 5, 0), (1651270912, 5, 0), (1, 400006001, 0)) Input port: cube@MJo3tkcbJ1Zgd2oqJzGis5<net.maxon.command.modeling.primitive.cube.separate -> DescID: ((1852142638, 5, 0), (1835104367, 5, 0), (1848533871, 5, 0), (1835884910, 5, 0), (1680764271, 5, 0), (1684368489, 5, 0), (1852255856, 5, 0), (1919511913, 5, 0), (1953068645, 5, 0), (778270050, 5, 0), (1697543013, 5, 0), (1885434465, 5, 0), (1952776192, 5, 0), (1, 400006001, 0)) Input port: cube@MJo3tkcbJ1Zgd2oqJzGis5<net.maxon.command.modeling.primitive.size -> DescID: ((1852142638, 5, 0), (1835104367, 5, 0), (1848533871, 5, 0), (1835884910, 5, 0), (1680764271, 5, 0), (1684368489, 5, 0), (1852255856, 5, 0), (1919511913, 5, 0), (1953068645, 5, 0), (779315578, 5, 0), (1694498816, 5, 0), (1, 23, 0)) Input port: cube@MJo3tkcbJ1Zgd2oqJzGis5<net.maxon.command.modeling.primitive.size/*access*zin -> DescID: ((1852142638, 5, 0), (1835104367, 5, 0), (1848533871, 5, 0), (1835884910, 5, 0), (1680764271, 5, 0), (1684368489, 5, 0), (1852255856, 5, 0), (1919511913, 5, 0), (1953068645, 5, 0), (779315578, 5, 0), (1697589857, 5, 0), (1667458419, 5, 0), (1932163689, 5, 0), (1845493760, 5, 0), (1, 19, 0)) Input port: cube@MJo3tkcbJ1Zgd2oqJzGis5<net.maxon.command.modeling.primitive.size/*access*xin -> DescID: ((1852142638, 5, 0), (1835104367, 5, 0), (1848533871, 5, 0), (1835884910, 5, 0), (1680764271, 5, 0), (1684368489, 5, 0), (1852255856, 5, 0), (1919511913, 5, 0), (1953068645, 5, 0), (779315578, 5, 0), (1697589857, 5, 0), (1667458419, 5, 0), (1932163177, 5, 0), (1845493760, 5, 0), (1, 19, 0)) Input port: cube@MJo3tkcbJ1Zgd2oqJzGis5<net.maxon.command.modeling.primitive.size/*access*yin -> DescID: ((1852142638, 5, 0), (1835104367, 5, 0), (1848533871, 5, 0), (1835884910, 5, 0), (1680764271, 5, 0), (1684368489, 5, 0), (1852255856, 5, 0), (1919511913, 5, 0), (1953068645, 5, 0), (779315578, 5, 0), (1697589857, 5, 0), (1667458419, 5, 0), (1932163433, 5, 0), (1845493760, 5, 0), (1, 19, 0)) Maxon API node: cube@MJo3tkcbJ1Zgd2oqJzGis5/parambuilder -> Cinema API surrogate node: None Maxon API node: cube@MJo3tkcbJ1Zgd2oqJzGis5/defaultselections -> Cinema API surrogate node: None Maxon API node: cube@MJo3tkcbJ1Zgd2oqJzGis5/generategeometry -> Cinema API surrogate node: None Maxon API node: context_externaltimeinput -> Cinema API surrogate node: <c4d.BaseList2D object called Group with ID 300001078 at 22186170048> Input port: context_externaltimeinput<searchpaths -> DescID: ((1936023922, 5, 0), (1667788897, 5, 0), (1953002240, 12, 0)) Input port: context_externaltimeinput<fps -> DescID: ((1718645504, 5, 0), (1, 19, 0)) Input port: context_externaltimeinput<time -> DescID: ((1953066341, 5, 0), (1, 19, 0)) Input port: context_externaltimeinput<nimbus -> DescID: ((1852403042, 5, 0), (1970470912, 12, 0)) Input port: context_externaltimeinput<ocioconfig -> DescID: ((1868786031, 5, 0), (1668247142, 5, 0), (1768357888, 12, 0)) Input port: context_externaltimeinput<renderspace -> DescID: ((1919250020, 5, 0), (1701999472, 5, 0), (1633903872, 12, 0)) Maxon API node: context_notime -> Cinema API surrogate node: <c4d.BaseList2D object called Group with ID 300001078 at 16252169408> Input port: context_notime<searchpaths -> DescID: ((1936023922, 5, 0), (1667788897, 5, 0), (1953002240, 12, 0)) Input port: context_notime<fps -> DescID: ((1718645504, 5, 0), (1, 19, 0)) Input port: context_notime<time -> DescID: ((1953066341, 5, 0), (1, 19, 0)) Input port: context_notime<nimbus -> DescID: ((1852403042, 5, 0), (1970470912, 12, 0)) Input port: context_notime<ocioconfig -> DescID: ((1868786031, 5, 0), (1668247142, 5, 0), (1768357888, 12, 0)) Input port: context_notime<renderspace -> DescID: ((1919250020, 5, 0), (1701999472, 5, 0), (1633903872, 12, 0)) Maxon API node: builder -> Cinema API surrogate node: <c4d.BaseList2D object called Group with ID 300001078 at 16252169792> Input port: builder<in -> DescID: ((1768816640, 5, 0), (1, 133, 0)) Input port: builder<in/flags -> DescID: ((1768828774, 5, 0), (1818322803, 12, 0)) Input port: builder<filter -> DescID: ((1718185076, 5, 0), (1701969920, 5, 0), (1, 133, 0)) Input port: builder/rot<in -> DescID: ((1768816640, 5, 0), (1, 133, 0)) Input port: builder/rot<datatype -> DescID: ((1684108385, 5, 0), (1954115685, 5, 0), (1, 15, 0)) Maxon API node: builder/rot -> Cinema API surrogate node: <c4d.BaseList2D object called Group with ID 300001078 at 22170201152> Input port: builder/rot<in -> DescID: ((1768816640, 5, 0), (1, 133, 0)) Input port: builder/rot<datatype -> DescID: ((1684108385, 5, 0), (1954115685, 5, 0), (1, 15, 0))Code
"""Demonstrates how to associate nodes in a Maxon API graph with their corresponding Cinema 4D API surrogate elements. Cinema 4D is split into two major APIs: - *Cinema API*: The 'classic' API that represents and describes most tangible entities in Cinema 4D, such as materials, objects, tags, and so on. This API is mostly based on the concept of `BaseList2D` scene elements that hold data containers and are organized in hierarchical and generic node relationships (via `GeListNode`, one of the base classes of `BaseList2D`). I.e., this data forms the graph that makes up a Cinema 4D scene, even when we usually think of it as a tree structure (but GeListNode relationships are more than pure tree relationships). - *Maxon API*: The Maxon API is a more modern API that also includes the Nodes API, which offers a a new (but not drop-in replacement) way to represent nodal scene data. It is used for Scene and Material Nodes at the moment (and subject of this part of the documentation). But the majority of the UI of Cinema 4D is still based on the Cinema API, and the Attribute Manager for example can only display `BaseList2D` scene elements and not `GraphNode` entities of the Maxon API. So, for user interaction purposes, Maxon API nodes must be associated with Cinema API surrogate scene elements that represent those nodes in the Cinema API world. A `NimusBaseInterface` is the glue between a Cinema API scene element and a Maxon API node graph. It not only provides access to the actual Nodes API graph associated with that element, but also manages the association between Nodes API nodes/ports and their Cinema API surrogate elements. This example focuses on the Scene Nodes system, but the same principles apply to other Maxon API node graphs. Compatibility Note: Remove all code in #main up to `print("\n\n--- Maxon API Scene Nodes Data ---\n") and the #mxutils import statement to make this example run in older versions of Cinema 4D (should work at least in 2025.x and with minor modifications even in 2024.x). """ __author__ = "Ferdinand Hoppe" __copyright__ = "Copyright (C) 2026 MAXON Computer GmbH" __date__ = "05/01/2026" __license__ = "Apache-2.0 License" __version__ = "2026.0.0" import c4d import maxon import mxutils 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. """ # An good way to visualize what we are doing is mxutils.GetSceneGraphString, as it will give # us a visual representation of a Cinema API scene graph. We can find there the nodes we # will retrieve and associate with Maxon API nodes further below. You have to look for a # Scene Nodes scene hook in the output. It will also hold all surrogate nodes for the Maxon # API Scene Nodes graph of the document. print("--- Cinema API Scene Graph ---\n") c4d.ClearPythonConsole() print(mxutils.GetSceneGraphString(doc)) print("\n\n--- Maxon API Scene Nodes Data ---\n") # Now we attempt to get the Cinema API scene element to which the Scene Nodes system of a # document is tied (and which also physically holds all Cinema API surrogate nodes for the # Maxon API Scene Nodes graph of the document). For scene nodes, this is a scene hook, for # material graphs it would be a BaseMaterial. # # Scene hooks are a Cinema API node type for which always exactly one instance exists per # document. It is only a coincidence that they also use the term "scene" in their name, there # is no semantic relation between scene hooks and Scene Nodes. For material graphs, we would # for example call `FindNimbusRef` on the `BaseMaterial` instance instead of retrieving # a scene hook. hook: c4d.BaseList2D = doc.FindSceneHook(c4d.SCENENODES_IDS_SCENEHOOK_ID) if not hook: raise RuntimeError("Could not retrieve Scene Nodes scene hook.") # A `BaseList2D` offers various methods to retrieve `NimusBaseInterface` references for itself. # And a NimusBaseInterface is the glue between a Cinema API scene element and a Maxon API node # graph. Here is the connection being made between a Cinema API scene element in form of a # scene hook and the the Scene Nodes Maxon API graph that is associated with that scene hook. # Scene nodes come with the special condition that the their graph might not yet exist for # performance reasons, so we must always send #MSG_CREATE_IF_REQUIRED before attempting to # access a scene nodes graph. For a material node graph, this would not be necessary. hook.Message(maxon.neutron.MSG_CREATE_IF_REQUIRED) handler: maxon.NimbusBaseRef | None = hook.GetNimbusRef(maxon.NodeSpaceIdentifiers.SceneNodes) if not handler: raise RuntimeError("Could not retrieve Scene Nodes handler.") # Now we get the nodes graph that is associated with this nimbus handler and iterate over all # true nodes in it. The Nodes API follows the a bit odd notion that it represents graphs as # trees of entities, where each entity is a GraphNode. Some of those entities are 'true' nodes, # i.e., nodes that also an end user would see in the Node Editor, while other entities represent # things like input and output ports (but are also GraphNodes). So, in short, a GraphNode does # not necessarily represent a 'true' node. graph: maxon.NodesGraphModelRef = handler.GetGraph() root: maxon.GraphNode = graph.GetViewRoot() # For each entity in the graph... for entity in root.GetInnerNodes(maxon.NODE_KIND.ALL_MASK, False, None): # .. step over all non 'true node' entities ... if entity.GetKind() != maxon.NODE_KIND.NODE: continue # .. and find (or create) the BaseList2D Cinema API surrogate entity that represents the # current #entity in this Maxon API graph. This is the surrogate that is shown in an # Attribute Manager when the user selects the node in the Node Editor. Reading and writing # its parameters will be reflected in the Maxon API node and vice versa. surrogate: c4d.BaseList2D = handler.FindOrCreateCorrespondingBaseList(entity.GetPath()) print(f"Maxon API node: {entity.GetPath()} -> Cinema API surrogate node: {surrogate}") # Now we are going to iterate over all input ports of #entity and translate them into # parameter IDs for our #surrogate. for port in entity.GetInnerNodes(maxon.NODE_KIND.ALL_MASK, False, None): if port.GetKind() != maxon.NODE_KIND.INPORT: continue # The reasons why we use here a try/except block is because nodes tend to hold input # ports which only fulfill internal purposes and do not have a corresponding parameter # in the Cinema API surrogate node (ports without an UI). Getting the DescID for such # ports will fail with a ValueError because ports without an UI are not translated (and # we are also probably not interested in them here). try: did: c4d.DescID = handler.GetDescID(port.GetPath()) # This fails print(f"\tInput port: {port.GetPath()} -> DescID: {did}") except: pass if __name__ == '__main__': main()