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$

1 Answer 1

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$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .