Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix various cases of mouse delta values being incorrect #796

Merged
merged 9 commits into from Jun 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,18 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE

using OpenTK;

namespace osu.Framework.Desktop.Input.Handlers.Mouse
{
/// <summary>
/// An OpenTK state which came from an event callback.
/// </summary>
internal class OpenTKEventMouseState : OpenTKMouseState
{
public OpenTKEventMouseState(OpenTK.Input.MouseState tkState, bool active, Vector2? mappedPosition)
: base(tkState, active, mappedPosition)
{
}
}
}
17 changes: 9 additions & 8 deletions osu.Framework.Desktop/Input/Handlers/Mouse/OpenTKMouseHandler.cs
Expand Up @@ -44,9 +44,14 @@ public override bool Initialize(GameHost host)
if (mouseInWindow || !host.Window.Visible) return;

var state = OpenTK.Input.Mouse.GetCursorState();

if (state.Equals(lastState)) return;

lastState = state;

var mapped = host.Window.PointToClient(new Point(state.X, state.Y));

handleState(state, new Vector2(mapped.X, mapped.Y));
handleState(new OpenTKPollMouseState(state, host.IsActive, new Vector2(mapped.X, mapped.Y)));
}, 0, 1000.0 / 60));
}
else
Expand All @@ -70,16 +75,12 @@ private void handleMouseEvent(object sender, MouseEventArgs e)
if (!mouseInWindow)
return;

handleState(e.Mouse);
handleState(new OpenTKEventMouseState(e.Mouse, host.IsActive, null));
}

private void handleState(OpenTK.Input.MouseState state, Vector2? mappedPosition = null)
private void handleState(MouseState state)
{
if (state.Equals(lastState)) return;

lastState = state;

PendingStates.Enqueue(new InputState { Mouse = new OpenTKMouseState(state, host.IsActive, mappedPosition) });
PendingStates.Enqueue(new InputState { Mouse = state });
FrameStatistics.Increment(StatisticsCounterType.MouseEvents);
}

Expand Down
Expand Up @@ -7,13 +7,13 @@

