Editable Object Plugin returns Null after scaling
-
I'm creating a basic ObjectData plugin that returns a cube with a modified scale. However, when making the object editable (C key), sometimes the result becomes a Null object with the cube inside, especially after changing the scale.
import c4d from c4d import plugins, utils class MyObjectPlugin(plugins.ObjectData): def Init(self, op): return True def GetVirtualObjects(self, op, hierarchyhelp): dirty = op.CheckCache(hierarchyhelp) or op.IsDirty(c4d.DIRTY_DATA) if not dirty: return op.GetCache(hierarchyhelp) cube = c4d.BaseObject(c4d.Ocube) if cube is None: return None cube[c4d.ID_BASEOBJECT_REL_SCALE, c4d.VECTOR_X] = 2.0 cube[c4d.ID_BASEOBJECT_REL_SCALE, c4d.VECTOR_Y] = 1.0 cube[c4d.ID_BASEOBJECT_REL_SCALE, c4d.VECTOR_Z] = 0.5 return cube
Am I doing something wrong? My intention is specifically that when making the generator editable, the result is the scaled object, but without the null object that is generated when modifying it, and without modifying the generator scale.
Thanks in advance for any help!
PS: I would also like to know if there is a specific way to return several objects or a specific one when making the generator editable, making it more customizable.
-
Hello @JH23,
Thank you for reaching out to us. Your code is looks correct, but you should not return
None
on a critical error (e.g., when you run out of memory to allocate things), but returnc4d.BaseObject(c4d.Onull)
instead, that is also what Cinema 4D will do, when it cannot make sense out of your method. E.g. it should be:if not(cube := c4d.BaseObject(c4d.Ocube)): return c4d.BaseObject(c4d.Onull) cube[c4d.ID_BASEOBJECT_REL_SCALE, c4d.VECTOR_X] = 2.0 ...
Also, does your object have child inputs it depends on? E.g., like an Extrude object which depends on a child spline? I assume it does not, right? You should then change your manual dirty check to this, because your code also tries to build the children of this node which could lead to issues.
# Only build the cache of the object when one of its parameters has changed or when there is no cache. if not op.IsDirty(c4d.DIRTY_DATA) and op.GetCache(): return op.GetCache() # you could also pass the hh here, but that is not necessary in this case
Do you see any errors in the console when this happens? Cinema 4D returning a null object for a cache means that building the cache failed. There must be somewhere a bug in your code, I am not sure though that my suggestions will fix it.
I would also like to know if there is a specific way to return several objects or a specific one when making the generator editable, making it more customizable.
A cache must always terminate into a singular object because it is just part of an object hierarchy. When you want your cache to contain multiple things, you must parent them to a null and return that null as your cache.
As to reacting to
CTSO
, yes that is possible, but not in Python. When an object is being built for CSTO, itsHierachyHelp->GetFlags()
will beBUILDFLAGS::EXTERNALRENDERER | BUILDFLAGS::ISOPARM
butHierachyHelp
has not been wrapped for Python. There isMSG_CURRENTSTATE_END
emitted, and you can capture this in Python too viaNodeData::Message
, but that is only the signal that CSTO has finished (and that you might want to revert to a non-CSTO specialized cache).But in general, we advise against such trickery where objects switch out their cache in certain contexts. It is valid to do this, but often requires intimate knowledge of the API to be done sucessfully.
Cheers,
Ferdinand