Refactor, Add UI preferences, UI updates

This commit is contained in:
Francesco Bellini 2024-09-07 18:34:41 +02:00
parent 782e507709
commit 41960910ee
7 changed files with 59 additions and 20 deletions

View File

@ -26,7 +26,7 @@ bl_info = {
"name": "Scene Workspaces", "name": "Scene Workspaces",
"tagline": "Filter and reorder workspaces independently for each scene", "tagline": "Filter and reorder workspaces independently for each scene",
"blender": (4, 2, 0), "blender": (4, 2, 0),
"location": "Workspaces", "location": "Workspaces topbar, Properties > Scene",
"category": ["System", "User Interface", "Scene"], "category": ["System", "User Interface", "Scene"],
"support": "COMMUNITY", "support": "COMMUNITY",
"blender_manifest": "blender_manifest.toml" "blender_manifest": "blender_manifest.toml"

View File

@ -10,8 +10,20 @@ def get_scene_workspaces(scene = None):
else: else:
return [] return []
def prefs():
return bpy.context.preferences.addons[base_package].preferences
def get_use_global(): def get_use_global():
return bpy.context.preferences.addons[base_package].preferences.use_global return prefs().use_global
def get_show_switch():
return prefs().show_switch
def get_active_spacing():
return prefs().active_spacing
def get_quick_unlink():
return prefs().quick_unlink
def set_scene_workspaces(workspaces): def set_scene_workspaces(workspaces):
bpy.data.scenes[bpy.context.scene.name]['scene_workspaces'] = workspaces bpy.data.scenes[bpy.context.scene.name]['scene_workspaces'] = workspaces

View File

@ -9,7 +9,7 @@ class SW_MT_copy_from(Menu):
layout = self.layout layout = self.layout
for s in bpy.data.scenes: for s in bpy.data.scenes:
if s.name != bpy.context.scene.name: if s.name != bpy.context.scene.name:
layout.operator("sw.copy_from_scene", text=s.name, icon="SCENE").scene = s.name layout.operator("sw.copy_from_scene", text=s.name, icon="SCENE_DATA").scene = s.name
class SW_MT_missing_workspaces(Menu): class SW_MT_missing_workspaces(Menu):
bl_label = "Link other workspaces to this scene" bl_label = "Link other workspaces to this scene"

View File

@ -3,15 +3,15 @@ import time
import bpy import bpy
from bpy.types import Operator from bpy.types import Operator
from bpy.props import StringProperty, BoolProperty, IntProperty from bpy.props import StringProperty, BoolProperty, IntProperty
from .funcs import select_all, get_scene_workspaces, set_scene_workspaces, get_use_global, has_data from .funcs import select_all, get_scene_workspaces, set_scene_workspaces, get_use_global, has_data, prefs
class SW_OT_switch(Operator): class SW_OT_switch(Operator):
bl_idname = "sw.switch" bl_idname = "sw.switch"
bl_label = "Scene Workspaces On/Off" bl_label = "Show/Hide Scene Workspaces"
bl_description = "Switch workspaces topbar between Scene Workspaces and default" bl_description = "Switch workspaces topbar between Scene Workspaces and default"
def execute(self, context): def execute(self, context):
context.preferences.addons[base_package].preferences.use_global = not get_use_global() prefs().use_global = not get_use_global()
context.preferences.is_dirty = True context.preferences.is_dirty = True
return {'FINISHED'} return {'FINISHED'}
@ -113,10 +113,13 @@ class SW_OT_copy_from_scene(Operator):
class SW_OT_link_workspace(Operator): class SW_OT_link_workspace(Operator):
bl_idname = "sw.link_workspace" bl_idname = "sw.link_workspace"
bl_label = "Link Workspace" bl_label = "Link Workspace"
bl_description = "Link this workspace to this Scene"
workspace: StringProperty(name="workspace") workspace: StringProperty(name="workspace")
@classmethod
def description(cls, context, props):
return "This is the active workspace, but it's not linked to this scene. Click to link" if props.workspace == bpy.context.window.workspace.name else "Link this workspace to this Scene"
def execute(self, context): def execute(self, context):
if not has_data(): if not has_data():
set_scene_workspaces([]) set_scene_workspaces([])

View File

@ -8,6 +8,7 @@ class SW_PT_select_scene_workspaces(Panel):
bl_space_type = 'PROPERTIES' bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW' bl_region_type = 'WINDOW'
bl_context = "scene" bl_context = "scene"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
@ -17,6 +18,7 @@ class SW_PT_select_scene_workspaces(Panel):
box = layout.box() box = layout.box()
if not sw: if not sw:
box.label(text="There are no workspaces linked right now...") box.label(text="There are no workspaces linked right now...")
box.operator("sw.link_all")
else: else:
i = 0 i = 0
for w in sw: for w in sw:

View File

@ -7,8 +7,17 @@ class SWPreferences(AddonPreferences):
bl_idname = base_package bl_idname = base_package
use_global: BoolProperty(name="Use default workspaces", description="Switch the workspace topbar between Scene Workspaces and the default one", default=False) use_global: BoolProperty(name="Use default workspaces", description="Switch the workspace topbar between Scene Workspaces and the default one", default=False)
show_switch: BoolProperty(name="Show Switch", description="Show/Hide the switch button next to the workspaces topbar. Useful for quickly lookup the original workspaces topbar", default=True)
active_spacing: BoolProperty(name="Active workspace spacing", description="Add space around the active workspace", default=True)
quick_unlink: BoolProperty(name="Show Quick Unlink", description="Show/Hide the unlink button at left of the active workspace", default=True)
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
layout.prop(self, "use_global") layout.prop(self, "use_global")
layout.prop(self, "show_switch")
box = layout.box()
box.label("UI Options")
box.prop(self, "quick_unlink")
box.prop(self, "active_spacing")

View File

@ -1,7 +1,7 @@
from .. import __package__ as base_package from .. import __package__ as base_package
import bpy import bpy
from bpy.types import Header, Panel from bpy.types import Header, Panel
from .funcs import get_scene_workspaces, get_use_global from .funcs import get_scene_workspaces, get_use_global, get_show_switch, get_quick_unlink, get_active_spacing
# Ref TOPBAR_HT_upper_bar https://projects.blender.org/blender/blender/src/commit/2204157a2c9fc926643b0e39968602c750d9b5e6/scripts/startup/bl_ui/space_topbar.py#L14 # Ref TOPBAR_HT_upper_bar https://projects.blender.org/blender/blender/src/commit/2204157a2c9fc926643b0e39968602c750d9b5e6/scripts/startup/bl_ui/space_topbar.py#L14
class TOPBAR_HT_upper_bar(Header): class TOPBAR_HT_upper_bar(Header):
@ -29,6 +29,8 @@ class TOPBAR_HT_upper_bar(Header):
# Edited # Edited
use_global = get_use_global() use_global = get_use_global()
quick_unlink = get_quick_unlink()
active_spacing = get_active_spacing()
if not screen.show_fullscreen: if not screen.show_fullscreen:
main_col = layout.column() main_col = layout.column()
@ -36,10 +38,11 @@ class TOPBAR_HT_upper_bar(Header):
spacer_row.scale_y = .33 spacer_row.scale_y = .33
main_row = main_col.row() main_row = main_col.row()
sy = 1.18 sy = 1.18
sx = 1.1 sx = 1.12
col = main_row.column() if get_show_switch():
col.scale_y = sy col = main_row.column()
col.operator("sw.switch", text="", emboss=False, icon="RADIOBUT_OFF" if use_global else "RADIOBUT_ON") # Show/Hide Custom Topbar
col.operator("sw.switch", text="", emboss=False, icon="CHECKBOX_DEHLT" if use_global else "CHECKBOX_HLT")
if use_global: if use_global:
# Original # Original
layout.template_ID_tabs(window, "workspace", new="workspace.add", menu="TOPBAR_MT_workspace_menu") layout.template_ID_tabs(window, "workspace", new="workspace.add", menu="TOPBAR_MT_workspace_menu")
@ -48,6 +51,7 @@ class TOPBAR_HT_upper_bar(Header):
r.scale_x = 0.87 r.scale_x = 0.87
r.scale_y = sy r.scale_y = sy
ws = get_scene_workspaces() ws = get_scene_workspaces()
# Link all (with no linked workspaces)
if not ws and bpy.data.workspaces: if not ws and bpy.data.workspaces:
c = r.column() c = r.column()
c.scale_x = 1.4 c.scale_x = 1.4
@ -56,42 +60,51 @@ class TOPBAR_HT_upper_bar(Header):
for w in ws: for w in ws:
i = ws.index(w) i = ws.index(w)
active = bpy.context.window.workspace.name == w active = bpy.context.window.workspace.name == w
if active and i > 0: if active and i > 0 and active_spacing:
r.separator() r.separator()
ab = r.box() ab = r.box()
ab = ab.row(align=True) ab = ab.row(align=True)
if active: # Workspace unlink
if active and quick_unlink:
col = ab.column() col = ab.column()
col.scale_x = sx col.scale_x = sx
col.operator("sw.remove", text="", icon="X", emboss=False).index = i col.operator("sw.remove", text="", icon="X", emboss=False).index = i
exist = w in [x.name for x in bpy.data.workspaces] exist = w in [x.name for x in bpy.data.workspaces]
# Workspace
ab.operator("sw.workspace", text=w, icon="NONE" if exist else "ERROR", emboss=active, depress=active).workspace = w ab.operator("sw.workspace", text=w, icon="NONE" if exist else "ERROR", emboss=active, depress=active).workspace = w
# Active workspace options
if active: if active:
col = ab.column() col = ab.column()
col.scale_x = sx col.scale_x = sx
col.menu("TOPBAR_MT_workspace_menu", text="", icon="OPTIONS") col.menu("TOPBAR_MT_workspace_menu", text="", icon="OPTIONS")
active_not_here = False active_not_here = False
r.separator() if active_spacing:
r.separator()
# Link other workspaces
if [x for x in bpy.data.workspaces if x.name not in get_scene_workspaces()]: if [x for x in bpy.data.workspaces if x.name not in get_scene_workspaces()]:
c = r.column() c = r.column()
c.scale_x = sx c.scale_x = sx
c.menu("SW_MT_missing_workspaces", text="", icon="THREE_DOTS") c.menu("SW_MT_missing_workspaces", text="", icon="WORKSPACE")
c = r.column() # Duplicate linked workspaces from other scenes
c.scale_x = sx
c.operator("workspace.add", text="", icon="ADD")
if len(bpy.data.scenes) > 1: if len(bpy.data.scenes) > 1:
c = r.column() c = r.column()
c.scale_x = sx c.scale_x = sx
c.menu("SW_MT_copy_from", text="", icon="DUPLICATE") c.menu("SW_MT_copy_from", text="", icon="DUPLICATE")
# Original Add Workspace menu
c = r.column()
c.scale_x = sx
c.operator("workspace.add", text="", icon="ADD")
# Active (but not linked) workspace
if active_not_here: if active_not_here:
r.separator() r.separator()
r = r.box() r = r.box()
r = r.row(align=True) r = r.row(align=True)
b = r.box() b = r.box()
b.scale_x = sx 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 b.operator("sw.link_workspace", text=f"{bpy.context.window.workspace.name} (link)", icon="LINKED", emboss=True, depress=True).workspace = bpy.context.window.workspace.name
# Active workspace options
col = r.box() col = r.box()
col.scale_x = sx col.scale_x = sx
col.menu("TOPBAR_MT_workspace_menu", text="", icon="OPTIONS") col.menu("TOPBAR_MT_workspace_menu", text="", icon="OPTIONS")