1
$\begingroup$

I'm trying to copy the viewport camera location/orientation from one workspace to another but the region_data props like .view_location or .view_matrix between the workspaces give me the same values.

Should I somehow force update the context or what am I missing? I've tried to add context.view_layer.update() and the DRAW_WIN_SWAP-thing from the Python Gotchas between the context calls without success.

rv3d_location = context.region_data.view_location
print(rv3d_location)

context.window.workspace = bpy.data.workspaces['Layout']

# context.view_layer.update() # didn't help
# bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1) # also didn't help

rv3d_location = context.region_data.view_location
print(rv3d_location) # prints the same values
$\endgroup$
3
  • $\begingroup$ Try: context.area.tag_redraw() $\endgroup$
    – Karan
    Commented Jan 9, 2023 at 13:18
  • $\begingroup$ @Karan thank you for your reply, unfortunately it didn't work: still getting the same values $\endgroup$ Commented Jan 9, 2023 at 14:01
  • $\begingroup$ Try: rv3d_location = context.region_data.view_location.copy() $\endgroup$
    – Karan
    Commented Jan 10, 2023 at 10:40

1 Answer 1

1
$\begingroup$

The same problem here a few months ago when workspace was changed by script. The sticking point: bpy.context.window.workspace = bpy.data.workspaces[ANY] toggles the workspace not before the script is finished.

"It’s not supported to immediately refresh the UI. That happens delayed after scripts (and built-in operators) finish executing."

https://devtalk.blender.org/t/set-a-choosed-workspace-to-active/3318/3

Try:

import bpy
print("before:" , bpy.context.workspace)
bpy.context.window.workspace = bpy.data.workspaces['Layout']
print("after", bpy.context.workspace)

the same workspace will be returned.

So we need a trigger that will operate when script is finished. The message bus system is suitable for this. https://docs.blender.org/api/current/bpy.msgbus.html#module-bpy.msgbus

The script attaches an msgbus to window.workspace and saves the region_data of Scripting workspace before changed. Function msgbus_event is called after the script and sets the saved values in region_data of workspace Layout (tested 2.9.3 and 3.3.2)

import bpy

# get region_data from active ws
def get_region_data():   
    area_v3d = [a for a in bpy.context.screen.areas if a.type == 'VIEW_3D']   # area View3D
    if area_v3d:
        region_v3d = [r for r in area_v3d[0].regions if r.type == 'WINDOW'][0]   # main region
        region_data_v3d = region_v3d.data                                        # region_data
        return region_data_v3d
    else:
        print("no 3DView in workspace '%s'" % bpy.context.workspace.name)   # e.g. ws Rendering
        return None
    
# msgbus callback
def msgbus_event():
    rv3d_new = get_region_data()  # get new region_data 
    if rv3d_new:
        print_region_datas(rv3d_new)
      # set values
        rv3d_new.view_location = rv3d_old.view_location        
        rv3d_new.view_matrix = rv3d_old.view_matrix        
        # clear if only first change
        bpy.msgbus.clear_by_owner(bpy) 

# print region values
def print_region_datas(rv3d):
    print("[%s]" % bpy.context.window.workspace.name)
    print("view location:", rv3d.view_location)
    print("view matrix:", rv3d.view_matrix)    

# prevent double entries     
def register():
    # msgbus clear
    bpy.msgbus.clear_by_owner(bpy)    
    # msgbus new
    bpy.msgbus.subscribe_rna(key=(bpy.types.Window,"workspace"), owner=bpy, args=(), notify=msgbus_event,)
def unregister():
    bpy.msgbus.clear_by_owner(bpy)
if __name__ == "__main__":
    register()

# testcall from ws Scripting
global rv3d_old                # available for msgbus_event
rv3d_old = get_region_data()   # region_data Scripting
print_region_datas(rv3d_old) 
bpy.context.window.workspace = bpy.data.workspaces['Layout'] # change ws

enter image description here

$\endgroup$
1
  • $\begingroup$ Awesome — thank you for the explanation and the solution! $\endgroup$ Commented Jan 12, 2023 at 17:01

You must log in to answer this question.

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