PageRenderTime 29ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/Core/Dependencies/Havok/Tools/Serialize/havokDomClass/domToClass.py

https://bitbucket.org/barakianc/nvidia-physx-and-apex-in-gge
Python | 850 lines | 835 code | 3 blank | 12 comment | 5 complexity | ea04ae96d4f2494ad0b27e18daab4f89 MD5 | raw file
  1. #
  2. # Confidential Information of Telekinesys Research Limited (t/a Havok). Not for disclosure or distribution without Havok's
  3. # prior written consent. This software contains code, techniques and know-how which is confidential and proprietary to Havok.
  4. # Level 2 and Level 3 source code contains trade secrets of Havok. Havok Software (C) Copyright 1999-2011 Telekinesys Research Limited t/a Havok. All Rights Reserved. Use of this software is subject to the terms of an end user license agreement.
  5. #
  6. #! /usr/bin/env python
  7. ###
  8. ### This script is used to generate an hkClass instance from an xml data binding.
  9. ### All the *class.cpp files in the havok tree are generated from this script.
  10. ###
  11. ### This script can be either be executed directly or imported
  12. ###
  13. _tkbms = """// TKBMS v1.0 -----------------------------------------------------
  14. //
  15. // PLATFORM : %s
  16. // PRODUCT : %s
  17. // VISIBILITY : %s
  18. //
  19. // ------------------------------------------------------TKBMS v1.0"""
  20. import re
  21. import sys
  22. import hkcToDom
  23. #import headerToDom
  24. havokTypes="""
  25. // plain old data types
  26. TYPE_BOOL, // "true", "false"
  27. TYPE_CHAR, // integers
  28. TYPE_INT8,
  29. TYPE_UINT8,
  30. TYPE_INT16,
  31. TYPE_UINT16,
  32. TYPE_INT32,
  33. TYPE_UINT32,
  34. TYPE_INT64,
  35. TYPE_UINT64,
  36. TYPE_REAL, // floating
  37. TYPE_HALF, // 16-bit float
  38. TYPE_VECTOR4,
  39. TYPE_QUATERNION,
  40. TYPE_MATRIX3,
  41. TYPE_ROTATION,
  42. TYPE_QSTRANSFORM,
  43. TYPE_MATRIX4,
  44. TYPE_TRANSFORM,
  45. TYPE_ZERO, // serialize as zero
  46. // complex types
  47. TYPE_POINTER, // generic pointer, see member flags for more info
  48. TYPE_FUNCTIONPOINTER,
  49. TYPE_ARRAY, // array
  50. TYPE_INPLACEARRAY, // inplace array
  51. TYPE_ENUM, // enumerated values
  52. TYPE_STRUCT, // simple struct
  53. TYPE_SIMPLEARRAY, // simple array (ptr(typed) and size only)
  54. TYPE_HOMOGENEOUSARRAY, // simple array of homogenous types, so is a class id followed by a void* ptr and size
  55. TYPE_CSTRING, // c-string, array of chars terminated by 0
  56. TYPE_ULONG,
  57. TYPE_VARIANT, // void* and hkClass*
  58. TYPE_FLAGS // named bitfield
  59. """
  60. def _extractHavokTypes():
  61. return [ 'hk%s' % m.lower() for m in re.findall('^\s*TYPE_([^,]*)(?m)', havokTypes) ]
  62. havokTypesList = _extractHavokTypes()
  63. floatingPointTypes = "hkHalf hkReal hkVector4 hkQuaternion hkMatrix3 hkRotation hkQsTransform hkMatrix4 hkTransform".split()
  64. aggregateTypes = "hkVector4 hkQuaternion hkMatrix3 hkRotation hkQsTransform hkMatrix4 hkTransform".split()
  65. def _readExtraTypes():
  66. import os
  67. fname = os.path.abspath( os.path.join( __file__, os.pardir, "typeMapping.txt") )
  68. ret = {}
  69. try:
  70. for line in open(fname).read().split():
  71. key, value = [ x.strip() for x in line.split(":") ]
  72. ret[ key ] = value
  73. except IOError:
  74. pass
  75. return fname, ret
  76. extraTypesFile, extraTypes = _readExtraTypes()
  77. def _enumerate(l):
  78. """Workalike for the python2.3 builtin.
  79. """
  80. return zip(range(len(l)), l)
  81. def removeFromDeclaration(decl, listToRemove):
  82. return "".join([x for x in decl.replace("*"," * ").replace("&"," & ").split() if x not in listToRemove])
  83. def removeFromDeclarationSpaced(decl, listToRemove):
  84. return " ".join([x for x in decl.replace("*"," * ").replace("&"," & ").split() if x not in listToRemove])
  85. def resolveExtraType(decl):
  86. """Get the enumerated type from a c++ type.
  87. """
  88. # the input decl must contains spaces among keywords (class, struct, union, enum), '*'/'&' chars, type name
  89. def resolveTypeNow(declWord):
  90. if declWord in extraTypes:
  91. return resolveTypeNow(removeFromDeclarationSpaced(extraTypes[declWord], ("const", "mutable")))
  92. else:
  93. return declWord
  94. return " ".join([resolveTypeNow(x) for x in decl.split()])
  95. def _typecode(mtype):
  96. """Get the enumerated type from a c++ type.
  97. """
  98. mtype = removeFromDeclarationSpaced( mtype.strip(), ("mutable","const") )
  99. mtype = mtype.replace(" *","*").replace(" &","&")
  100. # try to resolve custom type and clean up
  101. mtype = resolveExtraType(mtype)
  102. # template match
  103. for key, val in [
  104. ("hkArray<", "hkClassMember::TYPE_ARRAY"),
  105. ("hkRelArray<", "hkClassMember::TYPE_RELARRAY"),
  106. ("class hkRelArray<", "hkClassMember::TYPE_RELARRAY"), ##< Fix the parsers eventually
  107. ("hkInplaceArray<", "hkClassMember::TYPE_INPLACEARRAY"),
  108. ("hkSimpleArray<", "hkClassMember::TYPE_SIMPLEARRAY"),
  109. ("hkVariant ", "hkClassMember::TYPE_VARIANT"),
  110. ("hkEnum<", "hkClassMember::TYPE_ENUM"),
  111. ("hkFlags<", "hkClassMember::TYPE_FLAGS"),
  112. ("hkZero<", "hkClassMember::TYPE_ZERO"),
  113. ("hkHomogeneousArray<", "hkClassMember::TYPE_HOMOGENEOUSARRAY")
  114. ]:
  115. if mtype.startswith(key):
  116. return val
  117. # extract valuable type info only
  118. mtype = mtype.split("[")[0].strip()
  119. # exact match
  120. try:
  121. return {
  122. "hkUlong": "hkClassMember::TYPE_ULONG",
  123. "bool": "hkClassMember::TYPE_BOOL",
  124. "_Bool": "hkClassMember::TYPE_BOOL",
  125. "int": "hkClassMember::TYPE_INT32",
  126. "unsigned": "hkClassMember::TYPE_UINT32",
  127. "float": "hkClassMember::TYPE_REAL",
  128. "double": "hkClassMember::TYPE_REAL",
  129. "char": "hkClassMember::TYPE_CHAR",
  130. "char*": "hkClassMember::TYPE_CSTRING",
  131. "hkStringPtr": "hkClassMember::TYPE_STRINGPTR",
  132. "void": "hkClassMember::TYPE_VOID" }[mtype]
  133. except KeyError:
  134. pass
  135. # specials: pointer, enum, struct
  136. if mtype.endswith("*") or mtype.endswith("&"):
  137. return "hkClassMember::TYPE_POINTER"
  138. elif mtype.startswith("struct ") or mtype.startswith("class "):
  139. return "hkClassMember::TYPE_STRUCT"
  140. else:# mtype.startswith("hk"):
  141. if not mtype.lower() in havokTypesList:
  142. if not mtype in extraTypes:
  143. raise RuntimeError("'%s' not in Havok types list nor %s.\n" \
  144. "Maybe you meant 'class %s' or 'enum %s'?"% \
  145. (mtype, extraTypesFile, mtype, mtype))
  146. else:
  147. return _typecode(extraTypes[mtype])
  148. return "hkClassMember::TYPE_%s" % mtype[2:].upper()
  149. return ""
  150. def _getReferencedEnum(e):
  151. """Get the name of the c++ reflection object for enum e.
  152. """
  153. return e.replace("enum ","").split("<",1)[-1].replace("::","").split(",")[0].strip()
  154. def _getPointedClass(fullname):
  155. """Get the hkClass - must be type info only - no const or mutable
  156. """
  157. name = fullname.split("[")[0].strip()
  158. # Name can end with & and * (with spaces)
  159. while (name.endswith('*') or name.endswith('&')):
  160. # here we always expect '*' or '&' chars at the end of the declaration
  161. # so, strip the last char: '*' or '&'
  162. name = name[:-1].strip()
  163. name = name.strip().split()[-1]
  164. if name in "void hkBool bool char char* hkStringPtr float double hkHalf hkReal hkVector4 hkQuaternion hkMatrix3 " \
  165. "hkRotation hkQsTransform hkMatrix4 hkTransform".split():
  166. return None
  167. inttype = lambda(x) : [x+str(s) for s in [8,16,32,64]]
  168. if name in inttype("hkInt") or name in inttype("hkUint"):
  169. return None
  170. return name
  171. def _add_single_dot_f(val):
  172. """Add .f to float values to avoid double->float warnings.
  173. """
  174. val = val.strip()
  175. if val[-1] != 'f':
  176. try:
  177. float(val)
  178. except ValueError:
  179. if val.find("::") == -1:
  180. raise ValueError("'%s' is not a floating point value" % val)
  181. else:
  182. if val[-1] == ".":
  183. val = val + "0f"
  184. elif val.find('.') == -1:
  185. val = val + ".0f"
  186. else:
  187. val = val + "f"
  188. return val
  189. def _add_dot_fs(val):
  190. """Add .fs to multiple values
  191. """
  192. val = val.replace(" ","").replace("\t", "")
  193. b0 = val.find("(")
  194. if b0 != -1:
  195. bits = []
  196. while b0 != -1:
  197. b1 = val.find(")", b0)
  198. bits.append(", ".join([ _add_single_dot_f(f) for f in val[b0+1:b1].split(",")]))
  199. b0 = val.find("(", b1)
  200. return "(" + ") (".join(bits) + ")"
  201. else:
  202. return _add_single_dot_f(val)
  203. def _get_array_type(a):
  204. """Return the type of elements in an array.
  205. """
  206. # 'a' do not always have '>' bracket at the end
  207. t = a.split("<")[-1].split(">")[0].strip()
  208. if a.startswith("hkInplaceArray"):
  209. t = ",".join( a.split(",")[:-1] )
  210. return t
  211. def _get_type_from_pointer(a):
  212. """Return true if this is pointer to struct.
  213. """
  214. try:
  215. a = a.replace(" *","*").replace(" &","&")
  216. a = resolveExtraType(a)
  217. t = _typecode( a[:-1] )
  218. except RuntimeError:
  219. return "hkClassMember::TYPE_STRUCT"
  220. try:
  221. # we do not support pointer to void and pointer to pointer types
  222. if t == "hkClassMember::TYPE_POINTER" or t == "hkClassMember::TYPE_VOID":
  223. errMsg = "\nPointer to void and pointer to pointer types are not supported:\n\n\t%s\n" % a
  224. raise hkcToDom.HkcParseError(errMsg)
  225. except Exception:
  226. pass
  227. return t
  228. def _infocode(mtype):
  229. """Get the 'extra' information associated with a member.
  230. For arrays this is the contained type.
  231. For enums this is the size of the enum.
  232. """
  233. mtype = removeFromDeclarationSpaced( mtype.strip(), ("mutable","const") )
  234. # try to resolve custom type and clean up
  235. mtype = mtype.replace(" *","*").replace(" &","&")
  236. mtype = resolveExtraType(mtype)
  237. firstLessThan = mtype.find("<")#XXX
  238. if mtype[:firstLessThan] in ("hkArray", "hkInplaceArray", "hkSimpleArray", "hkZero", "hkRelArray", "class hkRelArray"): ##< Eventually fix the parsers
  239. elem = mtype[firstLessThan+1:-1]
  240. if mtype[:firstLessThan] == "hkInplaceArray":
  241. elem = ",".join( elem.split(",")[:-1] )
  242. return _typecode(elem)
  243. elif mtype.startswith("enum "):
  244. try:
  245. size = int( mtype.split(":")[1] )
  246. except ValueError:
  247. raise RuntimeError("found an unsized enum %s" % mtype.name)
  248. return {8:1, 16:2, 32:4}[size]
  249. return ""
  250. _pythonname = lambda x : x.replace("::","")
  251. class struct:
  252. def __init__(self, **args):
  253. self.__dict__.update(args)
  254. def _isFinishCtor(klass, method):
  255. return method.name == (klass.override_name.split("<")[0].split("::")[-1] if klass.override_name else klass.name) and len(method.parameter) == 1 and (removeFromDeclaration(method.parameter[0].type, ("class")) == "hkFinishLoadedObjectFlag" or removeFromDeclaration(method.parameter[0].type, ("class")) == "::hkFinishLoadedObjectFlag")
  256. def _hasFinishCtor(klass):
  257. return True in [ _isFinishCtor(klass, m) for m in klass.method ]
  258. def isGlobalType(pc):
  259. return True
  260. def isForVersioning(klass):
  261. return klass.serializable
  262. customAttributes = struct(imported={}, dictionary={})
  263. def domToClass(dom, debug=0, collectAll=False, pchfile=""):
  264. """Generate a c++ file from the given input hkClass dom.
  265. """
  266. def _getInternalMembersName(namespace, klass):
  267. hasNonPublicMembers = False in [m.visibility in ("","public") for m in klass.member]
  268. where = ("%s::%s%s" % (namespace, klass.name, "_typename" if klass.override_name else "")).lstrip(":")
  269. if hasNonPublicMembers and not collectAll:
  270. return "%s::Members" % where
  271. else:
  272. return "%sClass_Members" % where.replace("::","_")
  273. class ProgramList:
  274. """Class to format c++ code nicely.
  275. """
  276. def __init__(self):
  277. self.lines = []
  278. self.level = 0
  279. self.externs = {}
  280. def append(self, txt):
  281. for line in txt.split("\n"):
  282. self.level -= line.count("}")
  283. comment = self.level != 0 and line.find("///") != -1
  284. nline = "%s%s" % ((self.level + comment)* "\t", line)
  285. self.level += line.count("{")
  286. self.level += line.count("(")
  287. self.level -= line.count(")")
  288. if not self.externs.has_key(nline):
  289. self.lines.append(nline)
  290. if nline.startswith("extern"):
  291. self.externs[nline] = 1
  292. if debug: print nline
  293. ret = ProgramList()
  294. klasses = dict()
  295. def genMember(member, klass, namespace, notlast):
  296. """Generate a single member initializer.
  297. The fields of the initializer have different values depending
  298. on the type of the member. See Base/Reflection/hkClassMember.h for details.
  299. """
  300. def usesInternalType(klass, mclass):
  301. return klass.name not in ["hkClass", "hkClassMember", "hkClassEnum", "hkClassEnumItem"]\
  302. and mclass in ["hkClassClass", "hkClassMemberClass", "hkClassEnumClass", "hkClassEnumItemClass"]\
  303. and klass.name not in ["hkxSparselyAnimatedEnum", "hctAttributeDescription"] ### for compatibility, COM-434
  304. def getStructClass(mem):
  305. pc = _getPointedClass(mem)
  306. ret = "HK_NULL"
  307. structklass = None
  308. if pc:
  309. if collectAll:
  310. scopelist = ("%s::%s" % (klass.full_scope(), klass.name)).lstrip(":").split("::") # make list of names of 'pc' possible scope
  311. scopelist.append(pc.lstrip(":")) ## 'pc' may contain '::' in the name
  312. while len(scopelist):
  313. structname = _pythonname("".join(scopelist))
  314. if klasses.has_key(structname):
  315. structklass = klasses[structname]
  316. break
  317. del scopelist[len(scopelist)-2]
  318. if not structklass:
  319. print >>sys.__stderr__, "Class '%s' for member in '%s' is not found in class list and it is impossible to check if the class serializable."%(pc,klass.name)
  320. print >>sys.__stderr__, "Guessing it's a global"
  321. return "&%sClass" % pc.replace("::","")
  322. if not collectAll or isForVersioning(structklass):
  323. if isGlobalType(pc):
  324. ret = "&%sClass" % _pythonname(pc)
  325. else:
  326. ret = "&%s%sClass" % (namespace or klass.name, _pythonname(pc))
  327. return ret
  328. #
  329. # Overwrite the original value of member.type if overridetype is specified.
  330. #
  331. if member.overridetype:
  332. member_type = member.overridetype
  333. else:
  334. member_type = member.type
  335. # extract (member.name, mclass, menum, mtype, msubtype, marraysize, mflags, moffset )
  336. mname = klass.memberprefix + member.name
  337. mclass = "HK_NULL"
  338. menum = "HK_NULL"
  339. mtype = _typecode(member_type)
  340. mattr = "HK_NULL"
  341. if not collectAll and member.attributes:
  342. mattr = "&%s%s_%s_Attributes" % (namespace,klass.name,member.name)
  343. msubtype = "hkClassMember::TYPE_VOID"
  344. marraysize = 0
  345. # Get cstyle array size
  346. if member_type.find("[") != -1:
  347. member_type, rest = member_type.split("[")
  348. marraysize = rest.split("]")[0].strip()
  349. member_type += rest.split("]")[-1].strip() # handle array zeros: hkZero<int[3]>
  350. if mtype in ("hkClassMember::TYPE_ARRAY", "hkClassMember::TYPE_INPLACEARRAY", "hkClassMember::TYPE_ZERO", "hkClassMember::TYPE_SIMPLEARRAY", "hkClassMember::TYPE_RELARRAY"):
  351. msubtype = _infocode( member_type )
  352. if (msubtype == "hkClassMember::TYPE_POINTER" or msubtype == "hkClassMember::TYPE_STRUCT") and (member.flags.find("POINTER_VOIDSTAR") == -1):
  353. memClass = _get_array_type( member_type )
  354. mclass = getStructClass( removeFromDeclarationSpaced(memClass, ("const","class","struct")) )
  355. elif mtype == "hkClassMember::TYPE_POINTER" or mtype == "hkClassMember::TYPE_STRUCT":
  356. if mtype == "hkClassMember::TYPE_POINTER":
  357. msubtype = _get_type_from_pointer( removeFromDeclarationSpaced(member_type, ("mutable","const")) )
  358. if (mtype == "hkClassMember::TYPE_STRUCT" or msubtype == "hkClassMember::TYPE_STRUCT"):
  359. mclass = getStructClass( removeFromDeclarationSpaced(member_type, ("mutable","const","class","struct")) )
  360. elif mtype in ("hkClassMember::TYPE_ENUM", "hkClassMember::TYPE_FLAGS"):
  361. etype, esize = [x.strip() for x in member_type.split("<")[1].split(">")[0].split(",")]
  362. msubtype = _typecode( esize )
  363. if etype.startswith("enum "):
  364. etype = etype[5:].strip()
  365. if etype == "void":
  366. pass
  367. elif etype.find("::") != -1: #explicitly scoped -- this is always the case with LLVM
  368. menum = "%sEnum" % _getReferencedEnum(etype)
  369. else:
  370. menum = None
  371. # local scope
  372. for e in klass.enum:
  373. if etype == e.name:
  374. menum = "%s%s%sEnum" % (namespace.replace("::",""), klass.name, e.name)
  375. break
  376. # enclosing class scope
  377. if menum==None:
  378. for c in [ i for i in dom.file._class if i.name == namespace]:
  379. for e in c.enum:
  380. if etype == e.name:
  381. menum = "%s%sEnum" % (c.name, e.name)
  382. break
  383. # file scope
  384. if menum==None:
  385. menum = "%sEnum" % etype
  386. assert menum != None
  387. where = ("%s::%s%s" % (namespace, klass.name, "_typename" if klass.override_name else "")).lstrip(":")
  388. if member.overrideoffset: # hack for taggedunion - remove it
  389. offset = member.overrideoffset
  390. elif mtype == "hkClassMember::TYPE_HOMOGENEOUSARRAY": # offset is to the Type member
  391. offset = "HK_OFFSET_OF(%s,%sClass)" % (where, mname)
  392. else:
  393. offset = "HK_OFFSET_OF(%s,%s)" % (where, mname)
  394. if collectAll:
  395. offset = "0"
  396. flags = " | ".join( [ "%s" % x for x in member.flags.split() ] ) or "0"
  397. if member_type.startswith("enum ") and flags == "0":
  398. flags = "hkClassMember::ENUM_%i" % esize
  399. if member.align != 0:
  400. assert member.align in (8,16), "Only 8 & 16 byte alignment handled"
  401. flags += "|hkClassMember::ALIGN_%i"%member.align
  402. flags += "|hkClassMember::NOT_OWNED" if not member.owned else ""
  403. flags += "|hkClassMember::SERIALIZE_IGNORED" if not member.serialized else ""
  404. if usesInternalType(klass, mclass.replace("&","")):
  405. raise RuntimeError("\n%s::%s uses internal type %s\n"%(klass.name, mname, mclass.replace("&","")))
  406. ret.append('\t{ "%s", %s, %s, %s, %s, %s, %s, %s, %s }%s' % (member.name, mclass, menum, mtype, msubtype, marraysize, flags, offset, mattr, notlast and "," or "") )
  407. def genAllMembers(members, klass, namespace, klasses):
  408. """Generate the data block for all members.
  409. We have to do some extra work to make sure all objects
  410. we use are declared before use.
  411. """
  412. members = [m for m in members if m.reflected]
  413. if len(members):
  414. membersName = _getInternalMembersName(namespace, klass)
  415. qualifiers = ["", "static "][ membersName.find("::")==-1 ]
  416. if not collectAll:
  417. qualifiers += "const "
  418. if klass.override_name and membersName.find("::") != -1:
  419. ret.append("template<>")
  420. ret.append("%shkInternalClassMember %s[] =\n{" % (qualifiers,membersName))
  421. for i,m in _enumerate(members):
  422. genMember(m, klass, namespace, i!=len(members)-1)
  423. ret.append("};")
  424. def genDefaults(members, klass, namespace):
  425. defaults = []
  426. # 0 = non-zero default set
  427. # 1 = no default set
  428. # 2 = zero default set
  429. def specifiedAsZero(d):
  430. if d in (0, "0", "false", "0.0", "0.0f", "HK_NULL"):
  431. return 2
  432. elif d is None:
  433. return 1
  434. return 0
  435. defaultFound = False
  436. for i,m in _enumerate(members):
  437. if not m.default is None:
  438. defaultFound = True
  439. if not specifiedAsZero(m.default):
  440. mtype = m.type.split("[",1)
  441. carray = len(mtype)==2 and ("[%s"%mtype[1]) or ""
  442. mtype = mtype[0].strip()
  443. mtype = re.sub("(struct\s+)([^:])", r"\1%s%s::\2" % (namespace, klass.name), mtype)
  444. mtype = re.sub("^(class|struct)\s+", "", mtype)
  445. mtype = re.sub("hkZero<(.+)>", r"\1", mtype)
  446. mtype = re.sub("hkSimpleArray<(.+)>", r"\tstruct { void* p; int s; }", mtype)
  447. mtype = re.sub("hkHomogeneousArray", r"\tstruct { void* p; void* c; int s; }", mtype)
  448. mtype = mtype.replace("enum enum", "enum")
  449. mtype = mtype.replace("hkBool", "_hkBool")
  450. mtype = mtype.replace("hkStringPtr", "const char* /* hkStringPtr */")
  451. if m.type in aggregateTypes:
  452. mtype = "_"+mtype
  453. if mtype.startswith("hkEnum<") or mtype.startswith("hkFlags<"):
  454. enumstore = m.sourcecode.split(",")[-1].split(">")[0].strip()
  455. mtype = enumstore + " /* %s */"%mtype
  456. decl = "%s %s%s%s;" % (mtype, klass.memberprefix, m.name, carray)
  457. init = m.default
  458. #if m.type in floatingPointTypes:
  459. #init = _add_dot_fs(init)
  460. if m.type in aggregateTypes:
  461. init = "\t{%s}" % ",".join(init.split())
  462. defaults.append( (decl,init) )
  463. # We need to emit a list of default offsets, even when there are no non-zero defaults,
  464. # to signal that some of the defaults are zero. If no defaults at all, no list is generated
  465. if defaultFound:
  466. ret.append("namespace\n{")
  467. pyscope = "%s%s" % (namespace, klass.name)
  468. dstructtype = "%s_DefaultStruct" % pyscope
  469. ret.append("struct %s\n{" % dstructtype )
  470. ret.append("int s_defaultOffsets[%i];" % len(members))
  471. # some compilers cannot handle constants of these types so we fake it.
  472. ret.append("typedef hkInt8 _hkBool;")
  473. ret.append("typedef hkReal _hkVector4[4];")
  474. ret.append("typedef hkReal _hkQuaternion[4];")
  475. ret.append("typedef hkReal _hkMatrix3[12];")
  476. ret.append("typedef hkReal _hkRotation[12];")
  477. ret.append("typedef hkReal _hkQsTransform[12];")
  478. ret.append("typedef hkReal _hkMatrix4[16];")
  479. ret.append("typedef hkReal _hkTransform[16];")
  480. for d,i in defaults:
  481. ret.append(d)
  482. ret.append("};")
  483. ret.append("const %s %s_Default =\n{" % (dstructtype, pyscope));
  484. ret.append( "\t{%s}," % ",".join( [ ("HK_OFFSET_OF(%s,%s%s)" % (dstructtype,klass.memberprefix,m.name),"-1", "hkClassMember::HK_CLASS_ZERO_DEFAULT")[ specifiedAsZero(m.default) ] for m in members ] ) )
  485. ret.append(",".join([d[1] for d in defaults]))
  486. ret.append("};")
  487. ret.append("}")
  488. return "&%s_Default," % pyscope
  489. else: # no defaults
  490. return 'HK_NULL, // defaults'
  491. def genAttributes(members, klass, namespace):
  492. def genAttribute(attributes, symbol, klass, member):
  493. ret.append("// %s attributes" % symbol)
  494. attrs = []
  495. for attrname,val in attributes.items():
  496. if attrname.find(".") != -1:
  497. mod = attrname.rsplit(".",1)[0]
  498. customAttributes.dictionary.update( __import__("attributes."+mod).__dict__ )
  499. for attrname,val in attributes.items():
  500. keysym = "%s_%s" % (symbol, attrname.replace(".",""))
  501. try:
  502. generator = eval(attrname,customAttributes.dictionary)(symbol=keysym, member=member, klass=klass, caller="CPP")
  503. except (KeyError, NameError):
  504. print >>sys.stderr, "Attribute '%s' was not found." % (attrname, )
  505. else:
  506. code = eval("generator(%s)" % val, None, dict(generator=generator, true=True, false=False) )
  507. if code:
  508. ret.append( code )
  509. k = generator.__class__
  510. attrs.append( (attrname, keysym, k.__module__.replace("attributes","").replace(".","") + k.__name__) )
  511. if len(attrs):
  512. varname = "%s_Attributes" % symbol
  513. ret.append("static const hkInternalCustomAttributes::Attribute %sList[] =\n{" % (varname) )
  514. ret.append( ",\n".join( '\t{ "%s", &%s, &%sClass }' % attr for attr in attrs ) )
  515. ret.append("};")
  516. ret.append("static const hkInternalCustomAttributes %s = { %sList, HK_COUNT_OF(%sList) };" % (varname, varname, varname) )
  517. return "reinterpret_cast<const hkCustomAttributes*>(&%s)," % varname
  518. return 'HK_NULL, // attributes'
  519. for member in members:
  520. if member.attributes:
  521. symbol = "%s%s_%s" % (namespace, klass.name, member.name)
  522. genAttribute( member.attributes, symbol, klass, member)
  523. if klass.attributes:
  524. symbol = "%s%s" % (namespace, klass.name)
  525. return genAttribute( klass.attributes, symbol, klass, None)
  526. return 'HK_NULL, // attributes'
  527. def genAllExterns(classList):
  528. declarations = []
  529. def doExterns(classList, namespace):
  530. for klass in classList:
  531. klasses[_pythonname("%s%s"%(namespace,klass.name))] = klass
  532. if not collectAll or isForVersioning(klass):
  533. # declare pointer types used
  534. for i,m in _enumerate(klass.member):
  535. mtype = m.type.split("[")[0].strip()
  536. mtype = removeFromDeclarationSpaced(mtype, ("mutable","const"))
  537. #mtype = " ".join( [b for b in m.type.split() if b!="const"] )
  538. if mtype.endswith("*") or mtype.startswith("class ") or mtype.startswith("struct "):
  539. if (mtype.endswith("*") and _get_type_from_pointer(mtype) != "hkClassMember::TYPE_STRUCT"):
  540. pc = None
  541. elif mtype.find("<") != -1:
  542. pc = None
  543. else:
  544. pc = _getPointedClass(mtype)
  545. if pc:
  546. cname = "%s%s" % ("" if isGlobalType(pc) else klass.name, pc)
  547. declarations.append("extern const hkClass %sClass;" % (cname))
  548. elif (mtype.startswith("hkEnum<") or mtype.startswith("hkFlags<")) and mtype.find("::") != -1:
  549. declarations.append("extern const hkClassEnum* %sEnum;" % (_getReferencedEnum(mtype)) )
  550. elif (mtype.startswith("hkArray<") or mtype.startswith("hkSimpleArray<") or mtype.startswith("hkInplaceArray<") or mtype.startswith("hkRelArray<") or mtype.startswith("class hkRelArray<")): # Eventually fix the parsers
  551. pc = _getPointedClass(removeFromDeclarationSpaced(_get_array_type(mtype), ("*","&")))
  552. if pc:
  553. cname = "%s%s" % ("" if isGlobalType(pc) else klass.name, pc)
  554. declarations.append("extern const hkClass %sClass;" % (cname) )
  555. doExterns(klass._class, klass.name)
  556. doExterns(classList, "")
  557. if len(declarations):
  558. ret.append("\n// External pointer and enum types")
  559. declarations.sort()
  560. lastd = None
  561. for d in declarations:
  562. if d != lastd:
  563. r = d.replace("::","")
  564. if collectAll and r.find("hkClassEnum*") == -1:
  565. r = r.replace(" const "," ")
  566. ret.append(r)
  567. ## def genConstructor(klass):
  568. ## """Generate the constructor for the class.
  569. ## """
  570. ## # declare arrays of nonzero defaults
  571. ## def canonicalify(s):
  572. ## return ", ".join(s.replace("{"," { ").replace("}", " } ").split()).replace("{,","{").replace(", }"," }")
  573. ## # define any static arrays used in initialization
  574. ## for m in klass.member:
  575. ## if m.default and m.default.strip():
  576. ## default = m.default.strip()
  577. ## if m.type.find("hkArray") != -1:
  578. ## assert default[0]=="(" and default[-1]==")" and "Array default must be bracketed with ()"
  579. ## default = default[1:-1]
  580. ## atype = _get_array_type(m.type)
  581. ## if atype in ("hkVector4", "hkQuaternion", "hkMatrix3", "hkRotation", "hkMatrix4", "hkTransform"):
  582. ## struct = "Struct"
  583. ## elif atype.startswith("struct") and atype.find("::") == -1:
  584. ## atype = atype.replace("struct ", "struct %s::" % klass.name)
  585. ## struct = ""
  586. ## else:
  587. ## struct = ""
  588. ## ret.append("static const %s%s %s%sInit[] = { %s };" % (atype, struct, klass.name, m.name, canonicalify(default)))
  589. ## elif m.type.find("[") != -1:
  590. ## atype, nelem = m.type.split("[")
  591. ## nelem = int( nelem.split("]")[0] )
  592. ## if default.startswith("("):
  593. ## default = default[1:-1]
  594. ## if atype in ("hkVector4", "hkQuaternion", "hkMatrix3", "hkRotation", "hkMatrix4", "hkTransform"):
  595. ## struct = "Struct"
  596. ## else:
  597. ## struct = ""
  598. ## ret.append("static const %s%s %s%sInit[%i] = { %s };" % (atype, struct, klass.name, m.name, nelem, canonicalify(default)))
  599. ## # define constructor
  600. ## ret.append("\n%s::%s()\n{" % (klass.name, klass.name))
  601. ##
  602. ## # output member initializers
  603. ## for m in klass.member:
  604. ## ret.append( _initcode(klass.name, m.name, m.type, m.default))
  605. ##
  606. ## ret.append("}\n")
  607. def genClass(klass, namespace):
  608. """Generate a single class.
  609. """
  610. def genReflectionDefinition(klass, namespace=""):
  611. if klass.name == "hkBaseObject" or (klass.abstract and klass.override_name):
  612. return ""
  613. reflectiondefine = "HK_REFLECTION_DEFINE"
  614. if namespace:
  615. reflectiondefine = reflectiondefine + "_SCOPED"
  616. reflectiondefine = reflectiondefine + ((klass.abstract and "_ABSTRACT") or (klass.vtable and "_VIRTUAL") or (_hasFinishCtor(klass) and "_NONVIRTUAL") or "_SIMPLE")
  617. if klass.override_name:
  618. reflectiondefine += "_TEMPLATED"
  619. params = "%s%s, %s" % (klass.name, "_typename" if klass.override_name else "", klass.name)
  620. if namespace:
  621. params = "%s,%s,%s"%(namespace,namespace.replace("::",""),params)
  622. return "%s(%s);"%(reflectiondefine,params)
  623. namespace_klass_name = ("%s::%s" % (namespace, klass.name)).lstrip(":")
  624. # nested enums and structs
  625. if klass.reflected and (not collectAll or isForVersioning(klass)):
  626. genEnums(klass.enum, namespace_klass_name)
  627. for s in klass._class:
  628. genClass(s, namespace_klass_name)
  629. # check if klass is up to the requirements
  630. if not klass.reflected or (collectAll and not isForVersioning(klass)):
  631. return
  632. ret.append("\n//\n// Class %s\n//" % namespace_klass_name)
  633. if klass.override_name and not collectAll:
  634. ret.append("typedef %s %s_typename;\n\n" % (klass.override_name, namespace_klass_name))
  635. # members
  636. attributes = genAttributes(klass.member, klass, namespace) if not collectAll else 'HK_NULL, // attributes'
  637. genAllMembers(klass.member, klass, namespace, klasses)
  638. defaults = genDefaults(klass.member, klass, namespace)
  639. numInterfaces = len(klass.interface)
  640. if not klass.parent and klass.vtable:
  641. numInterfaces = 1
  642. const = ["const ",""][ collectAll ]
  643. if klass.parent:
  644. parent = "&%sClass" % (_pythonname(klass.parent))
  645. ret.append("extern %shkClass %s;\n" % (const, parent[1:]))
  646. else:
  647. parent = "HK_NULL"
  648. ret.append('extern %shkClass %sClass;' % (const, _pythonname(namespace_klass_name)) )
  649. ret.append('%shkClass %sClass(' % (const, _pythonname(namespace_klass_name)) )
  650. scoped_klass_name = namespace_klass_name.replace(':','')
  651. ret.append('\"%s\",' % scoped_klass_name)
  652. ret.append('%s, // parent' % parent)
  653. if klass.override_name:
  654. namespace_klass_name = ("%s::%s" % (namespace, klass.override_name)).lstrip(":")
  655. else:
  656. size_name = namespace_klass_name
  657. if not collectAll:
  658. ret.append('sizeof(%s),' % (namespace_klass_name))
  659. else:
  660. ret.append('0,')
  661. #ret.append(numInterfaces and ('%sClass_Interfaces,' % pythonname(namespace_klass_name)) or "HK_NULL,")
  662. ret.append("HK_NULL,")
  663. ret.append('%i, // interfaces' % numInterfaces )
  664. visible_enums = [k for k in klass.enum if k.reflected]
  665. ret.append(len(visible_enums) and ('reinterpret_cast<const hkClassEnum*>(%sEnums),' % _pythonname(namespace_klass_name)) or "HK_NULL,")
  666. ret.append('%s, // enums' % len(visible_enums) )
  667. ret.append(len(klass.member) and ('reinterpret_cast<const hkClassMember*>(%s),' % _getInternalMembersName(namespace,klass)) or "HK_NULL,")
  668. ret.append(len(klass.member) and ('HK_COUNT_OF(%s),' % _getInternalMembersName(namespace,klass)) or "0,")
  669. ret.append(defaults)
  670. ret.append(attributes)
  671. ret.append("0, // flags" if klass.serializable else "hkClass::FLAGS_NOT_SERIALIZABLE,")
  672. ret.append("hkUint32(%i) // version" % klass.version )
  673. ret.append(');')
  674. if not collectAll:
  675. ret.append(genReflectionDefinition(klass, namespace))
  676. def genEnums(enums, namespace):
  677. enums = [e for e in enums if e.reflected]
  678. if namespace == "":
  679. localname = dom.localfilename.replace("\\","_").replace("/","_").replace(":","_").split(".")[0]
  680. else:
  681. localname = _pythonname(namespace)
  682. def itemsName(e):
  683. return "%s%sEnumItems" % (localname, e.name)
  684. for enum in enums:
  685. localnamespace = namespace
  686. if localnamespace == "" and enum.scope:
  687. localnamespace = enum.scope
  688. print "%s %s %s" % (enum.name, localnamespace, enum.scope)
  689. ret.append("\n//\n// Enum %s::%s\n//" % (localnamespace, enum.name) )
  690. ret.append("static const hkInternalClassEnumItem %s[] =\n{" % itemsName(enum) )
  691. for i in enum.item:
  692. value = str(i.value)
  693. value += "u" if i.value >= (1<<31) else ""
  694. if i.initializer and i.initializer != str(i.value):
  695. value += "/*%s*/" % i.initializer
  696. ret.append("\t{%s, \"%s\"}," % (value, i.name))
  697. ret.append("};")
  698. if len(enums):
  699. localnamespace = namespace
  700. if localnamespace == "" and enum.scope:
  701. localnamespace = enum.scope
  702. ret.append('static const hkInternalClassEnum %sEnums[] = {' % localname)
  703. for i,e in _enumerate(enums):
  704. comma = (",","")[i+1==len(enums)]
  705. ret.append('\t{"%s", %s, %i, HK_NULL, 0 }%s' % (e.name, itemsName(e), len(e.item), comma) )
  706. ret.append('};')
  707. for i,e in _enumerate(enums):
  708. ret.append('const hkClassEnum* %s%sEnum = reinterpret_cast<const hkClassEnum*>(&%sEnums[%i]);' % (localnamespace.replace(":",""), e.name, localname, i))
  709. def genFile(file):
  710. filename = dom.localfilename.replace("\\","/")
  711. if not collectAll:
  712. ret.append("\n// WARNING: THIS FILE IS GENERATED. EDITS WILL BE LOST.")
  713. ret.append("// Generated from '%s'" % filename)
  714. ret.append("#include <%s>" % (pchfile or dom.pchfile or "Common/Base/hkBase.h"))
  715. ret.append("#include <Common/Base/Reflection/hkClass.h>")
  716. ret.append("#include <Common/Base/Reflection/hkInternalClassMember.h>")
  717. ret.append("#include <Common/Base/Reflection/hkTypeInfo.h>")
  718. ret.append("#include <Common/Base/Reflection/Attributes/hkAttributes.h>")
  719. ret.append("#include <%s>" % filename.replace(".hkclass", ".h") )
  720. ret.append("#define True true")
  721. ret.append("#define False false")
  722. ret.append("" if not file.overridedestination else 'HK_REFLECTION_CLASSFILE_HEADER("%s");\n' % filename )
  723. # should really use xml file decl order here
  724. ret.append("")
  725. if len(file.enum) or len(file.struct):
  726. ret.append("//\n// Global\n//")
  727. genEnums(file.enum + file.taggedunion, "")
  728. allClasses = file._class[:]
  729. for u in file.taggedunion:
  730. ret.append("// %s" % u.name)
  731. klass = hkcToDom.Class()
  732. klass.name = u.name
  733. klass.enum.append( u )
  734. klass.reflected = True
  735. def genMember(i):
  736. m = hkcToDom.Member()
  737. m.name = i.name
  738. m.type = "class %s*" % i.klass
  739. m.overrideoffset = "0"
  740. return m
  741. klass.member += [ genMember(i) for i in u.item if i.klass!="HK_NULL" ]
  742. allClasses.append( klass )
  743. genAllExterns(allClasses)
  744. for c in allClasses:
  745. classScope = ""
  746. if c.scope and c.scope != "::":
  747. classScope = c.scope
  748. genClass(c, classScope)
  749. def genDocument(doc):
  750. """Generate the skeleton.
  751. """
  752. ## if not collectAll:
  753. ## platform = re.sub("[^\s]*SPU[^\s]*", "", doc.file.platform) #HACK
  754. ## ret.append(_tkbms % ((platform or 'ALL'), (doc.file.product or 'PHYSICS'), (doc.file.visibility or 'PUBLIC')) )
  755. genFile(doc.file)
  756. ret.append("")
  757. genDocument(dom)
  758. return "\n".join(ret.lines)
  759. def main():
  760. print "This file should not be called directly"
  761. if __name__=="__main__":
  762. main()
  763. #
  764. # Havok SDK - NO SOURCE PC DOWNLOAD, BUILD(#20110914)
  765. #
  766. # Confidential Information of Havok. (C) Copyright 1999-2011
  767. # Telekinesys Research Limited t/a Havok. All Rights Reserved. The Havok
  768. # Logo, and the Havok buzzsaw logo are trademarks of Havok. Title, ownership
  769. # rights, and intellectual property rights in the Havok software remain in
  770. # Havok and/or its suppliers.
  771. #
  772. # Use of this software for evaluation purposes is subject to and indicates
  773. # acceptance of the End User licence Agreement for this product. A copy of
  774. # the license is included with this software and is also available at www.havok.com/tryhavok.
  775. #
  776. #