mxutils_debugprint¶
Demonstrates mxutils helpers for diagnosing Cinema 4D scene data.
mxutils_debugprint.py¶
"""Demonstrates mxutils helpers for diagnosing Cinema 4D scene data.
Run this example in the Cinema 4D Script Manager. It prints a container, parameter,
and scene graph tree for the active document and its selected object.
Topics:
* mxutils.DebugPrint.GetBaseList
* mxutils.DebugPrint.GetContainer
* mxutils.DebugPrint.GetFlags
* mxutils.DebugPrint.GetGraph
* mxutils.DebugPrint.GetParameters
* mxutils.DebugPrint.DiffParameters
* mxutils.DebugPrint.DiffFlags
* mxutils.DebugPrint.DiffBaseList
* mxutils.DebugPrint.DiffGraph
* mxutils.DebugPrint.PrintContainer
"""
__author__ = "Ferdinand Hoppe"
__copyright__ = "Copyright (C) 2026 MAXON Computer GmbH"
__license__ = "Apache-2.0 License"
__version__ = "2027.0"
import c4d
import mxutils
doc: c4d.documents.BaseDocument # The active Cinema 4D document.
def main() -> None:
"""Runs the example for the active document.
"""
# Create an example scene, get the first and second object, and their data containers.
mxutils.g_scene_faker.RandomizeScene(doc, randomizeParameters=False)
c4d.EventAdd()
first: c4d.BaseObject = mxutils.CheckType(doc.GetFirstObject())
second: c4d.BaseObject = mxutils.CheckType(first.GetDown() or first.GetNext())
bc1: c4d.BaseContainer = first.GetDataInstance()
bc2: c4d.BaseContainer = second.GetDataInstance()
print("\n--- DebugPrint.GetContainer -------------------------------------------------------\n")
# The class DebugPrint provides various static methods to inspect and debug different aspects of
# Cinema 4D scene data. At its core, the class returns a DebugNode object that represents the
# debug information in a structured tree format.
# Get the debug nodes for the first and second objects and their data containers.
debug1: mxutils.DebugNode = mxutils.DebugPrint.GetContainer(bc1)
debug2: mxutils.DebugNode = mxutils.DebugPrint.GetContainer(bc2)
# We can print the nodes like this, which will give us a tree view of the container.
print(f"GetContainer(bc1) = \n{debug1.ToString()}")
print(f"GetContainer(bc2) = \n{debug2.ToString()}")
# A shorter path can be to directly use the PrintContainer function when we do not need the nodes.
mxutils.DebugPrint.PrintContainer(bc1)
mxutils.DebugPrint.PrintContainer(bc2)
# Debugging containers can also be complemented with a symbol hint which can be useful for better
# readability when we can predict the symbolic names of the IDs. Here we poll for the current
# mouse input state and the print the result, predicting that most will have a symbolic name
# starting with 'BFM_'. When there is no symbolic name, or the match is ambiguous, the raw ID
# will be shown.
state: c4d.BaseContainer = c4d.BaseContainer()
c4d.gui.GetInputState(c4d.BFM_INPUT_MOUSE, 0, state)
debug: mxutils.DebugNode = mxutils.DebugPrint.GetContainer(state, '^BFM_')
print(f"\nMouse Input State:\n\n{debug.ToString()}")
print("\n--- DebugPrint.GetParameters ------------------------------------------------------\n")
# But when inspecting BaseList2D data containers, it is often more useful to use GetParameters,
# as it uses the description of the node and therefore always shows the correct symbolic names
# for the parameters and can also do more things. GetParameters has multiple arguments to display
# ids, data types, do filtering, and more, see the docs for details.
debug: mxutils.DebugNode = mxutils.DebugPrint.GetParameters(first)
print(f"GetParameters(first) = \n{debug.ToString()}")
print(f"\n--- DebugPrint.GetFlags -----------------------------------------------------------\n")
# With GetFlags, you can inspect the flags of a node in a tree structure, similar to how
# GetParameters works for parameters. This is useful for debugging the state of various
# flags on a node. There are multiple parameters with which you can control the output, similar
# to GetParameters.
debug: mxutils.DebugNode = mxutils.DebugPrint.GetFlags(first)
print(f"GetFlags(first) = \n{debug.ToString()}")
print("\n--- DebugPrint.GetBaseList --------------------------------------------------------\n")
# GetBaseList combines the parameter and flag trees into one debug tree (and also offers the
# combined tuning arguments of the other debug functions).
debug: mxutils.DebugNode = mxutils.DebugPrint.GetBaseList(first)
print(f"GetBaseList(first) = \n{debug.ToString()}")
print(f"\n--- DebugPrint.GetGraph -----------------------------------------------------------\n")
# And then there is GetGraph, which allows you to inspect the scene graph structure of a passed
# node. We can use just as the other node related debug functions on any form of BaseList2D node,
# e.g., a whole document as we do here, or just a single object within the scene. This will
# effectively return the output of mxutils.IterateGraph as a tree, i.e., unpack hierarchical,
# branching, and cache relationships of the passed node.
debug: mxutils.DebugNode = mxutils.DebugPrint.GetGraph(doc)
print(f"GetGraph(doc) = \n{debug.ToString()}")
print(f"\n--- DebugPrint Diffing -----------------------------------------------------------\n")
# All methods shown of the form GetXYZ also have a PrintXYZ counterpart that directly prints
# the debug information, but it is not shown for each case. But there are also diffing functions
# for each category which let you compare the debug output of two inputs. This can be helpful
# when trying to find out 'why does A not behave like B', which is a common debugging scenario.
diff: str = mxutils.DebugPrint.DiffContainer(bc1, bc2)
print(f"DiffContainer(bc1, bc2) = \n{diff}")
diff: str = mxutils.DebugPrint.DiffParameters(first, second)
print(f"DiffParameters(first, second) = \n{diff}")
diff: str = mxutils.DebugPrint.DiffFlags(first, second)
print(f"DiffFlags(first, second) = \n{diff}")
diff: str = mxutils.DebugPrint.DiffBaseList(first, second)
print(f"DiffBaseList(first, second) = \n{diff}")
diff: str = mxutils.DebugPrint.DiffGraph(first, second)
print(f"DiffGraph(first, second) = \n{diff}")
import importlib
if __name__ == "__main__":
c4d.ClearPythonConsole()
importlib.reload(mxutils.mxu_base)
importlib.reload(mxutils.mxu_scene)
importlib.reload(mxutils.mxu_provider)
importlib.reload(mxutils)
main()