[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [18014] trunk/blender/release/scripts/ import_web3d.py: WIP - support for VRML PROTO's
Campbell Barton
ideasman42 at gmail.com
Mon Dec 22 16:05:21 CET 2008
Revision: 18014
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=18014
Author: campbellbarton
Date: 2008-12-22 16:05:07 +0100 (Mon, 22 Dec 2008)
Log Message:
-----------
WIP - support for VRML PROTO's
Modified Paths:
--------------
trunk/blender/release/scripts/import_web3d.py
Modified: trunk/blender/release/scripts/import_web3d.py
===================================================================
--- trunk/blender/release/scripts/import_web3d.py 2008-12-22 12:57:53 UTC (rev 18013)
+++ trunk/blender/release/scripts/import_web3d.py 2008-12-22 15:05:07 UTC (rev 18014)
@@ -201,6 +201,7 @@
NODE_NORMAL = 1 # {}
NODE_ARRAY = 2 # []
NODE_REFERENCE = 3 # USE foobar
+# NODE_PROTO = 4 #
lines = []
@@ -211,6 +212,10 @@
if i>=len(lines):
break
+ '''
+ elif lines[i].startswith('PROTO'):
+ return NODE_PROTO, i+1
+ '''
elif lines[i]=='{':
# words.append(lines[i]) # no need
# print "OK"
@@ -239,11 +244,45 @@
# print "error value!!!", words
return 0, -1
-def is_nodeline(i, words):
+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):
+
if not lines[i][0].isalpha():
return 0, 0
+ # Is this a prototype??
+ 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] == '[':
if lines[i].count('"') % 2 == 0:
@@ -253,6 +292,7 @@
node_type, new_i = getNodePreText(i, words)
if not node_type:
+ print "not node_type", lines[i]
return 0, 0
# Ok, we have a { after some values
@@ -311,10 +351,10 @@
return True
except:
return False
-
+
class vrmlNode(object):
- __slots__ = 'id', 'fields', 'node_type', 'parent', 'children', 'parent', 'array_data', 'reference', 'lineno', 'filename', 'blendObject', 'DEF_NAMESPACE', 'ROUTE_IPO_NAMESPACE', 'FIELD_NAMESPACE', 'x3dNode'
+ __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'
def __init__(self, parent, node_type, lineno):
self.id = None
self.node_type = node_type
@@ -333,8 +373,13 @@
# Store in the root node because each inline file needs its own root node and its own namespace
self.DEF_NAMESPACE = None
self.ROUTE_IPO_NAMESPACE = None
+ '''
self.FIELD_NAMESPACE = None
+ '''
+
+ self.PROTO_NAMESPACE = None
+
self.reference = None
if node_type==NODE_REFERENCE:
@@ -343,16 +388,25 @@
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 = []
self.array_data = [] # use for arrays of data - should only be for NODE_ARRAY types
# Only available from the root node
+ '''
def getFieldDict(self):
if self.FIELD_NAMESPACE != None:
return self.FIELD_NAMESPACE
else:
return self.parent.getFieldDict()
+ '''
+ def getProtoDict(self):
+ if self.PROTO_NAMESPACE != None:
+ return self.PROTO_NAMESPACE
+ else:
+ return self.parent.getProtoDict()
def getDefDict(self):
if self.DEF_NAMESPACE != None:
@@ -368,9 +422,10 @@
def setRoot(self, filename):
self.filename = filename
- self.FIELD_NAMESPACE = {}
+ # self.FIELD_NAMESPACE = {}
self.DEF_NAMESPACE = {}
self.ROUTE_IPO_NAMESPACE = {}
+ self.PROTO_NAMESPACE = {}
def isRoot(self):
if self.filename == None:
@@ -404,16 +459,18 @@
return self.id[0]
return None
- def getDefName(self):
+ def getSpecialTypeName(self, typename):
self_real = self.getRealNode()
-
- if 'DEF' in self_real.id:
- # print self_real.id
- return self_real.id[ list(self_real.id).index('DEF')+1 ]
- else:
- return None
-
+ try: return self_real.id[ list(self_real.id).index(typename)+1 ]
+ except: return None
+
+ def getDefName(self):
+ return self.getSpecialTypeName('DEF')
+
+ def getProtoName(self):
+ return self.getSpecialTypeName('PROTO')
+
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
@@ -449,7 +506,21 @@
ancestry.append(self)
for child in self.getRealNode().children:
if child not in ancestry:
- child.getSerialized(results, ancestry)
+ # We dont want to load proto's, they are only references
+ # We could enforce this elsewhere
+
+ # Only add this in a very special case
+ # where the parent of this object is not the real parent
+ # - In this case we have added the proto as a child to a node instancing it.
+ # This is a bit arbitary, but its how Proto's are done with this importer.
+ if child.getProtoName() == None:
+ child.getSerialized(results, ancestry)
+ else:
+ print "\n\n\n\nTEST!!!!!!!!!!!!!"
+ print child.getProtoName(), self.getSpec()
+ if child.getProtoName()==self.getSpec():
+ print "PROTO!!!!!!!!!!!!!!!!\n"
+ child.getSerialized(results, ancestry)
return results
@@ -462,7 +533,7 @@
child.searchNodeTypeID(node_spec, results)
return results
- def getFieldName(self, field):
+ def getFieldName(self, field, ancestry):
self_real = self.getRealNode() # incase we're an instance
for f in self_real.fields:
@@ -470,14 +541,51 @@
if f and f[0] == field:
# print '\tfound field', f
- return f[1:]
+ if len(f)>=3 and f[1] == 'IS': # eg: 'diffuseColor IS legColor'
+ field_id = f[2]
+
+ # print "\n\n\n\n\n\nFOND IS!!!"
+ f_proto_lookup = None
+ i = len(ancestry)
+ while i:
+ i -= 1
+ node = ancestry[i]
+
+ # 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:]
+
+ # 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
+
+ return f_proto_lookup
+ else:
+ # Not using a proto
+ return f[1:]
# print '\tfield not found', field
+
+
+ # See if this is a proto name
+
+
+
return None
- def getFieldAsInt(self, field, default):
+ def getFieldAsInt(self, field, default, ancestry):
self_real = self.getRealNode() # incase we're an instance
- f = self_real.getFieldName(field)
+ f = self_real.getFieldName(field, ancestry)
if f==None: return default
if ',' in f: f = f[:f.index(',')] # strip after the comma
@@ -491,10 +599,10 @@
print '\tvalue "%s" could not be used as an int for field "%s"' % (f[0], field)
return default
- def getFieldAsFloat(self, field, default):
+ def getFieldAsFloat(self, field, default, ancestry):
self_real = self.getRealNode() # incase we're an instance
- f = self_real.getFieldName(field)
+ f = self_real.getFieldName(field, ancestry)
if f==None: return default
if ',' in f: f = f[:f.index(',')] # strip after the comma
@@ -508,10 +616,10 @@
print '\tvalue "%s" could not be used as a float for field "%s"' % (f[0], field)
return default
- def getFieldAsFloatTuple(self, field, default):
+ def getFieldAsFloatTuple(self, field, default, ancestry):
self_real = self.getRealNode() # incase we're an instance
- f = self_real.getFieldName(field)
+ f = self_real.getFieldName(field, ancestry)
if f==None: return default
# if ',' in f: f = f[:f.index(',')] # strip after the comma
@@ -532,10 +640,10 @@
print '\tvalue "%s" could not be used as a float tuple for field "%s"' % (f, field)
return default
- def getFieldAsBool(self, field, default):
+ def getFieldAsBool(self, field, default, ancestry):
self_real = self.getRealNode() # incase we're an instance
- f = self_real.getFieldName(field)
+ f = self_real.getFieldName(field, ancestry)
if f==None: return default
if ',' in f: f = f[:f.index(',')] # strip after the comma
@@ -551,10 +659,10 @@
print '\t"%s" could not be used as a bool for field "%s"' % (f[1], field)
return default
- def getFieldAsString(self, field, default=None):
+ def getFieldAsString(self, field, default, ancestry):
self_real = self.getRealNode() # incase we're an instance
- f = self_real.getFieldName(field)
+ f = self_real.getFieldName(field, ancestry)
if f==None: return default
if len(f) < 1:
print '\t"%s" wrong length for string conversion for field "%s"' % (f, field)
@@ -576,7 +684,7 @@
print '\tvalue "%s" could not be used as a string for field "%s"' % (f[0], field)
return default
- def getFieldAsArray(self, field, group):
+ def getFieldAsArray(self, field, group, ancestry):
'''
For this parser arrays are children
'''
@@ -593,7 +701,7 @@
# For x3d, should work ok with vrml too
# for x3d arrays are fields, vrml they are nodes, annoying but not tooo bad.
- data_split = self.getFieldName(field)
+ data_split = self.getFieldName(field, ancestry)
if not data_split:
return []
array_data = ' '.join(data_split)
@@ -660,7 +768,7 @@
return new_array
- def getFieldAsStringArray(self, field):
+ def getFieldAsStringArray(self, field, ancestry):
'''
Get a list of strings
'''
@@ -698,7 +806,7 @@
def __repr__(self):
level = self.getLevel()
ind = ' ' * level
-
+ print self.id
if self.node_type==NODE_REFERENCE:
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list