Compare commits
	
		
			No commits in common. "main" and "v1.0.0" have entirely different histories.
		
	
	
		
	
		
							
								
								
									
										18
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						| @ -1,20 +1,3 @@ | |||||||
| ## 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.   | ||||||
| @ -26,7 +9,6 @@ Current features: | |||||||
| - 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,42 +8,30 @@ | |||||||
| 
 | 
 | ||||||
| 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. | ||||||
| 
 | 
 | ||||||
| > Scene Workspaces is based on simple custom properties at scene level.   | > This is possible thanks to a custom property at scene level (which is saved with your .blend file).   | ||||||
|  | > *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 only with multiple scenes** *(default: off)*   | - **Show Switch**   | ||||||
|   *Show the topbar (and eventually the checkbox) only when the project has multiple scenes.   |   *When active, shows a checkbox to switch between Scene Workspaces and the default topbar.*   | ||||||
|   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** *(default: on)*   | - **Use Scene Workspaces topbar**   | ||||||
| *Scene Workspaces topbar.*   | *Scene Workspaces topbar.*   | ||||||
|    |    | ||||||
| *Default workspaces topbar.*   | *Default workspaces topbar.*   | ||||||
|    |    | ||||||
| - **Use Compact Mode** *(default: on)*   | - **Use Compact Mode** *(default ON)*   | ||||||
|   *Also avaliable from the workspace menu.*   | *Compact Mode ON*   | ||||||
|   *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.   | ||||||
| 
 | 
 | ||||||
|    |    | ||||||
| @ -53,21 +41,22 @@ 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 this scene)* | - **Reorder to front** *(only for these scene)* | ||||||
| - **Move left** *(only for this scene)* | - **Move left** *(only for these scene)* | ||||||
| - **Move right** *(only for this scene)* | - **Move right** *(only for these scene)* | ||||||
| - **Reorder to back** *(only for this scene)* | - **Reorder to back** *(only for these 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 you'll find the default workspace options.   | And then, starting from `Duplicate`, 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)` or use the panel instead.*   | *Instead, use the ones marked with `(scene only)`.*   | ||||||
| >   | >   | ||||||
| > Also, default options `Previous Workspace` and `Next Workspace` will follow the global workspaces order, and not the scene order.   | > Also, default options `Previous Workspace` and `Next Workspace` functions 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).*   | *Instead, use the ones marked with `(scene)`.*   | ||||||
|  | > Be sure to use the Scene Workspaces relative options, instead.   | ||||||
| 
 | 
 | ||||||
| --- | --- | ||||||
| 
 | 
 | ||||||
| @ -83,29 +72,21 @@ 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. | ||||||
| 
 | 
 | ||||||
| At the same time, you may need different workspaces in different scenes, depending on the purpose of the scene. | 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 possible with the custom topbar and a custom property for each scene. | **Scene Workspaces** make this possibile with the custom topbar and a custom property for each scene. | ||||||
| 
 | 
 | ||||||
| ## Changelog | ## Changelog | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,96 +0,0 @@ | |||||||
| **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,9 +14,8 @@ | |||||||
| # 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 bpy.app.handlers import persistent | from .sw.funcs import select_all, workspace_menu, assign_shortcuts, remove_shortcuts | ||||||
| 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 | ||||||
| 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 | ||||||
| @ -35,7 +34,6 @@ 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, | ||||||
| @ -51,22 +49,6 @@ 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(): | ||||||
| @ -75,8 +57,7 @@ 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(): | ||||||
| @ -84,8 +65,7 @@ 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.1.1" | version = "1.0.0" | ||||||
| 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,45 +1,21 @@ | |||||||
| from .. import __package__ as base_package | from .. import __package__ as base_package | ||||||
| import bpy | import bpy | ||||||
| 
 | 
 | ||||||
| prop_name = "scene_workspaces"; | def has_data(): | ||||||
| prop_i_name = "scene_workspaces_active"; |     return 'scene_workspaces' in bpy.data.scenes[bpy.context.scene.name] | ||||||
| 
 |  | ||||||
| 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(scene): |     if has_data(): | ||||||
|         return bpy.data.scenes[scene if scene else bpy.context.scene.name][prop_name] |         return bpy.data.scenes[scene if scene else bpy.context.scene.name]['scene_workspaces'] | ||||||
|     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 | ||||||
| 
 | 
 | ||||||
| @ -47,29 +23,11 @@ def get_compact(): | |||||||
|     return prefs().compact |     return prefs().compact | ||||||
| 
 | 
 | ||||||
