Right-click now toggles mouselook

This can be disabled with the "Sticky Mouselook" option.
This commit is contained in:
David Vierra 2016-02-14 05:11:30 -10:00
parent 12dae3d174
commit dfe9aa9ddc
4 changed files with 144 additions and 10 deletions

View File

@ -22,6 +22,9 @@ _errorShown = False
def showErrorDialog(text, tb, fatal): def showErrorDialog(text, tb, fatal):
global _errorShown global _errorShown
_errorShown = True _errorShown = True
grabber = QtGui.QWidget.mouseGrabber()
grabber.releaseMouse()
dialog = ErrorDialog(text, tb, fatal) dialog = ErrorDialog(text, tb, fatal)
dialog.exec_() dialog.exec_()
_errorShown = False _errorShown = False

View File

@ -51,9 +51,11 @@ class CompassRenderNode(rendernode.RenderNode):
with gl.glEnable(GL.GL_BLEND, GL.GL_TEXTURE_2D): with gl.glEnable(GL.GL_BLEND, GL.GL_TEXTURE_2D):
GL.glDrawArrays(GL.GL_QUADS, 0, 4) GL.glDrawArrays(GL.GL_QUADS, 0, 4)
class CompassNode(scenenode.Node): class CompassNode(scenenode.Node):
_yawPitch = (0., 0.) _yawPitch = (0., 0.)
RenderNodeClass = CompassRenderNode RenderNodeClass = CompassRenderNode
def __init__(self, small=False): def __init__(self, small=False):
super(CompassNode, self).__init__() super(CompassNode, self).__init__()
self.small = small self.small = small

View File

