diff options
Diffstat (limited to 'release/scripts/modules/bpy_xml_ui.py')
-rw-r--r-- | release/scripts/modules/bpy_xml_ui.py | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/release/scripts/modules/bpy_xml_ui.py b/release/scripts/modules/bpy_xml_ui.py new file mode 100644 index 00000000000..18eec9c4ef4 --- /dev/null +++ b/release/scripts/modules/bpy_xml_ui.py @@ -0,0 +1,151 @@ +# ##### 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 |