gen_view_code.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. import os
  4. import sys
  5. from xml.dom import minidom
  6. from jinja2 import Environment, FileSystemLoader
  7. from gen_view_code.class_type import class_type
  8. PY3 = sys.version_info[0] > '3'
  9. class class_member(object):
  10. def __init__(self, name, ct):
  11. self.name = name
  12. self.class_type = ct
  13. def get_plain_actors(root, res):
  14. for node in root.childNodes:
  15. if node.nodeType == node.TEXT_NODE:
  16. continue
  17. res.append(node)
  18. get_plain_actors(node, res)
  19. def save_if_changed(name, content):
  20. try:
  21. with open(name, "r") as rd:
  22. data = rd.read()
  23. if data == content:
  24. return
  25. except IOError:
  26. pass
  27. with open(name, "w") as rd:
  28. rd.write(content)
  29. mp_actor = class_type("spActor", "Actor", "Actor.h")
  30. mp_button = class_type("spButton", "Button", "Button.h")
  31. mp_text = class_type("spTextField", "TextField", "TextField.h")
  32. mp_bar = class_type("spProgressBar", "ProgressBar", "ProgressBar.h")
  33. mp_clip = class_type("spClipRectActor", "ClipRectActor", "ClipRectActor.h")
  34. mp_sprite = class_type("spSprite", "Sprite", "Sprite.h")
  35. mp_sliding = class_type("spSlidingActor", "SlidingActor", "SlidingActor.h")
  36. mp_color = class_type("spColorRectSprite",
  37. "ColorRectSprite", "ColorRectSprite.h")
  38. mp_box9sprite = class_type("spBox9Sprite", "Box9Sprite", "Box9Sprite.h")
  39. mp_polygon = class_type("spPolygon", "Polygon", "Polygon.h")
  40. mp_msprite = class_type("spMaskedSprite", "MaskedSprite", "MaskedSprite.h")
  41. mp_view = class_type("spView", "View", "View.h")
  42. def_mappings = (mp_bar,
  43. mp_clip,
  44. mp_button,
  45. mp_text,
  46. mp_actor,
  47. mp_sprite,
  48. mp_sliding,
  49. mp_color,
  50. mp_box9sprite,
  51. mp_polygon,
  52. mp_msprite)
  53. def get_mapping(lst, name):
  54. for m in lst:
  55. if m.className == name:
  56. return m
  57. return None
  58. user_mp = None
  59. def find_mapping(name, classes):
  60. if user_mp:
  61. mp = get_mapping(user_mp, name)
  62. if mp:
  63. return mp
  64. mp = get_mapping(def_mappings, name)
  65. if mp:
  66. return mp
  67. mp = get_mapping(classes, name)
  68. if mp:
  69. return mp
  70. return None
  71. def gen_classes(nodes, ct, classes):
  72. classes.add(ct)
  73. for child in nodes:
  74. class_mapping = mp_actor
  75. member = child.attrib["member"]
  76. res_id = ""
  77. if "id" in child.attrib:
  78. res_id = child.attrib["id"]
  79. if not res_id:
  80. res_id = os.path.splitext(child.attrib["file"])[0]
  81. class_mapping = mp_sprite
  82. if "ref" in child.attrib:
  83. class_mapping = mp_sprite
  84. try:
  85. # print res_id
  86. class_name = child.attrib["class"]
  87. class_mapping = find_mapping(class_name, classes)
  88. if not class_mapping:
  89. if class_name.endswith("<"):
  90. class_name = class_name.rstrip("<")
  91. class_mapping = class_type(
  92. class_name, "sp" + class_name, class_name,
  93. class_name + ".h", ns="", member=res_id,
  94. parent=mp_sprite, generated=True)
  95. gen_classes(nodes, class_mapping, classes)
  96. elif class_name.startswith(">"):
  97. return
  98. else:
  99. class_mapping = class_type(
  100. class_name, "sp" + class_name, class_name,
  101. class_name + ".h", ns="")
  102. except KeyError:
  103. pass
  104. classes.add(class_mapping)
  105. # note: unused variable
  106. index = child.attrib["order"]
  107. ct.members.append(class_member(member, class_mapping, res_id))
  108. def gen2(xml_res_file, dest_folder, mappings):
  109. global user_mp
  110. user_mp = mappings
  111. if not os.path.exists(dest_folder):
  112. os.makedirs(dest_folder)
  113. xml_res_file = os.path.normpath(xml_res_file)
  114. xml_res_file = xml_res_file.replace("\\", "/")
  115. doc = minidom.parse(xml_res_file)
  116. root = doc.documentElement
  117. folder = os.path.dirname(os.path.abspath(__file__)) + "/gen_view_code/templates"
  118. print(folder)
  119. env = Environment(trim_blocks=True, lstrip_blocks=True,
  120. loader=FileSystemLoader(folder))
  121. class_h_template = env.get_template("class.h")
  122. class_cpp_template = env.get_template("class.cpp")
  123. import io
  124. classes_node = root.getElementsByTagName("class")[0]
  125. classes = set()
  126. for class_node in classes_node.childNodes:
  127. if class_node.nodeType == class_node.TEXT_NODE:
  128. continue
  129. res = []
  130. get_plain_actors(class_node, res)
  131. class_name = class_node.getAttribute("class")
  132. local_classes = set()
  133. parent = find_mapping(class_node.nodeName, classes)
  134. custom_class = class_type(
  135. "sp" + class_name, class_name, class_name +
  136. ".h", ns="", member="", parent=parent, generated=True)
  137. classes.add(custom_class)
  138. local_classes.add(custom_class)
  139. header = io.StringIO()
  140. cpp = io.StringIO()
  141. for node in res:
  142. name = node.getAttribute("name")
  143. ct = find_mapping(node.nodeName, classes)
  144. custom_class.members.append(class_member(name, ct))
  145. classes.add(ct)
  146. local_classes.add(ct)
  147. cls = list(local_classes)
  148. q = 0
  149. def ff(a, b):
  150. def cmp(a, b):
  151. if a < b:
  152. return -1
  153. if a > b:
  154. return 1
  155. return 0
  156. return cmp(b.ns, a.ns) or cmp(b.primary, a.primary) or cmp(a.className, b.className)
  157. import functools
  158. cls.sort(key=functools.cmp_to_key(ff))
  159. includes = [inc for inc in cls if inc.header]
  160. args = {"types": cls,
  161. "ct": custom_class,
  162. "includes": includes}
  163. header.write(env.get_template("header.h").render(**args))
  164. cpp.write(env.get_template("header.cpp").render(**args))
  165. args = {"ct": custom_class,
  166. "xml": xml_res_file,
  167. "members": custom_class.members}
  168. header.write(class_h_template.render(**args))
  169. cpp.write(class_cpp_template.render(**args))
  170. header_name = class_name + ".h"
  171. cpp_name = class_name + ".cpp"
  172. gen_code = class_node.getAttribute("gencode")
  173. if gen_code == "false":
  174. continue
  175. save_if_changed(dest_folder + header_name, header.getvalue())
  176. save_if_changed(dest_folder + cpp_name, cpp.getvalue())
  177. if __name__ == "__main__":
  178. import argparse
  179. parser = argparse.ArgumentParser(
  180. description="generates h/cpp files from oxygine xml")
  181. parser.add_argument("xml", help="xml file to process")
  182. parser.add_argument(
  183. "-d", "--dest", help="destination folder for generated classes", default=".")
  184. args = parser.parse_args()
  185. gen2(args.xml, args.dest + "/", None)