2
$\begingroup$

Is it possible to have the render view update automatically instead of pressing manually F12 every time as I change motion blur effect properties? This is concerning Render view only and has nothing to do with viewport rendering because motion blur only gets applied in the render view if I am correct.

$\endgroup$
3
$\begingroup$

Use the Message Bus to notify when settings change and then render the image.

import bpy

scene = bpy.context.scene
key = scene.render if scene.render.engine == 'CYCLES' else scene.eevee

def msgbus_callback():
    bpy.ops.render.render("INVOKE_DEFAULT")

bpy.msgbus.subscribe_rna(key=key, owner=object(), args=(), notify=msgbus_callback)

FYI: this will render also when different settings are changed.

$\endgroup$
4
  • $\begingroup$ 10 seconds faster than me, good one! $\endgroup$
    – brockmann
    Jul 17 at 15:15
  • $\begingroup$ @brockmann I know the pain, I wish there was a feedback like with edits, where you see an answer is being edited - for straight-forward answers like this it would save me some time. $\endgroup$ Jul 17 at 15:16
  • $\begingroup$ Ez, no pain. Notice that the OP is asking for cycles motion blur. $\endgroup$
    – brockmann
    Jul 17 at 15:18
  • 1
    $\begingroup$ @brockmann thanks, I didn't read the tags - updated the answer. $\endgroup$ Jul 17 at 15:25
0
$\begingroup$

This, much more elaborate code will allow for more interactive blur adjustment - still, sadly, I didn't find a way to cancel current render from script, so it's not as interactive as it could be. Perhaps it could be changed to render with 1 sample first and then increase the number of samples and re-render...

import bpy

class BlurPreviewOperator(bpy.types.Operator):
    """Operator helping with interactive blur preview"""
    bl_idname = "render.blur_preview"
    bl_label = "for usage in a script"
    bl_options = {"INTERNAL"}

    delay = .2  # how long to wait after a change to render
    timer_delay = 0.1  # accuracy of delay depends on this
    timer = None
    last_duration = 0
    rendering = None
    last_shutter = None
    shutter = None
    next_shutter = None

    def render_cancel(self, *args, **kwargs):
        # treating cancel the same way as completing
        # instead could add some more logic to allow the user to cancel once
        # to render the most recent setting faster, or cancel twice
        # to avoid rendering (set self.render_needed = False)
        self.render_complete(*args, **kwargs)
        
    def render_complete(self, scene, depsgraph=None):
        self.rendering = False
        self.last_shutter = self.next_shutter
        
    def add_handlers(self, C):
        print("add")
        bpy.app.handlers.render_cancel.append(self.render_cancel)
        bpy.app.handlers.render_complete.append(self.render_complete)
        self.timer = C.window_manager.event_timer_add(self.timer_delay, window=C.window)
        print(dir(self.timer))

    def cancel(self, C):
        bpy.app.handlers.render_cancel.remove(self.rendering_stopped)
        bpy.app.handlers.render_complete.remove(self.rendering_stopped)
        C.window_manager.event_timer_remove(self.timer)

    def shutter_check(self, C):
        engine = C.scene.render.engine
        path = C.scene.render if engine == "CYCLES" else C.scene.eevee
        shutter = path.motion_blur_shutter
        if self.shutter != shutter:
            self.shutter = shutter
            self.last_duration = self.timer.time_duration
        
    def execute(self, C):
        self.add_handlers(C)
        C.window_manager.modal_handler_add(self)
        return {"RUNNING_MODAL"}    

    def modal(self, C, event):
        if event.type == "TIMER":
            self.shutter_check(C)
            if self.rendering or self.timer.time_duration < self.last_duration + self.delay:
                return {"PASS_THROUGH"}
            if self.last_shutter != self.shutter:
                self.rendering = True
                self.next_shutter = self.shutter
                bpy.ops.render.render("INVOKE_DEFAULT")
        return {"PASS_THROUGH"}


bpy.utils.register_class(BlurPreviewOperator)
bpy.ops.render.blur_preview()
$\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.