diff options
Diffstat (limited to 'intern/python/modules/vrml/scenegraph.py')
-rw-r--r-- | intern/python/modules/vrml/scenegraph.py | 833 |
1 files changed, 833 insertions, 0 deletions
diff --git a/intern/python/modules/vrml/scenegraph.py b/intern/python/modules/vrml/scenegraph.py new file mode 100644 index 00000000000..2f137b1e259 --- /dev/null +++ b/intern/python/modules/vrml/scenegraph.py @@ -0,0 +1,833 @@ +# 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 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": [], +} + + + |