123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- from sys import modules
- from math import floor
- from mathutils import Euler, Matrix
- from bpy import app
- from time import strftime
- MAX_FLOAT_PRECISION_INT = 4
- MAX_FLOAT_PRECISION = '%.' + str(MAX_FLOAT_PRECISION_INT) + 'f'
- VERTEX_OUTPUT_PER_LINE = 50
- STRIP_LEADING_ZEROS_DEFAULT = False # false for .babylon
- #===============================================================================
- # module level formatting methods, called from multiple classes
- #===============================================================================
- def get_title():
- bl_info = get_bl_info()
- return bl_info['name'] + ' ver ' + format_exporter_version(bl_info)
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def format_exporter_version(bl_info = None):
- if bl_info is None:
- bl_info = get_bl_info()
- exporterVersion = bl_info['version']
- return str(exporterVersion[0]) + '.' + str(exporterVersion[1]) + '.' + str(exporterVersion[2])
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def blenderMajorMinorVersion():
- # in form of '2.77 (sub 0)'
- split1 = app.version_string.partition('.')
- major = split1[0]
-
- split2 = split1[2].partition(' ')
- minor = split2[0]
-
- return float(major + '.' + minor)
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def verify_min_blender_version():
- reqd = get_bl_info()['blender']
-
- # in form of '2.77 (sub 0)'
- split1 = app.version_string.partition('.')
- major = int(split1[0])
- if reqd[0] > major: return False
-
- split2 = split1[2].partition(' ')
- minor = int(split2[0])
- if reqd[1] > minor: return False
-
- split3 = split2[2].partition(' ')
- revision = int(split3[2][:1])
- if reqd[2] > revision: return False
-
- return True
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def getNameSpace(filepathMinusExtension):
- # assign nameSpace, based on OS
- if filepathMinusExtension.find('\\') != -1:
- return legal_js_identifier(filepathMinusExtension.rpartition('\\')[2])
- else:
- return legal_js_identifier(filepathMinusExtension.rpartition('/')[2])
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def getLayer(obj):
- # empties / nodes do not have layers
- if not hasattr(object, 'layers') : return -1;
- for idx, layer in enumerate(obj.layers):
- if layer:
- return idx
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- # a class for getting the module name, exporter version, & reqd blender version in get_bl_info()
- class dummy: pass
- def get_bl_info():
- # .__module__ is the 'name of package.module', so strip after dot
- packageName = dummy.__module__.partition('.')[0]
- return modules.get(packageName).bl_info
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def legal_js_identifier(input):
- out = ''
- prefix = ''
- for char in input:
- if len(out) == 0:
- if char in '0123456789':
- # cannot take the chance that leading numbers being chopped of cause name conflicts, e.g (01.R & 02.R)
- prefix += char
- continue
- elif char.upper() not in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
- continue
- legal = char if char.upper() in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_' else '_'
- out += legal
- if len(prefix) > 0:
- out += '_' + prefix
- return out
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def format_f(num, stripLeadingZero = STRIP_LEADING_ZEROS_DEFAULT):
- s = MAX_FLOAT_PRECISION % num # rounds to N decimal places while changing to string
- s = s.rstrip('0') # strip trailing zeroes
- s = s.rstrip('.') # strip trailing .
- s = '0' if s == '-0' else s # nuke -0
-
- if stripLeadingZero:
- asNum = float(s)
- if asNum != 0 and asNum > -1 and asNum < 1:
- if asNum < 0:
- s = '-' + s[2:]
- else:
- s = s[1:]
-
- return s
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def format_matrix4(matrix):
- tempMatrix = matrix.copy()
- tempMatrix.transpose()
- ret = ''
- first = True
- for vect in tempMatrix:
- if (first != True):
- ret +=','
- first = False;
- ret += format_f(vect[0]) + ',' + format_f(vect[1]) + ',' + format_f(vect[2]) + ',' + format_f(vect[3])
- return ret
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def format_array3(array):
- return format_f(array[0]) + ',' + format_f(array[1]) + ',' + format_f(array[2])
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def format_array(array, indent = ''):
- ret = ''
- first = True
- nOnLine = 0
- for element in array:
- if (first != True):
- ret +=','
- first = False;
- ret += format_f(element)
- nOnLine += 1
- if nOnLine >= VERTEX_OUTPUT_PER_LINE:
- ret += '\n' + indent
- nOnLine = 0
- return ret
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def format_color(color):
- return format_f(color.r) + ',' + format_f(color.g) + ',' + format_f(color.b)
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def format_vector(vector, switchYZ = True):
- 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)
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def format_vector_array(vectorArray, indent = ''):
- ret = ''
- first = True
- nOnLine = 0
- for vector in vectorArray:
- if (first != True):
- ret +=','
- first = False;
- ret += format_vector(vector)
- nOnLine += 3
- if nOnLine >= VERTEX_OUTPUT_PER_LINE:
- ret += '\n' + indent
- nOnLine = 0
- return ret
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def format_quaternion(quaternion):
- return format_f(quaternion.x) + ',' + format_f(quaternion.z) + ',' + format_f(quaternion.y) + ',' + format_f(-quaternion.w)
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def format_int(int):
- candidate = str(int) # when int string of an int
- if '.' in candidate:
- return format_f(floor(int)) # format_f removes un-neccessary precision
- else:
- return candidate
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def format_bool(bool):
- if bool:
- return 'true'
- else:
- return 'false'
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def post_rotate_quaternion(quat, angle):
- post = Euler((angle, 0.0, 0.0)).to_matrix()
- mqtn = quat.to_matrix()
- quat = (mqtn*post).to_quaternion()
- return quat
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def scale_vector(vector, mult, xOffset = 0):
- ret = vector.copy()
- ret.x *= mult
- ret.x += xOffset
- ret.z *= mult
- ret.y *= mult
- return ret
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def same_matrix4(matA, matB):
- if(matA is None or matB is None): return False
- if (len(matA) != len(matB)): return False
- for i in range(len(matA)):
- if (format_f(matA[i][0]) != format_f(matB[i][0]) or
- format_f(matA[i][1]) != format_f(matB[i][1]) or
- format_f(matA[i][2]) != format_f(matB[i][2]) or
- format_f(matA[i][3]) != format_f(matB[i][3]) ):
- return False
- return True
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def same_vertex(vertA, vertB):
- if vertA is None or vertB is None: return False
-
- if (format_f(vertA.x) != format_f(vertB.x) or
- format_f(vertA.y) != format_f(vertB.y) or
- format_f(vertA.z) != format_f(vertB.z) ):
- return False
- return True
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- def same_array(arrayA, arrayB):
- if(arrayA is None or arrayB is None): return False
- if len(arrayA) != len(arrayB): return False
- for i in range(len(arrayA)):
- if format_f(arrayA[i]) != format_f(arrayB[i]) : return False
- return True
- #===============================================================================
- # module level methods for writing JSON (.babylon) files
- #===============================================================================
- def write_matrix4(file_handler, name, matrix):
- file_handler.write(',"' + name + '":[' + format_matrix4(matrix) + ']')
- def write_array(file_handler, name, array):
- file_handler.write('\n,"' + name + '":[' + format_array(array) + ']')
- def write_array3(file_handler, name, array):
- file_handler.write(',"' + name + '":[' + format_array3(array) + ']')
- def write_color(file_handler, name, color):
- file_handler.write(',"' + name + '":[' + format_color(color) + ']')
- def write_vector(file_handler, name, vector, switchYZ = True):
- file_handler.write(',"' + name + '":[' + format_vector(vector, switchYZ) + ']')
- def write_vector_array(file_handler, name, vectorArray):
- file_handler.write('\n,"' + name + '":[' + format_vector_array(vectorArray) + ']')
- def write_quaternion(file_handler, name, quaternion):
- file_handler.write(',"' + name +'":[' + format_quaternion(quaternion) + ']')
- def write_string(file_handler, name, string, noComma = False):
- if noComma == False:
- file_handler.write(',')
- file_handler.write('"' + name + '":"' + string + '"')
- def write_float(file_handler, name, float):
- file_handler.write(',"' + name + '":' + format_f(float))
- def write_int(file_handler, name, int, noComma = False):
- if noComma == False:
- file_handler.write(',')
- file_handler.write('"' + name + '":' + format_int(int))
- def write_bool(file_handler, name, bool, noComma = False):
- if noComma == False:
- file_handler.write(',')
- file_handler.write('"' + name + '":' + format_bool(bool))
|