Why won't my python generator update? R2024
-
I'm using user data to change rotations in a python generator. But it doesn't seem to want to update when I play the timeline? Should I add anything special to the script?
from typing import Optional import c4d from c4d import utils doc: c4d.documents.BaseDocument # The document evaluating this python generator op: c4d.BaseObject # The python generator hh: Optional["PyCapsule"] # A HierarchyHelp object, only defined when main is executed distance = op[c4d.ID_USERDATA,1] offset = op[c4d.ID_USERDATA,2] rotation = op[c4d.ID_USERDATA,3] def main() -> c4d.BaseObject: # create hierarchy of nulls points = 100 points_list = [] for p in range(points): pt = c4d.BaseObject(c4d.Onull) pt.SetParameter(c4d.NULLOBJECT_DISPLAY,c4d.NULLOBJECT_DISPLAY_SPHERE,c4d.DESCFLAGS_SET_NONE) if p==0: points_list.append(pt) else: pt.InsertUnder(points_list[p-1]) points_list.append(pt) # adjust position and rotation for i,pt in enumerate(points_list[::-1]): off = c4d.Vector(distance * i,0,0 ) mg = pt.GetMg() mg.off = off print(rotation.x) rm = c4d.utils.HPBToMatrix(rotation) pt.SetMg(mg * rm) return points_list[0]
-
Hi @SweepingMotion,
There's no time dependency in the code.
Most probably you're trying to animate with parameters, so you need to put user data getters under the
main()
function.distance = op[c4d.ID_USERDATA,1] offset = op[c4d.ID_USERDATA,2] rotation = op[c4d.ID_USERDATA,3]
In some specific cases it's also required to uncheck "Optimize Cache" checkbox.
-
Hello @SweepingMotion ,
Welcome to the Plugin Café forum and the Cinema 4D development community, it is great to have you with us!
Getting Started
Before creating your next postings, we would recommend making yourself accustomed with our Forum and Support Guidelines, as they line out details about the Maxon SDK Group support procedures. Of special importance are:
- Support Procedures: Scope of Support: Lines out the things we will do and what we will not do.
- Support Procedures: Confidential Data: Most questions should be accompanied by code but code cannot always be shared publicly. This section explains how to share code confidentially with Maxon.
- Forum Structure and Features: Lines out how the forum works.
- Structure of a Question: Lines out how to ask a good technical question. It is not mandatory to follow this exactly, but you should follow the idea of keeping things short and mentioning your primary question in a clear manner.
About your First Question
There are two layers to your question so to speak. Let us start with the outer more abstract layer.
What you are trying to do here, have the object update every time the time changes, is not an intended functionality of generator objects. And while you can achieve this more or less directly, this will be quite costly. It is fine when you do this for a couple of objects which you do not ship as plugins, but for everything else, you should do this properly. Th best way would be to expose an animatable parameter Time on the object, akin to what the Explosion deformer does for example. Updates of generator caches should always be tied to data changes on scene elements, either the cache holding element itself, or one of its inputs (things being "dirty" as Cinema calls it).
The second layer to this is object dirtiness and evaluating when to build the cache. You have probably ticked Optimize Cache in your generator, which will cause it only to update when its data container is dirty. In the video below I demonstrate the effect. We also have talked about the subject of evaluating dirtiness multiple times, a good starting point could be this answer of mine.
-
@ferdinand I think issue is only with user data variables, because those are not being updated during playback, once they are out of main() function
Just a guess, because there's no sample project.
It probably should be like so:from typing import Optional import c4d from c4d import utils doc: c4d.documents.BaseDocument # The document evaluating this python generator op: c4d.BaseObject # The python generator hh: Optional["PyCapsule"] # A HierarchyHelp object, only defined when main is executed def main() -> c4d.BaseObject: distance = op[c4d.ID_USERDATA,1] offset = op[c4d.ID_USERDATA,2] rotation = op[c4d.ID_USERDATA,3] # create hierarchy of nulls points = 100 points_list = [] for p in range(points): pt = c4d.BaseObject(c4d.Onull) pt.SetParameter(c4d.NULLOBJECT_DISPLAY,c4d.NULLOBJECT_DISPLAY_SPHERE,c4d.DESCFLAGS_SET_NONE) if p==0: points_list.append(pt) else: pt.InsertUnder(points_list[p-1]) points_list.append(pt) # adjust position and rotation for i,pt in enumerate(points_list[::-1]): off = c4d.Vector(distance * i,0,0 ) mg = pt.GetMg() mg.off = off print(rotation.x) rm = c4d.utils.HPBToMatrix(rotation) pt.SetMg(mg * rm) return points_list[0]
-
-
@baca @ferdinand Thank you both.
It was the fact that the user data was not collected in the main function. Silly I didn't catch that.
It's working fine now.