Hello @thomasb,
I am not sure what you mean by locked, but your posting should not be locked from editing.
Regarding DescID
, while they are not trivial, they are also not as hard to understand as it might look at the first glance. First of all, we have our C++ DescID Manual, containing information which can be transferred to Python in most parts. There was also the thread PYTHON - Userdata CTracks and Basecontainer in the past, where we did discuss DescID
in a bit more detail.
For your specific case, the condensed version would be that DescID
are ids for a description. So, they are used address parameters in an object, tag, material, etc. These IDs can be stated in many ways, with varying degrees of verboseness. This especially true for Python which simplifies this even further. See example at the end for details.
Cheers,
Ferdinand
"""Examples for DescID instances.
To be run in the script manger with an object selected.
As discussed in:
https://plugincafe.maxon.net/topic/13517
"""
import c4d
def main():
"""
"""
# If the is no active object, then bail.
if not isinstance(op, c4d.BaseObject):
raise RuntimeError("Please select an object.")
# --- Access a description element ---
# The most simple form of addressing the position of an object. The symbol
# is just a (whole) number.
print (c4d.ID_BASEOBJECT_REL_POSITION) # Will print 903
# We can read a parameter of a node in Python with the bracket syntax. By either
# passing in the number or the symbol.
print (op[903])
print (op[c4d.ID_BASEOBJECT_REL_POSITION])
# We could also use other access interfaces like C4DAtom.Get/SetParameter
# or BaseContainer access, but I am going to ignore them here.
# However, we can also wrap this number in a DescID in the following way.
descId = c4d.DescID(c4d.ID_BASEOBJECT_REL_POSITION)
# And pass that in instead. It will do exactly the same as the previous
# call op[c4d.ID_BASEOBJECT_REL_POSITION]
print (op[descId])
# DescIDs are formally constructed from DescLevels, what we did above
# was just a shorthand for this. A DescLevel just wraps around a number.
# So, we can state c4d.DescID(c4d.ID_BASEOBJECT_REL_POSITION) also like
# this.
descLevel = c4d.DescLevel(c4d.ID_BASEOBJECT_REL_POSITION)
descId = c4d.DescID(descLevel)
print (op[descId])
# However, DescLevels can convey more information than just the ID,
# they can also store the data type and the creator of that id. The
# position is a vector, so we can state that. The 0 at the end sort
# of means no creator or "whatever" ^^
descLevel = c4d.DescLevel(c4d.ID_BASEOBJECT_REL_POSITION,
c4d.DTYPE_VECTOR, 0)
descId = c4d.DescID(descLevel)
print (op[descId])
# So, to recap, these five ids are more or less all equivalent, they at
# least will return all the same parameter value.
#
# 903
# c4d.ID_BASEOBJECT_REL_POSITION
# c4d.DescID(c4d.ID_BASEOBJECT_REL_POSITION)
# c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_POSITION))
# c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_REL_POSITION,
# c4d.DTYPE_VECTOR, 0))
# --- Access the component of a description element ---
# Until now, we have only accessed the vector as a whole. But there are
# some data types which are composed out of sub-components, e.g.,
# BaseContainer or Vector. Which is why a DescID can be composed out of
# three IDs, where each level (DescLevel) further specifies which part
# of the parameter we want to access.
print (c4d.VECTOR_X) # Will print 1000
# To access the X component of the position vector, we can do this.
print (op[903, 1000])
print (op[c4d.ID_BASEOBJECT_REL_POSITION, c4d.VECTOR_X])
# Just as before, this can be done more verbosely with DescID to varying
# degrees.
# a.
dLvlVector = c4d.DescLevel(c4d.ID_BASEOBJECT_REL_POSITION)
dLvlVectorX = c4d.DescLevel(c4d.VECTOR_X)
descId = c4d.DescID(dLvlVector, dLvlVectorX)
print (op[descId])
# b.
dLvlVector = c4d.DescLevel(c4d.ID_BASEOBJECT_REL_POSITION,
c4d.DTYPE_VECTOR, 0)
dLvlVectorX = c4d.DescLevel(c4d.VECTOR_X,
c4d.DTYPE_REAL, 0)
descId = c4d.DescID(dLvlVector, dLvlVectorX)
print (op[descId])
# So, this part in the other code I did post:
#
# descId = c4d.DescID(c4d.DescLevel(c4d.ID_USERDATA, 5, 0),
# c4d.DescLevel(1, 1, 0))
#
# was written a bit lazily, a more verbose form would be:
#
# descId = c4d.DescID(
# c4d.DescLevel(c4d.ID_USERDATA, c4d.DTYPE_SUBCONTAINER, 0),
# c4d.DescLevel(1, c4d.DTYPE_GROUP, 0))
#
# It is just a complicated way of saying (700, 1) or in symbolic form
# (c4d.ID_USERDATA, 1). It just means the first element in the user data
# container. However, in some places, e.g., descriptions or xpresso nodes,
# this very verbose form is required by Cinema, as all other are just a
# shorthand form for user convenience.
if __name__ == '__main__':
main()