4
$\begingroup$

The Problem

Like many people, I use Render Region to lighten the load on viewport rendering by only rendering what's visible to the camera.

I also use Set Render Region (CtrlB) when I want to focus on just one specific area, and since all the samples get spent rendering that area, I can see that specific area more quickly.

The problem is that if you use Set Render Region and draw out a marquee selection, and then after that you want to resize the render region back to the camera bounds, you must Clear Render Region (CtrlAltB) and then re-enable Render Region by ticking the checkbox.

An animated GIF to illustrate the issue simply:

Switching between different render preview regions

The Question

Is there a way to re-map CtrlAltB to toggle between the marquee-selected region and the camera boundary region?

More Details

Examining the Info window, we can see that the syntax for enabling Render Region is bpy.context.scene.render.use_border = True

On the other hand, Set Render Region is bpy.ops.view3d.render_border(xmin=682, xmax=786, ymin=1248, ymax=1422)

And Clear Render Region is bpy.ops.view3d.clear_render_border()

Even though all three of these operations define the region to be rendered, they work differently. I have not found a way to toggle between two differently sized render regions (user-specified and camera bounds).

$\endgroup$

1 Answer 1

4
$\begingroup$

'Render Region' Toggle

You can implement a custom Operator to toggle Render Region using a shortcut. In this case, all you'd have to do is finding a reliable way to set the state of RenderSettings.use_border:

enter image description here

The following demo based on the answers of How to easily toggle a Boolean property? and Create keyboard shortcut for an operator using python?:

toggle-render-region.py

# ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>

import bpy

bl_info = {
    "name": "Toggle Render Region Hotkey",
    "author": "brockmann",
    "version": (0, 1),
    "blender" : (2, 80, 0),
    "location": "3D View",
    "category": "3D View"
}


class RR_OT_toggleRenderRegion(bpy.types.Operator):
    """Toggle Render Region in 3D View"""
    bl_idname = "view3d.toggle_render_region"
    bl_label = "Toggle Render Region"
    bl_options = {'REGISTER', 'UNDO'}
    
    def execute(self, context):
        context.scene.render.use_border ^= 1
        return {'FINISHED'}


addon_keymaps = []

def register():
    bpy.utils.register_class(RR_OT_toggleRenderRegion)
    addon_keymaps.clear()

    # handle the keymap
    wm = bpy.context.window_manager
    kc = wm.keyconfigs.addon
    if kc:
        km = wm.keyconfigs.addon.keymaps.new(name='3D View', space_type='VIEW_3D')
        #kmi = km.keymap_items.new(RR_OT_disableRenderRegion.bl_idname, type='B', value='PRESS', ctrl=True, shift=True)
        kmi = km.keymap_items.new(RR_OT_toggleRenderRegion.bl_idname, type='B', value='PRESS', ctrl=True, alt=True)
        addon_keymaps.append((km, kmi))

def unregister():
    bpy.utils.unregister_class(RR_OT_toggleRenderRegion)

    for km, kmi in addon_keymaps:
        km.keymap_items.remove(kmi)
    addon_keymaps.clear()

if __name__ == "__main__":
    register()

enter image description here

As mentioned by @batFINGER in the comments there is also a generic bpy.ops.wm.context_toggle() operator for convenience which allows to toggle any BoolProperty (also used for some of the default hotkeys in Blender).

toggle-render-region.py

 # ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>

import bpy

bl_info = {
    "name": "Toggle Render Region Hotkey",
    "author": "brockmann, batFINGER",
    "version": (0, 1),
    "blender" : (2, 80, 0),
    "location": "3D View",
    "category": "3D View"
}

addon_keymaps = []

def register():
    addon_keymaps.clear()

    # handle the keymap
    wm = bpy.context.window_manager
    kc = wm.keyconfigs.addon
    if kc:
        km = wm.keyconfigs.addon.keymaps.new(name='3D View', space_type='VIEW_3D')
        kmi = km.keymap_items.new("wm.context_toggle", type='B', value='PRESS', ctrl=True, alt=True)
        kmi.properties.data_path = "scene.render.use_border"
        addon_keymaps.append((km, kmi))

def unregister():
    for km, kmi in addon_keymaps:
        km.keymap_items.remove(kmi)
    addon_keymaps.clear()

if __name__ == "__main__":
    register()

If you'd like to edit the old shortcut manually without using an add-on, replace the identifier and the data_path for the old hotkey by wm.context_toggle and scene.render.use_border:

enter image description here


Toggle between 'Selection' and 'Camera Bounds'

If you'd like to toggle between the current selection and the camera bounds using a shortcut you'd have to implement a custom Operator as well as supplying a new scene property in order to store the coordinates and restore them if necessary:

enter image description here

custom-render-region.py

# ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>

import bpy

bl_info = {
    "name": "Custom Render Region",
    "author": "brockmann",
    "version": (0, 1),
    "blender" : (2, 80, 0),
    "location": "3D View",
    "category": "3D View"
}


class RR_OT_customRenderRegion(bpy.types.Operator):
    """Custom Render Region"""
    bl_idname = "view3d.custom_render_region"
    bl_label = "Custom Render Region"
    bl_options = {'REGISTER', 'UNDO'}
    
    def execute(self, context):
        scene = context.scene
        rnd = scene.render
        
        if rnd.border_min_x != 0 or rnd.border_min_y != 0 or \
            rnd.border_max_x != 1 or rnd.border_max_y != 1:
            # Store the values
            scene.custom_render_bounds = (
                    rnd.border_min_x, 
                    rnd.border_min_y, 
                    rnd.border_max_x, 
                    rnd.border_max_y)
            # Camera bounds
            rnd.border_min_x = rnd.border_min_y = 0
            rnd.border_max_x = rnd.border_max_y = 1
            
        else:
            # Set the values
            rnd.border_min_x = scene.custom_render_bounds[0]
            rnd.border_min_y = scene.custom_render_bounds[1]
            rnd.border_max_x = scene.custom_render_bounds[2]
            rnd.border_max_y = scene.custom_render_bounds[3]
        
        # Clear region if not in camera view
        if not context.space_data.region_3d.view_perspective == 'CAMERA':
            bpy.ops.view3d.clear_render_border()
        
        return {'FINISHED'}


addon_keymaps = []

def register():
    bpy.types.Scene.custom_render_bounds = bpy.props.FloatVectorProperty(size=4)
    bpy.utils.register_class(RR_OT_customRenderRegion)
    addon_keymaps.clear()

    # handle the keymap
    wm = bpy.context.window_manager
    kc = wm.keyconfigs.addon
    if kc:
        km = wm.keyconfigs.addon.keymaps.new(name='3D View', space_type='VIEW_3D')
        kmi = km.keymap_items.new(
            RR_OT_customRenderRegion.bl_idname, type='B', 
            value='PRESS', 
            ctrl=True, 
            alt=True)
        addon_keymaps.append((km, kmi))

def unregister():
    bpy.utils.unregister_class(RR_OT_customRenderRegion)

    for km, kmi in addon_keymaps:
        km.keymap_items.remove(kmi)
    addon_keymaps.clear()

if __name__ == "__main__":
    register()
$\endgroup$
0

You must log in to answer this question.

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