From d769171ed55197f68b11470f4f7e2eff2dcfd6e6 Mon Sep 17 00:00:00 2001 From: Miguel Canais Date: Thu, 6 Mar 2025 23:21:19 +0000 Subject: [PATCH] feat(input): allow changing mouse state through input plugin --- CHANGELOG.md | 1 + engine/include/cubos/engine/input/input.hpp | 22 ++++++++++++++++++++ engine/src/input/input.cpp | 23 +++++++++++++++++++++ engine/src/input/plugin.cpp | 7 ++++++- engine/src/utils/free_camera/plugin.cpp | 10 ++++----- 5 files changed, 57 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6768586faf..f94fcce9ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Made collision layer and mask their own components (#535, **@fallenatlas**). - Make RenderPicker optional (#1407, **@tomas7770**). +- Allow mouse state to be changed through the input plugin (#1401, **@mcanais**). ## [v0.6.0] - 2025-02-10 diff --git a/engine/include/cubos/engine/input/input.hpp b/engine/include/cubos/engine/input/input.hpp index a8b502c5ba..95e06463e7 100644 --- a/engine/include/cubos/engine/input/input.hpp +++ b/engine/include/cubos/engine/input/input.hpp @@ -32,6 +32,9 @@ namespace cubos::engine /// @brief Alias for @ref core::io::MouseButton. using MouseButton = core::io::MouseButton; + /// @brief Alias for @ref core::io::MouseState. + using MouseState = core::io::MouseState; + Input() = default; ~Input() = default; @@ -123,6 +126,22 @@ namespace cubos::engine /// @return Mouse displacement. glm::ivec2 mouseDelta() const; + /// @brief Sets the mouse state when the window is focused. + /// @param state Mouse state. + void mouseState(MouseState state); + + /// @brief Gets the mouse state when the window is focused. + /// @return Mouse state when the window is focused. + MouseState mouseState() const; + + /// @brief Sets the mouse state to be updated. + /// @param window Window. + void updateMouseState(core::io::Window& window); + + /// @brief Gets the update mouse state. + /// @return Whether the mouse state should be updated. + bool updateMouseState() const; + /// @brief Handle all other events - discards them. /// /// This is method exists so that `std::visit` can be used with @ref core::io::WindowEvent @@ -171,5 +190,8 @@ namespace cubos::engine glm::ivec2 mMousePosition = {0, 0}; glm::ivec2 mPreviousMousePosition = {0, 0}; + + MouseState mMouseState = MouseState::Default; + bool mUpdateMouseState = false; }; } // namespace cubos::engine diff --git a/engine/src/input/input.cpp b/engine/src/input/input.cpp index 125f98e2d0..69a5bffe6c 100644 --- a/engine/src/input/input.cpp +++ b/engine/src/input/input.cpp @@ -13,6 +13,7 @@ using cubos::core::io::KeyEvent; using cubos::core::io::MouseButton; using cubos::core::io::MouseButtonEvent; using cubos::core::io::MouseMoveEvent; +using cubos::core::io::MouseState; using cubos::core::io::Window; using namespace cubos::engine; @@ -444,6 +445,28 @@ glm::ivec2 Input::mouseDelta() const return mMousePosition - mPreviousMousePosition; } +void Input::mouseState(MouseState state) +{ + mUpdateMouseState = true; + mMouseState = state; +} + +MouseState Input::mouseState() const +{ + return mMouseState; +} + +void Input::updateMouseState(Window& window) +{ + window->mouseState(mMouseState); + mUpdateMouseState = false; +} + +bool Input::updateMouseState() const +{ + return mUpdateMouseState; +} + void Input::pollGamepads(const Window& window) { for (auto& [gamepad, state] : mGamepadStates) diff --git a/engine/src/input/plugin.cpp b/engine/src/input/plugin.cpp index 8b0c6579b4..766c63c0f3 100644 --- a/engine/src/input/plugin.cpp +++ b/engine/src/input/plugin.cpp @@ -26,7 +26,7 @@ void cubos::engine::inputPlugin(Cubos& cubos) cubos.system("handle WindowEvents for Input") .tagged(inputUpdateTag) .after(windowPollTag) - .call([](const Window& window, Input& input, EventReader events) { + .call([](Window& window, Input& input, EventReader events) { input.updateMouse(); input.updateActions(); @@ -35,6 +35,11 @@ void cubos::engine::inputPlugin(Cubos& cubos) std::visit([window, &input](auto e) { input.handle(window, e); }, event); } + if (input.updateMouseState()) + { + input.updateMouseState(window); + } + input.pollGamepads(window); }); } diff --git a/engine/src/utils/free_camera/plugin.cpp b/engine/src/utils/free_camera/plugin.cpp index ae4f3f52fc..91f31f1f7f 100644 --- a/engine/src/utils/free_camera/plugin.cpp +++ b/engine/src/utils/free_camera/plugin.cpp @@ -30,7 +30,7 @@ void cubos::engine::freeCameraPlugin(Cubos& cubos) cubos.resource(); cubos.system("rotate FreeCameraController on mouse motion") - .call([](const Input& input, Window& window, const DeltaTime& deltaTime, State& state, + .call([](Input& input, const DeltaTime& deltaTime, State& state, Query entities) { bool anyEnabled = false; @@ -68,16 +68,16 @@ void cubos::engine::freeCameraPlugin(Cubos& cubos) } // Lock/unlock mouse depending on if any FreeCameraController is enabled. - if (anyEnabled && window->mouseState() != MouseState::Locked) + if (anyEnabled && input.mouseState() != MouseState::Locked) { - window->mouseState(MouseState::Locked); + input.mouseState(MouseState::Locked); state.tookOverMouse = true; } if (!anyEnabled && state.tookOverMouse) { - window->mouseState(MouseState::Default); + input.mouseState(MouseState::Default); state.tookOverMouse = false; } }); -} \ No newline at end of file +}