namespace osu.Framework.Desktop.Input.Handlers.Mouse
{
internal class OpenTKMouseState : MouseState
internal abstract class OpenTKMouseState : MouseState
{
public readonly bool WasActive;

public override int WheelDelta => WasActive ? base.WheelDelta : 0;

public OpenTKMouseState(OpenTK.Input.MouseState tkState, bool active, Vector2? mappedPosition)
protected OpenTKMouseState(OpenTK.Input.MouseState tkState, bool active, Vector2? mappedPosition)
{
WasActive = active;

Expand Down
18 changes: 18 additions & 0 deletions osu.Framework.Desktop/Input/Handlers/Mouse/OpenTKPollMouseState.cs
@@ -0,0 +1,18 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE

using OpenTK;

namespace osu.Framework.Desktop.Input.Handlers.Mouse
{
/// <summary>
/// An OpenTK state which was retrieved via polling.
/// </summary>
internal class OpenTKPollMouseState : OpenTKMouseState
{
public OpenTKPollMouseState(OpenTK.Input.MouseState tkState, bool active, Vector2? mappedPosition)
: base(tkState, active, mappedPosition)
{
}
}
}
Expand Up @@ -73,13 +73,18 @@ public override bool Initialize(GameHost host)
currentPosition = new Vector2(screenPoint.X, screenPoint.Y);
}

lastState = state;

// While not focused, let's silently ignore everything but position.
if (!host.Window.Focused)
if (host.Window.Focused)
{
lastState = state;
}
else
{
lastState = null;
state = new OpenTK.Input.MouseState();
}

PendingStates.Enqueue(new InputState { Mouse = new OpenTKMouseState(state, host.IsActive, currentPosition) });
PendingStates.Enqueue(new InputState { Mouse = new OpenTKPollMouseState(state, host.IsActive, currentPosition) });

FrameStatistics.Increment(StatisticsCounterType.MouseEvents);
}, 0, 0));
Expand Down
2 changes: 2 additions & 0 deletions osu.Framework.Desktop/osu.Framework.Desktop.csproj
Expand Up @@ -64,6 +64,8 @@
<Compile Include="Host.cs" />
<Compile Include="Input\GameWindowTextInput.cs" />
<Compile Include="Input\Handlers\Keyboard\OpenTKKeyboardHandler.cs" />
<Compile Include="Input\Handlers\Mouse\OpenTKEventMouseState.cs" />
<Compile Include="Input\Handlers\Mouse\OpenTKPollMouseState.cs" />
<Compile Include="Input\Handlers\Mouse\OpenTKRawMouseHandler.cs" />
<Compile Include="Input\Handlers\Mouse\OpenTKMouseHandler.cs" />
<Compile Include="Input\Handlers\Mouse\OpenTKMouseState.cs" />
Expand Down
10 changes: 9 additions & 1 deletion osu.Framework/Graphics/Drawable.cs
Expand Up @@ -1890,11 +1890,14 @@ private struct LocalMouseState : IMouseState
{
public IMouseState NativeState { get; }

public IMouseState LastState { get; set; }

private readonly Drawable us;

public LocalMouseState(IMouseState state, Drawable us)
{
NativeState = state;
LastState = null;
this.us = us;
}

Expand All @@ -1904,7 +1907,12 @@ public LocalMouseState(IMouseState state, Drawable us)

public Vector2 LastPosition => us.Parent?.ToLocalSpace(NativeState.LastPosition) ?? NativeState.LastPosition;

public Vector2? PositionMouseDown => NativeState.PositionMouseDown == null ? null : us.Parent?.ToLocalSpace(NativeState.PositionMouseDown.Value) ?? NativeState.PositionMouseDown;
public Vector2? PositionMouseDown
{
get { return NativeState.PositionMouseDown == null ? null : us.Parent?.ToLocalSpace(NativeState.PositionMouseDown.Value) ?? NativeState.PositionMouseDown; }
set { throw new NotImplementedException(); }
}

public bool HasMainButtonPressed => NativeState.HasMainButtonPressed;
public int Wheel => NativeState.Wheel;
public int WheelDelta => NativeState.WheelDelta;
Expand Down
4 changes: 3 additions & 1 deletion osu.Framework/Input/IMouseState.cs
Expand Up @@ -10,12 +10,14 @@ public interface IMouseState
{
IMouseState NativeState { get; }

IMouseState LastState { get; set; }

Vector2 Delta { get; }
Vector2 Position { get; }

Vector2 LastPosition { get; }

Vector2? PositionMouseDown { get; }
Vector2? PositionMouseDown { get; set; }

bool HasMainButtonPressed { get; }

Expand Down
10 changes: 9 additions & 1 deletion osu.Framework/Input/InputManager.cs
Expand Up @@ -186,7 +186,15 @@ protected override void Update()
//move above?
updateInputQueues(CurrentState);

(s.Mouse as MouseState)?.SetLast(last.Mouse); //necessary for now as last state is used internally for stuff
// we only want to set a last state if both the new and old state are of the same type.
// this avoids giving the new state a false impression of being able to calculate delta values based on a last
// state potentially from a different input source.
if (last.Mouse != null && s.Mouse != null && last.Mouse.GetType() == s.Mouse.GetType())
{
last.Mouse.LastState = null;
s.Mouse.LastState = last.Mouse;
s.Mouse.PositionMouseDown = last.Mouse.PositionMouseDown;
}

//hover could change even when the mouse state has not.
updateHoverEvents(CurrentState);
Expand Down
21 changes: 6 additions & 15 deletions osu.Framework/Input/MouseState.cs
Expand Up @@ -10,38 +10,29 @@ namespace osu.Framework.Input
{
public class MouseState : IMouseState
{
public IMouseState LastState;

private const int mouse_button_count = (int)MouseButton.LastButton;

public bool[] PressedButtons = new bool[mouse_button_count];

public IMouseState NativeState => this;

public virtual int WheelDelta => Wheel - (LastState?.Wheel ?? 0);
public IMouseState LastState { get; set; }

public virtual int WheelDelta => Wheel - LastState?.Wheel ?? 0;

public int Wheel { get; set; }

public bool HasMainButtonPressed => IsPressed(MouseButton.Left )|| IsPressed(MouseButton.Right);
public bool HasMainButtonPressed => IsPressed(MouseButton.Left) || IsPressed(MouseButton.Right);

public bool HasAnyButtonPressed => PressedButtons.Any(b => b);

public Vector2 Delta => Position - (LastState?.Position ?? Vector2.Zero);
public Vector2 Delta => Position - LastPosition;

public Vector2 Position { get; protected set; }

public Vector2 LastPosition => LastState?.Position ?? Position;

public Vector2? PositionMouseDown { get; internal set; }

public void SetLast(IMouseState last)
{
(last as MouseState)?.SetLast(null);

LastState = last;
if (last != null)
PositionMouseDown = last.PositionMouseDown;
}
public Vector2? PositionMouseDown { get; set; }

public IMouseState Clone()
{
Expand Down