diff --git a/osu.Game.Rulesets.Tau.Tests/Objects/TestSceneHardBeat.cs b/osu.Game.Rulesets.Tau.Tests/Objects/TestSceneHardBeat.cs index 3a5f4909..3838d03e 100644 --- a/osu.Game.Rulesets.Tau.Tests/Objects/TestSceneHardBeat.cs +++ b/osu.Game.Rulesets.Tau.Tests/Objects/TestSceneHardBeat.cs @@ -1,9 +1,13 @@ using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Tau.Configuration; using osu.Game.Rulesets.Tau.Objects; using osu.Game.Rulesets.Tau.Objects.Drawables; using osu.Game.Rulesets.Tau.UI; @@ -15,16 +19,39 @@ public partial class TestSceneHardBeat : TauTestScene { private int depthIndex; - public TestSceneHardBeat() + private TauPlayfieldAdjustmentContainer container; + private BindableBool increaseVisualDistinction = new BindableBool(); + + [Test] + public void TestHardBeat() + { + AddStep("clear screen", Clear); + AddStep("add container", () => Add(container = new TauPlayfieldAdjustmentContainer())); + + AddStep("Visual distinction disabled", () => increaseVisualDistinction.Value = false); + AddStep("Miss single", () => container.Child = testSingle()); + AddStep("Hit single", () => container.Child = testSingle(true)); + AddUntilStep("Wait for object despawn", () => !Children.Any(h => h is DrawableHardBeat { AllJudged: false })); + } + + [Test] + public void TestVisuallyDistinctHardBeat() { - TauPlayfieldAdjustmentContainer container; - Add(container = new TauPlayfieldAdjustmentContainer()); + AddStep("clear screen", Clear); + AddStep("add container", () => Add(container = new TauPlayfieldAdjustmentContainer())); + AddStep("Visual distinction enabled", () => increaseVisualDistinction.Value = true); AddStep("Miss single", () => container.Child = testSingle()); AddStep("Hit single", () => container.Child = testSingle(true)); AddUntilStep("Wait for object despawn", () => !Children.Any(h => h is DrawableHardBeat { AllJudged: false })); } + [BackgroundDependencyLoader] + private void load() { + var config = (TauRulesetConfigManager)RulesetConfigs.GetConfigFor(Ruleset.Value.CreateInstance()).AsNonNull(); + config.BindWith(TauRulesetSettings.IncreaseVisualDistinction, increaseVisualDistinction); + } + private Drawable testSingle(bool auto = false) { var circle = new HardBeat diff --git a/osu.Game.Rulesets.Tau.Tests/Objects/TestSceneSliderHardBeat.cs b/osu.Game.Rulesets.Tau.Tests/Objects/TestSceneSliderHardBeat.cs index fed66f59..c007549d 100644 --- a/osu.Game.Rulesets.Tau.Tests/Objects/TestSceneSliderHardBeat.cs +++ b/osu.Game.Rulesets.Tau.Tests/Objects/TestSceneSliderHardBeat.cs @@ -1,10 +1,14 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Tau.Configuration; using osu.Game.Rulesets.Tau.Objects; using osu.Game.Rulesets.Tau.Objects.Drawables; using osu.Game.Rulesets.Tau.UI; @@ -17,16 +21,36 @@ public partial class TestSceneSliderHardBeat : TauTestScene private int depthIndex; private TauPlayfieldAdjustmentContainer container; + private BindableBool increaseVisualDistinction = new BindableBool(); + + [BackgroundDependencyLoader] + private void load() { + var config = (TauRulesetConfigManager)RulesetConfigs.GetConfigFor(Ruleset.Value.CreateInstance()).AsNonNull(); + config.BindWith(TauRulesetSettings.IncreaseVisualDistinction, increaseVisualDistinction); + } [Test] public void TestSingleSlider() { AddStep("clear screen", Clear); AddStep("add container", () => Add(container = new TauPlayfieldAdjustmentContainer())); + AddStep("visual distinction disabled", () => increaseVisualDistinction.Value = false); AddStep("Miss Single", () => container.Add(testSingle())); AddStep("Hit Single", () => container.Add(testSingle(true))); - AddUntilStep("Wait for object despawn", () => !Children.Any(h => h is DrawableSlider { AllJudged: false })); + AddUntilStep("Wait for object despawn", () => !container.Any(h => h is DrawableSlider { AllJudged: false })); + } + + [Test] + public void TestVisuallyDistinctSingleSlider() + { + AddStep("clear screen", Clear); + AddStep("add container", () => Add(container = new TauPlayfieldAdjustmentContainer())); + AddStep("visual distinction enabled", () => increaseVisualDistinction.Value = true); + + AddStep("Miss single", () => container.Add(testSingle())); + AddStep("Hit single", () => container.Add(testSingle(true))); + AddUntilStep("Wait for object despawn", () => !container.Any(h => h is DrawableSlider { AllJudged: false })); } [Test] @@ -35,8 +59,8 @@ public void TestSliderPerformance() AddStep("clear screen", Clear); AddStep("add container", () => Add(container = new TauPlayfieldAdjustmentContainer())); - AddStep("Miss Single", () => container.AddRange(testMultiple(100))); - AddStep("Hit Single", () => container.AddRange(testMultiple(100, true))); + AddStep("Miss many", () => container.AddRange(testMultiple(100))); + AddStep("Hit many", () => container.AddRange(testMultiple(100, true))); } private IEnumerable testMultiple(int count, bool auto = false) diff --git a/osu.Game.Rulesets.Tau.Tests/Objects/TestSceneStrictHardBeat.cs b/osu.Game.Rulesets.Tau.Tests/Objects/TestSceneStrictHardBeat.cs index 384ded3c..499be24c 100644 --- a/osu.Game.Rulesets.Tau.Tests/Objects/TestSceneStrictHardBeat.cs +++ b/osu.Game.Rulesets.Tau.Tests/Objects/TestSceneStrictHardBeat.cs @@ -1,9 +1,13 @@ using System.Linq; using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Tau.Configuration; using osu.Game.Rulesets.Tau.Objects; using osu.Game.Rulesets.Tau.Objects.Drawables; using osu.Game.Rulesets.Tau.UI; @@ -15,16 +19,41 @@ public partial class TestSceneStrictHardBeat : TauTestScene { private int depthIndex; - public TestSceneStrictHardBeat() + private TauPlayfieldAdjustmentContainer container; + private BindableBool increaseVisualDistinction = new BindableBool(); + + [BackgroundDependencyLoader] + private void load() { + var config = (TauRulesetConfigManager)RulesetConfigs.GetConfigFor(Ruleset.Value.CreateInstance()).AsNonNull(); + config.BindWith(TauRulesetSettings.IncreaseVisualDistinction, increaseVisualDistinction); + } + + [Test] + public void TestStrictHardBeat() + { + AddStep("clear screen", Clear); + AddStep("add container", () => Add(container = new TauPlayfieldAdjustmentContainer())); + AddStep("visual distinction disabled", () => increaseVisualDistinction.Value = false); + + AddStep("Miss Single", () => container.Add(testSingle())); + AddStep("Hit Single", () => container.Add(testSingle(true))); + AddStep("Miss Stream", () => Add(testStream())); + AddStep("Hit Stream", () => Add(testStream(true))); + AddUntilStep("Wait for object despawn", () => !container.Any(h => h is DrawableTauHitObject { AllJudged: false })); + } + + [Test] + public void TestVisuallyDistinctStrictHardBeat() { - TauPlayfieldAdjustmentContainer container; - Add(container = new TauPlayfieldAdjustmentContainer()); + AddStep("clear screen", Clear); + AddStep("add container", () => Add(container = new TauPlayfieldAdjustmentContainer())); + AddStep("visual distinction enabled", () => increaseVisualDistinction.Value = true); - AddStep("Miss Single", () => container.Child = testSingle()); - AddStep("Hit Single", () => container.Child = testSingle(true)); + AddStep("Miss Single", () => container.Add(testSingle())); + AddStep("Hit Single", () => container.Add(testSingle(true))); AddStep("Miss Stream", () => Add(testStream())); AddStep("Hit Stream", () => Add(testStream(true))); - AddUntilStep("Wait for object despawn", () => !Children.Any(h => h is DrawableTauHitObject { AllJudged: false })); + AddUntilStep("Wait for object despawn", () => !container.Any(h => h is DrawableTauHitObject { AllJudged: false })); } private Drawable testSingle(bool auto = false, double timeOffset = 0, float angle = 0) diff --git a/osu.Game.Rulesets.Tau/Configuration/TauRulesetConfigManager.cs b/osu.Game.Rulesets.Tau/Configuration/TauRulesetConfigManager.cs index 81428d1c..89ad2c71 100644 --- a/osu.Game.Rulesets.Tau/Configuration/TauRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Tau/Configuration/TauRulesetConfigManager.cs @@ -18,6 +18,7 @@ protected override void InitialiseDefaults() SetDefault(TauRulesetSettings.ShowVisualizer, true); SetDefault(TauRulesetSettings.ShowSliderEffects, true); SetDefault(TauRulesetSettings.HitLighting, false); + SetDefault(TauRulesetSettings.IncreaseVisualDistinction, false); SetDefault(TauRulesetSettings.KiaiType, KiaiType.Turbulence); SetDefault(TauRulesetSettings.PlayfieldDim, 0.7f, 0, 1, 0.01f); SetDefault(TauRulesetSettings.NotesSize, 16f, 10, 25, 1f); @@ -30,6 +31,7 @@ public enum TauRulesetSettings ShowVisualizer, ShowSliderEffects, // There's no real reason to have a toggle for showing Kiai effects, as that's already handled under KiaiType HitLighting, + IncreaseVisualDistinction, KiaiType, PlayfieldDim, NotesSize, diff --git a/osu.Game.Rulesets.Tau/Localisation/SettingStrings.cs b/osu.Game.Rulesets.Tau/Localisation/SettingStrings.cs index 228c8342..e130c557 100644 --- a/osu.Game.Rulesets.Tau/Localisation/SettingStrings.cs +++ b/osu.Game.Rulesets.Tau/Localisation/SettingStrings.cs @@ -26,6 +26,11 @@ public static class SettingStrings /// public static LocalisableString HitLighting => new TranslatableString(getKey(@"hit_lighting"), @"Hit Lighting"); + /// + /// "Increase Visual Distinction" + /// + public static LocalisableString IncreaseVisualDistinction = new TranslatableString(getKey(@"visual_distinction"), @"Increase Visual Distinction"); + /// /// "Kiai Type" /// diff --git a/osu.Game.Rulesets.Tau/Localisation/Translations/Settings.resx b/osu.Game.Rulesets.Tau/Localisation/Translations/Settings.resx index d2b7b975..f2369617 100644 --- a/osu.Game.Rulesets.Tau/Localisation/Translations/Settings.resx +++ b/osu.Game.Rulesets.Tau/Localisation/Translations/Settings.resx @@ -67,4 +67,7 @@ Hit Lighting + + Increase Visual Distinction + \ No newline at end of file diff --git a/osu.Game.Rulesets.Tau/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Tau/Objects/Drawables/DrawableSlider.cs index 6442aa8f..693aa952 100644 --- a/osu.Game.Rulesets.Tau/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Tau/Objects/Drawables/DrawableSlider.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Rendering; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Textures; using osu.Framework.Platform; using osu.Framework.Utils; using osu.Game.Audio; @@ -16,6 +17,7 @@ using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Tau.Configuration; using osu.Game.Rulesets.Tau.Judgements; using osu.Game.Rulesets.Tau.UI; using osu.Game.Skinning; @@ -28,6 +30,7 @@ public partial class DrawableSlider : DrawableAngledTauHitObject public Drawable SliderHead => headContainer.Child; private readonly BindableFloat size = new(16f); + public BindableBool IncreaseVisualDistinction = new(false); public float PathDistance = TauPlayfield.BASE_SIZE.X / 2; @@ -141,13 +144,29 @@ protected override void ClearNestedHitObjects() private float convertNoteSizeToSliderSize(float beatSize) => Interpolation.ValueAt(beatSize, 2f, 7f, 10f, 25f); + private Color4 convertVisualDistinctionSettingToColor(bool increaseVisualDistinction) + => increaseVisualDistinction && HitObject.IsHard ? Color4.Orange : Color4.White; + [BackgroundDependencyLoader] - private void load(IRenderer renderer, GameHost host) + private void load(IRenderer renderer, GameHost host, TauRulesetConfigManager config) { + config.BindWith(TauRulesetSettings.IncreaseVisualDistinction, IncreaseVisualDistinction); + NoteSize.BindValueChanged(value => path.PathRadius = convertNoteSizeToSliderSize(value.NewValue), true); host.DrawThread.Scheduler.AddDelayed(() => drawCache.Invalidate(), 0, true); path.Texture = properties.SliderTexture ??= generateSmoothPathTexture(renderer, path.PathRadius, _ => Color4.White); + + IncreaseVisualDistinction.BindValueChanged(value => { + if (value.NewValue) + { + properties.VisuallyDistinctSliderTexture ??= generateSmoothPathTexture(renderer, path.PathRadius, _ => Color4.Orange); + } + + path.Texture = (value.NewValue && HitObject.IsHard) + ? properties.VisuallyDistinctSliderTexture + : properties.SliderTexture; + }); } [Resolved] @@ -169,6 +188,8 @@ protected override void OnApply() path.Reverse = inversed; // PathDistance = path.PathDistance = TauPlayfield.BaseSize.X; } + + IncreaseVisualDistinction.TriggerChange(); } protected override void OnFree() diff --git a/osu.Game.Rulesets.Tau/Objects/Drawables/Pieces/HardBeatPiece.cs b/osu.Game.Rulesets.Tau/Objects/Drawables/Pieces/HardBeatPiece.cs index c9eeeae3..e3a1842b 100644 --- a/osu.Game.Rulesets.Tau/Objects/Drawables/Pieces/HardBeatPiece.cs +++ b/osu.Game.Rulesets.Tau/Objects/Drawables/Pieces/HardBeatPiece.cs @@ -1,8 +1,10 @@ -using osu.Framework.Bindables; +using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Utils; +using osu.Game.Rulesets.Tau.Configuration; using osuTK.Graphics; namespace osu.Game.Rulesets.Tau.Objects.Drawables.Pieces @@ -10,6 +12,7 @@ namespace osu.Game.Rulesets.Tau.Objects.Drawables.Pieces public partial class HardBeatPiece : CircularContainer { public BindableFloat NoteSize = new(16f); + public BindableBool IncreaseVisualDistinction = new(false); public HardBeatPiece() { @@ -30,6 +33,13 @@ public HardBeatPiece() }; NoteSize.BindValueChanged(value => BorderThickness = convertNoteSizeToThickness(value.NewValue)); + IncreaseVisualDistinction.BindValueChanged(value => BorderColour = value.NewValue ? Color4.Orange : Color4.White); + } + + [BackgroundDependencyLoader] + private void load(TauRulesetConfigManager config) + { + config.BindWith(TauRulesetSettings.IncreaseVisualDistinction, IncreaseVisualDistinction); } private float convertNoteSizeToThickness(float noteSize) diff --git a/osu.Game.Rulesets.Tau/Objects/Drawables/Pieces/StrictHardBeatPiece.cs b/osu.Game.Rulesets.Tau/Objects/Drawables/Pieces/StrictHardBeatPiece.cs index 2826399e..b52e40ea 100644 --- a/osu.Game.Rulesets.Tau/Objects/Drawables/Pieces/StrictHardBeatPiece.cs +++ b/osu.Game.Rulesets.Tau/Objects/Drawables/Pieces/StrictHardBeatPiece.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.UserInterface; using osu.Framework.Utils; +using osu.Game.Rulesets.Tau.Configuration; using osuTK; using osuTK.Graphics; @@ -12,6 +13,7 @@ public partial class StrictHardBeatPiece : CircularProgress { public BindableFloat NoteSize = new(16f); public BindableDouble AngleRange = new(25 * 0.75); + public BindableBool IncreaseVisualDistinction = new(false); public StrictHardBeatPiece() { @@ -28,14 +30,17 @@ public StrictHardBeatPiece() Progress = val.NewValue / 360; Rotation = -(float)(val.NewValue / 2); }, true); + IncreaseVisualDistinction.BindValueChanged(value => Colour = value.NewValue ? Color4.Orange : Color4.White); } [BackgroundDependencyLoader] - private void load() + private void load(TauRulesetConfigManager config) { // Size is set to zero here as to avoid standard fallback to original sprite's size (1,1), // see: https://github.com/ppy/osu-framework/blob/603e15fb2e68826e55878dfc09e1d7414b7cdf90/osu.Framework/Graphics/Sprites/Sprite.cs#L181-L182 Size = Vector2.Zero; + + config?.BindWith(TauRulesetSettings.IncreaseVisualDistinction, IncreaseVisualDistinction); } private float toNormalized(float value) diff --git a/osu.Game.Rulesets.Tau/UI/TauCachedProperties.cs b/osu.Game.Rulesets.Tau/UI/TauCachedProperties.cs index 6411457f..dc471c51 100644 --- a/osu.Game.Rulesets.Tau/UI/TauCachedProperties.cs +++ b/osu.Game.Rulesets.Tau/UI/TauCachedProperties.cs @@ -13,6 +13,7 @@ public class TauCachedProperties : IDisposable public readonly BindableDouble AngleRange = new(25); public readonly BindableBool InverseModEnabled = new(); public Texture SliderTexture; + public Texture VisuallyDistinctSliderTexture; /// /// Sets the range for the paddle. @@ -23,10 +24,10 @@ public void SetRange(float cs) AngleRange.Value = IBeatmapDifficultyInfo.DifficultyRange(cs, 75, 25, 10); } - public void Dispose() - { + public void Dispose() { SliderTexture?.Dispose(); - SliderTexture = null; + VisuallyDistinctSliderTexture?.Dispose(); + SliderTexture = VisuallyDistinctSliderTexture = null; } } } diff --git a/osu.Game.Rulesets.Tau/UI/TauSettingsSubsection.cs b/osu.Game.Rulesets.Tau/UI/TauSettingsSubsection.cs index 2a545dd1..e26637f7 100644 --- a/osu.Game.Rulesets.Tau/UI/TauSettingsSubsection.cs +++ b/osu.Game.Rulesets.Tau/UI/TauSettingsSubsection.cs @@ -51,6 +51,11 @@ private void load() LabelText = SettingStrings.HitLighting, Current = config.GetBindable(TauRulesetSettings.HitLighting) }, + new SettingsCheckbox + { + LabelText = SettingStrings.IncreaseVisualDistinction, + Current = config.GetBindable(TauRulesetSettings.IncreaseVisualDistinction) + }, kiaiType = new SettingsEnumDropdown() { LabelText = SettingStrings.KiaiType,