How to "Delete" level class

Hi Guys!

Well, i’m tryng to make my “level system” with the following code:

# - - - Panda3d Modules - - - #

import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject

from direct.actor.Actor import Actor
from direct.gui.OnscreenText import OnscreenText

from panda3d.core import CollisionTraverser,CollisionNode
from panda3d.core import CollisionHandlerQueue,CollisionRay
from panda3d.core import Vec3,Vec4,BitMask32
from panda3d.core import PandaNode,NodePath,Camera,TextNode

import random, sys, os, math

# - - - Level SuperClass - - - #

class level(DirectObject):
	class character(DirectObject):
		def __init__(self, parent):
			
			self.parent = parent
			
			# Set Model
			self.actor = Actor()
			self.actor.loadModel("Models/Char1")
			self.actor.reparentTo(self.parent.roomnode)
			self.actor.loadAnims({"stand":"Models/Char1a","walk":"Models/Char1b"})
			self.actor.setPlayRate(1.5, "walk")
			
			# Events
		
			taskMgr.add(self.test,"testTask")
		
		def test(self, task):
			if (self.parent.keyMap["left"]!=0):
				self.parent.level_clear(1)
			return task.cont
			
	
	def level_config(self):
        
		# -------- Default Level Settings -------- #
		
		# Set Keys 
		
		self.keyMap = {"left":0,"right":0,"up":0}
		
		self.accept("escape", sys.exit)
		self.accept("arrow_left", self.setKey, ["left",1])
		self.accept("arrow_right", self.setKey, ["right",1])
		self.accept("arrow_up", self.setKey, ["up",1])
		self.accept("arrow_left-up", self.setKey, ["left",0])
		self.accept("arrow_right-up", self.setKey, ["right",0])
		self.accept("arrow_up-up", self.setKey, ["up",0])
		
		# Load Objects 
		
		self.char = self.character(self)
		#self.char.actor.setPos(self.environ.find("**/start_point").getPos())
		
	def level_clear(self,a):
		self.roomnode.removeNode()
		self.parent.set_level(a)
	def setKey(self, key, value):
		self.keyMap[key] = value

# - - - Level Classes - - - #

class level1(level):
	def __init__(self, parent):
		self.parent = parent
		self.roomnode = render.attachNewNode("Nivel")
		self.environ = loader.loadModel("Models/Map/world")      
		self.environ.reparentTo(self.roomnode)
		self.environ.setPos(0,0,0)
		
		self.level_config()
		
class level2():
	def __init__(self, parent):
		print "lalala"


# - - - Scene Control - - - #

class main():
	def __init__(self):
		
		# All level classes
		self.allrooms = {0:level1,1:level2}
		
		self.set_level(0)
		
	def set_level(self,a):
		self.room = self.allrooms.get(a)(self)
		
		


start = main()

# - - - Main Bucle - - - #

run()

That’s good, when i press “left key” the scene it’s clean… but the “level1” class it’s still alive and his classes and tasks too.

The cuestion IS:

How can i delete the previous level class and “clean it” ?

Thank you very much, sorry my bad english.

It’s best to add some cleanup code (like a destroy function):

class level(DirectObject):
    def destroy(self):
        self.ignoreAll()
        taskMgr.remove('myevent1')
        taskMgr.remove('myevent2')
        taskMgr.remove('myevent3')
        taskMgr.remove('myevent4')
        self.myModelA.remove()
        self.myModelB.remove()
        self.myModelC.remove()

You’ll have to adjust that to your own code, though.
So just to clarify:
Build a destroy function for each class dubbed a level.
self.ignoreAll(), from DirectObject, will ignore all events bound.
self.myModel.remove(), from NodePath, will remove a node from the scene
taskMgr.remove(‘taskname’), will remove a task with a name, and does the exact opposite of taskMgr.add(myfunc, ‘taskname’)

Hope this helps,
~powerpup118

Very well, thank you powerpup118.

Now, i must really “remove” each task?

“self.ignoreAll()” function will work for task or “accept” events only?

Should i make a list for each model to remove? How?

SO, the memory for the declared class variables will never be free?

Thank you again, i hope to learn much more.

Finally, is there any panda3d class/function to display the “render tree” ?

If i remove a parent node for render, his son will be also free from the memory?

I know, my english SUX a lot.

Yes, for each task added, you should also manually remove it.
“self.ignoreAll()” from the DirectObject class will only work for accepted events. It release any events bound via “self.accept(‘event’, myCallback)” it will never release events bound via ‘base.accept(‘event’, myCallback)’, however, because base itself inherits from DirectObject.

If you desire it that way, you can make a list, yes.

class blah:
    def __init__(self):
        self.models = []
        self.smiley = loader.loadModel('smiley')
        self.models.append(self.smiley)
        self.box = loader.loadModel('box')
        self.models.append(self.box)

    def destroy(self):
        for model in self.models:
            model.remove()

Python releases the variables of the class as long as there are no references to the class itself.

#- Make a world
world = World()
#- Clean up the world
world.destroy()
#- Remove all class variables, and the reference to the class itself
del world

No problem, I dunno for sure if panda has one ‘to display every item in the tree’, however consider the following:

#- Display any nodes directly beneath the tree
render.ls()

that would, display any nodes directly parented to render, however it’s non-recursive. That means for instance if you have a scene that looks like this:
render -> myTreeNode -> leafNode1, leafNode2, etc
it will only show “myTreeNode”, give it a shot though and see if that’s what you want. You could walk the entire tree and display each one, if you wanted to, by getting into some recursive statements

Right. Any node you remove also removes the children.
Consider the following scene:
render -> myTreeNode -> leaf1, leaf2, leaf3

myTreeNode.remove()
#- All leaf's are now gone! and the main, "myTreeNode" has been removed, too.

Your english is quite fine to me, I bet me trying to speak your language would be much much funnier! anywho, you’re English is fine in my opinion.

~powerpup118

Understood, THANK YOU AGAIN, seriously, thanks.

Ok… so, i think maybe usefull mix both methods: the function destroy together with the list.

Something like this:

class World():
	class Bird():
		def __init__(self):
			self.actor = Actor("Models/Bird")
		def destroy(self)
			self.actor.remove()
	class Duck():
		def __init__(self):
			self.actor = Actor("Models/Duck")
		def destroy(self)
			self.actor.remove()

	def __init__(self)
		self.Models[]
		self.Environ = loader.loadModel("Maps/Level1")
		self.Bird1 = Bird()
		self.Bird2 = Bird()
		self.Duck1 = Duck()

		self.Models.append(self.Environ)
		self.Models.append(self.Bird1)
		self.Models.append(self.Bird2)
		self.Models.append(self.Duck1)

	def destroyWold():
		for i in range(len(self.Models))
			self.Models[i].destroy()
			del self.Models[i]

You think it’s right? How it’s the better way?