1
$\begingroup$

I'm currently working on addon and need to replace Render and Render Animation user operations with addon operations. The perfect way would be to re-link Blender original UI buttons and shortcuts directly to addon operations while addon is enabled, but I'm not sure if it is even possible without changing Blender source code. Of course the most obvious way would be to add Render and Render Animation buttons in addon UI, but I really want to avoid this to keep everything user-friendly and familiar.

The only way I've found is to use a handler with a function which aborts original Blender render operation and replaces it with addon operations, e.g.:

bpy.app.handlers.render_pre(my_render_replace_function)

The problem is that my algorithms for rendering a single frame and animation are a bit different, so the addon have to know exactly what command user have used. And unfortunately there's no handler in blender like:

bpy.app.handlers.render_animation_pre()

I thought it would be possible to access Undo History somehow to get the last undo item and use it for choosing the correct algorithm. There is a method which gives an access to perform direct operations over the Undo History:

bpy.ops.ed.undo_history(item=0)

Writing a function which would search for the last item's number is also no problem using preferences settings to get maximum number of undo steps in the scene

bpy.context.preferences.edit.undo_steps

and, in case it haven't been reached yet, using "for" loop to check smaller numbers until that method returns something different from '{CANCELLED}'

The only thing I can not find is the way to find exact undo item's meaning or even type, because bpy.ops.ed.undo_history doesn't have such methods. So is there another way to access undo history to get exact item, not just its number? Or maybe another way to define what was the last operation and tell it to Python?

Actually if anyone could suggest any solution without using undo history at all, it would be even more appreciated, because we all know that the whole undo system in Blender currently is not the thing you want to deal with and it can be replaced with new one in any new build.

$\endgroup$
0
$\begingroup$

The solution for this particular task may be in using render_pre handler to change a global variable. The first frame has to be rendered anyway, so this is not a very elegant solution, but it will do for my purposes. This particular code has to be executed before every render to reset global variable.

import bpy

render_count = 0 # global variable

def execute_for_single():
    print('executing single frame')
    pass

def execute_for_animation():
    print('executing animation')
    pass

def check_for_animation(context, dummy): # needs 2 arguments to be used in handlers
    global render_count # use global variable
    render_count += 1 # change global variable
    if render_count <= 1: # 1 or less frame is being rendered
        execute_for_single()
    else: # more than 1 frame is being rendered 
        execute_for_animation()
        render_count = 0 # reset global variable
        bpy.app.handlers.render_pre.clear() # reset handler

bpy.app.handlers.render_pre.clear() # just a cleanup before the start
bpy.app.handlers.render_pre.append(check_for_animation)

Also I found this:

bpy.context.active_operator

It returns the last executed operator, but needs the correct context, which I didn't manage to determine for render operators, even using the context override. But I guess for the most other operators it may be helpful.

$\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.