Find parent object from child?

In my game, I have a custom “character” class that contains all sorts of game-specific info (status, hit pts, speed, name, etc).

The character object has a property , “model”, which is actually a reference to an Actor model for the character.

When picking characters to move (basic RTS type setup) I have std picker code which finds the picked object (in this case the Actor model). Is there an easy way to get to the character object that is the “parent” of this model?

Right now, I do it by keeping a list of all characters and a python tag on the model with the character name. When the model is clicked, I call a function which checks for the name in the list and returns a reference to the character object.

It works fine, but just wondering if there’s a better /easier way.

Are you looking for this?:

panda3d.org/reference/python … d057a12e22

EDIT: After reading a second time I guess now I got what you’re after. You have a class and store an actor as an instance attribute. In this case the most simple thing to do is comparing the stored actor and the return value of certain functions.

EDIT2: Or store the instance in an attribute of the actor. Not sure if this works, but it should.
Example:

# Store the abstract "parent object" as actor attrribute
self.actor = Actor("whatever")
self.actor.abstract = self

...


# Get the abstract instance that has this actor as attribute
if return_value.hasattr('abstract'):
    self.abstract = return_value.abstract
# Now self.abstract.actor should be the same as the return_value

BTW, i wouldn’t speak of a “parent” here. People easily get it confused with the scene graph.

I would use a dictionary, like this:

characters_by_model = {}

class Character(object):
    def __init__(self):
        self.model = loader.loadModel('some_model')
        characters_by_model[self.model] = self

my_char = Character()
print characters_by_model[my_char.model]

Sorry. Won’t work. You can’t access class attributes from out of the scope. Beside that I guess he tries to get “my_char” from a model-object a function returns.

Unless I have some special Python, this code works just fine.

Ooops. Overseen the first line. In this case it might work indeed.

Sorry for my big smartass mouth :S

self.actor.abstract = self

does not work :frowning:

I get:

AttributeError: 'libpanda.NodePath' object has no attribute 'abstract'.

self.actor.setattr(…) also does not work.

For now i realised it with tags:

self.__model.setTag('id', 'bla')

def findGameObjectByNodePath(self, nodePath):     
    if nodePath.getNetTag('id') == 'bla':
       ...

Yep, I didn’t think storing it in the actor would work (has todo with python tag on a c++ object vs a Python wrapper around the c++ object, if I recall).

But using the nettag (or pythonTag) functions should as DavidM says.

However, my question then would be how do you find the object other than looping through a list (as I’m doing). Again, my way is working, just wondered if there was a better/faster way.

It sounds like the dictionary method might fit the bill. (but not sure if it would much faster than looping through the list - my list is probably less than 50 items)

Thanks!

Well the dictionary is future-proof. The time cost of a dictionary lookup is constant, whereas looping a list will increase in time as more items are added.

I also use a dictionary where i map the id strings to objects, so basically the same as mapping nodepaths to objects.

This is basically how I do it: I store the return value of a class instantiation do a dict.
That’s propably what you guys meant, too, but still I’d post some code sample:

class Ship(object):
	self.attribute = 2
	self.model = loader.loadModel("path/model.egg")
	
class Environment(object):
	self.Ships = {}
	self.ShipID = 0
	
	def addShip(self):
		self.Ships[ID] = Ship()
		self.ShipID += 1
		
	def removeShip(self, ID):
		print self.Ships[ID].attribute
		self.Ships[ID].model.removeNode()
		del self.Ships[ID]

The dict then follow the form:

self.Ships = {0: <memory adress>, 1: <memory adress>, (...)}

The nodepath of the model gets it’s ID as a tag. The collision ray from the mouse can then pick the ID.