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 #####
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.",
28 "doc_url": "{BLENDER_MANUAL_URL}/addons/system/demo_mode.html",
29 "support": 'OFFICIAL',
33 # To support reload properly, try to access a package var, if it's there, reload everything
36 if "config" in locals():
37 importlib
.reload(config
)
41 from bpy
.props
import (
50 class DemoModeSetup(bpy
.types
.Operator
):
51 """Create a demo script and optionally execute it"""
52 bl_idname
= "wm.demo_mode_setup"
53 bl_label
= "Demo Mode (Setup)"
54 bl_options
= {'PRESET'}
56 # List of operator properties, the attributes will be assigned
57 # to the class instance from the operator settings before calling.
59 # these are used to create the file list.
60 directory
: StringProperty(
62 description
="Directory used for importing the file",
66 random_order
: BoolProperty(
68 description
="Select files randomly",
76 ('RENDER', "Render", ""),
81 name
="Run Immediately!",
82 description
="Run demo immediately",
87 description
="Run once and exit",
91 # these are mapped directly to the config!
95 anim_cycles
: IntProperty(
97 description
="Number of times to play the animation",
101 anim_time_min
: FloatProperty(
103 description
="Minimum number of seconds to show the animation for "
106 soft_min
=1.0, soft_max
=1000.0,
109 anim_time_max
: FloatProperty(
111 description
="Maximum number of seconds to show the animation for "
112 "(in case the end frame is very high for no reason)",
113 min=0.0, max=100000000.0,
114 soft_min
=1.0, soft_max
=100000000.0,
117 anim_screen_switch
: FloatProperty(
118 name
="Screen Switch",
119 description
="Time between switching screens (in seconds) "
121 min=0.0, max=100000000.0,
122 soft_min
=1.0, soft_max
=60.0,
128 display_render
: FloatProperty(
130 description
="Time to display the rendered image before moving on "
135 anim_render
: BoolProperty(
137 description
="Render entire animation (render mode only)",
141 def execute(self
, context
):
144 keywords
= self
.as_keywords(ignore
=("directory", "random_order", "run", "exit"))
145 cfg_str
, _dirpath
= config
.as_string(
151 text
= bpy
.data
.texts
.get("demo.py")
155 text
= bpy
.data
.texts
.new("demo.py")
156 text
.from_string(cfg_str
)
159 extern_demo_mode_run()
163 def invoke(self
, context
, event
):
164 context
.window_manager
.fileselect_add(self
)
165 return {'RUNNING_MODAL'}
167 def check(self
, context
):
170 def draw(self
, context
):
174 box
.label(text
="Search *.blend recursively")
175 box
.label(text
="Writes: demo.py config text")
177 layout
.prop(self
, "run")
178 layout
.prop(self
, "exit")
180 layout
.label(text
="Generate Settings:")
182 row
.prop(self
, "mode", expand
=True)
183 layout
.prop(self
, "random_order")
188 sub
= layout
.column()
189 sub
.active
= (mode
in {'AUTO', 'PLAY'})
190 sub
.label(text
="Animate Settings:")
191 sub
.prop(self
, "anim_cycles")
192 sub
.prop(self
, "anim_time_min")
193 sub
.prop(self
, "anim_time_max")
194 sub
.prop(self
, "anim_screen_switch")
197 sub
= layout
.column()
198 sub
.active
= (mode
in {'AUTO', 'RENDER'})
199 sub
.label(text
="Render Settings:")
200 sub
.prop(self
, "display_render")
203 class DemoModeRun(bpy
.types
.Operator
):
204 bl_idname
= "wm.demo_mode_run"
205 bl_label
= "Demo Mode (Start)"
207 def execute(self
, context
):
208 if extern_demo_mode_run():
211 self
.report({'ERROR'}, "Cant load demo.py config, run: File -> Demo Mode (Setup)")
215 # --- call demo_mode.py funcs
216 def extern_demo_mode_run():
217 # this accesses demo_mode.py which is kept standalone
218 # and can be run direct.
219 from . import demo_mode
220 if demo_mode
.load_config():
221 demo_mode
.demo_mode_load_file() # kick starts the modal operator
227 def extern_demo_mode_register():
228 # this accesses demo_mode.py which is kept standalone
229 # and can be run direct.
230 from . import demo_mode
234 def extern_demo_mode_unregister():
235 # this accesses demo_mode.py which is kept standalone
236 # and can be run direct.
237 from . import demo_mode
238 demo_mode
.unregister()
243 def menu_func(self
, context
):
245 layout
.operator(DemoModeSetup
.bl_idname
, icon
='PREFERENCES')
246 layout
.operator(DemoModeRun
.bl_idname
, icon
='PLAY')
256 from bpy
.utils
import register_class
260 bpy
.types
.TOPBAR_MT_file
.prepend(menu_func
)
262 extern_demo_mode_register()
266 from bpy
.utils
import unregister_class
268 unregister_class(cls
)
270 bpy
.types
.TOPBAR_MT_file
.remove(menu_func
)
272 extern_demo_mode_unregister()
274 if __name__
== "__main__":