How to be sure if an object is a generator/modifier?
-
Hello guys,
as the title says I'm looking for a reliable way to check if an object in the object manager is actually a generator or modifier.
I know I can use e.g.
c4d.BaseList2D.GetInfo() & c4d.OBJECT_GENERATOR
. While that works with e.g.c4d.BaseObject(c4d.Osds)
it doesn't work withc4d.BaseObject(c4d.Olight)
. A light object doesn't seem to be a generator, is it?Basically I want a bullet proof way to know if an object is a generator or a modifier and therefore has
c4d.ID_BASEOBJECT_GENERATOR_FLAG
.Can this be done?
Cheers,
Sebastian -
Hello @HerrMay,
Thank you for reaching out to us. Well, what
c4d.BaseList2D.GetInfo()
is returning are the plugin flags the plugin has been registered with, e.g., c4d.OBJECT_GENERATOR. What one then considers "bullet proof" is a bit of a question of taste.c4d.BaseList2D.GetInfo
returns the plugin flags mask without any filtering, i.e., it is in this sense bullet proof, and in the sense that it will correctly identify plugins that exhibit the behavior that comes with for example withOBJECT_GENERATOR
. What you or the common user associate with these terms might be rightfully something different, and in the end these things are just that: flags. So nothing prevents a developer from registering something as aOBJECT_GENERATOR
and then writing something that behaves very differently. But things likeOlight
andOcamera
rightfully do not classify as generators because they have no cache, the core characteristic of a generator, as also indicated by the documentation:OBJECT_GENERATOR
: Generator object. Produces a polygonal or spline representation on its own. (E.g. primitive cube.)Noteworthy is in this context that
SplineObject
instances are generators because they generate theirLineObject
cache. the Modelling - Geometry Model Python code examples expand a bit more on that concept.As an alternative, you could test for objects being a
PointObject
instance, as all things which are not generators in your world view should be a point object (again, it is a bit ambiguous what you would consider a generator and what not). You can also check if something is aBaseObject
but not aPointObject
and has no cache to decide if it is something likeOlight
. What is a modifier or not in this interpretative/analytical sense is probably impossible, as there is already room for interpretation for the native objects of Cinema 4D, deformers and MoGraph effectors are modifiers, field objects are not. This likely extends to many plugin objects which might have modifier qualities but do not necessarily flag themselves as such withOBJECT_MODIFIER
.Regarding
ID_BASEOBJECT_GENERATOR_FLAG
, all objects have this parameter, even the ones which do not display it. So, callingC4DAtom.GetParameter
with the flagDESCFLAGS_GET_NO_GEDATADEFAULTVALUE
will not yieldNone
for objects which seem to not have this parameter. But you can inspect the description of an object to find out, see the code example at the end.Cheers,
FerdinandResult:
Cube.1(Polygon) cannot be enabled or disabled. Group(Group) enabled-state is: 0. Linear Field(Linear Field) enabled-state is: 1. Camera(Camera) cannot be enabled or disabled. Light(Light) enabled-state is: 1.
Code:
"""Demonstrates how to check if a BaseObject has the green enabled check-mark or not. Will print out the state for the selected object when run. """ import c4d import typing doc: c4d.documents.BaseDocument # The active document op: typing.Optional[c4d.BaseObject] # The active object, None if unselected def main() -> None: """Runs the example. """ if not op: return # Something like this will not work, because all BaseObject types carry this parameter, it is # just that some of them are hiding it. So, we will never retrieve None here. state: typing.Optional[bool] = op.GetParameter( c4d.ID_BASEOBJECT_GENERATOR_FLAG, c4d.DESCFLAGS_GET_NO_GEDATADEFAULTVALUE) # But we can look up if this parameter is hidden in the description of the object. description: c4d.Description = op.GetDescription(c4d.DESCFLAGS_DESC_NONE) param: typing.Optional[c4d.BaseContainer] = description.GetParameter( c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_GENERATOR_FLAG, c4d.DTYPE_BOOL, 0))) if not param: raise RuntimeError("Could not retrieve parameter container.") isHidden: bool = param[c4d.DESC_HIDE] if isHidden: print (f"{op.GetName()}({op.GetTypeName()}) cannot be enabled or disabled.") else: # We could also reuse #state here, but the fancier GetParameter() access is not required. print (f"{op.GetName()}({op.GetTypeName()}) enabled-state is: " f"{op[c4d.ID_BASEOBJECT_GENERATOR_FLAG]}.") if __name__ == '__main__': main()
-
Hello @ferdinand,
alright I see. I already thought that you would teach me once again that the naive thought I put up here would'nt hold up to the real world.
Thanks for the explanation and the example you provided. I guess that will do just fine. As always much appreciated!
Cheers,
Sebastian -