Python Cloner Effectors Keyframe
-
Hi,
I'm trying to add a keyframe of the strength of the inheritance that it is inside of a cloner effectors. (See image)
In order to add keyframes I know that I need to have a CTrack however I'm unable to locate which DescID or more specifically which DescLevel I need to use to achieve my goal.
How can I find the DescLevel I need?
Thank you for your time.
Joel.
-
@joel
The simplest way is to drag the parameter to the python console, then you could get desclevel id without dtype and creator. e.g.c4d.DescID(1500)
.
If you want to get the DescID programmatically. I wrote a function to list all parameters and detail descriptions of an object. This may help you.import c4d def find_ident(value: int, prefix=""): for key, val in c4d.__dict__.items(): if val == value and key.startswith(prefix): return f"c4d.{key}" def dump_params(obj: c4d.BaseList2D): def dump_param_desc(bc): for k, v in bc: ident = find_ident(k, "DESC_") if type(v) == str: v = repr(v) if not ident: continue if k == c4d.DESC_UNIT: v = find_ident(v, "DESC_") if k == c4d.DESC_CUSTOMGUI: v = find_ident(v, "CUSTOMGUI") or v if isinstance(v, c4d.Vector) and abs(v.x) > 1e10: v = "Vector" print('\t', ident, ":", v) description = obj.GetDescription(c4d.DESCFLAGS_DESC_0) descid: c4d.DescID for bc, descid, _ in description: name = bc[c4d.DESC_NAME] or bc[c4d.DESC_SHORT_NAME] if not name: continue if descid[descid.GetDepth() - 1].dtype == c4d.DTYPE_GROUP: print("---------") print(name, descid, ":", repr(obj[descid])) dump_param_desc(bc) if bc[c4d.DESC_CUSTOMGUI] == c4d.CUSTOMGUI_SUBDESCRIPTION: for subvector in [c4d.VECTOR_X, c4d.VECTOR_Y, c4d.VECTOR_Z]: subdescid = c4d.DescID(*[descid[i] for i in range(descid.GetDepth())]) subdescid.PushId(c4d.DescLevel(subvector)) subbc = description.GetParameter(subdescid) name = subbc[c4d.DESC_NAME] or subbc[c4d.DESC_SHORT_NAME] if not name: continue name = name.replace(" . ", ".") print(name, ":", obj[subdescid]) dump_param_desc(subbc) if __name__ == "__main__": obj = doc.GetActiveObject() dump_params(obj)
Following is the outputs to the end:
Effectors (2009, 1009290, 1018639) : <c4d.InExcludeData object at 0x00000198DD88E9C0> c4d.DESC_NAME : 'Effectors' c4d.DESC_SHORT_NAME : 'Effectors' c4d.DESC_VERSION : 3 c4d.DESC_ANIMATE : 0 c4d.DESC_CUSTOMGUI : c4d.CUSTOMGUI_INEXCLUDE_LIST c4d.DESC_ACCEPT : <c4d.BaseContainer object at 0x00000198DD88DE00> c4d.DESC_IDENT : 'ID_MG_MOTIONGENERATOR_EFFECTORLIST' Plain (1500, 19, 1018544) : 0.99 c4d.DESC_NAME : 'Plain' c4d.DESC_SHORT_NAME : 'Plain' c4d.DESC_VERSION : 3 c4d.DESC_MIN : -1e+20 c4d.DESC_MAX : 1e+20 c4d.DESC_MINEX : 0 c4d.DESC_MAXEX : 0 c4d.DESC_STEP : 0.01 c4d.DESC_ANIMATE : 1 c4d.DESC_UNIT : c4d.DESC_UNIT_PERCENT c4d.DESC_CUSTOMGUI : c4d.CUSTOMGUI_REALSLIDER c4d.DESC_MINSLIDER : 0.0 c4d.DESC_MAXSLIDER : 1.0 c4d.DESC_REMOVEABLE : 0 Plain.1 (1501, 19, 1018544) : 1.0 c4d.DESC_NAME : 'Plain.1' c4d.DESC_SHORT_NAME : 'Plain.1' c4d.DESC_VERSION : 3 c4d.DESC_MIN : -1e+20 c4d.DESC_MAX : 1e+20 c4d.DESC_MINEX : 0 c4d.DESC_MAXEX : 0 c4d.DESC_STEP : 0.01 c4d.DESC_ANIMATE : 1 c4d.DESC_UNIT : c4d.DESC_UNIT_PERCENT c4d.DESC_CUSTOMGUI : c4d.CUSTOMGUI_REALSLIDER c4d.DESC_MINSLIDER : 0.0 c4d.DESC_MAXSLIDER : 1.0 c4d.DESC_REMOVEABLE : 0
Then you can get the DescID:
c4d.DescID(c4d.DescLevel(1500, 19, 1018544))
-
I will test it out. Thank you so much.
-
Hello @joel,
Thank you for reaching out to us and thanks again @iplai for the detailed answer.
Here also not much to be added from our side, everything @iplai said was correct. What should be added though IMHO is that what you are dealing here with, is a
Description
which is modified at runtime. E.g., when you have the Cube Object, its description is fully static, all its parameters are statically defined in its resource (ocube.res and the matchingocube.h
file). You can therefore predict all its IDs and we can provide symbols for them, e.g.,PRIM_CUBE_LEN
for the size of the cube.The Cloner Object description is however not fully static. The sliders below the Effectors list depend on the (number of) objects the user has dragged into the list. It is not possible to know ahead of time which symbols are there.
You can then solve this in two ways:
- Figure out the stride/offset of things: In this case it is easy, the sliders are placed from the ID
1500
on with a stride of1
, e.g.,[1500, 1501, 1502, ...]
. You can then simply test out withC4DAtom.GetParamaeter
up to which point the sliders exist by trying to retrieve their value. - Inspect the description of the node as @iplai did. This is a more sophisticated approach, but be warned, in some rare cases where our developers went haywire with modifying the description at runtime,
C4DAtom.GetDescription()
might not always return the true state of the dynamically modified description. Which then results in parameters which are shown in the interface not to be contained in the description copy returned byC4DAtom.GetDescription()
.
Cheers,
Ferdinand - Figure out the stride/offset of things: In this case it is easy, the sliders are placed from the ID
-
@ferdinand
Hi again,
I am bumping into an issue that I do not know up to which point is a bug.
All that was described before works without issues. The problems arise when the inheritance gets deleted by the user via the GUI. In the GUI the Effectors list is empty but in python code, it says that the ObjectCount of the Effectors list is not empty.
How can this be?
PD: This is my second post on this forum. For this type of issues is it better to open another Topic?
-
I was able to solve it by searching the DescID in the Cloner Description with the Inheritance Name.