from Blender import * from Blender.Mathutils import * from test_fbx import test_fbx fbx_test = test_fbx do_debug = 0 class FBXMultipleKeyBag (list): pass #FBX dicts are kindof like normal dicts, #only they support more then one bucket using a key. class FBXDict (object): _list = 0 #list for preserving order _dict = 0 #dict for fast access name = 0 value = 0 def __init__(self, name): self._list = [] self._dict = {} self.name = name self.value = 0 def __getitem__(self, item, includeall=0): """ includeall means if there are multiple keys of the same name, a list of their values are returned """ global do_debug if self._dict.has_key(item)==0: raise KeyError("item no in dict") if do_debug == 0 or includeall == 1: if type(self._dict[item]) == type(FBXMultipleKeyBag): return self._dict[item][0] else: return self._dict[item] else: return self._dict[item] def __iter__(self): return self._list.__iter__() #convert integer number of tabs to whitespace def tlevel(self, level): s = "" for x in xrange(level): s += " " return s def __repr__(self, tlevel=0): #return self._dict.__repr__() s = "" tab = self.tlevel(tlevel) for l in self._list: if type(l[1]) == FBXDict: s += "\n" + tab + l[0] + ": " if type(l[1].value) == list: i = 0 for v in l[1].value: if type(v) == str: s += "\"" + str(v) + "\"" else: s += repr(v) if i != len(l[1].value)-1: s += ", " i += 1 s += " " elif type(l[1].value) == str and len(l[1].value) > 0: s += "\"" + l[1].value + "\" " s += "{\n" s += l[1].__repr__(tlevel + 1) s += tab +"}\n" elif type(l[1]) == list: i = 0 s += tab + l[0] + ": " for item in l[1]: if type(item) == str: s += "\"" + str(item) + "\"" else: s += repr(item) if i != len(l[1])-1: s += ", " i += 1 s += "\n" #have special case for strings, to output "string" instead of 'string' elif type(l[1]) == str: s += tab + l[0] + ": \"" + str(l[1]) + "\"\n" else: s += tab + l[0] + ": " + repr(l[1]) + "\n" return s def __str__(self): return self.__repr__() def getitem(self, item, includeall=0): return self.__getitem__(item, includeall) def __setitem__(self, item, val): self._list.append([item, val]) #check for if this key name already exists, and if #so keep track of the different values by putting them #in a FBXMultipleKeyBag, which is just a straight #copy (subclass) of list. if self._dict.has_key(item) == 0: self._dict[item] = val else: if type(self._dict[item]) != type(FBXMultipleKeyBag): self._dict[item] = FBXMultipleKeyBag([self._dict[item], val]) else: self._dict[item].append(val) def PreprocessFBX(st): def stripwhite(l): l = l.replace("\t", "").replace(" ", "").replace("\n", "").replace("\r", "") return l lines = [""] in_comment = 0 for s in st: if s == "\n": lines.append("") in_comment = 0 continue if s == ";": in_comment = 1 if s == "\r": continue #don't include \r's if in_comment==0: lines[-1] += s lines2 = [] for l in lines: if len(stripwhite(l)) > 0: lines2.append(l) lines = lines2 # remove comments and \n #lines = [l[:-1].rstrip() for l in lines if not l.lstrip().startswith(';')] # remove whitespace #lines = [l for l in lines if l] #this part of the code written by campbell barton, aka ideasman_42 # remove multiline float lists def unmultiline(i): lines[i-1] = lines[i-1] + lines.pop(i).lstrip() # Multiline floats, used for verts and matricies, this is harderto read so detect and make into 1 line. i = 0 lastl = 0 while i < len(lines): l = lines[i].strip() if l.startswith(',') or (lastl!=0 and lastl.endswith(",")): unmultiline(i) i-=1 try: float(l.split(',', 1)[0]) unmultiline(i) i-=1 except: pass lastl = l i += 1 return lines """ # remove comments and \n lines = [l[:-1].rstrip() for l in lines if not l.lstrip().startswith(';')] # remove whitespace lines = [l for l in lines if l] """ def isnumeral(st): if len(st) == 0: return 0 d = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '-'] for s in st: if s not in d: return 0 return 1 def ParseValue(val): #break val into blocks blocks = [""] in_str = 0 for s in val: if s == "\"": #\" if in_str == 0: in_str = 1 else: in_str = 0 continue if in_str==0 and (s == "\t" or s == "\n" or s == "\r" or s == " "): continue if s == "," and in_str==0: blocks.append("") continue blocks[-1] += s for i in xrange(len(blocks)): b = blocks[i] #ok, parse the value if isnumeral(b): if "." in b: #it's a float b = float(b) else: #it's an int b = int(b) blocks[i] = b if len(blocks) == 1: return blocks[0] else: return blocks def ParseFBX(string1, name="root"): lines = PreprocessFBX(string1) fdict = FBXDict(name) li = 0 while li < len(lines): i = 0 #read key name, and value if it has one, or recurse #if its nested subdict. key = "" val = "" state = 'r' #can be 'r' for reading key, 'v' for reading val. l = lines[li] in_str = 0 startsblock = 0 while i < len(l): #break on closing brackets if l[i] == "}": break if l[i] == "{" and in_str == 0: startsblock = 1 break if l[i] == ":" and state == 'r': state = 'v' i += 1 continue if (l[i] == "\t" or l[i] == " ") and (state == 'r' or in_str == 0): i += 1 continue if l[i] == "\n" or l[i] == "\r": i += 1 continue if l[i] == "\"" and state == 'v': #\" if in_str == 1: in_str = 0 else: in_str = 1 val += "\"" #\" this comment fixes syntax highlighting in blender i += 1 continue if state == 'r': key += l[i] else: val += l[i] i += 1 #key can be a null string if #we just processed a } closing bracket #line if key == "": li += 1 continue if startsblock: #make subset of lines lines2 = [] in_str = 0 level = 1 for l2 in lines[li+1:]: if level > 0: lines2.append(l2) else: break for s in l2: if s == "\"": #\" if in_str==0: in_str = 1 else: in_str = 0 if in_str == 0: if s == "{": level += 1 elif s == "}": level -= 1 #print lines2 #remove subset from lines lines = lines[:li] + lines[li+len(lines2):] #recurse to get nested subdict. #hackishly, we combine the subset lines (lines2) #back into one big string. s = "" for l in lines2: s += l + "\n" fdict2 = ParseFBX(s, key) fdict2.value = ParseValue(val) fdict[key] = fdict2 else: val = ParseValue(val) fdict[key] = val li += 1 return fdict print "\nparsing. . ." result = ParseFBX(fbx_test) """ a = repr(result) s2 = "" i = 0 limit = 40500 for s in a: if i > limit: break s2 += s i += 1 print s2 """ def import_object(fdict): pass def import_mesh(fdict): verts = fdict['Vertices'] def import_objects(fdict): for key, val in fdict: if key == "Model": name = val.value[0] type = val.value[1] if type == "Mesh": print "found a mesh!" import_mesh(fdict) for key, val in result: if key == "Objects": import_objects(val)