4
$\begingroup$

I have a list of translations and rotations from a rigid body calculation that I'd like to apply to an object using the frame_change_pre handler.

Both the translation/rotation text file and the script that defines the handler are stored in my .blend file. When I open the .blend file in Blender and render the animation, the script works as expected.

My problem is that when I run in batch mode using the command:
/path/to/blender tossTest.blend -b -s 1 -e 8 -a
the transformations aren't applying in the output.

The following listing is the python script, script.py.

import bpy
from mathutils import Matrix
from mathutils import Vector

# Create 'posList' from 'positionDataSmall.txt', which is
# a text file stored inside this .blend file.
posList=[]
text=bpy.data.texts['positionDataSmall.txt']

for i in range(1,15):
    text.current_line_index=i
    line=text.current_line.body
    posList.append([float(v) for v in line.split(',')])

# The function that rotates and translates Suzanne using
# the position list array.
# Called by the handler.
def rotByIndex(n):
    if n<0: n=0
    if n>=len(posList): n=len(posList)-1

    mr=Matrix((posList[n][4:7],
               posList[n][7:10],
               posList[n][10:13])).to_4x4()
    vt=Vector(posList[n][1:4])
    mt=Matrix.Translation(vt)
    m=mt*mr

    obj=bpy.data.objects['Suzanne']
    obj.matrix_local=m

# The handler which gets called
def my_handler(scene):
    bpy.data.objects['Suzanne'].select=True

    rotByIndex(scene.frame_current-1)
    scene=bpy.data.scenes['Scene']
    scene.update()

bpy.app.handlers.frame_change_pre.append(my_handler)

And here's positionDataSmall.txt:

time,X,Y,Z,r11,r12,r13,r21,r22,r23,r31,r32,r33
0,0,0,0,1,0,0,0,1,0,0,0,1
0.1,-0.008852,0.17392,0.582415,0.937926,-0.024107,-0.345997,0.099391,0.974378,0.201766,0.332292,-0.223621,0.916284
0.2,-0.086264,0.395815,1.171942,0.813167,0.008713,-0.581965,0.179952,0.947084,0.2658,0.553515,-0.320867,0.768548
0.3,-0.208956,0.61547,1.709725,0.682634,0.027446,-0.730245,0.263186,0.922954,0.280871,0.681722,-0.383931,0.622778
0.4,-0.359143,0.832437,2.177802,0.559921,0.035089,-0.827802,0.347363,0.897075,0.273121,0.752213,-0.440487,0.490048
0.5,-0.517773,1.04868,2.556567,0.434674,0.045545,-0.899435,0.429578,0.867257,0.251652,0.791527,-0.495778,0.357337
0.6,-0.676588,1.264907,2.837416,0.301292,0.064759,-0.95133,0.506222,0.834588,0.217262,0.808053,-0.547058,0.218583
0.7,-0.835403,1.481143,3.020156,0.162968,0.092379,-0.982297,0.575247,0.799951,0.170788,0.801569,-0.592908,0.077121
0.8,-0.994218,1.697387,3.104786,0.023238,0.127698,-0.991541,0.634886,0.764235,0.113421,0.772239,-0.632158,-0.063431
0.9,-1.153033,1.913641,3.091307,-0.114327,0.16981,-0.978823,0.683614,0.728353,0.046628,0.720813,-0.663804,-0.199482
1,-1.311849,2.129903,2.979719,-0.246211,0.217638,-0.944465,0.720182,0.693225,-0.027883,0.648604,-0.687039,-0.327552
1.1,-1.470664,2.346174,2.770023,-0.369041,0.269958,-0.889343,0.743655,0.659749,-0.108203,0.557458,-0.701271,-0.444365
1.2,-1.629479,2.562454,2.462217,-0.479677,0.32543,-0.814865,0.753434,0.628783,-0.192277,0.449704,-0.706136,-0.546936
1.3,-1.788296,2.778741,2.056303,-0.575288,0.382638,-0.722933,0.749268,0.601116,-0.277952,0.328096,-0.701514,-0.632639
1.4,-1.947117,2.995036,1.552281,-0.653427,0.440118,-0.615897,0.731267,0.577455,-0.363034,0.195743,-0.687524,-0.699282

Some notes and things I've tried:

  • Register is checked for script.py in the .blend file.
  • Auto Run Python Scripts is checked and saved in the user preferences.
  • I've tried placing -y among the command-line arguments
  • I've tried storing script.py as an external file and loading it using -P script.py
  • When I print the matrix m in rotByIndex, Blender shows that it's getting and updating the matrix appropriately in batch mode. So I know rotByIndex is being called on frame changes and that it has access to posList.

Does anybody know why my object isn't updating properly when not in the GUI?

$\endgroup$
  • $\begingroup$ What about calling bpy.data.objects['Suzanne'].update() before scene.update()? Not sure, but maybe this will help. $\endgroup$ – Daniil Romanov Jul 10 '15 at 7:38
1
$\begingroup$

From the API documentation:

By default handlers are freed when loading new files, in some cases you may wan’t the handler stay running across multiple files (when the handler is part of an addon for example).

For this the bpy.app.handlers.persistent decorator needs to be used.

import bpy
from bpy.app.handlers import persistent

@persistent
def load_handler(dummy):
    print("Load Handler:", bpy.data.filepath)

bpy.app.handlers.load_post.append(load_handler)
$\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.