Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 
 
 

291 rader
9.3 KiB

  1. #!/usr/bin/env python
  2. # -*- Coding: UTF-8 -*-
  3. # ---------------------------------------------------------------------------
  4. # Open Asset Import Library (ASSIMP)
  5. # ---------------------------------------------------------------------------
  6. #
  7. # Copyright (c) 2006-2010, ASSIMP Development Team
  8. #
  9. # All rights reserved.
  10. #
  11. # Redistribution and use of this software in source and binary forms,
  12. # with or without modification, are permitted provided that the following
  13. # conditions are met:
  14. #
  15. # * Redistributions of source code must retain the above
  16. # copyright notice, this list of conditions and the
  17. # following disclaimer.
  18. #
  19. # * Redistributions in binary form must reproduce the above
  20. # copyright notice, this list of conditions and the
  21. # following disclaimer in the documentation and/or other
  22. # materials provided with the distribution.
  23. #
  24. # * Neither the name of the ASSIMP team, nor the names of its
  25. # contributors may be used to endorse or promote products
  26. # derived from this software without specific prior
  27. # written permission of the ASSIMP Development Team.
  28. #
  29. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  30. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  31. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  32. # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  33. # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  34. # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  35. # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  36. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  37. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  38. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  39. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  40. # ---------------------------------------------------------------------------
  41. """Update PyAssimp's data structures to keep up with the
  42. C/C++ headers.
  43. This script is meant to be executed in the source tree, directly from
  44. port/PyAssimp/gen
  45. """
  46. import os
  47. import re
  48. #==[regexps]=================================================
  49. # Clean desc
  50. REdefine = re.compile(r''
  51. r'(?P<desc>)' # /** *desc */
  52. r'#\s*define\s(?P<name>[^(\n]+?)\s(?P<code>.+)$' # #define name value
  53. , re.MULTILINE)
  54. # Get structs
  55. REstructs = re.compile(r''
  56. #r'//\s?[\-]*\s(?P<desc>.*?)\*/\s' # /** *desc */
  57. #r'//\s?[\-]*(?P<desc>.*?)\*/(?:.*?)' # garbage
  58. r'//\s?[\-]*\s(?P<desc>.*?)\*/\W*?' # /** *desc */
  59. r'struct\s(?:ASSIMP_API\s)?(?P<name>[a-z][a-z0-9_]\w+\b)' # struct name
  60. r'[^{]*?\{' # {
  61. r'(?P<code>.*?)' # code
  62. r'\}\s*(PACK_STRUCT)?;' # };
  63. , re.IGNORECASE + re.DOTALL + re.MULTILINE)
  64. # Clean desc
  65. REdesc = re.compile(r''
  66. r'^\s*?([*]|/\*\*)(?P<line>.*?)' # * line
  67. , re.IGNORECASE + re.DOTALL + re.MULTILINE)
  68. # Remove #ifdef __cplusplus
  69. RErmifdef = re.compile(r''
  70. r'#ifdef __cplusplus' # #ifdef __cplusplus
  71. r'(?P<code>.*)' # code
  72. r'#endif(\s*//\s*!?\s*__cplusplus)*' # #endif
  73. , re.IGNORECASE + re.DOTALL)
  74. # Replace comments
  75. RErpcom = re.compile(r''
  76. r'\s*(/\*+\s|\*+/|\B\*\s|///?!?)' # /**
  77. r'(?P<line>.*?)' # * line
  78. , re.IGNORECASE + re.DOTALL)
  79. # Restructure
  80. def GetType(type, prefix='c_'):
  81. t = type
  82. while t.endswith('*'):
  83. t = t[:-1]
  84. if t[:5] == 'const':
  85. t = t[5:]
  86. # skip some types
  87. if t in skiplist:
  88. return None
  89. t = t.strip()
  90. types = {'unsigned int':'uint', 'unsigned char':'ubyte',}
  91. if t in types:
  92. t = types[t]
  93. t = prefix + t
  94. while type.endswith('*'):
  95. t = "POINTER(" + t + ")"
  96. type = type[:-1]
  97. return t
  98. def restructure( match ):
  99. type = match.group("type")
  100. if match.group("struct") == "":
  101. type = GetType(type)
  102. elif match.group("struct") == "C_ENUM ":
  103. type = "c_uint"
  104. else:
  105. type = GetType(type[2:], '')
  106. if type is None:
  107. return ''
  108. if match.group("index"):
  109. type = type + "*" + match.group("index")
  110. result = ""
  111. for name in match.group("name").split(','):
  112. result += "(\"" + name.strip() + "\", "+ type + "),"
  113. return result
  114. RErestruc = re.compile(r''
  115. r'(?P<struct>C_STRUCT\s|C_ENUM\s|)' # [C_STRUCT]
  116. r'(?P<type>\w+\s?\w+?[*]*)\s' # type
  117. #r'(?P<name>\w+)' # name
  118. r'(?P<name>\w+|[a-z0-9_, ]+)' # name
  119. r'(:?\[(?P<index>\w+)\])?;' # []; (optional)
  120. , re.DOTALL)
  121. #==[template]================================================
  122. template = """
  123. class $NAME$(Structure):
  124. \"\"\"
  125. $DESCRIPTION$
  126. \"\"\"
  127. $DEFINES$
  128. _fields_ = [
  129. $FIELDS$
  130. ]
  131. """
  132. templateSR = """
  133. class $NAME$(Structure):
  134. \"\"\"
  135. $DESCRIPTION$
  136. \"\"\"
  137. $DEFINES$
  138. $NAME$._fields_ = [
  139. $FIELDS$
  140. ]
  141. """
  142. skiplist = ("FileIO", "File", "locateFromAssimpHeap",'LogStream','MeshAnim','AnimMesh')
  143. #============================================================
  144. def Structify(fileName):
  145. file = open(fileName, 'r')
  146. text = file.read()
  147. result = []
  148. # Get defines.
  149. defs = REdefine.findall(text)
  150. # Create defines
  151. defines = "\n"
  152. for define in defs:
  153. # Clean desc
  154. desc = REdesc.sub('', define[0])
  155. # Replace comments
  156. desc = RErpcom.sub('#\g<line>', desc)
  157. defines += desc
  158. if len(define[2].strip()):
  159. # skip non-integral defines, we can support them right now
  160. try:
  161. int(define[2],0)
  162. except:
  163. continue
  164. defines += " "*4 + define[1] + " = " + define[2] + "\n"
  165. # Get structs
  166. rs = REstructs.finditer(text)
  167. fileName = os.path.basename(fileName)
  168. print fileName
  169. for r in rs:
  170. name = r.group('name')[2:]
  171. desc = r.group('desc')
  172. # Skip some structs
  173. if name in skiplist:
  174. continue
  175. text = r.group('code')
  176. # Clean desc
  177. desc = REdesc.sub('', desc)
  178. desc = "See '"+ fileName +"' for details." #TODO
  179. # Remove #ifdef __cplusplus
  180. text = RErmifdef.sub('', text)
  181. # Whether the struct contains more than just POD
  182. primitive = text.find('C_STRUCT') == -1
  183. # Restructure
  184. text = RErestruc.sub(restructure, text)
  185. # Replace comments
  186. text = RErpcom.sub('# \g<line>', text)
  187. text = text.replace("),#", "),\n#")
  188. text = text.replace("#", "\n#")
  189. text = "".join([l for l in text.splitlines(True) if not l.strip().endswith("#")]) # remove empty comment lines
  190. # Whether it's selfreferencing: ex. struct Node { Node* parent; };
  191. selfreferencing = text.find('POINTER('+name+')') != -1
  192. complex = name == "Scene"
  193. # Create description
  194. description = ""
  195. for line in desc.split('\n'):
  196. description += " "*4 + line.strip() + "\n"
  197. description = description.rstrip()
  198. # Create fields
  199. fields = ""
  200. for line in text.split('\n'):
  201. fields += " "*12 + line.strip() + "\n"
  202. fields = fields.strip()
  203. if selfreferencing:
  204. templ = templateSR
  205. else:
  206. templ = template
  207. # Put it all together
  208. text = templ.replace('$NAME$', name)
  209. text = text.replace('$DESCRIPTION$', description)
  210. text = text.replace('$FIELDS$', fields)
  211. if ((name.lower() == fileName.split('.')[0][2:].lower()) and (name != 'Material')) or name == "String":
  212. text = text.replace('$DEFINES$', defines)
  213. else:
  214. text = text.replace('$DEFINES$', '')
  215. result.append((primitive, selfreferencing, complex, text))
  216. return result
  217. text = "#-*- coding: UTF-8 -*-\n\n"
  218. text += "from ctypes import POINTER, c_int, c_uint, c_size_t, c_char, c_float, Structure, c_char_p, c_double, c_ubyte\n\n"
  219. structs1 = ""
  220. structs2 = ""
  221. structs3 = ""
  222. structs4 = ""
  223. path = '../../../include/assimp'
  224. files = os.listdir (path)
  225. #files = ["aiScene.h", "aiTypes.h"]
  226. for fileName in files:
  227. if fileName.endswith('.h'):
  228. for struct in Structify(os.path.join(path, fileName)):
  229. primitive, sr, complex, struct = struct
  230. if primitive:
  231. structs1 += struct
  232. elif sr:
  233. structs2 += struct
  234. elif complex:
  235. structs4 += struct
  236. else:
  237. structs3 += struct
  238. text += structs1 + structs2 + structs3 + structs4
  239. file = open('structs.py', 'w')
  240. file.write(text)
  241. file.close()
  242. print("Generation done. You can now review the file 'structs.py' and merge it.")