From 91cb559caae647f2ab73cdc1b8ffb3a9a04de368 Mon Sep 17 00:00:00 2001 From: cutealien Date: Mon, 26 Oct 2020 19:50:18 +0000 Subject: [PATCH] Bugfix: FPS camera animator on X11 no longer tries grabbing mouse events. Basically behavior about that is back to how it was in Irrlicht 1.8 - not perfect, but useable. So window still jumps a bit when dragging toolbar, but no longer outside the sreen. And it's possible again to alt+tab to other windows. The problem was caused by a combination of FPS camera changes and that we stopped doing mouse-coordinate clipping in the Linux device in r5593. Basically that clipping had the side-effect that the fps-camera never considered a mouse "outside" on Linux. Now on Linux we only update after we get a mouse-event (which we still get when the mouse is outside the window). On Windows we still grab the mouse in the camera, thought that's likely _not_ the best way to do that. Windows has some mouse-grabbing support, and I suppose we could use that (or camera should check if that is used as it also can be set by users I think). So maybe in future this can be further improved. Other operating systems (OSX) should behave like in 1.8 I hope, but as usual I can't test. Also did a few minor cleanups in the camera. - Back to using animateNode time instead of real-time. That's because that was not causing the problems I thought back then it might cause as time is only used for keyboard input and not mouse input. - Moved updating CursorPos to the rest of the code checking CursorControl Note: A future improvement would be to add support for systems without CursorControl object (could still use mouse-events to get it working usually). git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6142 dfc29bdd-3216-0410-991c-e03cc46cb475 --- .../Irrlicht/CSceneNodeAnimatorCameraFPS.cpp | 32 +++++++++++-------- source/Irrlicht/CSceneNodeAnimatorCameraFPS.h | 2 ++ 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/source/Irrlicht/CSceneNodeAnimatorCameraFPS.cpp b/source/Irrlicht/CSceneNodeAnimatorCameraFPS.cpp index c79f09b9..6da1c0b4 100644 --- a/source/Irrlicht/CSceneNodeAnimatorCameraFPS.cpp +++ b/source/Irrlicht/CSceneNodeAnimatorCameraFPS.cpp @@ -9,7 +9,6 @@ #include "ICursorControl.h" #include "ICameraSceneNode.h" #include "ISceneNodeAnimatorCollisionResponse.h" -#include "os.h" namespace irr { @@ -21,10 +20,19 @@ CSceneNodeAnimatorCameraFPS::CSceneNodeAnimatorCameraFPS(gui::ICursorControl* cu f32 rotateSpeed, f32 moveSpeed, f32 jumpSpeed, SKeyMap* keyMapArray, u32 keyMapSize, bool noVerticalMovement, bool invertY, float rotateSpeedKeyboard) : CursorControl(cursorControl), MaxVerticalAngle(88.0f), NoVerticalMovement(noVerticalMovement), - MoveSpeed(moveSpeed), RotateSpeedKeyboard(rotateSpeedKeyboard), RotateSpeed(rotateSpeed), + MoveSpeed(moveSpeed), +// On X11 we get events even when mouse is not inside the Irrlicht window, on Windows we don't. +// It might be possible to add grabbing on Windows as well in which case this has to be somewhat changed. +// TODO: I don't know about OSX, but in theory it should be like old Irrlicht 1.8 behavior whatever that was there. +#ifdef _IRR_COMPILE_WITH_X11_DEVICE_ + GrabMouse(false), +#else + GrabMouse(true), +#endif + RotateSpeedKeyboard(rotateSpeedKeyboard), RotateSpeed(rotateSpeed), JumpSpeed(jumpSpeed), MouseYDirection(invertY ? -1.0f : 1.0f), - LastAnimationTime(0), firstUpdate(true), firstInput(true) + LastAnimationTime(0), HadMouseEvent(false), firstUpdate(true), firstInput(true) { #ifdef _DEBUG setDebugName("CCameraSceneNodeAnimatorFPS"); @@ -80,6 +88,9 @@ bool CSceneNodeAnimatorCameraFPS::OnEvent(const SEvent& evt) } } break; + case EET_MOUSE_INPUT_EVENT: + HadMouseEvent = true; + return true; default: break; @@ -94,8 +105,6 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs) if (!node || node->getType() != ESNT_CAMERA) return; - timeMs = os::Timer::getRealTime(); // User input is always in real-time - ICameraSceneNode* camera = static_cast(node); if (firstUpdate) @@ -129,9 +138,6 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs) if(smgr && smgr->getActiveCamera() != camera) return; - if ( CursorControl ) - CursorPos = CursorControl->getRelativePosition(); - // get time f32 timeDiff = (f32) ( timeMs - LastAnimationTime ); LastAnimationTime = timeMs; @@ -144,6 +150,9 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs) { bool reset = false; + if ( HadMouseEvent || GrabMouse) + CursorPos = CursorControl->getRelativePosition(); + if (CursorPos != CenterCursor) { relativeRotation.Y -= (CenterCursor.X - CursorPos.X) * RotateSpeed; @@ -152,12 +161,8 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs) reset = true; } - if ( !reset ) + if ( GrabMouse && !reset) { - // TODO: not sure if this case is still needed. Might be it was only something - // that was necessary when someone tried to use mouse-events in the past. - // But not too expensive, test on all platforms before removing. - // Special case, mouse is whipped outside of window before it can update. video::IVideoDriver* driver = smgr->getVideoDriver(); core::vector2d mousepos(u32(CursorPos.X), u32(CursorPos.Y)); @@ -174,6 +179,7 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs) CursorPos = CenterCursor; } } + HadMouseEvent = false; // keyboard rotation if (CursorKeys[EKA_ROTATE_LEFT]) diff --git a/source/Irrlicht/CSceneNodeAnimatorCameraFPS.h b/source/Irrlicht/CSceneNodeAnimatorCameraFPS.h index 710c3eb5..0f49f223 100644 --- a/source/Irrlicht/CSceneNodeAnimatorCameraFPS.h +++ b/source/Irrlicht/CSceneNodeAnimatorCameraFPS.h @@ -114,6 +114,7 @@ namespace scene void allKeysUp(); gui::ICursorControl *CursorControl; + bool GrabMouse; f32 MaxVerticalAngle; bool NoVerticalMovement; @@ -129,6 +130,7 @@ namespace scene core::array KeyMap; core::position2d CenterCursor, CursorPos; + bool HadMouseEvent; bool CursorKeys[EKA_COUNT];