Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 145 additions & 0 deletions osu.Game.Rulesets.Osu.Tests/TestSceneSliderEndMissJudgement.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// 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.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Screens;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Replays;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu.Configuration;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Rulesets.Osu.Replays;
using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
using osu.Game.Screens.Play;
using osu.Game.Tests.Visual;
using osuTK;

namespace osu.Game.Rulesets.Osu.Tests
{
public partial class TestSceneSliderEndMissJudgement : RateAdjustedBeatmapTestScene
{
private const double time_slider_start = 1000;
private const float slider_path_length = 200;

private static readonly Vector2 slider_start_position = new Vector2(256 - slider_path_length / 2, 192);

private OsuRulesetConfigManager config = null!;

private ScoreAccessibleReplayPlayer currentPlayer = null!;
private readonly List<JudgementResult> judgementResults = new List<JudgementResult>();

[BackgroundDependencyLoader]
private void load()
{
config = (OsuRulesetConfigManager)RulesetConfigs.GetConfigFor(new OsuRuleset()).AsNonNull();
}

[Test]
public void TestMissMarkersHidden()
{
AddStep("disable slider tick miss markers", () => config.SetValue(OsuRulesetSetting.ShowSliderTickMissMarkers, false));

performMiss();

AddUntilStep("wait for tick miss", () => judgementResults.Any(r => r.Type == HitResult.LargeTickMiss));
AddAssert("no slider miss markers shown", () => !currentPlayer.ChildrenOfType<DrawableOsuJudgement>()
.Any(j => j.Result?.Type is HitResult.LargeTickMiss or HitResult.IgnoreMiss));
}

[Test]
public void TestMissMarkersShown()
{
AddStep("enable slider tick miss markers", () => config.SetValue(OsuRulesetSetting.ShowSliderTickMissMarkers, true));

performMiss();

AddUntilStep("slider miss markers shown", () => currentPlayer.ChildrenOfType<DrawableOsuJudgement>()
.Any(j => j.Result?.Type is HitResult.LargeTickMiss or HitResult.IgnoreMiss));
}

private void performMiss()
{
performTest(new List<ReplayFrame>
{
new OsuReplayFrame(time_slider_start - 150, slider_start_position, OsuAction.LeftButton),
new OsuReplayFrame(time_slider_start - 50, slider_start_position),
});
}

private void performTest(List<ReplayFrame> frames)
{
AddStep("load player", () =>
{
Beatmap.Value = CreateWorkingBeatmap(new Beatmap<OsuHitObject>
{
HitObjects =
{
new Slider
{
StartTime = time_slider_start,
Position = slider_start_position,
TickDistanceMultiplier = 3,
Path = new SliderPath(PathType.LINEAR, new[]
{
Vector2.Zero,
new Vector2(slider_path_length, 0),
}, slider_path_length),
}
},
BeatmapInfo =
{
Difficulty = new BeatmapDifficulty
{
SliderMultiplier = 1,
SliderTickRate = 3,
OverallDifficulty = 0
},
Ruleset = new OsuRuleset().RulesetInfo,
}
});

var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } });

p.OnLoadComplete += _ =>
{
p.ScoreProcessor.NewJudgement += result =>
{
if (currentPlayer == p) judgementResults.Add(result);
};
};

LoadScreen(currentPlayer = p);
judgementResults.Clear();
});

AddUntilStep("Beatmap at 0", () => Beatmap.Value.Track.CurrentTime == 0);
AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen());
}

private partial class ScoreAccessibleReplayPlayer : ReplayPlayer
{
public new ScoreProcessor ScoreProcessor => base.ScoreProcessor;

protected override bool PauseOnFocusLost => false;

public ScoreAccessibleReplayPlayer(Score score)
: base(score, new PlayerConfiguration
{
AllowPause = false,
ShowResults = false,
})
{
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ protected override void InitialiseDefaults()
base.InitialiseDefaults();
SetDefault(OsuRulesetSetting.SnakingInSliders, true);
SetDefault(OsuRulesetSetting.SnakingOutSliders, true);
SetDefault(OsuRulesetSetting.ShowSliderTickMissMarkers, true);
SetDefault(OsuRulesetSetting.HitAnimations, true);
SetDefault(OsuRulesetSetting.ShowCursorTrail, true);
SetDefault(OsuRulesetSetting.ShowCursorRipples, false);
Expand All @@ -36,6 +37,7 @@ public enum OsuRulesetSetting
{
SnakingInSliders,
SnakingOutSliders,
ShowSliderTickMissMarkers,
HitAnimations,
ShowCursorTrail,
ShowCursorRipples,
Expand Down
11 changes: 11 additions & 0 deletions osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Primitives;
Expand Down Expand Up @@ -52,6 +53,8 @@ public partial class OsuPlayfield : Playfield

private readonly Container judgementAboveHitObjectLayer;

private readonly Bindable<bool> showSliderTickMissMarkers = new Bindable<bool>(true);

public OsuPlayfield()
{
Anchor = Anchor.Centre;
Expand Down Expand Up @@ -135,6 +138,7 @@ private void onJudgementLoaded(DrawableOsuJudgement judgement)
private void load(OsuRulesetConfigManager? config, IBeatmap? beatmap)
{
config?.BindWith(OsuRulesetSetting.PlayfieldBorderStyle, playfieldBorder.PlayfieldBorderStyle);
config?.BindWith(OsuRulesetSetting.ShowSliderTickMissMarkers, showSliderTickMissMarkers);

var osuBeatmap = (OsuBeatmap?)beatmap;

Expand Down Expand Up @@ -194,6 +198,13 @@ private void onNewResult(DrawableHitObject judgedObject, JudgementResult result)
if (!judgedObject.DisplayResult || !DisplayJudgements.Value)
return;

// LargeTickMiss = slider ticks / ends / repeats; IgnoreMiss = slider tails.
if (!showSliderTickMissMarkers.Value
&& result.Type is HitResult.LargeTickMiss or HitResult.IgnoreMiss)
{
return;
}

var explosion = judgementPooler.Get(result.Type, doj => doj.Apply(result, judgedObject));

if (explosion == null)
Expand Down
5 changes: 5 additions & 0 deletions osu.Game.Rulesets.Osu/UI/OsuSettingsSubsection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ private void load()
ApplyClassicDefault = c => ((IHasCurrentValue<bool>)c).Current.Value = false,
},
new SettingsItemV2(new FormCheckBox
{
Caption = RulesetSettingsStrings.SliderTickMissMarkers,
Current = config.GetBindable<bool>(OsuRulesetSetting.ShowSliderTickMissMarkers)
}),
new SettingsItemV2(new FormCheckBox
{
Caption = RulesetSettingsStrings.HitAnimations,
HintText = RulesetSettingsStrings.HitAnimationsOsuTooltip,
Expand Down
5 changes: 5 additions & 0 deletions osu.Game/Localisation/RulesetSettingsStrings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ public static class RulesetSettingsStrings
/// </summary>
public static LocalisableString SnakingOutSliders => new TranslatableString(getKey(@"snaking_out_sliders"), @"Snaking out sliders");

/// <summary>
/// "Slider tick miss markers"
/// </summary>
public static LocalisableString SliderTickMissMarkers => new TranslatableString(getKey(@"slider_tick_miss_markers"), @"Slider tick miss markers");

/// <summary>
/// "Cursor trail"
/// </summary>
Expand Down
Loading