1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 03:22:57 +08:00

Automatically activate touch device mod in player

This commit is contained in:
Bartłomiej Dach 2023-10-25 20:27:07 +02:00
parent 29d4d81eaa
commit f2df02b60f
No known key found for this signature in database
4 changed files with 91 additions and 2 deletions

View File

@ -1,12 +1,15 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Input;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Timing;
using osu.Game.Configuration;
using osu.Game.Input;
using osu.Game.Overlays;
using osu.Game.Rulesets.Osu.Beatmaps;
using osu.Game.Rulesets.Osu.Mods;
@ -19,6 +22,9 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
{
public partial class TestSceneOsuModTouchDevice : PlayerTestScene
{
[Resolved]
private SessionStatics statics { get; set; } = null!;
private TestOnScreenDisplay testOnScreenDisplay = null!;
protected override Ruleset CreatePlayerRuleset() => new OsuRuleset();
@ -49,18 +55,26 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
private void load()
{
Add(testOnScreenDisplay = new TestOnScreenDisplay());
Add(new TouchInputInterceptor());
Dependencies.CacheAs<OnScreenDisplay>(testOnScreenDisplay);
}
public override void SetUpSteps()
{
base.SetUpSteps();
AddStep("reset OSD toast count", () => testOnScreenDisplay.ToastCount = 0);
AddStep("reset static", () => statics.SetValue(Static.TouchInputActive, false));
base.SetUpSteps();
}
[Test]
public void TestFirstObjectTouched()
public void TestUserAlreadyHasTouchDeviceActive()
{
// it is presumed that a previous screen (i.e. song select) will set this up
AddStep("set up touchscreen user", () =>
{
Player.Score.ScoreInfo.Mods = Player.Score.ScoreInfo.Mods.Append(new OsuModTouchDevice()).ToArray();
statics.SetValue(Static.TouchInputActive, true);
});
AddUntilStep("wait until 0 near", () => Player.GameplayClockContainer.CurrentTime, () => Is.GreaterThanOrEqualTo(0).Within(500));
AddStep("slow down", () => Player.GameplayClockContainer.AdjustmentsFromMods.Frequency.Value = 0.2);
AddUntilStep("wait until 0", () => Player.GameplayClockContainer.CurrentTime, () => Is.GreaterThanOrEqualTo(0));

View File

@ -0,0 +1,13 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
namespace osu.Game.Overlays.OSD
{
public partial class TouchDeviceDetectedToast : Toast
{
public TouchDeviceDetectedToast()
: base("osu!", "Touch device detected", "Touch Device mod applied to score")
{
}
}
}

View File

@ -285,6 +285,7 @@ namespace osu.Game.Screens.Play
fadeOut(true);
},
},
new PlayerTouchInputHandler()
});
if (cancellationToken.IsCancellationRequested)

View File

@ -0,0 +1,61 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Game.Configuration;
using osu.Game.Overlays;
using osu.Game.Overlays.OSD;
using osu.Game.Rulesets.Mods;
namespace osu.Game.Screens.Play
{
public partial class PlayerTouchInputHandler : Component
{
[Resolved]
private Player player { get; set; } = null!;
[Resolved]
private GameplayState gameplayState { get; set; } = null!;
[Resolved]
private OnScreenDisplay? onScreenDisplay { get; set; }
private IBindable<bool> touchActive = new BindableBool();
[BackgroundDependencyLoader]
private void load(SessionStatics statics)
{
touchActive = statics.GetBindable<bool>(Static.TouchInputActive);
touchActive.BindValueChanged(_ => updateState());
}
private void updateState()
{
if (!touchActive.Value)
return;
if (gameplayState.HasPassed || gameplayState.HasFailed || gameplayState.HasQuit)
return;
if (gameplayState.Score.ScoreInfo.Mods.OfType<ModTouchDevice>().Any())
return;
if (player.IsBreakTime.Value)
return;
var touchDeviceMod = gameplayState.Ruleset.GetTouchDeviceMod();
if (touchDeviceMod == null)
return;
onScreenDisplay?.Display(new TouchDeviceDetectedToast());
// TODO: this is kinda crude. `Player` (probably rightly so) assumes immutability of mods.
// this probably should be shown immediately on screen in the HUD,
// which means that immutability will probably need to be revisited.
player.Score.ScoreInfo.Mods = player.Score.ScoreInfo.Mods.Append(touchDeviceMod).ToArray();
}
}
}