@ -30,6 +30,8 @@ log = logging.getLogger(__name__)
settings = Settings().getNamespace("worldview/camera") settings = Settings().getNamespace("worldview/camera")
ViewDistanceSetting = settings.getOption("view_distance", int, 12) ViewDistanceSetting = settings.getOption("view_distance", int, 12)
PerspectiveSetting = settings.getOption("perspective", bool, True) PerspectiveSetting = settings.getOption("perspective", bool, True)
StickyMouselookSetting = settings.getOption("sticky_mouselook", bool, True)
class CameraWorldViewFrame(QtGui.QWidget): class CameraWorldViewFrame(QtGui.QWidget):
def __init__(self, dimension, textureAtlas, geometryCache, shareGLWidget, *args, **kwargs): def __init__(self, dimension, textureAtlas, geometryCache, shareGLWidget, *args, **kwargs):
@ -37,7 +39,17 @@ class CameraWorldViewFrame(QtGui.QWidget):
self.worldView = view = CameraWorldView(dimension, textureAtlas, geometryCache, shareGLWidget) self.worldView = view = CameraWorldView(dimension, textureAtlas, geometryCache, shareGLWidget)
self.viewControls = ViewControls(view) auxControlWidget = QtGui.QWidget()
StickyMouselookSetting.connectAndCall(view.setStickyMouselook)
stickyCheckbox = QtGui.QCheckBox(self.tr("Sticky Mouselook"))
stickyCheckbox.setChecked(StickyMouselookSetting.value())
stickyCheckbox.toggled.connect(StickyMouselookSetting.setValue)
auxControlWidget.setLayout(Column(stickyCheckbox))
self.viewControls = ViewControls(view, auxControlWidget)
ViewDistanceSetting.connectAndCall(view.setViewDistance) ViewDistanceSetting.connectAndCall(view.setViewDistance)
@ -256,14 +268,20 @@ class CameraWorldView(WorldView):
self.fov = 70.0 # needed by updateMatrices called from WorldView.__init__ self.fov = 70.0 # needed by updateMatrices called from WorldView.__init__
self._yawPitch = -45., 25. self._yawPitch = -45., 25.
self.viewDistance = 32 self.viewDistance = 32
self.stickyMouselook = False
self.workplaneNode = WorkplaneNode() self.workplaneNode = WorkplaneNode()
self.workplaneNode.visible = False self.workplaneNode.visible = False
WorldView.__init__(self, *a, **kw) WorldView.__init__(self, *a, **kw)
self.compassNode.yawPitch = self._yawPitch self.compassNode.yawPitch = self._yawPitch
stickyPanAction = CameraStickyPanMouseAction()
panAction = CameraPanMouseAction(stickyPanAction)
self.viewActions = [CameraMoveMouseAction(), self.viewActions = [CameraMoveMouseAction(),
CameraPanMouseAction()] panAction, stickyPanAction]
self.cameraControls = CameraKeyControls(self) self.cameraControls = CameraKeyControls(self)
self.viewActions.extend(self.cameraControls.viewActions) self.viewActions.extend(self.cameraControls.viewActions)
@ -277,6 +295,8 @@ class CameraWorldView(WorldView):
self.workplaneEnabled = False self.workplaneEnabled = False
self.viewportMoved.connect(self.updateWorkplane) self.viewportMoved.connect(self.updateWorkplane)
self.forceMouseCenter = False
def updateWorkplane(self): def updateWorkplane(self):
distance = 40 distance = 40
pos = self.centerPoint + self.cameraVector * distance pos = self.centerPoint + self.cameraVector * distance
@ -299,6 +319,10 @@ class CameraWorldView(WorldView):
return scenegraph return scenegraph
def augmentEvent(self, x, y, event): def augmentEvent(self, x, y, event):
if self.forceMouseCenter:
x = self.width() / 2
y = self.height() / 2
super(CameraWorldView, self).augmentEvent(x, y, event) super(CameraWorldView, self).augmentEvent(x, y, event)
if not self.workplaneEnabled: if not self.workplaneEnabled:
return return
@ -320,6 +344,9 @@ class CameraWorldView(WorldView):
self._chunkIter = None self._chunkIter = None
self.discardChunksOutsideViewDistance() self.discardChunksOutsideViewDistance()
self.update() self.update()
def setStickyMouselook(self, val):
self.stickyMouselook = val
def centerOnPoint(self, pos, distance=20): def centerOnPoint(self, pos, distance=20):
awayVector = self.cameraVector * -distance awayVector = self.cameraVector * -distance
@ -448,18 +475,121 @@ class CameraWorldView(WorldView):
return iter([]) return iter([])
return super(CameraWorldView, self).recieveChunk(chunk) return super(CameraWorldView, self).recieveChunk(chunk)
class CameraStickyPanMouseAction(ViewAction):
button = Qt.NoButton
modifiers = Qt.NoModifier
labelText = "Sticky Pan (Don't Edit)"
hidden = True
settingsKey = None
_sticking = False
mouseDragStart = None
def toggleSticky(self, event):
view = event.view
if not self._sticking:
self._sticking = True
cursor = view.cursor()
self._oldPos = cursor.pos()
self._oldShape = cursor.shape()
cursor.setShape(Qt.BlankCursor)
view.setCursor(cursor)
view.grabMouse()
view.forceMouseCenter = True
self.mouseDragStart = event.x(), event.y()
else:
self._sticking = False
cursor = view.cursor()
cursor.setPos(self._oldPos)
cursor.setShape(self._oldShape)
view.setCursor(cursor)
view.releaseMouse()
view.forceMouseCenter = False
self.mouseDragStart = None
sensitivity = .15
_last_dx = _last_dy = 0
def mouseMoveEvent(self, event):
if not self._sticking:
return
x = event.x()
y = event.y()
if self.mouseDragStart:
oldx, oldy = self.mouseDragStart
yaw, pitch = event.view.yawPitch
dx = (oldx - x)
dy = (oldy - y)
yaw -= dx * self.sensitivity
pitch -= dy * self.sensitivity
event.view.yawPitch = yaw, pitch
self.mouseDragStart = (x, y)
# If the (invisible) cursor goes out of the widget's bounds,
# move it back to the center so it doesn't stop at the screen's edge
margin = 10
w = event.view.width()
h = event.view.height()
if (x < margin
or y < margin
or x >= w - margin
or y >= h - margin):
# Disable camera movement while the cursor is repositioned
# since QCursor.setPos emits a mouseMoved event
self._sticking = False
self.mouseDragStart = (w / 2, h / 2)
pos = QtCore.QPoint(*self.mouseDragStart)
pos = event.view.mapToGlobal(pos)
QtGui.QCursor.setPos(pos)
def resumeSticking():
self._sticking = True
QtCore.QTimer.singleShot(0, resumeSticking)
class CameraPanMouseAction(ViewAction): class CameraPanMouseAction(ViewAction):
button = Qt.RightButton button = Qt.RightButton
mouseDragStart = None
modifiers = Qt.NoModifier modifiers = Qt.NoModifier
labelText = "Turn Camera" labelText = "Turn Camera"
settingsKey = "worldview/camera/holdToTurn" settingsKey = "worldview/camera/holdToTurn"
_stickyAction = None
mouseDragStart = None
_stickyThreshold = 0.25
def __init__(self, stickyAction):
super(CameraPanMouseAction, self).__init__()
self._stickyAction = stickyAction
def buttonPressEvent(self, event): def buttonPressEvent(self, event):
self.downTime = time.time()
x = event.x() x = event.x()
y = event.y() y = event.y()
self.mouseDragStart = x, y self.mouseDragStart = x, y
def buttonReleaseEvent(self, event):
if event.view.stickyMouselook and time.time() - self.downTime < self._stickyThreshold:
self._stickyAction.toggleSticky(event)
self.mouseDragStart = None
sensitivity = .15 sensitivity = .15
def mouseMoveEvent(self, event): def mouseMoveEvent(self, event):
@ -477,10 +607,6 @@ class CameraPanMouseAction(ViewAction):
self.mouseDragStart = (x, y) self.mouseDragStart = (x, y)
def buttonReleaseEvent(self, event):
self.mouseDragStart = None
class CameraMoveMouseAction(ViewAction): class CameraMoveMouseAction(ViewAction):
button = Qt.MiddleButton button = Qt.MiddleButton
mouseDragStart = None mouseDragStart = None
@ -512,6 +638,5 @@ class CameraMoveMouseAction(ViewAction):
self.mouseDragStart = (x, y) self.mouseDragStart = (x, y)
def buttonReleaseEvent(self, event): def buttonReleaseEvent(self, event):
self.mouseDragStart = None self.mouseDragStart = None

View File

@ -149,7 +149,7 @@ class ButtonModifierInput(QtGui.QPushButton):
class ViewControls(QtGui.QFrame): class ViewControls(QtGui.QFrame):
def __init__(self, worldView, *args, **kwargs): def __init__(self, worldView, auxWidget=None, *args, **kwargs):
""" """
Popup window for quickly reviewing and assigning movement controls for a world view. Popup window for quickly reviewing and assigning movement controls for a world view.
@ -178,7 +178,11 @@ class ViewControls(QtGui.QFrame):
self.controlsButton.setDefaultAction(action) self.controlsButton.setDefaultAction(action)
self.unlockButton = QtGui.QPushButton(self.tr("Edit Controls"), clicked=self.toggleUnlockControls) self.unlockButton = QtGui.QPushButton(self.tr("Edit Controls"), clicked=self.toggleUnlockControls)
self.setLayout(Column(layout, self.unlockButton)) col = [layout, self.unlockButton]
if auxWidget is not None:
col.append(auxWidget)
self.setLayout(Column(*col))
self.unlocked = False self.unlocked = False
def toggleUnlockControls(self): def toggleUnlockControls(self):