[SOLVED] Blender 2.5: bug or error on context ?

Scripting in Blender with Python, and working on the API

Moderators: jesterKing, stiv

zipgem
Posts: 9
Joined: Wed Dec 22, 2010 10:42 am

[SOLVED] Blender 2.5: bug or error on context ?

Postby zipgem » Mon Feb 07, 2011 8:24 am

Hi everybody,
I have a question for you.
When I use in python script (with blender -P script.py argument) some operation like

Code: Select all

bpy.ops.anim.keyframe_insert()

or other ops action, Blender/Python returns me an error which tells me that context is incorrect like

Code: Select all

SystemError: Operator bpy.ops.anim.keyframe_insert.poll() failed, context is incorrect

so,
which is the correct context for operations and how can I change to it?

Thank you all in advance

Zipgem
Last edited by zipgem on Fri Feb 25, 2011 7:58 am, edited 1 time in total.

martingu
Posts: 6
Joined: Sun Jan 30, 2011 8:35 pm

Postby martingu » Sat Feb 12, 2011 6:49 pm

Hi,

Incorrect context means that the context is not in the correct state for the operator to run. What the correct state is depends on the operator itself so you'll have to experiment a bit. I'm not sure about anim.keyframe_insert ... it operates on selected/active objects (I guess), so make sure that there is at least one selected object (I was getting this error with bpy.ops.object.convert because of not having valid selection).

I found that to select an object in Python and be able to apply an operator to it, you need to set the obj.select = True (and possibly set the selection state of other objects to False) and set the bpy.context.scene.objects.active = obj, where obj is your object.

One way to find out what are the conditions for an operator to work is to check how it works in the Blender UI. Then prepare the context in the same way as you had it before you invoked 'Insert Keyframe' in Blender.

zipgem
Posts: 9
Joined: Wed Dec 22, 2010 10:42 am

Postby zipgem » Mon Feb 14, 2011 10:48 am

Hi martingu,

thank you for your answer.

I did some test on Blender 2.56a, but I need more help :)
I started from an initial Blender scene with a camera, a point light and a cube in origin (base.blend); then I made the following Python script snippet:

Code: Select all

import bpy

cube = bpy.context.scene.objects['Cube']

# deactive and deselect all scene objects
bpy.context.scene.objects.active = None
for object in bpy.context.scene.objects:           # or 'for object in bpy.data.objects' ... I don't know
   object.select = False

# activate and select only cube object
bpy.context.scene.objects.active = cube
cube.select = True

# set current frame to 1
bpy.context.scene.frame_current = 1
# insert keyframe in location/rotation mode
bpy.ops.anim.keyframe_insert(type='LocRot')

# save scene
bpy.ops.wm.save_as_mainfile(filepath='/tmp/testing_keyframe.blend')


If I try this code with command:

Code: Select all

./blender256a -b base.blend -P testing_keyframe.py


Blender returns me the following error:

Code: Select all

Traceback (most recent call last):
  File "testing_keyframe.py", line ..., in <module>
    bpy.ops.anim.keyframe_insert(type='LocRot')
  File "/root/blender256a/2.56/scripts/modules/bpy/ops.py", line 179, in __call__
    ret = op_call(self.idname_py(), None, kw)
SystemError: Operator bpy.ops.anim.keyframe_insert.poll() failed, context is incorrect


So I try to comment insert_keyframe in the snippet and open saved scene. Then in Python console I launch command bpy.ops.anim.keyframe_insert(type='LocRot') and it works.
I don't understand the different from script and from Python console in Blender UI.

Some helps ??

Thank you

batFINGER
Posts: 33
Joined: Wed Jan 23, 2008 4:33 pm

Postby batFINGER » Mon Feb 14, 2011 1:11 pm

Why not just use

Code: Select all


#without an index specified it will insert all keys of type.
#without a frame specified it will insert the keyframe at the current_frame

cube.keyframe_insert('location',group="LocRot")
cube.keyframe_insert("rotation_euler",group="LocRot")

#you can specify an index and frame also
# this will insert a scaleX keyframe at frame 100 and put it in the "ABBA" group

frame = 100
cube.keyframe_insert('scale', index=0 ,frame=frame,group="ABBA")


Much easier especially if you know the object or bone or whatever that you want to keyframe.. you also don't have to change scene frame to use.

zipgem
Posts: 9
Joined: Wed Dec 22, 2010 10:42 am

Postby zipgem » Mon Feb 14, 2011 2:37 pm

Great!!!!!!!! :)
Thank you batFINGER!
It works, wow!
But I have again 2 questions for you:

1. can I use always an object method (or similar) to workaround context incorrect problem on ops ?

2. in documentation I look that keyframe_insert() have the parameter data_path and group. Which are the correct value for these 2 parameters?
I see for data_path there are:
- location
- rotation_euler
- scale
And for group, 'LocRot'.
So for data_path value is the property (object.location, object.rotation_euler, object.scale, ..., object.color .... ???)
And for group value is the group of keyframe_insert type like 'Location', 'Rotation', 'LocRot', 'Visual LocRot', 'Available', ...

Is it right?

Thank you again

Zipgem

batFINGER
Posts: 33
Joined: Wed Jan 23, 2008 4:33 pm

Postby batFINGER » Mon Feb 14, 2011 4:24 pm

Yep that's pretty much it.

You can get the data_path for just about every thing from the UI.. right click on a value and "copy data path" then paste it into text editor... also pays to have an up to date API pdf on hand.

Remember if you are in say the mesh panel of an object the data path will be in context of the mesh .. so for the object it would be

data.auto_smooth_angle (the normal smooth angle on the mesh panel)

data_path's like location rotation etc need to be indexed to get individual properties x, y, z etc.

As for groups .. they seem pretty arbitrary to me. They are assigned to the fcurves... and only once .. for instance if you key in LocRotScale then Scale.... and then vice versa you'll see what i mean. Not sure if there is a way to get what data_paths are set by the group names. But like in the example you can use ABBA for instance. Seems they are in some ways for convenience to be able to key in locrotscale for instance, all at once from the UI and have them nicely grouped. VisualLoc for instance is the world location after constraints etc are applied, whereas loc is unaffected... hope that makes sense.

The groups come in hand IMO on rigs to say keep hips and down in one group so you can mask out different parts of seperate animations easilly.

There is often a method to use rather than bpy.ops... If you could find away to clean fcurves from a script it would be most appreciated lol.

zipgem
Posts: 9
Joined: Wed Dec 22, 2010 10:42 am

Postby zipgem » Fri Feb 25, 2011 7:57 am

Hi batFINGER,
thank you for your reply.
If I find a way to run context correctly, I'll post the solution.

Thank you

Zipgem

sjjh
Posts: 2
Joined: Fri Jul 27, 2012 9:43 am

Postby sjjh » Fri Jul 27, 2012 10:17 am

Very helpful, if quite old, thanks both


Return to “Python”

Who is online

Users browsing this forum: No registered users and 1 guest