From 776b1071a01a1df2d71b4bf15a1679f72991c51d Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Mon, 31 Aug 2020 15:44:06 -0700 Subject: [PATCH 1/7] try to do it without QCursor::setPos --- .../resources/controllers/keyboardMouse.json | 18 +++++++++++ interface/src/Application.cpp | 20 +++++++++++- interface/src/Application.h | 1 + libraries/shared/src/shared/Camera.h | 31 +++++++++++++++++++ 4 files changed, 69 insertions(+), 1 deletion(-) diff --git a/interface/resources/controllers/keyboardMouse.json b/interface/resources/controllers/keyboardMouse.json index 11c80a4dd2..9449d37f7d 100644 --- a/interface/resources/controllers/keyboardMouse.json +++ b/interface/resources/controllers/keyboardMouse.json @@ -213,6 +213,15 @@ ] }, + { "from": { "makeAxis" : ["Keyboard.MouseMoveLeft", "Keyboard.MouseMoveRight"] }, + "to": "Actions.DeltaYaw", + "when": "Application.CaptureMouse", + "filters": + [ + { "type": "scale", "scale": 0.2 } + ] + }, + { "from": { "makeAxis" : ["Keyboard.MouseMoveUp", "Keyboard.MouseMoveDown"] }, "when": ["!Application.CameraSelfie", "!Application.CameraLookAt", "Keyboard.RightMouseButton"], "to": "Actions.DeltaPitch", @@ -222,6 +231,15 @@ ] }, + { "from": { "makeAxis" : ["Keyboard.MouseMoveUp", "Keyboard.MouseMoveDown"] }, + "to": "Actions.DeltaPitch", + "when": "Application.CaptureMouse", + "filters": + [ + { "type": "scale", "scale": 0.2 } + ] + }, + { "from": { "makeAxis" : ["Keyboard.MouseMoveUp", "Keyboard.MouseMoveDown"] }, "when": ["Application.CameraLookAt", "Keyboard.RightMouseButton"], "to": "Actions.DeltaPitch", diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cc2aed7f53..024df2343b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -680,6 +680,7 @@ private: * CameraIndependentnumbernumberThe camera is in independent mode. * CameraEntitynumbernumberThe camera is in entity mode. * InHMDnumbernumberThe user is in HMD mode. + * CaptureMousenumbernumberThe mouse is captured. * AdvancedMovementnumbernumberAdvanced movement (walking) controls are * enabled. * StrafeEnablednumbernumberStrafing is enabled @@ -715,6 +716,7 @@ static const QString STATE_PLATFORM_ANDROID = "PlatformAndroid"; static const QString STATE_LEFT_HAND_DOMINANT = "LeftHandDominant"; static const QString STATE_RIGHT_HAND_DOMINANT = "RightHandDominant"; static const QString STATE_STRAFE_ENABLED = "StrafeEnabled"; +static const QString STATE_CAMERA_CAPTURE_MOUSE = "CaptureMouse"; // Statically provided display and input plugins extern DisplayPluginList getDisplayPlugins(); @@ -918,7 +920,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); controller::StateController::setStateVariables({ { STATE_IN_HMD, STATE_CAMERA_FULL_SCREEN_MIRROR, STATE_CAMERA_FIRST_PERSON, STATE_CAMERA_FIRST_PERSON_LOOK_AT, STATE_CAMERA_THIRD_PERSON, - STATE_CAMERA_ENTITY, STATE_CAMERA_INDEPENDENT, STATE_CAMERA_LOOK_AT, STATE_CAMERA_SELFIE, + STATE_CAMERA_ENTITY, STATE_CAMERA_INDEPENDENT, STATE_CAMERA_LOOK_AT, STATE_CAMERA_SELFIE, STATE_CAMERA_CAPTURE_MOUSE, STATE_SNAP_TURN, STATE_ADVANCED_MOVEMENT_CONTROLS, STATE_GROUNDED, STATE_NAV_FOCUSED, STATE_PLATFORM_WINDOWS, STATE_PLATFORM_MAC, STATE_PLATFORM_ANDROID, STATE_LEFT_HAND_DOMINANT, STATE_RIGHT_HAND_DOMINANT, STATE_STRAFE_ENABLED } }); DependencyManager::set(); @@ -1891,6 +1893,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _applicationStateDevice->setInputVariant(STATE_CAMERA_INDEPENDENT, []() -> float { return qApp->getCamera().getMode() == CAMERA_MODE_INDEPENDENT ? 1 : 0; }); + _applicationStateDevice->setInputVariant(STATE_CAMERA_CAPTURE_MOUSE, []() -> float { + return qApp->getCamera().getCaptureMouse() ? 1 : 0; + }); _applicationStateDevice->setInputVariant(STATE_SNAP_TURN, []() -> float { return qApp->getMyAvatar()->getSnapTurn() ? 1 : 0; }); @@ -2406,6 +2411,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo updateSystemTabletMode(); connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged); + connect(&_myCamera, &Camera::captureMouseUpdated, this, &Application::captureMouseChanged); DependencyManager::get()->setShouldPickHUDOperator([]() { return DependencyManager::get()->isHMDMode(); }); DependencyManager::get()->setCalculatePos2DFromHUDOperator([this](const glm::vec3& intersection) { @@ -5910,6 +5916,18 @@ void Application::cameraModeChanged() { cameraMenuChanged(); } +void Application::captureMouseChanged() { + if (_myCamera.getCaptureMouse()) { + // we want to grab the mouse here so that no other widgets get events, and also hide the mouse, but these don't work: + //_glWidget->grabMouse(); + //QCursor::setShape(Qt::CursorShape::BlankCursor); + } else { + // we want to release the mouse here so that other widgets get events, and also show the mouse, but these don't work: + //_glWidget->releaseMouse(); + //QCursor::setShape(Qt::CursorShape::ArrowCursor); + } +} + void Application::changeViewAsNeeded(float boomLength) { // Switch between first and third person views as needed // This is called when the boom length has changed diff --git a/interface/src/Application.h b/interface/src/Application.h index f42696cda0..50ae9860fa 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -430,6 +430,7 @@ public slots: void cycleCamera(); void cameraModeChanged(); void cameraMenuChanged(); + void captureMouseChanged(); void toggleOverlays(); void setOverlaysVisible(bool visible); Q_INVOKABLE void centerUI(); diff --git a/libraries/shared/src/shared/Camera.h b/libraries/shared/src/shared/Camera.h index 48cd814d86..2564a3f7c8 100644 --- a/libraries/shared/src/shared/Camera.h +++ b/libraries/shared/src/shared/Camera.h @@ -43,6 +43,7 @@ class Camera : public QObject { Q_PROPERTY(glm::quat orientation READ getOrientation WRITE setOrientation) Q_PROPERTY(QString mode READ getModeString WRITE setModeString NOTIFY modeUpdated) Q_PROPERTY(QVariantMap frustum READ getViewFrustum CONSTANT) + Q_PROPERTY(bool captureMouse READ getCaptureMouse WRITE setCaptureMouse NOTIFY captureMouseUpdated) public: Camera(); @@ -110,6 +111,20 @@ public slots: */ void setOrientation(const glm::quat& orientation); + /**jsdoc + * Gets the current mouse capture state. + * @function Camera.getMouseCapture + * @returns {boolean} The current mouse capture state. + */ + bool getCaptureMouse() const { return _captureMouse; } + + /**jsdoc + * Sets mouse capture state. + * @function Camera.setCaptureMouse + * @param {boolean} captureMouse - Whether or not to capture the mouse. + */ + void setCaptureMouse(bool captureMouse) { _captureMouse = captureMouse; } + /**jsdoc * Computes a {@link PickRay} based on the current camera configuration and the specified x, y position on the * screen. The {@link PickRay} can be used in functions such as {@link Entities.findRayIntersection} and @@ -181,6 +196,20 @@ signals: */ void modeUpdated(const QString& newMode); + /**jsdoc + * Triggered when the camera mouse capture state changes. + * @function Camera.captureMouseUpdated + * @param {boolean} newCaptureMouse - The new mouse capture state. + * @returns {Signal} + * @example Report mouse capture state changes. + * function onCaptureMouseUpdated(newCaptureMouse) { + * print("The mouse capture has changed to " + newCaptureMouse); + * } + * + * Camera.captureMouseUpdated.connect(onCaptureMouseUpdated); + */ + void captureMouseUpdated(bool newCaptureMouse); + private: void recompose(); void decompose(); @@ -194,6 +223,8 @@ private: glm::quat _orientation; bool _isKeepLookingAt{ false }; glm::vec3 _lookingAt; + + bool _captureMouse { false }; }; #endif // hifi_Camera_h From 5281f89d0ddadb6d248bf5eed5caca98f9ac25c1 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Wed, 2 Sep 2020 11:28:43 -0700 Subject: [PATCH 2/7] FUUUUUUUCK FINALLY --- .../resources/controllers/keyboardMouse.json | 128 +++--------------- interface/src/Application.cpp | 30 ++-- interface/src/Application.h | 6 +- .../src/display-plugins/CompositorHelper.cpp | 1 - .../src/input-plugins/KeyboardMouseDevice.cpp | 20 ++- .../src/input-plugins/KeyboardMouseDevice.h | 4 +- libraries/shared/src/shared/Camera.h | 2 +- 7 files changed, 61 insertions(+), 130 deletions(-) diff --git a/interface/resources/controllers/keyboardMouse.json b/interface/resources/controllers/keyboardMouse.json index 9449d37f7d..a91151f4e5 100644 --- a/interface/resources/controllers/keyboardMouse.json +++ b/interface/resources/controllers/keyboardMouse.json @@ -3,9 +3,9 @@ "channels": [ { "from": "Keyboard.A", "when": ["Keyboard.RightMouseButton", "!Keyboard.Control"], "to": "Actions.LATERAL_LEFT" }, { "from": "Keyboard.D", "when": ["Keyboard.RightMouseButton", "!Keyboard.Control"], "to": "Actions.LATERAL_RIGHT" }, - { "from": "Keyboard.E", "when": ["!Application.CameraSelfie", "!Keyboard.Control"], "to": "Actions.LATERAL_RIGHT" }, - { "from": "Keyboard.Q", "when": ["!Application.CameraSelfie", "!Keyboard.Control"], "to": "Actions.LATERAL_LEFT" }, + { "from": "Keyboard.Q", "when": ["!Application.CameraSelfie", "!Keyboard.Control", "!Application.CaptureMouse"], "to": "Actions.LATERAL_LEFT" }, { "from": "Keyboard.Q", "when": ["Application.CameraSelfie", "!Keyboard.Control"], "to": "Actions.LATERAL_RIGHT" }, + { "from": "Keyboard.E", "when": ["!Application.CameraSelfie", "!Keyboard.Control", "!Application.CaptureMouse"], "to": "Actions.LATERAL_RIGHT" }, { "from": "Keyboard.E", "when": ["Application.CameraSelfie", "!Keyboard.Control"], "to": "Actions.LATERAL_LEFT" }, { "from": "Keyboard.T", "when": "!Keyboard.Control", "to": "Actions.TogglePushToTalk" }, @@ -72,46 +72,20 @@ { "from": { "makeAxis" : [ ["Keyboard.Left"], ["Keyboard.Right"] - ] + ] }, - "when": ["Application.CameraFirstPerson", "!Keyboard.Shift"], + "when": ["!Application.CameraFSM", "!Application.CameraIndependent", "!Application.CameraEntity", "!Application.CaptureMouse", "!Keyboard.Shift"], "to": "Actions.Yaw" }, - { "from": { "makeAxis" : [ - ["Keyboard.Left"], - ["Keyboard.Right"] - ] - }, - "when": ["Application.CameraFirstPersonLookat", "!Keyboard.Shift"], - "to": "Actions.Yaw" + { "from": "Keyboard.Left", + "when": ["!Application.CameraFSM", "!Application.CameraIndependent", "!Application.CameraEntity", "Application.CaptureMouse", "!Keyboard.Shift"], + "to": "Actions.LATERAL_LEFT" }, - { "from": { "makeAxis" : [ - ["Keyboard.Left"], - ["Keyboard.Right"] - ] - }, - "when": ["Application.CameraThirdPerson", "!Keyboard.Shift"], - "to": "Actions.Yaw" - }, - - { "from": { "makeAxis" : [ - ["Keyboard.Left"], - ["Keyboard.Right"] - ] - }, - "when": ["Application.CameraLookAt", "!Keyboard.Shift"], - "to": "Actions.Yaw" - }, - - { "from": { "makeAxis" : [ - ["Keyboard.Left"], - ["Keyboard.Right"] - ] - }, - "when": ["Application.CameraSelfie", "!Keyboard.Shift"], - "to": "Actions.Yaw" + { "from": "Keyboard.Right", + "when": ["!Application.CameraFSM", "!Application.CameraIndependent", "!Application.CameraEntity", "Application.CaptureMouse", "!Keyboard.Shift"], + "to": "Actions.LATERAL_RIGHT" }, { "from": { "makeAxis" : [ @@ -119,53 +93,18 @@ ["Keyboard.D"] ] }, - "when": ["Application.CameraFirstPerson", "!Keyboard.Control"], + "when": ["!Application.CameraFSM", "!Application.CameraIndependent", "!Application.CameraEntity", "!Application.CaptureMouse", "!Keyboard.Control"], "to": "Actions.Yaw" }, - { "from": { "makeAxis" : [ - ["Keyboard.A"], - ["Keyboard.D"] - ] - }, - "when": ["Application.CameraFirstPersonLookat", "!Keyboard.Control"], - "to": "Actions.Yaw" + { "from": "Keyboard.A", + "when": ["!Application.CameraFSM", "!Application.CameraIndependent", "!Application.CameraEntity", "Application.CaptureMouse", "!Keyboard.Control"], + "to": "Actions.LATERAL_LEFT" }, - { "from": { "makeAxis" : [ - ["Keyboard.A"], - ["Keyboard.D"] - ] - }, - "when": ["Application.CameraThirdPerson", "!Keyboard.Control"], - "to": "Actions.Yaw" - }, - - { "from": { "makeAxis" : [ - ["Keyboard.A"], - ["Keyboard.D"] - ] - }, - "when": ["Application.CameraLookAt", "!Keyboard.Control"], - "to": "Actions.Yaw" - }, - - { "from": { "makeAxis" : [ - ["Keyboard.A"], - ["Keyboard.D"] - ] - }, - "when": ["Application.CameraSelfie", "!Keyboard.Control"], - "to": "Actions.Yaw" - }, - - { "from": { "makeAxis" : [ - ["Keyboard.TouchpadLeft"], - ["Keyboard.TouchpadRight"] - ] - }, - "when": "Application.CameraFirstPerson", - "to": "Actions.Yaw" + { "from": "Keyboard.D", + "when": ["!Application.CameraFSM", "!Application.CameraIndependent", "!Application.CameraEntity", "Application.CaptureMouse", "!Keyboard.Control"], + "to": "Actions.LATERAL_RIGHT" }, { "from": { "makeAxis" : [ @@ -173,39 +112,12 @@ ["Keyboard.TouchpadRight"] ] }, - "when": "Application.CameraFirstPersonLookat", - "to": "Actions.Yaw" - }, - - { "from": { "makeAxis" : [ - ["Keyboard.TouchpadLeft"], - ["Keyboard.TouchpadRight"] - ] - }, - "when": "Application.CameraThirdPerson", - "to": "Actions.Yaw" - }, - - { "from": { "makeAxis" : [ - ["Keyboard.TouchpadLeft"], - ["Keyboard.TouchpadRight"] - ] - }, - "when": "Application.CameraLookAt", - "to": "Actions.Yaw" - }, - - { "from": { "makeAxis" : [ - ["Keyboard.TouchpadLeft"], - ["Keyboard.TouchpadRight"] - ] - }, - "when": "Application.CameraSelfie", + "when": ["!Application.CameraFSM", "!Application.CameraIndependent", "!Application.CameraEntity"], "to": "Actions.Yaw" }, { "from": { "makeAxis" : ["Keyboard.MouseMoveLeft", "Keyboard.MouseMoveRight"] }, - "when": "Keyboard.RightMouseButton", + "when": ["Keyboard.RightMouseButton", "!Application.CaptureMouse"], "to": "Actions.DeltaYaw", "filters": [ @@ -223,7 +135,7 @@ }, { "from": { "makeAxis" : ["Keyboard.MouseMoveUp", "Keyboard.MouseMoveDown"] }, - "when": ["!Application.CameraSelfie", "!Application.CameraLookAt", "Keyboard.RightMouseButton"], + "when": ["!Application.CameraSelfie", "!Application.CameraLookAt", "!Application.CaptureMouse", "Keyboard.RightMouseButton"], "to": "Actions.DeltaPitch", "filters": [ diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 024df2343b..e46182ed83 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4699,6 +4699,11 @@ void Application::maybeToggleMenuVisible(QMouseEvent* event) const { void Application::mouseMoveEvent(QMouseEvent* event) { PROFILE_RANGE(app_input_mouse, __FUNCTION__); + if (_ignoreMouseMove) { + _ignoreMouseMove = false; + return; + } + maybeToggleMenuVisible(event); auto& compositor = getApplicationCompositor(); @@ -4744,7 +4749,7 @@ void Application::mouseMoveEvent(QMouseEvent* event) { } if (_keyboardMouseDevice->isActive()) { - _keyboardMouseDevice->mouseMoveEvent(event); + _keyboardMouseDevice->mouseMoveEvent(event, _captureMouse, _mouseCaptureTarget); } } @@ -5916,15 +5921,13 @@ void Application::cameraModeChanged() { cameraMenuChanged(); } -void Application::captureMouseChanged() { - if (_myCamera.getCaptureMouse()) { - // we want to grab the mouse here so that no other widgets get events, and also hide the mouse, but these don't work: - //_glWidget->grabMouse(); - //QCursor::setShape(Qt::CursorShape::BlankCursor); +void Application::captureMouseChanged(bool captureMouse) { + _captureMouse = captureMouse; + if (_captureMouse) { + _glWidget->setCursor(QCursor(Qt::BlankCursor)); } else { - // we want to release the mouse here so that other widgets get events, and also show the mouse, but these don't work: - //_glWidget->releaseMouse(); - //QCursor::setShape(Qt::CursorShape::ArrowCursor); + _mouseCaptureTarget = QPointF(NAN, NAN); + _glWidget->unsetCursor(); } } @@ -6278,6 +6281,15 @@ void Application::update(float deltaTime) { PROFILE_ASYNC_END(app, "Scene Loading", ""); } + if (_captureMouse) { + QPoint point = _glWidget->mapToGlobal(_glWidget->geometry().center()); + if (QCursor::pos() != point) { + _mouseCaptureTarget = point; + _ignoreMouseMove = true; + QCursor::setPos(point); + } + } + auto myAvatar = getMyAvatar(); { PerformanceTimer perfTimer("devices"); diff --git a/interface/src/Application.h b/interface/src/Application.h index 50ae9860fa..d66d9c32b3 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -430,7 +430,7 @@ public slots: void cycleCamera(); void cameraModeChanged(); void cameraMenuChanged(); - void captureMouseChanged(); + void captureMouseChanged(bool captureMouse); void toggleOverlays(); void setOverlaysVisible(bool visible); Q_INVOKABLE void centerUI(); @@ -756,7 +756,9 @@ private: bool _settingsLoaded { false }; - bool _fakedMouseEvent { false }; + bool _captureMouse { false }; + bool _ignoreMouseMove { false }; + QPointF _mouseCaptureTarget { NAN, NAN }; bool _isMissingSequenceNumbers { false }; diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp index a1138b3018..0cc3e5216e 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp @@ -213,7 +213,6 @@ void CompositorHelper::setAllowMouseCapture(bool capture) { _allowMouseCapture = capture; emit allowMouseCaptureChanged(); } - _allowMouseCapture = capture; } void CompositorHelper::handleLeaveEvent() { diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index c436a5b510..a49c822014 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -36,13 +36,12 @@ void KeyboardMouseDevice::pluginUpdate(float deltaTime, const controller::InputC _inputDevice->_axisStateMap[MOUSE_AXIS_X].value = _lastCursor.x(); _inputDevice->_axisStateMap[MOUSE_AXIS_Y].value = _lastCursor.y(); - QPoint currentMove = _lastCursor - _previousCursor; - updateDeltaAxisValue(MOUSE_AXIS_X_POS, currentMove.x() > 0 ? currentMove.x() : 0.0f); - updateDeltaAxisValue(MOUSE_AXIS_X_NEG, currentMove.x() < 0 ? -currentMove.x() : 0.0f); + updateDeltaAxisValue(MOUSE_AXIS_X_POS, _accumulatedMove.x() > 0 ? _accumulatedMove.x() : 0.0f); + updateDeltaAxisValue(MOUSE_AXIS_X_NEG, _accumulatedMove.x() < 0 ? -_accumulatedMove.x() : 0.0f); // Y mouse is inverted positive is pointing up the screen - updateDeltaAxisValue(MOUSE_AXIS_Y_POS, currentMove.y() < 0 ? -currentMove.y() : 0.0f); - updateDeltaAxisValue(MOUSE_AXIS_Y_NEG, currentMove.y() > 0 ? currentMove.y() : 0.0f); - _previousCursor = _lastCursor; + updateDeltaAxisValue(MOUSE_AXIS_Y_POS, _accumulatedMove.y() < 0 ? -_accumulatedMove.y() : 0.0f); + updateDeltaAxisValue(MOUSE_AXIS_Y_NEG, _accumulatedMove.y() > 0 ? _accumulatedMove.y() : 0.0f); + _accumulatedMove = QPoint(0.0f, 0.0f); }); // For touch event, we need to check that the last event is not too long ago @@ -113,9 +112,16 @@ void KeyboardMouseDevice::eraseMouseClicked() { _inputDevice->_buttonPressedMap.erase(_inputDevice->makeInput(Qt::RightButton, true).getChannel()); } -void KeyboardMouseDevice::mouseMoveEvent(QMouseEvent* event) { +void KeyboardMouseDevice::mouseMoveEvent(QMouseEvent* event, bool capture, QPointF captureTarget) { QPoint currentPos = event->pos(); + if (!capture) { + _accumulatedMove += currentPos - _lastCursor; + } else if (!isNaN(captureTarget.x())) { + QPointF change = event->globalPos() - captureTarget; + _accumulatedMove += QPoint(change.x(), change.y()); + } + // FIXME - this has the characteristic that it will show large jumps when you move the cursor // outside of the application window, because we don't get MouseEvents when the cursor is outside // of the application window. diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h index 4286ced477..158e2f594f 100644 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h @@ -79,7 +79,7 @@ public: void keyPressEvent(QKeyEvent* event); void keyReleaseEvent(QKeyEvent* event); - void mouseMoveEvent(QMouseEvent* event); + void mouseMoveEvent(QMouseEvent* event, bool capture, QPointF captureTarget); void mousePressEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event); void eraseMouseClicked(); @@ -123,7 +123,7 @@ public: protected: QPoint _lastCursor; - QPoint _previousCursor; + QPoint _accumulatedMove; QPoint _mousePressPos; quint64 _mousePressTime; qreal _lastTotalScaleFactor; diff --git a/libraries/shared/src/shared/Camera.h b/libraries/shared/src/shared/Camera.h index 2564a3f7c8..d8ed98c0a2 100644 --- a/libraries/shared/src/shared/Camera.h +++ b/libraries/shared/src/shared/Camera.h @@ -123,7 +123,7 @@ public slots: * @function Camera.setCaptureMouse * @param {boolean} captureMouse - Whether or not to capture the mouse. */ - void setCaptureMouse(bool captureMouse) { _captureMouse = captureMouse; } + void setCaptureMouse(bool captureMouse) { _captureMouse = captureMouse; emit captureMouseUpdated(captureMouse); } /**jsdoc * Computes a {@link PickRay} based on the current camera configuration and the specified x, y position on the From 1403f8908f59417de53ccfad4005c217b4106936 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Wed, 2 Sep 2020 11:58:22 -0700 Subject: [PATCH 3/7] don't capture mouse when other windows or menus are active --- interface/src/Application.cpp | 18 +++++++++++++++++- interface/src/Application.h | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e46182ed83..270013a80d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5921,6 +5921,22 @@ void Application::cameraModeChanged() { cameraMenuChanged(); } +bool Application::shouldCaptureMouse() const { + if (!_captureMouse) { + return false; + } + + if (!_glWidget->isActiveWindow()) { + return false; + } + + if (ui::Menu::isSomeSubmenuShown()) { + return false; + } + + return true; +} + void Application::captureMouseChanged(bool captureMouse) { _captureMouse = captureMouse; if (_captureMouse) { @@ -6281,7 +6297,7 @@ void Application::update(float deltaTime) { PROFILE_ASYNC_END(app, "Scene Loading", ""); } - if (_captureMouse) { + if (shouldCaptureMouse()) { QPoint point = _glWidget->mapToGlobal(_glWidget->geometry().center()); if (QCursor::pos() != point) { _mouseCaptureTarget = point; diff --git a/interface/src/Application.h b/interface/src/Application.h index d66d9c32b3..7ab62016c8 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -603,6 +603,7 @@ private: void maybeToggleMenuVisible(QMouseEvent* event) const; void toggleTabletUI(bool shouldOpen = false) const; + bool shouldCaptureMouse() const; void userKickConfirmation(const QUuid& nodeID); From 932f5dbfb313ffb65bdb3bd67bcbc9d34c7f55cc Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sun, 6 Sep 2020 22:41:17 -0700 Subject: [PATCH 4/7] CR --- interface/src/Application.cpp | 14 +------------- .../src/display-plugins/CompositorHelper.cpp | 1 + .../src/display-plugins/CompositorHelper.h | 1 + .../src/input-plugins/KeyboardMouseDevice.cpp | 1 + .../src/input-plugins/KeyboardMouseDevice.h | 1 + libraries/shared/src/shared/Camera.h | 5 +++-- 6 files changed, 8 insertions(+), 15 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 270013a80d..a83b2c4431 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5922,19 +5922,7 @@ void Application::cameraModeChanged() { } bool Application::shouldCaptureMouse() const { - if (!_captureMouse) { - return false; - } - - if (!_glWidget->isActiveWindow()) { - return false; - } - - if (ui::Menu::isSomeSubmenuShown()) { - return false; - } - - return true; + return _captureMouse && _glWidget->isActiveWindow() && !ui::Menu::isSomeSubmenuShown(); } void Application::captureMouseChanged(bool captureMouse) { diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp index 0cc3e5216e..9b6946bbcc 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp @@ -1,6 +1,7 @@ // // Created by Benjamin Arnold on 5/27/14. // Copyright 2014 High Fidelity, Inc. +// Copyright 2020 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.h b/libraries/display-plugins/src/display-plugins/CompositorHelper.h index 1279050a57..c45119fd63 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.h +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.h @@ -1,6 +1,7 @@ // // Created by Bradley Austin Davis Arnold on 2015/06/13 // Copyright 2015 High Fidelity, Inc. +// Copyright 2020 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index a49c822014..c7c5543d44 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -4,6 +4,7 @@ // // Created by Sam Gateau on 4/27/15. // Copyright 2015 High Fidelity, Inc. +// Copyright 2020 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h index 158e2f594f..216194a712 100644 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h @@ -4,6 +4,7 @@ // // Created by Sam Gateau on 4/27/15. // Copyright 2015 High Fidelity, Inc. +// Copyright 2020 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html diff --git a/libraries/shared/src/shared/Camera.h b/libraries/shared/src/shared/Camera.h index d8ed98c0a2..76d344c21c 100644 --- a/libraries/shared/src/shared/Camera.h +++ b/libraries/shared/src/shared/Camera.h @@ -3,6 +3,7 @@ // interface/src // // Copyright 2013 High Fidelity, Inc. +// Copyright 2020 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -119,9 +120,9 @@ public slots: bool getCaptureMouse() const { return _captureMouse; } /**jsdoc - * Sets mouse capture state. + * Sets the mouse capture state. * @function Camera.setCaptureMouse - * @param {boolean} captureMouse - Whether or not to capture the mouse. + * @param {boolean} captureMouse - true to capture the mouse, false to release the mouse. */ void setCaptureMouse(bool captureMouse) { _captureMouse = captureMouse; emit captureMouseUpdated(captureMouse); } From 9546cebe3cae48dbf186fe5f620b040a2fb241f6 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Wed, 9 Sep 2020 08:32:54 -0700 Subject: [PATCH 5/7] CR --- interface/src/Application.cpp | 10 ++++++---- libraries/shared/src/shared/Camera.h | 4 +++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a83b2c4431..795325d761 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -680,7 +680,9 @@ private: * CameraIndependentnumbernumberThe camera is in independent mode. * CameraEntitynumbernumberThe camera is in entity mode. * InHMDnumbernumberThe user is in HMD mode. - * CaptureMousenumbernumberThe mouse is captured. + * CaptureMousenumbernumberThe mouse is captured. In this mode, + * the mouse is invisible and cannot leave the bounds of Interface, as long as Interface is the active window and + * no menu item is selected. * AdvancedMovementnumbernumberAdvanced movement (walking) controls are * enabled. * StrafeEnablednumbernumberStrafing is enabled @@ -716,7 +718,7 @@ static const QString STATE_PLATFORM_ANDROID = "PlatformAndroid"; static const QString STATE_LEFT_HAND_DOMINANT = "LeftHandDominant"; static const QString STATE_RIGHT_HAND_DOMINANT = "RightHandDominant"; static const QString STATE_STRAFE_ENABLED = "StrafeEnabled"; -static const QString STATE_CAMERA_CAPTURE_MOUSE = "CaptureMouse"; +static const QString STATE_CAPTURE_MOUSE = "CaptureMouse"; // Statically provided display and input plugins extern DisplayPluginList getDisplayPlugins(); @@ -920,7 +922,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); controller::StateController::setStateVariables({ { STATE_IN_HMD, STATE_CAMERA_FULL_SCREEN_MIRROR, STATE_CAMERA_FIRST_PERSON, STATE_CAMERA_FIRST_PERSON_LOOK_AT, STATE_CAMERA_THIRD_PERSON, - STATE_CAMERA_ENTITY, STATE_CAMERA_INDEPENDENT, STATE_CAMERA_LOOK_AT, STATE_CAMERA_SELFIE, STATE_CAMERA_CAPTURE_MOUSE, + STATE_CAMERA_ENTITY, STATE_CAMERA_INDEPENDENT, STATE_CAMERA_LOOK_AT, STATE_CAMERA_SELFIE, STATE_CAPTURE_MOUSE, STATE_SNAP_TURN, STATE_ADVANCED_MOVEMENT_CONTROLS, STATE_GROUNDED, STATE_NAV_FOCUSED, STATE_PLATFORM_WINDOWS, STATE_PLATFORM_MAC, STATE_PLATFORM_ANDROID, STATE_LEFT_HAND_DOMINANT, STATE_RIGHT_HAND_DOMINANT, STATE_STRAFE_ENABLED } }); DependencyManager::set(); @@ -1893,7 +1895,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _applicationStateDevice->setInputVariant(STATE_CAMERA_INDEPENDENT, []() -> float { return qApp->getCamera().getMode() == CAMERA_MODE_INDEPENDENT ? 1 : 0; }); - _applicationStateDevice->setInputVariant(STATE_CAMERA_CAPTURE_MOUSE, []() -> float { + _applicationStateDevice->setInputVariant(STATE_CAPTURE_MOUSE, []() -> float { return qApp->getCamera().getCaptureMouse() ? 1 : 0; }); _applicationStateDevice->setInputVariant(STATE_SNAP_TURN, []() -> float { diff --git a/libraries/shared/src/shared/Camera.h b/libraries/shared/src/shared/Camera.h index 76d344c21c..0dc8703b2d 100644 --- a/libraries/shared/src/shared/Camera.h +++ b/libraries/shared/src/shared/Camera.h @@ -120,7 +120,9 @@ public slots: bool getCaptureMouse() const { return _captureMouse; } /**jsdoc - * Sets the mouse capture state. + * Sets the mouse capture state. When true, the mouse will be invisible and cannot leave the bounds of + * Interface, as long as Interface is the active window and no menu item is selected. When false, the mouse + * will behave normally. * @function Camera.setCaptureMouse * @param {boolean} captureMouse - true to capture the mouse, false to release the mouse. */ From e4f32f1cea7c57d6a3273a360eb762fc05d55443 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sat, 19 Sep 2020 11:23:59 -0700 Subject: [PATCH 6/7] add camera sensitivity slider --- interface/src/Application.cpp | 4 ++-- interface/src/ui/PreferencesDialog.cpp | 10 ++++++++++ libraries/shared/src/shared/Camera.h | 16 ++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 795325d761..d8c4dde1a8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6351,8 +6351,8 @@ void Application::update(float deltaTime) { if (deltaTime > FLT_EPSILON && userInputMapper->getActionState(controller::Action::TRANSLATE_CAMERA_Z) == 0.0f) { myAvatar->setDriveKey(MyAvatar::PITCH, -1.0f * userInputMapper->getActionState(controller::Action::PITCH)); myAvatar->setDriveKey(MyAvatar::YAW, -1.0f * userInputMapper->getActionState(controller::Action::YAW)); - myAvatar->setDriveKey(MyAvatar::DELTA_PITCH, -1.0f * userInputMapper->getActionState(controller::Action::DELTA_PITCH)); - myAvatar->setDriveKey(MyAvatar::DELTA_YAW, -1.0f * userInputMapper->getActionState(controller::Action::DELTA_YAW)); + myAvatar->setDriveKey(MyAvatar::DELTA_PITCH, -_myCamera.getSensitivity() * userInputMapper->getActionState(controller::Action::DELTA_PITCH)); + myAvatar->setDriveKey(MyAvatar::DELTA_YAW, -_myCamera.getSensitivity() * userInputMapper->getActionState(controller::Action::DELTA_YAW)); myAvatar->setDriveKey(MyAvatar::STEP_YAW, -1.0f * userInputMapper->getActionState(controller::Action::STEP_YAW)); } } diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 9f8a8ec013..79d9ebaa5c 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -358,6 +358,16 @@ void setupPreferences() { preference->setItems(items); preferences->addPreference(preference); } + { + auto getter = [myAvatar]()->float { return qApp->getCamera().getSensitivity(); }; + auto setter = [myAvatar](float value) { qApp->getCamera().setSensitivity(value); }; + auto preference = new SpinnerSliderPreference(VR_MOVEMENT, "Camera Sensitivity", getter, setter); + preference->setMin(0.01f); + preference->setMax(5.0f); + preference->setStep(0.1); + preference->setDecimals(2); + preferences->addPreference(preference); + } { auto getter = [myAvatar]()->int { return myAvatar->getControlScheme(); }; auto setter = [myAvatar](int index) { myAvatar->setControlScheme(index); }; diff --git a/libraries/shared/src/shared/Camera.h b/libraries/shared/src/shared/Camera.h index 0dc8703b2d..f6ce9be2d8 100644 --- a/libraries/shared/src/shared/Camera.h +++ b/libraries/shared/src/shared/Camera.h @@ -45,6 +45,7 @@ class Camera : public QObject { Q_PROPERTY(QString mode READ getModeString WRITE setModeString NOTIFY modeUpdated) Q_PROPERTY(QVariantMap frustum READ getViewFrustum CONSTANT) Q_PROPERTY(bool captureMouse READ getCaptureMouse WRITE setCaptureMouse NOTIFY captureMouseUpdated) + Q_PROPERTY(float sensitivity READ getSensitivity WRITE setSensitivity) public: Camera(); @@ -128,6 +129,20 @@ public slots: */ void setCaptureMouse(bool captureMouse) { _captureMouse = captureMouse; emit captureMouseUpdated(captureMouse); } + /**jsdoc + * Gets the current camera sensitivity. + * @function Camera.getSensitivity + * @returns {boolean} The current camera sensitivity. + */ + float getSensitivity() const { return _sensitivity; } + + /**jsdoc + * Sets the camera sensitivity. Higher values mean that the camera will be more sensitive to mouse movements. + * @function Camera.setSensitivity + * @param {boolean} sensitivity - The desired camera sensitivity. + */ + void setSensitivity(float sensitivity) { _sensitivity = glm::max(0.0f, sensitivity); } + /**jsdoc * Computes a {@link PickRay} based on the current camera configuration and the specified x, y position on the * screen. The {@link PickRay} can be used in functions such as {@link Entities.findRayIntersection} and @@ -228,6 +243,7 @@ private: glm::vec3 _lookingAt; bool _captureMouse { false }; + float _sensitivity { 1.0f }; }; #endif // hifi_Camera_h From e028943645b2616662d24fe29259c50ec76604e1 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Fri, 9 Oct 2020 13:33:48 -0700 Subject: [PATCH 7/7] CR --- interface/src/Application.cpp | 2 +- interface/src/FancyCamera.h | 4 ++++ libraries/shared/src/shared/Camera.h | 25 +++++++++++++------------ 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d8c4dde1a8..866d9ffe66 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2413,7 +2413,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo updateSystemTabletMode(); connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged); - connect(&_myCamera, &Camera::captureMouseUpdated, this, &Application::captureMouseChanged); + connect(&_myCamera, &Camera::captureMouseChanged, this, &Application::captureMouseChanged); DependencyManager::get()->setShouldPickHUDOperator([]() { return DependencyManager::get()->isHMDMode(); }); DependencyManager::get()->setCalculatePos2DFromHUDOperator([this](const glm::vec3& intersection) { diff --git a/interface/src/FancyCamera.h b/interface/src/FancyCamera.h index 2a131d991f..afcd5197ff 100644 --- a/interface/src/FancyCamera.h +++ b/interface/src/FancyCamera.h @@ -36,6 +36,10 @@ class FancyCamera : public Camera { * @property {ViewFrustum} frustum - The camera frustum. * @property {Uuid} cameraEntity - The ID of the entity that is used for the camera position and orientation when the * camera is in entity mode. + * @property {boolean} captureMouse - The mouse capture state. When true, the mouse is invisible and cannot leave the bounds of + * Interface, as long as Interface is the active window and no menu item is selected. When false, the mouse + * behaves normally. + * @property {number} sensitivity - The current camera sensitivity. Must be positive. */ Q_PROPERTY(QUuid cameraEntity READ getCameraEntity WRITE setCameraEntity) diff --git a/libraries/shared/src/shared/Camera.h b/libraries/shared/src/shared/Camera.h index f6ce9be2d8..f494318c73 100644 --- a/libraries/shared/src/shared/Camera.h +++ b/libraries/shared/src/shared/Camera.h @@ -44,7 +44,7 @@ class Camera : public QObject { Q_PROPERTY(glm::quat orientation READ getOrientation WRITE setOrientation) Q_PROPERTY(QString mode READ getModeString WRITE setModeString NOTIFY modeUpdated) Q_PROPERTY(QVariantMap frustum READ getViewFrustum CONSTANT) - Q_PROPERTY(bool captureMouse READ getCaptureMouse WRITE setCaptureMouse NOTIFY captureMouseUpdated) + Q_PROPERTY(bool captureMouse READ getCaptureMouse WRITE setCaptureMouse NOTIFY captureMouseChanged) Q_PROPERTY(float sensitivity READ getSensitivity WRITE setSensitivity) public: @@ -115,31 +115,32 @@ public slots: /**jsdoc * Gets the current mouse capture state. - * @function Camera.getMouseCapture - * @returns {boolean} The current mouse capture state. + * @function Camera.getCaptureMouse + * @returns {boolean} true if the mouse is captured (is invisible and cannot leave the bounds of Interface, + * if Interface is the active window and no menu item is selected), false if the mouse is behaving normally. */ bool getCaptureMouse() const { return _captureMouse; } /**jsdoc - * Sets the mouse capture state. When true, the mouse will be invisible and cannot leave the bounds of + * Sets the mouse capture state. When true, the mouse is invisible and cannot leave the bounds of * Interface, as long as Interface is the active window and no menu item is selected. When false, the mouse - * will behave normally. + * behaves normally. * @function Camera.setCaptureMouse * @param {boolean} captureMouse - true to capture the mouse, false to release the mouse. */ - void setCaptureMouse(bool captureMouse) { _captureMouse = captureMouse; emit captureMouseUpdated(captureMouse); } + void setCaptureMouse(bool captureMouse) { _captureMouse = captureMouse; emit captureMouseChanged(captureMouse); } /**jsdoc * Gets the current camera sensitivity. * @function Camera.getSensitivity - * @returns {boolean} The current camera sensitivity. + * @returns {number} The current camera sensitivity. Must be positive. */ float getSensitivity() const { return _sensitivity; } /**jsdoc * Sets the camera sensitivity. Higher values mean that the camera will be more sensitive to mouse movements. * @function Camera.setSensitivity - * @param {boolean} sensitivity - The desired camera sensitivity. + * @param {number} sensitivity - The desired camera sensitivity. Must be positive. */ void setSensitivity(float sensitivity) { _sensitivity = glm::max(0.0f, sensitivity); } @@ -216,17 +217,17 @@ signals: /**jsdoc * Triggered when the camera mouse capture state changes. - * @function Camera.captureMouseUpdated + * @function Camera.captureMouseChanged * @param {boolean} newCaptureMouse - The new mouse capture state. * @returns {Signal} * @example Report mouse capture state changes. - * function onCaptureMouseUpdated(newCaptureMouse) { + * function onCaptureMouseChanged(newCaptureMouse) { * print("The mouse capture has changed to " + newCaptureMouse); * } * - * Camera.captureMouseUpdated.connect(onCaptureMouseUpdated); + * Camera.captureMouseChanged.connect(onCaptureMouseChanged); */ - void captureMouseUpdated(bool newCaptureMouse); + void captureMouseChanged(bool newCaptureMouse); private: void recompose();