| def set_scene_workspaces(workspaces, scene = None): | def set_scene_workspaces(workspaces, scene = None): | ||||||
|     s = scene if scene else bpy.context.scene.name |     bpy.data.scenes[scene if scene else bpy.context.scene.name]['scene_workspaces'] = workspaces | ||||||
|     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 = get_scene_workspaces() |     workspaces = [] | ||||||
|     match, templates = workspaces_match_template() |  | ||||||
|     if match and not workspaces: |  | ||||||
|         workspaces = templates |  | ||||||
|     else: |  | ||||||
|     for w in bpy.data.workspaces: |     for w in bpy.data.workspaces: | ||||||
|             if w.name not in workspaces: |  | ||||||
|         workspaces.append(w.name) |         workspaces.append(w.name) | ||||||
|     set_scene_workspaces(workspaces) |     set_scene_workspaces(workspaces) | ||||||
|      |      | ||||||
| @ -96,10 +54,11 @@ 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 == "sw.activate": |         if kmi.idname in ['sw.activate', 'sw.move'] : | ||||||
|             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() | ||||||
| @ -107,6 +66,7 @@ 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( | ||||||
| @ -135,6 +95,8 @@ 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, set_active, get_scene_workspaces, set_scene_workspaces, get_use_topbar, has_data, prefs, tag_redraw_topbar | from .funcs import select_all, 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): | ||||||
| @ -32,16 +32,6 @@ class SW_OT_workspace(Operator): | |||||||
|             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" | ||||||
| @ -74,14 +64,11 @@ 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(new_i, l.pop(i)) |                     l.insert(0 if self.top else len(l)-1, l.pop(i)) | ||||||
|                 else: |                 else: | ||||||
|                     new_i = i-self.up |                     l.insert(i-self.up, l.pop(i)) | ||||||
|                     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 | ||||||
| @ -163,7 +150,6 @@ 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'} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -192,13 +178,10 @@ 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 prop_name, prop_i_name, get_active, get_scene_workspaces, workspace_ops | from .funcs import 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" | ||||||
| @ -12,23 +12,24 @@ class SW_PT_select_scene_workspaces(Panel): | |||||||
|      |      | ||||||
|     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:") | ||||||
|         row = layout.row() |         box = layout.box() | ||||||
|         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 = get_active() |             i = 0 | ||||||
|             active = sw[i] |  | ||||||
|             r = row.box().column(align=True) |  | ||||||
|             for w in sw: |             for w in sw: | ||||||
|                 op = r.operator("sw.select", text=w, icon="RADIOBUT_ON" if active == w else "RADIOBUT_OFF", emboss=active == w) |                 box.scale_y = .4 | ||||||
|                 op.workspace = w |                 box2 = box.box() | ||||||
|             r = row.column(align=True) |                 row = box2.row(align=True) | ||||||
|             workspace_ops(r, i, False, active) |                 row.scale_y = 2.1 | ||||||
|  |                 row.label(text=f"{w}") | ||||||
|  |                 workspace_ops(row, i, False, w) | ||||||
|  |                 i += 1 | ||||||
|  |             box.separator() | ||||||
|              |              | ||||||
|         layout.separator() |         layout.separator() | ||||||
|          |          | ||||||
| @ -38,7 +39,7 @@ class SW_PT_select_scene_workspaces(Panel): | |||||||
|         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 % 3 == 0: |             if row_count > 0 and row_count % 4 == 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 | ||||||
| @ -46,4 +47,4 @@ class SW_PT_select_scene_workspaces(Panel): | |||||||
|             layout.separator() |             layout.separator() | ||||||
|             layout.operator("sw.link_all") |             layout.operator("sw.link_all") | ||||||
|         else: |         else: | ||||||
|             row.label(text="All workspaces are currently linked.") |             box2.label(text="All workspaces are currently linked.") | ||||||
|  | |||||||
| @ -6,22 +6,15 @@ 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 Checkbox", description="Show/Hide the checkbox button next to the workspaces topbar. Useful for quickly lookup the original workspaces topbar", 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) | ||||||
|     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, "only_with_multiple_scenes") |         layout.prop(self, "use_topbar") | ||||||
|         layout.prop(self, "auto_init") |         layout.prop(self, "switch") | ||||||
|         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, get_only_with_multiple | from .funcs import get_scene_workspaces, get_use_topbar, get_switch, get_compact | ||||||
| 
 | 
 | ||||||
| # 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,9 +29,6 @@ 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() | ||||||
| @ -40,11 +37,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 and multiple_satisfied: |             if switch: | ||||||
|                 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 or not multiple_satisfied: |             if not use_topbar: | ||||||
|                 # 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: 763 KiB After Width: | Height: | Size: 765 KiB | 
| Before Width: | Height: | Size: 10 KiB | 
| Before Width: | Height: | Size: 767 KiB After Width: | Height: | Size: 770 KiB | 
| Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 30 KiB |