return the object under mouse

Hey,

Is there a function that returns me the object thats under my mouse? Like when I point my mouse at a panda it will return me that panda instance?

what you are looking for is called “picking”. panda comes with a sample demonstratign it. there also are a number of threads here on the forum about it. try using the search function.

This seems not to work:

        self.myTraverser = CollisionTraverser()       
        self.myHandler     = CollisionHandlerQueue()      
        self.pickerNode = CollisionNode('mouseRay')
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        self.pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask())
        self.pickerRay = CollisionRay()
        self.pickerNode.setIntoCollideMask(BitMask32.allOff())
        self.pickerNode.addSolid(self.pickerRay)
        self.myTraverser.addCollider(self.pickerNP, self.myHandler)


    def getMouseOver(self):
        #return
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()
            self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
            if self.myHandler.getNumEntries() > 0:
                #if we have hit something, sort the hits so that the closest
                #is first, and highlight that node
                self.myHandler.sortEntries()
                i = self.myHandler.getEntry(0).getIntoNodePath()
                print i, type(i)
                return i

It returns none all the time

I observe that you don’t appear to be calling myTraverser.traverse() anywhere, so you’re not actually computing the ray intersection.

David

omg thank you!

I have got just one Question still:

self.myHandler.getEntry(0).getIntoNodePath()

does not return the instance of the object I clicked on. How can I return that? Or how can I compare it to an instance?

The collision system returns the actual GeomNode or CollisionNode that you clicked on, which is usually a node somewhere underneath the node that you consider your ‘object’.

To map from the child node back to the parent node that you care about, most people use the tag system; and indeed this is described in the manual and illustrated in a few of the sample programs. It is also discussed in the forums; try searching for setTag, getNetTag, and findNetTag.

David

lol, im not getting it.

I added

self.setTag('clickAbleTag', '1')

To my class but with this code:

self.myHandler.getEntry(0).getIntoNodePath().findNetTag('clickAbleTag')

I still wont get the object. :cry: What am I doing wrong?

Well, I don’t know, but you can diagnose it by printing the NodePath that you are actually retrieving from the collision system, and the NodePath that expect to be finding. Is the one a child of the other? It will show that way when you print it if it is true.

If it isn’t, then knowing which NodePath you are actually finding may give you some insight as to what is going wrong. If it is a child of the one you expect, then something’s going wrong with the findNetTag(), and again simply knowing this may provide some insight.

David

Do you mean this:

print target.NodePath

when target is the object i clicked on?
This and the NodePath of the object returns both

<type 'libpanda.NodePath'>

Or what do you mean?

You are printing the NodePath class. I mean for you to print the actual instance. What is your target object? Is it a NodePath, or is it something else? Just print target.

Also, for the thing you collide into, print that thing:

self.myHandler.getEntry(0).getIntoNodePath()

And, for that matter, print the thing returned by findNetTag:

self.myHandler.getEntry(0).getIntoNodePath().findNetTag('clickAbleTag')

David

            print target
            #print type(target)
            print monsters[0]

prints out:

render/panda_walk_character
Actor panda_walk_character, parts = ['modelRoot'], LODs = ['lodRoot'], anims = ['walk']

and

                print 1, self.myHandler.getEntry(0).getIntoNodePath() 
                print 2, self.myHandler.getEntry(0).getIntoNodePath().findNetTag('clickAbleTag') 

prints out

1 render/panda_walk_character/__Actor_modelRoot/-GeomNode
2 render/panda_walk_character

OK, so your “target” is an Actor, and now you are returning the NodePath that corresponds to the same node as your Actor.

But it’s not the same Python object, it’s just a NodePath. One cheesy workaround is to store your Python object on itself:

and then you can extract it with:

found = self.myHandler.getEntry(0).getIntoNodePath().getNetPythonTag('clickAbleTag')

When you do this, you have to be sure to clean it up later, when you want to delete your Actor, because otherwise it will never be deleted.

See “Subclassing” in the manual for more details.

David

Now it works!
Thanks