mirror of https://github.com/ppy/osu
Merge pull request #3739 from UselessToucan/fix_idle_tracker
Fix idle tracker
This commit is contained in:
commit
1ddb98e409
|
@ -0,0 +1,135 @@
|
|||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Input;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestCaseIdleTracker : ManualInputManagerTestCase
|
||||
{
|
||||
private readonly IdleTrackingBox box1;
|
||||
private readonly IdleTrackingBox box2;
|
||||
private readonly IdleTrackingBox box3;
|
||||
private readonly IdleTrackingBox box4;
|
||||
|
||||
public TestCaseIdleTracker()
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
box1 = new IdleTrackingBox(1000)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Red,
|
||||
Anchor = Anchor.TopLeft,
|
||||
Origin = Anchor.TopLeft,
|
||||
},
|
||||
box2 = new IdleTrackingBox(2000)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Green,
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight,
|
||||
},
|
||||
box3 = new IdleTrackingBox(3000)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Blue,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
},
|
||||
box4 = new IdleTrackingBox(4000)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Orange,
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNudge()
|
||||
{
|
||||
AddStep("move mouse to top left", () => InputManager.MoveMouseTo(box1.ScreenSpaceDrawQuad.Centre));
|
||||
|
||||
AddUntilStep(() => box1.IsIdle && box2.IsIdle && box3.IsIdle && box4.IsIdle, "Wait for all idle");
|
||||
|
||||
AddStep("nudge mouse", () => InputManager.MoveMouseTo(box1.ScreenSpaceDrawQuad.Centre + new Vector2(1)));
|
||||
|
||||
AddAssert("check not idle", () => !box1.IsIdle);
|
||||
AddAssert("check idle", () => box2.IsIdle);
|
||||
AddAssert("check idle", () => box3.IsIdle);
|
||||
AddAssert("check idle", () => box4.IsIdle);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMovement()
|
||||
{
|
||||
AddStep("move mouse", () => InputManager.MoveMouseTo(box2.ScreenSpaceDrawQuad.Centre));
|
||||
|
||||
AddAssert("check not idle", () => box1.IsIdle);
|
||||
AddAssert("check not idle", () => !box2.IsIdle);
|
||||
AddAssert("check idle", () => box3.IsIdle);
|
||||
AddAssert("check idle", () => box4.IsIdle);
|
||||
|
||||
AddStep("move mouse", () => InputManager.MoveMouseTo(box3.ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("move mouse", () => InputManager.MoveMouseTo(box4.ScreenSpaceDrawQuad.Centre));
|
||||
|
||||
AddAssert("check not idle", () => box1.IsIdle);
|
||||
AddAssert("check not idle", () => !box2.IsIdle);
|
||||
AddAssert("check idle", () => !box3.IsIdle);
|
||||
AddAssert("check idle", () => !box4.IsIdle);
|
||||
|
||||
AddUntilStep(() => box1.IsIdle && box2.IsIdle && box3.IsIdle && box4.IsIdle, "Wait for all idle");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTimings()
|
||||
{
|
||||
AddStep("move mouse", () => InputManager.MoveMouseTo(ScreenSpaceDrawQuad.Centre));
|
||||
|
||||
AddAssert("check not idle", () => !box1.IsIdle && !box2.IsIdle && !box3.IsIdle && !box4.IsIdle);
|
||||
AddUntilStep(() => box1.IsIdle, "Wait for idle");
|
||||
AddAssert("check not idle", () => !box2.IsIdle && !box3.IsIdle && !box4.IsIdle);
|
||||
AddUntilStep(() => box2.IsIdle, "Wait for idle");
|
||||
AddAssert("check not idle", () => !box3.IsIdle && !box4.IsIdle);
|
||||
AddUntilStep(() => box3.IsIdle, "Wait for idle");
|
||||
|
||||
AddUntilStep(() => box1.IsIdle && box2.IsIdle && box3.IsIdle && box4.IsIdle, "Wait for all idle");
|
||||
}
|
||||
|
||||
private class IdleTrackingBox : CompositeDrawable
|
||||
{
|
||||
private readonly IdleTracker idleTracker;
|
||||
|
||||
public bool IsIdle => idleTracker.IsIdle.Value;
|
||||
|
||||
public IdleTrackingBox(double timeToIdle)
|
||||
{
|
||||
Box box;
|
||||
|
||||
Alpha = 0.6f;
|
||||
Scale = new Vector2(0.6f);
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
idleTracker = new IdleTracker(timeToIdle),
|
||||
box = new Box
|
||||
{
|
||||
Colour = Color4.White,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
};
|
||||
|
||||
idleTracker.IsIdle.BindValueChanged(idle => box.Colour = idle ? Color4.White : Color4.Black, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
|
||||
namespace osu.Game.Input
|
||||
{
|
||||
/// <summary>
|
||||
/// Track whether the end-user is in an idle state, based on their last interaction with the game.
|
||||
/// </summary>
|
||||
public class IdleTracker : Component, IKeyBindingHandler<PlatformAction>, IHandleGlobalInput
|
||||
{
|
||||
private readonly double timeToIdle;
|
||||
|
||||
private double lastInteractionTime;
|
||||
|
||||
protected double TimeSpentIdle => Clock.CurrentTime - lastInteractionTime;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the user is currently in an idle state.
|
||||
/// </summary>
|
||||
public IBindable<bool> IsIdle => isIdle;
|
||||
|
||||
private readonly BindableBool isIdle = new BindableBool();
|
||||
|
||||
/// <summary>
|
||||
/// Intstantiate a new <see cref="IdleTracker"/>.
|
||||
/// </summary>
|
||||
/// <param name="timeToIdle">The length in milliseconds until an idle state should be assumed.</param>
|
||||
public IdleTracker(double timeToIdle)
|
||||
{
|
||||
this.timeToIdle = timeToIdle;
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
isIdle.Value = TimeSpentIdle > timeToIdle;
|
||||
}
|
||||
|
||||
public bool OnPressed(PlatformAction action) => updateLastInteractionTime();
|
||||
|
||||
public bool OnReleased(PlatformAction action) => updateLastInteractionTime();
|
||||
|
||||
protected override bool Handle(UIEvent e)
|
||||
{
|
||||
switch (e)
|
||||
{
|
||||
case KeyDownEvent _:
|
||||
case KeyUpEvent _:
|
||||
case MouseDownEvent _:
|
||||
case MouseUpEvent _:
|
||||
case MouseMoveEvent _:
|
||||
return updateLastInteractionTime();
|
||||
default:
|
||||
return base.Handle(e);
|
||||
}
|
||||
}
|
||||
|
||||
private bool updateLastInteractionTime()
|
||||
{
|
||||
lastInteractionTime = Clock.CurrentTime;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@
|
|||
using osu.Framework.Threading;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Input;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Overlays.Notifications;
|
||||
using osu.Game.Rulesets;
|
||||
|
@ -88,6 +89,8 @@ private Intro intro
|
|||
|
||||
public float ToolbarOffset => Toolbar.Position.Y + Toolbar.DrawHeight;
|
||||
|
||||
private IdleTracker idleTracker;
|
||||
|
||||
public readonly Bindable<OverlayActivation> OverlayActivationMode = new Bindable<OverlayActivation>();
|
||||
|
||||
private OsuScreen screenStack;
|
||||
|
@ -316,6 +319,7 @@ protected override void LoadComplete()
|
|||
},
|
||||
mainContent = new Container { RelativeSizeAxes = Axes.Both },
|
||||
overlayContent = new Container { RelativeSizeAxes = Axes.Both, Depth = float.MinValue },
|
||||
idleTracker = new IdleTracker(6000)
|
||||
});
|
||||
|
||||
loadComponentSingleFile(screenStack = new Loader(), d =>
|
||||
|
@ -373,6 +377,7 @@ protected override void LoadComplete()
|
|||
Depth = -6,
|
||||
}, overlayContent.Add);
|
||||
|
||||
dependencies.Cache(idleTracker);
|
||||
dependencies.Cache(settings);
|
||||
dependencies.Cache(onscreenDisplay);
|
||||
dependencies.Cache(social);
|
||||
|
|
|
@ -8,12 +8,14 @@
|
|||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Configuration;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Input;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Overlays;
|
||||
using osuTK;
|
||||
|
@ -26,6 +28,8 @@ public class ButtonSystem : Container, IStateful<ButtonSystemState>, IKeyBinding
|
|||
{
|
||||
public event Action<ButtonSystemState> StateChanged;
|
||||
|
||||
private readonly IBindable<bool> isIdle = new BindableBool();
|
||||
|
||||
public Action OnEdit;
|
||||
public Action OnExit;
|
||||
public Action OnDirect;
|
||||
|
@ -102,12 +106,22 @@ public ButtonSystem()
|
|||
private OsuGame game;
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(AudioManager audio, OsuGame game)
|
||||
private void load(AudioManager audio, OsuGame game, IdleTracker idleTracker)
|
||||
{
|
||||
this.game = game;
|
||||
|
||||
isIdle.ValueChanged += updateIdleState;
|
||||
if (idleTracker != null) isIdle.BindTo(idleTracker.IsIdle);
|
||||
|
||||
sampleBack = audio.Sample.Get(@"Menu/button-back-select");
|
||||
}
|
||||
|
||||
private void updateIdleState(bool isIdle)
|
||||
{
|
||||
if (isIdle && State != ButtonSystemState.Exit)
|
||||
State = ButtonSystemState.Initial;
|
||||
}
|
||||
|
||||
public bool OnPressed(GlobalAction action)
|
||||
{
|
||||
switch (action)
|
||||
|
@ -266,9 +280,6 @@ private void updateLogoState(ButtonSystemState lastState = ButtonSystemState.Ini
|
|||
|
||||
protected override void Update()
|
||||
{
|
||||
//if (OsuGame.IdleTime > 6000 && State != MenuState.Exit)
|
||||
// State = MenuState.Initial;
|
||||
|
||||
base.Update();
|
||||
|
||||
if (logo != null)
|
||||
|
|
Loading…
Reference in New Issue