nodePath.setCollideMask doesn't seem to work?

In [31]: zoomMask
Out[31]:  0000 0000 0000 0000 0000 0000 0000 0001
 
In [32]: np.getCollideMask()
Out[32]:  0000 0000 0000 0000 0000 0000 0000 0000
 
In [33]: np.setCollideMask(zoomMask)
 
In [34]: np.getCollideMask()
Out[34]:  0000 0000 0000 0000 0000 0000 0000 0000

What’s going on?

what that [in] [out] … does not even look like python! We want >>>

You might not be effecting the same camera or zoom mask.

nodePath.setCollideMask() will set the specified collide mask on any CollisionNodes or GeomNodes at that level or below. If the NodePath itself is not a CollisionNode or a GeomNode, then it will not directly be affected by the call (but its children might–see if nodePath.node().getNetCollideMask() changes).

David

Yeah I think I may be confused about how collide masks work. I thought I could just set the collide mask on an individual nodepath, but in fact it effects the children. I’ve also had a problem with the collide mask on a nodepath spuriously changing. It seems that changes in the collide masks of child nodes might affect the mask of a parent node? Also I think you may need to have Panda running for it to work properly, rather than just importing individual classes and testing them independently.

The In’s and Out’s are just prompts, those provided by the ipython shell, which is much better than the standard Python shell.

You can set the collide mask on an individual node, but only on a CollisionNode or GeomNode (other kinds of nodes don’t have collide masks).

Setting a collide mask on a node never affects its parent nodes’ collide masks. However, it will affect the return value for getNetCollideMask() from all parents, since this method returns the union of all collide masks defined at this node and below.

David

This does seem to be the case. From the API docs for NodePath method getCollideMask:

It also says “If you want to return what the into_collide_mask of this node itself is, without regard to its children, use node()->get_into_collide_mask().” But that method doesn’t seem to exist, either as get_into_collide_mask or getIntoCollideMask. Maybe there’s just no Python binding for it, or maybe it’s not a NodePath method.

I don’t think I can use collision masks for what I’m doing. What I need to do is enable/disable clicking on different nodepaths at different times. I think what I need to do instead is leave all the collide masks on, but set and unset tags on the nodepaths that say they are clickable. When the user clicks the mouse, find the nodepath it collided with, then move up the scene graph from that nodepath until you find one that has the clickable tag set, and that’s what the user clicked on. That means I need to ensure that the nodepath returned by the collision system is the one lowest down in the collision tree.

Oh, you’re right. NodePath.getCollideMask() actually returns the value of PandaNode.getNetCollideMask(). So it’s returning the union of all the collide masks at this node and below.

There is no NodePath.getIntoCollideMask()–this method is defined on PandaNode. So you have to call nodePath.node().getIntoCollideMask().

David

drwr, here’s my problem. I have a bunch of nodepaths all in the 2D scene graph, so their Y positions are all the same and irrelevant. Each nodepath ‘contains’ all of its child nodepaths, meaning the actual pos and bounds of the nodepath contain the bounds of all of its children. Now when a user clicks on one of the child nodepaths with the mouse, they may be clicking on that child, or the parent nodepath that encompasses it, or a higher parent, depending on the ‘clickable’ or not clickable state of all the nodepaths in my application.

Like I said, if when the user clicks the mouse button I can find the nodepath that is lowest down in the scene graph out of all those nodepaths whose bounds the mouse pointer was within, then I can search up the scene graph from that point and find the first nodepath that has a ‘clickable’ tag set.

But how can I find the nodepath to start from? If I use a collision ray, is there some way to ensure that it will hit the nodepath lowest in the scene graph?

From quick test, the standard shoot a collision ray from the mouse technique does seem to find the lowest nodepath when the mouse ray is within the bounds of multiple nodepaths all on the 2D scene graph.

Actually, thanks drwr, I think I’ve fixed my issue without having to resort to such a big refactoring. I just had to get and set the collide masks on my geom nodes, rather than on the nodepaths that own them. Seems to work now. Thanks!