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
This commit is contained in:
cutealien 2020-10-26 19:50:18 +00:00
parent 08ae93126c
commit 91cb559caa
2 changed files with 21 additions and 13 deletions

View File

@ -9,7 +9,6 @@
#include "ICursorControl.h" #include "ICursorControl.h"
#include "ICameraSceneNode.h" #include "ICameraSceneNode.h"
#include "ISceneNodeAnimatorCollisionResponse.h" #include "ISceneNodeAnimatorCollisionResponse.h"
#include "os.h"
namespace irr namespace irr
{ {
@ -21,10 +20,19 @@ CSceneNodeAnimatorCameraFPS::CSceneNodeAnimatorCameraFPS(gui::ICursorControl* cu
f32 rotateSpeed, f32 moveSpeed, f32 jumpSpeed, f32 rotateSpeed, f32 moveSpeed, f32 jumpSpeed,
SKeyMap* keyMapArray, u32 keyMapSize, bool noVerticalMovement, bool invertY, float rotateSpeedKeyboard) SKeyMap* keyMapArray, u32 keyMapSize, bool noVerticalMovement, bool invertY, float rotateSpeedKeyboard)
: CursorControl(cursorControl), MaxVerticalAngle(88.0f), NoVerticalMovement(noVerticalMovement), : 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), JumpSpeed(jumpSpeed),
MouseYDirection(invertY ? -1.0f : 1.0f), MouseYDirection(invertY ? -1.0f : 1.0f),
LastAnimationTime(0), firstUpdate(true), firstInput(true) LastAnimationTime(0), HadMouseEvent(false), firstUpdate(true), firstInput(true)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("CCameraSceneNodeAnimatorFPS"); setDebugName("CCameraSceneNodeAnimatorFPS");
@ -80,6 +88,9 @@ bool CSceneNodeAnimatorCameraFPS::OnEvent(const SEvent& evt)
} }
} }
break; break;
case EET_MOUSE_INPUT_EVENT:
HadMouseEvent = true;
return true;
default: default:
break; break;
@ -94,8 +105,6 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs)
if (!node || node->getType() != ESNT_CAMERA) if (!node || node->getType() != ESNT_CAMERA)
return; return;
timeMs = os::Timer::getRealTime(); // User input is always in real-time
ICameraSceneNode* camera = static_cast<ICameraSceneNode*>(node); ICameraSceneNode* camera = static_cast<ICameraSceneNode*>(node);
if (firstUpdate) if (firstUpdate)
@ -129,9 +138,6 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs)
if(smgr && smgr->getActiveCamera() != camera) if(smgr && smgr->getActiveCamera() != camera)
return; return;
if ( CursorControl )
CursorPos = CursorControl->getRelativePosition();
// get time // get time
f32 timeDiff = (f32) ( timeMs - LastAnimationTime ); f32 timeDiff = (f32) ( timeMs - LastAnimationTime );
LastAnimationTime = timeMs; LastAnimationTime = timeMs;
@ -144,6 +150,9 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs)
{ {
bool reset = false; bool reset = false;
if ( HadMouseEvent || GrabMouse)
CursorPos = CursorControl->getRelativePosition();
if (CursorPos != CenterCursor) if (CursorPos != CenterCursor)
{ {
relativeRotation.Y -= (CenterCursor.X - CursorPos.X) * RotateSpeed; relativeRotation.Y -= (CenterCursor.X - CursorPos.X) * RotateSpeed;
@ -152,12 +161,8 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs)
reset = true; 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. // Special case, mouse is whipped outside of window before it can update.
video::IVideoDriver* driver = smgr->getVideoDriver(); video::IVideoDriver* driver = smgr->getVideoDriver();
core::vector2d<u32> mousepos(u32(CursorPos.X), u32(CursorPos.Y)); core::vector2d<u32> mousepos(u32(CursorPos.X), u32(CursorPos.Y));
@ -174,6 +179,7 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs)
CursorPos = CenterCursor; CursorPos = CenterCursor;
} }
} }
HadMouseEvent = false;
// keyboard rotation // keyboard rotation
if (CursorKeys[EKA_ROTATE_LEFT]) if (CursorKeys[EKA_ROTATE_LEFT])

View File

@ -114,6 +114,7 @@ namespace scene
void allKeysUp(); void allKeysUp();
gui::ICursorControl *CursorControl; gui::ICursorControl *CursorControl;
bool GrabMouse;
f32 MaxVerticalAngle; f32 MaxVerticalAngle;
bool NoVerticalMovement; bool NoVerticalMovement;
@ -129,6 +130,7 @@ namespace scene
core::array<SKeyMap> KeyMap; core::array<SKeyMap> KeyMap;
core::position2d<f32> CenterCursor, CursorPos; core::position2d<f32> CenterCursor, CursorPos;
bool HadMouseEvent;
bool CursorKeys[EKA_COUNT]; bool CursorKeys[EKA_COUNT];