Keyframing a property using python.
martijnlambada last edited by m_magalhaes
I’m trying to make a little script that takes all selected cameras and puts them in a (newly created) stage object (one camera per frame).
Super useful if you want to render out stills on a render farm that doesn’t support takes.
I’ve got almost everything working:
- Getting the selected cameras and putting them in an array.
- Creating a stage object
- Looping through the array and putting the cameras into the camera slot of the stage object.
- Moving 1 frame forward
The two things I’m struggling with:
- How to key frame the camera slot properly so it actually creates the animation (different camera per frame). I’m using the mydoc.RecordKey() property but how do I find out which id (?) the camera property has?
- Ideally I want to catch errors when someone selects something other than a camera. Is there an easy way to catch that error? Should I loop through the array and check the individual elements?
Who can point me into the right direction?
Your help is much appreciated.
import c4d, math from c4d import gui # This is a little script that puts the selected cameras into a stage object with keyframes # Main function def main(): # Clear Console for easy debugging c4d.CallCommand(13957, 13957) # Get selected cameras obj = doc.GetActiveObjects(1) # Check if selected objects are cameras, if not pop-up error #code should come here # Go to Start of timeline c4d.CallCommand(12501) #create stage object stage = c4d.BaseObject(c4d.Ostage) doc.InsertObject(stage) # Get active document mydoc = c4d.documents.GetActiveDocument() # Loop through the array of cameras & put selected cameras in stage object for x in obj: mytime = mydoc.GetTime() myfps = mydoc.GetFps() # define prject fps myframe = mytime.GetFrame(myfps) #get current frame print(myframe) # print frame number stage[c4d.STAGEOBJECT_CLINK] = x # put camera camera slot of stage object #set keyframe How?? #mydoc.RecordKey(stage,[c4d.ID_BASEOBJECT_REL_ROTATION,c4d.VECTOR_X]) #Add the keyframe to Rotation X successfully mydoc.RecordKey(stage, 1) # Go to next key frame c4d.CallCommand(12414) c4d.EventAdd() #update # Execute main() if __name__=='__main__': main()
m_magalhaes last edited by m_magalhaes
For your next threads, please help us keeping things organised and clean. I know it's not your priority but it really simplify our work here. I've made the changes for this one already.
Regarding your question you have an example on our github repository how to create a keyFrame and add the track
We have useful information about ctrack in our c++ manual
If you have any questions, just ask.
Feel free to pass this thread as solved when ever you think it is.
import c4d def CreateKey(curve, time, value, interpolation): # Adds the key keyDict = curve.AddKey(time) # Checks if the key have been added if keyDict is None: raise MemoryError("Failed to create a key") # Retrieves the inserted key key = keyDict["key"] keyIndex = keyDict["nidx"] # Sets the value of the key key.SetGeData(curve, value) # Mandatory: Fill the key with default settings curve.SetKeyDefault(doc, keyIndex) # Changes it's interpolation key.SetInterpolation(curve, interpolation) return key, keyIndex # Main function def main(): # Retrieves the selected cameras cams = [x for x in doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_SELECTIONORDER) if x.IsInstanceOf(c4d.Ocamera)] # Creates the StageObject so = c4d.BaseObject(c4d.Ostage) # Creates the track in memory trackCamera = c4d.CTrack(so, c4d.DescID(c4d.DescLevel(1100, c4d.DTYPE_BASELISTLINK, 0))) # Retrieves the curve of the track curve = trackCamera.GetCurve() for i,cam in enumerate(cams): time = c4d.BaseTime(i, doc.GetFps()) CreateKey(curve, time, value=cam, interpolation=c4d.CINTERPOLATION_STEP) # Inserts the track to the stage object so.InsertTrackSorted(trackCamera) # Inserts the object to the scene and add an Undo step. doc.StartUndo() doc.InsertObject(so) doc.AddUndo(c4d.UNDOTYPE_NEW, so) doc.EndUndo() # Pushes an update event to Cinema 4D c4d.EventAdd() # Execute main() if __name__=='__main__': main()
martijnlambada last edited by
Thanks for your help! Next time I will use the 'ask question' when posting a question.
You code does exactly what I need, much appreciated!