Add copy from scene menu, refactor, UI updates
This commit is contained in:
parent
c8acd91d45
commit
782e507709
@ -14,13 +14,12 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
import bpy
|
||||
from bpy.app.handlers import persistent
|
||||
from .classes.funcs import init_data, draw_workspace_menu
|
||||
from .classes.ops import WBS_OT_workspace, WBS_OT_sel_workspace, WBS_OT_move, WBS_OT_sel_all, WBS_OT_remove, WBS_OT_switch, WBS_OT_rename
|
||||
from .classes.funcs import select_all, draw_workspace_menu
|
||||
from .classes.ops import SW_OT_workspace, SW_OT_link_workspace, SW_OT_move, SW_OT_link_all, SW_OT_remove, SW_OT_switch, SW_OT_rename, SW_OT_copy_from_scene
|
||||
from .classes.topbar import TOPBAR_HT_upper_bar
|
||||
from .classes.panel import WBS_PT_select_scene_workspaces
|
||||
from .classes.menu import WBS_MT_missing_workspaces
|
||||
from .classes.prefs import WBSPreferences
|
||||
from .classes.panel import SW_PT_select_scene_workspaces
|
||||
from .classes.menu import SW_MT_missing_workspaces, SW_MT_copy_from
|
||||
from .classes.prefs import SWPreferences
|
||||
|
||||
bl_info = {
|
||||
"id": "scene_workspaces",
|
||||
@ -33,21 +32,19 @@ bl_info = {
|
||||
"blender_manifest": "blender_manifest.toml"
|
||||
}
|
||||
|
||||
@persistent
|
||||
def load_handler(dummy):
|
||||
init_data()
|
||||
|
||||
classes = [
|
||||
WBS_OT_workspace,
|
||||
WBS_OT_switch,
|
||||
WBS_OT_move,
|
||||
WBS_OT_remove,
|
||||
WBS_OT_sel_all,
|
||||
WBS_OT_sel_workspace,
|
||||
WBS_OT_rename,
|
||||
WBS_MT_missing_workspaces,
|
||||
WBS_PT_select_scene_workspaces,
|
||||
WBSPreferences,
|
||||
SW_OT_workspace,
|
||||
SW_OT_switch,
|
||||
SW_OT_move,
|
||||
SW_OT_remove,
|
||||
SW_OT_link_all,
|
||||
SW_OT_link_workspace,
|
||||
SW_OT_rename,
|
||||
SW_OT_copy_from_scene,
|
||||
SW_MT_missing_workspaces,
|
||||
SW_MT_copy_from,
|
||||
SW_PT_select_scene_workspaces,
|
||||
SWPreferences,
|
||||
TOPBAR_HT_upper_bar
|
||||
]
|
||||
|
||||
@ -58,14 +55,12 @@ def register():
|
||||
og_header = bpy.types.TOPBAR_HT_upper_bar;
|
||||
for c in classes:
|
||||
bpy.utils.register_class(c)
|
||||
bpy.app.handlers.load_post.append(load_handler)
|
||||
bpy.types.TOPBAR_MT_workspace_menu.append(draw_workspace_menu)
|
||||
bpy.types.TOPBAR_MT_workspace_menu.prepend(draw_workspace_menu)
|
||||
|
||||
def unregister():
|
||||
for c in reversed(classes):
|
||||
bpy.utils.unregister_class(c)
|
||||
bpy.utils.register_class(og_header)
|
||||
bpy.app.handlers.load_post.remove(load_handler)
|
||||
bpy.types.TOPBAR_MT_workspace_menu.remove(draw_workspace_menu)
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -1,20 +1,12 @@
|
||||
import bpy
|
||||
from .. import __package__ as base_package
|
||||
|
||||
def redraw_props():
|
||||
for area in bpy.context.window.screen.areas:
|
||||
if area.type == 'TOPBAR':
|
||||
area.tag_redraw()
|
||||
for area in bpy.context.screen.areas:
|
||||
if area.type == 'PROPERTIES':
|
||||
area.tag_redraw()
|
||||
|
||||
def has_data():
|
||||
return 'scene_workspaces' in bpy.data.scenes[bpy.context.scene.name]
|
||||
|
||||
def get_scene_workspaces():
|
||||
def get_scene_workspaces(scene = None):
|
||||
if has_data():
|
||||
return bpy.data.scenes[bpy.context.scene.name]['scene_workspaces']
|
||||
return bpy.data.scenes[scene if scene else bpy.context.scene.name]['scene_workspaces']
|
||||
else:
|
||||
return []
|
||||
|
||||
@ -23,46 +15,48 @@ def get_use_global():
|
||||
|
||||
def set_scene_workspaces(workspaces):
|
||||
bpy.data.scenes[bpy.context.scene.name]['scene_workspaces'] = workspaces
|
||||
redraw_props()
|
||||
|
||||
def init_data():
|
||||
def select_all():
|
||||
workspaces = []
|
||||
for w in bpy.data.workspaces:
|
||||
workspaces.append(w.name)
|
||||
set_scene_workspaces(workspaces)
|
||||
|
||||
def get_other_scene_names():
|
||||
return [s.name for s in bpy.data.scenes if s.name != bpy.context.scene.name]
|
||||
|
||||
def draw_workspace_ops(layout, i, text=False, name=None):
|
||||
layout.separator()
|
||||
remove = layout.operator(
|
||||
"sw.remove", text="Unlink workspace from scene" if text else "", icon='X')
|
||||
remove.index = i
|
||||
layout.separator()
|
||||
rename = layout.operator(
|
||||
"wbs.rename", text="Rename" if text else "", icon="TEXT")
|
||||
"sw.rename", text="Rename" if text else "", icon="TEXT")
|
||||
rename.current_name = name if name else bpy.context.window.workspace.name
|
||||
rename.new_name = rename.current_name
|
||||
layout.separator()
|
||||
top = layout.operator("wbs.move", text="Reorder to Front" if text else "",
|
||||
top = layout.operator("sw.move", text="Reorder to Front" if text else "",
|
||||
icon='TRIA_LEFT_BAR' if text else 'TRIA_UP_BAR')
|
||||
top.index = i
|
||||
top.top = True
|
||||
up = layout.operator("wbs.move", text="Move Left" if text else "",
|
||||
up = layout.operator("sw.move", text="Move Left" if text else "",
|
||||
icon='TRIA_LEFT' if text else 'TRIA_UP')
|
||||
up.index = i
|
||||
up.up = 1
|
||||
down = layout.operator("wbs.move", text="Move Right" if text else "",
|
||||
down = layout.operator("sw.move", text="Move Right" if text else "",
|
||||
icon='TRIA_RIGHT' if text else 'TRIA_DOWN')
|
||||
down.index = i
|
||||
down.up = -1
|
||||
bottom = layout.operator("wbs.move", text="Reorder to Back" if text else "",
|
||||
bottom = layout.operator("sw.move", text="Reorder to Back" if text else "",
|
||||
icon='TRIA_RIGHT_BAR' if text else 'TRIA_DOWN_BAR')
|
||||
bottom.index = i
|
||||
bottom.top = False
|
||||
layout.separator()
|
||||
remove = layout.operator(
|
||||
"wbs.remove", text="Unlink workspace from scene" if text else "", icon='X')
|
||||
remove.index = i
|
||||
|
||||
def draw_workspace_menu(self, context):
|
||||
layout = self.layout
|
||||
use_global = get_use_global()
|
||||
if not use_global and has_data():
|
||||
layout.separator()
|
||||
draw_workspace_ops(layout, get_scene_workspaces().index(
|
||||
context.window.workspace.name), True)
|
||||
layout.separator()
|
||||
|
@ -2,17 +2,24 @@ import bpy
|
||||
from bpy.types import Menu
|
||||
from .funcs import get_scene_workspaces
|
||||
|
||||
class WBS_MT_missing_workspaces(Menu):
|
||||
bl_label = "Link other workspaces"
|
||||
class SW_MT_copy_from(Menu):
|
||||
bl_label = "Copy and link workspaces from other scenes"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
present = False
|
||||
for s in bpy.data.scenes:
|
||||
if s.name != bpy.context.scene.name:
|
||||
layout.operator("sw.copy_from_scene", text=s.name, icon="SCENE").scene = s.name
|
||||
|
||||
class SW_MT_missing_workspaces(Menu):
|
||||
bl_label = "Link other workspaces to this scene"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
present = len(bpy.data.workspaces) > len(get_scene_workspaces())
|
||||
if present:
|
||||
layout.operator("sw.link_all", text="Link all workspaces")
|
||||
layout.separator()
|
||||
for w in bpy.data.workspaces:
|
||||
if w.name not in get_scene_workspaces():
|
||||
present = True
|
||||
layout.operator("wbs.sel_workspace", text=w.name, icon="ADD").workspace = w.name
|
||||
|
||||
if present:
|
||||
layout.separator()
|
||||
layout.operator("wbs.sel_all", text="Link all workspaces")
|
||||
layout.operator("sw.link_workspace", text=w.name, icon="ADD").workspace = w.name
|
||||
|
@ -1,25 +1,23 @@
|
||||
from .. import __package__ as base_package
|
||||
import time
|
||||
import bpy
|
||||
from bpy.types import Operator
|
||||
from bpy.props import StringProperty, BoolProperty, IntProperty
|
||||
from .topbar import TOPBAR_HT_upper_bar
|
||||
from .funcs import init_data, redraw_props, set_scene_workspaces, draw_workspace_ops, get_use_global, has_data
|
||||
from .get_workspaces import get_scene_workspaces
|
||||
import time
|
||||
from .funcs import select_all, get_scene_workspaces, set_scene_workspaces, get_use_global, has_data
|
||||
|
||||
class WBS_OT_switch(Operator):
|
||||
bl_idname = "wbs.switch"
|
||||
bl_label = "Scene Workspaces Switch"
|
||||
bl_description = "Switch between Scene Workspaces and global workspaces"
|
||||
class SW_OT_switch(Operator):
|
||||
bl_idname = "sw.switch"
|
||||
bl_label = "Scene Workspaces On/Off"
|
||||
bl_description = "Switch workspaces topbar between Scene Workspaces and default"
|
||||
|
||||
def execute(self, context):
|
||||
context.preferences.addons[base_package].preferences.use_global = not get_use_global()
|
||||
context.preferences.is_dirty = True
|
||||
return {'FINISHED'}
|
||||
|
||||
class WBS_OT_workspace(Operator):
|
||||
bl_idname = "wbs.workspace"
|
||||
bl_label = "Select Workspace"
|
||||
class SW_OT_workspace(Operator):
|
||||
bl_idname = "sw.workspace"
|
||||
bl_label = "Workspace"
|
||||
bl_description = "Make this workspace active (or remove it from the scene, if missing)"
|
||||
|
||||
workspace: StringProperty(name="workspace")
|
||||
@ -33,18 +31,19 @@ class WBS_OT_workspace(Operator):
|
||||
set_scene_workspaces(l)
|
||||
return {'FINISHED'}
|
||||
|
||||
class WBS_OT_sel_all(Operator):
|
||||
bl_idname = "wbs.sel_all"
|
||||
class SW_OT_link_all(Operator):
|
||||
bl_idname = "sw.link_all"
|
||||
bl_label = "Link all workspaces to this Scene"
|
||||
bl_description = "Link all workspaces avaliable to this scene"
|
||||
|
||||
def execute(self, context):
|
||||
init_data()
|
||||
select_all()
|
||||
return {'FINISHED'}
|
||||
|
||||
class WBS_OT_move(Operator):
|
||||
bl_idname = "wbs.move"
|
||||
class SW_OT_move(Operator):
|
||||
bl_idname = "sw.move"
|
||||
bl_label = "Reorder Workspace"
|
||||
bl_description = "Re-order this workspace in the desired location (only for this Scene)"
|
||||
bl_description = "Reorder this workspace in the desired location (only for this Scene)"
|
||||
|
||||
up: IntProperty(name="up", default=0) # 0 means using `top` for reorder back/front
|
||||
index: IntProperty(name="index", default=-1)
|
||||
@ -63,10 +62,10 @@ class WBS_OT_move(Operator):
|
||||
self.top = False
|
||||
return {'FINISHED'}
|
||||
|
||||
class WBS_OT_rename(Operator):
|
||||
bl_idname = "wbs.rename"
|
||||
class SW_OT_rename(Operator):
|
||||
bl_idname = "sw.rename"
|
||||
bl_label = "Rename workspace"
|
||||
bl_description = "Rename the current workspace"
|
||||
bl_description = "Rename the current workspace (this rename both the global workspace and the Scene workspace)"
|
||||
|
||||
current_name: StringProperty(name="Current Name", options={'HIDDEN'})
|
||||
new_name: StringProperty(
|
||||
@ -86,10 +85,10 @@ class WBS_OT_rename(Operator):
|
||||
def invoke(self, context, event):
|
||||
return context.window_manager.invoke_props_dialog(self, title=f"Rename Workspace '{self.current_name}'")
|
||||
|
||||
class WBS_OT_remove(Operator):
|
||||
bl_idname = "wbs.remove"
|
||||
class SW_OT_remove(Operator):
|
||||
bl_idname = "sw.remove"
|
||||
bl_label = "Unlink Workspace"
|
||||
bl_description = "Unlink this workspace from this Scene"
|
||||
bl_description = "Unlink this workspace from this scene (this will not delete the workspace)"
|
||||
|
||||
index: IntProperty(name="index", default=-1)
|
||||
|
||||
@ -99,10 +98,22 @@ class WBS_OT_remove(Operator):
|
||||
set_scene_workspaces(l)
|
||||
return {'FINISHED'}
|
||||
|
||||
class WBS_OT_sel_workspace(Operator):
|
||||
bl_idname = "wbs.sel_workspace"
|
||||
class SW_OT_copy_from_scene(Operator):
|
||||
bl_idname = "sw.copy_from_scene"
|
||||
bl_label = "Copy from another Scene"
|
||||
bl_description = "Copy linked workspaces from this scene"
|
||||
|
||||
scene: StringProperty(name="scene")
|
||||
|
||||
def execute(self, context):
|
||||
l = get_scene_workspaces(self.scene)
|
||||
set_scene_workspaces(l)
|
||||
return {'FINISHED'}
|
||||
|
||||
class SW_OT_link_workspace(Operator):
|
||||
bl_idname = "sw.link_workspace"
|
||||
bl_label = "Link Workspace"
|
||||
bl_description = "This is the active workspace, but it's not linked to the current Scene. Click to link"
|
||||
bl_description = "Link this workspace to this Scene"
|
||||
|
||||
workspace: StringProperty(name="workspace")
|
||||
|
||||
@ -111,9 +122,6 @@ class WBS_OT_sel_workspace(Operator):
|
||||
set_scene_workspaces([])
|
||||
if self.workspace in get_scene_workspaces():
|
||||
set_scene_workspaces([x for x in get_scene_workspaces() if x != self.workspace])
|
||||
self.report({'INFO'}, f"{self.workspace} unchecked!")
|
||||
else:
|
||||
set_scene_workspaces([*get_scene_workspaces(), self.workspace])
|
||||
self.report({'INFO'}, f"{self.workspace} checked!")
|
||||
return {'FINISHED'}
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
import bpy
|
||||
from bpy.types import Panel
|
||||
from .funcs import get_scene_workspaces, draw_workspace_ops
|
||||
|
||||
class WBS_PT_select_scene_workspaces(Panel):
|
||||
bl_idname = "wbs.select_scene_workspaces"
|
||||
class SW_PT_select_scene_workspaces(Panel):
|
||||
bl_idname = "sw.select_scene_workspaces"
|
||||
bl_label = "Scene Workspaces"
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
@ -32,11 +33,16 @@ class WBS_PT_select_scene_workspaces(Panel):
|
||||
layout.label(text="Link other workspaces")
|
||||
l = [x for x in bpy.data.workspaces if x.name not in sw]
|
||||
|
||||
box2 = layout.box().split()
|
||||
box2.label(text="All workspaces are currently linked.")
|
||||
box2 = layout.box()
|
||||
row = box2.row()
|
||||
row_count = 0
|
||||
for w in l:
|
||||
row = box2.column()
|
||||
row.operator("wbs.sel_workspace", text=w.name).workspace = w.name
|
||||
if row_count > 0 and row_count % 4 == 0:
|
||||
row = box2.row()
|
||||
row.operator("sw.link_workspace", text=w.name).workspace = w.name
|
||||
row_count += 1
|
||||
if l:
|
||||
layout.separator()
|
||||
layout.operator("wbs.sel_all")
|
||||
layout.operator("sw.link_all")
|
||||
else:
|
||||
box2.label(text="All workspaces are currently linked.")
|
||||
|
@ -3,10 +3,10 @@ from bpy.types import AddonPreferences
|
||||
from bpy.props import BoolProperty
|
||||
from .. import __package__ as base_package
|
||||
|
||||
class WBSPreferences(AddonPreferences):
|
||||
class SWPreferences(AddonPreferences):
|
||||
bl_idname = base_package
|
||||
|
||||
use_global: BoolProperty(name="Use default workspaces", description="", default=False)
|
||||
use_global: BoolProperty(name="Use default workspaces", description="Switch the workspace topbar between Scene Workspaces and the default one", default=False)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
@ -31,46 +31,70 @@ class TOPBAR_HT_upper_bar(Header):
|
||||
use_global = get_use_global()
|
||||
|
||||
if not screen.show_fullscreen:
|
||||
main_col = layout.column()
|
||||
spacer_row = main_col.row()
|
||||
spacer_row.scale_y = .33
|
||||
main_row = main_col.row()
|
||||
sy = 1.18
|
||||
sx = 1.1
|
||||
col = main_row.column()
|
||||
col.scale_y = sy
|
||||
col.operator("sw.switch", text="", emboss=False, icon="RADIOBUT_OFF" if use_global else "RADIOBUT_ON")
|
||||
if use_global:
|
||||
# Original
|
||||
layout.template_ID_tabs(window, "workspace", new="workspace.add", menu="TOPBAR_MT_workspace_menu")
|
||||
else:
|
||||
r = layout.row(align=True)
|
||||
r.scale_x = 0.89
|
||||
r.scale_y = 1.24
|
||||
r = main_row.row(align=True)
|
||||
r.scale_x = 0.87
|
||||
r.scale_y = sy
|
||||
ws = get_scene_workspaces()
|
||||
if not ws and bpy.data.workspaces:
|
||||
c = r.column()
|
||||
c.scale_x = 1.4
|
||||
c.operator("sw.link_all", text="Link all workspaces", icon="LINKED")
|
||||
active_not_here = True
|
||||
for w in ws:
|
||||
i = ws.index(w)
|
||||
active = bpy.context.window.workspace.name == w
|
||||
if active and i > 0:
|
||||
r.separator()
|
||||
ab = r.box()
|
||||
ab = ab.row(align=True)
|
||||
if active:
|
||||
col = r.column()
|
||||
col.scale_x = 1.5
|
||||
col = ab.column()
|
||||
col.scale_x = sx
|
||||
col.operator("sw.remove", text="", icon="X", emboss=False).index = i
|
||||
exist = w in [x.name for x in bpy.data.workspaces]
|
||||
ab.operator("sw.workspace", text=w, icon="NONE" if exist else "ERROR", emboss=active, depress=active).workspace = w
|
||||
if active:
|
||||
col = ab.column()
|
||||
col.scale_x = sx
|
||||
col.menu("TOPBAR_MT_workspace_menu", text="", icon="OPTIONS")
|
||||
active_not_here = False
|
||||
box = r.box()
|
||||
exist = w in [x.name for x in bpy.data.workspaces]
|
||||
box.operator("wbs.workspace", text=w, icon="NONE" if exist else "ERROR", emboss=active, depress=active).workspace = w
|
||||
if active_not_here:
|
||||
r.separator()
|
||||
col = r.column()
|
||||
col.scale_x = 1.5
|
||||
col.menu("TOPBAR_MT_workspace_menu", text="", icon="OPTIONS")
|
||||
b = r.box()
|
||||
b.scale_x = 1.5
|
||||
b.operator("wbs.sel_workspace", text=bpy.context.window.workspace.name, icon="ADD", emboss=True, depress=True).workspace = bpy.context.window.workspace.name
|
||||
r.separator()
|
||||
|
||||
r.separator()
|
||||
if [x for x in bpy.data.workspaces if x.name not in get_scene_workspaces()]:
|
||||
c = r.column()
|
||||
c.scale_x = 1.3
|
||||
c.menu("WBS_MT_missing_workspaces", text="", icon="WORKSPACE")
|
||||
r.separator()
|
||||
c.scale_x = sx
|
||||
c.menu("SW_MT_missing_workspaces", text="", icon="THREE_DOTS")
|
||||
c = r.column()
|
||||
c.scale_x = 1.3
|
||||
c.scale_x = sx
|
||||
c.operator("workspace.add", text="", icon="ADD")
|
||||
col = layout.column()
|
||||
col.scale_y = 1.24
|
||||
col.operator("wbs.switch", text="", emboss=False, icon="RADIOBUT_OFF" if use_global else "RADIOBUT_ON")
|
||||
if len(bpy.data.scenes) > 1:
|
||||
c = r.column()
|
||||
c.scale_x = sx
|
||||
c.menu("SW_MT_copy_from", text="", icon="DUPLICATE")
|
||||
|
||||
if active_not_here:
|
||||
r.separator()
|
||||
r = r.box()
|
||||
r = r.row(align=True)
|
||||
b = r.box()
|
||||
b.scale_x = sx
|
||||
b.operator("sw.link_workspace", text=f"{bpy.context.window.workspace.name} (not linked)", icon="ADD", emboss=True, depress=True).workspace = bpy.context.window.workspace.name
|
||||
col = r.box()
|
||||
col.scale_x = sx
|
||||
col.menu("TOPBAR_MT_workspace_menu", text="", icon="OPTIONS")
|
||||
# End Edited
|
||||
else:
|
||||
layout.operator("screen.back_to_previous", icon='SCREEN_BACK', text="Back to Previous")
|
||||
|
Loading…
x
Reference in New Issue
Block a user