H3D API  2.4.1
H3DInterface.py.h
Go to the documentation of this file.
1 
3 // Copyright 2004-2019, SenseGraphics AB
4 //
5 // This file is part of H3D API.
6 //
7 // H3D API is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version.
11 //
12 // H3D API is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with H3D API; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 //
21 // A commercial license is also available. Please contact us at
22 // www.sensegraphics.com for more information.
23 //
24 //
28 //
30 
31 namespace H3D {
32 
33  namespace H3DInterface {
34  const string H3DInterface_string = "\
35 import sys\n\
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\
41 from H3D import *\n\
42 \n\
43 class LogLevel:\n\
44  Debug = 1\n\
45  Info = 3\n\
46  Warning = 4\n\
47  Error = 5\n\
48 \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\
53 \n\
54 sys.stdout = _ConsoleStdout\n\
55 sys.stderr = _ConsoleStderr\n\
56  \n\
57 def log ( level, message ):\n\
58  Console.writeAtLevel ( level, message + \"\\n\" )\n\
59 \n\
60 ###################################################################\n\
61 #\n\
62 # Base types; Vec2f, Vec3f, Vec2d, Vec2d, etc, etc, etc\n\
63 #\n\
64 ###################################################################\n\
65 \n\
66 ###################################################################\n\
67 #\n\
68 # Field base class and SF* MF* class definitions\n\
69 #\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\
77 \n\
78  def setName( self, name ):\n\
79  return fieldSetName( self, name )\n\
80 \n\
81  def getName( self ):\n\
82  return fieldGetName( self )\n\
83  \n\
84  def getFullName( self ):\n\
85  return fieldGetFullName( self )\n\
86  \n\
87  def getTypeName( self ):\n\
88  return fieldGetTypeName( self )\n\
89 \n\
90  def getOwner( self ):\n\
91  return fieldGetOwner( self )\n\
92 \n\
93  def setOwner( self, n ):\n\
94  return fieldSetOwner( self, n )\n\
95 \n\
96  def route( self, dest ):\n\
97  return fieldRoute( self, dest )\n\
98 \n\
99  def routeNoEvent( self, dest ):\n\
100  return fieldRouteNoEvent( self, dest )\n\
101 \n\
102  def unroute( self, dest ):\n\
103  return fieldUnroute( self, dest )\n\
104 \n\
105  def replaceRoute( self, dest, i ):\n\
106  return fieldReplaceRoute( self, dest, i )\n\
107 \n\
108  def replaceRouteNoEvent( self, dest, i ):\n\
109  return fieldReplaceRouteNoEvent( self, dest, i )\n\
110 \n\
111  def unrouteAll( self ):\n\
112  return fieldUnrouteAll( self )\n\
113  \n\
114  def touch( self ):\n\
115  return fieldTouch( self )\n\
116 \n\
117  def routesTo( self, f ):\n\
118  return fieldRoutesTo( self, f )\n\
119 \n\
120  def hasRouteFrom( self, f ):\n\
121  return fieldHasRouteFrom( self, f )\n\
122 \n\
123  def getRoutesIn( self ):\n\
124  return fieldGetRoutesIn( self )\n\
125 \n\
126  def getRoutesOut( self ):\n\
127  return fieldGetRoutesOut( self )\n\
128 \n\
129  def setAccessType( self, access_type ):\n\
130  return fieldSetAccessType( self, access_type )\n\
131 \n\
132  def getAccessType( self ):\n\
133  return fieldGetAccessType( self )\n\
134 \n\
135  def setAccessCheck( self, access_check ):\n\
136  return fieldSetAccessCheck( self, access_check )\n\
137 \n\
138  def isAccessCheckOn( self ):\n\
139  return fieldIsAccessCheckOn( self )\n\
140 \n\
141  def setValueFromString( self, value ):\n\
142  return fieldSetValueFromString( self, value )\n\
143 \n\
144  def getValueAsString( self ):\n\
145  return fieldGetValueAsString( self )\n\
146 \n\
147  def upToDate( self ):\n\
148  return fieldUpToDate( self )\n\
149 \n\
150  def isUpToDate( self ):\n\
151  return fieldIsUpToDate( self )\n\
152  \n\
153  def __cmp__( self, o ):\n\
154  return getCPtr(self) - getCPtr(o)\n\
155 \n\
156  def __eq__( self, o ):\n\
157  return not self.__cmp__( o )\n\
158 \n\
159  def __ne__( self, o ):\n\
160  return not self.__eq__( o )\n\
161  \n\
162  def __lt__( self, o ):\n\
163  return NotImplemented\n\
164  \n\
165  def __le__( self, o ):\n\
166  return NotImplemented\n\
167  \n\
168  def __gt__( self, o ):\n\
169  return NotImplemented\n\
170  \n\
171  def __ge__( self, o ):\n\
172  return NotImplemented\n\
173 \n\
174 class SField( Field ):\n\
175  type = UNKNOWN_X3D_TYPE\n\
176  def setValue( self, value ):\n\
177  fieldSetValue( self, value )\n\
178 \n\
179  def getValue( self ):\n\
180  return fieldGetValue( self )\n\
181 \n\
182 class MField( Field ):\n\
183  type = UNKNOWN_X3D_TYPE\n\
184  def setValue( self, value ):\n\
185  fieldSetValue( self, value )\n\
186 \n\
187  def getValue( self ):\n\
188  return fieldGetValue( self )\n\
189 \n\
190  def push_back( self, v ):\n\
191  MFieldPushBack( self, v ) \n\
192 \n\
193  def pop_back( self ):\n\
194  MFieldPopBack( self )\n\
195 \n\
196  def empty( self ):\n\
197  return MFieldEmpty( self )\n\
198 \n\
199  def front( self ):\n\
200  return MFieldFront( self )\n\
201 \n\
202  def back( self ):\n\
203  return MFieldBack( self )\n\
204 \n\
205  def clear( self ):\n\
206  MFieldClear( self )\n\
207 \n\
208  def erase( self, v ):\n\
209  MFieldErase( self, v ) \n\
210  \n\
211  def size( self ):\n\
212  return MFieldSize( self )\n\
213 \n\
214 \n\
215 # Install all built-in Field types:\n\
216 sfield_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\
238 \n\
239 mfield_types = [\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\
261 ]\n\
262 \n\
263 for t in sfield_types:\n\
264  exec(\"\"\"\n\
265 class %s( SField ):\n\
266  type = %s\n\
267 \"\"\" % (t[1], t[0] ))\n\
268 \n\
269 for t in mfield_types:\n\
270  exec(\"\"\"\n\
271 class %s( MField ):\n\
272  type = %s\n\
273 \"\"\" % (t[1], t[0] ))\n\
274 \n\
275 \n\
276 class SFString( SField ):\n\
277  type = SFSTRING\n\
278 \n\
279  def getValidValues( self ):\n\
280  return SFStringGetValidValues( self )\n\
281 \n\
282  def isValidValue( self, value ):\n\
283  return SFStringIsValidValue( self, value )\n\
284 \n\
285 typed_field_classes = {}\n\
286 \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\
291 \n\
292  class TypedBase( base_class ):\n\
293  pass\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\
298  else:\n\
299  TypedBase.__type_info__ = type_info\n\
300 \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\
305  else:\n\
306  TypedBase.__opt_type_info__ = opt_type_info\n\
307 \n\
308  typed_field_classes[(base_class, type_info, opt_type_info)] = TypedBase\n\
309  return TypedBase\n\
310 \n\
311 \n\
312 auto_update_classes = {}\n\
313 \n\
314 \n\
315 # AutoUpdate \"template\" as in C++\n\
316 def AutoUpdate( base_class ):\n\
317 \n\
318  global auto_update_classes\n\
319  if( base_class in auto_update_classes ):\n\
320  return auto_update_classes[base_class]\n\
321  else:\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\
327 \n\
328 periodic_update_classes = {}\n\
329 \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\
334  else:\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\
341 ";
342  const string H3DUtils_string = "\
343 from H3DInterface import *\n\
344 \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\
349  print(v)\n\
350  return v\n\
351  return PrintValueClass()\n\
352 \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\
357  return str( v )\n\
358  return Value2StringClass()\n\
359 \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\
364  return [str( v )]\n\
365  return Value2StringListClass()\n\
366 \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\
371  return int( v )\n\
372  return Value2IntClass()\n\
373 \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\
379  break\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\
386  break\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\
392  return [v]\n\
393  return SField2MFieldClass()\n\
394 \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\
398 ##\n\
399 ## <pre>\n\
400 ## def test( v ):\n\
401 ## print v\n\
402 ##\n\
403 ## tc = TimerCallback()\n\
404 ## tc.addCallback( time.getValue()+3, test, (\"Hello world!\",) )\n\
405 ## </pre>\n\
406 ## This will call the function test 3 seconds from it is run. \n\
407 class TimerCallback( AutoUpdate( SFTime ) ):\n\
408  ## Constructor.\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\
413 \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\
417 \n\
418  ## Specialized update function to call callback functions when the time\n\
419  ## is right.\n\
420  def update( self, event ):\n\
421  t = event.getValue()\n\
422  cbs_to_remove = []\n\
423  for cb in self.callbacks:\n\
424  if t > cb[0]:\n\
425  cb[1](*cb[2])\n\
426  cbs_to_remove.append( cb )\n\
427  for cb in cbs_to_remove:\n\
428  self.callbacks.remove( cb )\n\
429 \n\
430  return event.getValue()\n\
431 \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\
441  return cb\n\
442 \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\
446  try:\n\
447  self.callbacks.remove( cb )\n\
448  except:\n\
449  pass\n\
450 \n\
451 import gc\n\
452 import sys\n\
453 from types import FrameType\n\
454 import H3DInterface\n\
455 \n\
456 from types import ModuleType\n\
457 \n\
458 def printPythonPath(path, prefix = \"\", outstream = sys.stdout ):\n\
459  def _printPythonPathStep ( step, next, prefix ):\n\
460  #if not next:\n\
461  # outstream.write( repr(step) )\n\
462  outstream.write(\"%s%s -- \" % (prefix, str(type(step))))\n\
463  if isinstance(step, dict):\n\
464  found = False\n\
465  for key, val in step.items():\n\
466  if val is next:\n\
467  outstream.write(\"[%s]\" % repr(key))\n\
468  found = True\n\
469  break\n\
470  if key is next:\n\
471  outstream.write(\"[key] = %s\" % repr(val))\n\
472  found = True\n\
473  break\n\
474  if not found:\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\
481  else:\n\
482  outstream.write(repr(step)) \n\
483 \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\
490  \n\
491 def printNodePath(path, prefix = \"\", outstream = sys.stdout):\n\
492 \n\
493  def _printNodePathStep ( step, next, prefix ):\n\
494  #if not next:\n\
495  # outstream.write( repr(step) )\n\
496  n = step\n\
497  if( isinstance( step, tuple ) ):\n\
498  n = step[0]\n\
499  \n\
500  outstream.write(\"%s%s -- \" % (prefix, n.getTypeName()) )\n\
501  outstream.write(repr(n)) \n\
502 \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\
507  else:\n\
508  outstream.write( repr(next[1]) )\n\
509 \n\
510  # function start\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\
515  else:\n\
516  next = None\n\
517  _printNodePathStep( step, next, prefix )\n\
518  if( next ):\n\
519  outstream.write(\" ->\\n\")\n\
520  outstream.write(\"\\n\\n\")\n\
521 \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\
526  to the node. \n\
527  \"\"\"\n\
528  module_name = pythonscript_node.moduleName.getValue()\n\
529  module = sys.modules[ module_name ]\n\
530  nodes = _getPythonObjectNodeReferents( module, {}, [module] ) \n\
531  \n\
532  return nodes\n\
533  \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\
542  \"\"\"\n\
543  fields = node.getFieldList()\n\
544  referents = []\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\
552  if( n ):\n\
553  referents.append( (n, field_name ) )\n\
554  if( node.getTypeName() == \"PythonScript\" ):\n\
555  referents.extend(_getPythonScriptNodeReferents( node ) )\n\
556  return referents\n\
557 \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\
568  \"\"\"\n\
569  refs = gc.get_referents( obj )\n\
570 \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\
577  \n\
578  nodes = []\n\
579  for ref in refs:\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\
592  \n\
593  else:\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\
597  \n\
598  return nodes\n\
599 \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\
610  @return None\n\
611  \"\"\"\n\
612  if not node:\n\
613  return\n\
614 \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\
618 \n\
619  # get all children of the node\n\
620  referents = _getNodeReferents(node)\n\
621  for referent, origin in referents:\n\
622  if not referent:\n\
623  continue\n\
624  \n\
625  # The node is what we want, collect it\n\
626  if referent == start:\n\
627  output.append( current_path + [(referent, origin)] ) \n\
628 \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\
632  \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\
640  python code)\n\
641  \"\"\"\n\
642  \n\
643  s = H3DInterface.getCurrentScenes()[0]\n\
644  root = s.sceneRoot.getValue()\n\
645  output = []\n\
646  _getNodeRefsFromNode( s, node, { }, [ (s, \"\")], output )\n\
647  return output \n\
648  \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\
656  python code)\n\
657  \"\"\"\n\
658  visited = {}\n\
659  node_referents = []\n\
660 \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\
664 \n\
665  output = []\n\
666  \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\
669  if( n == node ):\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\
672  else:\n\
673  _getNodeRefsFromNode( n, node, {}, [ (n, path) ], output )\n\
674 \n\
675  return output\n\
676 \n\
677  ";
678  }
679 }
H3D API namespace.
Definition: Anchor.h:38