0
$\begingroup$

I'm working with the default Blender file that has single cube object. I'm rotating it with Python and adding keyframes. The problem is that a bpy.ops.transform.rotate() seems to take some time to execute so when I paste in a series of commands a keyframe is created before the rotation actually happens. If I paste commands in one at a time I get my expected animations. Is there a "finished" event, or "wait for last" command I can use?

This code pasted in the Console may show rotations on some of the keyframes and not on others, it is inconsistent.

bpy.context.scene.frame_current = 0
bpy.ops.anim.keyframe_insert()

bpy.context.scene.frame_current = 30

bpy.ops.transform.rotate(value=1.5708, axis=(1, 0, 0), constraint_axis=(True, False, False), constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1, release_confirm=False)

bpy.ops.anim.keyframe_insert()

bpy.context.scene.frame_current = 60

bpy.ops.transform.rotate(value=-1.5708, axis=(0, 1, 0), constraint_axis=(False, True, False), constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1, release_confirm=False)

bpy.ops.anim.keyframe_insert()

... and so on
$\endgroup$
0
$\begingroup$

Ditch the operators and use the API

Example script, rotates object 90 degrees about z axis. Inserts all keyframes of active keying set at frame 30. Not using any operators or changing the frame, simply set a property and call keyframe_insert.

import bpy
from mathutils import Matrix
from math import radians
context = bpy.context
ob = context.object
scene = context.scene
# emulate rotation op
R = Matrix.Rotation(radians(90), 4, 'Z') # rotate 90 about z axis
ob.matrix_world *= R

#emulate ops.anim.keyframe_insert
ks = scene.keying_sets.active
if ks:
    ks.refresh()
    for p in ks.paths:
        # check for entire array (index=-1)
        index = -1 if p.use_entire_array else p.array_index
        # insert keyframe
        ob.keyframe_insert(
                p.data_path, 
                index=index, 
                frame=30)

A method could be made using methods above that is passed the arguments object angle, axis and frame.

def rot_and_keyframe(ob, angle, axis, frame):
    ...

rot_and_keyframe(ob, radians(90), 'X', 30)
rot_and_keyframe(ob, radians(-90), 'Y', 60)
| improve this answer | |
$\endgroup$
  • $\begingroup$ Thank you, I'll give this a try. My ultimate goal is to animate the rotation of faces of a Rubik's cube and I've been having lots of trouble with x becoming z and y becoming x etc etc and what I did above is the only thing so far that didn't do that. $\endgroup$ – Crowcoder Sep 29 '18 at 18:49
  • $\begingroup$ Never did solve the Rubik's properly. Busted it apart and put back together. Would break it down similarly as an exercise in blender. Each move is Choose one of 3 axes to rotate to 1 of 3 other possible positions. for 1 or 2 of 3 of the "shearing plates". which comes down to manipulating a 3 x 3 x 3 array. Hope that makes some sense, is late. $\endgroup$ – batFINGER Sep 29 '18 at 19:15
  • $\begingroup$ It is not really working and my method with operators is doing the same thing. Once an axis has reached 180 degrees, further rotations go wacky. I need to be able to rotate as many times as necessary. If you are interested, you can see my blender file. It has your script and mine saved in Text Editor. In case you could not tell, I am new to 3D modeling and 3D math. $\endgroup$ – Crowcoder Sep 29 '18 at 23:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.