I am in the whole “do I wrap or subclass” stage.
I have been all over the forums; I guess I have a stupid-streak, I just want this to be pythonic. So, given that I may have to dump it all and play with wrapping NodePath instead, let’s see what we can make of the code below.
from pandac.PandaModules import *
import direct.directbase.DirectStart
class DNodePath(NodePath):
def __init__(self, *args, **kwargs):
## If no *args, then this class will NOT work!
NodePath.__init__(self, *args)
self.instance = "instance" # calls setter
## Gratuitous decorator frenzy, move along...
@property
def instance(self):
return NodePath.getPythonTag(self._tag)
@instance.setter
def instance( self, tag ):
self._tag = tag
NodePath.setPythonTag(self, tag, self)
@instance.deleter
def instance(self):
NodePath.clearPythonTag( self, self._tag )
self._tag = None
print "instance deleted"
class ModelThing( DNodePath):
def __init__(self, parent, file):
_nphandle = loader.loadModel("/usr/share/panda3d/models/%s" % file)
## Make sure we pass a PandaNode in: this one's node() is a <type 'libpanda.ModelRoot'>
## This causes ModelThing to BE A ModelRoot type.
DNodePath.__init__(self, _nphandle)
self.reparentTo( parent )
self.blah = "blah"
def cast( nodepath ):
if nodepath.hasPythonTag("instance"):
return nodepath.getPythonTag("instance") # return my actual subclass
return nodepath # It's not one of my subclasses.
def walkGraph(node):
node = cast(node)
print node, type(node), type(node.node())
for child in node.getChildren():
walkGraph(child)
base.disableMouse()
base.camera.setPos(0,-100,0)
base.camera.setHpr(0, 0, 0)
base.camLens.setFar(9000)
base.camLens.setFov(55)
node1 = render.attachNewNode("node1")
p = ModelThing( node1, "panda")
print "###",repr(p),type(p), type(p.node())
## Find a pure NodePath object from the SG, so
## I can experiment with the poor bugger:
t = cast( render.find("node1/panda.egg") )
print "t:", t, type(t), type(t.node()), t.blah
walkGraph(render)
node1.removeNode() ## <-- WTF?!
run()
If I make a ModelThing class and add it to render, it does ye olde fake C++ object wrapped in a distant Python cousin that is not welcome in the valley trick. So I have PythonTag (inherited through DNodePath) pointing back at my class-instance and I use the cast() function to fetch it when I have only a pure NodePath to work with.
All fine so far. I think.
But, how do I ensure that my ModelThing (and all children) are removed when I use something like somenode.removeNode()?
It wipes-out the nodes on the scene-graph, great, but I want it to also bump-off those awkward cousins, the ModelThings…
I suppose I could write my own removeNode and perform some recursive-fu but I am not sure where to begin really.
Is there some way to get a NodePath to call-back to the object pointed to in PythonTag? That would rule.
Failing that, is there any event or signal that a NodePath emits that can be detected anywhere in Python? I could use that to target a ModelThing and pull the trigger myself.
\d