How to add a keyframe when not in insert menu?

Hi,

how do I add a keyframe for properties not in the insert keyframe menu?

E.g. this is clear for the object properties


bpy.ops.anim.keyframe_insert(type='Location')

but what’s with properties like the camera focal length or the shift_x/y values of a camera.

I tried this, but it doesn’t work:


bpy.ops.object.select_all(action='DESELECT')
bpy.ops.object.select_camera()
bpy.context.active_object.data.shift_x = myShiftVal 
bpy.context.active_object.keyframe_insert(data_path="shift_x")

Thanks or any help

Do you have to do this with code? Both of these can be animated from the regular Blender GUI.

Thanks for your answer bill2reg,

yes I have to do it with python because I want to render scenes from a lots of different camera positions and each camera position needs a specific camera shift value, depending on the position. You don’t want to do this each time by hand.

But there should be a way to animate properties like the lens or the shifts using python, or not?

Yes, unfortunately I have to do it in python, because I want to render scenes from a lot of different camera positions and each camera position must have a different camera shift value depending on the cam position.

Hi Pat,

You can insert keyframes dir;ectly from a referenced object.


>>> cam = C.scene.camera.data
>>> cam
bpy.data.cameras['Camera']

>>> 
>>> cam.keyframe_insert(
keyframe_insert(data_path, index=-1, frame=bpy.context.scene.frame_current, group="")
.. method:: keyframe_insert(data_path, index=-1, frame=bpy.context.scene.frame_current, group="")
Insert a keyframe on the property given, adding fcurves and animation data when necessary.
:arg data_path: path to the property to key, analogous to the fcurve's data path.
:type data_path: string
:arg index: array index of the property to key. Defaults to -1 which will key all indices or a single channel if the property is not an array.
:type index: int
:arg frame: The frame on which the keyframe is inserted, defaulting to the current frame.
:type frame: float
:arg group: The name of the group the F-Curve should be added to if it doesn't exist yet.
:type group: str
:return: Success of keyframe insertion.
:rtype: boolean

>>> cam.keyframe_insert('shift_x')
True

>>> 


import bpy

context = bpy.context

scene = context.scene
camobj = scene.objects.get("Camera")
frame = 29 
if camobj is not None and camobj.type == 'CAMERA':
    cam = camobj.data
    cam.keyframe_insert("shift_x", frame=frame)

Hi batFINGER,

thank you so much, this works and I wonder a little bit why I haven’t found the solution for myself, because it seems very logic, but sometimes … :no:

Can anyone help with a VSE 2.60 python keyframe insert when I am using both crop and an image composite shift?

Using the GUI I have no problem inserting the keyframes to animate to make the image move but the normally helpful “info” window shows me nothing as I add the keyframes using the GUI. The following python code, without a keyframe insert, works perfectly, shifting the image vertically (with obj.transform.offset_y=300) just as I want:

obj=seq[‘test.png’]
obj.select=True
obj.use_crop=True
obj.crop.max_x=100 # arbitrary example crop
obj.use_translation=True
obj.transform.offset_y=300 # this vertical shift of the image works finr

However, when I add the following python keyframe insert I get

TypeError: bpy_struct.keyframe_insert() property “transform.offset_y” not found

obj.keyframe_insert(data_path=‘transform.offset_y’,frame=0)

Guessing it has to be a wrong data_path. So I used print("obj.path_from_id(): ", obj.path_from_id())

obj.path_from_id(): sequence_editor.sequences_all[“temp.png”]

Any suggestions appreciated!

Hi,

the animation fcurves have a path from the id object of what you are keyframing in…


>> obj = C.scene.sequence_editor.sequences_all['tmp0012.png']
>>> obj.id_data
bpy.data.scenes['Scene']

This tells us to keyframe from the scene object, You can see this if you add a keyframe manually then look at the data_path of the fcurve.


>>> a = bpy.data.actions.get('SceneAction')
>>> a.fcurves[0].data_path
'sequence_editor.sequences_all["tmp0012.png"].transform.offset_x'


In your code you could use


obj.id_data.keyframe_insert(datapath="%s.transform.offset_y" % obj.path_from_id())

Sweet batFINGER - two comments:

“obj.id_data.keyframe_insert(data_path=”%s.transform.offset_y" % obj.path_from_id(),frame=frameCurrent)" works perfectly!!!

Would appreciate knowing where you got this “%s.transform.offset_y” construct (perhaps a link to the blender doc)? It has a very “c/c++/gcc” like construct look but googling I saw nothing like this.

Also, how do I monetarily recognise you - have you perhaps a donate button somewhere / payPal?

You rock!!!

Aseire

The “%s.transform.offset_y” % obj.path_from_id()" construct does a ‘s’ String (converts any Python object using str()):

http://docs.python.org/library/stdtypes.html#string-formatting-operations