[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [35849] trunk/blender/intern/tools/ demo_mode.py: demo mode WIP, use a configuration file rather then command line args.

Campbell Barton ideasman42 at gmail.com
Mon Mar 28 15:56:20 CEST 2011


Revision: 35849
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=35849
Author:   campbellbarton
Date:     2011-03-28 13:56:20 +0000 (Mon, 28 Mar 2011)
Log Message:
-----------
demo mode WIP, use a configuration file rather then command line args.

Modified Paths:
--------------
    trunk/blender/intern/tools/demo_mode.py

Modified: trunk/blender/intern/tools/demo_mode.py
===================================================================
--- trunk/blender/intern/tools/demo_mode.py	2011-03-28 13:53:53 UTC (rev 35848)
+++ trunk/blender/intern/tools/demo_mode.py	2011-03-28 13:56:20 UTC (rev 35849)
@@ -22,10 +22,10 @@
 # C code, WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), 0x0110, 0.1f);
 #
 # play for 8 seconds then quick, switch screens every 4 sec.
-# ./blender.bin demo.blend --python demo_mode.py -- --animate=8 --screen_switch=4
+# ./blender.bin demo.blend --python intern/tools/demo_mode.py -- --animate=8 --screen_switch=4
 #
 # render and pause for 3 seconds.
-# ./blender.bin demo.blend --python demo_mode.py -- --render 3
+# ./blender.bin demo.blend --python intern/tools/demo_mode.py -- --render 3
 
 
 import bpy
@@ -34,86 +34,210 @@
 import tempfile
 import os
 
+from collections import OrderedDict
 
+# populate from script
+global_config_files = OrderedDict()
+
 global_config = {
     "animate": 0,  # seconds
     "render": 0,
     "screen_switch": 0,
-    "_init_time": 0.0,
-    "_last_switch": 0.0,
-    "_reset_anim": False,
-    "_render_out": "",
 }
 
+# switch to the next file in 2 sec.
+global_config_fallback = {
+    "animate": 2,  # seconds
+    "render": 0,
+    "screen_switch": 0,
+}
 
+global_state = {
+    "init_time": 0.0,
+    "last_switch": 0.0,
+    "reset_anim": False,
+    "render_out": "",
+    "render_time": "",  # time render was finished.
+    "timer": None,
+    "basedir": "",  # demo.py is stored here
+}
+
+
+def lookup_config():
+    # match the config up with the open file
+    found = False
+    basename = os.path.basename(bpy.data.filepath)
+    for i, filepath in enumerate(global_config_files):
+        if basename == os.path.basename(filepath):
+            return (i, filepath)
+    return -1, None
+
+
+def demo_mode_next_file():
+    ls = list(global_config_files.keys())
+    index, filepath = lookup_config()
+    if index == -1:
+        # file not in demo loaded
+        filepath_next = ls[0]
+    else:
+        index += 1
+        filepath_next = ls[0] if index >= len(ls) else ls[index]
+
+    bpy.ops.wm.open_mainfile(filepath=filepath_next)
+
+
+def demo_mode_timer_add():
+    global_state["timer"] = bpy.context.window_manager.event_timer_add(0.8, bpy.context.window)
+
+def demo_mode_timer_remove():
+    if global_state["timer"]:
+        bpy.context.window_manager.event_timer_remove(global_state["timer"])
+        global_state["timer"] = None
+
+def demo_mode_load_file():
+    """ Take care, this can only do limited functions since its running
+        before the file is fully loaded.
+        Some operators will crash like playing an animation.
+    """
+    DemoMode.first_run = True
+    bpy.ops.wm.demo_mode('EXEC_DEFAULT')
+
+
 def demo_mode_init():
+    print("INIT")
+    DemoKeepAlive.ensure()
+
+    if 1:
+        index, filepath = lookup_config()
+        global_config.clear()
+        if index == -1:
+            print("  using fallback config")
+            global_config.update(global_config_fallback)
+        else:
+            global_config.update(global_config_files[filepath])
+
+    print(global_config)
+
+    demo_mode_timer_add()
+
     if global_config["animate"]:
         bpy.ops.screen.animation_play()
 
-    if global_config["render"]:
-        global_config["_render_out"] = tempfile.mkstemp()[1]
+    elif global_config["render"]:
+        print("  render")
+        global_state["render_out"] = tempfile.mkstemp()[1]
 
-        bpy.context.scene.render.filepath = global_config["_render_out"]
+        bpy.context.scene.render.filepath = global_state["render_out"]
         bpy.context.scene.render.use_file_extension = False
         bpy.context.scene.render.use_placeholder = False
-        if os.path.exists(global_config["_render_out"]):
-            os.remove(global_config["_render_out"])
+        if os.path.exists(global_state["render_out"]):
+            print("  render!!!")
+            os.remove(global_state["render_out"])
 
         bpy.ops.render.render('INVOKE_DEFAULT', write_still=True)
 
-    global_config["_init_time"] = global_config["_last_switch"] = time.time()
+    global_state["init_time"] = global_state["last_switch"] = time.time()
+    global_state["render_time"] = -1.0
 
 
 def demo_mode_update():
     time_current = time.time()
-    time_delta = time_current - global_config["_last_switch"]
-    time_total = time_current - global_config["_init_time"]
+    time_delta = time_current - global_state["last_switch"]
+    time_total = time_current - global_state["init_time"]
 
-    # check for exit
-    if global_config["animate"] and time_total > global_config["animate"]:
-        sys.exit(0)
+    # --------------------------------------------------------------------------
+    # ANIMATE MODE
+    if global_config["animate"]:
+        # check for exit
+        if time_total > global_config["animate"]:
+            demo_mode_next_file()
+            return
 
-    if global_config["render"] and os.path.exists(global_config["_render_out"]):
-        # sleep and quit
-        os.remove(global_config["_render_out"])
-        time.sleep(global_config["render"])
-        sys.exit(0)
+        # run update funcs
+        if global_state["reset_anim"]:
+            global_state["reset_anim"] = False
+            bpy.ops.screen.animation_cancel(restore_frame=False)
+            bpy.ops.screen.animation_play()
 
-    # run update funcs
-    if global_config["_reset_anim"]:
-        global_config["_reset_anim"] = False
-        bpy.ops.screen.animation_cancel(restore_frame=False)
-        bpy.ops.screen.animation_play()
+        if global_config["screen_switch"]:
+            # print(time_delta, 1)
+            if time_delta > global_config["screen_switch"]:
 
-    if global_config["screen_switch"]:
-        print(time_delta, 1)
-        if time_delta > global_config["screen_switch"]:
-            screen = bpy.context.window.screen
-            index = bpy.data.screens.keys().index(screen.name)
-            screen_new = bpy.data.screens[(index if index > 0 else len(bpy.data.screens)) - 1]
-            bpy.context.window.screen = screen_new
+                screen = bpy.context.window.screen
+                index = bpy.data.screens.keys().index(screen.name)
+                screen_new = bpy.data.screens[(index if index > 0 else len(bpy.data.screens)) - 1]
+                bpy.context.window.screen = screen_new
 
-            global_config["_last_switch"] = time_current
+                global_state["last_switch"] = time_current
 
-            if global_config["animate"]:
-                global_config["_reset_anim"] = True
+                if global_config["animate"]:
+                    global_state["reset_anim"] = True
 
+    # --------------------------------------------------------------------------
+    # RENDER MODE
+    elif global_config["render"]:
+        if os.path.exists(global_state["render_out"]):
+            # wait until the time has passed
+            if global_state["render_time"] == -1.0:
+                global_state["render_time"] = time.time()
+            else:
+                if time.time() - global_state["render_time"] > global_config["render"]:
+                    os.remove(global_state["render_out"])
+                    demo_mode_next_file()
+                    return
 
+
+def demo_mode_exit():
+    # bpy.context.window_manager.event_timer_remove(global_state["timer"])
+    # global_state["timer"] = None
+    pass
+
+
 # -----------------------------------------------------------------------------
 # modal operator
 
+class DemoKeepAlive:
+    secret_attr = "_keepalive"
+
+    @staticmethod
+    def ensure():
+        if DemoKeepAlive.secret_attr not in bpy.app.driver_namespace:
+            bpy.app.driver_namespace[DemoKeepAlive.secret_attr] = DemoKeepAlive()
+
+    @staticmethod
+    def remove():
+        if DemoKeepAlive.secret_attr in bpy.app.driver_namespace:
+            del bpy.app.driver_namespace[DemoKeepAlive.secret_attr]
+
+    def __del__(self):
+        """ Hack, when the file is loaded the drivers namespace is cleared.
+        """
+        if DemoMode.enabled:
+            demo_mode_load_file()
+
+
 class DemoMode(bpy.types.Operator):
     bl_idname = "wm.demo_mode"
-    bl_label = "Simple Modal Operator"
+    bl_label = "Demo"
 
-    _first_run = True
+    enabled = True
 
+    first_run = True
+
+    def cleanup(self):
+        DemoKeepAlive.remove()
+        demo_mode_timer_remove()
+        self.__class__.first_run = True
+        
+
     def modal(self, context, event):
         if event.type in ('RIGHTMOUSE', 'ESC'):
+            self.cleanup()
             return {'CANCELLED'}
+
         # print(event.type)
-        if self.__class__._first_run:
-            self.__class__._first_run = False
+        if self.__class__.first_run:
+            self.__class__.first_run = False
 
             demo_mode_init()
         else:
@@ -122,70 +246,87 @@
         return {'PASS_THROUGH'}
 
     def execute(self, context):
+        self.__class__.enabled = True
         context.window_manager.modal_handler_add(self)
         return {'RUNNING_MODAL'}
 
+    def __del__(self):
+        self.cleanup()
+        demo_mode_exit()
 
+
+def menu_func(self, context):
+    print("DemoMode.enabled:", DemoMode.enabled, "bpy.app.driver_namespace: keep alive ", DemoKeepAlive.secret_attr not in bpy.app.driver_namespace, 'global_state["timer"]:', global_state["timer"])
+    if not DemoMode.enabled:
+        pass
+    if 1:
+        layout = self.layout
+        layout.operator_context = 'EXEC_DEFAULT'
+        layout.operator("wm.demo_mode", icon='PLAY')
+
+
 def register():
     bpy.utils.register_class(DemoMode)
+    bpy.types.INFO_HT_header.append(menu_func)
 
 
 def unregister():
     bpy.utils.unregister_class(DemoMode)
 
 
-def main_model_op():
-    register()
-    bpy.ops.wm.demo_mode('EXEC_DEFAULT')
-
-
 # -----------------------------------------------------------------------------
 # parse args
 
+def load_config(cfg_name="demo.py"):
+    namespace = {}
+    text = bpy.data.texts.get(cfg_name)
+    if text is None:
+        basedir = os.path.dirname(bpy.data.filepath)
+        demo_path = os.path.join(basedir, "demo.py")
+        demo_file = open(demo_path, "r")
+        demo_data = demo_file.read()
+    else:
+        demo_data = text.as_string()
+        demo_path = os.path.join(bpy.data.filepath, cfg_name)  # fake
 
-def main():
-    import argparse

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list