Compare commits
21 Commits
Author | SHA1 | Date | |
---|---|---|---|
ecc418f196 | |||
cc074b3fd5 | |||
be6456975d | |||
82701bb3b0 | |||
facd4240fd | |||
397a20c721 | |||
93b6b61811 | |||
95e94a7457 | |||
186199ee17 | |||
0193d28d5f | |||
401e61b966 | |||
e194139ddb | |||
1273ab83ef | |||
369f350e02 | |||
14fa397c1b | |||
ea2c0fa883 | |||
017f15bf98 | |||
18b37319bb | |||
57b9262780 | |||
e887322e5a | |||
0a943132bc |
20
CHANGELOG.md
@ -1,3 +1,20 @@
|
|||||||
|
## v1.1.1
|
||||||
|
|
||||||
|
- Fix partial select all
|
||||||
|
|
||||||
|
## v1.1.0
|
||||||
|
|
||||||
|
- Auto initialize Scene Workspaces if empty (on load, on scene change)
|
||||||
|
- Auto order Scene Workspaces, on initialization
|
||||||
|
*Only when using workspaces from one of the 5 default Blender's templates*
|
||||||
|
- Update `Properties > Scene > Scene Workspaces` panel
|
||||||
|
*Rename, unlink and reorder buttons are now based on the active element, for better UX.*
|
||||||
|
- New preferences:
|
||||||
|
1) `Show only with multiple scenes` *(default: false)*
|
||||||
|
*Show the custom topbar and the checkbox (if enabled) only if the project has multiple scenes. Basically, Scene Workspaces disappear as long as you have one scene only.*
|
||||||
|
2) `Auto initialize Scene Workspaces` *(default: true)*
|
||||||
|
*When active, automatically initialize (and for special cases, order) Scene Workspaces when empty (on load, on scene change). All avaliable workspaces are added.*
|
||||||
|
|
||||||
## v1.0.0
|
## v1.0.0
|
||||||
|
|
||||||
This is the first official version of the extension.
|
This is the first official version of the extension.
|
||||||
@ -5,10 +22,11 @@ This is the first official version of the extension.
|
|||||||
Current features:
|
Current features:
|
||||||
|
|
||||||
- Custom workspaces topbar (only showing workspaces linked to the current scene)
|
- Custom workspaces topbar (only showing workspaces linked to the current scene)
|
||||||
- Custom Property for Scenes listing the linked workspaces (saved in .blend file)
|
- Custom Property for Scenes listing the linked workspaces (saved in .blend file)
|
||||||
- Add, Remove, Reorder linked workspace, scene by scene
|
- Add, Remove, Reorder linked workspace, scene by scene
|
||||||
- Rename workspace
|
- Rename workspace
|
||||||
*This will rename the workspace globally, and also every custom property of the scene that use it.*
|
*This will rename the workspace globally, and also every custom property of the scene that use it.*
|
||||||
|
- Previous/Next Workspace (following scene workspaces order)
|
||||||
- Menu to copy the linked workspaces from other scenes
|
- Menu to copy the linked workspaces from other scenes
|
||||||
- Menu to link other workspaces (the unlinked ones)
|
- Menu to link other workspaces (the unlinked ones)
|
||||||
- Panel in `Properties > Scene > Scene Workspaces`, to manage, reorder, rename linked workspaces for the current scene
|
- Panel in `Properties > Scene > Scene Workspaces`, to manage, reorder, rename linked workspaces for the current scene
|
||||||
|
65
README.md
@ -8,30 +8,42 @@
|
|||||||
|
|
||||||
Basically, you can decide which workspace you want to link to each scene.
|
Basically, you can decide which workspace you want to link to each scene.
|
||||||
|
|
||||||
> This is possible thanks to a custom property at scene level (which is saved with your .blend file).
|
> Scene Workspaces is based on simple custom properties at scene level.
|
||||||
> *This property simply list names of the linked workspaces, in the correct order.*
|
|
||||||
|
|
||||||
---
|
Scene Workspaces can be particularly useful in projects with multiple scenes with different needs/purpose.
|
||||||
|
|
||||||
|
### Make yourself comfortable
|
||||||
|
|
||||||
You can customize Scene Workspaces from add-on preferences:
|
You can customize Scene Workspaces from add-on preferences:
|
||||||
|
|
||||||
- **Show Switch**
|
- **Show only with multiple scenes** *(default: off)*
|
||||||
*When active, shows a checkbox to switch between Scene Workspaces and the default topbar.*
|
*Show the topbar (and eventually the checkbox) only when the project has multiple scenes.
|
||||||
|
Basically, Scene Workspaces disappear as long as you have one scene only.*
|
||||||
|
- **Auto initialize Scene Workspaces** *(default: on)*
|
||||||
|
*Automatically add all available workspaces to the current scene, if empty.
|
||||||
|
If available workspaces match one of the 5 default templates, they will be automatically ordered on intialization. Otherwise, workspaces will be ordered alphabetically.*
|
||||||
|
> This limitation is due to the fact that Scene Workspace can't access the global workspaces order.
|
||||||
|
> Use the panel `Properties > Scene > Scene Workspaces`, or the workspace menu to reorder your workspaces.
|
||||||
|
- **Show Checkbox** *(default: on)*
|
||||||
|
*When active, shows a checkbox to switch between Scene Workspaces and the default topbar.*
|
||||||

