#!/usr/bin/env python # -*- coding: utf-8 -*- import os import sys from xml.dom import minidom from jinja2 import Environment, FileSystemLoader from gen_view_code.class_type import class_type PY3 = sys.version_info[0] > '3' class class_member(object): def __init__(self, name, ct): self.name = name self.class_type = ct def get_plain_actors(root, res): for node in root.childNodes: if node.nodeType == node.TEXT_NODE: continue res.append(node) get_plain_actors(node, res) def save_if_changed(name, content): try: with open(name, "r") as rd: data = rd.read() if data == content: return except IOError: pass with open(name, "w") as rd: rd.write(content) mp_actor = class_type("spActor", "Actor", "Actor.h") mp_button = class_type("spButton", "Button", "Button.h") mp_text = class_type("spTextField", "TextField", "TextField.h") mp_bar = class_type("spProgressBar", "ProgressBar", "ProgressBar.h") mp_clip = class_type("spClipRectActor", "ClipRectActor", "ClipRectActor.h") mp_sprite = class_type("spSprite", "Sprite", "Sprite.h") mp_sliding = class_type("spSlidingActor", "SlidingActor", "SlidingActor.h") mp_color = class_type("spColorRectSprite", "ColorRectSprite", "ColorRectSprite.h") mp_box9sprite = class_type("spBox9Sprite", "Box9Sprite", "Box9Sprite.h") mp_polygon = class_type("spPolygon", "Polygon", "Polygon.h") mp_msprite = class_type("spMaskedSprite", "MaskedSprite", "MaskedSprite.h") mp_view = class_type("spView", "View", "View.h") def_mappings = (mp_bar, mp_clip, mp_button, mp_text, mp_actor, mp_sprite, mp_sliding, mp_color, mp_box9sprite, mp_polygon, mp_msprite) def get_mapping(lst, name): for m in lst: if m.className == name: return m return None user_mp = None def find_mapping(name, classes): if user_mp: mp = get_mapping(user_mp, name) if mp: return mp mp = get_mapping(def_mappings, name) if mp: return mp mp = get_mapping(classes, name) if mp: return mp return None def gen_classes(nodes, ct, classes): classes.add(ct) for child in nodes: class_mapping = mp_actor member = child.attrib["member"] res_id = "" if "id" in child.attrib: res_id = child.attrib["id"] if not res_id: res_id = os.path.splitext(child.attrib["file"])[0] class_mapping = mp_sprite if "ref" in child.attrib: class_mapping = mp_sprite try: # print res_id class_name = child.attrib["class"] class_mapping = find_mapping(class_name, classes) if not class_mapping: if class_name.endswith("<"): class_name = class_name.rstrip("<") class_mapping = class_type( class_name, "sp" + class_name, class_name, class_name + ".h", ns="", member=res_id, parent=mp_sprite, generated=True) gen_classes(nodes, class_mapping, classes) elif class_name.startswith(">"): return else: class_mapping = class_type( class_name, "sp" + class_name, class_name, class_name + ".h", ns="") except KeyError: pass classes.add(class_mapping) # note: unused variable index = child.attrib["order"] ct.members.append(class_member(member, class_mapping, res_id)) def gen2(xml_res_file, dest_folder, mappings): global user_mp user_mp = mappings if not os.path.exists(dest_folder): os.makedirs(dest_folder) xml_res_file = os.path.normpath(xml_res_file) xml_res_file = xml_res_file.replace("\\", "/") doc = minidom.parse(xml_res_file) root = doc.documentElement folder = os.path.dirname(os.path.abspath(__file__)) + "/gen_view_code/templates" print(folder) env = Environment(trim_blocks=True, lstrip_blocks=True, loader=FileSystemLoader(folder)) class_h_template = env.get_template("class.h") class_cpp_template = env.get_template("class.cpp") import io classes_node = root.getElementsByTagName("class")[0] classes = set() for class_node in classes_node.childNodes: if class_node.nodeType == class_node.TEXT_NODE: continue res = [] get_plain_actors(class_node, res) class_name = class_node.getAttribute("class") local_classes = set() parent = find_mapping(class_node.nodeName, classes) custom_class = class_type( "sp" + class_name, class_name, class_name + ".h", ns="", member="", parent=parent, generated=True) classes.add(custom_class) local_classes.add(custom_class) header = io.StringIO() cpp = io.StringIO() for node in res: name = node.getAttribute("name") ct = find_mapping(node.nodeName, classes) custom_class.members.append(class_member(name, ct)) classes.add(ct) local_classes.add(ct) cls = list(local_classes) q = 0 def ff(a, b): def cmp(a, b): if a < b: return -1 if a > b: return 1 return 0 return cmp(b.ns, a.ns) or cmp(b.primary, a.primary) or cmp(a.className, b.className) import functools cls.sort(key=functools.cmp_to_key(ff)) includes = [inc for inc in cls if inc.header] args = {"types": cls, "ct": custom_class, "includes": includes} header.write(env.get_template("header.h").render(**args)) cpp.write(env.get_template("header.cpp").render(**args)) args = {"ct": custom_class, "xml": xml_res_file, "members": custom_class.members} header.write(class_h_template.render(**args)) cpp.write(class_cpp_template.render(**args)) header_name = class_name + ".h" cpp_name = class_name + ".cpp" gen_code = class_node.getAttribute("gencode") if gen_code == "false": continue save_if_changed(dest_folder + header_name, header.getvalue()) save_if_changed(dest_folder + cpp_name, cpp.getvalue()) if __name__ == "__main__": import argparse parser = argparse.ArgumentParser( description="generates h/cpp files from oxygine xml") parser.add_argument("xml", help="xml file to process") parser.add_argument( "-d", "--dest", help="destination folder for generated classes", default=".") args = parser.parse_args() gen2(args.xml, args.dest + "/", None)