How to move the default mouse 3 click function to the mouse 1?

I want to move the default mouse 3 button (scroll wheel button) function to mouse 1 (left mouse button). But I don’t know mouse 3 button function name.

Here is my code:

from direct.showbase.ShowBase import ShowBase


class MyApp(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)

        self.disableMouse()

        self.cam.setPos(0, -20, 0)

        self.jack = self.loader.loadModel("models/jack")
        self.jack.setHpr(0, 180, 180)
        self.jack.reparentTo(self.render)

        self.accept("wheel_up", self.zoomin)
        self.accept("wheel_down", self.zoomout)
        # self.accept("mouse 3",)

    def zoomin(self):
        x = self.cam.getPos().getX()
        y = self.cam.getPos().getY()
        z = self.cam.getPos().getZ()
        # print(f" zoom {x},{y},{z}")
        self.cam.setPos(x, y + 0.2, z)

    def zoomout(self):
        x = self.cam.getPos().getX()
        y = self.cam.getPos().getY()
        z = self.cam.getPos().getZ()
        # print(f" zoom {x},{y},{z}")
        self.cam.setPos(x, y - 0.2, z)


app = MyApp()
app.run()

Oddly enough, the answer is in the manual.

https://docs.panda3d.org/1.10/python/programming/hardware-support/keyboard-support#keyboard-events

1 Like

Thanks for your reply. I know how to disable the default mouse function and set the mouse click events, but I want the move camera angle function(the default mouse 3 btn function) and set it to mouse 1.

Could I ask for clarification, please: Is the question that of how to implement rotation of the camera around a pivot? Or of how to derive rotation values from mouse-movements? Or something else…?

1 Like

I think he wants to call the built-in trackball method. However, the default mouse control isn’t meant for rich features, it’s usually meant for debugging purposes.

@caden_caden You need to re-implement mouse control.

1 Like

I think that that was my first impression–but given that they’ve already re-implemented zooming, I’m wondering whether they don’t perhaps already intend to re-implement rotation, and are uncertain as to how to do so.

1 Like

Thank you for your reply. I’m also sorry I wasn’t clear about what I was trying to do.
I am still learning the panda3d camera. In learning the camera, I have two goals. The first is to put the default mouse functions on other mouse buttons. The second is to write a program to control the rotation of the camera. So re-implementing mouse control, rotating the camera around a pivot point, and deriving the rotation value from the mouse movement were all things I wanted to know.

I have read through the content and I may not have understood enough to find out what the middle mouse button does. If you know of any, can you provide me with the information or example code about changing the default mouse3 button to mouse 1?
https://docs.panda3d.org/1.10/python/programming/hardware-support/keyboard-support#keyboard-events

Thank you for reading this post.

Ah, I think that I better understand now. Thank you for clarifying! :slight_smile:

Deriving a rotation value from the mouse should be fairly straightforward, I think:

  • Take the position of the mouse relative to an origin point
    • That origin point would likely be the position of the mouse when the mouse-button was first pressed down, based on the behaviour of the default mouse-control
  • For each of the x- and y- components of that position, multiply the component by an appropriate value (in order to scale it to desired values)
    • You might determine the value by which to multiply experimentally
  • And then perform “h”- and “p”- rotations using the “x”- and “y”- values respectively.
    • Note that this is a rotation, not an assignment of orientation. That is, don’t just set the object’s h- and p- values to the new values that you calculated from the mouse-cursor. Rather, offset the object’s h- and p- values by those new values. This can be done either by performing a relative rotation, or by assigning the object’s h- and p- values to their current values plus the new ones.

As to rotation, this is what I’d suggest:

First:

  • Create a pivot-node, and attach the camera to it.
  • No, offset the camera along the y-axis.

This means that, if we rotate the pivot-node, the camera will retain its position relative to that pivot node–and thus swing around it, orbiting the pivot.

Then:

  • Alter your camera-zoom functions to only alter the camera’s y-coordinate

Since the camera is being swung around by the pivot, it remains in the same position relative to the pivot–it’s just that the pivot’s orientation is changing. Thus we need only move the camera “forwards” and “backwards” from its own perspective–i.e. along its y-axis–in order to zoom it -in and -out.

And finally:

  • Create a method to be called by the mouse-event that rotates the pivot according to the mouse-position.
2 Likes

It is worth noting that you are mistaken in the fact that you want to implement this by the mouse button event. However, in this case, a combined approach is needed, that is, to use a dictionary and a task.

from direct.showbase.ShowBase import ShowBase
from panda3d.core import NodePath

class MyApp(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)
        self.disableMouse()
        
        scene = loader.load_model("environment")
        scene.reparent_to(render)

        self.axis_y = NodePath("Axis_Y")
        self.axis_y.reparent_to(render)
        
        self.camera.set_pos(0, -500, 0)
        self.camera.reparent_to(self.axis_y)

        self.accept("mouse1", self.set_key, ["left_mouse", True])
        self.accept("mouse1-up", self.set_key, ["left_mouse", False])

        self.accept("mouse2", self.set_key, ["center_mouse", True])
        self.accept("mouse2-up", self.set_key, ["center_mouse", False])

        self.accept("mouse3", self.set_key, ["right_mouse", True])
        self.accept("mouse3-up", self.set_key, ["right_mouse", False])

        self.key_map = {"left_mouse":False, "right_mouse":False, "center_mouse":False}

        taskMgr.add(self.update, 'update')

    def set_key(self, key, value):
        self.key_map[key] = value

    def update(self, task):
        if self.key_map["left_mouse"]:
            print("left_mouse")
            md = base.win.get_pointer(0)
            if base.win.movePointer(0, base.win.get_x_size()//2, base.win.get_y_size()//2):
                delta_x = self.axis_y.get_h() - (md.get_x() - base.win.get_x_size()/2)*0.1
                delta_y = self.axis_y.get_p() - (md.get_y() - base.win.get_y_size()/2)*0.1
                self.axis_y.set_hpr(delta_x, delta_y, 0)

        if self.key_map["right_mouse"]:
            print("right_mouse")

        if self.key_map["center_mouse"]:
            print("center_mouse")

        return task.cont

app = MyApp()
app.run()

This is a simple example with the use of inheritance. However, you can use trigonometry like here and it will work too.

1 Like

Hmm… In this specific case, I would argue that an event-based approach works just as well–arguably (a very tiny bit) better, as update-based polling may skip over actions if the frame-rate drops below the duration of the action.

To be clear, both ways would work; I’m just saying that, while in some cases the key-map based approach is better, in this case I think that both approaches are fine.

The event-based approach is also arguably a bit clearer in this case–which may be an advantage when it’s being used to learn something else, such as the handling of the camera.

1 Like

Mouse button 3 is named mouse2 in Panda3D, and mouse button 2 is named mouse3 in Panda3D.

2 Likes

Thanks for your reply. I got some ideas from your code.
I modified the code into the right mouse click.
The result is frame rate is more smooth, but why?

        if (self.key_map["right_mouse"] ):
            print("right_mouse")

            if self.mouseWatcherNode.hasMouse():
                x = self.mouseWatcherNode.getMouseX()
                y = self.mouseWatcherNode.getMouseY()
                print(x, y)
                self.cam.setP(p + y * 1.1)  # up down
                self.cam.setH(h - x * 1.1)  # left right

This is not my code, I don’t use aspect coordinates of the screen.