NodePath subclassing - help needed!

Hey all,

I’ve read up on some of the guidelines for NodePath subclassing, and thought I would write up a few code examples to illustrate what’s going on. I’ve now come to a point where I also want to be able to attach classes to NodePaths, so I’ve come up with a slight variation to the circular reference method described in this post: [url]Inheriting from NodePath]
I didn’t get the results that I expected however, and now I’m not sure I understand the whole thing as well as I did. I’m hoping someone can help me understand!

Here’s my code:

import direct.directbase.DirectStart
from panda3d.core import NodePath


class PandaObject( object ):
    
    def __init__( self, *args ):
        self.np = NodePath( *args )
        self.np.setPythonTag( 'PandaObject', self )
        
    def __del__( self ):
        print 'deleted!'
        
    @staticmethod
    def Get( np ):
        return np.getPythonTag( 'PandaObject' )
        

def AddPandaObject( name ):
    
    # Create an instance of our class, stick the node path into the scene
    # graph
    pObj = PandaObject( name )
    pObj.np.reparentTo( render )
    

def Destroy( name ):
    
    # Find the node in the scene graph, attempt to remove it - note how the
    # destructor message isn't printed
    np = render.find( name )
    print np
    np.removeNode()
    

def DestroyViaStaticMethod( name ):
   
    # Find the node in the scene graph, get the object using the static method
    # then attempt to remove the node path
    pObj = PandaObject.Get( render.find( name ) )
    print pObj.np
    pObj.np.removeNode()
    

print 'Result for removing normally: '
AddPandaObject( 'first' )
Destroy( 'first' )

print 'Result for removing via static method: '
AddPandaObject( 'second' )
DestroyViaStaticMethod( 'second' )

run()

So basically I want to use a static method to turn a NodePath back into its parent class. When I remove the node in the Destroy() function, the destructor message doesn’t print - which is to be expected because I haven’t broken the circular reference by clearing the tag. Since my class hasn’t been destroyed I assume that the NodePath hasn’t been either, but I’ll never be able to test that properly.

However when I destroy via the static method, I do see the destructor message. I haven’t broken the circular reference though, so how can this be? If my class has been destroyed, has the NodePath been too? If so, why?

Also - is there anyway to ‘see’ all the NodePaths that exist even if they aren’t attached to anything? That would be super handy to figure out some of this stuff :slight_smile:

In the second case, with the “static method”, you are calling pObj.np.removeNode(), which is specifically operating on the NodePath instance within the class object itself. Since NodePath.removeNode() resets the NodePath to empty after it has finished, this breaks the circular reference (the class object no longer contains a pointer to the node, so there is no cycle even though the node still contains a pointer to the class object).

In the first case, you are getting a new NodePath and calling removeNode() on this one. This detaches the node from the scene graph, and resets the new NodePath to empty, but it doesn’t affect the NodePath that is still within the class object, which still contains a reference to the same node. So in that case, the circular reference remains.

This is all just a kind of a fringe case, though, which serves to illustrate the dangers of circular references: it usually isn’t obvious when the circular reference is completely destroyed or not.

David