sun_position: fix warning from deleted prop in User Preferences
[blender-addons.git] / system_demo_mode / __init__.py
blobce85a8622db4822c6a7a545e7c67ad152aee7862
1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
19 # <pep8 compliant>
21 bl_info = {
22 "name": "Demo Mode",
23 "author": "Campbell Barton",
24 "blender": (2, 80, 0),
25 "location": "File > Demo Menu",
26 "description": "Demo mode lets you select multiple blend files and loop over them.",
27 "warning": "",
28 "wiki_url": "https://docs.blender.org/manual/en/dev/addons/"
29 "system/demo_mode.html",
30 "support": 'OFFICIAL',
31 "category": "System",
34 # To support reload properly, try to access a package var, if it's there, reload everything
35 if "bpy" in locals():
36 import importlib
37 if "config" in locals():
38 importlib.reload(config)
41 import bpy
42 from bpy.props import (
43 StringProperty,
44 BoolProperty,
45 IntProperty,
46 FloatProperty,
47 EnumProperty,
51 class DemoModeSetup(bpy.types.Operator):
52 """Create a demo script and optionally execute it"""
53 bl_idname = "wm.demo_mode_setup"
54 bl_label = "Demo Mode (Setup)"
55 bl_options = {'PRESET'}
57 # List of operator properties, the attributes will be assigned
58 # to the class instance from the operator settings before calling.
60 # these are used to create the file list.
61 directory: StringProperty(
62 name="Search Path",
63 description="Directory used for importing the file",
64 maxlen=1024,
65 subtype='DIR_PATH',
67 random_order: BoolProperty(
68 name="Random Order",
69 description="Select files randomly",
70 default=False,
72 mode: EnumProperty(
73 name="Method",
74 items=(
75 ('AUTO', "Auto", ""),
76 ('PLAY', "Play", ""),
77 ('RENDER', "Render", ""),
81 run: BoolProperty(
82 name="Run Immediately!",
83 description="Run demo immediately",
84 default=True,
86 exit: BoolProperty(
87 name="Exit",
88 description="Run once and exit",
89 default=False,
92 # these are mapped directly to the config!
94 # anim
95 # ====
96 anim_cycles: IntProperty(
97 name="Cycles",
98 description="Number of times to play the animation",
99 min=1, max=1000,
100 default=2,
102 anim_time_min: FloatProperty(
103 name="Time Min",
104 description="Minimum number of seconds to show the animation for "
105 "(for small loops)",
106 min=0.0, max=1000.0,
107 soft_min=1.0, soft_max=1000.0,
108 default=4.0,
110 anim_time_max: FloatProperty(
111 name="Time Max",
112 description="Maximum number of seconds to show the animation for "
113 "(in case the end frame is very high for no reason)",
114 min=0.0, max=100000000.0,
115 soft_min=1.0, soft_max=100000000.0,
116 default=8.0,
118 anim_screen_switch: FloatProperty(
119 name="Screen Switch",
120 description="Time between switching screens (in seconds) "
121 "or 0 to disable",
122 min=0.0, max=100000000.0,
123 soft_min=1.0, soft_max=60.0,
124 default=0.0,
127 # render
128 # ======
129 display_render: FloatProperty(
130 name="Render Delay",
131 description="Time to display the rendered image before moving on "
132 "(in seconds)",
133 min=0.0, max=60.0,
134 default=4.0,
136 anim_render: BoolProperty(
137 name="Render Anim",
138 description="Render entire animation (render mode only)",
139 default=False,
142 def execute(self, context):
143 from . import config
145 keywords = self.as_keywords(ignore=("directory", "random_order", "run", "exit"))
146 cfg_str, _dirpath = config.as_string(
147 self.directory,
148 self.random_order,
149 self.exit,
150 **keywords,
152 text = bpy.data.texts.get("demo.py")
153 if text:
154 text.name += ".back"
156 text = bpy.data.texts.new("demo.py")
157 text.from_string(cfg_str)
159 if self.run:
160 extern_demo_mode_run()
162 return {'FINISHED'}
164 def invoke(self, context, event):
165 context.window_manager.fileselect_add(self)
166 return {'RUNNING_MODAL'}
168 def check(self, context):
169 return True # lazy
171 def draw(self, context):
172 layout = self.layout
174 box = layout.box()
175 box.label(text="Search *.blend recursively")
176 box.label(text="Writes: demo.py config text")
178 layout.prop(self, "run")
179 layout.prop(self, "exit")
181 layout.label(text="Generate Settings:")
182 row = layout.row()
183 row.prop(self, "mode", expand=True)
184 layout.prop(self, "random_order")
186 mode = self.mode
188 layout.separator()
189 sub = layout.column()
190 sub.active = (mode in {'AUTO', 'PLAY'})
191 sub.label(text="Animate Settings:")
192 sub.prop(self, "anim_cycles")
193 sub.prop(self, "anim_time_min")
194 sub.prop(self, "anim_time_max")
195 sub.prop(self, "anim_screen_switch")
197 layout.separator()
198 sub = layout.column()
199 sub.active = (mode in {'AUTO', 'RENDER'})
200 sub.label(text="Render Settings:")
201 sub.prop(self, "display_render")
204 class DemoModeRun(bpy.types.Operator):
205 bl_idname = "wm.demo_mode_run"
206 bl_label = "Demo Mode (Start)"
208 def execute(self, context):
209 if extern_demo_mode_run():
210 return {'FINISHED'}
211 else:
212 self.report({'ERROR'}, "Cant load demo.py config, run: File -> Demo Mode (Setup)")
213 return {'CANCELLED'}
216 # --- call demo_mode.py funcs
217 def extern_demo_mode_run():
218 # this accesses demo_mode.py which is kept standalone
219 # and can be run direct.
220 from . import demo_mode
221 if demo_mode.load_config():
222 demo_mode.demo_mode_load_file() # kick starts the modal operator
223 return True
224 else:
225 return False
228 def extern_demo_mode_register():
229 # this accesses demo_mode.py which is kept standalone
230 # and can be run direct.
231 from . import demo_mode
232 demo_mode.register()
235 def extern_demo_mode_unregister():
236 # this accesses demo_mode.py which is kept standalone
237 # and can be run direct.
238 from . import demo_mode
239 demo_mode.unregister()
241 # --- integration
244 def menu_func(self, context):
245 layout = self.layout
246 layout.operator(DemoModeSetup.bl_idname, icon='PREFERENCES')
247 layout.operator(DemoModeRun.bl_idname, icon='PLAY')
248 layout.separator()
251 classes = (
252 DemoModeSetup,
253 DemoModeRun,
256 def register():
257 from bpy.utils import register_class
258 for cls in classes:
259 register_class(cls)
261 bpy.types.TOPBAR_MT_file.prepend(menu_func)
263 extern_demo_mode_register()
266 def unregister():
267 from bpy.utils import unregister_class
268 for cls in classes:
269 unregister_class(cls)
271 bpy.types.TOPBAR_MT_file.remove(menu_func)
273 extern_demo_mode_unregister()
275 if __name__ == "__main__":
276 register()