Hello @bentraje,
Thank you for reaching out to us. To start with what I would consider most important: Avoiding exception handling for performance reasons is IMHO just C++/programmer folklore and does not make too much sense in Python. If you want to do it, C4DAtom.Get/SetParameter
would be the way to go.
But accessing ID_MATERIALASSIGNMENTS
should not fail, the parameter should be always populated. Find below an example script which demonstrates the approach on ID_USERDATA, 1
, the first user data parameter in a node, which indeed can be absent.
Cheers,
Ferdinand
Result for running on the default cube:
Yikes, access error, we scratched the paint on <c4d.BaseObject object called Cube/Cube with ID 5159 at 2574288990272> (parameter access failed).
C4DAtom.GetParameter = None
Code:
"""Demonstrates how to let parameter access fail gracefully using C4DAtom.GetParameter in contrast
to GeListNode.__getitem__ access.
"""
import c4d
doc: c4d.documents.BaseDocument # The active document
op: c4d.BaseObject | None # The active object, None if unselected.
def main() -> None:
"""Runs the example.
"""
if not op:
return
# Use __getitem__ and error handling. Apart from a subjective aesthetical standpoint, there is
# nothing objectively wrong with using exceptions IMHO. Exception handling is cheap, exception
# raising is not, but that does not really matter, as Python is slow as a snail anyways. And
# I think all that "exceptions are slow"-talk is just folklore that has carried over from C++.
#
# See:
# https://docs.python.org/3.10/faq/design.html#how-fast-are-exceptions
try:
data: any = op[c4d.ID_USERDATA, 1]
print(f"__getitem__ = {data}")
except Exception as e:
print(f"Yikes, access error, we scratched the paint on {op} ({e}).")
# Use C4DAtom.GetParameter instead, it will fail gracefully by returning None when a parameter
# does not exist.
data: c4d.MatAssignData | None = op.GetParameter(
c4d.DescID(c4d.DescLevel(c4d.ID_USERDATA),
c4d.DescLevel(1)),
c4d.DESCFLAGS_GET_NONE)
print (f"C4DAtom.GetParameter = {data}")
if __name__ == '__main__':
main()