blender/intern/python/modules/vrml/scenegraph.py
Michel Selten c95d631b83 Removed references to modules that do not exist. The python interface is
broken, but it should give 0 errors when building.

Michel
2003-01-06 17:27:43 +00:00

835 lines
27 KiB
Python

# VRML node prototype class (SGbuilder)
# Wed Oct 31 16:18:35 CET 2001
'''Prototype2 -- VRML 97 sceneGraph/Node/Script/ROUTE/IS implementations'''
#import copy, types # extern
import types # extern
import strop as string # builtin
from utils import typeclasses, err, namespace # XXX
## TODO: namespace must go
class baseProto:
def __vrmlStr__( self, **namedargs ):
'''Generate a VRML 97-syntax string representing this Prototype
**namedargs -- key:value
passed arguments for the linearisation object
see lineariser4.Lineariser
'''
# import lineariser4
lineariser = apply( lineariser4.Lineariser, (), namedargs )
return apply( lineariser.linear, ( self, ), namedargs )
toString = __vrmlStr__
# added stuff for linking support for target scenegraph
def setTargetnode(self, node):
self.__dict__['_targetnode'] = node
def getTargetnode(self):
try:
return self.__dict__['_targetnode']
except:
return None
class Prototype(baseProto):
''' A VRML 97 Prototype object
A Prototype is a callable object which produces Node instances
the Node uses a pointer to its Prototype to provide much of the
Node's standard functionality.
Prototype's are often stored in a sceneGraph's protoTypes namespace,
where you can access them as sceneGraph.protoTypes.nodeGI . They are
also commonly found in Nodes' PROTO attributes.
Attributes:
__gi__ -- constant string "PROTO"
nodeGI -- string gi
The "generic identifier" of the node type, i.e. the name of the node
fieldDictionary -- string name: (string name, string dataType, boolean exposed)
defaultDictionary -- string name: object defaultValue
Will be blank for EXTERNPROTO's and Script prototypes
eventDictionary -- string name: (string name, string dataType, boolean eventOut)
sceneGraph -- object sceneGraph
MFNodeNames -- list of field name strings
Allows for easy calculation of "children" nodes
SFNodeNames -- list of field name strings
Allows for easy calculation of "children" nodes
'''
__gi__ = "PROTO"
def __init__(self, gi, fieldDict=None, defaultDict=None, eventDict=None, sGraph=None):
'''
gi -- string gi
see attribute nodeGI
fieldDict -- string name: (string name, string dataType, boolean exposed)
see attribute fieldDictionary
defaultDict -- string name: object defaultValue
see attribute defaultDictionary
eventDict -- string name: (string name, string dataType, boolean eventOut)
see attribute eventDictionary
sceneGraph -- object sceneGraph
see attribute sceneGraph
'''
self.nodeGI = checkName( gi )
self.fieldDictionary = {}
self.defaultDictionary = {}
self.eventDictionary = {}
self.SFNodeNames = []
self.MFNodeNames = []
self.sceneGraph = sGraph
# setup the fields/events
for definition in (fieldDict or {}).values():
self.addField( definition, (defaultDict or {}).get( definition[0]))
for definition in (eventDict or {}).values():
self.addEvent( definition )
def getSceneGraph( self ):
''' Retrieve the sceneGraph object (may be None object)
see attribute sceneGraph'''
return self.sceneGraph
def setSceneGraph( self, sceneGraph ):
''' Set the sceneGraph object (may be None object)
see attribute sceneGraph'''
self.sceneGraph = sceneGraph
def getChildren(self, includeSceneGraph=None, includeDefaults=1, *args, **namedargs):
''' Calculate the current children of the PROTO and return as a list of nodes
if includeDefaults:
include those default values which are node values
if includeSceneGraph:
include the sceneGraph object if it is not None
see attribute MFNodeNames
see attribute SFNodeNames
see attribute sceneGraph
'''
temp = []
if includeDefaults:
for attrname in self.SFNodeNames:
try:
temp.append( self.defaultDictionary[attrname] )
except KeyError: # sceneGraph object is not copied...
pass
for attrname in self.MFNodeNames:
try:
temp[len(temp):] = self.defaultDictionary[attrname]
except KeyError:
pass
if includeSceneGraph and self.sceneGraph:
temp.append( self.getSceneGraph() )
return temp
def addField (self, definition, default = None):
''' Add a single field definition to the Prototype
definition -- (string name, string dataType, boolean exposed)
default -- object defaultValue
see attribute fieldDictionary
see attribute defaultDictionary
'''
if type (definition) == types.InstanceType:
definition = definition.getDefinition()
default = definition.getDefault ()
self.removeField( definition[0] )
self.fieldDictionary[definition [0]] = definition
if default is not None:
default = fieldcoercian.FieldCoercian()( default, definition[1] )
self.defaultDictionary [definition [0]] = default
if definition[1] == 'SFNode':
self.SFNodeNames.append(definition[0])
elif definition[1] == 'MFNode':
self.MFNodeNames.append(definition[0])
def removeField (self, key):
''' Remove a single field from the Prototype
key -- string fieldName
The name of the field to remove
'''
if self.fieldDictionary.has_key (key):
del self.fieldDictionary [key]
if self.defaultDictionary.has_key (key):
del self.defaultDictionary [key]
for attribute in (self.SFNodeNames, self.MFNodeNames):
while key in attribute:
attribute.remove(key)
def addEvent(self, definition):
''' Add a single event definition to the Prototype
definition -- (string name, string dataType, boolean eventOut)
see attribute eventDictionary
'''
if type (definition) == types.InstanceType:
definition = definition.getDefinition()
self.eventDictionary[definition [0]] = definition
def removeEvent(self, key):
''' Remove a single event from the Prototype
key -- string eventName
The name of the event to remove
'''
if self.eventDictionary.has_key (key):
del self.eventDictionary [key]
def getField( self, key ):
'''Return a Field or Event object representing a given name
key -- string name
The name of the field or event to retrieve
will attempt to match key, key[4:], and key [:-8]
corresponding to key, set_key and key_changed
see class Field
see class Event
'''
# print self.fieldDictionary, self.eventDictionary
for tempkey in (key, key[4:], key[:-8]):
if self.fieldDictionary.has_key( tempkey ):
return Field( self.fieldDictionary[tempkey], self.defaultDictionary.get(tempkey) )
elif self.eventDictionary.has_key( tempkey ):
return Event( self.eventDictionary[tempkey] )
raise AttributeError, key
def getDefault( self, key ):
'''Return the default value for the given field
key -- string name
The name of the field
Will attempt to match key, key[4:], and key [:-8]
corresponding to key, set_key and key_changed
see attribute defaultDictionary
'''
for key in (key, key[4:], key[:-8]):
if self.defaultDictionary.has_key( key ):
val = self.defaultDictionary[key]
if type(val) in typeclasses.MutableTypes:
val = copy.deepcopy( val )
return val
elif self.fieldDictionary.has_key( key ):
'''We have the field, but we don't have a default, we are likely an EXTERNPROTO'''
return None
raise AttributeError, key
def setDefault (self, key, value):
'''Set the default value for the given field
key -- string name
The name of the field to set
value -- object defaultValue
The default value, will be checked for type and coerced if necessary
'''
field = self.getField (key)
self.defaultDictionary [field.name]= field.coerce (value)
def clone( self, children = 1, sceneGraph = 1 ):
'''Return a copy of this Prototype
children -- boolean
if true, copy the children of the Prototype, otherwise include them
sceneGraph -- boolean
if true, copy the sceneGraph of the Prototype
'''
if sceneGraph:
sceneGraph = self.sceneGraph
else:
sceneGraph = None
# defaults should always be copied before modification, but this is still dangerous...
defaultDictionary = self.defaultDictionary.copy()
if not children:
for attrname in self.SFNodeNames+self.MFNodeNames:
try:
del defaultDictionary[attrname]
except KeyError: # sceneGraph object is not copied...
pass
# now make a copy
if self.__gi__ == "PROTO":
newNode = self.__class__(
self.nodeGI,
self.fieldDictionary,
defaultDictionary,
self.eventDictionary,
sceneGraph,
)
else:
newNode = self.__class__(
self.nodeGI,
self.url,
self.fieldDictionary,
self.eventDictionary,
)
return newNode
def __call__(self, *args, **namedargs):
'''Create a new Node instance associated with this Prototype
*args, **namedargs -- passed to the Node.__init__
see class Node
'''
node = apply( Node, (self, )+args, namedargs )
return node
def __repr__ ( self ):
'''Create a simple Python representation'''
return '''%s( %s )'''%( self.__class__.__name__, self.nodeGI )
class ExternalPrototype( Prototype ):
'''Sub-class of Prototype
The ExternalPrototype is a minor sub-classing of the Prototype
it does not have any defaults, nor a sceneGraph
Attributes:
__gi__ -- constant string "EXTERNPROTO"
url -- string list urls
implementation source for the ExternalPrototype
'''
__gi__ = "EXTERNPROTO"
def __init__(self, gi, url=None, fieldDict=None, eventDict=None):
'''
gi -- string gi
see attribute nodeGI
url -- string list url
MFString-compatible list of url's for EXTERNPROTO
fieldDict -- string name: (string name, string dataType, boolean exposed)
see attribute fieldDictionary
eventDict -- string name: (string name, string dataType, boolean eventOut)
see attribute eventDictionary
'''
if url is None:
url = []
self.url = url
Prototype.__init__( self, gi, fieldDict=fieldDict, eventDict=eventDict)
from vrml import fieldcoercian # XXX
class Field:
''' Representation of a Prototype Field
The Field object is a simple wrapper to provide convenient
access to field coercian and meta- information
'''
def __init__( self, specification, default=None ):
self.name, self.type, self.exposure = specification
self.default = default
def getDefinition (self):
return self.name, self.type, self.exposure
def getDefault (self):
return self.default
def coerce( self, value ):
''' Coerce value to the appropriate dataType for this Field '''
return fieldcoercian.FieldCoercian()( value,self.type, )
def __repr__( self ):
if hasattr (self, "default"):
return '%s( (%s,%s,%s), %s)'%( self.__class__.__name__, self.name, self.type, self.exposure, self.default)
else:
return '%s( (%s,%s,%s),)'%( self.__class__.__name__, self.name, self.type, self.exposure)
def __str__( self ):
if self.exposure:
exposed = "exposedField"
else:
exposed = field
if hasattr (self, "default"):
default = ' ' + str( self.default)
else:
default = ""
return '%s %s %s%s'%(exposed, self.type, self.name, default)
class Event (Field):
def __str__( self ):
if self.exposure:
exposed = "eventOut"
else:
exposed = "eventIn"
return '%s %s %s'%(exposed, self.type, self.name)
### Translation strings for VRML node names...
translationstring = '''][0123456789{}"'#,.\\ \000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023'''
NAMEFIRSTCHARTRANSLATOR = string.maketrans( translationstring, '_'*len(translationstring) )
translationstring = '''][{}"'#,.\\ \000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023'''
NAMERESTCHARTRANSLATOR = string.maketrans( translationstring, '_'*len(translationstring) )
del translationstring
def checkName( name ):
'''Convert arbitrary string to a valid VRML id'''
if type(name) is types.StringType:
if not name:
return name
return string.translate( name[:1], NAMEFIRSTCHARTRANSLATOR) + string.translate( name[1:], NAMERESTCHARTRANSLATOR)
else:
raise TypeError, "VRML Node Name must be a string, was a %s: %s"%(type(name), name)
class Node(baseProto):
''' A VRML 97 Node object
A Node object represents a VRML 97 node. Attributes of the Node
can be set/retrieved with standard python setattr/getattr syntax.
VRML 97 attributes may be passed to the constructor as named
arguments.
Attributes:
__gi__ -- string PROTOname
DEF -- string DEFName
The DEF name of the node, will be coerced to be a valid
identifier (with "" being considered valid)
PROTO -- Prototype PROTO
The node's Prototype object
attributeDictionary -- string name: object value
Dictionary in which VRML 97 attributes are stored
'''
DEF = '' # the default name for all nodes (arbitrary)
def __init__(self, PROTO, name='', attrDict=None, *args, **namedargs):
'''Normally this method is only called indirectly via the Prototype() interface
PROTO -- Prototype PROTO
see attribute PROTO
name -- string DEFName
see attribute DEF
attrDict -- string name: object value
see attribute attributeDictionary
**namedargs -- string name: object value
added to attrDict to create attributeDictionary
'''
self.__dict__["PROTO"] = PROTO
self.DEF = name
self.__dict__["attributeDictionary"] = {}
## print attrDict, namedargs
for dict in (attrDict or {}), namedargs:
if dict:
for key, value in dict.items ():
self.__setattr__( key, value, check=1 )
def __setattr__( self, key, value, check=1, raw=0 ):
'''Set attribute on Node
key -- string attributeName
value -- object attributeValue
check -- boolean check
if false, put values for unrecognized keys into __dict__
otherwise, raise an AttributeError
'''
if key == "DEF":
self.__dict__["DEF"] = checkName( value )
return None
elif key == "PROTO":
self.__dict__["PROTO"] = value
try:
field = self.PROTO.getField( key )
if (hasattr( value, "__gi__") and value.__gi__ == "IS") or raw:
self.attributeDictionary[ field.name] = value
else:
self.attributeDictionary[ field.name] = field.coerce( value )
except ValueError, x:
raise ValueError( "Could not coerce value %s into value of VRML type %s for %s node %s's field %s"%( value, field.type, self.__gi__, self.DEF, key), x.args)
except (AttributeError), x:
if check:
raise AttributeError("%s is not a known field for node %s"%(key, repr(self)))
else:
self.__dict__[key] = value
def __getattr__( self, key, default = 1 ):
''' Retrieve an attribute when standard lookup fails
key -- string attributeName
default -- boolean default
if true, return the default value if the node does not have local value
otherwise, raise AttributeError
'''
if key != "attributeDictionary":
if self.__dict__.has_key( key):
return self.__dict__[ key ]
elif self.attributeDictionary.has_key( key):
return self.attributeDictionary[key]
if key != "PROTO":
if key == "__gi__":
return self.PROTO.nodeGI
elif default:
try:
default = self.PROTO.getDefault( key )
if type( default ) in typeclasses.MutableTypes:
# we need a copy, not the original
default = copy.deepcopy( default )
self.__setattr__( key, default, check=0, raw=1 )
return default
except AttributeError:
pass
raise AttributeError, key
def __delattr__( self, key ):
''' Delete an attribute from the Node
key -- string attributeName
'''
if key != "attributeDictionary":
if self.attributeDictionary.has_key( key):
del self.attributeDictionary[key]
elif self.__dict__.has_key( key):
del self.__dict__[ key ]
raise AttributeError, key
def __repr__(self):
''' Create simple python representation '''
return '<%s(%s): %s>'%(self.__gi__, `self.DEF`, self.attributeDictionary.keys() )
def getChildrenNames( self, current = 1, *args, **namedargs ):
''' Get the (current) children of Node
returns two lists: MFNode children, SFNode children
current -- boolean currentOnly
if true, only return current children
otherwise, include all potential children
'''
MFNODES, SFNODES = self.PROTO.MFNodeNames, self.PROTO.SFNodeNames
mns, sns = [],[]
for key in MFNODES:
if current and self.attributeDictionary.has_key(key):
mns.append(key)
elif not current:
mns.append(key)
for key in SFNODES:
if self.attributeDictionary.has_key(key):
sns.append(key)
elif not current:
sns.append(key)
return mns,sns
def calculateChildren(self, *args, **namedargs):
'''Calculate the current children of the Node as list of Nodes
'''
MFNODES, SFNODES = self.getChildrenNames( )
temp = []
for key in MFNODES:
try:
temp.extend( self.__getattr__( key, default=0 ) )
except AttributeError:
pass
for key in SFNODES:
try:
temp.append( self.__getattr__(key, default = 0 ) )
except AttributeError:
pass
return temp
def clone(self, newclass=None, name=None, children=None, attrDeepCopy=1, *args, **namedargs):
'''Return a copy of this Node
newclass -- object newClass or None
optionally use a different Prototype as base
name -- string DEFName or None or 1
if 1, copy from current
elif None, set to ""
else, set to passed value
children -- boolean copyChildren
if true, copy the children of this node
otherwise, skip children
attrDeepCopy -- boolean deepCopy
if true, use deepcopy
otherwise, use copy
'''
if attrDeepCopy:
cpy = copy.deepcopy
else:
cpy = copy.copy
newattrs = self.attributeDictionary.copy()
if not children:
mnames,snames = self.getChildrenNames( )
for key in mnames+snames:
try:
del(newattrs[key])
except KeyError:
pass
for key, val in newattrs.items():
if type(val) in typeclasses.MutableTypes:
newattrs[key] = cpy(val)
# following is Node specific, won't work for sceneGraphs, scripts, etceteras
if name == 1: # asked to copy the name
name = self.DEF
elif name is None: # asked to clear the name
name = ''
if not newclass:
newclass = self.PROTO
return newclass( name, newattrs )
def __cmp__( self, other, stop=None ):
''' Compare this node to another object/node
other -- object otherNode
stop -- boolean stopIfFailure
if true, failure to find comparison causes match failure (i.e. considered unequal)
'''
if hasattr( other, '__gi__') and other.__gi__ == self.__gi__:
try:
return cmp( self.DEF, other.DEF) or cmp( self.attributeDictionary, other.attributeDictionary )
except:
if not stop:
try:
return other.__cmp__( self , 1) # 1 being stop...
except:
pass
return -1 # could be one, doesn't really matter
def Script( name="", attrDict=None, fieldDict=None, defaultDict=None, eventDict=None, **namedarguments):
''' Create a script node (and associated prototype)
name -- string DEFName
attrDict -- string name: object value
see class Node.attributeDictionary
fieldDict -- string name: (string name, string dataType, boolean exposure)
see class Prototype.fieldDictionary
defaultDict -- string name: object value
see class Prototype.defaultDictionary
eventDict -- string name: (string name, string dataType, boolean eventOut)
'''
fieldDictionary = {
'directOutput':('directOutput', 'SFBool',0),
'url':('url',"MFString",0),
'mustEvaluate':('mustEvaluate', 'SFBool',0),
}
fieldDictionary.update( fieldDict or {})
defaultDictionary = {
"directOutput":0,
"url":[],
"mustEvaluate":0,
}
defaultDictionary.update( defaultDict or {})
PROTO = Prototype(
"Script",
fieldDictionary,
defaultDictionary ,
eventDict = eventDict,
)
if attrDict is not None:
attrDict.update( namedarguments )
else:
attrDict = namedarguments
return PROTO( name, attrDict )
class NullNode:
'''NULL SFNode value
There should only be a single NULL instance for
any particular system. It should, for all intents and
purposes just sit there inertly
'''
__gi__ = 'NULL'
DEF = ''
__walker_is_temporary_item__ = 1 # hacky signal to walking engine not to reject this node as already processed
def __repr__(self):
return '<NULL vrml SFNode>'
def __vrmlStr__(self,*args,**namedargs):
return ' NULL '
toString = __vrmlStr__
def __nonzero__(self ):
return 0
def __call__(self, *args, **namedargs):
return self
def __cmp__( self, other ):
if hasattr( other, '__gi__') and other.__gi__ == self.__gi__:
return 0
return -1 # could be one, doesn't really matter
def clone( self ):
return self
NULL = NullNode()
class fieldRef:
'''IS Prototype field reference
'''
__gi__ = 'IS'
DEF = ''
def __init__(self, declaredName):
self.declaredName = declaredName
def __repr__(self):
return 'IS %s'%self.declaredName
def __vrmlStr__(self,*args,**namedargs):
return 'IS %s'%self.declaredName
toString = __vrmlStr__
def __cmp__( self, other ):
if hasattr( other, '__gi__') and other.__gi__ == self.__gi__:
return cmp( self.declaredName, other.declaredName )
return -1 # could be one, doesn't really matter
def clone( self ):
return self.__class__( self.declaredName )
IS = fieldRef
class ROUTE:
''' VRML 97 ROUTE object
The ROUTE object keeps track of its source and destination nodes and attributes
It generally lives in a sceneGraph's "routes" collection
'''
__gi__ = 'ROUTE'
def __init__( self, fromNode, fromField, toNode, toField ):
if type(fromNode) is types.StringType:
raise TypeError( "String value for ROUTE fromNode",fromNode)
if type(toNode) is types.StringType:
raise TypeError( "String value for ROUTE toNode",toNode)
self.fromNode = fromNode
self.fromField = fromField
self.toNode = toNode
self.toField = toField
def __getitem__( self, index ):
return (self.fromNode, self.fromField, self.toNode, self.toField)[index]
def __setitem__( self, index, value ):
attribute = ("fromNode","fromField","toNode", "toField")[index]
setattr( self, attribute, value )
def __repr__( self ):
return 'ROUTE %s.%s TO %s.%s'%( self.fromNode.DEF, self.fromField, self.toNode.DEF, self.toField )
def clone( self ):
return self.__class__(
self.fromNode,
self.fromField,
self.toNode,
self.toField,
)
class sceneGraph(baseProto):
''' A VRML 97 sceneGraph
Attributes:
__gi__ -- constant string "sceneGraph"
DEF -- constant string ""
children -- Node list
List of the root children of the sceneGraph, nodes/scripts only
routes -- ROUTE list
List of the routes within the sceneGraph
defNames -- string DEFName: Node node
Mapping of DEF names to their respective nodes
protoTypes -- Namespace prototypes
Namespace (with chaining lookup) collection of prototypes
getattr( sceneGraph.protoTypes, 'nodeGI' ) retrieves a prototype
'''
__gi__ = 'sceneGraph'
DEF = ''
def __init__(self, root=None, protoTypes=None, routes=None, defNames=None, children=None, *args, **namedargs):
'''
root -- sceneGraph root or Dictionary root or Module root or None
Base object for root of protoType namespace hierarchy
protoTypes -- string nodeGI: Prototype PROTO
Dictionary of prototype definitions
routes -- ROUTE list or (string sourcenode, string sourceeventOut, string destinationnode, string destinationeventOut) list
List of route objects or tuples to be added to the sceneGraph
see attribute routes
defNames -- string DEFName: Node node
see attribute defNames
children -- Node list
see attribute children
'''
if children is None:
self.children = []
else:
self.children = children
if routes is None:
self.routes = [] # how will we efficiently handle routes?
else:
self.routes = routes
if defNames == None:
self.defNames = {} # maps 'defName':Node
else:
self.defNames = defNames
if protoTypes is None:
protoTypes = {}
if root is None:
from vrml import basenodes # XXX
self.protoTypes = namespace.NameSpace(
protoTypes,
children = [namespace.NameSpace(basenodes)]
)
else: # there is a root file, so need to use it as the children instead of basenodes...
if hasattr( root, "protoTypes"):
self.protoTypes = namespace.NameSpace(
protoTypes,
children = [root.protoTypes]
)
else:
self.protoTypes = namespace.NameSpace(
protoTypes,
children = [ namespace.NameSpace(root) ]
)
def __getinitargs__( self ):
# we only copy our explicit protos, our routes, our defNames, and our children
# inherited protos will be pulled along by their nodes...
return None, self.protoTypes._base, self.routes, self.defNames, self.children
def __getstate__( self ):
return {}
def __setstate__( self, dict ):
pass
def __del__( self, id=id ):
'''
Need to clean up the namespace's mutual references,
this can be done without affecting the cascade by just
eliminating the key/value pairs. The namespaces will
no longer contain the prototypes, but they will still
chain up to the higher-level namespaces, and the nodes
will have those prototypes still in use.
'''
## print 'del sceneGraph', id(self )
try:
## import pdb
## pdb.set_trace()
## self.protoTypes.__dict__.clear()
self.protoTypes._base.clear()
del self.protoTypes.__namespace_cascade__[:]
except:
print 'unable to free references'
def addRoute(self, routeTuple, getNewNodes=0):
''' Add a single route to the sceneGraph
routeTuple -- ROUTE route or (string sourcenode, string sourceeventOut, string destinationnode, string destinationeventOut)
getNewNodes -- boolean getNewNodes
if true, look up sourcenode and destinationnode within the current defNames to determine source/destination nodes
otherwise, just use current if available
'''
# create and wire together the Routes here,
# should just be a matter of pulling the events and passing the nodes...
## import pdb
## pdb.set_trace()
if type( routeTuple) in ( types.TupleType, types.ListType):
(fromNode, fromField, toNode, toField ) = routeTuple
if type(fromNode) is types.StringType:
# get the node instead of the string...
if self.defNames.has_key( fromNode ):
fromNode = self.defNames[fromNode]
else:
err.err( "ROUTE from an unknown node %s "%(routeTuple) )
return 0
if type(toNode) is types.StringType:
# get the node instead of the string...
if self.defNames.has_key( toNode ):
toNode = self.defNames[toNode]
else:
err.err( "ROUTE to an unknown node %s "%(routeTuple) )
return 0
routeTuple = ROUTE( fromNode, fromField, toNode, toField)
elif getNewNodes:
# get the nodes with the same names...
if self.defNames.has_key( routeTuple[0].DEF ):
routeTuple[0] = self.defNames[routeTuple[0].DEF]
else:
err.err( "ROUTE from an unknown node %s "%(routeTuple) )
return 0
if self.defNames.has_key( routeTuple[2].DEF ):
routeTuple[2] = self.defNames[routeTuple[2].DEF]
else:
err.err( "ROUTE to an unknown node %s "%(routeTuple) )
return 0
# should be a Route node now, append to our ROUTE list...
self.routes.append(routeTuple)
return 1
def regDefName(self, defName, object):
''' Register a DEF name for a particular object
defName -- string DEFName
object -- Node node
'''
object.DEF = defName
self.defNames[defName] = object
def addProto(self, proto):
'''Register a Prototype for this sceneGraph
proto -- Prototype PROTO
'''
setattr( self.protoTypes, proto.__gi__, proto )
#toString = __vrmlStr__
#__vrmlStr__ = toString
## def __setattr__( self, key, value ):
## if key == 'protoTypes' and type( value) is types.ListType:
## import pdb
## pdb.set_trace()
## raise TypeError( "Invalid type for protoTypes attribute of sceneGraph %s"%(`value`) )
## else:
## self.__dict__[key] = value
DEFAULTFIELDVALUES ={
"SFBool": 0,
"SFString": "",
"SFFloat": 0,
"SFTime": 0,
"SFVec3f": (0, 0,0),
"SFVec2f": (0,0),
"SFRotation": (0, 1,0, 0),
"SFInt32": 0,
"SFImage": (0,0,0),
"SFColor": (0,0, 0),
"SFNode": NULL,
"MFString": [],
"MFFloat": [],
"MFTime": [],
"MFVec3f": [],
"MFVec2f": [],
"MFRotation": [],
"MFInt32": [],
"MFColor": [],
"MFNode": [],
}