Ed Swartz fc5a2e5e33 Implement confined mouse mode for OS X.
Note: it seems that using #set_pointer() will result in
a long delay before an absolute mouse position is updated,
even though deltas are reported.

Thus, in CocoaPandaView, the mouse deltas are sent for both
relative and confined modes, so client code (e.g. the "mouse
modes" demo) will be able to recenter the mouse without
choppy movement.
2015-04-30 17:57:00 -05:00

175 lines
5.8 KiB
Python

#!/usr/bin/env python
'''
Demonstrate different mouse modes
'''
# from panda3d.core import loadPrcFileData
#
# loadPrcFileData("", "notify-level-x11display debug")
# loadPrcFileData("", "notify-level-windisplay debug")
#
# loadPrcFileData("", "load-display p3tinydisplay")
from panda3d.core import WindowProperties, TextNode
from direct.task.TaskManagerGlobal import taskMgr
from direct.gui.OnscreenText import OnscreenText
from direct.task import Task
from direct.showbase.ShowBase import ShowBase
import sys
class App(ShowBase):
def __init__(self):
ShowBase.__init__(self)
self.base = self
self.setup()
def genLabelText(self, text, i):
text = OnscreenText(text = text, pos = (-1.3, .5-.05*i), fg=(0,1,0,1),
align = TextNode.ALeft, scale = .05)
return text
def setup(self):
# Disable the camera trackball controls.
self.disableMouse()
# control mapping of mouse movement to box movement
self.mouseMagnitude = 1
self.rotateX, self.rotateY = 0, 0
self.genLabelText("[0] Absolute mode, [1] Relative mode, [2] Confined mode", 0)
self.base.accept('0', lambda: self.setMouseMode(WindowProperties.M_absolute))
self.base.accept('1', lambda: self.setMouseMode(WindowProperties.M_relative))
self.base.accept('2', lambda: self.setMouseMode(WindowProperties.M_confined))
self.genLabelText("[C] Manually re-center mouse on each tick", 1)
self.base.accept('C', lambda: self.toggleRecenter())
self.base.accept('c', lambda: self.toggleRecenter())
self.genLabelText("[S] Show mouse", 2)
self.base.accept('S', lambda: self.toggleMouse())
self.base.accept('s', lambda: self.toggleMouse())
self.base.accept('escape', sys.exit, [0])
self.mouseText = self.genLabelText("", 5)
self.deltaText = self.genLabelText("", 6)
self.positionText = self.genLabelText("", 8)
self.lastMouseX, self.lastMouseY = None, None
self.hideMouse = False
self.setMouseMode(WindowProperties.M_absolute)
self.manualRecenterMouse = True
# make a box to move with the mouse
self.model = self.loader.loadModel("box.egg")
self.model.reparentTo(self.render)
self.cam.setPos(0, -5, 0)
self.cam.lookAt(0, 0, 0)
self.mouseTask = taskMgr.add(self.mouseTask, "Mouse Task")
def setMouseMode(self, mode):
print "Changing mode to",mode
self.mouseMode = mode
wp = WindowProperties()
wp.setMouseMode(mode)
self.base.win.requestProperties(wp)
# these changes may require a tick to apply
self.base.taskMgr.doMethodLater(0, self.resolveMouse, "Resolve mouse setting")
def resolveMouse(self, t):
wp = self.base.win.getProperties()
actualMode = wp.getMouseMode()
if self.mouseMode != actualMode:
print "ACTUAL MOUSE MODE:", actualMode
self.mouseMode = actualMode
self.rotateX, self.rotateY = -.5, -.5
self.lastMouseX, self.lastMouseY = None, None
self.recenterMouse()
def recenterMouse(self):
self.base.win.movePointer(0,
int(self.base.win.getProperties().getXSize() / 2),
int(self.base.win.getProperties().getYSize() / 2))
def toggleRecenter(self):
print "Toggling re-center behavior"
self.manualRecenterMouse = not self.manualRecenterMouse
def toggleMouse(self):
print "Toggling mouse visibility"
self.hideMouse = not self.hideMouse
wp = WindowProperties()
wp.setCursorHidden(self.hideMouse)
self.base.win.requestProperties(wp)
def mouseTask(self, task):
mw = self.base.mouseWatcherNode
hasMouse = mw.hasMouse()
if hasMouse:
# get the window manager's idea of the mouse position
x, y = mw.getMouseX(), mw.getMouseY()
if self.lastMouseX is not None:
# get the delta
if self.manualRecenterMouse:
# when recentering, the position IS the delta
# since the center is reported as 0, 0
dx, dy = x, y
else:
dx, dy = x - self.lastMouseX, y - self.lastMouseY
else:
# no data to compare with yet
dx, dy = 0, 0
self.lastMouseX, self.lastMouseY = x, y
else:
x, y, dx, dy = 0, 0, 0, 0
if self.manualRecenterMouse:
# move mouse back to center
self.recenterMouse()
self.lastMouseX, self.lastMouseY = 0, 0
# scale position and delta to pixels for user
w, h = self.win.getSize()
self.mouseText.setText("Mode: {0}, Recenter: {1} | Mouse: {2}, {3} | hasMouse: {4}".format(
self.mouseMode, self.manualRecenterMouse,
int(x*w), int(y*h),
hasMouse))
self.deltaText.setText("Delta: {0}, {1}".format(
int(dx*w), int(dy*h)))
# rotate box by delta
self.rotateX += dx * 10 * self.mouseMagnitude
self.rotateY += dy * 10 * self.mouseMagnitude
self.positionText.setText("Model rotation: {0}, {1}".format(
int(self.rotateX*1000)/1000., int(self.rotateY*1000)/1000.))
self.model.setH(self.rotateX)
self.model.setP(self.rotateY)
return Task.cont
app = App()
app.run()