From bfcea85c6ff6c019013961bc8578688fa475fe43 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 10 Jan 2011 13:56:14 +0000 Subject: [PATCH] x3d import now passes pep8 checker --- release/scripts/op/io_scene_x3d/import_x3d.py | 1068 +++++++++-------- 1 file changed, 571 insertions(+), 497 deletions(-) diff --git a/release/scripts/op/io_scene_x3d/import_x3d.py b/release/scripts/op/io_scene_x3d/import_x3d.py index d1923d17848..a77af66ba03 100644 --- a/release/scripts/op/io_scene_x3d/import_x3d.py +++ b/release/scripts/op/io_scene_x3d/import_x3d.py @@ -26,17 +26,23 @@ try: except: from os.path import exists + def baseName(path): return path.split('/')[-1].split('\\')[-1] + def dirName(path): return path[:-len(baseName(path))] + def imageConvertCompat(path): - try: import os - except: return path - if os.sep=='\\': return path # assime win32 has quicktime, dont convert + try: + import os + except: + return path + if os.sep == '\\': + return path # assime win32 has quicktime, dont convert if path.lower().endswith('.gif'): path_to = path[:-3] + 'png' @@ -45,8 +51,8 @@ def imageConvertCompat(path): if exists(path_to): return path_to ''' - # print '\n'+path+'\n'+path_to+'\n' - os.system('convert "%s" "%s"' % (path, path_to)) # for now just hope we have image magick + # print('\n'+path+'\n'+path_to+'\n') + os.system('convert "%s" "%s"' % (path, path_to)) # for now just hope we have image magick if exists(path_to): return path_to @@ -61,10 +67,8 @@ def imageConvertCompat(path): # rotation first defines axis then ammount in radians - # =============================== VRML Spesific - def vrmlFormat(data): ''' Keep this as a valid vrml file, but format in a way we can predict. @@ -79,35 +83,35 @@ def vrmlFormat(data): i = l.find('#') - if i==-1: + if i == -1: return l # Most cases accounted for! if we have a comment at the end of the line do this... #j = l.find('url "') j = l.find('"') - if j == -1: # simple no strings + if j == -1: # simple no strings return l[:i].strip() q = False - for i,c in enumerate(l): + for i, c in enumerate(l): if c == '"': - q = not q # invert + q = not q # invert elif c == '#': - if q==False: - return l[:i-1] + if q == False: + return l[:i - 1] return l - data = '\n'.join([strip_comment(l) for l in data.split('\n') ]) # remove all whitespace + data = '\n'.join([strip_comment(l) for l in data.split('\n')]) # remove all whitespace - EXTRACT_STRINGS = True # only needed when strings or filesnames containe ,[]{} chars :/ + EXTRACT_STRINGS = True # only needed when strings or filesnames containe ,[]{} chars :/ if EXTRACT_STRINGS: # We need this so we can detect URL's - data = '\n'.join([' '.join(l.split()) for l in data.split('\n')]) # remove all whitespace + data = '\n'.join([' '.join(l.split()) for l in data.split('\n')]) # remove all whitespace string_ls = [] @@ -121,20 +125,19 @@ def vrmlFormat(data): i = data.find(search, last_i) if i != -1: - start = i + len(search) # first char after end of search + start = i + len(search) # first char after end of search end = data.find('"', start) if end != -1: item = data[start:end] - string_ls.append( item ) + string_ls.append(item) data = data[:start] + data[end:] - ok = True # keep looking + ok = True # keep looking last_i = (end - len(item)) + 1 - # print last_i, item, '|' + data[last_i] + '|' + # print(last_i, item, '|' + data[last_i] + '|') # done with messy extracting strings part - # Bad, dont take strings into account ''' data = data.replace('#', '\n#') @@ -144,35 +147,34 @@ def vrmlFormat(data): data = data.replace('}', '\n}\n') data = data.replace('[', '\n[\n') data = data.replace(']', '\n]\n') - data = data.replace(',', ' , ') # make sure comma's seperate + data = data.replace(',', ' , ') # make sure comma's seperate if EXTRACT_STRINGS: # add strings back in - search = '"' # fill in these empty strings + search = '"' # fill in these empty strings ok = True last_i = 0 while ok: ok = False i = data.find(search + '"', last_i) - # print i + # print(i) if i != -1: - start = i + len(search) # first char after end of search + start = i + len(search) # first char after end of search item = string_ls.pop(0) - # print item + # print(item) data = data[:start] + item + data[start:] last_i = start + len(item) + 1 ok = True - # More annoying obscure cases where USE or DEF are placed on a newline # data = data.replace('\nDEF ', ' DEF ') # data = data.replace('\nUSE ', ' USE ') - data = '\n'.join([' '.join(l.split()) for l in data.split('\n')]) # remove all whitespace + data = '\n'.join([' '.join(l.split()) for l in data.split('\n')]) # remove all whitespace # Better to parse the file accounting for multiline arrays ''' @@ -182,30 +184,31 @@ def vrmlFormat(data): return [l for l in data.split('\n') if l] -NODE_NORMAL = 1 # {} -NODE_ARRAY = 2 # [] -NODE_REFERENCE = 3 # USE foobar +NODE_NORMAL = 1 # {} +NODE_ARRAY = 2 # [] +NODE_REFERENCE = 3 # USE foobar # NODE_PROTO = 4 # lines = [] + def getNodePreText(i, words): - # print lines[i] + # print(lines[i]) use_node = False while len(words) < 5: - if i>=len(lines): + if i >= len(lines): break ''' elif lines[i].startswith('PROTO'): return NODE_PROTO, i+1 ''' - elif lines[i]=='{': + elif lines[i] == '{': # words.append(lines[i]) # no need - # print "OK" - return NODE_NORMAL, i+1 - elif lines[i].count('"') % 2 != 0: # odd number of quotes? - part of a string. - # print 'ISSTRING' + # print("OK") + return NODE_NORMAL, i + 1 + elif lines[i].count('"') % 2 != 0: # odd number of quotes? - part of a string. + # print('ISSTRING') break else: new_words = lines[i].split() @@ -218,16 +221,17 @@ def getNodePreText(i, words): # Check for USE node - no { # USE #id - should always be on the same line. if use_node: - # print 'LINE', i, words[:words.index('USE')+2] - words[:] = words[:words.index('USE')+2] - if lines[i] == '{' and lines[i+1] == '}': + # print('LINE', i, words[:words.index('USE')+2]) + words[:] = words[:words.index('USE') + 2] + if lines[i] == '{' and lines[i + 1] == '}': # USE sometimes has {} after it anyway - i+=2 + i += 2 return NODE_REFERENCE, i - # print "error value!!!", words + # print("error value!!!", words) return 0, -1 + def is_nodeline(i, words): if not lines[i][0].isalpha(): @@ -239,10 +243,10 @@ def is_nodeline(i, words): # 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 + return NODE_NORMAL, i + 1 # TODO - assumes the next line is a '[\n', skip that if lines[i].startswith('EXTERNPROTO'): words[:] = lines[i].split() - return NODE_ARRAY, i+1 # TODO - assumes the next line is a '[\n', skip that + return NODE_ARRAY, i + 1 # TODO - assumes the next line is a '[\n', skip that ''' proto_type, new_i = is_protoline(i, words, proto_field_defs) @@ -251,21 +255,22 @@ def is_nodeline(i, words): ''' # Simple "var [" type - if lines[i+1] == '[': + if lines[i + 1] == '[': if lines[i].count('"') % 2 == 0: words[:] = lines[i].split() - return NODE_ARRAY, i+2 + return NODE_ARRAY, i + 2 node_type, new_i = getNodePreText(i, words) if not node_type: - if DEBUG: print "not node_type", lines[i] + if DEBUG: + print("not node_type", lines[i]) return 0, 0 # Ok, we have a { after some values # Check the values are not fields for i, val in enumerate(words): - if i != 0 and words[i-1] in ('DEF', 'USE'): + if i != 0 and words[i - 1] in ('DEF', 'USE'): # ignore anything after DEF, it is a ID and can contain any chars. pass elif val[0].isalpha() and val not in ('TRUE', 'FALSE'): @@ -275,9 +280,10 @@ def is_nodeline(i, words): return 0, 0 #if node_type==NODE_REFERENCE: - # print words, "REF_!!!!!!!" + # print(words, "REF_!!!!!!!") return node_type, new_i + def is_numline(i): ''' Does this line start with a number? @@ -307,27 +313,45 @@ def is_numline(i): if l.startswith(', '): line_start += 2 - line_end = len(l)-1 - line_end_new = l.find(' ', line_start) # comma's always have a space before them + line_end = len(l) - 1 + line_end_new = l.find(' ', line_start) # comma's always have a space before them if line_end_new != -1: line_end = line_end_new try: - float(l[line_start:line_end]) # works for a float or int + float(l[line_start:line_end]) # works for a float or int return True except: return False class vrmlNode(object): - __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' + __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 self.parent = parent self.blendObject = None - self.x3dNode = None # for x3d import only + self.x3dNode = None # for x3d import only if parent: parent.children.append(self) @@ -336,7 +360,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" + 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 @@ -345,23 +369,21 @@ class vrmlNode(object): self.FIELD_NAMESPACE = None ''' - self.PROTO_NAMESPACE = None self.reference = None - if node_type==NODE_REFERENCE: + if node_type == NODE_REFERENCE: # For references, only the parent and ID are needed # the reference its self is assigned on parsing return - self.fields = [] # fields have no order, in some cases rool level values are not unique so dont use a dict + 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.proto_field_defs = [] # proto field definition eg: "field SFColor seatColor .6 .6 .1" + self.proto_fields = [] # proto field usage "diffuseColor IS seatColor" self.children = [] - self.array_data = [] # use for arrays of data - should only be for NODE_ARRAY types - + self.array_data = [] # use for arrays of data - should only be for NODE_ARRAY types # Only available from the root node ''' @@ -392,9 +414,9 @@ class vrmlNode(object): def setRoot(self, filename): self.filename = filename # self.FIELD_NAMESPACE = {} - self.DEF_NAMESPACE = {} - self.ROUTE_IPO_NAMESPACE = {} - self.PROTO_NAMESPACE = {} + self.DEF_NAMESPACE = {} + self.ROUTE_IPO_NAMESPACE = {} + self.PROTO_NAMESPACE = {} def isRoot(self): if self.filename == None: @@ -419,7 +441,7 @@ class vrmlNode(object): def getSpec(self): self_real = self.getRealNode() try: - return self_real.id[-1] # its possible this node has no spec + return self_real.id[-1] # its possible this node has no spec except: return None @@ -441,9 +463,10 @@ class vrmlNode(object): def getSpecialTypeName(self, typename): self_real = self.getRealNode() - try: return self_real.id[ list(self_real.id).index(typename)+1 ] - except: return None - + try: + return self_real.id[list(self_real.id).index(typename) + 1] + except: + return None def getDefName(self): return self.getSpecialTypeName('DEF') @@ -454,34 +477,36 @@ class vrmlNode(object): def getExternprotoName(self): return self.getSpecialTypeName('EXTERNPROTO') - def getChildrenBySpec(self, node_spec): # spec could be Transform, Shape, Appearance + def getChildrenBySpec(self, node_spec): # spec could be Transform, Shape, Appearance self_real = self.getRealNode() # using getSpec functions allows us to use the spec of USE children that dont have their spec in their ID if type(node_spec) == str: - return [child for child in self_real.children if child.getSpec()==node_spec] + return [child for child in self_real.children if child.getSpec() == node_spec] else: # Check inside a list of optional types return [child for child in self_real.children if child.getSpec() in node_spec] - def getChildBySpec(self, node_spec): # spec could be Transform, Shape, Appearance + def getChildBySpec(self, node_spec): # spec could be Transform, Shape, Appearance # Use in cases where there is only ever 1 child of this type ls = self.getChildrenBySpec(node_spec) - if ls: return ls[0] - else: return None + if ls: + return ls[0] + else: + return None - def getChildrenByName(self, node_name): # type could be geometry, children, appearance + def getChildrenByName(self, node_name): # type could be geometry, children, appearance self_real = self.getRealNode() - return [child for child in self_real.children if child.id if child.id[0]==node_name] + return [child for child in self_real.children if child.id if child.id[0] == node_name] def getChildByName(self, node_name): self_real = self.getRealNode() for child in self_real.children: - if child.id and child.id[0]==node_name: # and child.id[-1]==node_spec: + if child.id and child.id[0] == node_name: # and child.id[-1]==node_spec: return child def getSerialized(self, results, ancestry): ''' Return this node and all its children in a flat list ''' - ancestry = ancestry[:] # always use a copy + ancestry = ancestry[:] # always use a copy # self_real = self.getRealNode() @@ -500,39 +525,39 @@ class vrmlNode(object): child.getSerialized(results, ancestry) else: - if DEBUG: print 'getSerialized() is proto:', child.getProtoName(), child.getExternprotoName(), self.getSpec() + if DEBUG: + print('getSerialized() is proto:', child.getProtoName(), child.getExternprotoName(), self.getSpec()) self_spec = self.getSpec() if child.getProtoName() == self_spec or child.getExternprotoName() == self_spec: - if DEBUG: "FoundProto!" + #if DEBUG: + # "FoundProto!" child.getSerialized(results, ancestry) - - return results def searchNodeTypeID(self, node_spec, results): self_real = self.getRealNode() - # print self.lineno, self.id - if self_real.id and self_real.id[-1]==node_spec: # use last element, could also be only element + # print(self.lineno, self.id) + if self_real.id and self_real.id[-1] == node_spec: # use last element, could also be only element results.append(self_real) for child in self_real.children: child.searchNodeTypeID(node_spec, results) return results def getFieldName(self, field, ancestry, AS_CHILD=False): - self_real = self.getRealNode() # incase we're an instance + self_real = self.getRealNode() # incase we're an instance for f in self_real.fields: - # print f + # print(f) if f and f[0] == field: - # print '\tfound field', f + # print('\tfound field', f) - if len(f)>=3 and f[1] == 'IS': # eg: 'diffuseColor IS legColor' + if len(f) >= 3 and f[1] == 'IS': # eg: 'diffuseColor IS legColor' field_id = f[2] - # print "\n\n\n\n\n\nFOND IS!!!" + # print("\n\n\n\n\n\nFOND IS!!!") f_proto_lookup = None f_proto_child_lookup = None i = len(ancestry) @@ -554,7 +579,7 @@ class vrmlNode(object): 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: + 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. @@ -563,21 +588,21 @@ class vrmlNode(object): # eg: 'legColor 1 0 0' if AS_CHILD: for child in node.children: - if child.id and child.id[0]==field_id: + 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 + if f_def[0] == field_id: + if DEBUG: + print("getFieldName(), found proto", f_def) f_proto_lookup = f_def[1:] - if AS_CHILD: if f_proto_child_lookup: if DEBUG: - print "getFieldName() - AS_CHILD=True, child found" - print f_proto_child_lookup + print("getFieldName() - AS_CHILD=True, child found") + print(f_proto_child_lookup) return f_proto_child_lookup else: return f_proto_lookup @@ -587,9 +612,7 @@ class vrmlNode(object): else: # Not using a proto return f[1:] - - # print '\tfield not found', field - + # print('\tfield not found', field) # See if this is a proto name if AS_CHILD: @@ -601,89 +624,99 @@ class vrmlNode(object): return None def getFieldAsInt(self, field, default, ancestry): - self_real = self.getRealNode() # incase we're an instance + self_real = self.getRealNode() # incase we're an instance f = self_real.getFieldName(field, ancestry) - if f==None: return default - if ',' in f: f = f[:f.index(',')] # strip after the comma + if f == None: + return default + if ',' in f: + f = f[:f.index(',')] # strip after the comma if len(f) != 1: - print '\t"%s" wrong length for int conversion for field "%s"' % (f, field) + print('\t"%s" wrong length for int conversion for field "%s"' % (f, field)) return default try: return int(f[0]) except: - print '\tvalue "%s" could not be used as an int for field "%s"' % (f[0], field) + print('\tvalue "%s" could not be used as an int for field "%s"' % (f[0], field)) return default def getFieldAsFloat(self, field, default, ancestry): - self_real = self.getRealNode() # incase we're an instance + self_real = self.getRealNode() # incase we're an instance f = self_real.getFieldName(field, ancestry) - if f==None: return default - if ',' in f: f = f[:f.index(',')] # strip after the comma + if f == None: + return default + if ',' in f: + f = f[:f.index(',')] # strip after the comma if len(f) != 1: - print '\t"%s" wrong length for float conversion for field "%s"' % (f, field) + print('\t"%s" wrong length for float conversion for field "%s"' % (f, field)) return default try: return float(f[0]) except: - print '\tvalue "%s" could not be used as a float for field "%s"' % (f[0], field) + print('\tvalue "%s" could not be used as a float for field "%s"' % (f[0], field)) return default def getFieldAsFloatTuple(self, field, default, ancestry): - self_real = self.getRealNode() # incase we're an instance + self_real = self.getRealNode() # incase we're an instance f = self_real.getFieldName(field, ancestry) - if f==None: return default + if f == None: + return default # if ',' in f: f = f[:f.index(',')] # strip after the comma if len(f) < 1: - print '"%s" wrong length for float tuple conversion for field "%s"' % (f, field) + print('"%s" wrong length for float tuple conversion for field "%s"' % (f, field)) return default ret = [] for v in f: if v != ',': - try: ret.append(float(v)) - except: break # quit of first non float, perhaps its a new field name on the same line? - if so we are going to ignore it :/ TODO - # print ret + try: + ret.append(float(v)) + except: + break # quit of first non float, perhaps its a new field name on the same line? - if so we are going to ignore it :/ TODO + # print(ret) if ret: return ret if not ret: - print '\tvalue "%s" could not be used as a float tuple for field "%s"' % (f, field) + print('\tvalue "%s" could not be used as a float tuple for field "%s"' % (f, field)) return default def getFieldAsBool(self, field, default, ancestry): - self_real = self.getRealNode() # incase we're an instance + self_real = self.getRealNode() # incase we're an instance f = self_real.getFieldName(field, ancestry) - if f==None: return default - if ',' in f: f = f[:f.index(',')] # strip after the comma + if f == None: + return default + if ',' in f: + f = f[:f.index(',')] # strip after the comma if len(f) != 1: - print '\t"%s" wrong length for bool conversion for field "%s"' % (f, field) + print('\t"%s" wrong length for bool conversion for field "%s"' % (f, field)) return default - if f[0].upper()=='"TRUE"' or f[0].upper()=='TRUE': + if f[0].upper() == '"TRUE"' or f[0].upper() == 'TRUE': return True - elif f[0].upper()=='"FALSE"' or f[0].upper()=='FALSE': + elif f[0].upper() == '"FALSE"' or f[0].upper() == 'FALSE': return False else: - print '\t"%s" could not be used as a bool for field "%s"' % (f[1], field) + print('\t"%s" could not be used as a bool for field "%s"' % (f[1], field)) return default def getFieldAsString(self, field, default, ancestry): - self_real = self.getRealNode() # incase we're an instance + self_real = self.getRealNode() # incase we're an instance f = self_real.getFieldName(field, ancestry) - if f==None: return default + if f == None: + return default if len(f) < 1: - print '\t"%s" wrong length for string conversion for field "%s"' % (f, field) + print('\t"%s" wrong length for string conversion for field "%s"' % (f, field)) return default if len(f) > 1: @@ -696,24 +729,24 @@ class vrmlNode(object): if self.x3dNode: return st - if st[0]=='"' and st[-1]=='"': + if st[0] == '"' and st[-1] == '"': return st[1:-1] else: - print '\tvalue "%s" could not be used as a string for field "%s"' % (f[0], field) + print('\tvalue "%s" could not be used as a string for field "%s"' % (f[0], field)) return default def getFieldAsArray(self, field, group, ancestry): ''' For this parser arrays are children ''' - self_real = self.getRealNode() # incase we're an instance + self_real = self.getRealNode() # incase we're an instance child_array = self_real.getFieldName(field, ancestry, True) #if type(child_array)==list: # happens occasionaly # array_data = child_array - if child_array==None: + if child_array == None: # For x3d, should work ok with vrml too # for x3d arrays are fields, vrml they are nodes, annoying but not tooo bad. @@ -732,17 +765,15 @@ class vrmlNode(object): try: array_data = [float(val) for val in data_split] except: - print '\tWarning, could not parse array data from field' + print('\tWarning, could not parse array data from field') array_data = [] else: - # print child_array + # print(child_array) # Normal vrml array_data = child_array.array_data - - # print 'array_data', array_data - - if group==-1 or len(array_data)==0: + # print('array_data', array_data) + if group == -1 or len(array_data) == 0: return array_data # We want a flat list @@ -754,18 +785,19 @@ class vrmlNode(object): # make a flat array if flat: - flat_array = array_data # we are alredy flat. + flat_array = array_data # we are alredy flat. else: flat_array = [] def extend_flat(ls): for item in ls: - if type(item)==list: extend_flat(item) - else: flat_array.append(item) + if type(item) == list: + extend_flat(item) + else: + flat_array.append(item) extend_flat(array_data) - # We requested a flat array if group == 0: return flat_array @@ -775,12 +807,12 @@ class vrmlNode(object): for item in flat_array: sub_array.append(item) - if len(sub_array)==group: + if len(sub_array) == group: new_array.append(sub_array) sub_array = [] if sub_array: - print '\twarning, array was not aligned to requested grouping', group, 'remaining value', sub_array + print('\twarning, array was not aligned to requested grouping', group, 'remaining value', sub_array) return new_array @@ -788,7 +820,7 @@ class vrmlNode(object): ''' Get a list of strings ''' - self_real = self.getRealNode() # incase we're an instance + self_real = self.getRealNode() # incase we're an instance child_array = None for child in self_real.children: @@ -802,29 +834,29 @@ class vrmlNode(object): try: new_array = [f[0][1:-1] for f in child_array.fields] except: - print '\twarning, string array could not be made' + print('\twarning, string array could not be made') new_array = [] return new_array - def getLevel(self): # Ignore self_real level = 0 p = self.parent while p: - level +=1 + level += 1 p = p.parent - if not p: break + if not p: + break return level def __repr__(self): level = self.getLevel() ind = ' ' * level - if self.node_type==NODE_REFERENCE: + if self.node_type == NODE_REFERENCE: brackets = '' - elif self.node_type==NODE_NORMAL: + elif self.node_type == NODE_NORMAL: brackets = '{}' else: brackets = '[]' @@ -836,7 +868,7 @@ class vrmlNode(object): text += ind + 'ID: ' + str(self.id) + ' ' + str(level) + (' lineno %d\n' % self.lineno) - if self.node_type==NODE_REFERENCE: + if self.node_type == NODE_REFERENCE: text += ind + "(reference node)\n" return text @@ -847,15 +879,15 @@ class vrmlNode(object): text += ind + 'FIELDS:' + str(len(self.fields)) + '\n' - for i,item in enumerate(self.fields): + for i, item in enumerate(self.fields): text += ind + 'FIELD:\n' - text += ind + str(item) +'\n' + text += ind + str(item) + '\n' text += ind + 'PROTO_FIELD_DEFS:' + str(len(self.proto_field_defs)) + '\n' - for i,item in enumerate(self.proto_field_defs): + for i, item in enumerate(self.proto_field_defs): text += ind + 'PROTO_FIELD:\n' - text += ind + str(item) +'\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' @@ -872,14 +904,14 @@ class vrmlNode(object): def parse(self, i, IS_PROTO_DATA=False): new_i = self.__parse(i, IS_PROTO_DATA) - # print self.id, self.getFilename() + # print(self.id, self.getFilename()) # Check if this node was an inline or externproto url_ls = [] if self.node_type == NODE_NORMAL and self.getSpec() == 'Inline': - ancestry = [] # Warning! - PROTO's using this wont work at all. + ancestry = [] # Warning! - PROTO's using this wont work at all. url = self.getFieldAsString('url', None, ancestry) if url: url_ls = [(url, None)] @@ -890,38 +922,37 @@ class vrmlNode(object): url_ls = [] for f in self.fields: - if type(f)==str: + if type(f) == str: f = [f] for ff in f: for f_split in ff.split('"'): - # print f_split + # print(f_split) # "someextern.vrml#SomeID" if '#' in f_split: - f_split, f_split_id = f_split.split('#') # there should only be 1 # anyway + f_split, f_split_id = f_split.split('#') # there should only be 1 # anyway - url_ls.append( (f_split, f_split_id) ) + url_ls.append((f_split, f_split_id)) else: - url_ls.append( (f_split, None) ) - + url_ls.append((f_split, None)) # Was either an Inline or an EXTERNPROTO if url_ls: - # print url_ls + # print(url_ls) for url, extern_key in url_ls: - print url + print(url) urls = [] - urls.append( url ) - urls.append( BPySys.caseInsensitivePath(urls[-1]) ) + urls.append(url) + urls.append(BPySys.caseInsensitivePath(urls[-1])) - urls.append( dirName(self.getFilename()) + url ) - urls.append( BPySys.caseInsensitivePath(urls[-1]) ) + urls.append(dirName(self.getFilename()) + url) + urls.append(BPySys.caseInsensitivePath(urls[-1])) - urls.append( dirName(self.getFilename()) + baseName(url) ) - urls.append( BPySys.caseInsensitivePath(urls[-1]) ) + urls.append(dirName(self.getFilename()) + baseName(url)) + urls.append(BPySys.caseInsensitivePath(urls[-1])) try: url = [url for url in urls if exists(url)][0] @@ -930,27 +961,26 @@ class vrmlNode(object): url_found = False if not url_found: - print '\tWarning: Inline URL could not be found:', url + print('\tWarning: Inline URL could not be found:', url) else: - if url==self.getFilename(): - print '\tWarning: cant Inline yourself recursively:', url + if url == self.getFilename(): + print('\tWarning: cant Inline yourself recursively:', url) else: try: data = gzipOpen(url) except: - print '\tWarning: cant open the file:', url + print('\tWarning: cant open the file:', url) data = None if data: # Tricky - inline another VRML - print '\tLoading Inline:"%s"...' % url + print('\tLoading Inline:"%s"...' % url) # Watch it! - backup lines lines_old = lines[:] - - lines[:] = vrmlFormat( data ) + lines[:] = vrmlFormat(data) lines.insert(0, '{') lines.insert(0, 'root_node____') @@ -961,12 +991,12 @@ class vrmlNode(object): ''' child = vrmlNode(self, NODE_NORMAL, -1) - child.setRoot(url) # initialized dicts + child.setRoot(url) # initialized dicts child.parse(0) # if self.getExternprotoName(): if self.getExternprotoName(): - if not extern_key: # if none is spesified - use the name + if not extern_key: # if none is spesified - use the name extern_key = self.getSpec() if extern_key: @@ -980,9 +1010,10 @@ class vrmlNode(object): self.children.append(extern_child) extern_child.parent = self - if DEBUG: print "\tEXTERNPROTO ID found!:", extern_key + if DEBUG: + print("\tEXTERNPROTO ID found!:", extern_key) else: - print "\tEXTERNPROTO ID not found!:", extern_key + print("\tEXTERNPROTO ID not found!:", extern_key) # Watch it! - restore lines lines[:] = lines_old @@ -991,26 +1022,26 @@ class vrmlNode(object): def __parse(self, i, IS_PROTO_DATA=False): ''' - print 'parsing at', i, - print i, self.id, self.lineno + print('parsing at', i, end="") + print(i, self.id, self.lineno) ''' l = lines[i] - if l=='[': + if l == '[': # An anonymous list self.id = None - i+=1 + i += 1 else: words = [] node_type, new_i = is_nodeline(i, words) - if not node_type: # fail for parsing new node. - print "Failed to parse new node" + if not node_type: # fail for parsing new node. + print("Failed to parse new node") raise ValueError - if self.node_type==NODE_REFERENCE: + if self.node_type == NODE_REFERENCE: # Only assign the reference and quit - key = words[words.index('USE')+1] + key = words[words.index('USE') + 1] self.id = (words[0],) self.reference = self.getDefDict()[key] @@ -1021,14 +1052,15 @@ class vrmlNode(object): # fill in DEF/USE key = self.getDefName() if key != None: - self.getDefDict()[ key ] = self + self.getDefDict()[key] = self key = self.getProtoName() - if not key: key = self.getExternprotoName() + if not key: + key = self.getExternprotoName() proto_dict = self.getProtoDict() if key != None: - proto_dict[ key ] = self + proto_dict[key] = self # Parse the proto nodes fields self.proto_node = vrmlNode(self, NODE_ARRAY, new_i) @@ -1036,15 +1068,14 @@ class vrmlNode(object): self.children.remove(self.proto_node) - # print self.proto_node + # print(self.proto_node) - new_i += 1 # skip past the { + new_i += 1 # skip past the { - - else: # If we're a proto instance, add the proto node as our child. + else: # If we're a proto instance, add the proto node as our child. spec = self.getSpec() try: - self.children.append( proto_dict[spec] ) + self.children.append(proto_dict[spec]) #pass except: pass @@ -1055,39 +1086,39 @@ class vrmlNode(object): i = new_i - # print self.id + # print(self.id) ok = True while ok: - if i>=len(lines): - return len(lines)-1 + if i >= len(lines): + return len(lines) - 1 l = lines[i] - # print '\tDEBUG:', i, self.node_type, l - if l=='': - i+=1 + # print('\tDEBUG:', i, self.node_type, l) + if l == '': + i += 1 continue - if l=='}': - if self.node_type != NODE_NORMAL: # also ends proto nodes, we may want a type for these too. - print 'wrong node ending, expected an } ' + str(i) + ' ' + str(self.node_type) + if l == '}': + if self.node_type != NODE_NORMAL: # also ends proto nodes, we may want a type for these too. + print('wrong node ending, expected an } ' + str(i) + ' ' + str(self.node_type)) if DEBUG: raise ValueError - ### print "returning", i - return i+1 - if l==']': + ### print("returning", i) + return i + 1 + if l == ']': if self.node_type != NODE_ARRAY: - print 'wrong node ending, expected a ] ' + str(i) + ' ' + str(self.node_type) + print('wrong node ending, expected a ] ' + str(i) + ' ' + str(self.node_type)) if DEBUG: raise ValueError - ### print "returning", i - return i+1 + ### print("returning", i) + return i + 1 node_type, new_i = is_nodeline(i, []) - if node_type: # check text\n{ + if node_type: # check text\n{ child = vrmlNode(self, node_type, i) i = child.parse(i) - elif l=='[': # some files have these anonymous lists + elif l == '[': # some files have these anonymous lists child = vrmlNode(self, NODE_ARRAY, i) i = child.parse(i) @@ -1099,53 +1130,52 @@ class vrmlNode(object): for num_type in (int, float): try: - values = [num_type(v) for v in l_split ] + values = [num_type(v) for v in l_split] break except: pass - try: - values = [[num_type(v) for v in segment.split()] for segment in l_split ] + values = [[num_type(v) for v in segment.split()] for segment in l_split] break except: pass - if values == None: # dont parse + if values == None: # dont parse values = l_split # This should not extend over multiple lines however it is possible - # print self.array_data + # print(self.array_data) if values: - self.array_data.extend( values ) - i+=1 + self.array_data.extend(values) + i += 1 else: words = l.split() if len(words) > 2 and words[1] == 'USE': vrmlNode(self, NODE_REFERENCE, i) else: - # print "FIELD", i, l + # print("FIELD", i, l) # #words = l.split() - ### print '\t\ttag', i + ### print('\t\ttag', i) # this is a tag/ - # print words, i, l + # print(words, i, l) value = l - # print i + # print(i) # javastrips can exist as values. quote_count = l.count('"') - if quote_count % 2: # odd number? - # print 'MULTILINE' + if quote_count % 2: # odd number? + # print('MULTILINE') while 1: - i+=1 + i += 1 l = lines[i] quote_count = l.count('"') - if quote_count % 2: # odd number? - value += '\n'+ l[:l.rfind('"')] - break # assume + if quote_count % 2: # odd number? + value += '\n' + l[:l.rfind('"')] + break # assume else: - value += '\n'+ l + value += '\n' + l value_all = value.split() @@ -1166,7 +1196,7 @@ class vrmlNode(object): if iskey(value[j]): if field_context: # this IS a key but the previous value was not a key, ot it was a defined field. - if (not iskey(field_context[-1])) or ((len(field_context)==3 and field_context[1]=='IS')): + if (not iskey(field_context[-1])) or ((len(field_context) == 3 and field_context[1] == 'IS')): field_list.append(field_context) field_context = [value[j]] @@ -1185,34 +1215,41 @@ class vrmlNode(object): return field_list - for value in split_fields(value_all): # Split - if value[0]=='field': + if value[0] == 'field': # field SFFloat creaseAngle 4 self.proto_field_defs.append(value) else: self.fields.append(value) - i+=1 + i += 1 + def gzipOpen(path): - try: import gzip - except: gzip = None + try: + import gzip + except: + gzip = None data = None if gzip: - try: data = gzip.open(path, 'r').read() - except: pass + try: + data = gzip.open(path, 'r').read() + except: + pass else: - print '\tNote, gzip module could not be imported, compressed files will fail to load' + print('\tNote, gzip module could not be imported, compressed files will fail to load') - if data==None: - try: data = open(path, 'rU').read() - except: pass + if data == None: + try: + data = open(path, 'rU').read() + except: + pass return data + def vrml_parse(path): ''' Sets up the root node and returns it so load_web3d() can deal with the blender side of things. @@ -1220,11 +1257,11 @@ def vrml_parse(path): ''' data = gzipOpen(path) - if data==None: + if data == None: return None, 'Failed to open file: ' + path # Stripped above - lines[:] = vrmlFormat( data ) + lines[:] = vrmlFormat(data) lines.insert(0, '{') lines.insert(0, 'dymmy_node') @@ -1244,26 +1281,24 @@ def vrml_parse(path): # Trick to make sure we get all root nodes. lines.insert(0, '{') - lines.insert(0, 'root_node____') # important the name starts with an ascii char + lines.insert(0, 'root_node____') # important the name starts with an ascii char lines.append('}') root = vrmlNode(None, NODE_NORMAL, -1) - root.setRoot(path) # we need to set the root so we have a namespace and know the path incase of inlineing + root.setRoot(path) # we need to set the root so we have a namespace and know the path incase of inlineing # Parse recursively root.parse(0) # This prints a load of text if DEBUG: - print root + print(root) return root, '' # ====================== END VRML - - # ====================== X3d Support # Sane as vrml but replace the parser @@ -1273,7 +1308,7 @@ class x3dNode(vrmlNode): self.x3dNode = x3dNode def parse(self, IS_PROTO_DATA=False): - # print self.x3dNode.tagName + # print(self.x3dNode.tagName) define = self.x3dNode.getAttributeNode('DEF') if define: @@ -1285,7 +1320,7 @@ class x3dNode(vrmlNode): self.reference = self.getDefDict()[use.value] self.node_type = NODE_REFERENCE except: - print '\tWarning: reference', use.value, 'not found' + print('\tWarning: reference', use.value, 'not found') self.parent.children.remove(self) return @@ -1295,7 +1330,7 @@ class x3dNode(vrmlNode): continue node_type = NODE_NORMAL - # print x3dChildNode, dir(x3dChildNode) + # print(x3dChildNode, dir(x3dChildNode)) if x3dChildNode.getAttributeNode('USE'): node_type = NODE_REFERENCE @@ -1305,11 +1340,12 @@ class x3dNode(vrmlNode): # TODO - x3d Inline def getSpec(self): - return self.x3dNode.tagName # should match vrml spec + return self.x3dNode.tagName # should match vrml spec def getDefName(self): data = self.x3dNode.getAttributeNode('DEF') - if data: data.value + if data: + data.value # XXX, return?? return None # Other funcs operate from vrml, but this means we can wrap XML fields, still use nice utility funcs @@ -1317,7 +1353,7 @@ class x3dNode(vrmlNode): def getFieldName(self, field, ancestry, AS_CHILD=False): # ancestry and AS_CHILD are ignored, only used for VRML now - self_real = self.getRealNode() # incase we're an instance + self_real = self.getRealNode() # incase we're an instance field_xml = self.x3dNode.getAttributeNode(field) if field_xml: value = field_xml.value @@ -1328,6 +1364,7 @@ class x3dNode(vrmlNode): else: return None + def x3d_parse(path): ''' Sets up the root node and returns it so load_web3d() can deal with the blender side of things. @@ -1347,31 +1384,27 @@ def x3d_parse(path): # Could add a try/except here, but a console error is more useful. data = gzipOpen(path) - if data==None: + if data == None: return None, 'Failed to open file: ' + path doc = xml.dom.minidom.parseString(data) - try: x3dnode = doc.getElementsByTagName('X3D')[0] except: return None, 'Not a valid x3d document, cannot import' root = x3dNode(None, NODE_NORMAL, x3dnode) - root.setRoot(path) # so images and Inline's we load have a relative path + root.setRoot(path) # so images and Inline's we load have a relative path root.parse() return root, '' - - ## f = open('/_Cylinder.wrl', 'r') # f = open('/fe/wrl/Vrml/EGS/TOUCHSN.WRL', 'r') # vrml_parse('/fe/wrl/Vrml/EGS/TOUCHSN.WRL') #vrml_parse('/fe/wrl/Vrml/EGS/SCRIPT.WRL') ''' - import os files = os.popen('find /fe/wrl -iname "*.wrl"').readlines() files.sort() @@ -1381,7 +1414,7 @@ for i, f in enumerate(files): # continue f = f.strip() - print f, i, tot + print(f, i, tot) vrml_parse(f) ''' @@ -1401,25 +1434,28 @@ from Blender.Mathutils import Matrix RAD_TO_DEG = 57.29578 -GLOBALS = {'CIRCLE_DETAIL':16} +GLOBALS = {'CIRCLE_DETAIL': 16} + def translateRotation(rot): ''' axis, angle ''' - return RotationMatrix(rot[3]*RAD_TO_DEG, 4, 'r', Vector(rot[:3])) + return RotationMatrix(rot[3] * RAD_TO_DEG, 4, 'r', Vector(rot[:3])) + def translateScale(sca): - mat = Matrix() # 4x4 default + mat = Matrix() # 4x4 default mat[0][0] = sca[0] mat[1][1] = sca[1] mat[2][2] = sca[2] return mat + def translateTransform(node, ancestry): - cent = node.getFieldAsFloatTuple('center', None, ancestry) # (0.0, 0.0, 0.0) - rot = node.getFieldAsFloatTuple('rotation', None, ancestry) # (0.0, 0.0, 1.0, 0.0) - sca = node.getFieldAsFloatTuple('scale', None, ancestry) # (1.0, 1.0, 1.0) - scaori = node.getFieldAsFloatTuple('scaleOrientation', None, ancestry) # (0.0, 0.0, 1.0, 0.0) - tx = node.getFieldAsFloatTuple('translation', None, ancestry) # (0.0, 0.0, 0.0) + cent = node.getFieldAsFloatTuple('center', None, ancestry) # (0.0, 0.0, 0.0) + rot = node.getFieldAsFloatTuple('rotation', None, ancestry) # (0.0, 0.0, 1.0, 0.0) + sca = node.getFieldAsFloatTuple('scale', None, ancestry) # (1.0, 1.0, 1.0) + scaori = node.getFieldAsFloatTuple('scaleOrientation', None, ancestry) # (0.0, 0.0, 1.0, 0.0) + tx = node.getFieldAsFloatTuple('translation', None, ancestry) # (0.0, 0.0, 0.0) if cent: cent_mat = TranslationMatrix(Vector(cent)).resize4x4() @@ -1427,11 +1463,15 @@ def translateTransform(node, ancestry): else: cent_mat = cent_imat = None - if rot: rot_mat = translateRotation(rot) - else: rot_mat = None + if rot: + rot_mat = translateRotation(rot) + else: + rot_mat = None - if sca: sca_mat = translateScale(sca) - else: sca_mat = None + if sca: + sca_mat = translateScale(sca) + else: + sca_mat = None if scaori: scaori_mat = translateRotation(scaori) @@ -1439,8 +1479,10 @@ def translateTransform(node, ancestry): else: scaori_mat = scaori_imat = None - if tx: tx_mat = TranslationMatrix(Vector(tx)).resize4x4() - else: tx_mat = None + if tx: + tx_mat = TranslationMatrix(Vector(tx)).resize4x4() + else: + tx_mat = None new_mat = Matrix() @@ -1451,12 +1493,12 @@ def translateTransform(node, ancestry): return new_mat -def translateTexTransform(node, ancestry): - cent = node.getFieldAsFloatTuple('center', None, ancestry) # (0.0, 0.0) - rot = node.getFieldAsFloat('rotation', None, ancestry) # 0.0 - sca = node.getFieldAsFloatTuple('scale', None, ancestry) # (1.0, 1.0) - tx = node.getFieldAsFloatTuple('translation', None, ancestry) # (0.0, 0.0) +def translateTexTransform(node, ancestry): + cent = node.getFieldAsFloatTuple('center', None, ancestry) # (0.0, 0.0) + rot = node.getFieldAsFloat('rotation', None, ancestry) # 0.0 + sca = node.getFieldAsFloatTuple('scale', None, ancestry) # (1.0, 1.0) + tx = node.getFieldAsFloatTuple('translation', None, ancestry) # (0.0, 0.0) if cent: # cent is at a corner by default @@ -1465,14 +1507,20 @@ def translateTexTransform(node, ancestry): else: cent_mat = cent_imat = None - if rot: rot_mat = RotationMatrix(rot*RAD_TO_DEG, 4, 'z') # translateRotation(rot) - else: rot_mat = None + if rot: + rot_mat = RotationMatrix(rot * RAD_TO_DEG, 4, 'z') # translateRotation(rot) + else: + rot_mat = None - if sca: sca_mat = translateScale((sca[0], sca[1], 0.0)) - else: sca_mat = None + if sca: + sca_mat = translateScale((sca[0], sca[1], 0.0)) + else: + sca_mat = None - if tx: tx_mat = TranslationMatrix(Vector(tx).resize3D()).resize4x4() - else: tx_mat = None + if tx: + tx_mat = TranslationMatrix(Vector(tx).resize3D()).resize4x4() + else: + tx_mat = None new_mat = Matrix() @@ -1486,15 +1534,14 @@ def translateTexTransform(node, ancestry): return new_mat - def getFinalMatrix(node, mtx, ancestry): transform_nodes = [node_tx for node_tx in ancestry if node_tx.getSpec() == 'Transform'] - if node.getSpec()=='Transform': + if node.getSpec() == 'Transform': transform_nodes.append(node) transform_nodes.reverse() - if mtx==None: + if mtx is None: mtx = Matrix() for node_tx in transform_nodes: @@ -1503,31 +1550,34 @@ def getFinalMatrix(node, mtx, ancestry): return mtx -def importMesh_IndexedFaceSet(geom, bpyima, ancestry): - # print geom.lineno, geom.id, vrmlNode.DEF_NAMESPACE.keys() - ccw = geom.getFieldAsBool('ccw', True, ancestry) - ifs_colorPerVertex = geom.getFieldAsBool('colorPerVertex', True, ancestry) # per vertex or per face - ifs_normalPerVertex = geom.getFieldAsBool('normalPerVertex', True, ancestry) +def importMesh_IndexedFaceSet(geom, bpyima, ancestry): + # print(geom.lineno, geom.id, vrmlNode.DEF_NAMESPACE.keys()) + + ccw = geom.getFieldAsBool('ccw', True, ancestry) + ifs_colorPerVertex = geom.getFieldAsBool('colorPerVertex', True, ancestry) # per vertex or per face + ifs_normalPerVertex = geom.getFieldAsBool('normalPerVertex', True, ancestry) # This is odd how point is inside Coordinate # VRML not x3d #coord = geom.getChildByName('coord') # 'Coordinate' - coord = geom.getChildBySpec('Coordinate') # works for x3d and vrml + coord = geom.getChildBySpec('Coordinate') # works for x3d and vrml - if coord: ifs_points = coord.getFieldAsArray('point', 3, ancestry) - else: coord = [] + if coord: + ifs_points = coord.getFieldAsArray('point', 3, ancestry) + else: + coord = [] if not coord: - print '\tWarnint: IndexedFaceSet has no points' + print('\tWarnint: IndexedFaceSet has no points') return None, ccw ifs_faces = geom.getFieldAsArray('coordIndex', 0, ancestry) coords_tex = None - if ifs_faces: # In rare cases this causes problems - no faces but UVs??? + if ifs_faces: # In rare cases this causes problems - no faces but UVs??? # WORKS - VRML ONLY # coords_tex = geom.getChildByName('texCoord') @@ -1541,27 +1591,26 @@ def importMesh_IndexedFaceSet(geom, bpyima, ancestry): # IF we have no coords, then dont bother coords_tex = None - # WORKS - VRML ONLY # vcolor = geom.getChildByName('color') vcolor = geom.getChildBySpec('Color') - vcolor_spot = None # spot color when we dont have an array of colors + vcolor_spot = None # spot color when we dont have an array of colors if vcolor: # float to char - ifs_vcol = [(0,0,0)] # EEKADOODLE - vertex start at 1 - ifs_vcol.extend([[int(c*256) for c in col] for col in vcolor.getFieldAsArray('color', 3, ancestry)]) + ifs_vcol = [(0, 0, 0)] # EEKADOODLE - vertex start at 1 + ifs_vcol.extend([[int(c * 256) for c in col] for col in vcolor.getFieldAsArray('color', 3, ancestry)]) ifs_color_index = geom.getFieldAsArray('colorIndex', 0, ancestry) if not ifs_vcol: - vcolor_spot = [int(c*256) for c in vcolor.getFieldAsFloatTuple('color', [], ancestry)] + vcolor_spot = [int(c * 256) for c in vcolor.getFieldAsFloatTuple('color', [], ancestry)] # Convert faces into somthing blender can use edges = [] # All lists are aligned! faces = [] - faces_uv = [] # if ifs_texfaces is empty then the faces_uv will match faces exactly. - faces_orig_index = [] # for ngons, we need to know our original index + faces_uv = [] # if ifs_texfaces is empty then the faces_uv will match faces exactly. + faces_orig_index = [] # for ngons, we need to know our original index if coords_tex and ifs_texfaces: do_uvmap = True @@ -1572,19 +1621,20 @@ def importMesh_IndexedFaceSet(geom, bpyima, ancestry): def add_face(face, fuvs, orig_index): l = len(face) - if l==3 or l==4: + if l == 3 or l == 4: faces.append(face) # faces_orig_index.append(current_face[0]) if do_uvmap: faces_uv.append(fuvs) faces_orig_index.append(orig_index) - elif l==2: edges.append(face) - elif l>4: + elif l == 2: + edges.append(face) + elif l > 4: for i in xrange(2, len(face)): - faces.append([face[0], face[i-1], face[i]]) + faces.append([face[0], face[i - 1], face[i]]) if do_uvmap: - faces_uv.append([fuvs[0], fuvs[i-1], fuvs[i]]) + faces_uv.append([fuvs[0], fuvs[i - 1], fuvs[i]]) faces_orig_index.append(orig_index) else: # faces with 1 verts? pfft! @@ -1600,11 +1650,11 @@ def importMesh_IndexedFaceSet(geom, bpyima, ancestry): # face.append(int(fi)) # in rare cases this is a float # EEKADOODLE!!! # Annoyance where faces that have a zero index vert get rotated. This will then mess up UVs and VColors - face.append(int(fi)+1) # in rare cases this is a float, +1 because of stupid EEKADOODLE :/ + face.append(int(fi) + 1) # in rare cases this is a float, +1 because of stupid EEKADOODLE :/ if do_uvmap: if i >= len(ifs_texfaces): - print '\tWarning: UV Texface index out of range' + print('\tWarning: UV Texface index out of range') fuvs.append(ifs_texfaces[0]) else: fuvs.append(ifs_texfaces[i]) @@ -1616,44 +1666,44 @@ def importMesh_IndexedFaceSet(geom, bpyima, ancestry): orig_index += 1 add_face(face, fuvs, orig_index) - del add_face # dont need this func anymore + del add_face # dont need this func anymore bpymesh = bpy.data.meshes.new() - bpymesh.verts.extend([(0,0,0)]) # EEKADOODLE + bpymesh.verts.extend([(0, 0, 0)]) # EEKADOODLE bpymesh.verts.extend(ifs_points) - # print len(ifs_points), faces, edges, ngons + # print(len(ifs_points), faces, edges, ngons) try: bpymesh.faces.extend(faces, smooth=True, ignoreDups=True) except KeyError: - print "one or more vert indicies out of range. corrupt file?" + print("one or more vert indicies out of range. corrupt file?") #for f in faces: # bpymesh.faces.extend(faces, smooth=True) bpymesh.calcNormals() if len(bpymesh.faces) != len(faces): - print '\tWarning: adding faces did not work! file is invalid, not adding UVs or vcolors' + print('\tWarning: adding faces did not work! file is invalid, not adding UVs or vcolors') return bpymesh, ccw # Apply UVs if we have them if not do_uvmap: - faces_uv = faces # fallback, we didnt need a uvmap in the first place, fallback to the face/vert mapping. + faces_uv = faces # fallback, we didnt need a uvmap in the first place, fallback to the face/vert mapping. if coords_tex: - #print ifs_texpoints - # print geom + #print(ifs_texpoints) + # print(geom) bpymesh.faceUV = True - for i,f in enumerate(bpymesh.faces): + for i, f in enumerate(bpymesh.faces): f.image = bpyima - fuv = faces_uv[i] # uv indicies - for j,uv in enumerate(f.uv): - # print fuv, j, len(ifs_texpoints) + fuv = faces_uv[i] # uv indicies + for j, uv in enumerate(f.uv): + # print(fuv, j, len(ifs_texpoints)) try: uv[:] = ifs_texpoints[fuv[j]] except: - print '\tWarning: UV Index out of range' + print('\tWarning: UV Index out of range') uv[:] = ifs_texpoints[0] elif bpyima and len(bpymesh.faces): @@ -1675,14 +1725,20 @@ def importMesh_IndexedFaceSet(geom, bpyima, ancestry): xmin, ymin, zmin = ifs_points[0] xmax, ymax, zmax = ifs_points[0] for co in ifs_points: - x,y,z = co - if x < xmin: xmin = x - if y < ymin: ymin = y - if z < zmin: zmin = z + x, y, z = co + if x < xmin: + xmin = x + if y < ymin: + ymin = y + if z < zmin: + zmin = z - if x > xmax: xmax = x - if y > ymax: ymax = y - if z > zmax: zmax = z + if x > xmax: + xmax = x + if y > ymax: + ymax = y + if z > zmax: + zmax = z xlen = xmax - xmin ylen = ymax - ymin @@ -1696,7 +1752,7 @@ def importMesh_IndexedFaceSet(geom, bpyima, ancestry): depth_idx = [depth_list.index(val) for val in depth_sort] axis_u = depth_idx[-1] - axis_v = depth_idx[-2] # second longest + axis_v = depth_idx[-2] # second longest # Hack, swap these !!! TODO - Why swap??? - it seems to work correctly but should not. # axis_u,axis_v = axis_v,axis_u @@ -1721,68 +1777,70 @@ def importMesh_IndexedFaceSet(geom, bpyima, ancestry): f.image = bpyima fuv = f.uv - for i,v in enumerate(f): + for i, v in enumerate(f): co = v.co - fuv[i][:] = (co[axis_u]-min_u) / depth_u, (co[axis_v]-min_v) / depth_v + fuv[i][:] = (co[axis_u] - min_u) / depth_u, (co[axis_v] - min_v) / depth_v # Add vcote if vcolor: - # print ifs_vcol + # print(ifs_vcol) bpymesh.vertexColors = True for f in bpymesh.faces: fcol = f.col if ifs_colorPerVertex: fv = f.verts - for i,c in enumerate(fcol): - color_index = fv[i].index # color index is vert index + for i, c in enumerate(fcol): + color_index = fv[i].index # color index is vert index if ifs_color_index: try: color_index = ifs_color_index[color_index] except: - print '\tWarning: per vertex color index out of range' + print('\tWarning: per vertex color index out of range') continue if color_index < len(ifs_vcol): c.r, c.g, c.b = ifs_vcol[color_index] else: - #print '\tWarning: per face color index out of range' + #print('\tWarning: per face color index out of range') pass else: - if vcolor_spot: # use 1 color, when ifs_vcol is [] + if vcolor_spot: # use 1 color, when ifs_vcol is [] for c in fcol: c.r, c.g, c.b = vcolor_spot else: - color_index = faces_orig_index[f.index] # color index is face index - #print color_index, ifs_color_index + color_index = faces_orig_index[f.index] # color index is face index + #print(color_index, ifs_color_index) if ifs_color_index: if color_index <= len(ifs_color_index): - print '\tWarning: per face color index out of range' + print('\tWarning: per face color index out of range') color_index = 0 else: color_index = ifs_color_index[color_index] - col = ifs_vcol[color_index] - for i,c in enumerate(fcol): + for i, c in enumerate(fcol): try: c.r, c.g, c.b = col except: - pass # incase its not between 0 and 255 + pass # incase its not between 0 and 255 - bpymesh.verts.delete([0,]) # EEKADOODLE + bpymesh.verts.delete([0, ]) # EEKADOODLE return bpymesh, ccw + def importMesh_IndexedLineSet(geom, ancestry): # VRML not x3d #coord = geom.getChildByName('coord') # 'Coordinate' - coord = geom.getChildBySpec('Coordinate') # works for x3d and vrml - if coord: points = coord.getFieldAsArray('point', 3, ancestry) - else: points = [] + coord = geom.getChildBySpec('Coordinate') # works for x3d and vrml + if coord: + points = coord.getFieldAsArray('point', 3, ancestry) + else: + points = [] if not points: - print '\tWarning: IndexedLineSet had no points' + print('\tWarning: IndexedLineSet had no points') return None ils_lines = geom.getFieldAsArray('coordIndex', 0, ancestry) @@ -1791,7 +1849,7 @@ def importMesh_IndexedLineSet(geom, ancestry): line = [] for il in ils_lines: - if il==-1: + if il == -1: lines.append(line) line = [] else: @@ -1803,7 +1861,7 @@ def importMesh_IndexedLineSet(geom, ancestry): bpycurve = bpy.data.curves.new('IndexedCurve', 'Curve') bpycurve.setFlag(1) - w=t=1 + w = t = 1 curve_index = 0 @@ -1812,13 +1870,12 @@ def importMesh_IndexedLineSet(geom, ancestry): continue co = points[line[0]] bpycurve.appendNurb([co[0], co[1], co[2], w, t]) - bpycurve[curve_index].type= 0 # Poly Line + bpycurve[curve_index].type = 0 # Poly Line for il in line[1:]: co = points[il] bpycurve.appendPoint(curve_index, [co[0], co[1], co[2], w]) - curve_index += 1 return bpycurve @@ -1828,30 +1885,34 @@ def importMesh_PointSet(geom, ancestry): # VRML not x3d #coord = geom.getChildByName('coord') # 'Coordinate' coord = geom.getChildBySpec('Coordinate') # works for x3d and vrml - if coord: points = coord.getFieldAsArray('point', 3, ancestry) - else: points = [] + if coord: + points = coord.getFieldAsArray('point', 3, ancestry) + else: + points = [] # vcolor = geom.getChildByName('color') # blender dosnt have per vertex color bpymesh = bpy.data.meshes.new() bpymesh.verts.extend(points) - bpymesh.calcNormals() # will just be dummy normals + bpymesh.calcNormals() # will just be dummy normals return bpymesh GLOBALS['CIRCLE_DETAIL'] = 12 MATRIX_Z_TO_Y = RotationMatrix(90, 4, 'x') + def importMesh_Sphere(geom, ancestry): # bpymesh = bpy.data.meshes.new() - diameter = geom.getFieldAsFloat('radius', 0.5, ancestry) * 2 # * 2 for the diameter + diameter = geom.getFieldAsFloat('radius', 0.5, ancestry) * 2 # * 2 for the diameter bpymesh = Mesh.Primitives.UVsphere(GLOBALS['CIRCLE_DETAIL'], GLOBALS['CIRCLE_DETAIL'], diameter) bpymesh.transform(MATRIX_Z_TO_Y) return bpymesh + def importMesh_Cylinder(geom, ancestry): # bpymesh = bpy.data.meshes.new() - diameter = geom.getFieldAsFloat('radius', 1.0, ancestry) * 2 # * 2 for the diameter + diameter = geom.getFieldAsFloat('radius', 1.0, ancestry) * 2 # * 2 for the diameter height = geom.getFieldAsFloat('height', 2, ancestry) bpymesh = Mesh.Primitives.Cylinder(GLOBALS['CIRCLE_DETAIL'], diameter, height) bpymesh.transform(MATRIX_Z_TO_Y) @@ -1863,21 +1924,22 @@ def importMesh_Cylinder(geom, ancestry): side = geom.getFieldAsBool('side', True, ancestry) top = geom.getFieldAsBool('top', True, ancestry) - if not top: # last vert is top center of tri fan. - bpymesh.verts.delete([(GLOBALS['CIRCLE_DETAIL']+GLOBALS['CIRCLE_DETAIL'])+1]) + if not top: # last vert is top center of tri fan. + bpymesh.verts.delete([(GLOBALS['CIRCLE_DETAIL'] + GLOBALS['CIRCLE_DETAIL']) + 1]) - if not bottom: # second last vert is bottom of triangle fan - bpymesh.verts.delete([GLOBALS['CIRCLE_DETAIL']+GLOBALS['CIRCLE_DETAIL']]) + if not bottom: # second last vert is bottom of triangle fan + bpymesh.verts.delete([GLOBALS['CIRCLE_DETAIL'] + GLOBALS['CIRCLE_DETAIL']]) if not side: # remove all quads - bpymesh.faces.delete(1, [f for f in bpymesh.faces if len(f)==4]) + bpymesh.faces.delete(1, [f for f in bpymesh.faces if len(f) == 4]) return bpymesh + def importMesh_Cone(geom, ancestry): # bpymesh = bpy.data.meshes.new() - diameter = geom.getFieldAsFloat('bottomRadius', 1.0, ancestry) * 2 # * 2 for the diameter + diameter = geom.getFieldAsFloat('bottomRadius', 1.0, ancestry) * 2 # * 2 for the diameter height = geom.getFieldAsFloat('height', 2, ancestry) bpymesh = Mesh.Primitives.Cone(GLOBALS['CIRCLE_DETAIL'], diameter, height) bpymesh.transform(MATRIX_Z_TO_Y) @@ -1888,13 +1950,14 @@ def importMesh_Cone(geom, ancestry): bottom = geom.getFieldAsBool('bottom', True, ancestry) side = geom.getFieldAsBool('side', True, ancestry) - if not bottom: # last vert is on the bottom - bpymesh.verts.delete([GLOBALS['CIRCLE_DETAIL']+1]) - if not side: # second last vert is on the pointy bit of the cone + if not bottom: # last vert is on the bottom + bpymesh.verts.delete([GLOBALS['CIRCLE_DETAIL'] + 1]) + if not side: # second last vert is on the pointy bit of the cone bpymesh.verts.delete([GLOBALS['CIRCLE_DETAIL']]) return bpymesh + def importMesh_Box(geom, ancestry): # bpymesh = bpy.data.meshes.new() @@ -1902,14 +1965,16 @@ def importMesh_Box(geom, ancestry): bpymesh = Mesh.Primitives.Cube(1.0) # Scale the box to the size set - scale_mat = Matrix([size[0],0,0], [0, size[1], 0], [0, 0, size[2]]) + scale_mat = Matrix([size[0], 0, 0], [0, size[1], 0], [0, 0, size[2]]) bpymesh.transform(scale_mat.resize4x4()) return bpymesh + def importShape(node, ancestry): vrmlname = node.getDefName() - if not vrmlname: vrmlname = 'Shape' + if not vrmlname: + vrmlname = 'Shape' # works 100% in vrml, but not x3d #appr = node.getChildByName('appearance') # , 'Appearance' @@ -1925,14 +1990,14 @@ def importShape(node, ancestry): bpyima = None texmtx = None - depth = 0 # so we can set alpha face flag later + depth = 0 # so we can set alpha face flag later if appr: #mat = appr.getChildByName('material') # 'Material' #ima = appr.getChildByName('texture') # , 'ImageTexture' #if ima and ima.getSpec() != 'ImageTexture': - # print '\tWarning: texture type "%s" is not supported' % ima.getSpec() + # print('\tWarning: texture type "%s" is not supported' % ima.getSpec()) # ima = None # textx = appr.getChildByName('textureTransform') @@ -1944,52 +2009,52 @@ def importShape(node, ancestry): if textx: texmtx = translateTexTransform(textx, ancestry) - - - # print mat, ima + # print(mat, ima) if mat or ima: if not mat: - mat = ima # This is a bit dumb, but just means we use default values for all + mat = ima # This is a bit dumb, but just means we use default values for all # all values between 0.0 and 1.0, defaults from VRML docs bpymat = bpy.data.materials.new() - bpymat.amb = mat.getFieldAsFloat('ambientIntensity', 0.2, ancestry) - bpymat.rgbCol = mat.getFieldAsFloatTuple('diffuseColor', [0.8, 0.8, 0.8], ancestry) + bpymat.amb = mat.getFieldAsFloat('ambientIntensity', 0.2, ancestry) + bpymat.rgbCol = mat.getFieldAsFloatTuple('diffuseColor', [0.8, 0.8, 0.8], ancestry) # NOTE - blender dosnt support emmisive color # Store in mirror color and approximate with emit. - emit = mat.getFieldAsFloatTuple('emissiveColor', [0.0, 0.0, 0.0], ancestry) - bpymat.mirCol = emit - bpymat.emit = (emit[0]+emit[1]+emit[2])/3.0 + emit = mat.getFieldAsFloatTuple('emissiveColor', [0.0, 0.0, 0.0], ancestry) + bpymat.mirCol = emit + bpymat.emit = (emit[0] + emit[1] + emit[2]) / 3.0 - bpymat.hard = int(1+(510*mat.getFieldAsFloat('shininess', 0.2, ancestry))) # 0-1 -> 1-511 - bpymat.specCol = mat.getFieldAsFloatTuple('specularColor', [0.0, 0.0, 0.0], ancestry) - bpymat.alpha = 1.0 - mat.getFieldAsFloat('transparency', 0.0, ancestry) + bpymat.hard = int(1 + (510 * mat.getFieldAsFloat('shininess', 0.2, ancestry))) # 0-1 -> 1-511 + bpymat.specCol = mat.getFieldAsFloatTuple('specularColor', [0.0, 0.0, 0.0], ancestry) + bpymat.alpha = 1.0 - mat.getFieldAsFloat('transparency', 0.0, ancestry) if bpymat.alpha < 0.999: bpymat.mode |= Material.Modes.ZTRANSP - if ima: + ima_url = ima.getFieldAsString('url', None, ancestry) - ima_url = ima.getFieldAsString('url', None, ancestry) + if ima_url == None: + try: + ima_url = ima.getFieldAsStringArray('url', ancestry)[0] # in some cases we get a list of images. + except: + ima_url = None - if ima_url==None: - try: ima_url = ima.getFieldAsStringArray('url', ancestry)[0] # in some cases we get a list of images. - except: ima_url = None - - if ima_url==None: - print "\twarning, image with no URL, this is odd" + if ima_url == None: + print("\twarning, image with no URL, this is odd") else: - bpyima= BPyImage.comprehensiveImageLoad(ima_url, dirName(node.getFilename()), PLACE_HOLDER= False, RECURSIVE= False, CONVERT_CALLBACK= imageConvertCompat) + bpyima = BPyImage.comprehensiveImageLoad(ima_url, dirName(node.getFilename()), PLACE_HOLDER=False, RECURSIVE=False, CONVERT_CALLBACK=imageConvertCompat) if bpyima: - texture= bpy.data.textures.new() + texture = bpy.data.textures.new() texture.setType('Image') texture.image = bpyima # Adds textures for materials (rendering) - try: depth = bpyima.depth - except: depth = -1 + try: + depth = bpyima.depth + except: + depth = -1 if depth == 32: # Image has alpha @@ -2000,14 +2065,16 @@ def importShape(node, ancestry): else: bpymat.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.COL) - ima_repS = ima.getFieldAsBool('repeatS', True, ancestry) - ima_repT = ima.getFieldAsBool('repeatT', True, ancestry) + ima_repS = ima.getFieldAsBool('repeatS', True, ancestry) + ima_repT = ima.getFieldAsBool('repeatT', True, ancestry) # To make this work properly we'd need to scale the UV's too, better to ignore th # texture.repeat = max(1, ima_repS * 512), max(1, ima_repT * 512) - if not ima_repS: bpyima.clampX = True - if not ima_repT: bpyima.clampY = True + if not ima_repS: + bpyima.clampX = True + if not ima_repT: + bpyima.clampY = True bpydata = None geom_spec = geom.getSpec() @@ -2027,7 +2094,7 @@ def importShape(node, ancestry): elif geom_spec == 'Cone': bpydata = importMesh_Cone(geom, ancestry) else: - print '\tWarning: unsupported type "%s"' % geom_spec + print('\tWarning: unsupported type "%s"' % geom_spec) return if bpydata: @@ -2035,22 +2102,23 @@ def importShape(node, ancestry): bpydata.name = vrmlname - bpyob = node.blendObject = bpy.data.scenes.active.objects.new(bpydata) + bpyob = node.blendObject = bpy.data.scenes.active.objects.new(bpydata) if type(bpydata) == Types.MeshType: - is_solid = geom.getFieldAsBool('solid', True, ancestry) - creaseAngle = geom.getFieldAsFloat('creaseAngle', None, ancestry) + is_solid = geom.getFieldAsBool('solid', True, ancestry) + creaseAngle = geom.getFieldAsFloat('creaseAngle', None, ancestry) if creaseAngle != None: - bpydata.maxSmoothAngle = 1+int(min(79, creaseAngle * RAD_TO_DEG)) + bpydata.maxSmoothAngle = 1 + int(min(79, creaseAngle * RAD_TO_DEG)) bpydata.mode |= Mesh.Modes.AUTOSMOOTH # Only ever 1 material per shape - if bpymat: bpydata.materials = [bpymat] + if bpymat: + bpydata.materials = [bpymat] if bpydata.faceUV: - if depth==32: # set the faces alpha flag? + if depth == 32: # set the faces alpha flag? transp = Mesh.FaceTranspModes.ALPHA for f in bpydata.faces: f.transp = transp @@ -2066,28 +2134,26 @@ def importShape(node, ancestry): uv.x, uv.y = (uv_copy * texmtx)[0:2] # Done transforming the texture - # Must be here and not in IndexedFaceSet because it needs an object for the flip func. Messy :/ - if not ccw: bpydata.flipNormals() - + if not ccw: + bpydata.flipNormals() # else could be a curve for example - - # Can transform data or object, better the object so we can instance the data #bpymesh.transform(getFinalMatrix(node)) - bpyob.setMatrix( getFinalMatrix(node, None, ancestry) ) + bpyob.setMatrix(getFinalMatrix(node, None, ancestry)) def importLamp_PointLight(node, ancestry): vrmlname = node.getDefName() - if not vrmlname: vrmlname = 'PointLight' + if not vrmlname: + vrmlname = 'PointLight' # ambientIntensity = node.getFieldAsFloat('ambientIntensity', 0.0, ancestry) # TODO # attenuation = node.getFieldAsFloatTuple('attenuation', (1.0, 0.0, 0.0), ancestry) # TODO color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0), ancestry) - intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher. + intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher. location = node.getFieldAsFloatTuple('location', (0.0, 0.0, 0.0), ancestry) # is_on = node.getFieldAsBool('on', True, ancestry) # TODO radius = node.getFieldAsFloat('radius', 100.0, ancestry) @@ -2102,14 +2168,16 @@ def importLamp_PointLight(node, ancestry): return bpylamp, mtx + def importLamp_DirectionalLight(node, ancestry): vrmlname = node.getDefName() - if not vrmlname: vrmlname = 'DirectLight' + if not vrmlname: + vrmlname = 'DirectLight' # ambientIntensity = node.getFieldAsFloat('ambientIntensity', 0.0) # TODO color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0), ancestry) direction = node.getFieldAsFloatTuple('direction', (0.0, 0.0, -1.0), ancestry) - intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher. + intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher. # is_on = node.getFieldAsBool('on', True, ancestry) # TODO bpylamp = bpy.data.lamps.new(vrmlname) @@ -2124,17 +2192,19 @@ def importLamp_DirectionalLight(node, ancestry): # looks like default values for beamWidth and cutOffAngle were swapped in VRML docs. + def importLamp_SpotLight(node, ancestry): vrmlname = node.getDefName() - if not vrmlname: vrmlname = 'SpotLight' + if not vrmlname: + vrmlname = 'SpotLight' # ambientIntensity = geom.getFieldAsFloat('ambientIntensity', 0.0, ancestry) # TODO # attenuation = geom.getFieldAsFloatTuple('attenuation', (1.0, 0.0, 0.0), ancestry) # TODO - beamWidth = node.getFieldAsFloat('beamWidth', 1.570796, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. + beamWidth = node.getFieldAsFloat('beamWidth', 1.570796, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. color = node.getFieldAsFloatTuple('color', (1.0, 1.0, 1.0), ancestry) - cutOffAngle = node.getFieldAsFloat('cutOffAngle', 0.785398, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. + cutOffAngle = node.getFieldAsFloat('cutOffAngle', 0.785398, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. direction = node.getFieldAsFloatTuple('direction', (0.0, 0.0, -1.0), ancestry) - intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher. + intensity = node.getFieldAsFloat('intensity', 1.0, ancestry) # max is documented to be 1.0 but some files have higher. location = node.getFieldAsFloatTuple('location', (0.0, 0.0, 0.0), ancestry) # is_on = node.getFieldAsBool('on', True, ancestry) # TODO radius = node.getFieldAsFloat('radius', 100.0, ancestry) @@ -2148,7 +2218,7 @@ def importLamp_SpotLight(node, ancestry): if beamWidth > cutOffAngle: bpylamp.spotBlend = 0.0 else: - if cutOffAngle==0.0: #@#$%^&*(!!! - this should never happen + if cutOffAngle == 0.0: # this should never happen! bpylamp.spotBlend = 0.5 else: bpylamp.spotBlend = beamWidth / cutOffAngle @@ -2162,25 +2232,26 @@ def importLamp_SpotLight(node, ancestry): def importLamp(node, spec, ancestry): - if spec=='PointLight': - bpylamp,mtx = importLamp_PointLight(node, ancestry) - elif spec=='DirectionalLight': - bpylamp,mtx = importLamp_DirectionalLight(node, ancestry) - elif spec=='SpotLight': - bpylamp,mtx = importLamp_SpotLight(node, ancestry) + if spec == 'PointLight': + bpylamp, mtx = importLamp_PointLight(node, ancestry) + elif spec == 'DirectionalLight': + bpylamp, mtx = importLamp_DirectionalLight(node, ancestry) + elif spec == 'SpotLight': + bpylamp, mtx = importLamp_SpotLight(node, ancestry) else: - print "Error, not a lamp" + print("Error, not a lamp") raise ValueError bpyob = node.blendObject = bpy.data.scenes.active.objects.new(bpylamp) - bpyob.setMatrix( getFinalMatrix(node, mtx, ancestry) ) + bpyob.setMatrix(getFinalMatrix(node, mtx, ancestry)) def importViewpoint(node, ancestry): name = node.getDefName() - if not name: name = 'Viewpoint' + if not name: + name = 'Viewpoint' - fieldOfView = node.getFieldAsFloat('fieldOfView', 0.785398, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. + fieldOfView = node.getFieldAsFloat('fieldOfView', 0.785398, ancestry) * RAD_TO_DEG # max is documented to be 1.0 but some files have higher. # jump = node.getFieldAsBool('jump', True, ancestry) orientation = node.getFieldAsFloatTuple('orientation', (0.0, 0.0, 1.0, 0.0), ancestry) position = node.getFieldAsFloatTuple('position', (0.0, 0.0, 0.0), ancestry) @@ -2192,21 +2263,21 @@ def importViewpoint(node, ancestry): mtx = translateRotation(orientation) * TranslationMatrix(Vector(position)) - bpyob = node.blendObject = bpy.data.scenes.active.objects.new(bpycam) - bpyob.setMatrix( getFinalMatrix(node, mtx, ancestry) ) + bpyob.setMatrix(getFinalMatrix(node, mtx, ancestry)) def importTransform(node, ancestry): name = node.getDefName() - if not name: name = 'Transform' + if not name: + name = 'Transform' - bpyob = node.blendObject = bpy.data.scenes.active.objects.new('Empty', name) # , name) - bpyob.setMatrix( getFinalMatrix(node, None, ancestry) ) + bpyob = node.blendObject = bpy.data.scenes.active.objects.new('Empty', name) # , name) + bpyob.setMatrix(getFinalMatrix(node, None, ancestry)) # so they are not too annoying - bpyob.emptyShape= Blender.Object.EmptyShapes.AXES - bpyob.drawSize= 0.2 + bpyob.emptyShape = Blender.Object.EmptyShapes.AXES + bpyob.drawSize = 0.2 #def importTimeSensor(node): @@ -2226,12 +2297,15 @@ def translatePositionInterpolator(node, ipo, ancestry): loc_x.interpolation = loc_y.interpolation = loc_z.interpolation = Blender.IpoCurve.InterpTypes.LINEAR for i, time in enumerate(key): - try: x,y,z = keyValue[i] - except: continue + try: + x, y, z = keyValue[i] + except: + continue + + loc_x.append((time, x)) + loc_y.append((time, y)) + loc_z.append((time, z)) - loc_x.append((time,x)) - loc_y.append((time,y)) - loc_z.append((time,z)) def translateOrientationInterpolator(node, ipo, ancestry): key = node.getFieldAsArray('key', 0, ancestry) @@ -2247,14 +2321,17 @@ def translateOrientationInterpolator(node, ipo, ancestry): rot_x.interpolation = rot_y.interpolation = rot_z.interpolation = Blender.IpoCurve.InterpTypes.LINEAR for i, time in enumerate(key): - try: x,y,z,w = keyValue[i] - except: continue + try: + x, y, z, w = keyValue[i] + except: + continue - mtx = translateRotation((x,y,z,w)) + mtx = translateRotation((x, y, z, w)) eul = mtx.toEuler() - rot_x.append((time,eul.x/10.0)) - rot_y.append((time,eul.y/10.0)) - rot_z.append((time,eul.z/10.0)) + rot_x.append((time, eul.x / 10.0)) + rot_y.append((time, eul.y / 10.0)) + rot_z.append((time, eul.z / 10.0)) + # Untested! def translateScalarInterpolator(node, ipo, ancestry): @@ -2271,11 +2348,14 @@ def translateScalarInterpolator(node, ipo, ancestry): sca_x.interpolation = sca_y.interpolation = sca_z.interpolation = Blender.IpoCurve.InterpTypes.LINEAR for i, time in enumerate(key): - try: x,y,z = keyValue[i] - except: continue - sca_x.append((time,x/10.0)) - sca_y.append((time,y/10.0)) - sca_z.append((time,z/10.0)) + try: + x, y, z = keyValue[i] + except: + continue + sca_x.append((time, x / 10.0)) + sca_y.append((time, y / 10.0)) + sca_z.append((time, z / 10.0)) + def translateTimeSensor(node, ipo, ancestry): ''' @@ -2292,16 +2372,15 @@ def translateTimeSensor(node, ipo, ancestry): stopTime = node.getFieldAsFloat('stopTime', 250.0, ancestry) if cycleInterval != None: - stopTime = startTime+cycleInterval + stopTime = startTime + cycleInterval loop = node.getFieldAsBool('loop', False, ancestry) - time_cu.append((1+startTime, 0.0)) - time_cu.append((1+stopTime, 1.0/10.0))# anoying, the UI uses /10 - + time_cu.append((1 + startTime, 0.0)) + time_cu.append((1 + stopTime, 1.0 / 10.0)) # anoying, the UI uses /10 if loop: - time_cu.extend = Blender.IpoCurve.ExtendTypes.CYCLIC # or - EXTRAP, CYCLIC_EXTRAP, CONST, + time_cu.extend = Blender.IpoCurve.ExtendTypes.CYCLIC # or - EXTRAP, CYCLIC_EXTRAP, CONST, def importRoute(node, ancestry): @@ -2315,8 +2394,10 @@ def importRoute(node, ancestry): routeIpoDict = node.getRouteIpoDict() def getIpo(id): - try: ipo = routeIpoDict[id] - except: ipo = routeIpoDict[id] = bpy.data.ipos.new('web3d_ipo', 'Object') + try: + ipo = routeIpoDict[id] + except: + ipo = routeIpoDict[id] = bpy.data.ipos.new('web3d_ipo', 'Object') return ipo # for getting definitions @@ -2340,12 +2421,12 @@ ROUTE champFly001.bindTime TO vpTs.set_startTime time_node = None for field in node.fields: - if field and field[0]=='ROUTE': + if field and field[0] == 'ROUTE': try: from_id, from_type = field[1].split('.') to_id, to_type = field[3].split('.') except: - print "Warning, invalid ROUTE", field + print("Warning, invalid ROUTE", field) continue if from_type == 'value_changed': @@ -2364,15 +2445,13 @@ ROUTE champFly001.bindTime TO vpTs.set_startTime set_data_from_node = defDict[from_id] translateScalarInterpolator(set_data_from_node, ipo, ancestry) - elif from_type =='bindTime': + elif from_type == 'bindTime': ipo = getIpo(from_id) time_node = defDict[to_id] translateTimeSensor(time_node, ipo, ancestry) - - -def load_web3d(path, PREF_FLAT=False, PREF_CIRCLE_DIV=16, HELPER_FUNC = None): +def load_web3d(path, PREF_FLAT=False, PREF_CIRCLE_DIV=16, HELPER_FUNC=None): # Used when adding blender primitives GLOBALS['CIRCLE_DETAIL'] = PREF_CIRCLE_DIV @@ -2385,12 +2464,11 @@ def load_web3d(path, PREF_FLAT=False, PREF_CIRCLE_DIV=16, HELPER_FUNC = None): if not root_node: if Blender.mode == 'background': - print msg + print(msg) else: Blender.Draw.PupMenu(msg) return - # fill with tuples - (node, [parents-parent, parent]) all_nodes = root_node.getSerialized([], []) @@ -2409,15 +2487,15 @@ def load_web3d(path, PREF_FLAT=False, PREF_CIRCLE_DIV=16, HELPER_FUNC = None): # Note, include this function so the VRML/X3D importer can be extended # by an external script. - gets first pick pass - if spec=='Shape': + if spec == 'Shape': importShape(node, ancestry) elif spec in ('PointLight', 'DirectionalLight', 'SpotLight'): importLamp(node, spec, ancestry) - elif spec=='Viewpoint': + elif spec == 'Viewpoint': importViewpoint(node, ancestry) - elif spec=='Transform': + elif spec == 'Transform': # Only use transform nodes when we are not importing a flat object hierarchy - if PREF_FLAT==False: + if PREF_FLAT == False: importTransform(node, ancestry) ''' # These are delt with later within importRoute @@ -2426,8 +2504,6 @@ def load_web3d(path, PREF_FLAT=False, PREF_CIRCLE_DIV=16, HELPER_FUNC = None): translatePositionInterpolator(node, ipo) ''' - - # After we import all nodes, route events - anim paths for node, ancestry in all_nodes: importRoute(node, ancestry) @@ -2443,15 +2519,13 @@ def load_web3d(path, PREF_FLAT=False, PREF_CIRCLE_DIV=16, HELPER_FUNC = None): # Assign anim curves node = defDict[key] - if node.blendObject==None: # Add an object if we need one for animation - node.blendObject = bpy.data.scenes.active.objects.new('Empty', 'AnimOb') # , name) + if node.blendObject == None: # Add an object if we need one for animation + node.blendObject = bpy.data.scenes.active.objects.new('Empty', 'AnimOb') # , name) node.blendObject.setIpo(ipo) - - # Add in hierarchy - if PREF_FLAT==False: + if PREF_FLAT == False: child_dict = {} for node, ancestry in all_nodes: if node.blendObject: @@ -2460,7 +2534,7 @@ def load_web3d(path, PREF_FLAT=False, PREF_CIRCLE_DIV=16, HELPER_FUNC = None): # Get the last parent i = len(ancestry) while i: - i-=1 + i -= 1 blendObject = ancestry[i].blendObject if blendObject: break @@ -2470,8 +2544,10 @@ def load_web3d(path, PREF_FLAT=False, PREF_CIRCLE_DIV=16, HELPER_FUNC = None): # blendObject.makeParent([node.blendObject], 0, 1) # Parent FAST - try: child_dict[blendObject].append(node.blendObject) - except: child_dict[blendObject] = [node.blendObject] + try: + child_dict[blendObject].append(node.blendObject) + except: + child_dict[blendObject] = [node.blendObject] # Parent FAST for parent, children in child_dict.iteritems(): @@ -2484,11 +2560,11 @@ def load_web3d(path, PREF_FLAT=False, PREF_CIRCLE_DIV=16, HELPER_FUNC = None): def load_ui(path): Draw = Blender.Draw - PREF_HIERARCHY= Draw.Create(0) - PREF_CIRCLE_DIV= Draw.Create(16) + PREF_HIERARCHY = Draw.Create(0) + PREF_CIRCLE_DIV = Draw.Create(16) # Get USER Options - pup_block= [\ + pup_block = [ \ 'Import...',\ ('Hierarchy', PREF_HIERARCHY, 'Import transform nodes as empties to create a parent/child hierarchy'),\ ('Circle Div:', PREF_CIRCLE_DIV, 3, 128, 'Number of divisions to use for circular primitives') @@ -2545,8 +2621,6 @@ if __name__ == '__main__': # load_web3d('/fe/x3d/www.web3d.org/x3d/content/examples/Basic/StudentProjects/PlayRoom.x3d') # invalid UVs - - def test(): import os @@ -2567,7 +2641,7 @@ def test(): # continue f = f.strip() - print f, i, tot + print(f, i, tot) sce = bpy.data.scenes.new(str(i) + '_' + f.split('/')[-1]) bpy.data.scenes.active = sce # Window.