- 2 panels implimented in properties_render_test.xml (Render Dimensions and Stamp) - only enabled in debug mode. - poll() functions are not supported yet. - as stated above experemental, we'll see if this is at all useful, remove if not. - XML could be replaced with JSON or YAML.
152 lines
5.3 KiB
Python
152 lines
5.3 KiB
Python
# ##### 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
|