Other methods for material[c4d.ID_MATERIALASSIGNMENTS]?
-
Hi,
To get the material assignments, you usually do:
material[c4d.ID_MATERIALASSIGNMENTS]
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 butNone
.I can do it through:
try: material[c4d.ID_MATERIALASSIGNMENTS] except: # 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 onID_USERDATA, 1
, the first user data parameter in a node, which indeed can be absent.Cheers,
FerdinandResult 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()
-
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 ac4d.DescID
? Because I think that's the thing I need for theGetParameter
. -
Hey @bentraje,
First of all, also a
BaseMaterial
can have user data, anyBaseList2D
can:And secondly, I intentionally chose
[ID_USERDATA, 1]
, because other than forID_MATERIALASSIGNMENTS
the parameter for the first user data element can actually be not present on a node. ABaseMaterial
on the other hand should always carryID_MATERIALASSIGNMENTS
:Anyhow how do I convert the [c4d.ID_MATERIALASSIGNMENTS] to a c4d.DescID?
c4d.DescID(c4d.ID_MATERIALASSIGNMENTS)
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 withtry: ... except: ... finally: ...
.Cheers,
Ferdinand -
RE: there is nothing wrong with try: ... except:
Yep there is nothing. I just want to avoid it.RE: c4d.DescID(c4d.ID_MATERIALASSIGNMENTS)
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.Cheers,
Ferdinand -
Gotcha. Thanks. Will close this thread now.