Solved Other methods for material[c4d.ID_MATERIALASSIGNMENTS]?


To get the material assignments, you usually do:

It works but it gives an error (i.e. breaks the code flow) if the material assignments are empty.
What I would expect is not an error but None.

I can do it through:

   # Do something. 

It works but I want to avoid the try/except block and would just a None return instead.

So are there any other methods aside from material[c4d.ID_MATERIALASSIGNMENTS]?

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.


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


"""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:

    # 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:
        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(
    print (f"C4DAtom.GetParameter = {data}")

if __name__ == '__main__':

MAXON SDK Specialist


Thanks for the response. I can't get it though.

You are assigning it to an object, BaseObject.
I'm after the BaseMaterial. So the [c4d.ID_USERDATA, 1] is not really something I can use.
The Assign Tab is not a userdata. It's a built-in data.

Anyhow how do I convert the [c4d.ID_MATERIALASSIGNMENTS] to a c4d.DescID? Because I think that's the thing I need for the GetParameter.


Hey @bentraje,

First of all, also a BaseMaterial can have user data, any BaseList2D can:


And secondly, I intentionally chose [ID_USERDATA, 1], because other than for ID_MATERIALASSIGNMENTS the parameter for the first user data element can actually be not present on a node. A BaseMaterial on the other hand should always carry ID_MATERIALASSIGNMENTS:


Anyhow how do I convert the [c4d.ID_MATERIALASSIGNMENTS] to a c4d.DescID?


I understand that you are here on a mission, but what you want to do should not be required for two reasons. Because for once ID_MATERIALASSIGNMENTS should not fail and on the other hand, there is nothing wrong with try: ... except: ... finally: ....


MAXON SDK Specialist


RE: there is nothing wrong with try: ... except:
Yep there is nothing. I just want to avoid it.

This works. Didn't realize it is this straightforward.

Are there any pointers for reconstructing DescID?
I see some having a tuple within the tuple. Like what you referred above:
c4d.DescID(c4d.DescLevel(c4d.ID_USERDATA), c4d.DescLevel(1)),

In animation for position parameter, it could be:
c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_POSITION, c4d.DA_VECTOR),c4d.DescLevel(c4d.VECTOR_Z, c4d.DA_REAL, c4d.DA_VECTOR))

In this case, it is a tuple within a tuple within a tuple.
That's why I don't usually use GetParameter because I don't actually get the actual parameter descID to use. lol

Hello @bentraje,

you could have a look at this posting of mine, there I did explain DescId a bit. The C++ Manual can also be helpful.


MAXON SDK Specialist


Gotcha. Thanks. Will close this thread now.