Go to the documentation of this file.
33 namespace H3DInterface {
34 const string H3DInterface_string =
"\
36 # This is required in the case that the interpreter was initialized before the builtin H3D module\n\
37 # was added with PyImport_AppendInittab(), as is the case when the interpreter is initialized by\n\
38 # an external library (e.g. Sofa). Also see PythonScript.cpp.\n\
39 if 'H3D' not in sys.builtin_module_names:\n\
40 sys.builtin_module_names = sys.builtin_module_names + ( 'H3D', )\n\
49 _ConsoleStdout = H3DConsole( LogLevel.Info )\n\
50 _ConsoleStderr = H3DConsole( LogLevel.Error )\n\
51 # Console kept for backwards compatibility reasons \n\
52 Console = _ConsoleStdout\n\
54 sys.stdout = _ConsoleStdout\n\
55 sys.stderr = _ConsoleStderr\n\
57 def log ( level, message ):\n\
58 Console.writeAtLevel ( level, message + \"\\n\" )\n\
60 ###################################################################\n\
62 # Base types; Vec2f, Vec3f, Vec2d, Vec2d, etc, etc, etc\n\
64 ###################################################################\n\
66 ###################################################################\n\
68 # Field base class and SF* MF* class definitions\n\
70 ###################################################################\n\
71 class Field(object):\n\
72 type = UNKNOWN_X3D_TYPE\n\
73 def __init__( self, auto_update = 0 ):\n\
74 super(Field, self).__init__()\n\
75 module = self.__class__.__dict__[\"__module__\"]\n\
76 createField( self, auto_update, module + \".\" + self.__class__.__name__ )\n\
78 def setName( self, name ):\n\
79 return fieldSetName( self, name )\n\
81 def getName( self ):\n\
82 return fieldGetName( self )\n\
84 def getFullName( self ):\n\
85 return fieldGetFullName( self )\n\
87 def getTypeName( self ):\n\
88 return fieldGetTypeName( self )\n\
90 def getOwner( self ):\n\
91 return fieldGetOwner( self )\n\
93 def setOwner( self, n ):\n\
94 return fieldSetOwner( self, n )\n\
96 def route( self, dest ):\n\
97 return fieldRoute( self, dest )\n\
99 def routeNoEvent( self, dest ):\n\
100 return fieldRouteNoEvent( self, dest )\n\
102 def unroute( self, dest ):\n\
103 return fieldUnroute( self, dest )\n\
105 def replaceRoute( self, dest, i ):\n\
106 return fieldReplaceRoute( self, dest, i )\n\
108 def replaceRouteNoEvent( self, dest, i ):\n\
109 return fieldReplaceRouteNoEvent( self, dest, i )\n\
111 def unrouteAll( self ):\n\
112 return fieldUnrouteAll( self )\n\
114 def touch( self ):\n\
115 return fieldTouch( self )\n\
117 def routesTo( self, f ):\n\
118 return fieldRoutesTo( self, f )\n\
120 def hasRouteFrom( self, f ):\n\
121 return fieldHasRouteFrom( self, f )\n\
123 def getRoutesIn( self ):\n\
124 return fieldGetRoutesIn( self )\n\
126 def getRoutesOut( self ):\n\
127 return fieldGetRoutesOut( self )\n\
129 def setAccessType( self, access_type ):\n\
130 return fieldSetAccessType( self, access_type )\n\
132 def getAccessType( self ):\n\
133 return fieldGetAccessType( self )\n\
135 def setAccessCheck( self, access_check ):\n\
136 return fieldSetAccessCheck( self, access_check )\n\
138 def isAccessCheckOn( self ):\n\
139 return fieldIsAccessCheckOn( self )\n\
141 def setValueFromString( self, value ):\n\
142 return fieldSetValueFromString( self, value )\n\
144 def getValueAsString( self ):\n\
145 return fieldGetValueAsString( self )\n\
147 def upToDate( self ):\n\
148 return fieldUpToDate( self )\n\
150 def isUpToDate( self ):\n\
151 return fieldIsUpToDate( self )\n\
153 def __cmp__( self, o ):\n\
154 return getCPtr(self) - getCPtr(o)\n\
156 def __eq__( self, o ):\n\
157 return not self.__cmp__( o )\n\
159 def __ne__( self, o ):\n\
160 return not self.__eq__( o )\n\
162 def __lt__( self, o ):\n\
163 return NotImplemented\n\
165 def __le__( self, o ):\n\
166 return NotImplemented\n\
168 def __gt__( self, o ):\n\
169 return NotImplemented\n\
171 def __ge__( self, o ):\n\
172 return NotImplemented\n\
174 class SField( Field ):\n\
175 type = UNKNOWN_X3D_TYPE\n\
176 def setValue( self, value ):\n\
177 fieldSetValue( self, value )\n\
179 def getValue( self ):\n\
180 return fieldGetValue( self )\n\
182 class MField( Field ):\n\
183 type = UNKNOWN_X3D_TYPE\n\
184 def setValue( self, value ):\n\
185 fieldSetValue( self, value )\n\
187 def getValue( self ):\n\
188 return fieldGetValue( self )\n\
190 def push_back( self, v ):\n\
191 MFieldPushBack( self, v ) \n\
193 def pop_back( self ):\n\
194 MFieldPopBack( self )\n\
196 def empty( self ):\n\
197 return MFieldEmpty( self )\n\
199 def front( self ):\n\
200 return MFieldFront( self )\n\
203 return MFieldBack( self )\n\
205 def clear( self ):\n\
206 MFieldClear( self )\n\
208 def erase( self, v ):\n\
209 MFieldErase( self, v ) \n\
212 return MFieldSize( self )\n\
215 # Install all built-in Field types:\n\
217 ( SFFLOAT, \"SFFloat\" ),\n\
218 ( SFDOUBLE, \"SFDouble\" ),\n\
219 ( SFTIME, \"SFTime\" ),\n\
220 ( SFINT32, \"SFInt32\" ),\n\
221 ( SFVEC2F, \"SFVec2f\" ),\n\
222 ( SFVEC2D, \"SFVec2d\" ),\n\
223 ( SFVEC3F, \"SFVec3f\" ),\n\
224 ( SFVEC3D, \"SFVec3d\" ),\n\
225 ( SFVEC4F, \"SFVec4f\" ),\n\
226 ( SFVEC4D, \"SFVec4d\" ),\n\
227 ( SFBOOL, \"SFBool\" ),\n\
228 # ( SFSTRING, \"SFString\" ),\n\
229 ( SFCOLOR, \"SFColor\" ),\n\
230 ( SFCOLORRGBA,\"SFColorRGBA\" ),\n\
231 ( SFROTATION, \"SFRotation\" ),\n\
232 ( SFQUATERNION, \"SFQuaternion\" ),\n\
233 ( SFMATRIX3F, \"SFMatrix3f\" ),\n\
234 ( SFMATRIX4F, \"SFMatrix4f\" ),\n\
235 ( SFMATRIX3D, \"SFMatrix3d\" ),\n\
236 ( SFMATRIX4D, \"SFMatrix4d\" ),\n\
237 ( SFNODE , \"SFNode\" ) ]\n\
240 ( MFFLOAT, \"MFFloat\" ),\n\
241 ( MFDOUBLE, \"MFDouble\" ),\n\
242 ( MFTIME, \"MFTime\" ),\n\
243 ( MFINT32, \"MFInt32\" ),\n\
244 ( MFVEC2F, \"MFVec2f\" ),\n\
245 ( MFVEC2D, \"MFVec2d\" ),\n\
246 ( MFVEC3F, \"MFVec3f\" ),\n\
247 ( MFVEC3D, \"MFVec3d\" ),\n\
248 ( MFVEC4F, \"MFVec4f\" ),\n\
249 ( MFVEC4D, \"MFVec4d\" ),\n\
250 ( MFBOOL, \"MFBool\" ),\n\
251 ( MFSTRING, \"MFString\" ),\n\
252 ( MFCOLOR, \"MFColor\" ),\n\
253 ( MFCOLORRGBA,\"MFColorRGBA\" ),\n\
254 ( MFROTATION, \"MFRotation\" ),\n\
255 ( MFQUATERNION, \"MFQuaternion\" ),\n\
256 ( MFMATRIX3F, \"MFMatrix3f\" ),\n\
257 ( MFMATRIX4F, \"MFMatrix4f\" ),\n\
258 ( MFMATRIX3D, \"MFMatrix3d\" ),\n\
259 ( MFMATRIX4D, \"MFMatrix4d\" ),\n\
260 ( MFNODE , \"MFNode\" )\n\
263 for t in sfield_types:\n\
265 class %s( SField ):\n\
267 \"\"\" % (t[1], t[0] ))\n\
269 for t in mfield_types:\n\
271 class %s( MField ):\n\
273 \"\"\" % (t[1], t[0] ))\n\
276 class SFString( SField ):\n\
279 def getValidValues( self ):\n\
280 return SFStringGetValidValues( self )\n\
282 def isValidValue( self, value ):\n\
283 return SFStringIsValidValue( self, value )\n\
285 typed_field_classes = {}\n\
287 def TypedField( base_class, type_info = None, opt_type_info = None ):\n\
288 global typed_field_classes\n\
289 if( (base_class, type_info, opt_type_info) in typed_field_classes ):\n\
290 return typed_field_classes[(base_class, type_info, opt_type_info)]\n\
292 class TypedBase( base_class ):\n\
294 if type_info == None:\n\
295 TypedBase.__type_info__ = ()\n\
296 elif type( type_info ) != type(()):\n\
297 TypedBase.__type_info__ = ( type_info, )\n\
299 TypedBase.__type_info__ = type_info\n\
301 if opt_type_info == None:\n\
302 TypedBase.__opt_type_info__ = ()\n\
303 elif type( opt_type_info ) != type(()):\n\
304 TypedBase.__opt_type_info__ = ( opt_type_info, )\n\
306 TypedBase.__opt_type_info__ = opt_type_info\n\
308 typed_field_classes[(base_class, type_info, opt_type_info)] = TypedBase\n\
312 auto_update_classes = {}\n\
315 # AutoUpdate \"template\" as in C++\n\
316 def AutoUpdate( base_class ):\n\
318 global auto_update_classes\n\
319 if( base_class in auto_update_classes ):\n\
320 return auto_update_classes[base_class]\n\
322 class AutoUpdateBase( base_class ):\n\
323 def __init__( self ):\n\
324 super(AutoUpdateBase, self).__init__(1)\n\
325 auto_update_classes[base_class] = AutoUpdateBase\n\
326 return AutoUpdateBase\n\
328 periodic_update_classes = {}\n\
330 def PeriodicUpdate( base_class ):\n\
331 global periodic_update_classes\n\
332 if( base_class in periodic_update_classes ):\n\
333 return periodic_update_classes[base_class]\n\
335 class PeriodicUpdateBase( base_class ):\n\
336 def __init__( self ):\n\
337 super(PeriodicUpdateBase, self).__init__(0)\n\
338 self.route( eventSink )\n\
339 periodic_update_classes[base_class] = PeriodicUpdateBase\n\
340 return PeriodicUpdateBase\n\
342 const string H3DUtils_string =
"\
343 from H3DInterface import *\n\
345 def PrintFieldValue( base_class ):\n\
346 class PrintValueClass( AutoUpdate( base_class ) ):\n\
347 def update( self, event ):\n\
348 v = event.getValue()\n\
351 return PrintValueClass()\n\
353 def FieldValue2String( base_class ):\n\
354 class Value2StringClass( TypedField( SFString, base_class ) ):\n\
355 def update( self, event ):\n\
356 v = event.getValue()\n\
358 return Value2StringClass()\n\
360 def FieldValue2StringList( base_class ):\n\
361 class Value2StringListClass( TypedField( MFString, base_class ) ):\n\
362 def update( self, event ):\n\
363 v = event.getValue()\n\
365 return Value2StringListClass()\n\
367 def FieldValue2Int( base_class ):\n\
368 class Value2IntClass( TypedField( SFInt32, base_class ) ):\n\
369 def update( self, event ):\n\
370 v = event.getValue()\n\
372 return Value2IntClass()\n\
374 def SField2MField( sfield, mfield ):\n\
375 valid_sfield = False\n\
376 for t in sfield_types:\n\
377 if sfield.type == t[0]:\n\
378 valid_sfield = True\n\
380 if not valid_sfield:\n\
381 raise Exception( \"Warning: Could not create SField2MField. Invalid sfield type \" + sfield.__name__ + \" used.\" )\n\
382 valid_mfield = False\n\
383 for t in mfield_types:\n\
384 if mfield.type == t[0]:\n\
385 valid_mfield = True\n\
387 if not valid_mfield:\n\
388 raise Exception( \"Warning: Could not create SField2MField. Invalid mfield type \" + mfield.__name__ + \" used.\" )\n\
389 class SField2MFieldClass( TypedField( mfield, sfield ) ):\n\
390 def update( self, event ):\n\
391 v = event.getValue()\n\
393 return SField2MFieldClass()\n\
395 ## The TimerCallback field is a field in which you can set callback functions\n\
396 ## to be called at a later time that you specify.\n\
397 ## <b>Example usage:</b>\n\
403 ## tc = TimerCallback()\n\
404 ## tc.addCallback( time.getValue()+3, test, (\"Hello world!\",) )\n\
406 ## This will call the function test 3 seconds from it is run. \n\
407 class TimerCallback( AutoUpdate( SFTime ) ):\n\
409 def __init__( self ):\n\
410 AutoUpdate( SFTime ).__init__( self )\n\
411 ## The list of callbacks currently in use.\n\
412 self.callbacks = []\n\
414 # Set up a route from H3DInterface.time in order for the update\n\
415 # function to run once per scene graph loop.\n\
416 time.route( self )\n\
418 ## Specialized update function to call callback functions when the time\n\
420 def update( self, event ):\n\
421 t = event.getValue()\n\
422 cbs_to_remove = []\n\
423 for cb in self.callbacks:\n\
426 cbs_to_remove.append( cb )\n\
427 for cb in cbs_to_remove:\n\
428 self.callbacks.remove( cb )\n\
430 return event.getValue()\n\
432 ## Add a callback function. The function will be called at the specified\n\
433 ## time with the given arguments and then removed.\n\
434 ## @param time The time to run the function.\n\
435 ## @param func The function to call.\n\
436 ## @param args Tuple with the arguments to call.\n\
437 ## @return Handle to callback function.\n\
438 def addCallback( self, time, func, args ):\n\
439 cb = (time, func, args )\n\
440 self.callbacks.append( cb )\n\
443 ## Remove a callback function before it has executed.\n\
444 ## @param cb The handle of the callback to remove.\n\
445 def removeCallback( self, cb ):\n\
447 self.callbacks.remove( cb )\n\
453 from types import FrameType\n\
454 import H3DInterface\n\
456 from types import ModuleType\n\
458 def printPythonPath(path, prefix = \"\", outstream = sys.stdout ):\n\
459 def _printPythonPathStep ( step, next, prefix ):\n\
461 # outstream.write( repr(step) )\n\
462 outstream.write(\"%s%s -- \" % (prefix, str(type(step))))\n\
463 if isinstance(step, dict):\n\
465 for key, val in step.items():\n\
467 outstream.write(\"[%s]\" % repr(key))\n\
471 outstream.write(\"[key] = %s\" % repr(val))\n\
475 print( \"Not found: \", repr(next) )\n\
476 print( gc.get_referents(step))\n\
477 elif isinstance(step, list):\n\
478 outstream.write(\"[%d]\" % step.index(next))\n\
479 elif isinstance(step, tuple):\n\
480 outstream.write(\"[%d]\" % list(step).index(next))\n\
482 outstream.write(repr(step)) \n\
484 for i, step in enumerate(path):\n\
485 # next \"wraps around\"\n\
486 next = path[(i + 1) % len(path)]\n\
487 _printPythonPathStep( step, next, prefix )\n\
488 if( i < len(path) - 1 ):\n\
489 outstream.write(\" ->\\n\") \n\
491 def printNodePath(path, prefix = \"\", outstream = sys.stdout):\n\
493 def _printNodePathStep ( step, next, prefix ):\n\
495 # outstream.write( repr(step) )\n\
497 if( isinstance( step, tuple ) ):\n\
500 outstream.write(\"%s%s -- \" % (prefix, n.getTypeName()) )\n\
501 outstream.write(repr(n)) \n\
503 if( isinstance( next, tuple ) ):\n\
504 if isinstance( next[1], list ):\n\
505 outstream.write( \"\\n\" ) \n\
506 printPythonPath( next[1], prefix + \" \", outstream )\n\
508 outstream.write( repr(next[1]) )\n\
511 for i, step in enumerate(path):\n\
512 # next \"wraps around\"\n\
513 if( i < len( path ) - 1 ):\n\
514 next = path[(i + 1) % len(path)]\n\
517 _printNodePathStep( step, next, prefix )\n\
519 outstream.write(\" ->\\n\")\n\
520 outstream.write(\"\\n\\n\")\n\
522 def _getPythonScriptNodeReferents( pythonscript_node ):\n\
523 \"\"\" Get all nodes that are held by references by variables in the python code in a PythonScript node. \n\
524 @return [ list[ tuple( Node, list ) ] A list of tuples for each node where the first element is the node itself and the second\n\
525 element a representation of the path within the python script code to the variable that holds the reference\n\
528 module_name = pythonscript_node.moduleName.getValue()\n\
529 module = sys.modules[ module_name ]\n\
530 nodes = _getPythonObjectNodeReferents( module, {}, [module] ) \n\
534 def _getNodeReferents( node ):\n\
535 \"\"\" Get all nodes that are directly referenced in the given node, i.e. nodes that are contained in a\n\
536 field of the node or in the case of a PythonScript nodes that are held by references by variables\n\
537 in the PythonScript.\n\
538 @return [ list[ tuple( Node, str|list ) ] A list of tuples for each node where the first element is the node itself and the second\n\
539 element is the name of the field (string) it resides in. If the node is a PythonScript the second element\n\
540 will be a representation of the path within the python script code to the variable that holds the reference\n\
541 to the node (see _getPythonReferents for details)\n\
543 fields = node.getFieldList()\n\
545 for field_name in fields:\n\
546 field = node.getField( field_name )\n\
547 if field.type == H3DInterface.MFNODE:\n\
548 ns = field.getValue()\n\
549 referents.extend( [ (n, field_name) for n in ns ] )\n\
550 elif field.type == H3DInterface.SFNODE:\n\
551 n = field.getValue()\n\
553 referents.append( (n, field_name ) )\n\
554 if( node.getTypeName() == \"PythonScript\" ):\n\
555 referents.extend(_getPythonScriptNodeReferents( node ) )\n\
558 def _getPythonObjectNodeReferents( obj, visited = {}, current_path = [] ):\n\
559 \"\"\" Get all nodes that are held in variables directly or indirectly referenced by a python object. . \n\
560 @param obj [any] The object to check for nodes in\n\
561 @param visited [dict[id]] A dict of python objects already visited. Only used for internal purposes, should not be set by user.\n\
562 @param current_path list[python objects] A list of python objects representing the hierarchical references in how to get\n\
563 to the current object. Only used for internal purposes, should not be set by user.\n\
564 @return [ list[ tuple( Node, list[ python_objects ] ) A list of tuples for each node fount where the first element is the \n\
565 node itself and the second element is a representation of the path within the python script code to the variable that holds\n\
566 the reference to the node is found. It is defined as list of python objects where the first element is the topmost object\n\
567 that the last element is the object that actually holds the reference to the node.\n\
569 refs = gc.get_referents( obj )\n\
571 # ignore the __scriptnode__ member of PythonScript python modules as that variable does\n\
572 # not increase the reference count of the node\n\
573 if( isinstance(obj, ModuleType ) ):\n\
574 n = obj.__dict__.get(\"__scriptnode__\", None)\n\
575 if( not id(n) in visited ):\n\
576 visited[id(n)] = None\n\
580 object_id = id( ref )\n\
581 if not object_id in visited:\n\
582 visited[ object_id ] = None \n\
583 if( isinstance( ref, H3DInterface.Node ) ):\n\
584 nodes.append( (ref, current_path + [ref] ) )\n\
585 elif( hasattr( ref, \"__fieldptr__\" ) ):\n\
586 if( ref.type == H3DInterface.SFNode ):\n\
587 n = ref.getValue()\n\
588 nodes.append( (n, current_path+[ref]) )\n\
589 elif( ref.type == H3DInterface.MFNode ):\n\
590 ns = ref.getValue()\n\
591 nodes.extend( (n, current_path+[ref]) for n in ns ) \n\
594 # ignoring modules to keep things within the current python script code\n\
595 if( not isinstance( ref, ModuleType ) ):\n\
596 nodes.extend( _getPythonObjectNodeReferents( ref, visited, current_path + [ref] ) )\n\
600 def _getNodeRefsFromNode(node, start, all, current_path, output):\n\
601 \"\"\" Recursive function to step through all child node references to node.\n\
602 @param node [ Node instance ] The node which children to step through.\n\
603 @param start [ Node instance ] The node that we are looking for.\n\
604 @param all [ dict[str] ]A dict object with the name of all nodes encountered so far while recursing\n\
605 @param current_path [ list[ tuple( Node, str|list ) ] ] A representation of the hieararchy of where to find the node parameter. \n\
606 @param output list[ list[ tuple( Node, str|list[ python objects ] List to add references to as they are found\n\
607 It is a list of tuple objects with the first parameter being a node and the second the field name of the parent where this node \n\
608 resided. If the node is a PythonScript node the second parameter is a description of the path in python to the node, see\n\
609 _getReferents for details.\n\
615 # Add the current node to the dict of all visited nodes\n\
616 # todo: if slow, find a better key to use than this\n\
617 all[repr(node)] = None\n\
619 # get all children of the node\n\
620 referents = _getNodeReferents(node)\n\
621 for referent, origin in referents:\n\
625 # The node is what we want, collect it\n\
626 if referent == start:\n\
627 output.append( current_path + [(referent, origin)] ) \n\
629 # We haven't seen this object before, so recurse\n\
630 if repr(referent) not in all :\n\
631 _getNodeRefsFromNode(referent, start, all, current_path + [(referent, origin)], output)\n\
633 def getNodeRefsFromScene(node):\n\
634 \"\"\"Get all references to a node in the current scene.\n\
635 @param node [Node] Node instance to get all references of.\n\
636 @return [list[ list[ tuple( Node, str|list[ python objects ] ) ] ] Returns a list with one entry for each reference with the \"path\" to that \n\
637 reference. Each path is represented by a list of tuples where the first element is the topmost object\n\
638 that the last element is the object that actually holds the reference to the node. The each tuple contains a node and the name of the \n\
639 field in the parent node (or in case of a reference held in python code a list of python objects describing the path within the\n\
643 s = H3DInterface.getCurrentScenes()[0]\n\
644 root = s.sceneRoot.getValue()\n\
646 _getNodeRefsFromNode( s, node, { }, [ (s, \"\")], output )\n\
649 def getNodeRefsFromPythonModules( node ):\n\
650 \"\"\"Get all references to a node that can be reached from any python modules in sys.modules.\n\
651 @param node [Node] Node instance to get all references of.\n\
652 @return [list[ list[ tuple( Node, str|list[ python objects ] ) ] ] Returns a list with one entry for each reference with the \"path\" to that \n\
653 reference. Each path is represented by a list of tuples where the first element is the topmost object\n\
654 that the last element is the object that actually holds the reference to the node. The each tuple contains a node and the name of the \n\
655 field in the parent node (or in case of a reference held in python code a list of python objects describing the path within the\n\
659 node_referents = []\n\
661 # add all nodes that are held by any python object that can be reached from sys.modules to node_referents\n\
662 for module_name, module in sys.modules.items():\n\
663 node_referents.extend( _getPythonObjectNodeReferents( module, visited, [module] ) )\n\
667 # for each node in python objects, find the ones that have the node of interest in its children and add them to output.\n\
668 for n, path in node_referents:\n\
670 # the python object itself is holding the node of interest, so just add it to output\n\
671 output.append( [ (n, path) ] )\n\
673 _getNodeRefsFromNode( n, node, {}, [ (n, path) ], output )\n\
H3D API namespace.
Definition: Anchor.h:38