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. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to