1
$\begingroup$

I have a problem with the context being incorrect while i try to work with both the animator and do renderings.

I have a script where i would like to do a bunch of renders of the same object dropped in different positions using the physics engine. The problem is that after rendering i can not get the right context to work with the timeline.

Here I can show an example of my problem (I have removed a bit of code which basically remove handlers when they are no longer used, etc. in order to make it more readable)

First i will call this generate image function. Everything works fine and the animation resets and plays. No problem

def generate_image():
  scene = bpy.context.scene

  # Add the handler to know when rendering should be done
  bpy.app.handlers.frame_change_post.append(stop_at_last_frame)

  # Reset the animation (to before physics)
  bpy.ops.screen.frame_jump()

  # Move objects randomly around before dropping

  # Play the animation (run the physics system)
  bpy.ops.screen.animation_play()

The stop_at_last_frame is called when the animation is finished and all physics simulations are done. It looks like this

def stop_at_last_frame(scene):
  if scene.frame_current == scene.frame_end:
    # Stop the physics engine this is omitted for readability  
    # Call on render done when rendering is done
    bpy.app.handlers.render_post.append(on_render_done)
    # some setup here is omitted
    bpy.ops.render.render('INVOKE_DEFAULT', write_still=True)

When rendering is done this final callback function is called, which simply starts the process all over

def on_render_done(scene):
  # Keep generating images
  generate_image()

Now when the process starts all over and generate_image() is called after the render, i get the following error

RuntimeError: Operator bpy.ops.screen.animation_play.poll() failed, context is incorrect

This happens basically for all operations using the timeline. It seems that something has happened to my context during rendering which i have to "reset". However i can not really see what i have to do here.

$\endgroup$
2
$\begingroup$

OK so I found a solution for this.

It should be noticed that I just needed to run everything as a script. I however thought that the UI would help me debugging, hence i tried to run it all from within blender.

The solution was to actually run blender in background mode, and not using bpy.ops for anything else then rendering.

blender blender_file.blend --background --python script.py

When running in background mode, I do not need all the callbacks to know when stuff is done, since the code is no longer async.

Now to do the physics simulation and then render I can simply do the following:

# Reset to first frame
scene = bpy.context.scene
scene.frame_set(0)

# Run the physics simulation
for i in range(250):
    scene.frame_set(i)

# Render image
bpy.ops.render.render(write_still=True)
$\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.