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:
*
CameraIndependent | number | number | The camera is in independent mode. |
* CameraEntity | number | number | The camera is in entity mode. |
* InHMD | number | number | The user is in HMD mode. |
+ * CaptureMouse | number | number | The mouse is captured. |
* AdvancedMovement | number | number | Advanced movement (walking) controls are
* enabled. |
* StrafeEnabled | number | number | Strafing 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