package_level.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. from sys import modules
  2. from math import floor
  3. from bpy import app
  4. from time import strftime
  5. MAX_FLOAT_PRECISION_INT = 4
  6. MAX_FLOAT_PRECISION = '%.' + str(MAX_FLOAT_PRECISION_INT) + 'f'
  7. VERTEX_OUTPUT_PER_LINE = 50
  8. STRIP_LEADING_ZEROS_DEFAULT = False # false for .babylon
  9. #===============================================================================
  10. # module level formatting methods, called from multiple classes
  11. #===============================================================================
  12. def get_title():
  13. bl_info = get_bl_info()
  14. return bl_info['name'] + ' ver ' + format_exporter_version(bl_info)
  15. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  16. def format_exporter_version(bl_info = None):
  17. if bl_info is None:
  18. bl_info = get_bl_info()
  19. exporterVersion = bl_info['version']
  20. return str(exporterVersion[0]) + '.' + str(exporterVersion[1]) + '.' + str(exporterVersion[2])
  21. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  22. def blenderMajorMinorVersion():
  23. # in form of '2.77 (sub 0)'
  24. split1 = app.version_string.partition('.')
  25. major = split1[0]
  26. split2 = split1[2].partition(' ')
  27. minor = split2[0]
  28. return float(major + '.' + minor)
  29. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  30. def verify_min_blender_version():
  31. reqd = get_bl_info()['blender']
  32. # in form of '2.77 (sub 0)'
  33. split1 = app.version_string.partition('.')
  34. major = int(split1[0])
  35. if reqd[0] > major: return False
  36. split2 = split1[2].partition(' ')
  37. minor = int(split2[0])
  38. if reqd[1] > minor: return False
  39. split3 = split2[2].partition(' ')
  40. revision = int(split3[2][:1])
  41. if reqd[2] > revision: return False
  42. return True
  43. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  44. def getNameSpace(filepathMinusExtension):
  45. # assign nameSpace, based on OS
  46. if filepathMinusExtension.find('\\') != -1:
  47. return legal_js_identifier(filepathMinusExtension.rpartition('\\')[2])
  48. else:
  49. return legal_js_identifier(filepathMinusExtension.rpartition('/')[2])
  50. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  51. def getLayer(obj):
  52. # empties / nodes do not have layers
  53. if not hasattr(object, 'layers') : return -1;
  54. for idx, layer in enumerate(obj.layers):
  55. if layer:
  56. return idx
  57. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  58. # a class for getting the module name, exporter version, & reqd blender version in get_bl_info()
  59. class dummy: pass
  60. def get_bl_info():
  61. # .__module__ is the 'name of package.module', so strip after dot
  62. packageName = dummy.__module__.partition('.')[0]
  63. return modules.get(packageName).bl_info
  64. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  65. def legal_js_identifier(input):
  66. out = ''
  67. prefix = ''
  68. for char in input:
  69. if len(out) == 0:
  70. if char in '0123456789':
  71. # cannot take the chance that leading numbers being chopped of cause name conflicts, e.g (01.R & 02.R)
  72. prefix += char
  73. continue
  74. elif char.upper() not in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
  75. continue
  76. legal = char if char.upper() in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_' else '_'
  77. out += legal
  78. if len(prefix) > 0:
  79. out += '_' + prefix
  80. return out
  81. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  82. def format_f(num, stripLeadingZero = STRIP_LEADING_ZEROS_DEFAULT):
  83. s = MAX_FLOAT_PRECISION % num # rounds to N decimal places while changing to string
  84. s = s.rstrip('0') # strip trailing zeroes
  85. s = s.rstrip('.') # strip trailing .
  86. s = '0' if s == '-0' else s # nuke -0
  87. if stripLeadingZero:
  88. asNum = float(s)
  89. if asNum != 0 and asNum > -1 and asNum < 1:
  90. if asNum < 0:
  91. s = '-' + s[2:]
  92. else:
  93. s = s[1:]
  94. return s
  95. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  96. def format_matrix4(matrix):
  97. tempMatrix = matrix.copy()
  98. tempMatrix.transpose()
  99. ret = ''
  100. first = True
  101. for vect in tempMatrix:
  102. if (first != True):
  103. ret +=','
  104. first = False;
  105. ret += format_f(vect[0]) + ',' + format_f(vect[1]) + ',' + format_f(vect[2]) + ',' + format_f(vect[3])
  106. return ret
  107. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  108. def format_array3(array):
  109. return format_f(array[0]) + ',' + format_f(array[1]) + ',' + format_f(array[2])
  110. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  111. def format_array(array, indent = ''):
  112. ret = ''
  113. first = True
  114. nOnLine = 0
  115. for element in array:
  116. if (first != True):
  117. ret +=','
  118. first = False;
  119. ret += format_f(element)
  120. nOnLine += 1
  121. if nOnLine >= VERTEX_OUTPUT_PER_LINE:
  122. ret += '\n' + indent
  123. nOnLine = 0
  124. return ret
  125. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  126. def format_color(color):
  127. return format_f(color.r) + ',' + format_f(color.g) + ',' + format_f(color.b)
  128. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  129. def format_vector(vector, switchYZ = True):
  130. return format_f(vector.x) + ',' + format_f(vector.z) + ',' + format_f(vector.y) if switchYZ else format_f(vector.x) + ',' + format_f(vector.y) + ',' + format_f(vector.z)
  131. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  132. def format_vector_array(vectorArray, indent = ''):
  133. ret = ''
  134. first = True
  135. nOnLine = 0
  136. for vector in vectorArray:
  137. if (first != True):
  138. ret +=','
  139. first = False;
  140. ret += format_vector(vector)
  141. nOnLine += 3
  142. if nOnLine >= VERTEX_OUTPUT_PER_LINE:
  143. ret += '\n' + indent
  144. nOnLine = 0
  145. return ret
  146. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  147. def format_quaternion(quaternion):
  148. return format_f(quaternion.x) + ',' + format_f(quaternion.z) + ',' + format_f(quaternion.y) + ',' + format_f(-quaternion.w)
  149. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  150. def format_int(int):
  151. candidate = str(int) # when int string of an int
  152. if '.' in candidate:
  153. return format_f(floor(int)) # format_f removes un-neccessary precision
  154. else:
  155. return candidate
  156. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  157. def format_bool(bool):
  158. if bool:
  159. return 'true'
  160. else:
  161. return 'false'
  162. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  163. def post_rotate_quaternion(quat, angle):
  164. post = mathutils.Euler((angle, 0.0, 0.0)).to_matrix()
  165. mqtn = quat.to_matrix()
  166. quat = (mqtn*post).to_quaternion()
  167. return quat
  168. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  169. def scale_vector(vector, mult, xOffset = 0):
  170. ret = vector.copy()
  171. ret.x *= mult
  172. ret.x += xOffset
  173. ret.z *= mult
  174. ret.y *= mult
  175. return ret
  176. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  177. def same_matrix4(matA, matB):
  178. if(matA is None or matB is None): return False
  179. if (len(matA) != len(matB)): return False
  180. for i in range(len(matA)):
  181. if (format_f(matA[i][0]) != format_f(matB[i][0]) or
  182. format_f(matA[i][1]) != format_f(matB[i][1]) or
  183. format_f(matA[i][2]) != format_f(matB[i][2]) or
  184. format_f(matA[i][3]) != format_f(matB[i][3]) ):
  185. return False
  186. return True
  187. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  188. def same_vertex(vertA, vertB):
  189. if vertA is None or vertB is None: return False
  190. if (format_f(vertA.x) != format_f(vertB.x) or
  191. format_f(vertA.y) != format_f(vertB.y) or
  192. format_f(vertA.z) != format_f(vertB.z) ):
  193. return False
  194. return True
  195. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  196. def same_array(arrayA, arrayB):
  197. if(arrayA is None or arrayB is None): return False
  198. if len(arrayA) != len(arrayB): return False
  199. for i in range(len(arrayA)):
  200. if format_f(arrayA[i]) != format_f(arrayB[i]) : return False
  201. return True
  202. #===============================================================================
  203. # module level methods for writing JSON (.babylon) files
  204. #===============================================================================
  205. def write_matrix4(file_handler, name, matrix):
  206. file_handler.write(',"' + name + '":[' + format_matrix4(matrix) + ']')
  207. def write_array(file_handler, name, array):
  208. file_handler.write('\n,"' + name + '":[' + format_array(array) + ']')
  209. def write_array3(file_handler, name, array):
  210. file_handler.write(',"' + name + '":[' + format_array3(array) + ']')
  211. def write_color(file_handler, name, color):
  212. file_handler.write(',"' + name + '":[' + format_color(color) + ']')
  213. def write_vector(file_handler, name, vector, switchYZ = True):
  214. file_handler.write(',"' + name + '":[' + format_vector(vector, switchYZ) + ']')
  215. def write_vector_array(file_handler, name, vectorArray):
  216. file_handler.write('\n,"' + name + '":[' + format_vector_array(vectorArray) + ']')
  217. def write_quaternion(file_handler, name, quaternion):
  218. file_handler.write(',"' + name +'":[' + format_quaternion(quaternion) + ']')
  219. def write_string(file_handler, name, string, noComma = False):
  220. if noComma == False:
  221. file_handler.write(',')
  222. file_handler.write('"' + name + '":"' + string + '"')
  223. def write_float(file_handler, name, float):
  224. file_handler.write(',"' + name + '":' + format_f(float))
  225. def write_int(file_handler, name, int, noComma = False):
  226. if noComma == False:
  227. file_handler.write(',')
  228. file_handler.write('"' + name + '":' + format_int(int))
  229. def write_bool(file_handler, name, bool, noComma = False):
  230. if noComma == False:
  231. file_handler.write(',')
  232. file_handler.write('"' + name + '":' + format_bool(bool))