Hi, @q1w2ertyu first of all welcome in the plugincafe community.
As a reminder, I would point you to How to Post Questions and Q&A Functionality, I've set up your topic correctly, don't worry since it's the first topic no issue at all but try to do it for the next ones.
So while your approach to animate the whole document is valid, it's a bit too much for you need and will probably take some time to compute on heavy scenes.
In Cinema 4D Keyframe are represented as Ckey which is hosted on Ccurve which is hosted on a CTrack.
All three elements inherit from BaseList2D so that means they also inherit from C4DAtom so that means to have a copy of one of these objects you can directly call GetClone.
So if you want to copy only the position based on the keyframe of an object you can simply do the next things.
"""
Copyright: MAXON Computer GmbH
Author: Manuel Magalhaes
Description:
- Copies the position, rotation and animation Tracks (so all Keyframes) from obj1 to obj2.
Notes:
- If obj2 already have some animation data for its position, rotation, and animation these data will be lost.
Class/method highlighted:
- BaseObject.GetCTracks()
- CTracks.GetDescriptionID()
- CTracks.FindCTrack()
- C4DAtom.GetClone()
- CTracks.InsertTrackSorted()
- BaseDocument.AnimateObject()
Compatible:
- Win / Mac
- R14, R15, R16, R17, R18, R19, R20
"""
import c4d
def main():
# Retrieves the object called obj1 from the active document.
animatedBox = doc.SearchObject("obj1")
if animatedBox is None:
raise RuntimeError("Failed to retrieves obj1 in document.")
# Retrieves the object called obj2 from the active document.
fixedBox = doc.SearchObject("obj2")
if fixedBox is None:
raise RuntimeError("Failed to retrieves obj2 in document.")
# Retrieves all the CTrack of obj1. CTracks contains all keyframes information of a parameter.
tracks = animatedBox.GetCTracks()
if not tracks:
raise ValueError("Failed to retrieved animated tracks information for obj1.")
# Defines a list that will contains the ID of parameters we want to copies.
# Such ID can be found by drag-and-drop a parameter into the python console.
trackListToCopy = [c4d.ID_BASEOBJECT_POSITION, c4d.ID_BASEOBJECT_ROTATION, c4d.ID_BASEOBJECT_SCALE]
# Start the Undo process.
doc.StartUndo()
# Iterates overs the CTracks of obj1.
for track in tracks:
# Retrieves the full parameter ID (DescID) describing a parameter.
did = track.GetDescriptionID()
# If the Parameter ID of the current CTracks is not on the trackListToCopy we go to the next one.
if not did[0].id in trackListToCopy:
continue
# Find if our static object already got an animation track for this parameter ID.
foundTrack = fixedBox.FindCTrack(did)
if foundTrack:
# Removes the track if found.
doc.AddUndo(c4d.UNDOTYPE_DELETE, foundTrack)
foundTrack.Remove()
# Copies the initial CTrack in memory. All CCurve and CKey are kept in this CTrack.
clone = track.GetClone()
# Inserts the copied CTrack to the static object.
fixedBox.InsertTrackSorted(clone)
doc.AddUndo(c4d.UNDOTYPE_NEW, clone)
# Ends the Undo Process.
doc.EndUndo()
# Updates fixedBox Geometry taking in account previously created keyframes
animateflag = c4d.ANIMATEFLAGS_NONE if c4d.GetC4DVersion() > 20000 else c4d.ANIMATEFLAGS_0
doc.AnimateObject(fixedBox, doc.GetTime(), animateflag)
# Updates Cinema 4D with All Changes we made
c4d.EventAdd()
if __name__ == "__main__":
main()
Finally just in case, in your initial script you need a call to BaseDocument.ExecutePasses to generates the new state of the documentation, this will update the object geometry and move the object taking in consideration, keyframe, dynamics, expression and so on (so very overkill for your need).
Cheers,
Maxime.