[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [18023] trunk/blender/release/scripts/ import_web3d.py: improved PROTO support, works for many testfiles now.

Campbell Barton ideasman42 at gmail.com
Tue Dec 23 07:47:44 CET 2008


Revision: 18023
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=18023
Author:   campbellbarton
Date:     2008-12-23 07:47:43 +0100 (Tue, 23 Dec 2008)

Log Message:
-----------
improved PROTO support, works for many testfiles now.

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-23 02:07:13 UTC (rev 18022)
+++ trunk/blender/release/scripts/import_web3d.py	2008-12-23 06:47:43 UTC (rev 18023)
@@ -36,6 +36,8 @@
 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 @@
 	# print "error value!!!", words
 	return 0, -1
 
-def is_protoline(i, words, proto_field_defs):
+def is_nodeline(i, words):
 	
-	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
 	
+	#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 @@
 	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 @@
 
 
 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 @@
 		# 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 @@
 			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 @@
 				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 @@
 			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,40 +529,70 @@
 					
 					# 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
 	
 	def getFieldAsInt(self, field, default, ancestry):
@@ -690,13 +703,11 @@
 		'''
 		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 @@
 	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 @@
 			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 @@
 		
 		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 @@
 		
 		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 @@
 			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 @@
 				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 @@
 			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 @@
 				### 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)

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list