[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [31238] trunk/blender: python declarative UI

Campbell Barton ideasman42 at gmail.com
Wed Aug 11 17:11:30 CEST 2010


Revision: 31238
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=31238
Author:   campbellbarton
Date:     2010-08-11 17:11:30 +0200 (Wed, 11 Aug 2010)

Log Message:
-----------
python declarative UI
- remove XML testing feature
- add 2 modules: bpyml - generic, bpyml_ui - blender spesific. nothing uses these now.

==bpyml_ui module==
defines BPyML_BaseUI and its draw() function which uses the bpyml member of the class instance self.draw_data & self.draw_header_data.

This way declarative ui is opt-in and easy to use by using BPyML_BaseUI as a mix-in class.

==bpyml module==

This module translates a python like XML representation into XML
or simple python blender/ui function calls.

    sometag(arg=10) [
        another(),
        another(key="value")
    ]

# converts into ...

    <sometag arg="10">
        <another/>
        <another key="value" />
    </sometag>

Modified Paths:
--------------
    trunk/blender/release/scripts/modules/bpy/utils.py
    trunk/blender/release/scripts/ui/properties_render.py
    trunk/blender/source/blender/makesrna/intern/rna_color.c
    trunk/blender/source/blender/makesrna/intern/rna_fluidsim.c

Added Paths:
-----------
    trunk/blender/release/scripts/modules/bpyml.py
    trunk/blender/release/scripts/modules/bpyml_ui.py

Removed Paths:
-------------
    trunk/blender/release/scripts/modules/bpy_xml_ui.py
    trunk/blender/release/scripts/ui/properties_render_test.xml

Modified: trunk/blender/release/scripts/modules/bpy/utils.py
===================================================================
--- trunk/blender/release/scripts/modules/bpy/utils.py	2010-08-11 14:51:52 UTC (rev 31237)
+++ trunk/blender/release/scripts/modules/bpy/utils.py	2010-08-11 15:11:30 UTC (rev 31238)
@@ -30,8 +30,6 @@
 from _bpy import blend_paths
 from _bpy import script_paths as _bpy_script_paths
 
-_TEST_XML = _bpy.app.debug
-
 def _test_import(module_name, loaded_modules):
     import traceback
     import time
@@ -54,36 +52,7 @@
     loaded_modules.add(mod.__name__) # should match mod.__name__ too
     return mod
 
-if _TEST_XML:
-    # TEST CODE
-    def _test_import_xml(path, f, loaded_modules):
-        import bpy_xml_ui
-        import traceback
 
-        f_full = _os.path.join(path, f)
-        _bpy_types._register_immediate = True
-        try:
-            classes = bpy_xml_ui.load_xml(f_full)
-        except:
-            traceback.print_exc()
-            classes = []
-        _bpy_types._register_immediate = False
-
-        if classes:
-            mod_name = f.split(".")[0]
-
-            # fake module
-            mod = type(traceback)(mod_name)
-            mod.__file__ = f_full
-            for cls in classes:
-                setattr(mod, cls.__name__, cls)
-            
-            loaded_modules.add(mod_name)
-            _sys.modules[mod_name] = mod
-            mod.register = lambda: None # quiet errors
-            return mod
-
-
 def modules_from_path(path, loaded_modules):
     """
     Load all modules in a path and return them as a list.
@@ -110,10 +79,6 @@
         else:
             mod = None
 
-        if _TEST_XML:
-            if mod is None and f.endswith(".xml"):
-                mod = _test_import_xml(path, f, loaded_modules)
-
         if mod:
             modules.append(mod)
 

Deleted: trunk/blender/release/scripts/modules/bpy_xml_ui.py
===================================================================
--- trunk/blender/release/scripts/modules/bpy_xml_ui.py	2010-08-11 14:51:52 UTC (rev 31237)
+++ trunk/blender/release/scripts/modules/bpy_xml_ui.py	2010-08-11 15:11:30 UTC (rev 31238)
@@ -1,151 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-#  This program is free software; you can redistribute it and/or
-#  modify it under the terms of the GNU General Public License
-#  as published by the Free Software Foundation; either version 2
-#  of the License, or (at your option) any later version.
-#
-#  This program is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#  GNU General Public License for more details.
-#
-#  You should have received a copy of the GNU General Public License
-#  along with this program; if not, write to the Free Software Foundation,
-#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-# <pep8 compliant>
-
-"""
-This module translates XML into blender/ui function calls.
-"""
-
-import xml.dom.minidom
-import bpy as _bpy
-
-def parse_rna(prop, value):
-    if prop.type == 'FLOAT':
-        value = float(value)
-    elif prop.type == 'INT':
-        value = int(value)
-    elif prop.type == 'BOOLEAN':
-        if value not in ("true", "false"):
-            raise Exception("invalid bool value: %s", value)
-        value = bool(value == "true")
-    elif prop.type in ('STRING', 'ENUM'):
-        pass
-    elif prop.type == 'POINTER':
-        value = eval("_bpy." + value)
-    else:
-        raise Exception("type not supported %s.%s" % (prop.identifier, prop.type))
-    return value
-    
-def parse_args(base, xml_node):
-    args = {}
-    rna_params = base.bl_rna.functions[xml_node.tagName].parameters
-    for key, value in xml_node.attributes.items():
-        args[key] = parse_rna(rna_params[key], value)
-    return args
-
-def ui_xml(base, xml_node):
-    name = xml_node.tagName
-    prop = base.bl_rna.properties.get(name)
-    if name in base.bl_rna.properties:
-        attr = xml_node.attributes.get("expr")
-        if attr:
-            value = attr.value
-            value = eval(value, {"context": _bpy.context})
-            setattr(base, name, value)
-        else:
-            attr = xml_node.attributes['value']
-            value = attr.value
-            value = parse_rna(prop, value)
-            setattr(base, name, value)
-    else:
-        func_new = getattr(base, name)
-        kw_args = parse_args(base, xml_node)
-        base_new = func_new(**kw_args) # call blender func
-        if xml_node.hasChildNodes():
-            ui_xml_list(base_new, xml_node.childNodes)
-
-def ui_xml_list(base, xml_nodes):
-    import bpy
-    for node in xml_nodes:
-        if node.nodeType not in (node.TEXT_NODE, node.COMMENT_NODE):
-            ui_xml(base, node)
-            bpy.N = node
-
-def test(layout):
-    uixml = xml.dom.minidom.parseString(open("/mnt/test/blender-svn/blender/release/scripts/ui/test.xml", 'r').read())
-    panel = uixml.getElementsByTagName('panel')[0]
-    ui_xml_list(layout, panel.childNodes)
-
-def load_xml(filepath):
-    classes = []
-    fn = open(filepath, 'r')
-    data = fn.read()
-    uixml = xml.dom.minidom.parseString(data).getElementsByTagName("ui")[0]
-    fn.close()
-    
-    def draw_xml(self, context):
-        node = self._xml_node.getElementsByTagName("draw")[0]
-        ui_xml_list(self.layout, node.childNodes)
-        
-    def draw_header_xml(self, context):
-        node = self._xml_node.getElementsByTagName("draw_header")[0]
-        ui_xml_list(self.layout, node.childNodes)
-    
-    for node in uixml.childNodes:
-        if node.nodeType not in (node.TEXT_NODE, node.COMMENT_NODE):
-            name = node.tagName
-            class_name = node.attributes["identifier"].value
-
-            if name == "panel":
-                class_dict = {
-                    "bl_label": node.attributes["label"].value,
-                    "bl_region_type": node.attributes["region_type"].value,
-                    "bl_space_type": node.attributes["space_type"].value,
-                    "bl_context": node.attributes["context"].value,
-                    "bl_default_closed": ((node.attributes["default_closed"].value == "true") if "default_closed" in node.attributes else False),
-
-                    "draw": draw_xml,
-                    "_xml_node": node
-                }
-                
-                if node.getElementsByTagName("draw_header"):
-                    class_dict["draw_header"] = draw_header_xml
-
-                # will register instantly
-                class_new = type(class_name, (_bpy.types.Panel,), class_dict)
-
-            elif name == "menu":
-                class_dict = {
-                    "bl_label": node.attributes["label"].value,
-
-                    "draw": draw_xml,
-                    "_xml_node": node
-                }
-
-                # will register instantly
-                class_new = type(class_name, (_bpy.types.Menu,), class_dict)
-
-            elif name == "header":
-                class_dict = {
-                    "bl_label": node.attributes["label"].value,
-                    "bl_space_type": node.attributes["space_type"].value,
-
-                    "draw": draw_xml,
-                    "_xml_node": node
-                }
-
-                # will register instantly
-                class_new = type(class_name, (_bpy.types.Header,), class_dict)
-            else:
-                raise Exception("invalid id found '%s': expected a value in ('header', 'panel', 'menu)'" % name)
-
-            classes.append(class_new)
-            
-
-    return classes

Added: trunk/blender/release/scripts/modules/bpyml.py
===================================================================
--- trunk/blender/release/scripts/modules/bpyml.py	                        (rev 0)
+++ trunk/blender/release/scripts/modules/bpyml.py	2010-08-11 15:11:30 UTC (rev 31238)
@@ -0,0 +1,204 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+"""
+This module translates a python like XML representation into XML
+or simple python blender/ui function calls.
+
+    sometag(arg=10) [
+        another()
+        another(key="value")
+    ]
+
+# converts into ...
+
+    <sometag arg="10">
+        <another/>
+        <another key="value" />
+    </sometag>
+
+"""
+
+TAG, ARGS, CHILDREN = range(3)
+class ReturnStore(tuple):
+    def __getitem__(self, key):
+
+        # single item get's
+        if type(key) is ReturnStore:
+            key = (key, )
+
+        if type(key) is tuple:
+            children = self[CHILDREN]
+            if children:
+                raise Exception("Only a single __getitem__ is allowed on the ReturnStore")
+            else:
+                children[:] = key
+            return self
+        else:
+            return tuple.__getitem__(self, key)
+
+
+class FunctionStore(object):
+    def __call__(self, **kwargs):
+        return ReturnStore((self.__class__.__name__, kwargs, []))
+
+
+def tag_vars(tags, module=__name__):
+    return {tag: type(tag, (FunctionStore, ), {"__module__": module})() for tag in tags}
+
+
+def tag_module(mod_name, tags):
+    import sys
+    from types import ModuleType
+    mod = ModuleType(mod_name)
+    sys.modules[mod_name] = mod
+    dict_values = tag_vars(tags, mod_name)
+    mod.__dict__.update(dict_values)
+    return mod
+
+
+def toxml(py_data, indent="    "):
+
+    if len(py_data) != 1 or type(py_data) != list:
+        raise Exception("Expected a list with one member")
+
+    def _to_xml(py_item, xml_node=None):
+        if xml_node is None:

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list