redirect NodePath.analyze

hi,

NodePath.analyze currently writes directly to the console. is there a way to redirect the output easily, so i can do something like the snippets below?

   print >> mystream, np.analyze()

or

   logging.debug(np.analyze())

or is there some way to get the same information easily and reformat them as wanted by Python code?

cheers,
kaweh

NodePath.analyze() uses an object called a SceneGraphAnalyzer to produce its output. You can do this yourself, directly:

sga = SceneGraphAnalyzer()
sga.addNode(render.node())
sga.write(myStream)

Note that myStream must be a C++ type ostream, not a Python file-like object. Panda provides a convenient ostream class called a LineStream, which saves up its output and allows you to retrieve it one line at a time:

ls = LineStream()
sga.write(ls)
while ls.isTextAvailable():
  line = ls.getLine()
  print line

The only problem with my suggestion to use the SceneGraphAnalyzer object is that, up until two minutes ago, the SceneGraphAnalyzer class was not exported to the Python layer. So you can’t create one directly right now unless you have the bleeding-edge CVS version of Panda.

There’s another answer, which is to redirect Panda’s low-level Notify object. This is where all of the C++ output from Panda is written to–including the output of nodePath.analyze()–so you can temporarily redirect the Notify output, run analyze(), and then set it back, like this:

ls = LineStream()
Notify.ptr().setOstreamPtr(ls, 0)
render.analyze()
Notify.ptr().setOstreamPtr(ostream, 0)

Of course, all of the information reported by the SceneGraphAnalyzer is obtainable through other calls available to Python. You could just write a simple traversal that would walk through the entire scene graph and, each time it discovers a GeomNode, it would count up its primitives, etc, as described in the Panda3D manual.

David

Addendum: I’ve just added accessors to SceneGraphAnalyzer for all of its output. So if you’re looking for particular number, you don’t need to parse it out of the text output; instead, you can just get it directly, like this:

>>> sga = SceneGraphAnalyzer()
>>> sga.addNode(render.node())
>>> sga.getNumNodes()
5
>>> sga.getNumVertices()
673
>>> sga.getNumTristrips()
0
>>> sga.getNumIndividualTris()
1280

David

Thanks a million, David!