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)