diff options
author | Campbell Barton <ideasman42@gmail.com> | 2008-12-23 09:47:43 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2008-12-23 09:47:43 +0300 |
commit | 5a96981cc6d643c175397f2ec2369917332674f7 (patch) | |
tree | 5fa8434b2037ed3b1b62f742dfee89974eb24954 /release | |
parent | 05fc2aa9da96bb8451ec6c0db882d731914fdc3c (diff) |
improved PROTO support, works for many testfiles now.
Diffstat (limited to 'release')
-rwxr-xr-x | release/scripts/import_web3d.py | 221 |
1 files changed, 121 insertions, 100 deletions
diff --git a/release/scripts/import_web3d.py b/release/scripts/import_web3d.py index a4b367b6df8..7542afcb5b9 100755 --- a/release/scripts/import_web3d.py +++ b/release/scripts/import_web3d.py @@ -36,6 +36,8 @@ __bpydoc__ = """\ This script is an importer for the X3D and VRML97 file formats. """ +DEBUG = False + # This should work without a blender at all try: from Blender.sys import exists @@ -244,44 +246,23 @@ def getNodePreText(i, words): # print "error value!!!", words return 0, -1 -def is_protoline(i, words, proto_field_defs): - - node_type = NODE_NORMAL - # print "PRPTOTOOOO ---- test", i, lines[i] - if not lines[i].startswith('PROTO' ): - # print 'not a proto' - return node_type, -1 - - words[:] = lines[i].split() # TODO - maybe multiline proto's exist? - - i+=1 - if lines[i].startswith('['): # ']\n' - while not lines[i].startswith(']'): - proto_field_defs.append(lines[i].split()) - i+=1 - i+=1 # advance past the ']\n' - - if lines[i].startswith('{'): - node_type = NODE_NORMAL - i+=1 # advance past the '{\n' - - elif lines[i].startswith('['): # does this even exist??, add incase - node_type = NODE_ARRAY - i+=1 # advance past the '{\n' - - print "IS PROTO", i, node_type - return node_type, i - -def is_nodeline(i, words, proto_field_defs): +def is_nodeline(i, words): if not lines[i][0].isalpha(): return 0, 0 + #if lines[i].startswith('field'): + # return 0, 0 + # Is this a prototype?? + if lines[i].startswith('PROTO'): + words[:] = lines[i].split() + return NODE_NORMAL, i+1 # TODO - assumes the next line is a '[\n', skip that + ''' proto_type, new_i = is_protoline(i, words, proto_field_defs) if new_i != -1: return proto_type, new_i - + ''' # Simple "var [" type if lines[i+1] == '[': @@ -292,7 +273,7 @@ def is_nodeline(i, words, proto_field_defs): node_type, new_i = getNodePreText(i, words) if not node_type: - print "not node_type", lines[i] + if DEBUG: print "not node_type", lines[i] return 0, 0 # Ok, we have a { after some values @@ -354,7 +335,7 @@ def is_numline(i): class vrmlNode(object): - __slots__ = 'id', 'fields', 'proto_field_defs', 'proto_fields', 'node_type', 'parent', 'children', 'parent', 'array_data', 'reference', 'lineno', 'filename', 'blendObject', 'DEF_NAMESPACE', 'ROUTE_IPO_NAMESPACE', 'PROTO_NAMESPACE', 'x3dNode' + __slots__ = 'id', 'fields', 'proto_node', 'proto_field_defs', 'proto_fields', 'node_type', 'parent', 'children', 'parent', 'array_data', 'reference', 'lineno', 'filename', 'blendObject', 'DEF_NAMESPACE', 'ROUTE_IPO_NAMESPACE', 'PROTO_NAMESPACE', 'x3dNode' def __init__(self, parent, node_type, lineno): self.id = None self.node_type = node_type @@ -369,6 +350,7 @@ class vrmlNode(object): # This is only set from the root nodes. # Having a filename also denotes a root node self.filename = None + self.proto_node = None # proto field definition eg: "field SFColor seatColor .6 .6 .1" # Store in the root node because each inline file needs its own root node and its own namespace self.DEF_NAMESPACE = None @@ -388,6 +370,7 @@ class vrmlNode(object): return self.fields = [] # fields have no order, in some cases rool level values are not unique so dont use a dict + self.proto_field_defs = [] # proto field definition eg: "field SFColor seatColor .6 .6 .1" self.proto_fields = [] # proto field usage "diffuseColor IS seatColor" self.children = [] @@ -516,10 +499,10 @@ class vrmlNode(object): if child.getProtoName() == None: child.getSerialized(results, ancestry) else: - print "\n\n\n\nTEST!!!!!!!!!!!!!" - print child.getProtoName(), self.getSpec() + + if DEBUG: print 'getSerialized() is proto:', child.getProtoName(), self.getSpec() if child.getProtoName()==self.getSpec(): - print "PROTO!!!!!!!!!!!!!!!!\n" + if DEBUG: "FoundProto!" child.getSerialized(results, ancestry) return results @@ -533,7 +516,7 @@ class vrmlNode(object): child.searchNodeTypeID(node_spec, results) return results - def getFieldName(self, field, ancestry): + def getFieldName(self, field, ancestry, AS_CHILD=False): self_real = self.getRealNode() # incase we're an instance for f in self_real.fields: @@ -546,39 +529,69 @@ class vrmlNode(object): # print "\n\n\n\n\n\nFOND IS!!!" f_proto_lookup = None + f_proto_child_lookup = None i = len(ancestry) while i: i -= 1 node = ancestry[i] + node = node.getRealNode() - # Get the default value from the proto, this can be overwridden by the proto instace - # 'field SFColor legColor .8 .4 .7' - for f_def in node.proto_field_defs: - if len(f_def) >= 4: - if f_def[0]=='field' and f_def[2]==field_id: - f_proto_lookup = f_def[3:] + # proto settings are stored in "self.proto_node" + if node.proto_node: + # Get the default value from the proto, this can be overwridden by the proto instace + # 'field SFColor legColor .8 .4 .7' + if AS_CHILD: + for child in node.proto_node.children: + #if child.id and len(child.id) >= 3 and child.id[2]==field_id: + if child.id and ('point' in child.id or 'points' in child.id): + f_proto_child_lookup = child + + else: + for f_def in node.proto_node.proto_field_defs: + if len(f_def) >= 4: + if f_def[0]=='field' and f_def[2]==field_id: + f_proto_lookup = f_def[3:] # Node instance, Will be 1 up from the proto-node in the ancestry list. but NOT its parent. # This is the setting as defined by the instance, including this setting is optional, # and will override the default PROTO value # eg: 'legColor 1 0 0' - for f_def in node.fields: - # print "\n\n\n\n\nASSSSSSSS", f_def - if len(f_def) >= 2: - if f_def[0]==field_id: - f_proto_lookup = f_def[1:] - # print "\n\n\n\nWOOOOHOOO", field, f_proto_lookup + if AS_CHILD: + for child in node.children: + if child.id and child.id[0]==field_id: + f_proto_child_lookup = child + else: + for f_def in node.fields: + if len(f_def) >= 2: + if f_def[0]==field_id: + if DEBUG: print "getFieldName(), found proto", f_def + f_proto_lookup = f_def[1:] + - return f_proto_lookup + if AS_CHILD: + if f_proto_child_lookup: + if DEBUG: + print "getFieldName() - AS_CHILD=True, child found" + print f_proto_child_lookup + return f_proto_child_lookup + else: + return f_proto_lookup else: - # Not using a proto - return f[1:] + if AS_CHILD: + return None + else: + # Not using a proto + return f[1:] + # print '\tfield not found', field # See if this is a proto name - - + if AS_CHILD: + child_array = None + for child in self_real.children: + if child.id and len(child.id) == 1 and child.id[0] == field: + return child return None @@ -690,13 +703,11 @@ class vrmlNode(object): ''' self_real = self.getRealNode() # incase we're an instance - child_array = None - for child in self_real.children: - # print "ID IS", child.id - if child.id and len(child.id) == 1 and child.id[0] == field: - child_array = child - break + child_array = self_real.getFieldName(field, ancestry, True) + #if type(child_array)==list: # happens occasionaly + # array_data = child_array + if child_array==None: # For x3d, should work ok with vrml too @@ -806,7 +817,6 @@ class vrmlNode(object): def __repr__(self): level = self.getLevel() ind = ' ' * level - print self.id if self.node_type==NODE_REFERENCE: brackets = '' elif self.node_type==NODE_NORMAL: @@ -825,14 +835,25 @@ class vrmlNode(object): text += ind + "(reference node)\n" return text + if self.proto_node: + text += ind + 'PROTO NODE...\n' + text += str(self.proto_node) + text += ind + 'PROTO NODE_DONE\n' + text += ind + 'FIELDS:' + str(len(self.fields)) + '\n' for i,item in enumerate(self.fields): text += ind + 'FIELD:\n' text += ind + str(item) +'\n' + + text += ind + 'PROTO_FIELD_DEFS:' + str(len(self.proto_field_defs)) + '\n' - #text += ind + 'ARRAY: ' + str(len(self.array_data)) + ' ' + str(self.array_data) + '\n' - text += ind + 'ARRAY: ' + str(len(self.array_data)) + '[...] \n' + for i,item in enumerate(self.proto_field_defs): + text += ind + 'PROTO_FIELD:\n' + text += ind + str(item) +'\n' + + text += ind + 'ARRAY: ' + str(len(self.array_data)) + ' ' + str(self.array_data) + '\n' + #text += ind + 'ARRAY: ' + str(len(self.array_data)) + '[...] \n' text += ind + 'CHILDREN: ' + str(len(self.children)) + '\n' for i, child in enumerate(self.children): @@ -843,8 +864,8 @@ class vrmlNode(object): return text - def parse(self, i): - new_i = self.__parse(i) + def parse(self, i, IS_PROTO_DATA=False): + new_i = self.__parse(i, IS_PROTO_DATA) # print self.id, self.getFilename() @@ -911,7 +932,7 @@ class vrmlNode(object): return new_i - def __parse(self, i): + def __parse(self, i, IS_PROTO_DATA=False): ''' print 'parsing at', i, print i, self.id, self.lineno @@ -924,9 +945,8 @@ class vrmlNode(object): i+=1 else: words = [] - proto_field_defs = [] - node_type, new_i = is_nodeline(i, words, proto_field_defs) + node_type, new_i = is_nodeline(i, words) if not node_type: # fail for parsing new node. print "Failed to parse new node" raise ValueError @@ -940,7 +960,6 @@ class vrmlNode(object): return new_i self.id = tuple(words) - self.proto_field_defs[:] = proto_field_defs # fill in DEF/USE key = self.getDefName() @@ -951,6 +970,17 @@ class vrmlNode(object): proto_dict = self.getProtoDict() if key != None: proto_dict[ key ] = self + + # Parse the proto nodes fields + self.proto_node = vrmlNode(self, NODE_ARRAY, new_i) + new_i = self.proto_node.parse(new_i) + + self.children.remove(self.proto_node) + + # print self.proto_node + + new_i += 1 # skip past the { + else: # If we're a proto instance, add the proto node as our child. spec = self.getSpec() @@ -988,12 +1018,10 @@ class vrmlNode(object): ### print "returning", i return i+1 - node_type, new_i = is_nodeline(i, [], []) + node_type, new_i = is_nodeline(i, []) if node_type: # check text\n{ - ### print '\t\tgroup', i child = vrmlNode(self, node_type, i) i = child.parse(i) - # print child.id, 'YYY' elif l=='[': # some files have these anonymous lists child = vrmlNode(self, NODE_ARRAY, i) @@ -1099,27 +1127,9 @@ class vrmlNode(object): if value[0]=='field': # field SFFloat creaseAngle 4 - ''' #oldproto - self.getFieldDict()[value[2]] = value[3:] # skip the first 3 values - ''' - #self.proto_field_defs.append(value) self.proto_field_defs.append(value) else: - # Get referenced field - if len(value) >= 3 and value[1]=='IS': - self.fields.append(value) - - ''' - try: - value = [ value[0] ] + self.getFieldDict()[ value[2] ] - except: - print '\tWarning, field could not be found:', value, 'TODO add support for exposedField' - print '\t', self.getFieldDict() - self.fields.append(value) - ''' - else: - print "ADDING '%s'" % value - self.fields.append(value) + self.fields.append(value) i+=1 def gzipOpen(path): @@ -1164,7 +1174,7 @@ def vrml_parse(path): # Now evaluate it - node_type, new_i = is_nodeline(0, [], []) + node_type, new_i = is_nodeline(0, []) if not node_type: return None, 'Error: VRML file has no starting Node' @@ -1180,9 +1190,8 @@ def vrml_parse(path): root.parse(0) # This prints a load of text - ''' - print root - ''' + if DEBUG: + print root return root, '' @@ -1199,7 +1208,7 @@ class x3dNode(vrmlNode): vrmlNode.__init__(self, parent, node_type, -1) self.x3dNode = x3dNode - def parse(self): + def parse(self, IS_PROTO_DATA=False): # print self.x3dNode.tagName define = self.x3dNode.getAttributeNode('DEF') @@ -1660,7 +1669,12 @@ def importMesh_IndexedFaceSet(geom, bpyima, ancestry): fv = f.verts for i,c in enumerate(fcol): color_index = fv[i].index # color index is vert index - if ifs_color_index: color_index = ifs_color_index[color_index] + if ifs_color_index: + try: + color_index = ifs_color_index[color_index] + except: + print '\tWarning: per vertex color index out of range' + continue if len(ifs_vcol) < color_index: c.r, c.g, c.b = ifs_vcol[color_index] @@ -1684,7 +1698,10 @@ def importMesh_IndexedFaceSet(geom, bpyima, ancestry): col = ifs_vcol[color_index] for i,c in enumerate(fcol): - c.r, c.g, c.b = col + try: + c.r, c.g, c.b = col + except: + pass # incase its not between 0 and 255 bpymesh.verts.delete([0,]) # EEKADOODLE @@ -2253,8 +2270,12 @@ ROUTE champFly001.bindTime TO vpTs.set_startTime for field in node.fields: if field and field[0]=='ROUTE': - from_id, from_type = field[1].split('.') - to_id, to_type = field[3].split('.') + try: + from_id, from_type = field[1].split('.') + to_id, to_type = field[3].split('.') + except: + print "Warning, invalid ROUTE", field + continue if from_type == 'value_changed': if to_type == 'set_position': @@ -2470,7 +2491,7 @@ def test(): #if i < 126 or i > 1000000: # continue - if i < 181 or i > 1000000: + if i != 1068: continue #if i != 12686: |