Add Workspace from Template feature, +refactor
This commit is contained in:
parent
079487299b
commit
28bc4dac8f
@ -14,22 +14,25 @@
|
|||||||
# 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 .classes.draw import draw_file_new_templates, draw_file_default_operators
|
from .classes.draw import draw_file_new_templates, draw_file_default_operators, draw_ws_menu_add
|
||||||
from .classes.splash import WM_MT_splash, CT_MT_splash_mode, CT_OT_splash_custom, CT_OT_splash_default
|
from .classes.splash import WM_MT_splash, CT_MT_splash_mode, CT_OT_splash_custom, CT_OT_splash_default
|
||||||
from .classes.ots import CustomTemplatesPreferences, TemplateItem, CT_OT_export_templates, CT_OT_import_templates, CT_MT_templates_menu, CT_OT_select_template_popup, CT_OT_add_template_popup, CT_OT_add, CT_OT_remove, CT_OT_move_down, CT_OT_move_up, CT_OT_open_preferences, CT_OT_add_templates_from_folder, CT_OT_clear
|
from .classes.ots import CustomTemplatesPreferences, TemplateItem, CT_OT_export_templates, CT_OT_import_templates, CT_MT_templates_menu, CT_OT_select_template_popup, CT_OT_add_template_popup, CT_OT_add, CT_OT_remove, CT_OT_move_down, CT_OT_move_up, CT_OT_open_preferences, CT_OT_add_templates_from_folder, CT_OT_clear, CT_MT_workspace_add, CT_OT_template_workspaces, CT_OT_add_workspace
|
||||||
|
|
||||||
bl_info = {
|
bl_info = {
|
||||||
"id": "custom_templates",
|
"id": "custom_templates",
|
||||||
"name": "Custom Templates",
|
"name": "Custom Templates",
|
||||||
"tagline": "Add your own .blend files as template options for new projects",
|
"tagline": "Add your own .blend files as template options for new projects",
|
||||||
"blender": (4, 2, 0),
|
"blender": (4, 2, 0),
|
||||||
"location": "File > New & File > Defaults",
|
"location": "File > New, File > Defaults, Splash Screen",
|
||||||
"category": "System",
|
"category": "System",
|
||||||
"support": "COMMUNITY",
|
"support": "COMMUNITY",
|
||||||
"blender_manifest": "blender_manifest.toml"
|
"blender_manifest": "blender_manifest.toml"
|
||||||
}
|
}
|
||||||
|
|
||||||
classes = [WM_MT_splash,
|
classes = [WM_MT_splash,
|
||||||
|
CT_OT_add_workspace,
|
||||||
|
CT_OT_template_workspaces,
|
||||||
|
CT_MT_workspace_add,
|
||||||
TemplateItem,
|
TemplateItem,
|
||||||
CT_OT_export_templates,
|
CT_OT_export_templates,
|
||||||
CT_OT_import_templates,
|
CT_OT_import_templates,
|
||||||
@ -57,6 +60,7 @@ def register():
|
|||||||
bpy.utils.register_class(c)
|
bpy.utils.register_class(c)
|
||||||
bpy.types.TOPBAR_MT_file_new.append(draw_file_new_templates)
|
bpy.types.TOPBAR_MT_file_new.append(draw_file_new_templates)
|
||||||
bpy.types.TOPBAR_MT_file_defaults.append(draw_file_default_operators)
|
bpy.types.TOPBAR_MT_file_defaults.append(draw_file_default_operators)
|
||||||
|
bpy.types.TOPBAR_MT_workspace_menu.append(draw_ws_menu_add)
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
for c in reversed(classes):
|
for c in reversed(classes):
|
||||||
@ -64,6 +68,7 @@ def unregister():
|
|||||||
bpy.utils.register_class(og_splash)
|
bpy.utils.register_class(og_splash)
|
||||||
bpy.types.TOPBAR_MT_file_new.remove(draw_file_new_templates)
|
bpy.types.TOPBAR_MT_file_new.remove(draw_file_new_templates)
|
||||||
bpy.types.TOPBAR_MT_file_defaults.remove(draw_file_default_operators)
|
bpy.types.TOPBAR_MT_file_defaults.remove(draw_file_default_operators)
|
||||||
|
bpy.types.TOPBAR_MT_workspace_menu.remove(draw_ws_menu_add)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
register()
|
registers()
|
||||||
|
@ -4,7 +4,6 @@ import bpy
|
|||||||
|
|
||||||
def draw_file_new_templates(self, context):
|
def draw_file_new_templates(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
|
|
||||||
prefs = context.preferences.addons[base_package].preferences
|
prefs = context.preferences.addons[base_package].preferences
|
||||||
if len(prefs.projects) > 0:
|
if len(prefs.projects) > 0:
|
||||||
layout.separator()
|
layout.separator()
|
||||||
@ -37,3 +36,11 @@ def draw_file_default_operators(self, context):
|
|||||||
if bpy.data.filepath != "":
|
if bpy.data.filepath != "":
|
||||||
layout.operator("ct.add_template_popup",
|
layout.operator("ct.add_template_popup",
|
||||||
text="Use current file as template")
|
text="Use current file as template")
|
||||||
|
|
||||||
|
def draw_ws_menu_add(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
prefs = context.preferences.addons[base_package].preferences
|
||||||
|
if prefs.projects:
|
||||||
|
layout.separator()
|
||||||
|
layout.menu("CT_MT_workspace_add", text="Add from Custom Templates", icon="WORKSPACE")
|
||||||
|
|
@ -2,7 +2,7 @@ from .. import __package__ as base_package
|
|||||||
import os
|
import os
|
||||||
import bpy
|
import bpy
|
||||||
import json
|
import json
|
||||||
from bpy.types import Operator, PropertyGroup, AddonPreferences
|
from bpy.types import Operator, Menu, PropertyGroup, AddonPreferences
|
||||||
from bpy.props import StringProperty, CollectionProperty, IntProperty, BoolProperty
|
from bpy.props import StringProperty, CollectionProperty, IntProperty, BoolProperty
|
||||||
|
|
||||||
def already_present(self, prefs, path, report=True):
|
def already_present(self, prefs, path, report=True):
|
||||||
@ -27,7 +27,7 @@ def on_path_update(self, context):
|
|||||||
if self.path and self.path.startswith('//'):
|
if self.path and self.path.startswith('//'):
|
||||||
self.path = bpy.path.abspath(self.path)
|
self.path = bpy.path.abspath(self.path)
|
||||||
context.preferences.is_dirty = True
|
context.preferences.is_dirty = True
|
||||||
|
|
||||||
class TemplateItem(PropertyGroup):
|
class TemplateItem(PropertyGroup):
|
||||||
name: StringProperty(
|
name: StringProperty(
|
||||||
name="Name", description="Display name for this template")
|
name="Name", description="Display name for this template")
|
||||||
@ -38,7 +38,7 @@ class CustomTemplatesPreferences(AddonPreferences):
|
|||||||
bl_idname = base_package
|
bl_idname = base_package
|
||||||
|
|
||||||
override_splash: BoolProperty(
|
override_splash: BoolProperty(
|
||||||
default=True, name="Override Splash Screen Templates", description="Override Splash Screen's 'New File' list with your Custom Templates")
|
default=True, name="Use Custom Templates", description="Override Splash Screen's 'New File' list with your Custom Templates")
|
||||||
projects: CollectionProperty(type=TemplateItem)
|
projects: CollectionProperty(type=TemplateItem)
|
||||||
active_template_index: IntProperty(
|
active_template_index: IntProperty(
|
||||||
description="Index of the selected template")
|
description="Index of the selected template")
|
||||||
@ -55,7 +55,8 @@ class CustomTemplatesPreferences(AddonPreferences):
|
|||||||
col = row.column(align=True)
|
col = row.column(align=True)
|
||||||
col.menu("CT_MT_templates_menu", icon='DOWNARROW_HLT', text="")
|
col.menu("CT_MT_templates_menu", icon='DOWNARROW_HLT', text="")
|
||||||
col.separator()
|
col.separator()
|
||||||
col.operator("ct.add_templates_from_folder", text="", icon="FILE_FOLDER")
|
col.operator("ct.add_templates_from_folder",
|
||||||
|
text="", icon="FILE_FOLDER")
|
||||||
col.operator("ct.add", icon='ADD', text="")
|
col.operator("ct.add", icon='ADD', text="")
|
||||||
col.operator("ct.remove", icon='REMOVE', text="")
|
col.operator("ct.remove", icon='REMOVE', text="")
|
||||||
col.separator()
|
col.separator()
|
||||||
@ -66,35 +67,39 @@ class CustomTemplatesPreferences(AddonPreferences):
|
|||||||
project = self.projects[self.active_template_index]
|
project = self.projects[self.active_template_index]
|
||||||
layout.prop(project, "path")
|
layout.prop(project, "path")
|
||||||
layout.prop(project, "name")
|
layout.prop(project, "name")
|
||||||
|
|
||||||
layout.prop(self, "override_splash")
|
b = layout.box()
|
||||||
box = layout.box()
|
b.label(text="Splash Screen", icon="SETTINGS")
|
||||||
if self.override_splash and len(self.projects) == 0:
|
b.prop(self, "override_splash")
|
||||||
box.label(text="There are currently no templates.")
|
box = b.box()
|
||||||
elif self.override_splash:
|
if self.override_splash and self.projects:
|
||||||
box.label(text="Custom templates will be shown in the Splash Screen.")
|
box.label(text="Custom templates will be shown in the Splash Screen.")
|
||||||
|
|
||||||
if not self.override_splash or len(self.projects) == 0:
|
if not self.override_splash or len(self.projects) == 0:
|
||||||
box.label(
|
box.label(
|
||||||
text="The default Blender list will be shown in the Splash Screen.")
|
text="The default Blender list will be shown in the Splash Screen.", icon=("ERROR" if not self.projects else "NONE"))
|
||||||
|
|
||||||
if len(self.projects) > 5:
|
if len(self.projects) > 5:
|
||||||
box.label(
|
box.label(
|
||||||
text="Note: Only the first 5 templates in the list will be shown in the splash screen.")
|
text="Note: Only the first 5 templates in the list will be shown in the splash screen.")
|
||||||
|
|
||||||
class CT_MT_templates_menu(bpy.types.Menu):
|
class CT_MT_templates_menu(Menu):
|
||||||
bl_label = "Manage your custom templates"
|
bl_label = "Manage your custom templates"
|
||||||
bl_description = "Import, export, add from folder (with controllable recursion depth), clear current templates"
|
bl_description = "Import, export, add from folder (with controllable recursion depth), clear current templates"
|
||||||
|
|
||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
layout = self.layout
|
layout = self.layout
|
||||||
layout.operator("ct.add_templates_from_folder", text="Add from folder", icon="ADD")
|
layout.operator("ct.add_templates_from_folder",
|
||||||
layout.operator("ct.clear", text="Clear current templates", icon="TRASH")
|
text="Add from folder", icon="ADD")
|
||||||
|
layout.operator(
|
||||||
|
"ct.clear", text="Clear current templates", icon="TRASH")
|
||||||
layout.separator()
|
layout.separator()
|
||||||
layout.operator("ct.import_templates", text="Import templates", icon="IMPORT")
|
layout.operator("ct.import_templates",
|
||||||
layout.operator("ct.export_templates", text="Export templates", icon="EXPORT")
|
text="Import templates", icon="IMPORT")
|
||||||
|
layout.operator("ct.export_templates",
|
||||||
|
text="Export templates", icon="EXPORT")
|
||||||
|
|
||||||
class CT_OT_export_templates(bpy.types.Operator):
|
class CT_OT_export_templates(Operator):
|
||||||
bl_idname = "ct.export_templates"
|
bl_idname = "ct.export_templates"
|
||||||
bl_label = "Export custom templates"
|
bl_label = "Export custom templates"
|
||||||
bl_description = "Export the current list of templates to JSON file"
|
bl_description = "Export the current list of templates to JSON file"
|
||||||
@ -120,7 +125,7 @@ class CT_OT_export_templates(bpy.types.Operator):
|
|||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
return len(context.preferences.addons[base_package].preferences.projects) > 0
|
return len(context.preferences.addons[base_package].preferences.projects) > 0
|
||||||
|
|
||||||
class CT_OT_import_templates(bpy.types.Operator):
|
class CT_OT_import_templates(Operator):
|
||||||
bl_idname = "ct.import_templates"
|
bl_idname = "ct.import_templates"
|
||||||
bl_label = "Import custom templates"
|
bl_label = "Import custom templates"
|
||||||
bl_description = "Import a list of templates from JSON file (note that this will override the current templates list)"
|
bl_description = "Import a list of templates from JSON file (note that this will override the current templates list)"
|
||||||
@ -235,7 +240,7 @@ class CT_OT_clear(Operator):
|
|||||||
prefs.active_template_index = 0
|
prefs.active_template_index = 0
|
||||||
context.preferences.is_dirty = True
|
context.preferences.is_dirty = True
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
return context.window_manager.invoke_props_dialog(self)
|
return context.window_manager.invoke_props_dialog(self)
|
||||||
|
|
||||||
@ -273,7 +278,8 @@ class CT_OT_select_template_popup(Operator):
|
|||||||
bl_label = "Select a new custom template"
|
bl_label = "Select a new custom template"
|
||||||
bl_description = "Create a new template by selecting an existing .blend file"
|
bl_description = "Create a new template by selecting an existing .blend file"
|
||||||
|
|
||||||
path: StringProperty(name="Template Path", subtype="FILE_PATH", update=on_path_update)
|
path: StringProperty(name="Template Path",
|
||||||
|
subtype="FILE_PATH", update=on_path_update)
|
||||||
name: StringProperty(name="Template Name")
|
name: StringProperty(name="Template Name")
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
@ -285,7 +291,7 @@ class CT_OT_select_template_popup(Operator):
|
|||||||
context.preferences.is_dirty = True
|
context.preferences.is_dirty = True
|
||||||
self.name = ''
|
self.name = ''
|
||||||
self.path = ''
|
self.path = ''
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
@ -348,3 +354,52 @@ class CT_OT_open_preferences(Operator):
|
|||||||
context.preferences.active_section = 'ADDONS'
|
context.preferences.active_section = 'ADDONS'
|
||||||
context.window_manager.addon_search = "Custom Templates"
|
context.window_manager.addon_search = "Custom Templates"
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
class CT_OT_add_workspace(Operator):
|
||||||
|
bl_idname = "ct.add_workspace"
|
||||||
|
bl_label = "Add this workspace from your template"
|
||||||
|
bl_description = "Add to the current project, the selected workspace from your Custom Template"
|
||||||
|
|
||||||
|
workspace: StringProperty(name="workspace")
|
||||||
|
path: StringProperty(name="path")
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
bpy.ops.workspace.append_activate(idname=self.workspace, filepath=self.path)
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
class CT_OT_template_workspaces(Operator):
|
||||||
|
bl_idname = "ct.template_workspaces"
|
||||||
|
bl_label = "Add workspace from this template"
|
||||||
|
bl_description = "Click to select one of the workspaces from this Custom Template"
|
||||||
|
|
||||||
|
index: IntProperty(name='index', default=0)
|
||||||
|
|
||||||
|
def draw_ws(self, s, context):
|
||||||
|
layout = s.layout
|
||||||
|
template = context.preferences.addons[base_package].preferences.projects[self.index]
|
||||||
|
with bpy.data.libraries.load(template.path) as (data, _):
|
||||||
|
for w in data.workspaces:
|
||||||
|
op = layout.operator("ct.add_workspace", text=w)
|
||||||
|
op.workspace = w
|
||||||
|
op.path = template.path
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
return {'RUNNING_MODAL'}
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
wm = context.window_manager
|
||||||
|
template = context.preferences.addons[base_package].preferences.projects[self.index]
|
||||||
|
wm.popup_menu(self.draw_ws, title=f"Workspaces from '{template.name}'", icon="ADD")
|
||||||
|
return {'RUNNING_MODAL'}
|
||||||
|
|
||||||
|
class CT_MT_workspace_add(Menu):
|
||||||
|
bl_label = "Add workspace from Custom Templates"
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
layout = self.layout
|
||||||
|
templates = context.preferences.addons[base_package].preferences.projects
|
||||||
|
layout.label(text="Add workspace from Custom Templates", icon="ADD")
|
||||||
|
layout.separator()
|
||||||
|
for i in range(len(templates)):
|
||||||
|
t = templates[i]
|
||||||
|
layout.operator("CT_OT_template_workspaces", text=t.name).index = i
|
||||||
|
Loading…
x
Reference in New Issue
Block a user