Implement relative mouse mode (raw input) for SDL platform
This commit is contained in:
@@ -266,6 +266,7 @@ namespace FlaxEditor.GUI.Input
|
||||
return base.OnMouseDown(location, button);
|
||||
}
|
||||
|
||||
#if !PLATFORM_SDL
|
||||
/// <inheritdoc />
|
||||
public override void OnMouseMove(Float2 location)
|
||||
{
|
||||
@@ -292,6 +293,36 @@ namespace FlaxEditor.GUI.Input
|
||||
base.OnMouseMove(location);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnMouseMoveRelative(Float2 mouseMotion)
|
||||
{
|
||||
var location = Root.TrackingMouseOffset;
|
||||
if (_isSliding)
|
||||
{
|
||||
// Update sliding
|
||||
ApplySliding(Root.TrackingMouseOffset.X * _slideSpeed);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update cursor type so user knows they can slide value
|
||||
if (CanUseSliding && SlideRect.Contains(location) && !_isSliding)
|
||||
{
|
||||
Cursor = CursorType.SizeWE;
|
||||
_cursorChanged = true;
|
||||
}
|
||||
else if (_cursorChanged && !_isSliding)
|
||||
{
|
||||
Cursor = CursorType.Default;
|
||||
_cursorChanged = false;
|
||||
}
|
||||
|
||||
base.OnMouseMoveRelative(mouseMotion);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool OnMouseUp(Float2 location, MouseButton button)
|
||||
{
|
||||
|
||||
@@ -435,6 +435,9 @@ DEFINE_INTERNAL_CALL(void) EditorInternal_RunVisualScriptBreakpointLoopTick(floa
|
||||
case InputDevice::EventType::MouseMove:
|
||||
window->OnMouseMove(window->ScreenToClient(e.MouseData.Position));
|
||||
break;
|
||||
case InputDevice::EventType::MouseMoveRelative:
|
||||
window->OnMouseMoveRelative(e.MouseMovementData.PositionRelative);
|
||||
break;
|
||||
case InputDevice::EventType::MouseLeave:
|
||||
window->OnMouseLeave();
|
||||
break;
|
||||
|
||||
@@ -158,18 +158,22 @@ namespace FlaxEditor.Viewport
|
||||
private float _movementSpeed;
|
||||
private float _minMovementSpeed;
|
||||
private float _maxMovementSpeed;
|
||||
#if !PLATFORM_SDL
|
||||
private float _mouseAccelerationScale;
|
||||
private bool _useMouseFiltering;
|
||||
private bool _useMouseAcceleration;
|
||||
#endif
|
||||
|
||||
// Input
|
||||
|
||||
internal bool _disableInputUpdate;
|
||||
private bool _isControllingMouse, _isViewportControllingMouse, _wasVirtualMouseRightDown, _isVirtualMouseRightDown;
|
||||
private int _deltaFilteringStep;
|
||||
private Float2 _startPos;
|
||||
#if !PLATFORM_SDL
|
||||
private Float2 _mouseDeltaLast;
|
||||
private int _deltaFilteringStep;
|
||||
private Float2[] _deltaFilteringBuffer = new Float2[FpsCameraFilteringFrames];
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// The previous input (from the previous update).
|
||||
@@ -522,10 +526,11 @@ namespace FlaxEditor.Viewport
|
||||
: base(task)
|
||||
{
|
||||
_editor = Editor.Instance;
|
||||
|
||||
#if !PLATFORM_SDL
|
||||
_mouseAccelerationScale = 0.1f;
|
||||
_useMouseFiltering = false;
|
||||
_useMouseAcceleration = false;
|
||||
#endif
|
||||
_camera = camera;
|
||||
if (_camera != null)
|
||||
_camera.Viewport = this;
|
||||
@@ -1460,7 +1465,9 @@ namespace FlaxEditor.Viewport
|
||||
// Hide cursor and start tracking mouse movement
|
||||
win.StartTrackingMouse(false);
|
||||
win.Cursor = CursorType.Hidden;
|
||||
win.MouseMoveRelative += OnMouseMoveRelative;
|
||||
|
||||
#if !PLATFORM_SDL
|
||||
// Center mouse position if it's too close to the edge
|
||||
var size = Size;
|
||||
var center = Float2.Round(size * 0.5f);
|
||||
@@ -1469,6 +1476,7 @@ namespace FlaxEditor.Viewport
|
||||
_viewMousePos = center;
|
||||
win.MousePosition = PointToWindow(_viewMousePos);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1480,6 +1488,7 @@ namespace FlaxEditor.Viewport
|
||||
// Restore cursor and stop tracking mouse movement
|
||||
win.Cursor = CursorType.Default;
|
||||
win.EndTrackingMouse();
|
||||
win.MouseMoveRelative -= OnMouseMoveRelative;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1584,6 +1593,14 @@ namespace FlaxEditor.Viewport
|
||||
else
|
||||
EndMouseCapture();
|
||||
}
|
||||
#if PLATFORM_SDL
|
||||
bool useMouse = IsControllingMouse || true;
|
||||
_prevInput = _input;
|
||||
if (canUseInput && ContainsFocus)
|
||||
_input.Gather(win.Window, useMouse, ref _prevInput);
|
||||
else
|
||||
_input.Clear();
|
||||
#else
|
||||
bool useMouse = IsControllingMouse || (Mathf.IsInRange(_viewMousePos.X, 0, Width) && Mathf.IsInRange(_viewMousePos.Y, 0, Height));
|
||||
_prevInput = _input;
|
||||
var hit = GetChildAt(_viewMousePos, c => c.Visible && !(c is CanvasRootControl) && !(c is UIEditorRoot));
|
||||
@@ -1591,6 +1608,7 @@ namespace FlaxEditor.Viewport
|
||||
_input.Gather(win.Window, useMouse, ref _prevInput);
|
||||
else
|
||||
_input.Clear();
|
||||
#endif
|
||||
|
||||
// Track controlling mouse state change
|
||||
bool wasControllingMouse = _prevInput.IsControllingMouse;
|
||||
@@ -1699,6 +1717,10 @@ namespace FlaxEditor.Viewport
|
||||
if (_input.IsControlDown)
|
||||
moveDelta *= 0.3f;
|
||||
|
||||
#if PLATFORM_SDL
|
||||
var mouseDelta = _mouseDelta;
|
||||
_mouseDelta = Float2.Zero;
|
||||
#else
|
||||
// Calculate smooth mouse delta not dependant on viewport size
|
||||
var offset = _viewMousePos - _startPos;
|
||||
if (_input.IsZooming && !_input.IsMouseRightDown && !_input.IsMouseLeftDown && !_input.IsMouseMiddleDown && !_isOrtho && !rmbWheel && !_isVirtualMouseRightDown)
|
||||
@@ -1740,6 +1762,7 @@ namespace FlaxEditor.Viewport
|
||||
mouseDelta += _mouseDeltaLast * _mouseAccelerationScale;
|
||||
_mouseDeltaLast = currentDelta;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Update
|
||||
moveDelta *= dt * (60.0f * 4.0f);
|
||||
@@ -1748,12 +1771,14 @@ namespace FlaxEditor.Viewport
|
||||
mouseDelta *= new Float2(1, -1);
|
||||
UpdateView(dt, ref moveDelta, ref mouseDelta, out var centerMouse);
|
||||
|
||||
#if !PLATFORM_SDL
|
||||
// Move mouse back to the root position
|
||||
if (centerMouse && (_input.IsMouseRightDown || _input.IsMouseLeftDown || _input.IsMouseMiddleDown || _isVirtualMouseRightDown))
|
||||
{
|
||||
var center = PointToWindow(_startPos);
|
||||
win.MousePosition = center;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Change Ortho size on mouse scroll
|
||||
if (_isOrtho && !rmbWheel)
|
||||
@@ -1765,6 +1790,8 @@ namespace FlaxEditor.Viewport
|
||||
}
|
||||
else
|
||||
{
|
||||
#if PLATFORM_SDL
|
||||
#else
|
||||
if (_input.IsMouseLeftDown || _input.IsMouseRightDown || _isVirtualMouseRightDown)
|
||||
{
|
||||
// Calculate smooth mouse delta not dependant on viewport size
|
||||
@@ -1779,6 +1806,7 @@ namespace FlaxEditor.Viewport
|
||||
_mouseDelta = Float2.Zero;
|
||||
}
|
||||
_mouseDeltaLast = Float2.Zero;
|
||||
#endif
|
||||
|
||||
if (ContainsFocus)
|
||||
{
|
||||
@@ -1828,6 +1856,12 @@ namespace FlaxEditor.Viewport
|
||||
_input.MouseWheelDelta = 0;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void OnMouseMoveRelative(ref Float2 mouseMotion)
|
||||
{
|
||||
_mouseDelta += mouseMotion;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool OnMouseDown(Float2 location, MouseButton button)
|
||||
{
|
||||
|
||||
@@ -106,13 +106,25 @@ void Screen::SetCursorVisible(const bool value)
|
||||
#else
|
||||
const auto win = Engine::MainWindow;
|
||||
#endif
|
||||
bool focused = false;
|
||||
if (win && Engine::HasGameViewportFocus())
|
||||
{
|
||||
win->SetCursor(value ? CursorType::Default : CursorType::Hidden);
|
||||
focused = true;
|
||||
}
|
||||
else if (win)
|
||||
win->SetCursor(CursorType::Default);
|
||||
CursorVisible = value;
|
||||
|
||||
// Just enable relative mode when cursor is constrained and not visible
|
||||
if (CursorLock != CursorLockMode::None && !CursorVisible && focused)
|
||||
{
|
||||
Input::Mouse->SetRelativeMode(true);
|
||||
}
|
||||
else if (CursorLock == CursorLockMode::None || CursorVisible || !focused)
|
||||
{
|
||||
Input::Mouse->SetRelativeMode(false);
|
||||
}
|
||||
}
|
||||
|
||||
CursorLockMode Screen::GetCursorLock()
|
||||
@@ -141,6 +153,17 @@ void Screen::SetCursorLock(CursorLockMode mode)
|
||||
win->EndClippingCursor();
|
||||
}
|
||||
CursorLock = mode;
|
||||
|
||||
// Just enable relative mode when cursor is constrained and not visible
|
||||
bool focused = win && Engine::HasGameViewportFocus();
|
||||
if (CursorLock != CursorLockMode::None && !CursorVisible && focused)
|
||||
{
|
||||
Input::Mouse->SetRelativeMode(true);
|
||||
}
|
||||
else if (CursorLock == CursorLockMode::None || CursorVisible || !focused)
|
||||
{
|
||||
Input::Mouse->SetRelativeMode(false);
|
||||
}
|
||||
}
|
||||
|
||||
GameWindowMode Screen::GetGameWindowMode()
|
||||
|
||||
@@ -78,6 +78,7 @@ Delegate<const Float2&, MouseButton> Input::MouseUp;
|
||||
Delegate<const Float2&, MouseButton> Input::MouseDoubleClick;
|
||||
Delegate<const Float2&, float> Input::MouseWheel;
|
||||
Delegate<const Float2&> Input::MouseMove;
|
||||
Delegate<const Float2&> Input::MouseMoveRelative;
|
||||
Action Input::MouseLeave;
|
||||
Delegate<const Float2&, int32> Input::TouchDown;
|
||||
Delegate<const Float2&, int32> Input::TouchMove;
|
||||
@@ -208,6 +209,14 @@ void Mouse::OnMouseMove(const Float2& position, Window* target)
|
||||
e.MouseData.Position = position;
|
||||
}
|
||||
|
||||
void Mouse::OnMouseMoveRelative(const Float2& positionRelative, Window* target)
|
||||
{
|
||||
Event& e = _queue.AddOne();
|
||||
e.Type = EventType::MouseMoveRelative;
|
||||
e.Target = target;
|
||||
e.MouseMovementData.PositionRelative = positionRelative;
|
||||
}
|
||||
|
||||
void Mouse::OnMouseLeave(Window* target)
|
||||
{
|
||||
Event& e = _queue.AddOne();
|
||||
@@ -273,6 +282,11 @@ bool Mouse::Update(EventQueue& queue)
|
||||
_state.MousePosition = e.MouseData.Position;
|
||||
break;
|
||||
}
|
||||
case EventType::MouseMoveRelative:
|
||||
{
|
||||
_state.MousePosition += e.MouseMovementData.PositionRelative;
|
||||
break;
|
||||
}
|
||||
case EventType::MouseLeave:
|
||||
{
|
||||
break;
|
||||
@@ -933,6 +947,9 @@ void InputService::Update()
|
||||
case InputDevice::EventType::MouseMove:
|
||||
window->OnMouseMove(window->ScreenToClient(e.MouseData.Position));
|
||||
break;
|
||||
case InputDevice::EventType::MouseMoveRelative:
|
||||
window->OnMouseMoveRelative(e.MouseMovementData.PositionRelative);
|
||||
break;
|
||||
case InputDevice::EventType::MouseLeave:
|
||||
window->OnMouseLeave();
|
||||
break;
|
||||
@@ -989,6 +1006,9 @@ void InputService::Update()
|
||||
case InputDevice::EventType::MouseMove:
|
||||
Input::MouseMove(e.MouseData.Position);
|
||||
break;
|
||||
case InputDevice::EventType::MouseMoveRelative:
|
||||
Input::MouseMoveRelative(e.MouseMovementData.PositionRelative);
|
||||
break;
|
||||
case InputDevice::EventType::MouseLeave:
|
||||
Input::MouseLeave();
|
||||
break;
|
||||
@@ -1202,6 +1222,7 @@ void InputService::Update()
|
||||
}
|
||||
}
|
||||
|
||||
#if !PLATFORM_SDL
|
||||
// Lock mouse if need to
|
||||
const auto lockMode = Screen::GetCursorLock();
|
||||
if (lockMode == CursorLockMode::Locked)
|
||||
@@ -1210,6 +1231,7 @@ void InputService::Update()
|
||||
Screen::ScreenToGameViewport(Float2::Zero);
|
||||
Input::SetMousePosition(pos);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Send events for the active actions and axes (send events only in play mode)
|
||||
if (!Time::GetGamePaused())
|
||||
|
||||
@@ -108,6 +108,11 @@ public:
|
||||
/// </summary>
|
||||
API_EVENT() static Delegate<const Float2&> MouseMove;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when mouse moves while in relative mode.
|
||||
/// </summary>
|
||||
API_EVENT() static Delegate<const Float2&> MouseMoveRelative;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when mouse leaves window.
|
||||
/// </summary>
|
||||
|
||||
@@ -25,6 +25,7 @@ public:
|
||||
MouseDoubleClick,
|
||||
MouseWheel,
|
||||
MouseMove,
|
||||
MouseMoveRelative,
|
||||
MouseLeave,
|
||||
TouchDown,
|
||||
TouchMove,
|
||||
@@ -54,6 +55,11 @@ public:
|
||||
Float2 Position;
|
||||
} MouseData;
|
||||
|
||||
struct
|
||||
{
|
||||
Float2 PositionRelative;
|
||||
} MouseMovementData;
|
||||
|
||||
struct
|
||||
{
|
||||
float WheelDelta;
|
||||
|
||||
@@ -46,12 +46,14 @@ public:
|
||||
protected:
|
||||
State _state;
|
||||
State _prevState;
|
||||
bool _relativeMode;
|
||||
|
||||
explicit Mouse()
|
||||
: InputDevice(SpawnParams(Guid::New(), TypeInitializer), TEXT("Mouse"))
|
||||
{
|
||||
_state.Clear();
|
||||
_prevState.Clear();
|
||||
_relativeMode = false;
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -114,6 +116,14 @@ public:
|
||||
return !_state.MouseButtons[static_cast<int32>(button)] && _prevState.MouseButtons[static_cast<int32>(button)];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current state of mouse relative mode.
|
||||
/// </summary>
|
||||
API_FUNCTION() FORCE_INLINE bool IsRelative() const
|
||||
{
|
||||
return _relativeMode;
|
||||
}
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Sets the mouse position.
|
||||
@@ -121,6 +131,16 @@ public:
|
||||
/// <param name="newPosition">The new position.</param>
|
||||
virtual void SetMousePosition(const Float2& newPosition) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the mouse relative mode state. While enabled, the mouse movement tracking becomes more accurate.
|
||||
/// The cursor will be hidden while in relative mode.
|
||||
/// </summary>
|
||||
/// <param name="relativeMode">The new relative mode state.</param>
|
||||
virtual void SetRelativeMode(bool relativeMode)
|
||||
{
|
||||
_relativeMode = relativeMode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when mouse cursor gets moved by the application. Invalidates the previous cached mouse position to prevent mouse jitter when locking the cursor programmatically.
|
||||
/// </summary>
|
||||
@@ -158,6 +178,13 @@ public:
|
||||
/// <param name="target">The target window to receive this event, otherwise input system will pick the window automatically.</param>
|
||||
void OnMouseMove(const Float2& position, Window* target = nullptr);
|
||||
|
||||
/// <summary>
|
||||
/// Called when mouse moves in relative mode.
|
||||
/// </summary>
|
||||
/// <param name="positionRelative">The mouse position change.</param>
|
||||
/// <param name="target">The target window to receive this event, otherwise input system will pick the window automatically.</param>
|
||||
void OnMouseMoveRelative(const Float2& positionRelative, Window* target = nullptr);
|
||||
|
||||
/// <summary>
|
||||
/// Called when mouse leaves the input source area.
|
||||
/// </summary>
|
||||
|
||||
@@ -257,6 +257,13 @@ void WindowBase::OnMouseMove(const Float2& mousePosition)
|
||||
INVOKE_EVENT_PARAMS_1(OnMouseMove, (void*)&mousePosition);
|
||||
}
|
||||
|
||||
void WindowBase::OnMouseMoveRelative(const Float2& mousePositionRelative)
|
||||
{
|
||||
PROFILE_CPU_NAMED("GUI.OnMouseMoveRelative");
|
||||
MouseMoveRelative(mousePositionRelative);
|
||||
INVOKE_EVENT_PARAMS_1(OnMouseMoveRelative, (void*)&mousePositionRelative);
|
||||
}
|
||||
|
||||
void WindowBase::OnMouseLeave()
|
||||
{
|
||||
PROFILE_CPU_NAMED("GUI.OnMouseLeave");
|
||||
|
||||
@@ -592,6 +592,12 @@ public:
|
||||
MouseDelegate MouseMove;
|
||||
void OnMouseMove(const Float2& mousePosition);
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when mouse moves in relative mode.
|
||||
/// </summary>
|
||||
MouseDelegate MouseMoveRelative;
|
||||
void OnMouseMoveRelative(const Float2& mousePositionRelative);
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when mouse leaves window.
|
||||
/// </summary>
|
||||
|
||||
@@ -616,7 +616,7 @@ void LinuxWindow::OnButtonPress(void* event)
|
||||
}
|
||||
|
||||
// Handle double-click
|
||||
if (buttonEvent->button == Button1)
|
||||
if (buttonEvent->button == Button1 && !Input::Mouse->IsRelative())
|
||||
{
|
||||
if (
|
||||
buttonEvent->time < (MouseLastButtonPressTime + MouseDoubleClickTime) &&
|
||||
|
||||
@@ -507,7 +507,7 @@ static void ConvertNSRect(NSScreen *screen, NSRect *r)
|
||||
Float2 mousePos = GetMousePosition(Window, event);
|
||||
mousePos = Window->ClientToScreen(mousePos);
|
||||
MouseButton mouseButton = MouseButton::Left;
|
||||
if ([event clickCount] == 2)
|
||||
if ([event clickCount] == 2 && !Input::Mouse->IsRelative())
|
||||
Input::Mouse->OnMouseDoubleClick(mousePos, mouseButton, Window);
|
||||
else
|
||||
Input::Mouse->OnMouseDown(mousePos, mouseButton, Window);
|
||||
@@ -544,7 +544,7 @@ static void ConvertNSRect(NSScreen *screen, NSRect *r)
|
||||
if (IsWindowInvalid(Window)) return;
|
||||
Float2 mousePos = GetMousePosition(Window, event);
|
||||
MouseButton mouseButton = MouseButton::Right;
|
||||
if ([event clickCount] == 2)
|
||||
if ([event clickCount] == 2 && !Input::Mouse->IsRelative())
|
||||
Input::Mouse->OnMouseDoubleClick(Window->ClientToScreen(mousePos), mouseButton, Window);
|
||||
else
|
||||
Input::Mouse->OnMouseDown(Window->ClientToScreen(mousePos), mouseButton, Window);
|
||||
@@ -582,7 +582,7 @@ static void ConvertNSRect(NSScreen *screen, NSRect *r)
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if ([event clickCount] == 2)
|
||||
if ([event clickCount] == 2 && !Input::Mouse->IsRelative())
|
||||
Input::Mouse->OnMouseDoubleClick(Window->ClientToScreen(mousePos), mouseButton, Window);
|
||||
else
|
||||
Input::Mouse->OnMouseDown(Window->ClientToScreen(mousePos), mouseButton, Window);
|
||||
|
||||
@@ -474,8 +474,16 @@ bool SDLInput::HandleEvent(SDLWindow* window, SDL_Event& event)
|
||||
{
|
||||
case SDL_EVENT_MOUSE_MOTION:
|
||||
{
|
||||
const Float2 mousePos = window->ClientToScreen({ event.motion.x, event.motion.y });
|
||||
Input::Mouse->OnMouseMove(mousePos, window);
|
||||
if (Input::Mouse->IsRelative())
|
||||
{
|
||||
const Float2 mouseDelta(event.motion.xrel, event.motion.yrel);
|
||||
Input::Mouse->OnMouseMoveRelative(mouseDelta, window);
|
||||
}
|
||||
else
|
||||
{
|
||||
const Float2 mousePos = window->ClientToScreen({ event.motion.x, event.motion.y });
|
||||
Input::Mouse->OnMouseMove(mousePos, window);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
|
||||
@@ -486,7 +494,7 @@ bool SDLInput::HandleEvent(SDLWindow* window, SDL_Event& event)
|
||||
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||
{
|
||||
const Float2 mousePos = window->ClientToScreen({ event.button.x, event.button.y });
|
||||
Float2 mousePos = window->ClientToScreen({ event.button.x, event.button.y });
|
||||
MouseButton button = MouseButton::None;
|
||||
if (event.button.button == SDL_BUTTON_LEFT)
|
||||
button = MouseButton::Left;
|
||||
@@ -499,9 +507,16 @@ bool SDLInput::HandleEvent(SDLWindow* window, SDL_Event& event)
|
||||
else if (event.button.button == SDL_BUTTON_X2)
|
||||
button = MouseButton::Extended2;
|
||||
|
||||
if (Input::Mouse->IsRelative())
|
||||
{
|
||||
// Use the previous visible mouse position here, the event or global
|
||||
// mouse position would cause input to trigger in other editor windows.
|
||||
mousePos = SDLInputImpl::Mouse->GetMousePosition();
|
||||
}
|
||||
|
||||
if (event.button.state == SDL_RELEASED)
|
||||
Input::Mouse->OnMouseUp(mousePos, button, window);
|
||||
// Prevent sending mouse down event when double-clicking
|
||||
// Prevent sending multiple mouse down event when double-clicking UI elements
|
||||
else if (event.button.clicks % 2 == 1)
|
||||
Input::Mouse->OnMouseDown(mousePos, button, window);
|
||||
else
|
||||
@@ -511,9 +526,16 @@ bool SDLInput::HandleEvent(SDLWindow* window, SDL_Event& event)
|
||||
}
|
||||
case SDL_EVENT_MOUSE_WHEEL:
|
||||
{
|
||||
const Float2 mousePos = window->ClientToScreen({ event.wheel.mouse_x, event.wheel.mouse_y });
|
||||
Float2 mousePos = window->ClientToScreen({ event.wheel.mouse_x, event.wheel.mouse_y });
|
||||
const float delta = event.wheel.y;
|
||||
|
||||
if (Input::Mouse->IsRelative())
|
||||
{
|
||||
// Use the previous visible mouse position here, the event or global
|
||||
// mouse position would cause input to trigger in other editor windows.
|
||||
mousePos = SDLInputImpl::Mouse->GetMousePosition();
|
||||
}
|
||||
|
||||
Input::Mouse->OnMouseWheel(mousePos, delta, window);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -957,6 +957,10 @@ void SDLWindow::StartTrackingMouse(bool useMouseScreenOffset)
|
||||
{
|
||||
if (SDL_CaptureMouse(SDL_TRUE) != 0)
|
||||
LOG(Warning, "SDL_CaptureMouse: {0}", String(SDL_GetError()));
|
||||
|
||||
// For viewport camera mouse tracking we want to use relative mode for best precision
|
||||
if (_cursor == CursorType::Hidden)
|
||||
Input::Mouse->SetRelativeMode(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -973,6 +977,7 @@ void SDLWindow::EndTrackingMouse()
|
||||
LOG(Warning, "SDL_CaptureMouse: {0}", String(SDL_GetError()));
|
||||
|
||||
//SDL_SetWindowGrab(_window, SDL_FALSE);
|
||||
Input::Mouse->SetRelativeMode(false);
|
||||
}
|
||||
|
||||
void SDLWindow::StartClippingCursor(const Rectangle& bounds)
|
||||
@@ -1038,9 +1043,14 @@ void SDLWindow::UpdateCursor() const
|
||||
if (_cursor == CursorType::Hidden)
|
||||
{
|
||||
SDL_HideCursor();
|
||||
|
||||
if (_isTrackingMouse)
|
||||
Input::Mouse->SetRelativeMode(true);
|
||||
return;
|
||||
}
|
||||
SDL_ShowCursor();
|
||||
//if (_isTrackingMouse)
|
||||
// Input::Mouse->SetRelativeMode(false);
|
||||
|
||||
int32 index = SDL_SYSTEM_CURSOR_DEFAULT;
|
||||
switch (_cursor)
|
||||
|
||||
@@ -17,31 +17,37 @@ namespace FlaxEngine
|
||||
/// <summary>
|
||||
/// Perform window hit test delegate.
|
||||
/// </summary>
|
||||
/// <param name="mouse">The mouse position. The coordinate is relative to the upper-left corner of the screen. Use <see cref="ScreenToClient"/> to convert position into client space coordinates.</param>
|
||||
/// <param name="mousePosition">The mouse position. The coordinate is relative to the upper-left corner of the screen. Use <see cref="ScreenToClient"/> to convert position into client space coordinates.</param>
|
||||
/// <returns>Hit result.</returns>
|
||||
public delegate WindowHitCodes HitTestDelegate(ref Float2 mouse);
|
||||
public delegate WindowHitCodes HitTestDelegate(ref Float2 mousePosition);
|
||||
|
||||
/// <summary>
|
||||
/// Perform mouse buttons action.
|
||||
/// </summary>
|
||||
/// <param name="mouse">The mouse position.</param>
|
||||
/// <param name="mousePosition">The mouse position.</param>
|
||||
/// <param name="button">The mouse buttons state.</param>
|
||||
/// <param name="handled">The flag that indicated that event has been handled by the custom code and should not be passed further. By default it is set to false.</param>
|
||||
public delegate void MouseButtonDelegate(ref Float2 mouse, MouseButton button, ref bool handled);
|
||||
public delegate void MouseButtonDelegate(ref Float2 mousePosition, MouseButton button, ref bool handled);
|
||||
|
||||
/// <summary>
|
||||
/// Perform mouse move action.
|
||||
/// </summary>
|
||||
/// <param name="mouse">The mouse position.</param>
|
||||
public delegate void MouseMoveDelegate(ref Float2 mouse);
|
||||
/// <param name="mousePosition">The mouse position.</param>
|
||||
public delegate void MouseMoveDelegate(ref Float2 mousePosition);
|
||||
|
||||
/// <summary>
|
||||
/// Perform mouse move action in relative mode.
|
||||
/// </summary>
|
||||
/// <param name="mouseMotion">The relative mouse motion.</param>
|
||||
public delegate void MouseMoveRelativeDelegate(ref Float2 mouseMotion);
|
||||
|
||||
/// <summary>
|
||||
/// Perform mouse wheel action.
|
||||
/// </summary>
|
||||
/// <param name="mouse">The mouse position.</param>
|
||||
/// <param name="mousePosition">The mouse position.</param>
|
||||
/// <param name="delta">The mouse wheel move delta (can be positive or negative; normalized to [-1;1] range).</param>
|
||||
/// <param name="handled">The flag that indicated that event has been handled by the custom code and should not be passed further. By default it is set to false.</param>
|
||||
public delegate void MouseWheelDelegate(ref Float2 mouse, float delta, ref bool handled);
|
||||
public delegate void MouseWheelDelegate(ref Float2 mousePosition, float delta, ref bool handled);
|
||||
|
||||
/// <summary>
|
||||
/// Perform touch action.
|
||||
@@ -99,9 +105,14 @@ namespace FlaxEngine
|
||||
public event MouseWheelDelegate MouseWheel;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when mouse moves
|
||||
/// Event fired when mouse moves.
|
||||
/// </summary>
|
||||
public event MouseMoveDelegate MouseMove;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when mouse moves in relative mode.
|
||||
/// </summary>
|
||||
public event MouseMoveRelativeDelegate MouseMoveRelative;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when mouse leaves window.
|
||||
@@ -273,6 +284,12 @@ namespace FlaxEngine
|
||||
MouseMove?.Invoke(ref pos);
|
||||
GUI.OnMouseMove(pos);
|
||||
}
|
||||
|
||||
internal void Internal_OnMouseMoveRelative(ref Float2 mouseMotion)
|
||||
{
|
||||
MouseMoveRelative?.Invoke(ref mouseMotion);
|
||||
GUI.OnMouseMoveRelative(mouseMotion);
|
||||
}
|
||||
|
||||
internal void Internal_OnMouseLeave()
|
||||
{
|
||||
|
||||
@@ -265,19 +265,38 @@ bool WindowsMouse::WndProc(Window* window, const UINT msg, WPARAM wParam, LPARAM
|
||||
}
|
||||
case WM_LBUTTONDBLCLK:
|
||||
{
|
||||
OnMouseDoubleClick(mousePos, MouseButton::Left, window);
|
||||
if (!Input::Mouse->IsRelative())
|
||||
OnMouseDoubleClick(mousePos, MouseButton::Left, window);
|
||||
else
|
||||
OnMouseDown(mousePos, MouseButton::Left, window);
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
case WM_RBUTTONDBLCLK:
|
||||
{
|
||||
OnMouseDoubleClick(mousePos, MouseButton::Right, window);
|
||||
if (!Input::Mouse->IsRelative())
|
||||
OnMouseDoubleClick(mousePos, MouseButton::Right, window);
|
||||
else
|
||||
OnMouseDown(mousePos, MouseButton::Right, window);
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
case WM_MBUTTONDBLCLK:
|
||||
{
|
||||
OnMouseDoubleClick(mousePos, MouseButton::Middle, window);
|
||||
if (!Input::Mouse->IsRelative())
|
||||
OnMouseDoubleClick(mousePos, MouseButton::Middle, window);
|
||||
else
|
||||
OnMouseDown(mousePos, MouseButton::Middle, window);
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
case WM_XBUTTONDBLCLK:
|
||||
{
|
||||
const auto button = (HIWORD(wParam) & XBUTTON1) ? MouseButton::Extended1 : MouseButton::Extended2;
|
||||
if (!Input::Mouse->IsRelative())
|
||||
OnMouseDoubleClick(mousePos, button, window);
|
||||
else
|
||||
OnMouseDown(mousePos, button, window);
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -769,6 +769,15 @@ namespace FlaxEngine.GUI
|
||||
Tooltip?.OnMouseLeaveControl(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When mouse moves over control's area while mouse is in relative mode
|
||||
/// </summary>
|
||||
/// <param name="mouseMotion">Mouse relative motion</param>
|
||||
[NoAnimate]
|
||||
public virtual void OnMouseMoveRelative(Float2 mouseMotion)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When mouse leaves control's area
|
||||
|
||||
@@ -338,5 +338,17 @@ namespace FlaxEngine.GUI
|
||||
|
||||
base.OnMouseMove(location);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnMouseMoveRelative(Float2 mouseMotion)
|
||||
{
|
||||
if (_trackingControl != null)
|
||||
{
|
||||
_trackingControl.OnMouseMoveRelative(mouseMotion);
|
||||
return;
|
||||
}
|
||||
|
||||
base.OnMouseMoveRelative(mouseMotion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user