Right-click now toggles mouselook
This can be disabled with the "Sticky Mouselook" option.
This commit is contained in:
parent
12dae3d174
commit
dfe9aa9ddc
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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):
|
||||||
|
Reference in New Issue
Block a user