2
$\begingroup$

I'm trying to render a bunch of actions with a modal operator that is called with a timer. The first action is rendered as expected, and strangely some times the second and third are rendered aswell, but at some point

bpy.ops.render.render("INVOKE_DEFAULT", write_still=True, animation=True)

returns {'CANCELLED'}, which breaks my callback handler. If i render it in serial without "INVOKE_DEFAULT" it works just fine. I also tried calling the render operator multiple times if it failes, but without success.

If I use a higher timeout like around 2 seconds it seems to work just. But why? Is there some kind of race condition between my modal operator and the render operator?

class BC_render_modal(bpy.types.Operator):
"""Start blenderclonk render process"""
bl_idname = "action.render_modal"
bl_label = "Start render"

_timer = None

rendering = False
render_lsit = []
pending_list = []   # Actions of the currently rendered mode
composition_list = []

@classmethod
def poll(cls, context):
    return True

def execute(self, context):
    wm = context.window_manager

    # Prepare render list
    self.render_list = create_render_list(context)
    # Register timer to check render status
    self._timer = wm.event_timer_add(0.1, window=context.window)
    # Register post render reset function
    bpy.app.handlers.render_complete.append(self.render_complete)

    wm.modal_handler_add(self)
    return {"RUNNING_MODAL"}

def render_complete(self, scene):
    self.rendering = False

def modal(self, context, event):

    if event.type == "TIMER":
        if not self.rendering:

            if self.pending_list:
                print("Render action")

                self.rendering = True    
                action_name = self.pending_list.pop(0)
                anim.selectAction(action_name)

                bpy.ops.render.render("INVOKE_DEFAULT", write_still=True, animation=True)

            elif self.render_list:   # Next render block    
                print("Prepare render")

                mode, actions = self.render_list.pop(0)

                self.pending_list = actions
                prepare_materials(mode)

                if mode not in self.composition_list:
                    self.composition_list.append(mode)

            else:
                wm = context.window_manager
                wm.event_timer_remove(self._timer)

                bpy.app.handlers.render_complete.remove(self.render_complete)

                for mode in self.composition_list:
                    ComposeGraphics(mode)

                self.report({"INFO"}, "Render finished successfully")
                return {"FINISHED"}

    return {"PASS_THROUGH"}

EDIT:

Seems to be an issue with the render thread reporting finished before the job is actually done. Check out https://developer.blender.org/T52258 for detailed explanation.

Workaround: This will lead to multiple failing attempts to start the render process but renders it eventually.

def modal(self, context, event):

    if event.type == "TIMER":
        if not self.rendering:

            if self.pending_list:
                print("Render action")

                self.rendering = True    
                action_name = self.pending_list.pop(0)
                anim.selectAction(action_name)

                result = bpy.ops.render.render("INVOKE_DEFAULT", write_still=True, animation=True)
                if result == {"CANCELLED"}:
                    print("Render failed!")
                    self.pending_list.insert(0, action_name)
                    self.rendering = False
$\endgroup$

1 Answer 1

0
$\begingroup$

it's passed a while but I still have the same problem. Is it possible that the issue is not solved? I had a look at the bug tracker and it seems closed but not solved... Is there a better way in 2022 to launch a modal render and to be notified when execution finish? I've also read in the issue that the suggested alternative is to use EXEC_DEFAULT instead of INVOKE_DEFAULT but to me this is unacceptable since I want to be able to interrupt render from UI. Any news on this topic?

$\endgroup$

You must log in to answer this question.

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