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

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.