Merge branch 'blender-v4.0-release'
[blender-addons.git] / storypencil / scene_tools.py
blob1a3eb0c5b54b63621f9f6d69db711a1a6a763187
1 # SPDX-FileCopyrightText: 2022-2023 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 import bpy
6 import os
8 from bpy.types import (
9 Operator,
13 # -------------------------------------------------------------
14 # Add a new scene and set to new strip
16 # -------------------------------------------------------------
17 class STORYPENCIL_OT_NewScene(Operator):
18 bl_idname = "storypencil.new_scene"
19 bl_label = "New Scene"
20 bl_description = "Create a new scene base on template scene"
21 bl_options = {'REGISTER', 'UNDO'}
23 scene_name: bpy.props.StringProperty(default="Scene")
24 num_strips: bpy.props.IntProperty(default=1, min=1, max=128, description="Number of scenes to add")
26 # ------------------------------
27 # Poll
28 # ------------------------------
29 @classmethod
30 def poll(cls, context):
31 scene = context.scene
32 scene_base = scene.storypencil_base_scene
33 if scene_base is not None and scene_base.name in bpy.data.scenes:
34 return True
36 return False
38 def invoke(self, context, event):
39 return context.window_manager.invoke_props_dialog(self)
41 def draw(self, context):
42 layout = self.layout
43 col = layout.column()
44 col.prop(self, "scene_name", text="Scene Name")
45 col.prop(self, "num_strips", text="Repeat")
47 def format_to3(self, value):
48 return f"{value:03}"
50 # ------------------------------
51 # Execute button action
52 # ------------------------------
53 def execute(self, context):
54 scene_prv = context.scene
55 cfra_prv = scene_prv.frame_current
56 scene_base = scene_prv.storypencil_base_scene
57 repeat = self.num_strips
59 offset = 0
60 for i in range(repeat):
61 # Set context to base scene and duplicate
62 context.window.scene = scene_base
63 bpy.ops.scene.new(type='FULL_COPY')
64 scene_new = context.window.scene
65 new_name = scene_prv.storypencil_name_prefix + \
66 self.scene_name + scene_prv.storypencil_name_suffix
67 id = 0
68 while new_name in bpy.data.scenes:
69 id += 1
70 new_name = scene_prv.storypencil_name_prefix + self.scene_name + \
71 scene_prv.storypencil_name_suffix + '.' + self.format_to3(id)
73 scene_new.name = new_name
74 # Set duration of new scene
75 scene_new.frame_end = scene_new.frame_start + \
76 scene_prv.storypencil_scene_duration - 1
78 # Back to original scene
79 context.window.scene = scene_prv
80 scene_prv.frame_current = cfra_prv
81 bpy.ops.sequencer.scene_strip_add(
82 frame_start=cfra_prv + offset, scene=scene_new.name)
84 # Add offset for repeat
85 offset += scene_new.frame_end - scene_new.frame_start + 1
87 scene_new.update_tag()
88 scene_prv.update_tag()
90 return {"FINISHED"}
93 def draw_new_scene(self, context):
94 """Add menu options."""
96 self.layout.operator_context = 'INVOKE_REGION_WIN'
97 row = self.layout.row(align=True)
98 row.operator(STORYPENCIL_OT_NewScene.bl_idname, text="New Template Scene")
101 def setup_storyboard(self, context):
102 """Add Setup menu option."""
103 # For security, check if this is the default template.
104 is_gpencil = context.active_object and context.active_object.name == 'Stroke'
105 if is_gpencil and context.workspace.name in ('2D Animation', '2D Full Canvas') and context.scene.name == 'Scene':
106 if "Video Editing" not in bpy.data.workspaces:
107 row = self.layout.row(align=True)
108 row.separator()
109 row = self.layout.row(align=True)
110 row.operator(STORYPENCIL_OT_Setup.bl_idname,
111 text="Setup Storyboard Session")
114 # -------------------------------------------------------------
115 # Setup all environment
117 # -------------------------------------------------------------
118 class STORYPENCIL_OT_Setup(Operator):
119 bl_idname = "storypencil.setup"
120 bl_label = "Setup"
121 bl_description = "Configure all settings for a storyboard session"
122 bl_options = {'REGISTER', 'UNDO'}
124 # ------------------------------
125 # Poll
126 # ------------------------------
127 @classmethod
128 def poll(cls, context):
129 return True
131 def get_workspace(self, type):
132 for wrk in bpy.data.workspaces:
133 if wrk.name == type:
134 return wrk
136 return None
138 # ------------------------------
139 # Execute button action
140 # ------------------------------
141 def execute(self, context):
142 scene_base = context.scene
143 # Create Workspace
144 templatepath = None
145 if "Video Editing" not in bpy.data.workspaces:
146 template_path = None
147 for path in bpy.utils.app_template_paths():
148 template_path = path
150 filepath = os.path.join(
151 template_path, "Video_Editing", "startup.blend")
152 bpy.ops.workspace.append_activate(
153 idname="Video Editing", filepath=filepath)
154 # Create New scene
155 bpy.ops.scene.new()
156 scene_edit = context.scene
157 scene_edit.name = 'Edit'
158 # Rename original base scene
159 scene_base.name = 'Base'
160 # Setup Edit scene settings
161 scene_edit.storypencil_main_workspace = self.get_workspace(
162 "Video Editing")
163 scene_edit.storypencil_main_scene = scene_edit
164 scene_edit.storypencil_base_scene = scene_base
165 scene_edit.storypencil_edit_workspace = self.get_workspace(
166 "2D Animation")
168 # Add a new strip (need set the area context)
169 context.window.scene = scene_edit
170 area_prv = context.area.ui_type
171 context.area.ui_type = 'SEQUENCE_EDITOR'
172 prv_frame = scene_edit.frame_current
174 scene_edit.frame_current = scene_edit.frame_start
175 bpy.ops.storypencil.new_scene()
177 context.area.ui_type = area_prv
178 scene_edit.frame_current = prv_frame
180 scene_edit.update_tag()
181 bpy.ops.sequencer.reload()
183 return {"FINISHED"}