How to create a Track on a Vector Userdata?
-
I have a Python Tag that loads on button press a json with some animation data. Position / Rotation working fine but i still haven't figured out how to create a track on a userdata with the type vector. i think i'm missing the desc ids or something like that
def CreateOrUpdateKey(curve, time, value, interpolation): keyDict = curve.FindKey(time) if keyDict: key = keyDict["key"] key.SetValue(curve, value) key.SetInterpolation(curve, interpolation) else: keyDict = curve.AddKey(time) if not keyDict: raise MemoryError("Failed to create key") key = keyDict["key"] index = keyDict["nidx"] key.SetValue(curve, value) curve.SetKeyDefault(doc, index) key.SetInterpolation(curve, interpolation) def LoadJsonToTracks(obj, path): if not os.path.isfile(path): raise FileNotFoundError(f"JSON file not found: {path}") with open(path, "r") as f: rawData = json.load(f) fps = doc.GetFps() interpolation = c4d.CINTERPOLATION_LINEAR # --- POSITION TRACKS --- pos_curves = [] for axis in [c4d.VECTOR_X, c4d.VECTOR_Y, c4d.VECTOR_Z]: descID = c4d.DescID( c4d.DescLevel(c4d.ID_BASEOBJECT_REL_POSITION, c4d.DTYPE_VECTOR, 0), c4d.DescLevel(axis, c4d.DTYPE_REAL, 0) ) track = obj.FindCTrack(descID) if not track: track = c4d.CTrack(obj, descID) obj.InsertTrackSorted(track) curve = track.GetCurve() curve.FlushKeys() pos_curves.append(curve) # --- ROTATION TRACKS --- rot_curves = [] for axis in [c4d.VECTOR_X, c4d.VECTOR_Y, c4d.VECTOR_Z]: descID = c4d.DescID( c4d.DescLevel(c4d.ID_BASEOBJECT_REL_ROTATION, c4d.DTYPE_VECTOR, 0), c4d.DescLevel(axis, c4d.DTYPE_REAL, 0) ) track = obj.FindCTrack(descID) if not track: track = c4d.CTrack(obj, descID) obj.InsertTrackSorted(track) curve = track.GetCurve() curve.FlushKeys() rot_curves.append(curve) # --- Add keyframes from JSON --- for entry in rawData: frame = entry.get("frame") pos = entry.get("position", [0, 0, 0]) rot = entry.get("rotation", [0, 0, 0]) if frame is None or len(pos) != 3 or len(rot) != 3: continue time = c4d.BaseTime(frame, fps) for i in range(3): CreateOrUpdateKey(pos_curves[i], time, pos[i], interpolation) CreateOrUpdateKey(rot_curves[i], time, rot[i], interpolation)
-
Hey @pyr,
Thank you for reaching out to us. Do you refer with 'userdata' to your JSON input or do you mean 'a vector parameter in the user data of an object.'? Your code generally looks fine, as you took the main hurdle of understanding that there is no such thing as an animated vector; for animations, all data is decomposed into float/int/bool or custom tracks.
When you just want to address a vector inside the user data, the answer is simply that you have to add that desc level for the user data, forming an ID such as
(user data container, user data element, ...)
. Because the user data is itself a just a parameter of typeDTYPE_SUBCONTAINER
.Cheers,
Ferdinand"""Showcases how to use a three level DescID to address the x component of a vector in the user data of a scene element. """ import c4d doc: c4d.documents.BaseDocument # The currently active document. op: c4d.BaseObject | None # The primary selected object in `doc`. Can be `None`. def main() -> None: """Called by Cinema 4D when the script is being executed. """ if not op: c4d.gui.MessageDialog("No object selected.") return uid: int = 1 # The ID of the thing in the user data we want to access. did: c4d.DescID = c4d.DescID( c4d.DescLevel(c4d.ID_USERDATA, c4d.DTYPE_SUBCONTAINER, 0), # 1st level, the user data container. c4d.DescLevel(uid, c4d.DTYPE_VECTOR, 0), # 2nd level, the user data ID, here a vector. c4d.DescLevel(c4d.VECTOR_X, c4d.DTYPE_REAL, 0)) # 3rd level, the x component of the vector. if op.FindCTrack(did): return track: c4d.CTrack = c4d.CTrack(op, did) op.InsertTrackSorted(track) c4d.EventAdd() print(f"Added track for {did} to {op.GetName()}.") if __name__ == '__main__': main()
-
Works! Thank you!