0
$\begingroup$

The code snippet below contains a block code; running once in the global scope, and once inside the else branch of a condition:

>>> bpy.context.selected_pose_bones[0].constraints[0].influence = 0.0
>>> mat1 = bpy.context.selected_pose_bones[0].matrix.copy()
>>> bpy.context.selected_pose_bones[0].constraints[0].influence = 1.0
>>> mat2 = bpy.context.selected_pose_bones[0].matrix.copy()
>>> result = "Good" if (mat1 != mat2) else "Bad"
>>> print("Result: %s" % (result))

Result: Good

>>> 
>>> if (armature == None or armature.type != 'ARMATURE'):
...     print("Selected object must be an armature")
... elif (bpy.context.selected_pose_bones == None or len(bpy.context.selected_pose_bones) != 1):
...     print("Select at least 1 pose bone")
... else:
...     bpy.context.selected_pose_bones[0].constraints[0].influence = 0.0
...     mat1 = bpy.context.selected_pose_bones[0].matrix.copy()
...     bpy.context.selected_pose_bones[0].constraints[0].influence = 1.0
...     mat2 = bpy.context.selected_pose_bones[0].matrix.copy()
...     result = "Good" if (mat1 != mat2) else "Bad"
...     print("Result: %s" % (result))
...

Result: Bad

From some reason though, it doesn’t evaluate correctly when inside a condition. What is going on? what am I missing?

$\endgroup$
  • 2
    $\begingroup$ Hi. Please include any relevant code in the question body itself. $\endgroup$ – Ray Mairlot Jan 4 at 13:31
1
$\begingroup$

This answer warns that for performance reasons, Blender does not update certain attributes (like obj.matrix_world) until necessary. I think your experiment suggests that bpy.context.selected_pose_bones[0] falls into this category.

The same linked answer shows that you can force an update using

bpy.context.scene.update()

Let's try it here:

armature = bpy.data.objects['Armature']
if (armature == None or armature.type != 'ARMATURE'):
    print("Selected object must be an armature")
elif (bpy.context.selected_pose_bones == None or len(bpy.context.selected_pose_bones) != 1):
    print("Select at least 1 pose bone")
else:
    bpy.context.selected_pose_bones[0].constraints[0].influence = 0.0
    bpy.context.scene.update()
    mat1 = bpy.context.selected_pose_bones[0].matrix.copy()
    bpy.context.selected_pose_bones[0].constraints[0].influence = 1.0
    bpy.context.scene.update()
    mat2 = bpy.context.selected_pose_bones[0].matrix.copy()
    print(mat1)
    print(mat2)        
    result = "Good" if (mat1 != mat2) else "Bad"
    print("Result: %s" % (result))

yields

<Matrix 4x4 (1.0000, 0.0000,  0.0000, 0.0000)
            (0.0000, 0.0000, -1.0000, 0.0000)
            (0.0000, 1.0000,  0.0000, 0.0000)
            (0.0000, 0.0000,  0.0000, 1.0000)>
<Matrix 4x4 (1.0000, 0.0000,  0.0000, -0.0494)
            (0.0000, 0.0000, -1.0000, -0.0543)
            (0.0000, 1.0000,  0.0000,  0.1240)
            (0.0000, 0.0000,  0.0000,  1.0000)>
Result: Good

When you enter the commands individually on the command line, Blender seems to call bpy.context.scene.update() in the background for you. When all the commands are placed in the body of an if-statement, then the commands are not executed until the entire if-statement is written and sent to the Python interpreter. The interpreter then executes all of the statements in the body of the if-statement very quickly, one after another. Now, Blender does not have time to call bpy.context.scene.update() in the background between each statement.

This explains why you saw a difference in behavior.

$\endgroup$

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.