converting mouse coordinates to position coordinates?


I create a DirectGui object (for example a button) and position it on the screen using the pos keyword. This works great.

But when I later get the mouse coordinates I see that the mouse coords does not correspond to the positioning coords…

I create the object like this:

DirectButton(text = self.b_text,
                        frameColor = self.b_fcolor,
                        frameSize = self.b_fsize,
                        text_fg = self.b_fontcolor,
                        text_pos = self.b_textpos,
                        text_scale = self.b_textscale,
                        borderWidth = self.b_bwidth,
                        pos = self.b_pos)

And I get the mouse coords like this:

if base.mouseWatcherNode.hasMouse():

Why are the positioning coordinates different than the mouse coordinates of the same point on the screen?

I noticed that mouse coords are given in (x, y) and positioning coords are given in (x, y, z).

Is there a way to convert mouse coordinates (x,y) to position coordinates (x,z)?
And is that method independent of window size?


The scene graph is a 3-D scene graph, so it has (x, y, z). It’s Panda3D, after all. For the 2-D interfaces, we don’t use the y component, so it’s usually (x, 0, z).

So, you could (almost) take the mouse coordinates and insert an extra 0 in the middle to go to screen coordinates, and simply drop the middle coordinate to go back to mouse coordinates.

I say almost because there’s another complication: your DirectGui widgets are parented to aspect2d, which introduces a scale to compensate for the non-square aspect ratio of the window. So you need to get the coordinates in the space of render2d, which is where the mouse coordinates are relative to. Fortunately, Panda makes this easy.

To get the position of your button in mouse coordinates:

mousePos3d = button.getPos(render2d)
mousePos = (mousePos3d[0], mousePos3d[2])

To get the mouse position in aspect2d coordinates:

mousePos = base.mouseWatcherNode.getMouse()
mousePos3d = (mousePos[0], 0, mousePos[1])
mousePosButton = button.getRelativePoint(render, mousePos3d)


1 Like

Thanks a lot for the help!

It works now, no matter what size the window is :smiley:

Here is the resulting code for the task:

    def checkForTooltip(self, task):
        """Showing tooltip if mouse is over button"""
        if self.button['state'] == "normal":
            if base.mouseWatcherNode.hasMouse(): 
                mousePos = base.mouseWatcherNode.getMouse() 
                mousePos3d = VBase3(mousePos[0], 0, mousePos[1]) 
                mousePosButton = self.button.getRelativePoint(render, mousePos3d)
                x = mousePosButton[0]
                y = mousePosButton[2]
                if x < self.b_width/2 and x > -self.b_width/2 and y < self.b_height/2 and y > -self.b_height/2:
            return Task.cont
1 Like

Note that you can also achieve a similar effect, perhaps more easily, simply by binding on the mouse enter and exit events for the button, as described in this recent thread.