From f5076723e83ef93f4d0a2ad2c5b590841d903e96 Mon Sep 17 00:00:00 2001 From: grorp Date: Sat, 28 Sep 2024 11:23:13 +0200 Subject: [PATCH] Android: Fix camera jump when switching to mouse mode Easy way to reproduce: 1. Connect a bluetooth mouse to your Android phone with Minetest installed 2. Play Minetest 3. Slowly move the mouse to the right so that the camera rotates continously 4. While still moving the mouse continously, tap the screen a few times per second Before this commit: The camera jumps around randomly. After this commit: The camera moves like it should. This is a combination of two Irrlicht changes copied from MoNTE48/irrlicht and one Minetest change authored by me. I have no idea why this works, but it does work and I have spent way too much time on this bug already. --- irr/src/CIrrDeviceSDL.cpp | 15 +++++++++++---- irr/src/CIrrDeviceSDL.h | 5 +++++ src/client/game.cpp | 4 +++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/irr/src/CIrrDeviceSDL.cpp b/irr/src/CIrrDeviceSDL.cpp index 14d996e47..6d1b45886 100644 --- a/irr/src/CIrrDeviceSDL.cpp +++ b/irr/src/CIrrDeviceSDL.cpp @@ -721,12 +721,19 @@ bool CIrrDeviceSDL::run() irrevent.EventType = irr::EET_MOUSE_INPUT_EVENT; irrevent.MouseInput.Event = irr::EMIE_MOUSE_MOVED; - MouseX = irrevent.MouseInput.X = - static_cast(SDL_event.motion.x * ScaleX); - MouseY = irrevent.MouseInput.Y = - static_cast(SDL_event.motion.y * ScaleY); + MouseXRel = static_cast(SDL_event.motion.xrel * ScaleX); MouseYRel = static_cast(SDL_event.motion.yrel * ScaleY); + if (!SDL_GetRelativeMouseMode()) { + MouseX = static_cast(SDL_event.motion.x * ScaleX); + MouseY = static_cast(SDL_event.motion.y * ScaleY); + } else { + MouseX += MouseXRel; + MouseY += MouseYRel; + } + irrevent.MouseInput.X = MouseX; + irrevent.MouseInput.Y = MouseY; + irrevent.MouseInput.ButtonStates = MouseButtonStates; irrevent.MouseInput.Shift = (keymod & KMOD_SHIFT) != 0; irrevent.MouseInput.Control = (keymod & KMOD_CTRL) != 0; diff --git a/irr/src/CIrrDeviceSDL.h b/irr/src/CIrrDeviceSDL.h index f881bba5c..7156c19b6 100644 --- a/irr/src/CIrrDeviceSDL.h +++ b/irr/src/CIrrDeviceSDL.h @@ -158,9 +158,13 @@ public: //! Sets the new position of the cursor. void setPosition(s32 x, s32 y) override { +#ifndef __ANDROID__ + // On Android, this somehow results in a camera jump when enabling + // relative mouse mode and it isn't supported anyway. SDL_WarpMouseInWindow(Device->Window, static_cast(x / Device->ScaleX), static_cast(y / Device->ScaleY)); +#endif if (SDL_GetRelativeMouseMode()) { // There won't be an event for this warp (details on libsdl-org/SDL/issues/6034) @@ -298,6 +302,7 @@ private: #endif s32 MouseX, MouseY; + // these two only continue to exist for some Emscripten stuff idk about s32 MouseXRel, MouseYRel; u32 MouseButtonStates; diff --git a/src/client/game.cpp b/src/client/game.cpp index 090af05c9..32c57ec1b 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2679,7 +2679,7 @@ void Game::updateCameraDirection(CameraOrientation *cam, float dtime) cur_control->setVisible(false); } - if (m_first_loop_after_window_activation) { + if (m_first_loop_after_window_activation && !g_touchcontrols) { m_first_loop_after_window_activation = false; input->setMousePos(driver->getScreenSize().Width / 2, @@ -2695,6 +2695,8 @@ void Game::updateCameraDirection(CameraOrientation *cam, float dtime) m_first_loop_after_window_activation = true; } + if (g_touchcontrols) + m_first_loop_after_window_activation = true; } // Get the factor to multiply with sensitivity to get the same mouse/joystick