With the Blender Python API, we can work not only with scene objects, but also with the user interface (UI). For example, we can save and restore the position of the 3D Viewport in the scene.
Code author: Andrej
The position of the viewport in the Blender Python API is described by a number of parameters that can be stored in a list for ease of working with them.
1 2 3 4 5 |
VIEWPORT_ATTRIBUTES = [ 'view_matrix', 'view_distance', 'view_perspective', 'use_box_clip', 'use_clip_planes', 'is_perspective', 'show_sync_view', 'clip_planes' ] |
We can get the current area of a 3D viewport using the following function:
1 2 3 4 |
def get_r3d(): area = next(area for area in bpy.context.screen.areas if area.type == "VIEW_3D") r3d = area.spaces[0].region_3d return r3d |
The “save_viewport_position” function saves a copy of the current value for each of the previously listed viewport options.
1 2 3 4 5 |
def save_viewport_position(): r3d = get_r3d() copy_if_possible = lambda x: x.copy() if hasattr(x, 'copy') else x data = {attr: copy_if_possible(getattr(r3d, attr)) for attr in VIEWPORT_ATTRIBUTES} return data |
The function returns a block of saved data.
To restore the saved viewport parameters, the “apply_viewport_position” function is used, in the parameter of which the previously saved data block is passed.
1 2 3 4 |
def apply_viewport_position(data): r3d = get_r3d() for attr in VIEWPORT_ATTRIBUTES: setattr(r3d, attr, data[attr]) |
Way of use: save data about the current position of the viewport into a variable, change the viewport position if necessary, and call the restore function to return to the saved position of the viewport.
1 2 3 4 5 6 7 |
# save viewport current_viewport = save_viewport_position() # rotate viewport to test it # restore viewport apply_viewport_position(current_viewport) |
Full code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
import bpy VIEWPORT_ATTRIBUTES = [ 'view_matrix', 'view_distance', 'view_perspective', 'use_box_clip', 'use_clip_planes', 'is_perspective', 'show_sync_view', 'clip_planes' ] def get_r3d(): area = next(area for area in bpy.context.screen.areas if area.type == "VIEW_3D") r3d = area.spaces[0].region_3d return r3d def save_viewport_position(): r3d = get_r3d() copy_if_possible = lambda x: x.copy() if hasattr(x, 'copy') else x data = {attr: copy_if_possible(getattr(r3d, attr)) for attr in VIEWPORT_ATTRIBUTES} return data def apply_viewport_position(data): r3d = get_r3d() for attr in VIEWPORT_ATTRIBUTES: setattr(r3d, attr, data[attr]) # save viewport current_viewport = save_viewport_position() # rotate viewport to test it # restore viewport apply_viewport_position(current_viewport) |