|

|
||||||
*This checkbox will directly affect the next preference.*
|
*This checkbox will directly affect the next preference.*
|
||||||
- **Use Scene Workspaces topbar**
|
- **Use Scene Workspaces topbar** *(default: on)*
|
||||||
*Scene Workspaces topbar.*
|
*Scene Workspaces topbar.*
|
||||||

|

|
||||||
*Default workspaces topbar.*
|
*Default workspaces topbar.*
|
||||||

|

|
||||||
- **Use Compact Mode** *(default ON)*
|
- **Use Compact Mode** *(default: on)*
|
||||||
*Compact Mode ON*
|
*Also avaliable from the workspace menu.*
|
||||||
|
*Compact Mode ON*
|
||||||

|

|
||||||
*Compact Mode OFF*
|
*Compact Mode OFF*
|
||||||

|

|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### Topbar menus
|
||||||
|
|
||||||
What you can usually to do by right-clicking on a workspace (and more) it's avaliable by clicking the near options button.
|
What you can usually to do by right-clicking on a workspace (and more) it's avaliable by clicking the near options button.
|
||||||
|
|
||||||

|

|
||||||
@ -41,22 +53,21 @@ The first options are the ones from Scene Workspaces:
|
|||||||
- **Toggle Compact Mode** *(preference)*
|
- **Toggle Compact Mode** *(preference)*
|
||||||
- **Unlink workspace from scene**
|
- **Unlink workspace from scene**
|
||||||
- **Rename** *(for all scenes)*
|
- **Rename** *(for all scenes)*
|
||||||
- **Reorder to front** *(only for these scene)*
|
- **Reorder to front** *(only for this scene)*
|
||||||
- **Move left** *(only for these scene)*
|
- **Move left** *(only for this scene)*
|
||||||
- **Move right** *(only for these scene)*
|
- **Move right** *(only for this scene)*
|
||||||
- **Reorder to back** *(only for these scene)*
|
- **Reorder to back** *(only for this scene)*
|
||||||
- **Previous workspace** *(using scene order) `Shift + Ctrl + Page Up`*
|
- **Previous workspace** *(using scene order) `Shift + Ctrl + Page Up`*
|
||||||
- **Next Workspace** *(using scene order) `Shift + Ctrl + Page Down`*
|
- **Next Workspace** *(using scene order) `Shift + Ctrl + Page Down`*
|
||||||
|
|
||||||
And then, starting from `Duplicate`, you'll find the default workspace options.
|
And then you'll find the default workspace options.
|
||||||
|
|
||||||
> **Note**
|
> **Note**
|
||||||
> Default options like `Reorder to Front`, `Reorder to Back` will only affect the global workspaces, and not the Scene Workspaces topbar.
|
> Default options like `Reorder to Front`, `Reorder to Back` will only affect the global workspaces, and not the Scene Workspaces topbar.
|
||||||
*Instead, use the ones marked with `(scene only)`.*
|
> *Instead, use the ones marked with `(scene only)` or use the panel instead.*
|
||||||
>
|
>
|
||||||
> Also, default options `Previous Workspace` and `Next Workspace` functions will follow the global workspaces order, and not the scene order.
|
> Also, default options `Previous Workspace` and `Next Workspace` will follow the global workspaces order, and not the scene order.
|
||||||
*Instead, use the ones marked with `(scene)`.*
|
> *Instead, use the ones marked with `(scene)` or the relative shortcuts (default ones + Shift).*
|
||||||
> Be sure to use the Scene Workspaces relative options, instead.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -72,21 +83,29 @@ You can also copy the linked workspaces from another scene, using the menu with
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
You can also reorder, rename, link and unlink the Scene Workspaces, using the panel `Properties > Scene > Scene Workspaces`.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### Panel Management
|
||||||
|
|
||||||
|
You can always reorder, rename, link and unlink the Scene Workspaces, using the panel `Properties > Scene > Scene Workspaces`.
|
||||||
|
*At the top, you can select and reorder, rename or unlink any workspace.*
|
||||||
|
*At the bottom, you can link the missing workspaces to the current scene.*
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Templates
|
||||||
|
|
||||||
|
You can use the add-on [Custom Templates](https://extensions.blender.org/add-ons/custom-templates/) to prepare templates with your Scene Workspaces already configured.
|
||||||
|
|
||||||
## Why this add-on?
|
## Why this add-on?
|
||||||
|
|
||||||
In Blender, workspaces are common across scenes.
|
In Blender, workspaces are common across scenes.
|
||||||
|
|
||||||
You may need different workspaces in different scenes, depending on the purpose of the scene.
|
At the same time, you may need different workspaces in different scenes, depending on the purpose of the scene.
|
||||||
|
|
||||||
*For example, you may want a scene with workspaces optimized for modelling and another Scene optimized for Video Editing, in the same project.*
|
*For example, you may want a scene with workspaces optimized for modelling and another Scene optimized for Video Editing, in the same project.*
|
||||||
|
|
||||||
**Scene Workspaces** make this possibile with the custom topbar and a custom property for each scene.
|
**Scene Workspaces** make this possible with the custom topbar and a custom property for each scene.
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
96
README_EXT.md
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
**Scene Workspaces** creates an alternative workspaces topbar, allowing you to filter and reorder workspaces, scene by scene.
|
||||||
|
|
||||||
|
Basically, you can decide which workspace you want to link to each scene.
|
||||||
|
|
||||||
|
> Scene Workspaces is based on simple custom properties at scene level.
|
||||||
|
|
||||||
|
Scene Workspaces can be particularly useful in projects with multiple scenes with different needs/purpose.
|
||||||
|
|
||||||
|
### Make yourself comfortable
|
||||||
|
|
||||||
|
You can customize Scene Workspaces from add-on preferences:
|
||||||
|
|
||||||
|
- **Show only with multiple scenes** *(default: off)*
|
||||||
|
*Show the topbar (and eventually the checkbox) only when the project has multiple scenes.
|
||||||
|
Basically, Scene Workspaces disappear as long as you have one scene only.*
|
||||||
|
- **Auto initialize Scene Workspaces** *(default: on)*
|
||||||
|
*Automatically add all available workspaces to the current scene, if empty.
|
||||||
|
If available workspaces match one of the 5 default templates, they will be automatically ordered on initialization. Otherwise, workspaces will be ordered alphabetically.*
|
||||||
|
- **Show Checkbox** *(default: on)*
|
||||||
|
*When active, shows a checkbox to switch between Scene Workspaces and the default topbar.*
|
||||||
|
*This checkbox will directly affect the next preference.*
|
||||||
|
- **Use Scene Workspaces topbar** *(default: on)*
|
||||||
|
*Switch between Scene Workspaces topbar and the default topbar.*
|
||||||
|
- **Use Compact Mode** *(default: on)*
|
||||||
|
*Also avaliable from the workspace menu.*
|
||||||
|
*Compact Mode ON*
|
||||||
|

|
||||||
|
*Compact Mode OFF*
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Topbar menus
|
||||||
|
|
||||||
|
What you can usually to do by right-clicking on a workspace (and more) it's avaliable by clicking the near options button.
|
||||||
|
|
||||||
|
The first options are the ones from Scene Workspaces:
|
||||||
|
|
||||||
|
- **Toggle Compact Mode** *(preference)*
|
||||||
|
- **Unlink workspace from scene**
|
||||||
|
- **Rename** *(for all scenes)*
|
||||||
|
- **Reorder to front** *(only for this scene)*
|
||||||
|
- **Move left** *(only for this scene)*
|
||||||
|
- **Move right** *(only for this scene)*
|
||||||
|
- **Reorder to back** *(only for this scene)*
|
||||||
|
- **Previous workspace** *(using scene order) `Shift + Ctrl + Page Up`*
|
||||||
|
- **Next Workspace** *(using scene order) `Shift + Ctrl + Page Down`*
|
||||||
|
|
||||||
|
> **Note**
|
||||||
|
> Default options like `Reorder to Front`, `Reorder to Back` will only affect the global workspaces, and not the Scene Workspaces topbar.
|
||||||
|
> *Instead, use the ones marked with `(scene only)` or use the panel instead.*
|
||||||
|
>
|
||||||
|
> Also, default options `Previous Workspace` and `Next Workspace` will follow the global workspaces order, and not the scene order.
|
||||||
|
> *Instead, use the ones marked with `(scene)` or the relative shortcuts (default ones + Shift).*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
You can link other workspaces to the current scene, using the menu with the workspace icon:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
or by clicking the active workspace, if it's not currently linked
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
You can also copy the linked workspaces from another scene, using the menu with the duplicate icon:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Panel Management
|
||||||
|
|
||||||
|
You can always reorder, rename, link and unlink the Scene Workspaces, using the panel `Properties > Scene > Scene Workspaces`.
|
||||||
|
*At the top, you can select and reorder, rename or unlink any workspace.*
|
||||||
|
*At the bottom, you can link the missing workspaces to the current scene.*
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Templates
|
||||||
|
|
||||||
|
You can use the add-on [Custom Templates](https://extensions.blender.org/add-ons/custom-templates/) to prepare templates with your Scene Workspaces already configured.
|
||||||
|
|
||||||
|
## Why this add-on?
|
||||||
|
|
||||||
|
In Blender, workspaces are common across scenes.
|
||||||
|
|
||||||
|
At the same time, you may need different workspaces in different scenes, depending on the purpose of the scene.
|
||||||
|
|
||||||
|
*For example, you may want a scene with workspaces optimized for modelling and another Scene optimized for Video Editing, in the same project.*
|
||||||
|
|
||||||
|
**Scene Workspaces** make this possible with the custom topbar and a custom property for each scene.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
For more info, checkout the project's [README](https://projects.blender.org/Francesco-Bellini/scene_workspaces_addon/src/branch/main/README.md).
|
@ -14,8 +14,9 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
import bpy
|
import bpy
|
||||||
from .sw.funcs import select_all, workspace_menu, assign_shortcuts, remove_shortcuts
|
from bpy.app.handlers import persistent
|
||||||
from .sw.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, SW_OT_activate
|
from .sw.funcs import select_all, workspace_menu, assign_shortcuts, remove_shortcuts, has_data
|
||||||
|
from .sw.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, SW_OT_activate, SW_OT_select
|
||||||
from .sw.topbar import TOPBAR_HT_upper_bar
|
from .sw.topbar import TOPBAR_HT_upper_bar
|
||||||
from .sw.panel import SW_PT_select_scene_workspaces
|
from .sw.panel import SW_PT_select_scene_workspaces
|
||||||
from .sw.menu import SW_MT_missing_workspaces, SW_MT_copy_from
|
from .sw.menu import SW_MT_missing_workspaces, SW_MT_copy_from
|
||||||
@ -34,6 +35,7 @@ bl_info = {
|
|||||||
|
|
||||||
classes = [
|
classes = [
|
||||||
SW_OT_workspace,
|
SW_OT_workspace,
|
||||||
|
SW_OT_select,
|
||||||
SW_OT_switch,
|
SW_OT_switch,
|
||||||
SW_OT_move,
|
SW_OT_move,
|
||||||
SW_OT_remove,
|
SW_OT_remove,
|
||||||
@ -49,6 +51,22 @@ classes = [
|
|||||||
TOPBAR_HT_upper_bar
|
TOPBAR_HT_upper_bar
|
||||||
]
|
]
|
||||||
|
|
||||||
|
last_scene = None
|
||||||
|
@persistent
|
||||||
|
def on_scene(scene):
|
||||||
|
global last_scene
|
||||||
|
last_scene = bpy.context.scene.name
|
||||||
|
if not has_data():
|
||||||
|
select_all()
|
||||||
|
@persistent
|
||||||
|
def on_frame(scene):
|
||||||
|
# Avoid simple playback or frame change (only scene change)
|
||||||
|
global last_scene
|
||||||
|
if bpy.context.scene.name != last_scene:
|
||||||
|
last_scene = bpy.context.scene.name
|
||||||
|
if not has_data():
|
||||||
|
select_all()
|
||||||
|
|
||||||
og_header = None;
|
og_header = None;
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
@ -57,7 +75,8 @@ def register():
|
|||||||
for c in classes:
|
for c in classes:
|
||||||
bpy.utils.register_class(c)
|
bpy.utils.register_class(c)
|
||||||
bpy.types.TOPBAR_MT_workspace_menu.prepend(workspace_menu)
|
bpy.types.TOPBAR_MT_workspace_menu.prepend(workspace_menu)
|
||||||
|
bpy.app.handlers.frame_change_post.append(on_frame)
|
||||||
|
bpy.app.handlers.load_post.append(on_scene)
|
||||||
assign_shortcuts()
|
assign_shortcuts()
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
@ -65,7 +84,8 @@ def unregister():
|
|||||||
bpy.utils.unregister_class(c)
|
bpy.utils.unregister_class(c)
|
||||||
bpy.utils.register_class(og_header)
|
bpy.utils.register_class(og_header)
|
||||||
bpy.types.TOPBAR_MT_workspace_menu.remove(workspace_menu)
|
bpy.types.TOPBAR_MT_workspace_menu.remove(workspace_menu)
|
||||||
|
bpy.app.handlers.frame_change_post.remove(on_frame)
|
||||||
|
bpy.app.handlers.load_post.remove(on_scene)
|
||||||
remove_shortcuts()
|
remove_shortcuts()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
schema_version = "1.0.0"
|
schema_version = "1.0.0"
|
||||||
id = "scene_workspaces"
|
id = "scene_workspaces"
|
||||||
version = "1.0.0"
|
version = "1.1.1"
|
||||||
name = "Scene Workspaces"
|
name = "Scene Workspaces"
|
||||||
tagline = "Filter and sort your workspaces, scene by scene"
|
tagline = "Filter and sort your workspaces, scene by scene"
|
||||||
maintainer = "Francesco Bellini <doc.open.dev@gmail.com>"
|
maintainer = "Francesco Bellini <doc.open.dev@gmail.com>"
|
||||||
|
@ -1,21 +1,45 @@
|
|||||||
from .. import __package__ as base_package
|
from .. import __package__ as base_package
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
def has_data():
|
prop_name = "scene_workspaces";
|
||||||
return 'scene_workspaces' in bpy.data.scenes[bpy.context.scene.name]
|
prop_i_name = "scene_workspaces_active";
|
||||||
|
|
||||||
|
def_templates_w_order = [
|
||||||
|
['Layout','Modeling','Sculpting','UV Editing','Texture Paint','Shading','Animation','Rendering','Compositing','Geometry Nodes','Scripting'],
|
||||||
|
['2D Animation','2D Full Canvas','Compositing','Rendering'],
|
||||||
|
['Sculpting','Shading'],
|
||||||
|
['Motion Tracking','Masking','Compositing','Rendering'],
|
||||||
|
['Video Editing','Rendering']
|
||||||
|
]
|
||||||
|
|
||||||
|
def has_data(scene = None, prop = prop_name):
|
||||||
|
return prop in bpy.data.scenes[scene if scene else bpy.context.scene.name]
|
||||||
|
|
||||||
def get_scene_workspaces(scene = None):
|
def get_scene_workspaces(scene = None):
|
||||||
if has_data():
|
if has_data(scene):
|
||||||
return bpy.data.scenes[scene if scene else bpy.context.scene.name]['scene_workspaces']
|
return bpy.data.scenes[scene if scene else bpy.context.scene.name][prop_name]
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
def get_active(scene = None):
|
||||||
|
if has_data(scene, prop_i_name):
|
||||||
|
i = bpy.data.scenes[scene if scene else bpy.context.scene.name][prop_i_name]
|
||||||
|
return i if i else 0
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def set_active(val = 0):
|
||||||
|
bpy.data.scenes[bpy.context.scene.name][prop_i_name] = val
|
||||||
|
|
||||||
def prefs():
|
def prefs():
|
||||||
return bpy.context.preferences.addons[base_package].preferences
|
return bpy.context.preferences.addons[base_package].preferences
|
||||||
|
|
||||||
def get_use_topbar():
|
def get_use_topbar():
|
||||||
return prefs().use_topbar
|
return prefs().use_topbar
|
||||||
|
|
||||||
|
def get_only_with_multiple():
|
||||||
|
return prefs().only_with_multiple_scenes
|
||||||
|
|
||||||
def get_switch():
|
def get_switch():
|
||||||
return prefs().switch
|
return prefs().switch
|
||||||
|
|
||||||
@ -23,12 +47,30 @@ def get_compact():
|
|||||||
return prefs().compact
|
return prefs().compact
|
||||||
|
|
||||||
def set_scene_workspaces(workspaces, scene = None):
|
def set_scene_workspaces(workspaces, scene = None):
|
||||||
bpy.data.scenes[scene if scene else bpy.context.scene.name]['scene_workspaces'] = workspaces
|
s = scene if scene else bpy.context.scene.name
|
||||||
|
bpy.data.scenes[s][prop_name] = workspaces
|
||||||
|
if not get_active():
|
||||||
|
set_active()
|
||||||
|
|
||||||
|
def workspaces_match_template():
|
||||||
|
match = False
|
||||||
|
templates = []
|
||||||
|
for templs in def_templates_w_order:
|
||||||
|
if set([w.name for w in bpy.data.workspaces]) == set(templs):
|
||||||
|
match = True
|
||||||
|
templates = templs
|
||||||
|
break
|
||||||
|
return match, templates
|
||||||
|
|
||||||
def select_all():
|
def select_all():
|
||||||
workspaces = []
|
workspaces = get_scene_workspaces()
|
||||||
for w in bpy.data.workspaces:
|
match, templates = workspaces_match_template()
|
||||||
workspaces.append(w.name)
|
if match and not workspaces:
|
||||||
|
workspaces = templates
|
||||||
|
else:
|
||||||
|
for w in bpy.data.workspaces:
|
||||||
|
if w.name not in workspaces:
|
||||||
|
workspaces.append(w.name)
|
||||||
set_scene_workspaces(workspaces)
|
set_scene_workspaces(workspaces)
|
||||||
|
|
||||||
def get_other_scene_names():
|
def get_other_scene_names():
|
||||||
@ -54,11 +96,10 @@ def remove_shortcuts():
|
|||||||
wm = bpy.context.window_manager
|
wm = bpy.context.window_manager
|
||||||
km = wm.keyconfigs.addon.keymaps.new(name='Window', space_type='EMPTY')
|
km = wm.keyconfigs.addon.keymaps.new(name='Window', space_type='EMPTY')
|
||||||
for kmi in km.keymap_items:
|
for kmi in km.keymap_items:
|
||||||
if kmi.idname in ['sw.activate', 'sw.move'] :
|
if kmi.idname == "sw.activate":
|
||||||
km.keymap_items.remove(kmi)
|
km.keymap_items.remove(kmi)
|
||||||
|
|
||||||
def workspace_ops(layout, i, menu_mode=False, name=None):
|
def workspace_ops(layout, i, menu_mode=False, name=None):
|
||||||
layout.separator()
|
|
||||||
if menu_mode:
|
if menu_mode:
|
||||||
layout.prop(prefs(), "compact", text="Compact Mode")
|
layout.prop(prefs(), "compact", text="Compact Mode")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
@ -66,9 +107,8 @@ def workspace_ops(layout, i, menu_mode=False, name=None):
|
|||||||
remove = l.operator(
|
remove = l.operator(
|
||||||
"sw.remove", text="Unlink workspace from scene" if menu_mode else "", icon='X')
|
"sw.remove", text="Unlink workspace from scene" if menu_mode else "", icon='X')
|
||||||
remove.index = i
|
remove.index = i
|
||||||
if menu_mode:
|
remove(layout)
|
||||||
remove(layout)
|
layout.separator()
|
||||||
layout.separator()
|
|
||||||
rename = layout.operator(
|
rename = layout.operator(
|
||||||
"sw.rename", text="Rename" if menu_mode else "", icon="TEXT")
|
"sw.rename", text="Rename" if menu_mode else "", icon="TEXT")
|
||||||
rename.current_name = name if name else bpy.context.window.workspace.name
|
rename.current_name = name if name else bpy.context.window.workspace.name
|
||||||
@ -95,8 +135,6 @@ def workspace_ops(layout, i, menu_mode=False, name=None):
|
|||||||
layout.separator()
|
layout.separator()
|
||||||
layout.operator("sw.activate", text="Previous Workspace (scene)" if menu_mode else "").next = False
|
layout.operator("sw.activate", text="Previous Workspace (scene)" if menu_mode else "").next = False
|
||||||
layout.operator("sw.activate", text="Next Workspace (scene)" if menu_mode else "").next = True
|
layout.operator("sw.activate", text="Next Workspace (scene)" if menu_mode else "").next = True
|
||||||
else:
|
|
||||||
remove(layout)
|
|
||||||
|
|
||||||
def workspace_menu(self, context):
|
def workspace_menu(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
@ -2,7 +2,7 @@ from .. import __package__ as base_package
|
|||||||
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_topbar, has_data, prefs, tag_redraw_topbar
|
from .funcs import select_all, set_active, get_scene_workspaces, set_scene_workspaces, get_use_topbar, has_data, prefs, tag_redraw_topbar
|
||||||
|
|
||||||
|
|
||||||
class SW_OT_switch(Operator):
|
class SW_OT_switch(Operator):
|
||||||
@ -31,7 +31,17 @@ class SW_OT_workspace(Operator):
|
|||||||
l.pop(l.index(self.workspace))
|
l.pop(l.index(self.workspace))
|
||||||
set_scene_workspaces(l)
|
set_scene_workspaces(l)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
class SW_OT_select(Operator):
|
||||||
|
bl_idname = "sw.select"
|
||||||
|
bl_label = "Workspace"
|
||||||
|
bl_description = "Select this workspace to reorder, rename or unlink"
|
||||||
|
|
||||||
|
workspace: StringProperty(name="workspace")
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
set_active(get_scene_workspaces().index(self.workspace))
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
class SW_OT_link_all(Operator):
|
class SW_OT_link_all(Operator):
|
||||||
bl_idname = "sw.link_all"
|
bl_idname = "sw.link_all"
|
||||||
@ -64,11 +74,14 @@ class SW_OT_move(Operator):
|
|||||||
if self.valid(context):
|
if self.valid(context):
|
||||||
try:
|
try:
|
||||||
i = self.index if self.index != -1 else l.index(bpy.context.window.workspace.name)
|
i = self.index if self.index != -1 else l.index(bpy.context.window.workspace.name)
|
||||||
|
new_i = 0 if self.top else len(l)-1
|
||||||
if self.up == 0:
|
if self.up == 0:
|
||||||
l.insert(0 if self.top else len(l)-1, l.pop(i))
|
l.insert(new_i, l.pop(i))
|
||||||
else:
|
else:
|
||||||
l.insert(i-self.up, l.pop(i))
|
new_i = i-self.up
|
||||||
|
l.insert(new_i, l.pop(i))
|
||||||
|
|
||||||
|
set_active(new_i)
|
||||||
set_scene_workspaces(l)
|
set_scene_workspaces(l)
|
||||||
self.up = 0
|
self.up = 0
|
||||||
self.top = False
|
self.top = False
|
||||||
@ -150,6 +163,7 @@ class SW_OT_remove(Operator):
|
|||||||
l = get_scene_workspaces()
|
l = get_scene_workspaces()
|
||||||
l.pop(self.index)
|
l.pop(self.index)
|
||||||
set_scene_workspaces(l)
|
set_scene_workspaces(l)
|
||||||
|
set_active(max(0, self.index-1))
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
@ -178,10 +192,13 @@ class SW_OT_link_workspace(Operator):
|
|||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
if not has_data():
|
if not has_data():
|
||||||
|
set_active()
|
||||||
set_scene_workspaces([])
|
set_scene_workspaces([])
|
||||||
if self.workspace in get_scene_workspaces():
|
if self.workspace in get_scene_workspaces():
|
||||||
set_scene_workspaces(
|
set_scene_workspaces(
|
||||||
[x for x in get_scene_workspaces() if x != self.workspace])
|
[x for x in get_scene_workspaces() if x != self.workspace])
|
||||||
|
set_active(len(get_scene_workspaces()) - 1)
|
||||||
else:
|
else:
|
||||||
set_scene_workspaces([*get_scene_workspaces(), self.workspace])
|
set_scene_workspaces([*get_scene_workspaces(), self.workspace])
|
||||||
|
set_active(len(get_scene_workspaces()) - 1)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import bpy
|
import bpy
|
||||||
from bpy.types import Panel
|
from bpy.types import Panel
|
||||||
from .funcs import get_scene_workspaces, workspace_ops
|
from .funcs import prop_name, prop_i_name, get_active, get_scene_workspaces, workspace_ops
|
||||||
|
|
||||||
class SW_PT_select_scene_workspaces(Panel):
|
class SW_PT_select_scene_workspaces(Panel):
|
||||||
bl_idname = "sw.select_scene_workspaces"
|
bl_idname = "sw.select_scene_workspaces"
|
||||||
@ -9,37 +9,36 @@ class SW_PT_select_scene_workspaces(Panel):
|
|||||||
bl_region_type = 'WINDOW'
|
bl_region_type = 'WINDOW'
|
||||||
bl_context = "scene"
|
bl_context = "scene"
|
||||||
bl_options = {'DEFAULT_CLOSED'}
|
bl_options = {'DEFAULT_CLOSED'}
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
layout.alignment = 'LEFT'
|
||||||
layout.label(text="Workspaces linked to this Scene:")
|
layout.label(text="Workspaces linked to this Scene")
|
||||||
box = layout.box()
|
row = layout.row()
|
||||||
sw = get_scene_workspaces()
|
sw = get_scene_workspaces()
|
||||||
if not sw:
|
if not sw:
|
||||||
|
box = row.box()
|
||||||
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")
|
box.operator("sw.link_all")
|
||||||
else:
|
else:
|
||||||
i = 0
|
i = get_active()
|
||||||
|
active = sw[i]
|
||||||
|
r = row.box().column(align=True)
|
||||||
for w in sw:
|
for w in sw:
|
||||||
box.scale_y = .4
|
op = r.operator("sw.select", text=w, icon="RADIOBUT_ON" if active == w else "RADIOBUT_OFF", emboss=active == w)
|
||||||
box2 = box.box()
|
op.workspace = w
|
||||||
row = box2.row(align=True)
|
r = row.column(align=True)
|
||||||
row.scale_y = 2.1
|
workspace_ops(r, i, False, active)
|
||||||
row.label(text=f"{w}")
|
|
||||||
workspace_ops(row, i, False, w)
|
|
||||||
i += 1
|
|
||||||
box.separator()
|
|
||||||
|
|
||||||
layout.separator()
|
layout.separator()
|
||||||
|
|
||||||
layout.label(text="Link other workspaces")
|
layout.label(text="Link other workspaces")
|
||||||
box2 = layout.box()
|
box2 = layout.box()
|
||||||
row = box2.row()
|
row = box2.row()
|
||||||
row_count = 0
|
row_count = 0
|
||||||
l = [x for x in bpy.data.workspaces if x.name not in sw]
|
l = [x for x in bpy.data.workspaces if x.name not in sw]
|
||||||
for w in l:
|
for w in l:
|
||||||
if row_count > 0 and row_count % 4 == 0:
|
if row_count > 0 and row_count % 3 == 0:
|
||||||
row = box2.row()
|
row = box2.row()
|
||||||
row.operator("sw.link_workspace", text=w.name).workspace = w.name
|
row.operator("sw.link_workspace", text=w.name).workspace = w.name
|
||||||
row_count += 1
|
row_count += 1
|
||||||
@ -47,4 +46,4 @@ class SW_PT_select_scene_workspaces(Panel):
|
|||||||
layout.separator()
|
layout.separator()
|
||||||
layout.operator("sw.link_all")
|
layout.operator("sw.link_all")
|
||||||
else:
|
else:
|
||||||
box2.label(text="All workspaces are currently linked.")
|
row.label(text="All workspaces are currently linked.")
|
||||||
|
@ -6,15 +6,22 @@ from bpy.props import BoolProperty
|
|||||||
class SW_Preferences(AddonPreferences):
|
class SW_Preferences(AddonPreferences):
|
||||||
bl_idname = base_package
|
bl_idname = base_package
|
||||||
|
|
||||||
|
only_with_multiple_scenes: BoolProperty(name="Show only with multiple scenes", description="Show the topbar (and eventually the checkbox) only when the project has multiple scenes", default=False)
|
||||||
|
auto_init: BoolProperty(name="Auto initialize Scene Workspaces", description="Automatically add all avaliable workspaces to the current scene, if empty (with ordering only for common cases)", default=True)
|
||||||
use_topbar: BoolProperty(name="Use Scene Workspaces topbar", description="Switch the workspace topbar between Scene Workspaces and the default one", default=True)
|
use_topbar: BoolProperty(name="Use Scene Workspaces topbar", description="Switch the workspace topbar between Scene Workspaces and the default one", default=True)
|
||||||
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)
|
switch: BoolProperty(name="Show Checkbox", description="Show/Hide the checkbox button next to the workspaces topbar. Useful for quickly lookup the original workspaces topbar", default=True)
|
||||||
compact: BoolProperty(name="Use Compact Mode", description="If disabled, adds spacing around the active workspace and a quick unlink button", default=True)
|
compact: BoolProperty(name="Use Compact Mode", description="If disabled, adds spacing around the active workspace and a quick unlink button", default=True)
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.prop(self, "use_topbar")
|
layout.prop(self, "only_with_multiple_scenes")
|
||||||
layout.prop(self, "switch")
|
layout.prop(self, "auto_init")
|
||||||
|
if self.auto_init:
|
||||||
|
layout.label(text="Note: Scene Workspaces cannot retrive the global workspaces order.")
|
||||||
|
layout.label(text="Only workspaces from one of the 5 default templates will be automatically ordered.")
|
||||||
|
|
||||||
box = layout.box()
|
box = layout.box()
|
||||||
box.label(text="UI Options")
|
box.label(text="UI Options")
|
||||||
|
box.prop(self, "use_topbar")
|
||||||
|
box.prop(self, "switch")
|
||||||
box.prop(self, "compact")
|
box.prop(self, "compact")
|
||||||
|
@ -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_topbar, get_switch, get_compact
|
from .funcs import get_scene_workspaces, get_use_topbar, get_switch, get_compact, get_only_with_multiple
|
||||||
|
|
||||||
# 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,9 @@ class TOPBAR_HT_upper_bar(Header):
|
|||||||
use_topbar = get_use_topbar()
|
use_topbar = get_use_topbar()
|
||||||
compact = get_compact()
|
compact = get_compact()
|
||||||
switch= get_switch()
|
switch= get_switch()
|
||||||
|
only_with_multiple = get_only_with_multiple()
|
||||||
|
has_multiple = len(bpy.data.scenes) > 1
|
||||||
|
multiple_satisfied = (not only_with_multiple or only_with_multiple and has_multiple)
|
||||||
|
|
||||||
if not screen.show_fullscreen:
|
if not screen.show_fullscreen:
|
||||||
main_col = layout.column()
|
main_col = layout.column()
|
||||||
@ -37,11 +40,11 @@ class TOPBAR_HT_upper_bar(Header):
|
|||||||
main_row = main_col.row()
|
main_row = main_col.row()
|
||||||
sy = 1.18
|
sy = 1.18
|
||||||
sx = 1.18
|
sx = 1.18
|
||||||
if switch:
|
if switch and multiple_satisfied:
|
||||||
col = main_row.column()
|
col = main_row.column()
|
||||||
# Show/Hide Custom Topbar
|
# Show/Hide Custom Topbar
|
||||||
col.operator("sw.switch", text="", emboss=False, icon="CHECKBOX_HLT" if use_topbar else "CHECKBOX_DEHLT")
|
col.operator("sw.switch", text="", emboss=False, icon="CHECKBOX_HLT" if use_topbar else "CHECKBOX_DEHLT")
|
||||||
if not use_topbar:
|
if not use_topbar or not multiple_satisfied:
|
||||||
# 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")
|
||||||
else:
|
else:
|
||||||
|
Before Width: | Height: | Size: 765 KiB After Width: | Height: | Size: 763 KiB |
BIN
assets/Icon-256.png
Normal file
After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 770 KiB After Width: | Height: | Size: 767 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 36 KiB |