gen_view_code.py 8.9 KB

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