From 1366b53a7150c56165a534dacea2eae9933e0a3b Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Tue, 9 Oct 2018 13:16:27 +0200 Subject: [PATCH 001/239] Added traceable mod + HideButApproachCircle function for DrawableHitCircle --- osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 32 +++++++++++++++++++ .../Objects/Drawables/DrawableHitCircle.cs | 9 ++++++ osu.Game.Rulesets.Osu/OsuRuleset.cs | 1 + 3 files changed, 42 insertions(+) create mode 100644 osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs new file mode 100644 index 0000000000..43eac55ffd --- /dev/null +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using osu.Game.Graphics; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Osu.Objects.Drawables; + +namespace osu.Game.Rulesets.Osu.Mods +{ + internal class OsuModTraceable : Mod, IApplicableToDrawableHitObjects + { + public override string Name => "Traceable"; + public override string ShortenedName => "TC"; + public override FontAwesome Icon => FontAwesome.fa_snapchat_ghost; + public override ModType Type => ModType.Fun; + public override string Description => "Put your faith in the approach circles..."; + public override double ScoreMultiplier => 1; + + public void ApplyToDrawableHitObjects(IEnumerable drawables) + { + foreach (var drawable in drawables) + { + if (drawable is DrawableHitCircle c) + c.HideButApproachCircle(); + if (drawable is DrawableSlider s) + s.HeadCircle.HideButApproachCircle(); + } + } + } +} diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 4bdddcef11..79cc88e474 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -76,6 +76,15 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } + public void HideButApproachCircle() + { + circle.Hide(); + circle.AlwaysPresent = true; + ring.Hide(); + number.Hide(); + glow.Hide(); + } + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (!userTriggered) diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 6736d10dab..0b6aee7881 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -121,6 +121,7 @@ namespace osu.Game.Rulesets.Osu return new Mod[] { new OsuModTransform(), new OsuModWiggle(), + new OsuModTraceable(), }; default: return new Mod[] { }; From 954bcd8c123dcad1112ed94bc07bf3a824adfc9d Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Tue, 9 Oct 2018 18:36:12 +0200 Subject: [PATCH 002/239] Treat non-DrawableHitCircle's similar to OsuModHidden --- osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 61 +++++++++++++++++-- .../Objects/Drawables/DrawableHitCircle.cs | 2 + 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index 43eac55ffd..dfd398e7e4 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -1,11 +1,14 @@ // Copyright (c) 2007-2018 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Collections.Generic; using osu.Game.Graphics; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Osu.Mods { @@ -21,11 +24,61 @@ namespace osu.Game.Rulesets.Osu.Mods public void ApplyToDrawableHitObjects(IEnumerable drawables) { foreach (var drawable in drawables) + drawable.ApplyCustomUpdateState += ApplyTraceableState; + } + + /* Similar to ApplyHiddenState, only different if drawable is DrawableHitCircle. + * If we'd use ApplyHiddenState instead but only on non-DrawableHitCircle's, then + * the nested object HeadCircle of DrawableSlider would still use ApplyHiddenState, + * thus treating the DrawableHitCircle with the hidden mod instead of the traceable mod. + */ + protected void ApplyTraceableState(DrawableHitObject drawable, ArmedState state) + { + if (!(drawable is DrawableOsuHitObject d)) + return; + + var h = d.HitObject; + + var fadeOutStartTime = h.StartTime - h.TimePreempt + h.TimeFadeIn; + + // new duration from completed fade in to end (before fading out) + var longFadeDuration = ((h as IHasEndTime)?.EndTime ?? h.StartTime) - fadeOutStartTime; + + switch (drawable) { - if (drawable is DrawableHitCircle c) - c.HideButApproachCircle(); - if (drawable is DrawableSlider s) - s.HeadCircle.HideButApproachCircle(); + case DrawableHitCircle circle: + // we only want to see the approach circle + using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) + circle.HideButApproachCircle(); + + // approach circle fades out quickly at StartTime + using (drawable.BeginAbsoluteSequence(h.StartTime, true)) + circle.ApproachCircle.FadeOut(50); + + break; + case DrawableSlider slider: + using (slider.BeginAbsoluteSequence(fadeOutStartTime, true)) + slider.Body.FadeOut(longFadeDuration, Easing.Out); + + break; + case DrawableSliderTick sliderTick: + // slider ticks fade out over up to one second + var tickFadeOutDuration = Math.Min(sliderTick.HitObject.TimePreempt - DrawableSliderTick.ANIM_DURATION, 1000); + + using (sliderTick.BeginAbsoluteSequence(sliderTick.HitObject.StartTime - tickFadeOutDuration, true)) + sliderTick.FadeOut(tickFadeOutDuration); + + break; + case DrawableSpinner spinner: + // hide elements we don't care about. + spinner.Disc.Hide(); + spinner.Ticks.Hide(); + spinner.Background.Hide(); + + using (spinner.BeginAbsoluteSequence(fadeOutStartTime + longFadeDuration, true)) + spinner.FadeOut(h.TimePreempt); + + break; } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 79cc88e474..1644480aa4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -81,6 +81,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables circle.Hide(); circle.AlwaysPresent = true; ring.Hide(); + flash.Hide(); + explode.Hide(); number.Hide(); glow.Hide(); } From edb69463fd4318145ff97e2bb3a0219fc8f646dc Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Tue, 9 Oct 2018 18:52:34 +0200 Subject: [PATCH 003/239] Trimming whitespace from comment...... --- osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index dfd398e7e4..a6d8d35125 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Mods } /* Similar to ApplyHiddenState, only different if drawable is DrawableHitCircle. - * If we'd use ApplyHiddenState instead but only on non-DrawableHitCircle's, then + * If we'd use ApplyHiddenState instead but only on non-DrawableHitCircle's, then * the nested object HeadCircle of DrawableSlider would still use ApplyHiddenState, * thus treating the DrawableHitCircle with the hidden mod instead of the traceable mod. */ From dea2acaea3f24b6fb33cf7f1746002e7151941f7 Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Sun, 14 Oct 2018 11:18:10 -0400 Subject: [PATCH 004/239] Add new interface that allows restarts --- .../Rulesets/Mods/IApplicableForceRestart.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 osu.Game/Rulesets/Mods/IApplicableForceRestart.cs diff --git a/osu.Game/Rulesets/Mods/IApplicableForceRestart.cs b/osu.Game/Rulesets/Mods/IApplicableForceRestart.cs new file mode 100644 index 0000000000..2c9a6b6cb9 --- /dev/null +++ b/osu.Game/Rulesets/Mods/IApplicableForceRestart.cs @@ -0,0 +1,16 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Rulesets.Mods +{ + /// + /// Represents a mod which can override (and block) a fail. + /// + public interface IApplicableRestartOnFail : IApplicableMod + { + /// + /// Whether we allow restarting + /// + bool AllowRestart { get; } + } +} From fd774c6a09edf2abd7954e7fd4fc8703bd3d015e Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Sun, 14 Oct 2018 11:18:52 -0400 Subject: [PATCH 005/239] Allow restarts in ModPerfect --- osu.Game/Rulesets/Mods/ModPerfect.cs | 4 +++- osu.Game/Screens/Play/Player.cs | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModPerfect.cs b/osu.Game/Rulesets/Mods/ModPerfect.cs index 802890866f..5d6065b4a2 100644 --- a/osu.Game/Rulesets/Mods/ModPerfect.cs +++ b/osu.Game/Rulesets/Mods/ModPerfect.cs @@ -6,13 +6,15 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mods { - public abstract class ModPerfect : ModSuddenDeath + public abstract class ModPerfect : ModSuddenDeath, IApplicableRestartOnFail { public override string Name => "Perfect"; public override string ShortenedName => "PF"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_perfect; public override string Description => "SS or quit."; + public bool AllowRestart => true; + protected override bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Accuracy.Value != 1; } } diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index b3cbeb3850..0577369b05 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -289,6 +289,12 @@ namespace osu.Game.Screens.Play if (Beatmap.Value.Mods.Value.OfType().Any(m => !m.AllowFail)) return false; + if (Beatmap.Value.Mods.Value.OfType().Any(m => m.AllowRestart)) + { + Restart(); + return false; + } + adjustableClock.Stop(); HasFailed = true; From 39c767af2d349e3219b20690208694a4eb7d778a Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Sun, 14 Oct 2018 11:25:05 -0400 Subject: [PATCH 006/239] Update file name and update summary --- .../{IApplicableForceRestart.cs => IApplicableRestartOnFail.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename osu.Game/Rulesets/Mods/{IApplicableForceRestart.cs => IApplicableRestartOnFail.cs} (86%) diff --git a/osu.Game/Rulesets/Mods/IApplicableForceRestart.cs b/osu.Game/Rulesets/Mods/IApplicableRestartOnFail.cs similarity index 86% rename from osu.Game/Rulesets/Mods/IApplicableForceRestart.cs rename to osu.Game/Rulesets/Mods/IApplicableRestartOnFail.cs index 2c9a6b6cb9..43b3f36624 100644 --- a/osu.Game/Rulesets/Mods/IApplicableForceRestart.cs +++ b/osu.Game/Rulesets/Mods/IApplicableRestartOnFail.cs @@ -4,7 +4,7 @@ namespace osu.Game.Rulesets.Mods { /// - /// Represents a mod which can override (and block) a fail. + /// Represents a mod which can request to restart on fail. /// public interface IApplicableRestartOnFail : IApplicableMod { From d7d83a27d40289d73e819984721a9b18a0fa94e6 Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Wed, 24 Oct 2018 13:36:35 -0400 Subject: [PATCH 007/239] Add restart as mods settings --- osu.Game/Configuration/OsuConfigManager.cs | 2 ++ osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 9ac2cabe9f..bcdd3acd10 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -84,6 +84,7 @@ namespace osu.Game.Configuration Set(OsuSetting.ScoreDisplayMode, ScoringMode.Standardised); Set(OsuSetting.IncreaseFirstObjectVisibility, true); + Set(OsuSetting.RestartOnFail, false); // Update Set(OsuSetting.ReleaseStream, ReleaseStream.Lazer); @@ -148,6 +149,7 @@ namespace osu.Game.Configuration BeatmapSkins, BeatmapHitsounds, IncreaseFirstObjectVisibility, + RestartOnFail, ScoreDisplayMode } } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs index a9cefa81da..a3a0bf118b 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs @@ -20,6 +20,11 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay LabelText = "Increase visibility of first object with \"Hidden\" mod", Bindable = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility) }, + new SettingsCheckbox + { + LabelText = "Restart on fail with \"Perfect\" and \"Sudden Death\" mod", + Bindable = config.GetBindable(OsuSetting.RestartOnFail) + }, }; } } From 794afa988fe6e599ca9e13a1de130d7a765bf4c0 Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Wed, 24 Oct 2018 13:37:27 -0400 Subject: [PATCH 008/239] Make both SD and PF auto-restart based on settings --- osu.Game/Rulesets/Mods/ModPerfect.cs | 4 +--- osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 12 +++++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModPerfect.cs b/osu.Game/Rulesets/Mods/ModPerfect.cs index 5d6065b4a2..802890866f 100644 --- a/osu.Game/Rulesets/Mods/ModPerfect.cs +++ b/osu.Game/Rulesets/Mods/ModPerfect.cs @@ -6,15 +6,13 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mods { - public abstract class ModPerfect : ModSuddenDeath, IApplicableRestartOnFail + public abstract class ModPerfect : ModSuddenDeath { public override string Name => "Perfect"; public override string ShortenedName => "PF"; public override FontAwesome Icon => FontAwesome.fa_osu_mod_perfect; public override string Description => "SS or quit."; - public bool AllowRestart => true; - protected override bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Accuracy.Value != 1; } } diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 48f7d496a5..af7d9be785 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -3,11 +3,13 @@ using System; using osu.Game.Graphics; +using osu.Game.Configuration; using osu.Game.Rulesets.Scoring; +using osu.Framework.Configuration; namespace osu.Game.Rulesets.Mods { - public abstract class ModSuddenDeath : Mod, IApplicableToScoreProcessor + public abstract class ModSuddenDeath : Mod, IReadFromConfig, IApplicableToScoreProcessor, IApplicableRestartOnFail { public override string Name => "Sudden Death"; public override string ShortenedName => "SD"; @@ -18,11 +20,19 @@ namespace osu.Game.Rulesets.Mods public override bool Ranked => true; public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModRelax), typeof(ModAutoplay) }; + protected Bindable RestartOnFail = new Bindable(); + public bool AllowRestart => RestartOnFail.Value; + public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { scoreProcessor.FailConditions += FailCondition; } + public void ReadFromConfig(OsuConfigManager config) + { + RestartOnFail = config.GetBindable(OsuSetting.RestartOnFail); + } + protected virtual bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Combo.Value == 0; } } From cb9ec94dc2af3c511554b9a8a6ce0439164938c9 Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Mon, 29 Oct 2018 08:19:38 -0400 Subject: [PATCH 009/239] Remove option from settings --- osu.Game/Configuration/OsuConfigManager.cs | 2 -- .../Settings/Sections/Gameplay/ModsSettings.cs | 5 ----- osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 10 ++-------- 3 files changed, 2 insertions(+), 15 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index bcdd3acd10..9ac2cabe9f 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -84,7 +84,6 @@ namespace osu.Game.Configuration Set(OsuSetting.ScoreDisplayMode, ScoringMode.Standardised); Set(OsuSetting.IncreaseFirstObjectVisibility, true); - Set(OsuSetting.RestartOnFail, false); // Update Set(OsuSetting.ReleaseStream, ReleaseStream.Lazer); @@ -149,7 +148,6 @@ namespace osu.Game.Configuration BeatmapSkins, BeatmapHitsounds, IncreaseFirstObjectVisibility, - RestartOnFail, ScoreDisplayMode } } diff --git a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs index a3a0bf118b..a9cefa81da 100644 --- a/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Gameplay/ModsSettings.cs @@ -20,11 +20,6 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay LabelText = "Increase visibility of first object with \"Hidden\" mod", Bindable = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility) }, - new SettingsCheckbox - { - LabelText = "Restart on fail with \"Perfect\" and \"Sudden Death\" mod", - Bindable = config.GetBindable(OsuSetting.RestartOnFail) - }, }; } } diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index af7d9be785..77e08dff86 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -9,7 +9,7 @@ using osu.Framework.Configuration; namespace osu.Game.Rulesets.Mods { - public abstract class ModSuddenDeath : Mod, IReadFromConfig, IApplicableToScoreProcessor, IApplicableRestartOnFail + public abstract class ModSuddenDeath : Mod, IApplicableToScoreProcessor, IApplicableRestartOnFail { public override string Name => "Sudden Death"; public override string ShortenedName => "SD"; @@ -20,19 +20,13 @@ namespace osu.Game.Rulesets.Mods public override bool Ranked => true; public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModRelax), typeof(ModAutoplay) }; - protected Bindable RestartOnFail = new Bindable(); - public bool AllowRestart => RestartOnFail.Value; + public bool AllowRestart => true; public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { scoreProcessor.FailConditions += FailCondition; } - public void ReadFromConfig(OsuConfigManager config) - { - RestartOnFail = config.GetBindable(OsuSetting.RestartOnFail); - } - protected virtual bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Combo.Value == 0; } } From 52b9a3f5e9a0096ff5529a223a317b8b489977ec Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Mon, 29 Oct 2018 17:51:49 -0400 Subject: [PATCH 010/239] Remove unused using --- osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 77e08dff86..733fd6345a 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -3,9 +3,7 @@ using System; using osu.Game.Graphics; -using osu.Game.Configuration; using osu.Game.Rulesets.Scoring; -using osu.Framework.Configuration; namespace osu.Game.Rulesets.Mods { From 007dfedbb751fa0e4767740e39fcc621e73cdf54 Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Tue, 30 Oct 2018 07:12:06 -0400 Subject: [PATCH 011/239] Combine RestartOnFail into FailOverride --- osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs | 1 + .../Rulesets/Mods/IApplicableFailOverride.cs | 5 +++++ .../Rulesets/Mods/IApplicableRestartOnFail.cs | 16 ---------------- osu.Game/Rulesets/Mods/ModAutoplay.cs | 1 + osu.Game/Rulesets/Mods/ModNoFail.cs | 1 + osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 5 +++-- osu.Game/Screens/Play/Player.cs | 2 +- 7 files changed, 12 insertions(+), 19 deletions(-) delete mode 100644 osu.Game/Rulesets/Mods/IApplicableRestartOnFail.cs diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs index 8d27502b3c..2240425654 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModRelax.cs @@ -19,6 +19,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).ToArray(); public bool AllowFail => false; + public bool RestartOnFail => false; public void Update(Playfield playfield) { diff --git a/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs b/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs index 6a4042a906..f650259373 100644 --- a/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs +++ b/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs @@ -12,5 +12,10 @@ namespace osu.Game.Rulesets.Mods /// Whether we should allow failing at the current point in time. /// bool AllowFail { get; } + + /// + /// Whether we want to restart on fail. Only used if AllowFail is true. + /// + bool RestartOnFail { get; } } } diff --git a/osu.Game/Rulesets/Mods/IApplicableRestartOnFail.cs b/osu.Game/Rulesets/Mods/IApplicableRestartOnFail.cs deleted file mode 100644 index 43b3f36624..0000000000 --- a/osu.Game/Rulesets/Mods/IApplicableRestartOnFail.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -namespace osu.Game.Rulesets.Mods -{ - /// - /// Represents a mod which can request to restart on fail. - /// - public interface IApplicableRestartOnFail : IApplicableMod - { - /// - /// Whether we allow restarting - /// - bool AllowRestart { get; } - } -} diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index 5c03cb9736..849eaeeb5a 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -30,6 +30,7 @@ namespace osu.Game.Rulesets.Mods public override string Description => "Watch a perfect automated play through the song."; public override double ScoreMultiplier => 1; public bool AllowFail => false; + public bool RestartOnFail => false; public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail) }; } } diff --git a/osu.Game/Rulesets/Mods/ModNoFail.cs b/osu.Game/Rulesets/Mods/ModNoFail.cs index 7510f62432..c30c6d712d 100644 --- a/osu.Game/Rulesets/Mods/ModNoFail.cs +++ b/osu.Game/Rulesets/Mods/ModNoFail.cs @@ -21,5 +21,6 @@ namespace osu.Game.Rulesets.Mods /// We never fail, 'yo. /// public bool AllowFail => false; + public bool RestartOnFail => false; } } diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 733fd6345a..252df98f32 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -7,7 +7,7 @@ using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mods { - public abstract class ModSuddenDeath : Mod, IApplicableToScoreProcessor, IApplicableRestartOnFail + public abstract class ModSuddenDeath : Mod, IApplicableToScoreProcessor, IApplicableFailOverride { public override string Name => "Sudden Death"; public override string ShortenedName => "SD"; @@ -18,7 +18,8 @@ namespace osu.Game.Rulesets.Mods public override bool Ranked => true; public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModRelax), typeof(ModAutoplay) }; - public bool AllowRestart => true; + public bool AllowFail => true; + public bool RestartOnFail => true; public void ApplyToScoreProcessor(ScoreProcessor scoreProcessor) { diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 0577369b05..863cfeda07 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -289,7 +289,7 @@ namespace osu.Game.Screens.Play if (Beatmap.Value.Mods.Value.OfType().Any(m => !m.AllowFail)) return false; - if (Beatmap.Value.Mods.Value.OfType().Any(m => m.AllowRestart)) + if (Beatmap.Value.Mods.Value.OfType().Any(m => m.RestartOnFail)) { Restart(); return false; From d8f97a32c779f40005c6328c925ec9c327a5b54a Mon Sep 17 00:00:00 2001 From: Paul Teng Date: Wed, 31 Oct 2018 07:03:37 -0400 Subject: [PATCH 012/239] Make sure restart on fail actually fails --- osu.Game/Screens/Play/Player.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 863cfeda07..b388387866 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -289,15 +289,16 @@ namespace osu.Game.Screens.Play if (Beatmap.Value.Mods.Value.OfType().Any(m => !m.AllowFail)) return false; - if (Beatmap.Value.Mods.Value.OfType().Any(m => m.RestartOnFail)) - { - Restart(); - return false; - } - adjustableClock.Stop(); HasFailed = true; + + if (Beatmap.Value.Mods.Value.OfType().Any(m => m.RestartOnFail)) + { + Restart(); + return true; + } + failOverlay.Retries = RestartCount; failOverlay.Show(); return true; From 5496b8bc58fae51b4dc242bb5eb0051a7d2039a1 Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Mon, 1 Jul 2019 20:11:50 +0200 Subject: [PATCH 013/239] Rewrote traceable mod to inherit from hidden --- osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs | 3 + osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 2 + osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 90 ++++++++----------- .../Objects/Drawables/DrawableHitCircle.cs | 23 ++--- osu.Game/Overlays/Mods/ModSection.cs | 4 +- 5 files changed, 48 insertions(+), 74 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs index 8072dc09c1..9b1f43b209 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModGrow.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.Linq; using osu.Framework.Bindables; @@ -28,6 +29,8 @@ namespace osu.Game.Rulesets.Osu.Mods public override double ScoreMultiplier => 1; + public override Type[] IncompatibleMods => new[] { typeof(OsuModTraceable) }; + private Bindable increaseFirstObjectVisibility = new Bindable(); public void ReadFromConfig(OsuConfigManager config) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index ddf708d0f1..5887cb2865 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -17,6 +17,8 @@ namespace osu.Game.Rulesets.Osu.Mods { public override string Description => @"Play with no approach circles and fading circles/sliders."; public override double ScoreMultiplier => 1.06; + public override Type[] IncompatibleMods => new[] { typeof(OsuModTraceable) }; + private const double fade_in_duration_multiplier = 0.4; private const double fade_out_duration_multiplier = 0.3; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index a6d8d35125..858b7e15c8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -2,83 +2,63 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Linq; using System.Collections.Generic; -using osu.Game.Graphics; +using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables; -using osu.Framework.Graphics; -using osu.Game.Rulesets.Objects.Types; namespace osu.Game.Rulesets.Osu.Mods { - internal class OsuModTraceable : Mod, IApplicableToDrawableHitObjects + internal class OsuModTraceable : OsuModHidden, IReadFromConfig, IApplicableToDrawableHitObjects { public override string Name => "Traceable"; - public override string ShortenedName => "TC"; - public override FontAwesome Icon => FontAwesome.fa_snapchat_ghost; + public override string Acronym => "TC"; + public override IconUsage Icon => FontAwesome.Brands.SnapchatGhost; public override ModType Type => ModType.Fun; public override string Description => "Put your faith in the approach circles..."; public override double ScoreMultiplier => 1; + public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden), typeof(OsuModGrow) }; - public void ApplyToDrawableHitObjects(IEnumerable drawables) + public override void ApplyToDrawableHitObjects(IEnumerable drawables) { - foreach (var drawable in drawables) - drawable.ApplyCustomUpdateState += ApplyTraceableState; + foreach (var drawable in drawables.Skip(IncreaseFirstObjectVisibility.Value ? 1 : 0)) + { + switch (drawable) + { + case DrawableHitCircle _: + drawable.ApplyCustomUpdateState += ApplyTraceableState; + break; + case DrawableSlider slider: + slider.ApplyCustomUpdateState += ApplyHiddenState; + slider.HeadCircle.ApplyCustomUpdateState += ApplyTraceableState; + break; + default: + drawable.ApplyCustomUpdateState += ApplyHiddenState; + break; + } + } } - /* Similar to ApplyHiddenState, only different if drawable is DrawableHitCircle. - * If we'd use ApplyHiddenState instead but only on non-DrawableHitCircle's, then - * the nested object HeadCircle of DrawableSlider would still use ApplyHiddenState, - * thus treating the DrawableHitCircle with the hidden mod instead of the traceable mod. - */ protected void ApplyTraceableState(DrawableHitObject drawable, ArmedState state) { - if (!(drawable is DrawableOsuHitObject d)) + if (!(drawable is DrawableHitCircle circle)) return; - var h = d.HitObject; + var h = circle.HitObject; - var fadeOutStartTime = h.StartTime - h.TimePreempt + h.TimeFadeIn; - - // new duration from completed fade in to end (before fading out) - var longFadeDuration = ((h as IHasEndTime)?.EndTime ?? h.StartTime) - fadeOutStartTime; - - switch (drawable) + // we only want to see the approach circle + using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) { - case DrawableHitCircle circle: - // we only want to see the approach circle - using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) - circle.HideButApproachCircle(); - - // approach circle fades out quickly at StartTime - using (drawable.BeginAbsoluteSequence(h.StartTime, true)) - circle.ApproachCircle.FadeOut(50); - - break; - case DrawableSlider slider: - using (slider.BeginAbsoluteSequence(fadeOutStartTime, true)) - slider.Body.FadeOut(longFadeDuration, Easing.Out); - - break; - case DrawableSliderTick sliderTick: - // slider ticks fade out over up to one second - var tickFadeOutDuration = Math.Min(sliderTick.HitObject.TimePreempt - DrawableSliderTick.ANIM_DURATION, 1000); - - using (sliderTick.BeginAbsoluteSequence(sliderTick.HitObject.StartTime - tickFadeOutDuration, true)) - sliderTick.FadeOut(tickFadeOutDuration); - - break; - case DrawableSpinner spinner: - // hide elements we don't care about. - spinner.Disc.Hide(); - spinner.Ticks.Hide(); - spinner.Background.Hide(); - - using (spinner.BeginAbsoluteSequence(fadeOutStartTime + longFadeDuration, true)) - spinner.FadeOut(h.TimePreempt); - - break; + circle.circle.Hide(); // CirclePiece + circle.circle.AlwaysPresent = true; + circle.ring.Hide(); + circle.flash.Hide(); + circle.explode.Hide(); + circle.number.Hide(); + circle.glow.Hide(); + circle.ApproachCircle.Show(); } } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 67c8371340..31c86474cd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -17,12 +17,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public class DrawableHitCircle : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach { public ApproachCircle ApproachCircle; - private readonly CirclePiece circle; - private readonly RingPiece ring; - private readonly FlashPiece flash; - private readonly ExplodePiece explode; - private readonly NumberPiece number; - private readonly GlowPiece glow; + public readonly CirclePiece circle; + public readonly RingPiece ring; + public readonly FlashPiece flash; + public readonly ExplodePiece explode; + public readonly NumberPiece number; + public readonly GlowPiece glow; private readonly IBindable positionBindable = new Bindable(); private readonly IBindable stackHeightBindable = new Bindable(); @@ -113,17 +113,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } - public void HideButApproachCircle() - { - circle.Hide(); - circle.AlwaysPresent = true; - ring.Hide(); - flash.Hide(); - explode.Hide(); - number.Hide(); - glow.Hide(); - } - protected override void CheckForResult(bool userTriggered, double timeOffset) { if (!userTriggered) diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index dedd397fa5..0eca1bcbec 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -112,7 +112,7 @@ namespace osu.Game.Overlays.Mods if (selected == null) continue; foreach (var type in modTypes) - if (type.IsInstanceOfType(selected)) + if (type.IsInstanceOfType(selected) && !selected.GetType().IsSubclassOf(type)) { if (immediate) button.Deselect(); @@ -130,7 +130,7 @@ namespace osu.Game.Overlays.Mods { foreach (var button in buttons) { - int i = Array.FindIndex(button.Mods, m => modTypes.Any(t => t.IsInstanceOfType(m))); + int i = Array.FindIndex(button.Mods, m => modTypes.Any(t => t.IsInstanceOfType(m) && !m.GetType().IsSubclassOf(t))); if (i >= 0) button.SelectAt(i); From d753f446e4fb995ea8ad403c851e22ff9bf46d13 Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Mon, 1 Jul 2019 20:20:25 +0200 Subject: [PATCH 014/239] Updated license header --- osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index 858b7e15c8..fe1b20c0cc 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Linq; From 4145173ac905e0b3eef36e77ae542695dc68712c Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Tue, 2 Jul 2019 04:04:07 +0200 Subject: [PATCH 015/239] Combined hidden with traceable as multi mod --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 1 - osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 22 +++++---- .../Objects/Drawables/DrawableHitCircle.cs | 48 +++++++++---------- osu.Game.Rulesets.Osu/OsuRuleset.cs | 4 +- .../TestSceneModSelectOverlay.cs | 5 +- osu.Game/Overlays/Mods/ModSection.cs | 6 ++- 6 files changed, 44 insertions(+), 42 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index 5887cb2865..2723be9df8 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -17,7 +17,6 @@ namespace osu.Game.Rulesets.Osu.Mods { public override string Description => @"Play with no approach circles and fading circles/sliders."; public override double ScoreMultiplier => 1.06; - public override Type[] IncompatibleMods => new[] { typeof(OsuModTraceable) }; private const double fade_in_duration_multiplier = 0.4; private const double fade_out_duration_multiplier = 0.3; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index fe1b20c0cc..64a331213f 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -11,15 +11,15 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Mods { - internal class OsuModTraceable : OsuModHidden, IReadFromConfig, IApplicableToDrawableHitObjects + internal class OsuModTraceable : OsuModHidden { public override string Name => "Traceable"; public override string Acronym => "TC"; public override IconUsage Icon => FontAwesome.Brands.SnapchatGhost; - public override ModType Type => ModType.Fun; + public override ModType Type => ModType.DifficultyIncrease; public override string Description => "Put your faith in the approach circles..."; public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden), typeof(OsuModGrow) }; + public override Type[] IncompatibleMods => new[] { typeof(OsuModGrow) }; public override void ApplyToDrawableHitObjects(IEnumerable drawables) { @@ -30,10 +30,12 @@ namespace osu.Game.Rulesets.Osu.Mods case DrawableHitCircle _: drawable.ApplyCustomUpdateState += ApplyTraceableState; break; + case DrawableSlider slider: slider.ApplyCustomUpdateState += ApplyHiddenState; slider.HeadCircle.ApplyCustomUpdateState += ApplyTraceableState; break; + default: drawable.ApplyCustomUpdateState += ApplyHiddenState; break; @@ -51,13 +53,13 @@ namespace osu.Game.Rulesets.Osu.Mods // we only want to see the approach circle using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) { - circle.circle.Hide(); // CirclePiece - circle.circle.AlwaysPresent = true; - circle.ring.Hide(); - circle.flash.Hide(); - circle.explode.Hide(); - circle.number.Hide(); - circle.glow.Hide(); + circle.Circle.Hide(); // CirclePiece + circle.Circle.AlwaysPresent = true; + circle.Ring.Hide(); + circle.Flash.Hide(); + circle.Explode.Hide(); + circle.Number.Hide(); + circle.Glow.Hide(); circle.ApproachCircle.Show(); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 31c86474cd..e8a2f94c14 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -17,18 +17,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables public class DrawableHitCircle : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach { public ApproachCircle ApproachCircle; - public readonly CirclePiece circle; - public readonly RingPiece ring; - public readonly FlashPiece flash; - public readonly ExplodePiece explode; - public readonly NumberPiece number; - public readonly GlowPiece glow; + public readonly CirclePiece Circle; + public readonly RingPiece Ring; + public readonly FlashPiece Flash; + public readonly ExplodePiece Explode; + public readonly NumberPiece Number; + public readonly GlowPiece Glow; private readonly IBindable positionBindable = new Bindable(); private readonly IBindable stackHeightBindable = new Bindable(); private readonly IBindable scaleBindable = new Bindable(); - public OsuAction? HitAction => circle.HitAction; + public OsuAction? HitAction => Circle.HitAction; private readonly Container explodeContainer; @@ -55,8 +55,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Anchor = Anchor.Centre, Children = new Drawable[] { - glow = new GlowPiece(), - circle = new CirclePiece + Glow = new GlowPiece(), + Circle = new CirclePiece { Hit = () => { @@ -67,13 +67,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables return true; }, }, - number = new NumberPiece + Number = new NumberPiece { Text = (HitObject.IndexInCurrentCombo + 1).ToString(), }, - ring = new RingPiece(), - flash = new FlashPiece(), - explode = new ExplodePiece(), + Ring = new RingPiece(), + Flash = new FlashPiece(), + Explode = new ExplodePiece(), ApproachCircle = new ApproachCircle { Alpha = 0, @@ -85,7 +85,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables }; //may not be so correct - Size = circle.DrawSize; + Size = Circle.DrawSize; } [BackgroundDependencyLoader] @@ -106,9 +106,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables set { base.AccentColour = value; - explode.Colour = AccentColour; - glow.Colour = AccentColour; - circle.Colour = AccentColour; + Explode.Colour = AccentColour; + Glow.Colour = AccentColour; + Circle.Colour = AccentColour; ApproachCircle.Colour = AccentColour; } } @@ -145,7 +145,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void UpdateCurrentState(ArmedState state) { - glow.FadeOut(400); + Glow.FadeOut(400); switch (state) { @@ -154,7 +154,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Expire(true); - circle.HitAction = null; + Circle.HitAction = null; // override lifetime end as FadeIn may have been changed externally, causing out expiration to be too early. LifetimeEnd = HitObject.StartTime + HitObject.HitWindows.HalfWindowFor(HitResult.Miss); @@ -170,18 +170,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables ApproachCircle.FadeOut(50); const double flash_in = 40; - flash.FadeTo(0.8f, flash_in) + Flash.FadeTo(0.8f, flash_in) .Then() .FadeOut(100); - explode.FadeIn(flash_in); + Explode.FadeIn(flash_in); using (BeginDelayedSequence(flash_in, true)) { //after the flash, we can hide some elements that were behind it - ring.FadeOut(); - circle.FadeOut(); - number.FadeOut(); + Ring.FadeOut(); + Circle.FadeOut(); + Number.FadeOut(); this.FadeOut(800); explodeContainer.ScaleTo(1.5f, 400, Easing.OutQuad); diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 169d54d64a..9c48169a24 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.Osu new OsuModHardRock(), new MultiMod(new OsuModSuddenDeath(), new OsuModPerfect()), new MultiMod(new OsuModDoubleTime(), new OsuModNightcore()), - new OsuModHidden(), + new MultiMod(new OsuModHidden(), new OsuModTraceable()), new MultiMod(new OsuModFlashlight(), new OsuModBlinds()), }; @@ -136,8 +136,6 @@ namespace osu.Game.Rulesets.Osu new OsuModWiggle(), new OsuModGrow(), new MultiMod(new ModWindUp(), new ModWindDown()), - - new OsuModTraceable(), }; default: diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 80408ab43b..9074b64eb8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -85,7 +85,7 @@ namespace osu.Game.Tests.Visual.UserInterface var assistMods = instance.GetModsFor(ModType.Automation); var noFailMod = easierMods.FirstOrDefault(m => m is OsuModNoFail); - var hiddenMod = harderMods.FirstOrDefault(m => m is OsuModHidden); + var hiddenMod = harderMods.OfType().FirstOrDefault(m => m.Mods.Any(a => a is OsuModHidden)); var doubleTimeMod = harderMods.OfType().FirstOrDefault(m => m.Mods.Any(a => a is OsuModDoubleTime)); @@ -96,10 +96,11 @@ namespace osu.Game.Tests.Visual.UserInterface testSingleMod(noFailMod); testMultiMod(doubleTimeMod); + testMultiMod(hiddenMod); testIncompatibleMods(easy, hardRock); testDeselectAll(easierMods.Where(m => !(m is MultiMod))); testMultiplierTextColour(noFailMod, modSelect.LowMultiplierColour); - testMultiplierTextColour(hiddenMod, modSelect.HighMultiplierColour); + testMultiplierTextColour(hardRock, modSelect.HighMultiplierColour); testUnimplementedMod(autoPilotMod); } diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index 0eca1bcbec..5c2ab8e18c 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -112,13 +112,15 @@ namespace osu.Game.Overlays.Mods if (selected == null) continue; foreach (var type in modTypes) - if (type.IsInstanceOfType(selected) && !selected.GetType().IsSubclassOf(type)) + { + if (type.IsInstanceOfType(selected)) { if (immediate) button.Deselect(); else Scheduler.AddDelayed(button.Deselect, delay += 50); } + } } } @@ -130,7 +132,7 @@ namespace osu.Game.Overlays.Mods { foreach (var button in buttons) { - int i = Array.FindIndex(button.Mods, m => modTypes.Any(t => t.IsInstanceOfType(m) && !m.GetType().IsSubclassOf(t))); + int i = Array.FindIndex(button.Mods, m => modTypes.Any(t => t.IsInstanceOfType(m))); if (i >= 0) button.SelectAt(i); From 664257fbbe31f7b1617fc55527e59a088dc5c259 Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Wed, 3 Jul 2019 18:42:02 +0200 Subject: [PATCH 016/239] Sliders no longer modified by HD but have transparent body now --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 1 - osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 60 ++++++++++--------- osu.Game/Overlays/Mods/ModSection.cs | 2 - 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index 2723be9df8..ddf708d0f1 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -17,7 +17,6 @@ namespace osu.Game.Rulesets.Osu.Mods { public override string Description => @"Play with no approach circles and fading circles/sliders."; public override double ScoreMultiplier => 1.06; - private const double fade_in_duration_multiplier = 0.4; private const double fade_out_duration_multiplier = 0.3; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index 64a331213f..8ccff6b258 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables; +using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Mods { @@ -24,43 +25,44 @@ namespace osu.Game.Rulesets.Osu.Mods public override void ApplyToDrawableHitObjects(IEnumerable drawables) { foreach (var drawable in drawables.Skip(IncreaseFirstObjectVisibility.Value ? 1 : 0)) - { - switch (drawable) - { - case DrawableHitCircle _: - drawable.ApplyCustomUpdateState += ApplyTraceableState; - break; - - case DrawableSlider slider: - slider.ApplyCustomUpdateState += ApplyHiddenState; - slider.HeadCircle.ApplyCustomUpdateState += ApplyTraceableState; - break; - - default: - drawable.ApplyCustomUpdateState += ApplyHiddenState; - break; - } - } + drawable.ApplyCustomUpdateState += ApplyTraceableState; } protected void ApplyTraceableState(DrawableHitObject drawable, ArmedState state) { - if (!(drawable is DrawableHitCircle circle)) + if (!(drawable is DrawableOsuHitObject d)) return; - var h = circle.HitObject; + var h = d.HitObject; - // we only want to see the approach circle - using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) + switch (drawable) { - circle.Circle.Hide(); // CirclePiece - circle.Circle.AlwaysPresent = true; - circle.Ring.Hide(); - circle.Flash.Hide(); - circle.Explode.Hide(); - circle.Number.Hide(); - circle.Glow.Hide(); - circle.ApproachCircle.Show(); + case DrawableHitCircle circle: + // we only want to see the approach circle + using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) + { + circle.Circle.Hide(); // CirclePiece + circle.Circle.AlwaysPresent = true; + circle.Ring.Hide(); + circle.Flash.Hide(); + circle.Explode.Hide(); + circle.Number.Hide(); + circle.Glow.Hide(); + circle.ApproachCircle.Show(); + } + + break; + + case DrawableSlider slider: + ApplyTraceableState(slider.HeadCircle, state); + slider.Body.AccentColour = Color4.Transparent; + + break; + + default: + ApplyHiddenState(drawable, state); + + break; } } } diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs index 5c2ab8e18c..dedd397fa5 100644 --- a/osu.Game/Overlays/Mods/ModSection.cs +++ b/osu.Game/Overlays/Mods/ModSection.cs @@ -112,7 +112,6 @@ namespace osu.Game.Overlays.Mods if (selected == null) continue; foreach (var type in modTypes) - { if (type.IsInstanceOfType(selected)) { if (immediate) @@ -120,7 +119,6 @@ namespace osu.Game.Overlays.Mods else Scheduler.AddDelayed(button.Deselect, delay += 50); } - } } } From 5b4640d3ead5a89f31cb30b95c2234e79beb03c4 Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Wed, 3 Jul 2019 21:40:14 +0200 Subject: [PATCH 017/239] Traceable no longer inherits from OsuModHidden and is no longer multi mod --- osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs | 1 + osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 24 +++++++++++++------ .../Mods/OsuModeObjectScaleTween.cs | 2 +- osu.Game.Rulesets.Osu/OsuRuleset.cs | 3 ++- .../TestSceneModSelectOverlay.cs | 5 ++-- 5 files changed, 23 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs index ddf708d0f1..74f9398f18 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs @@ -17,6 +17,7 @@ namespace osu.Game.Rulesets.Osu.Mods { public override string Description => @"Play with no approach circles and fading circles/sliders."; public override double ScoreMultiplier => 1.06; + public override Type[] IncompatibleMods => new[] { typeof(OsuModTraceable) }; private const double fade_in_duration_multiplier = 0.4; private const double fade_out_duration_multiplier = 0.3; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index c5b5a064a6..1d68793c50 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -3,8 +3,10 @@ using System; using System.Linq; +using osu.Framework.Bindables; using System.Collections.Generic; using osu.Framework.Graphics.Sprites; +using osu.Game.Configuration; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables; @@ -12,19 +14,25 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Mods { - internal class OsuModTraceable : OsuModHidden + internal class OsuModTraceable : Mod, IReadFromConfig, IApplicableToDrawableHitObjects { public override string Name => "Traceable"; public override string Acronym => "TC"; public override IconUsage Icon => FontAwesome.Brands.SnapchatGhost; - public override ModType Type => ModType.DifficultyIncrease; + public override ModType Type => ModType.Fun; public override string Description => "Put your faith in the approach circles..."; public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => new[] { typeof(OsuModeObjectScaleTween) }; + public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden), typeof(OsuModeObjectScaleTween) }; + private Bindable increaseFirstObjectVisibility = new Bindable(); - public override void ApplyToDrawableHitObjects(IEnumerable drawables) + public void ReadFromConfig(OsuConfigManager config) { - foreach (var drawable in drawables.Skip(IncreaseFirstObjectVisibility.Value ? 1 : 0)) + increaseFirstObjectVisibility = config.GetBindable(OsuSetting.IncreaseFirstObjectVisibility); + } + + public void ApplyToDrawableHitObjects(IEnumerable drawables) + { + foreach (var drawable in drawables.Skip(increaseFirstObjectVisibility.Value ? 1 : 0)) drawable.ApplyCustomUpdateState += ApplyTraceableState; } @@ -59,8 +67,10 @@ namespace osu.Game.Rulesets.Osu.Mods break; - default: - ApplyHiddenState(drawable, state); + case DrawableSpinner spinner: + spinner.Disc.Hide(); + //spinner.Ticks.Hide(); // do they contribute to the theme? debatable + spinner.Background.Hide(); break; } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs b/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs index de277100b5..db61c15846 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => new[] { typeof(OsuModeObjectScaleTween) }; + public override Type[] IncompatibleMods => new[] { typeof(OsuModTraceable) }; protected virtual float StartScale => 1; diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index 949b473ca6..c0e2809b38 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.Osu new OsuModHardRock(), new MultiMod(new OsuModSuddenDeath(), new OsuModPerfect()), new MultiMod(new OsuModDoubleTime(), new OsuModNightcore()), - new MultiMod(new OsuModHidden(), new OsuModTraceable()), + new OsuModHidden(), new MultiMod(new OsuModFlashlight(), new OsuModBlinds()), }; @@ -136,6 +136,7 @@ namespace osu.Game.Rulesets.Osu new OsuModWiggle(), new MultiMod(new OsuModGrow(), new OsuModDeflate()), new MultiMod(new ModWindUp(), new ModWindDown()), + new OsuModTraceable(), }; default: diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 9074b64eb8..80408ab43b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -85,7 +85,7 @@ namespace osu.Game.Tests.Visual.UserInterface var assistMods = instance.GetModsFor(ModType.Automation); var noFailMod = easierMods.FirstOrDefault(m => m is OsuModNoFail); - var hiddenMod = harderMods.OfType().FirstOrDefault(m => m.Mods.Any(a => a is OsuModHidden)); + var hiddenMod = harderMods.FirstOrDefault(m => m is OsuModHidden); var doubleTimeMod = harderMods.OfType().FirstOrDefault(m => m.Mods.Any(a => a is OsuModDoubleTime)); @@ -96,11 +96,10 @@ namespace osu.Game.Tests.Visual.UserInterface testSingleMod(noFailMod); testMultiMod(doubleTimeMod); - testMultiMod(hiddenMod); testIncompatibleMods(easy, hardRock); testDeselectAll(easierMods.Where(m => !(m is MultiMod))); testMultiplierTextColour(noFailMod, modSelect.LowMultiplierColour); - testMultiplierTextColour(hardRock, modSelect.HighMultiplierColour); + testMultiplierTextColour(hiddenMod, modSelect.HighMultiplierColour); testUnimplementedMod(autoPilotMod); } From 581ffb7fb09d50fc0b64bb422841f830c61d1ac7 Mon Sep 17 00:00:00 2001 From: MaxOhn Date: Mon, 8 Jul 2019 13:52:15 +0200 Subject: [PATCH 018/239] Adjusted slider border colour --- osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index 1d68793c50..4918ea60b2 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -64,14 +64,13 @@ namespace osu.Game.Rulesets.Osu.Mods case DrawableSlider slider: ApplyTraceableState(slider.HeadCircle, state); slider.Body.AccentColour = Color4.Transparent; - + slider.Body.BorderColour = slider.HeadCircle.AccentColour; break; case DrawableSpinner spinner: spinner.Disc.Hide(); //spinner.Ticks.Hide(); // do they contribute to the theme? debatable spinner.Background.Hide(); - break; } } From 0584ee9ce55c5a9e86940c66754f5722ba4d4cd3 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 14 Jul 2019 12:34:12 +0300 Subject: [PATCH 019/239] Basic implementation --- .../SongSelect/TestSceneUserTopScore.cs | 97 +++++++++++++++++++ .../Select/Details/UserTopScoreContainer.cs | 79 +++++++++++++++ 2 files changed, 176 insertions(+) create mode 100644 osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs create mode 100644 osu.Game/Screens/Select/Details/UserTopScoreContainer.cs diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs new file mode 100644 index 0000000000..f7cfd4156d --- /dev/null +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs @@ -0,0 +1,97 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Screens.Select.Details; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osuTK.Graphics; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Scoring; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.SongSelect +{ + public class TestSceneUserTopScore : OsuTestScene + { + private readonly UserTopScoreContainer topScoreContainer; + private readonly APILegacyUserTopScoreInfo[] scores; + + public TestSceneUserTopScore() + { + Add(new Container + { + Origin = Anchor.BottomCentre, + Anchor = Anchor.Centre, + AutoSizeAxes = Axes.Y, + Width = 500, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.DarkGreen, + }, + topScoreContainer = new UserTopScoreContainer + { + Origin = Anchor.BottomCentre, + Anchor = Anchor.BottomCentre, + } + } + }); + + AddStep(@"Trigger visibility", topScoreContainer.ToggleVisibility); + AddStep(@"Add score", () => topScoreContainer.TopScore = scores[0]); + AddStep(@"Add another score", () => topScoreContainer.TopScore = scores[1]); + + scores = new APILegacyUserTopScoreInfo[] + { + new APILegacyUserTopScoreInfo + { + Position = 999, + Score = new APILegacyScoreInfo + { + Rank = ScoreRank.XH, + Accuracy = 1, + MaxCombo = 244, + TotalScore = 1707827, + Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, + User = new User + { + Id = 6602580, + Username = @"waaiiru", + Country = new Country + { + FullName = @"Spain", + FlagName = @"ES", + }, + }, + } + }, + new APILegacyUserTopScoreInfo + { + Position = 110000, + Score = new APILegacyScoreInfo + { + Rank = ScoreRank.X, + Accuracy = 1, + MaxCombo = 244, + TotalScore = 1707827, + User = new User + { + Id = 4608074, + Username = @"Skycries", + Country = new Country + { + FullName = @"Brazil", + FlagName = @"BR", + }, + }, + } + } + }; + } + } +} diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs new file mode 100644 index 0000000000..05d0930de5 --- /dev/null +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -0,0 +1,79 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Online.Leaderboards; + +namespace osu.Game.Screens.Select.Details +{ + public class UserTopScoreContainer : VisibilityContainer + { + private const int height = 150; + private const int duration = 300; + + private readonly Container contentContainer; + private readonly Container scoreContainer; + + public APILegacyUserTopScoreInfo TopScore + { + set + { + scoreContainer.Clear(); + scoreContainer.Add(new LeaderboardScore(value.Score, value.Position)); + } + } + + protected override bool StartHidden => true; + + public UserTopScoreContainer() + { + RelativeSizeAxes = Axes.X; + Height = height; + Anchor = Anchor.BottomCentre; + Origin = Anchor.BottomCentre; + Children = new Drawable[] + { + contentContainer = new Container + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Height = height, + RelativeSizeAxes = Axes.X, + Children = new Drawable[] + { + new OsuSpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = @"your personal best".ToUpper(), + Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold), + }, + scoreContainer = new Container + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + } + } + } + }; + } + + protected override void PopIn() + { + this.ResizeHeightTo(height, duration, Easing.OutQuint); + contentContainer.FadeIn(duration, Easing.OutQuint); + } + + protected override void PopOut() + { + this.ResizeHeightTo(0, duration, Easing.OutQuint); + contentContainer.FadeOut(duration, Easing.OutQuint); + } + } +} From d30ae24f581d14d2068fbec2acf69375f6ff620a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 14 Jul 2019 12:40:54 +0300 Subject: [PATCH 020/239] Use Bindable for setting score --- .../SongSelect/TestSceneUserTopScore.cs | 5 +++-- .../Select/Details/UserTopScoreContainer.cs | 20 +++++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs index f7cfd4156d..3fa85ffca6 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs @@ -43,8 +43,9 @@ namespace osu.Game.Tests.Visual.SongSelect }); AddStep(@"Trigger visibility", topScoreContainer.ToggleVisibility); - AddStep(@"Add score", () => topScoreContainer.TopScore = scores[0]); - AddStep(@"Add another score", () => topScoreContainer.TopScore = scores[1]); + AddStep(@"Add score", () => topScoreContainer.TopScore.Value = scores[0]); + AddStep(@"Add another score", () => topScoreContainer.TopScore.Value = scores[1]); + AddStep(@"Add null score", () => topScoreContainer.TopScore.Value = null); scores = new APILegacyUserTopScoreInfo[] { diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index 05d0930de5..21c16d1d74 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; @@ -18,14 +19,7 @@ namespace osu.Game.Screens.Select.Details private readonly Container contentContainer; private readonly Container scoreContainer; - public APILegacyUserTopScoreInfo TopScore - { - set - { - scoreContainer.Clear(); - scoreContainer.Add(new LeaderboardScore(value.Score, value.Position)); - } - } + public Bindable TopScore = new Bindable(); protected override bool StartHidden => true; @@ -62,6 +56,16 @@ namespace osu.Game.Screens.Select.Details } } }; + + TopScore.BindValueChanged((score) => onScoreChanged(score.NewValue)); + } + + private void onScoreChanged(APILegacyUserTopScoreInfo score) + { + scoreContainer.Clear(); + + if (score != null) + scoreContainer.Add(new LeaderboardScore(score.Score, score.Position)); } protected override void PopIn() From 922c3c89ae4eb9d89c6e5c90d7af0c2ae7222fd0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 14 Jul 2019 12:47:35 +0300 Subject: [PATCH 021/239] Make leaderboard score use metric system --- .../SongSelect/TestSceneUserTopScore.cs | 26 +++++++++++++++++-- .../Online/Leaderboards/LeaderboardScore.cs | 12 ++++----- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs index 3fa85ffca6..1023294000 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs @@ -43,8 +43,9 @@ namespace osu.Game.Tests.Visual.SongSelect }); AddStep(@"Trigger visibility", topScoreContainer.ToggleVisibility); - AddStep(@"Add score", () => topScoreContainer.TopScore.Value = scores[0]); - AddStep(@"Add another score", () => topScoreContainer.TopScore.Value = scores[1]); + AddStep(@"Add score(rank 999)", () => topScoreContainer.TopScore.Value = scores[0]); + AddStep(@"Add score(rank 110000)", () => topScoreContainer.TopScore.Value = scores[1]); + AddStep(@"Add score(rank 22333)", () => topScoreContainer.TopScore.Value = scores[2]); AddStep(@"Add null score", () => topScoreContainer.TopScore.Value = null); scores = new APILegacyUserTopScoreInfo[] @@ -91,6 +92,27 @@ namespace osu.Game.Tests.Visual.SongSelect }, }, } + }, + new APILegacyUserTopScoreInfo + { + Position = 22333, + Score = new APILegacyScoreInfo + { + Rank = ScoreRank.S, + Accuracy = 1, + MaxCombo = 244, + TotalScore = 1707827, + User = new User + { + Id = 1541390, + Username = @"Toukai", + Country = new Country + { + FullName = @"Canada", + FlagName = @"CA", + }, + }, + } } }; } diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 9840b59805..713d4a25f7 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -20,23 +20,23 @@ using osu.Game.Scoring; using osu.Game.Users.Drawables; using osuTK; using osuTK.Graphics; +using Humanizer; namespace osu.Game.Online.Leaderboards { public class LeaderboardScore : OsuClickableContainer { - public readonly int RankPosition; - public const float HEIGHT = 60; private const float corner_radius = 5; private const float edge_margin = 5; private const float background_alpha = 0.25f; - private const float rank_width = 30; + private const float rank_width = 35; protected Container RankContainer { get; private set; } private readonly ScoreInfo score; + private readonly int rank; private Box background; private Container content; @@ -52,7 +52,7 @@ namespace osu.Game.Online.Leaderboards public LeaderboardScore(ScoreInfo score, int rank) { this.score = score; - RankPosition = rank; + this.rank = rank; RelativeSizeAxes = Axes.X; Height = HEIGHT; @@ -79,8 +79,8 @@ namespace osu.Game.Online.Leaderboards { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 22, italics: true), - Text = RankPosition.ToString(), + Font = OsuFont.GetFont(size: 20, italics: true), + Text = rank <= 999 ? rank.ToString() : rank.ToMetric(decimals: rank < 100000 ? 1 : 0), }, }, }, From d1409d4610bbcb4f58c6cc5fb0ee0ea8b8e6f37d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 14 Jul 2019 13:33:47 +0300 Subject: [PATCH 022/239] Add top score section into beatmap detail area --- .../SongSelect/TestSceneBeatmapDetailArea.cs | 1 + osu.Game/Screens/Select/BeatmapDetailArea.cs | 68 +++++++++++-------- .../Select/Details/UserTopScoreContainer.cs | 3 +- 3 files changed, 42 insertions(+), 30 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs index 7b97a27732..e9650343af 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs @@ -163,6 +163,7 @@ namespace osu.Game.Tests.Visual.SongSelect }); AddStep("null beatmap", () => detailsArea.Beatmap = null); + AddStep("Toggle top score visibility", () => detailsArea.TopScore.ToggleVisibility()); } } } diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index b66a2ffe0f..678b18e8cf 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -5,19 +5,18 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; +using osu.Game.Screens.Select.Details; using osu.Game.Screens.Select.Leaderboards; namespace osu.Game.Screens.Select { public class BeatmapDetailArea : Container { - private const float details_padding = 10; - - private readonly Container content; - protected override Container Content => content; + private const float padding = 10; public readonly BeatmapDetails Details; public readonly BeatmapLeaderboard Leaderboard; + public readonly UserTopScoreContainer TopScore; private WorkingBeatmap beatmap; @@ -34,7 +33,7 @@ namespace osu.Game.Screens.Select public BeatmapDetailArea() { - AddRangeInternal(new Drawable[] + Children = new Drawable[] { new BeatmapDetailAreaTabControl { @@ -58,33 +57,44 @@ namespace osu.Game.Screens.Select } }, }, - content = new Container + new GridContainer { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = BeatmapDetailAreaTabControl.HEIGHT }, + Margin = new MarginPadding { Top = BeatmapDetailAreaTabControl.HEIGHT }, + RowDimensions = new Dimension[] + { + new Dimension(GridSizeMode.Distributed), + new Dimension(GridSizeMode.AutoSize), + }, + Content = new[] + { + new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + Details = new BeatmapDetails + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + Padding = new MarginPadding { Vertical = padding }, + }, + Leaderboard = new BeatmapLeaderboard + { + RelativeSizeAxes = Axes.Both, + } + } + } + }, + new Drawable[] + { + TopScore = new UserTopScoreContainer(), + } + }, }, - }); - - AddRange(new Drawable[] - { - Details = new BeatmapDetails - { - RelativeSizeAxes = Axes.X, - Alpha = 0, - Margin = new MarginPadding { Top = details_padding }, - }, - Leaderboard = new BeatmapLeaderboard - { - RelativeSizeAxes = Axes.Both, - } - }); - } - - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - Details.Height = Math.Min(DrawHeight - details_padding * 3 - BeatmapDetailAreaTabControl.HEIGHT, 450); + }; } } } diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index 21c16d1d74..2cc47a7483 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -13,7 +13,7 @@ namespace osu.Game.Screens.Select.Details { public class UserTopScoreContainer : VisibilityContainer { - private const int height = 150; + private const int height = 110; private const int duration = 300; private readonly Container contentContainer; @@ -37,6 +37,7 @@ namespace osu.Game.Screens.Select.Details Origin = Anchor.BottomCentre, Height = height, RelativeSizeAxes = Axes.X, + Padding = new MarginPadding { Vertical = 10 }, Children = new Drawable[] { new OsuSpriteText From 963e025bb8882eb94884adbf40bb6b13cc0b298a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 14 Jul 2019 14:03:14 +0300 Subject: [PATCH 023/239] Make it works and some layout adjustments --- .../SongSelect/TestSceneUserTopScore.cs | 8 +-- osu.Game/Screens/Select/BeatmapDetailArea.cs | 60 +++++++++++-------- .../Select/Details/UserTopScoreContainer.cs | 11 ++-- .../Select/Leaderboards/BeatmapLeaderboard.cs | 9 ++- 4 files changed, 53 insertions(+), 35 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs index 1023294000..b33dbddccb 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs @@ -43,10 +43,10 @@ namespace osu.Game.Tests.Visual.SongSelect }); AddStep(@"Trigger visibility", topScoreContainer.ToggleVisibility); - AddStep(@"Add score(rank 999)", () => topScoreContainer.TopScore.Value = scores[0]); - AddStep(@"Add score(rank 110000)", () => topScoreContainer.TopScore.Value = scores[1]); - AddStep(@"Add score(rank 22333)", () => topScoreContainer.TopScore.Value = scores[2]); - AddStep(@"Add null score", () => topScoreContainer.TopScore.Value = null); + AddStep(@"Add score(rank 999)", () => topScoreContainer.Score.Value = scores[0]); + AddStep(@"Add score(rank 110000)", () => topScoreContainer.Score.Value = scores[1]); + AddStep(@"Add score(rank 22333)", () => topScoreContainer.Score.Value = scores[2]); + AddStep(@"Add null score", () => topScoreContainer.Score.Value = null); scores = new APILegacyUserTopScoreInfo[] { diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index 678b18e8cf..cac1281cc2 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -1,10 +1,10 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Screens.Select.Details; using osu.Game.Screens.Select.Leaderboards; @@ -28,6 +28,7 @@ namespace osu.Game.Screens.Select beatmap = value; Leaderboard.Beatmap = beatmap?.BeatmapInfo; Details.Beatmap = beatmap?.BeatmapInfo; + TopScore.Hide(); } } @@ -57,43 +58,50 @@ namespace osu.Game.Screens.Select } }, }, - new GridContainer + new Container { + Padding = new MarginPadding { Top = BeatmapDetailAreaTabControl.HEIGHT, Bottom = padding }, RelativeSizeAxes = Axes.Both, - Margin = new MarginPadding { Top = BeatmapDetailAreaTabControl.HEIGHT }, - RowDimensions = new Dimension[] + Child = new GridContainer { - new Dimension(GridSizeMode.Distributed), - new Dimension(GridSizeMode.AutoSize), - }, - Content = new[] - { - new Drawable[] + RelativeSizeAxes = Axes.Both, + RowDimensions = new Dimension[] { - new Container + new Dimension(GridSizeMode.Distributed), + new Dimension(GridSizeMode.AutoSize), + }, + Content = new[] + { + new Drawable[] { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + new Container { - Details = new BeatmapDetails + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - Padding = new MarginPadding { Vertical = padding }, - }, - Leaderboard = new BeatmapLeaderboard - { - RelativeSizeAxes = Axes.Both, + Details = new BeatmapDetails + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + Padding = new MarginPadding { Top = padding }, + }, + Leaderboard = new BeatmapLeaderboard + { + RelativeSizeAxes = Axes.Both, + } } } + }, + new Drawable[] + { + TopScore = new UserTopScoreContainer + { + Score = { BindTarget = Leaderboard.TopScore } + } } }, - new Drawable[] - { - TopScore = new UserTopScoreContainer(), - } }, - }, + } }; } } diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index 2cc47a7483..0bc30fae6b 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -13,13 +13,13 @@ namespace osu.Game.Screens.Select.Details { public class UserTopScoreContainer : VisibilityContainer { - private const int height = 110; + private const int height = 90; private const int duration = 300; private readonly Container contentContainer; private readonly Container scoreContainer; - public Bindable TopScore = new Bindable(); + public Bindable Score = new Bindable(); protected override bool StartHidden => true; @@ -37,13 +37,13 @@ namespace osu.Game.Screens.Select.Details Origin = Anchor.BottomCentre, Height = height, RelativeSizeAxes = Axes.X, - Padding = new MarginPadding { Vertical = 10 }, Children = new Drawable[] { new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, + Margin = new MarginPadding { Top = 5 }, Text = @"your personal best".ToUpper(), Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold), }, @@ -58,7 +58,7 @@ namespace osu.Game.Screens.Select.Details } }; - TopScore.BindValueChanged((score) => onScoreChanged(score.NewValue)); + Score.BindValueChanged((score) => onScoreChanged(score.NewValue)); } private void onScoreChanged(APILegacyUserTopScoreInfo score) @@ -66,7 +66,10 @@ namespace osu.Game.Screens.Select.Details scoreContainer.Clear(); if (score != null) + { scoreContainer.Add(new LeaderboardScore(score.Score, score.Position)); + Show(); + } } protected override void PopIn() diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 0f6d4f3188..c41bf17685 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -9,6 +9,7 @@ using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; @@ -18,6 +19,8 @@ namespace osu.Game.Screens.Select.Leaderboards { public class BeatmapLeaderboard : Leaderboard { + public Bindable TopScore = new Bindable(); + public Action ScoreSelected; private BeatmapInfo beatmap; @@ -133,7 +136,11 @@ namespace osu.Game.Screens.Select.Leaderboards var req = new GetScoresRequest(Beatmap, ruleset.Value ?? Beatmap.Ruleset, Scope, requestMods); - req.Success += r => scoresCallback?.Invoke(r.Scores); + req.Success += r => + { + scoresCallback?.Invoke(r.Scores); + TopScore.Value = r.UserScore; + }; return req; } From ecf0e624849901aedcb2eac6008853773ef6aee8 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 14 Jul 2019 16:16:21 +0300 Subject: [PATCH 024/239] CI fixes --- .../SongSelect/TestSceneUserTopScore.cs | 19 +++++++++---------- osu.Game/Screens/Select/BeatmapDetailArea.cs | 3 +-- .../Select/Details/UserTopScoreContainer.cs | 2 +- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs index b33dbddccb..1de8a5375e 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs @@ -16,11 +16,10 @@ namespace osu.Game.Tests.Visual.SongSelect { public class TestSceneUserTopScore : OsuTestScene { - private readonly UserTopScoreContainer topScoreContainer; - private readonly APILegacyUserTopScoreInfo[] scores; - public TestSceneUserTopScore() { + UserTopScoreContainer topScoreContainer; + Add(new Container { Origin = Anchor.BottomCentre, @@ -42,13 +41,7 @@ namespace osu.Game.Tests.Visual.SongSelect } }); - AddStep(@"Trigger visibility", topScoreContainer.ToggleVisibility); - AddStep(@"Add score(rank 999)", () => topScoreContainer.Score.Value = scores[0]); - AddStep(@"Add score(rank 110000)", () => topScoreContainer.Score.Value = scores[1]); - AddStep(@"Add score(rank 22333)", () => topScoreContainer.Score.Value = scores[2]); - AddStep(@"Add null score", () => topScoreContainer.Score.Value = null); - - scores = new APILegacyUserTopScoreInfo[] + APILegacyUserTopScoreInfo[] scores = new[] { new APILegacyUserTopScoreInfo { @@ -115,6 +108,12 @@ namespace osu.Game.Tests.Visual.SongSelect } } }; + + AddStep(@"Trigger visibility", topScoreContainer.ToggleVisibility); + AddStep(@"Add score(rank 999)", () => topScoreContainer.Score.Value = scores[0]); + AddStep(@"Add score(rank 110000)", () => topScoreContainer.Score.Value = scores[1]); + AddStep(@"Add score(rank 22333)", () => topScoreContainer.Score.Value = scores[2]); + AddStep(@"Add null score", () => topScoreContainer.Score.Value = null); } } } diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index cac1281cc2..6cd6372152 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -4,7 +4,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; -using osu.Game.Online.API.Requests.Responses; using osu.Game.Screens.Select.Details; using osu.Game.Screens.Select.Leaderboards; @@ -65,7 +64,7 @@ namespace osu.Game.Screens.Select Child = new GridContainer { RelativeSizeAxes = Axes.Both, - RowDimensions = new Dimension[] + RowDimensions = new[] { new Dimension(GridSizeMode.Distributed), new Dimension(GridSizeMode.AutoSize), diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index 0bc30fae6b..0300d14ac1 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -58,7 +58,7 @@ namespace osu.Game.Screens.Select.Details } }; - Score.BindValueChanged((score) => onScoreChanged(score.NewValue)); + Score.BindValueChanged(score => onScoreChanged(score.NewValue)); } private void onScoreChanged(APILegacyUserTopScoreInfo score) From 19680c8df8f7c883df97f600bde0e1f882687758 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 14 Jul 2019 16:37:05 +0300 Subject: [PATCH 025/239] Minor adjustments --- osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs | 2 +- osu.Game/Screens/Select/Details/UserTopScoreContainer.cs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs index 1de8a5375e..5ddccb4c8e 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs @@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.SongSelect } }); - APILegacyUserTopScoreInfo[] scores = new[] + var scores = new APILegacyUserTopScoreInfo[] { new APILegacyUserTopScoreInfo { diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index 0300d14ac1..e5e33a47d8 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -63,13 +63,14 @@ namespace osu.Game.Screens.Select.Details private void onScoreChanged(APILegacyUserTopScoreInfo score) { - scoreContainer.Clear(); - if (score != null) { + scoreContainer.Clear(); scoreContainer.Add(new LeaderboardScore(score.Score, score.Position)); Show(); } + else + Hide(); } protected override void PopIn() From a01e7260e06e7b23d6b40d7c54d56bee969eb2cc Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 14 Jul 2019 16:49:46 +0300 Subject: [PATCH 026/239] Testcase fix --- osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs index 5ddccb4c8e..5f3e7d09dd 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs @@ -41,7 +41,7 @@ namespace osu.Game.Tests.Visual.SongSelect } }); - var scores = new APILegacyUserTopScoreInfo[] + var scores = new[] { new APILegacyUserTopScoreInfo { From 27258e3a9b6b16d2ed845b9e65ab63515366a718 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 15 Jul 2019 14:38:05 +0900 Subject: [PATCH 027/239] Rename test scene to match class --- ...SceneUserTopScore.cs => TestSceneUserTopScoreContainer.cs} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename osu.Game.Tests/Visual/SongSelect/{TestSceneUserTopScore.cs => TestSceneUserTopScoreContainer.cs} (97%) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs similarity index 97% rename from osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs rename to osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs index 5f3e7d09dd..38ebb58e76 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScore.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs @@ -14,9 +14,9 @@ using osu.Game.Users; namespace osu.Game.Tests.Visual.SongSelect { - public class TestSceneUserTopScore : OsuTestScene + public class TestSceneUserTopScoreContainer : OsuTestScene { - public TestSceneUserTopScore() + public TestSceneUserTopScoreContainer() { UserTopScoreContainer topScoreContainer; From 7e367dc397e9ce17fe089b83df4b324689d5d756 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 15 Jul 2019 12:30:42 +0300 Subject: [PATCH 028/239] Push results screen when clicking on top score --- osu.Game/Screens/Select/Details/UserTopScoreContainer.cs | 9 ++++++++- osu.Game/Screens/Select/SongSelect.cs | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index e5e33a47d8..ba6751475e 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -8,6 +8,8 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; +using osu.Game.Scoring; +using System; namespace osu.Game.Screens.Select.Details { @@ -21,6 +23,8 @@ namespace osu.Game.Screens.Select.Details public Bindable Score = new Bindable(); + public Action ScoreSelected; + protected override bool StartHidden => true; public UserTopScoreContainer() @@ -66,7 +70,10 @@ namespace osu.Game.Screens.Select.Details if (score != null) { scoreContainer.Clear(); - scoreContainer.Add(new LeaderboardScore(score.Score, score.Position)); + scoreContainer.Add(new LeaderboardScore(score.Score, score.Position) + { + Action = () => ScoreSelected?.Invoke(score.Score) + }); Show(); } else diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index b3c3925a26..94b1fedeab 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -216,6 +216,7 @@ namespace osu.Game.Screens.Select } BeatmapDetails.Leaderboard.ScoreSelected += s => this.Push(new SoloResults(s)); + BeatmapDetails.TopScore.ScoreSelected += s => this.Push(new SoloResults(s)); } [BackgroundDependencyLoader(true)] From 764513feea591b2d6e25e378e15913017d525b20 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jul 2019 23:13:48 +0900 Subject: [PATCH 029/239] Fix code quality --- .../Select/Details/UserTopScoreContainer.cs | 46 ++++++++++--------- osu.Game/Screens/Select/SongSelect.cs | 6 ++- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index ba6751475e..cc2d2a3dae 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -31,30 +31,31 @@ namespace osu.Game.Screens.Select.Details { RelativeSizeAxes = Axes.X; Height = height; - Anchor = Anchor.BottomCentre; - Origin = Anchor.BottomCentre; + + Anchor = Anchor.BottomLeft; + Origin = Anchor.BottomLeft; + Children = new Drawable[] { contentContainer = new Container { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Height = height, - RelativeSizeAxes = Axes.X, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.Both, Children = new Drawable[] { new OsuSpriteText { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, + Anchor = Anchor.TopLeft, + Origin = Anchor.TopLeft, Margin = new MarginPadding { Top = 5 }, Text = @"your personal best".ToUpper(), Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold), }, scoreContainer = new Container { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, } @@ -62,22 +63,25 @@ namespace osu.Game.Screens.Select.Details } }; - Score.BindValueChanged(score => onScoreChanged(score.NewValue)); + Score.BindValueChanged(onScoreChanged); } - private void onScoreChanged(APILegacyUserTopScoreInfo score) + private void onScoreChanged(ValueChangedEvent score) { - if (score != null) + var newScore = score.NewValue; + + if (newScore == null) { - scoreContainer.Clear(); - scoreContainer.Add(new LeaderboardScore(score.Score, score.Position) - { - Action = () => ScoreSelected?.Invoke(score.Score) - }); - Show(); - } - else Hide(); + return; + } + + scoreContainer.Child = new LeaderboardScore(newScore.Score, newScore.Position) + { + Action = () => ScoreSelected?.Invoke(newScore.Score) + }; + + Show(); } protected override void PopIn() diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 209707d8fe..a3b87b5068 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -215,8 +215,10 @@ namespace osu.Game.Screens.Select }); } - BeatmapDetails.Leaderboard.ScoreSelected += s => this.Push(new SoloResults(s)); - BeatmapDetails.TopScore.ScoreSelected += s => this.Push(new SoloResults(s)); + void displayScore(ScoreInfo score) => this.Push(new SoloResults(score)); + + BeatmapDetails.Leaderboard.ScoreSelected += displayScore; + BeatmapDetails.TopScore.ScoreSelected += displayScore; } [BackgroundDependencyLoader(true)] From d83d93ee66fa26b2aabe1678d5c4704f1f74c0d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jul 2019 23:21:07 +0900 Subject: [PATCH 030/239] Use asynchronous loading --- .../Select/Details/UserTopScoreContainer.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index cc2d2a3dae..1535aa3df1 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -10,6 +10,7 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; using osu.Game.Scoring; using System; +using System.Threading; namespace osu.Game.Screens.Select.Details { @@ -66,6 +67,8 @@ namespace osu.Game.Screens.Select.Details Score.BindValueChanged(onScoreChanged); } + private CancellationTokenSource loadScoreCancellation; + private void onScoreChanged(ValueChangedEvent score) { var newScore = score.NewValue; @@ -76,12 +79,17 @@ namespace osu.Game.Screens.Select.Details return; } - scoreContainer.Child = new LeaderboardScore(newScore.Score, newScore.Position) + scoreContainer.Clear(); + loadScoreCancellation?.Cancel(); + + LoadComponentAsync(new LeaderboardScore(newScore.Score, newScore.Position) { Action = () => ScoreSelected?.Invoke(newScore.Score) - }; - - Show(); + }, drawableScore => + { + scoreContainer.Child = drawableScore; + Show(); + }, (loadScoreCancellation = new CancellationTokenSource()).Token); } protected override void PopIn() From 95241165cce4724758f7267630b1755c748b1dbc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jul 2019 23:26:11 +0900 Subject: [PATCH 031/239] Fix text alignment --- osu.Game/Screens/Select/Details/UserTopScoreContainer.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index 1535aa3df1..5a224756b9 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; @@ -47,8 +47,8 @@ namespace osu.Game.Screens.Select.Details { new OsuSpriteText { - Anchor = Anchor.TopLeft, - Origin = Anchor.TopLeft, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, Margin = new MarginPadding { Top = 5 }, Text = @"your personal best".ToUpper(), Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold), From 5a6c8bfec9ff1563856ecd22936dc396e2360d90 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 22 Jul 2019 23:28:17 +0900 Subject: [PATCH 032/239] Adjust transition to now show janky resize --- .../Select/Details/UserTopScoreContainer.cs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index 5a224756b9..8e9df8bbb1 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; @@ -17,7 +17,7 @@ namespace osu.Game.Screens.Select.Details public class UserTopScoreContainer : VisibilityContainer { private const int height = 90; - private const int duration = 300; + private const int duration = 800; private readonly Container contentContainer; private readonly Container scoreContainer; @@ -92,16 +92,8 @@ namespace osu.Game.Screens.Select.Details }, (loadScoreCancellation = new CancellationTokenSource()).Token); } - protected override void PopIn() - { - this.ResizeHeightTo(height, duration, Easing.OutQuint); - contentContainer.FadeIn(duration, Easing.OutQuint); - } + protected override void PopIn() => this.ResizeHeightTo(height, duration / 4f, Easing.OutQuint).OnComplete(_ => contentContainer.FadeIn(duration, Easing.OutQuint)); - protected override void PopOut() - { - this.ResizeHeightTo(0, duration, Easing.OutQuint); - contentContainer.FadeOut(duration, Easing.OutQuint); - } + protected override void PopOut() => contentContainer.FadeOut(duration, Easing.OutQuint).OnComplete(_ => this.ResizeHeightTo(0)); } } From 94ed03548d7a401bc43be3b9ce602412efb6e662 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 22 Jul 2019 18:34:31 +0300 Subject: [PATCH 033/239] Hide top score at every leaderboard change --- osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index ee16123e20..f4a18e3b58 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -86,6 +86,8 @@ namespace osu.Game.Screens.Select.Leaderboards protected override APIRequest FetchScores(Action> scoresCallback) { + TopScore.Value = null; + if (Scope == BeatmapLeaderboardScope.Local) { var scores = scoreManager From 76b79f355443cba1b1f60fea02f24fae764e771d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 23 Jul 2019 01:14:45 +0300 Subject: [PATCH 034/239] Transform adjustments --- osu.Game/Screens/Select/Details/UserTopScoreContainer.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index 8e9df8bbb1..c10f4d4fd4 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -42,7 +42,8 @@ namespace osu.Game.Screens.Select.Details { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.Both, + RelativeSizeAxes = Axes.X, + Height = height, Children = new Drawable[] { new OsuSpriteText @@ -94,6 +95,10 @@ namespace osu.Game.Screens.Select.Details protected override void PopIn() => this.ResizeHeightTo(height, duration / 4f, Easing.OutQuint).OnComplete(_ => contentContainer.FadeIn(duration, Easing.OutQuint)); - protected override void PopOut() => contentContainer.FadeOut(duration, Easing.OutQuint).OnComplete(_ => this.ResizeHeightTo(0)); + protected override void PopOut() + { + this.ResizeHeightTo(0); + contentContainer.FadeOut(duration / 4f, Easing.OutQuint); + } } } From 6e09d857fd3d2ed0b18737e6565836fb6ea5bdf7 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 26 Jul 2019 19:00:07 +0900 Subject: [PATCH 035/239] Fix ValueChanged events being called out of order --- osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 5606328575..5c98c72b75 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -53,7 +53,13 @@ namespace osu.Game.Graphics.Containers samplePopIn = audio.Samples.Get(@"UI/overlay-pop-in"); samplePopOut = audio.Samples.Get(@"UI/overlay-pop-out"); + } + protected override void LoadComplete() + { + base.LoadComplete(); + + // This must be added after the base LoadComplete. The overlay may need to be hidden immediately if its disabled. State.ValueChanged += onStateChanged; } From 1b0f7b0459c28ff4684b580e2104b69978ddea58 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 26 Jul 2019 19:05:55 +0900 Subject: [PATCH 036/239] more detailed explanation --- osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 5c98c72b75..158f96b46b 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -59,7 +59,8 @@ namespace osu.Game.Graphics.Containers { base.LoadComplete(); - // This must be added after the base LoadComplete. The overlay may need to be hidden immediately if its disabled. + // This must be added after the base LoadComplete. The overlay may need to be hidden immediately if its disabled, + // but the overlay doesn't get shown until after the stateChanged function from VisibilityContainer gets called. State.ValueChanged += onStateChanged; } From 4b5fb84888dd7afed64bdafc497031675182489d Mon Sep 17 00:00:00 2001 From: David Zhao Date: Mon, 29 Jul 2019 11:02:44 +0900 Subject: [PATCH 037/239] Rewrite comment --- osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 158f96b46b..c33e980a9a 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -59,8 +59,8 @@ namespace osu.Game.Graphics.Containers { base.LoadComplete(); - // This must be added after the base LoadComplete. The overlay may need to be hidden immediately if its disabled, - // but the overlay doesn't get shown until after the stateChanged function from VisibilityContainer gets called. + // This must be added after the base LoadComplete, since onStateChanged contains logic that + // must be run after other state change logic has been completed. State.ValueChanged += onStateChanged; } From ac0abe0692cd81496b6fd5b8839ede050202752d Mon Sep 17 00:00:00 2001 From: David Zhao Date: Tue, 6 Aug 2019 14:21:34 +0900 Subject: [PATCH 038/239] Use newly exposed UpdateState --- .../Containers/OsuFocusedOverlayContainer.cs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index c33e980a9a..eff853abcf 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -55,15 +55,6 @@ namespace osu.Game.Graphics.Containers samplePopOut = audio.Samples.Get(@"UI/overlay-pop-out"); } - protected override void LoadComplete() - { - base.LoadComplete(); - - // This must be added after the base LoadComplete, since onStateChanged contains logic that - // must be run after other state change logic has been completed. - State.ValueChanged += onStateChanged; - } - /// /// Whether mouse input should be blocked screen-wide while this overlay is visible. /// Performing mouse actions outside of the valid extents will hide the overlay. @@ -101,8 +92,10 @@ namespace osu.Game.Graphics.Containers public bool OnReleased(GlobalAction action) => false; - private void onStateChanged(ValueChangedEvent state) + protected override void UpdateState(ValueChangedEvent state) { + base.UpdateState(state); + switch (state.NewValue) { case Visibility.Visible: From 6e5cb8a318840fc1b1e156f8583641d4881cfd84 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 30 Aug 2019 23:19:34 +0300 Subject: [PATCH 039/239] implement video parsing --- osu.Game/Beatmaps/BeatmapManager.cs | 2 ++ .../Beatmaps/BeatmapManager_WorkingBeatmap.cs | 16 ++++++++++++++++ osu.Game/Beatmaps/BeatmapMetadata.cs | 4 +++- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 3 +++ .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 9 +++++++-- osu.Game/Beatmaps/IWorkingBeatmap.cs | 6 ++++++ osu.Game/Beatmaps/WorkingBeatmap.cs | 9 +++++++++ .../20171019041408_InitialCreate.Designer.cs | 2 ++ .../Migrations/20171019041408_InitialCreate.cs | 1 + ...171025071459_AddMissingIndexRules.Designer.cs | 2 ++ ...ddBeatmapOnlineIDUniqueConstraint.Designer.cs | 2 ++ ...209034410_AddRulesetInfoShortName.Designer.cs | 2 ++ .../20180125143340_Settings.Designer.cs | 2 ++ .../20180219060912_AddSkins.Designer.cs | 2 ++ ...55154_RemoveUniqueHashConstraints.Designer.cs | 2 ++ ...044111_UpdateTaikoDefaultBindings.Designer.cs | 2 ++ ...180628011956_RemoveNegativeSetIDs.Designer.cs | 2 ++ .../20180913080842_AddRankStatus.Designer.cs | 2 ++ .../20181007180454_StandardizePaths.Designer.cs | 2 ++ .../20181007180454_StandardizePaths.cs | 1 + .../20181128100659_AddSkinInfoHash.Designer.cs | 2 ++ ...20181130113755_AddScoreInfoTables.Designer.cs | 2 ++ .../20190225062029_AddUserIDColumn.Designer.cs | 2 ++ .../20190525060824_SkinSettings.Designer.cs | 2 ++ ...46_AddDateAddedColumnToBeatmapSet.Designer.cs | 2 ++ ...0708070844_AddBPMAndLengthColumns.Designer.cs | 2 ++ osu.Game/Migrations/OsuDbContextModelSnapshot.cs | 2 ++ osu.Game/Screens/Edit/EditorWorkingBeatmap.cs | 3 +++ osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs | 3 +++ osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs | 3 +++ 30 files changed, 93 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 166ba5111c..b9ed3664ef 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -13,6 +13,7 @@ using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Extensions; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Video; using osu.Framework.Lists; using osu.Framework.Logging; using osu.Framework.Platform; @@ -340,6 +341,7 @@ namespace osu.Game.Beatmaps protected override IBeatmap GetBeatmap() => beatmap; protected override Texture GetBackground() => null; + protected override VideoSprite GetVideo() => null; protected override Track GetTrack() => null; } diff --git a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs index 5bbffc2f77..1d00c94ef2 100644 --- a/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/BeatmapManager_WorkingBeatmap.cs @@ -7,6 +7,7 @@ using System.Linq; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Video; using osu.Framework.IO.Stores; using osu.Framework.Logging; using osu.Game.Beatmaps.Formats; @@ -64,6 +65,21 @@ namespace osu.Game.Beatmaps } } + protected override VideoSprite GetVideo() + { + if (Metadata?.VideoFile == null) + return null; + + try + { + return new VideoSprite(textureStore.GetStream(getPathForFile(Metadata.VideoFile))); + } + catch + { + return null; + } + } + protected override Track GetTrack() { try diff --git a/osu.Game/Beatmaps/BeatmapMetadata.cs b/osu.Game/Beatmaps/BeatmapMetadata.cs index 001f319307..9267527d79 100644 --- a/osu.Game/Beatmaps/BeatmapMetadata.cs +++ b/osu.Game/Beatmaps/BeatmapMetadata.cs @@ -52,6 +52,7 @@ namespace osu.Game.Beatmaps public int PreviewTime { get; set; } public string AudioFile { get; set; } public string BackgroundFile { get; set; } + public string VideoFile { get; set; } public override string ToString() => $"{Artist} - {Title} ({Author})"; @@ -81,7 +82,8 @@ namespace osu.Game.Beatmaps && Tags == other.Tags && PreviewTime == other.PreviewTime && AudioFile == other.AudioFile - && BackgroundFile == other.BackgroundFile; + && BackgroundFile == other.BackgroundFile + && VideoFile == other.VideoFile; } } } diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index 29ade24328..a3ab01c886 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -7,6 +7,7 @@ using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Video; using osu.Game.Rulesets; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; @@ -44,6 +45,8 @@ namespace osu.Game.Beatmaps protected override Texture GetBackground() => textures?.Get(@"Backgrounds/bg4"); + protected override VideoSprite GetVideo() => null; + protected override Track GetTrack() => GetVirtualTrack(); private class DummyRulesetInfo : RulesetInfo diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 02d969b571..0532790f0a 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -296,8 +296,13 @@ namespace osu.Game.Beatmaps.Formats switch (type) { case EventType.Background: - string filename = split[2].Trim('"'); - beatmap.BeatmapInfo.Metadata.BackgroundFile = FileSafety.PathStandardise(filename); + string bgFilename = split[2].Trim('"'); + beatmap.BeatmapInfo.Metadata.BackgroundFile = FileSafety.PathStandardise(bgFilename); + break; + + case EventType.Video: + string videoFilename = split[2].Trim('"'); + beatmap.BeatmapInfo.Metadata.VideoFile = FileSafety.PathStandardise(videoFilename); break; case EventType.Break: diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index 44071d9cc1..b932e67bae 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Video; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; @@ -25,6 +26,11 @@ namespace osu.Game.Beatmaps /// Texture Background { get; } + /// + /// Retrieves the video file for this . + /// + VideoSprite Video { get; } + /// /// Retrieves the audio track for this . /// diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index d8ab411beb..b489936556 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -19,6 +19,7 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.UI; using osu.Game.Skinning; +using osu.Framework.Graphics.Video; namespace osu.Game.Beatmaps { @@ -43,6 +44,7 @@ namespace osu.Game.Beatmaps track = new RecyclableLazy(() => GetTrack() ?? GetVirtualTrack()); background = new RecyclableLazy(GetBackground, BackgroundStillValid); + video = new RecyclableLazy(GetVideo); waveform = new RecyclableLazy(GetWaveform); storyboard = new RecyclableLazy(GetStoryboard); skin = new RecyclableLazy(GetSkin); @@ -183,9 +185,16 @@ namespace osu.Game.Beatmaps public bool BackgroundLoaded => background.IsResultAvailable; public Texture Background => background.Value; protected virtual bool BackgroundStillValid(Texture b) => b == null || b.Available; + protected abstract Texture GetBackground(); private readonly RecyclableLazy background; + public bool VideoLoaded => video.IsResultAvailable; + public VideoSprite Video => video.Value; + + protected abstract VideoSprite GetVideo(); + private readonly RecyclableLazy video; + public bool TrackLoaded => track.IsResultAvailable; public Track Track => track.Value; protected abstract Track GetTrack(); diff --git a/osu.Game/Migrations/20171019041408_InitialCreate.Designer.cs b/osu.Game/Migrations/20171019041408_InitialCreate.Designer.cs index c751530bf4..596d80557b 100644 --- a/osu.Game/Migrations/20171019041408_InitialCreate.Designer.cs +++ b/osu.Game/Migrations/20171019041408_InitialCreate.Designer.cs @@ -123,6 +123,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20171019041408_InitialCreate.cs b/osu.Game/Migrations/20171019041408_InitialCreate.cs index 9b6881f98c..3349998873 100644 --- a/osu.Game/Migrations/20171019041408_InitialCreate.cs +++ b/osu.Game/Migrations/20171019041408_InitialCreate.cs @@ -35,6 +35,7 @@ namespace osu.Game.Migrations AudioFile = table.Column(type: "TEXT", nullable: true), Author = table.Column(type: "TEXT", nullable: true), BackgroundFile = table.Column(type: "TEXT", nullable: true), + VideoFile = table.Column(type: "TEXT", nullable: true), PreviewTime = table.Column(type: "INTEGER", nullable: false), Source = table.Column(type: "TEXT", nullable: true), Tags = table.Column(type: "TEXT", nullable: true), diff --git a/osu.Game/Migrations/20171025071459_AddMissingIndexRules.Designer.cs b/osu.Game/Migrations/20171025071459_AddMissingIndexRules.Designer.cs index 4cd234f2ef..ab85aece9f 100644 --- a/osu.Game/Migrations/20171025071459_AddMissingIndexRules.Designer.cs +++ b/osu.Game/Migrations/20171025071459_AddMissingIndexRules.Designer.cs @@ -125,6 +125,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20171119065731_AddBeatmapOnlineIDUniqueConstraint.Designer.cs b/osu.Game/Migrations/20171119065731_AddBeatmapOnlineIDUniqueConstraint.Designer.cs index 006acf12cd..d565e1cbf2 100644 --- a/osu.Game/Migrations/20171119065731_AddBeatmapOnlineIDUniqueConstraint.Designer.cs +++ b/osu.Game/Migrations/20171119065731_AddBeatmapOnlineIDUniqueConstraint.Designer.cs @@ -128,6 +128,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20171209034410_AddRulesetInfoShortName.Designer.cs b/osu.Game/Migrations/20171209034410_AddRulesetInfoShortName.Designer.cs index fc2496bc24..3c37c59595 100644 --- a/osu.Game/Migrations/20171209034410_AddRulesetInfoShortName.Designer.cs +++ b/osu.Game/Migrations/20171209034410_AddRulesetInfoShortName.Designer.cs @@ -128,6 +128,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180125143340_Settings.Designer.cs b/osu.Game/Migrations/20180125143340_Settings.Designer.cs index 4bb599eec1..4c41d223c5 100644 --- a/osu.Game/Migrations/20180125143340_Settings.Designer.cs +++ b/osu.Game/Migrations/20180125143340_Settings.Designer.cs @@ -128,6 +128,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180219060912_AddSkins.Designer.cs b/osu.Game/Migrations/20180219060912_AddSkins.Designer.cs index cdc4ef2e66..124c61283f 100644 --- a/osu.Game/Migrations/20180219060912_AddSkins.Designer.cs +++ b/osu.Game/Migrations/20180219060912_AddSkins.Designer.cs @@ -128,6 +128,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs b/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs index f28408bfb3..9cbd75ce2c 100644 --- a/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs +++ b/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs @@ -126,6 +126,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.Designer.cs b/osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.Designer.cs index aaa11e88b6..150bc2ecbc 100644 --- a/osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.Designer.cs +++ b/osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.Designer.cs @@ -125,6 +125,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180628011956_RemoveNegativeSetIDs.Designer.cs b/osu.Game/Migrations/20180628011956_RemoveNegativeSetIDs.Designer.cs index 7eeacd56d7..0a1db37c7f 100644 --- a/osu.Game/Migrations/20180628011956_RemoveNegativeSetIDs.Designer.cs +++ b/osu.Game/Migrations/20180628011956_RemoveNegativeSetIDs.Designer.cs @@ -125,6 +125,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180913080842_AddRankStatus.Designer.cs b/osu.Game/Migrations/20180913080842_AddRankStatus.Designer.cs index 5ab43da046..b04d36fac1 100644 --- a/osu.Game/Migrations/20180913080842_AddRankStatus.Designer.cs +++ b/osu.Game/Migrations/20180913080842_AddRankStatus.Designer.cs @@ -127,6 +127,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20181007180454_StandardizePaths.Designer.cs b/osu.Game/Migrations/20181007180454_StandardizePaths.Designer.cs index b387a45ecf..aed946e577 100644 --- a/osu.Game/Migrations/20181007180454_StandardizePaths.Designer.cs +++ b/osu.Game/Migrations/20181007180454_StandardizePaths.Designer.cs @@ -127,6 +127,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20181007180454_StandardizePaths.cs b/osu.Game/Migrations/20181007180454_StandardizePaths.cs index 274b8030a9..c106b839e2 100644 --- a/osu.Game/Migrations/20181007180454_StandardizePaths.cs +++ b/osu.Game/Migrations/20181007180454_StandardizePaths.cs @@ -15,6 +15,7 @@ namespace osu.Game.Migrations migrationBuilder.Sql($"UPDATE `BeatmapInfo` SET `Path` = REPLACE(`Path`, '{windowsStyle}', '{standardized}')"); migrationBuilder.Sql($"UPDATE `BeatmapMetadata` SET `AudioFile` = REPLACE(`AudioFile`, '{windowsStyle}', '{standardized}')"); migrationBuilder.Sql($"UPDATE `BeatmapMetadata` SET `BackgroundFile` = REPLACE(`BackgroundFile`, '{windowsStyle}', '{standardized}')"); + migrationBuilder.Sql($"UPDATE `BeatmapMetadata` SET `VideoFile` = REPLACE(`VideoFile`, '{windowsStyle}', '{standardized}')"); migrationBuilder.Sql($"UPDATE `BeatmapSetFileInfo` SET `Filename` = REPLACE(`Filename`, '{windowsStyle}', '{standardized}')"); migrationBuilder.Sql($"UPDATE `SkinFileInfo` SET `Filename` = REPLACE(`Filename`, '{windowsStyle}', '{standardized}')"); } diff --git a/osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs b/osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs index 120674671a..fe0594e542 100644 --- a/osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs +++ b/osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs @@ -127,6 +127,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20181130113755_AddScoreInfoTables.Designer.cs b/osu.Game/Migrations/20181130113755_AddScoreInfoTables.Designer.cs index eee53182ce..efa64f014f 100644 --- a/osu.Game/Migrations/20181130113755_AddScoreInfoTables.Designer.cs +++ b/osu.Game/Migrations/20181130113755_AddScoreInfoTables.Designer.cs @@ -127,6 +127,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs b/osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs index 8e1e3a59f3..a950a54e39 100644 --- a/osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs +++ b/osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs @@ -127,6 +127,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs b/osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs index 348c42adb9..df2c434b4e 100644 --- a/osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs +++ b/osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs @@ -127,6 +127,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs b/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs index 9477369aa0..ea699edcc9 100644 --- a/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs +++ b/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs @@ -127,6 +127,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.Designer.cs b/osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.Designer.cs index c5fcc16f84..fb678178a2 100644 --- a/osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.Designer.cs +++ b/osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.Designer.cs @@ -131,6 +131,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index 761dca2801..1725812d33 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -129,6 +129,8 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); + b.Property("VideoFile"); + b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs b/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs index 299059407c..4b8720fe1c 100644 --- a/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorWorkingBeatmap.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Video; using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; @@ -33,6 +34,8 @@ namespace osu.Game.Screens.Edit public Texture Background => workingBeatmap.Background; + public VideoSprite Video => workingBeatmap.Video; + public Track Track => workingBeatmap.Track; public Waveform Waveform => workingBeatmap.Waveform; diff --git a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs index a555a52e42..3fc9662b17 100644 --- a/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs +++ b/osu.Game/Tests/Beatmaps/BeatmapConversionTest.cs @@ -10,6 +10,7 @@ using Newtonsoft.Json; using NUnit.Framework; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Video; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; using osu.Game.Rulesets; @@ -201,6 +202,8 @@ namespace osu.Game.Tests.Beatmaps protected override Texture GetBackground() => throw new NotImplementedException(); + protected override VideoSprite GetVideo() => throw new NotImplementedException(); + protected override Track GetTrack() => throw new NotImplementedException(); protected override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) diff --git a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs index 0ef35879e3..0d9f4f51be 100644 --- a/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs +++ b/osu.Game/Tests/Beatmaps/TestWorkingBeatmap.cs @@ -3,6 +3,7 @@ using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Video; using osu.Game.Beatmaps; namespace osu.Game.Tests.Beatmaps @@ -25,6 +26,8 @@ namespace osu.Game.Tests.Beatmaps protected override Texture GetBackground() => null; + protected override VideoSprite GetVideo() => null; + protected override Track GetTrack() => null; } } From 58a0b4e19b2f5cfe29e9a98e3d33d314ffd9c277 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 30 Aug 2019 23:19:55 +0300 Subject: [PATCH 040/239] Add basic layout for player --- osu.Game/Screens/Play/Player.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index b487f3e61b..9ff52d8444 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -10,6 +10,7 @@ using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Video; using osu.Framework.Input.Events; using osu.Framework.Logging; using osu.Framework.Screens; @@ -81,6 +82,8 @@ namespace osu.Game.Screens.Play protected DimmableStoryboard DimmableStoryboard { get; private set; } + protected VideoSprite Video { get; private set; } + [Cached] [Cached(Type = typeof(IBindable>))] protected new readonly Bindable> Mods = new Bindable>(Array.Empty()); @@ -143,6 +146,14 @@ namespace osu.Game.Screens.Play private void addUnderlayComponents(Container target) { target.Add(DimmableStoryboard = new DimmableStoryboard(Beatmap.Value.Storyboard) { RelativeSizeAxes = Axes.Both }); + + var video = Beatmap.Value.Video; + + if (video != null) + { + target.Add(Video = video); + Video.RelativeSizeAxes = Axes.Both; + } } private void addGameplayComponents(Container target, WorkingBeatmap working) From d55be4d59cd645e3dcde3d60c28c266235127115 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 30 Aug 2019 23:48:38 +0300 Subject: [PATCH 041/239] Implement DimmableVideo component --- osu.Game/Screens/Play/DimmableVideo.cs | 64 ++++++++++++++++++++++++++ osu.Game/Screens/Play/Player.cs | 10 +--- 2 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 osu.Game/Screens/Play/DimmableVideo.cs diff --git a/osu.Game/Screens/Play/DimmableVideo.cs b/osu.Game/Screens/Play/DimmableVideo.cs new file mode 100644 index 0000000000..68ce5fcd40 --- /dev/null +++ b/osu.Game/Screens/Play/DimmableVideo.cs @@ -0,0 +1,64 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Video; +using osu.Game.Graphics.Containers; + +namespace osu.Game.Screens.Play +{ + public class DimmableVideo : UserDimContainer + { + private readonly VideoSprite video; + private DrawableVideo drawableVideo; + + public DimmableVideo(VideoSprite video) + { + this.video = video; + } + + [BackgroundDependencyLoader] + private void load() + { + initializeVideo(false); + } + + protected override void LoadComplete() + { + ShowStoryboard.BindValueChanged(_ => initializeVideo(true), true); + base.LoadComplete(); + } + + protected override bool ShowDimContent => ShowStoryboard.Value && DimLevel < 1; + + private void initializeVideo(bool async) + { + if (drawableVideo != null) + return; + + if (!ShowStoryboard.Value) + return; + + drawableVideo = new DrawableVideo(video); + + if (async) + LoadComponentAsync(drawableVideo, Add); + else + Add(drawableVideo); + } + + private class DrawableVideo : Container + { + public DrawableVideo(VideoSprite video) + { + RelativeSizeAxes = Axes.Both; + Masking = true; + + AddInternal(video); + video.RelativeSizeAxes = Axes.Both; + } + } + } +} diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 9ff52d8444..968b78ad8e 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -81,6 +81,7 @@ namespace osu.Game.Screens.Play protected GameplayClockContainer GameplayClockContainer { get; private set; } protected DimmableStoryboard DimmableStoryboard { get; private set; } + protected DimmableVideo DimmableVideo { get; private set; } protected VideoSprite Video { get; private set; } @@ -146,14 +147,7 @@ namespace osu.Game.Screens.Play private void addUnderlayComponents(Container target) { target.Add(DimmableStoryboard = new DimmableStoryboard(Beatmap.Value.Storyboard) { RelativeSizeAxes = Axes.Both }); - - var video = Beatmap.Value.Video; - - if (video != null) - { - target.Add(Video = video); - Video.RelativeSizeAxes = Axes.Both; - } + target.Add(DimmableVideo = new DimmableVideo(Beatmap.Value.Video) { RelativeSizeAxes = Axes.Both }); } private void addGameplayComponents(Container target, WorkingBeatmap working) From 5dd688a51b841f534070fe3066905817a9dec8c4 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 31 Aug 2019 00:09:23 +0300 Subject: [PATCH 042/239] Fix video doesn't use gameplay clock --- osu.Game/Screens/Play/DimmableVideo.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Screens/Play/DimmableVideo.cs b/osu.Game/Screens/Play/DimmableVideo.cs index 68ce5fcd40..bc4105c3b9 100644 --- a/osu.Game/Screens/Play/DimmableVideo.cs +++ b/osu.Game/Screens/Play/DimmableVideo.cs @@ -59,6 +59,13 @@ namespace osu.Game.Screens.Play AddInternal(video); video.RelativeSizeAxes = Axes.Both; } + + [BackgroundDependencyLoader] + private void load(GameplayClock clock) + { + if (clock != null) + Clock = clock; + } } } } From fa3591e5ec35b80115b3ed3005067ef1ae05231a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 31 Aug 2019 00:42:20 +0300 Subject: [PATCH 043/239] Add setting to turn on/off the video --- osu.Game/Configuration/OsuConfigManager.cs | 2 ++ osu.Game/Graphics/Containers/UserDimContainer.cs | 4 ++++ .../Overlays/Settings/Sections/Graphics/DetailSettings.cs | 5 +++++ osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs | 2 +- osu.Game/Screens/Play/DimmableVideo.cs | 6 +++--- osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs | 3 +++ 6 files changed, 18 insertions(+), 4 deletions(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 0cecbb225f..357883da45 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -69,6 +69,7 @@ namespace osu.Game.Configuration Set(OsuSetting.ShowFpsDisplay, false); Set(OsuSetting.ShowStoryboard, true); + Set(OsuSetting.ShowVideo, true); Set(OsuSetting.BeatmapSkins, true); Set(OsuSetting.BeatmapHitsounds, true); @@ -136,6 +137,7 @@ namespace osu.Game.Configuration DimLevel, BlurLevel, ShowStoryboard, + ShowVideo, KeyOverlay, ScoreMeter, FloatingComments, diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index 2b7635cc88..d0e932fac0 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -35,6 +35,8 @@ namespace osu.Game.Graphics.Containers protected Bindable ShowStoryboard { get; private set; } + protected Bindable ShowVideo { get; private set; } + protected double DimLevel => EnableUserDim.Value ? UserDimLevel.Value : 0; protected override Container Content => dimContent; @@ -54,10 +56,12 @@ namespace osu.Game.Graphics.Containers { UserDimLevel = config.GetBindable(OsuSetting.DimLevel); ShowStoryboard = config.GetBindable(OsuSetting.ShowStoryboard); + ShowVideo = config.GetBindable(OsuSetting.ShowVideo); EnableUserDim.ValueChanged += _ => UpdateVisuals(); UserDimLevel.ValueChanged += _ => UpdateVisuals(); ShowStoryboard.ValueChanged += _ => UpdateVisuals(); + ShowVideo.ValueChanged += _ => UpdateVisuals(); StoryboardReplacesBackground.ValueChanged += _ => UpdateVisuals(); } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs index 01cdc9aa32..6d9870598f 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs @@ -22,6 +22,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics Bindable = config.GetBindable(OsuSetting.ShowStoryboard) }, new SettingsCheckbox + { + LabelText = "Video", + Bindable = config.GetBindable(OsuSetting.ShowVideo) + }, + new SettingsCheckbox { LabelText = "Rotate cursor when dragging", Bindable = config.GetBindable(OsuSetting.CursorRotation) diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs index 5225740d0b..2730b0b90d 100644 --- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs +++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs @@ -178,7 +178,7 @@ namespace osu.Game.Screens.Backgrounds BlurAmount.ValueChanged += _ => UpdateVisuals(); } - protected override bool ShowDimContent => !ShowStoryboard.Value || !StoryboardReplacesBackground.Value; // The background needs to be hidden in the case of it being replaced by the storyboard + protected override bool ShowDimContent => !ShowStoryboard.Value || !StoryboardReplacesBackground.Value || !ShowVideo.Value; // The background needs to be hidden in the case of it being replaced by the storyboard protected override void UpdateVisuals() { diff --git a/osu.Game/Screens/Play/DimmableVideo.cs b/osu.Game/Screens/Play/DimmableVideo.cs index bc4105c3b9..0452af8419 100644 --- a/osu.Game/Screens/Play/DimmableVideo.cs +++ b/osu.Game/Screens/Play/DimmableVideo.cs @@ -27,18 +27,18 @@ namespace osu.Game.Screens.Play protected override void LoadComplete() { - ShowStoryboard.BindValueChanged(_ => initializeVideo(true), true); + ShowVideo.BindValueChanged(_ => initializeVideo(true), true); base.LoadComplete(); } - protected override bool ShowDimContent => ShowStoryboard.Value && DimLevel < 1; + protected override bool ShowDimContent => ShowVideo.Value && DimLevel < 1; private void initializeVideo(bool async) { if (drawableVideo != null) return; - if (!ShowStoryboard.Value) + if (!ShowVideo.Value) return; drawableVideo = new DrawableVideo(video); diff --git a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs index 1c8628f704..5e47b730ad 100644 --- a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs @@ -15,6 +15,7 @@ namespace osu.Game.Screens.Play.PlayerSettings private readonly PlayerSliderBar dimSliderBar; private readonly PlayerSliderBar blurSliderBar; private readonly PlayerCheckbox showStoryboardToggle; + private readonly PlayerCheckbox showVideoToggle; private readonly PlayerCheckbox beatmapSkinsToggle; private readonly PlayerCheckbox beatmapHitsoundsToggle; @@ -37,6 +38,7 @@ namespace osu.Game.Screens.Play.PlayerSettings Text = "Toggles:" }, showStoryboardToggle = new PlayerCheckbox { LabelText = "Storyboards" }, + showVideoToggle = new PlayerCheckbox { LabelText = "Video" }, beatmapSkinsToggle = new PlayerCheckbox { LabelText = "Beatmap skins" }, beatmapHitsoundsToggle = new PlayerCheckbox { LabelText = "Beatmap hitsounds" } }; @@ -48,6 +50,7 @@ namespace osu.Game.Screens.Play.PlayerSettings dimSliderBar.Bindable = config.GetBindable(OsuSetting.DimLevel); blurSliderBar.Bindable = config.GetBindable(OsuSetting.BlurLevel); showStoryboardToggle.Current = config.GetBindable(OsuSetting.ShowStoryboard); + showVideoToggle.Current = config.GetBindable(OsuSetting.ShowVideo); beatmapSkinsToggle.Current = config.GetBindable(OsuSetting.BeatmapSkins); beatmapHitsoundsToggle.Current = config.GetBindable(OsuSetting.BeatmapHitsounds); } From 264441d90c0662edfdcf722e7806f9997551c0de Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 31 Aug 2019 02:42:26 +0300 Subject: [PATCH 044/239] Fix broken test --- osu.Game.Tests/WaveformTestBeatmap.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Tests/WaveformTestBeatmap.cs b/osu.Game.Tests/WaveformTestBeatmap.cs index 3e0df8d45e..db9576b5fa 100644 --- a/osu.Game.Tests/WaveformTestBeatmap.cs +++ b/osu.Game.Tests/WaveformTestBeatmap.cs @@ -6,6 +6,7 @@ using System.Linq; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; +using osu.Framework.Graphics.Video; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Formats; using osu.Game.IO.Archives; @@ -42,6 +43,8 @@ namespace osu.Game.Tests protected override Texture GetBackground() => null; + protected override VideoSprite GetVideo() => null; + protected override Waveform GetWaveform() => new Waveform(trackStore.GetStream(firstAudioFile)); protected override Track GetTrack() => trackStore.Get(firstAudioFile); From fd958ec1abb31f182b673dc2b13223df9a854560 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 31 Aug 2019 02:56:41 +0300 Subject: [PATCH 045/239] Remove unused property accessor --- osu.Game/Screens/Play/Player.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 968b78ad8e..b5a378506a 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -83,8 +83,6 @@ namespace osu.Game.Screens.Play protected DimmableStoryboard DimmableStoryboard { get; private set; } protected DimmableVideo DimmableVideo { get; private set; } - protected VideoSprite Video { get; private set; } - [Cached] [Cached(Type = typeof(IBindable>))] protected new readonly Bindable> Mods = new Bindable>(Array.Empty()); From d4291556eef6a67926b0dffd855c933abfc1ab82 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 31 Aug 2019 02:57:14 +0300 Subject: [PATCH 046/239] Remove unused using --- osu.Game/Screens/Play/Player.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index b5a378506a..274107dfa5 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -10,7 +10,6 @@ using osu.Framework.Audio.Sample; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Video; using osu.Framework.Input.Events; using osu.Framework.Logging; using osu.Framework.Screens; From c10d2302dc6d276a3f50601bd59db44a1b4ec443 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 31 Aug 2019 15:49:57 +0300 Subject: [PATCH 047/239] Remove video property from migrations --- osu.Game/Migrations/20171019041408_InitialCreate.Designer.cs | 2 -- .../Migrations/20171025071459_AddMissingIndexRules.Designer.cs | 2 -- ...0171119065731_AddBeatmapOnlineIDUniqueConstraint.Designer.cs | 2 -- .../20171209034410_AddRulesetInfoShortName.Designer.cs | 2 -- osu.Game/Migrations/20180125143340_Settings.Designer.cs | 2 -- osu.Game/Migrations/20180219060912_AddSkins.Designer.cs | 2 -- .../20180529055154_RemoveUniqueHashConstraints.Designer.cs | 2 -- .../20180621044111_UpdateTaikoDefaultBindings.Designer.cs | 2 -- .../Migrations/20180628011956_RemoveNegativeSetIDs.Designer.cs | 2 -- osu.Game/Migrations/20180913080842_AddRankStatus.Designer.cs | 2 -- osu.Game/Migrations/20181007180454_StandardizePaths.Designer.cs | 2 -- osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs | 2 -- .../Migrations/20181130113755_AddScoreInfoTables.Designer.cs | 2 -- osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs | 2 -- osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs | 2 -- .../20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs | 2 -- .../20190708070844_AddBPMAndLengthColumns.Designer.cs | 2 -- osu.Game/Migrations/OsuDbContextModelSnapshot.cs | 2 -- 18 files changed, 36 deletions(-) diff --git a/osu.Game/Migrations/20171019041408_InitialCreate.Designer.cs b/osu.Game/Migrations/20171019041408_InitialCreate.Designer.cs index 596d80557b..c751530bf4 100644 --- a/osu.Game/Migrations/20171019041408_InitialCreate.Designer.cs +++ b/osu.Game/Migrations/20171019041408_InitialCreate.Designer.cs @@ -123,8 +123,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20171025071459_AddMissingIndexRules.Designer.cs b/osu.Game/Migrations/20171025071459_AddMissingIndexRules.Designer.cs index ab85aece9f..4cd234f2ef 100644 --- a/osu.Game/Migrations/20171025071459_AddMissingIndexRules.Designer.cs +++ b/osu.Game/Migrations/20171025071459_AddMissingIndexRules.Designer.cs @@ -125,8 +125,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20171119065731_AddBeatmapOnlineIDUniqueConstraint.Designer.cs b/osu.Game/Migrations/20171119065731_AddBeatmapOnlineIDUniqueConstraint.Designer.cs index d565e1cbf2..006acf12cd 100644 --- a/osu.Game/Migrations/20171119065731_AddBeatmapOnlineIDUniqueConstraint.Designer.cs +++ b/osu.Game/Migrations/20171119065731_AddBeatmapOnlineIDUniqueConstraint.Designer.cs @@ -128,8 +128,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20171209034410_AddRulesetInfoShortName.Designer.cs b/osu.Game/Migrations/20171209034410_AddRulesetInfoShortName.Designer.cs index 3c37c59595..fc2496bc24 100644 --- a/osu.Game/Migrations/20171209034410_AddRulesetInfoShortName.Designer.cs +++ b/osu.Game/Migrations/20171209034410_AddRulesetInfoShortName.Designer.cs @@ -128,8 +128,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180125143340_Settings.Designer.cs b/osu.Game/Migrations/20180125143340_Settings.Designer.cs index 4c41d223c5..4bb599eec1 100644 --- a/osu.Game/Migrations/20180125143340_Settings.Designer.cs +++ b/osu.Game/Migrations/20180125143340_Settings.Designer.cs @@ -128,8 +128,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180219060912_AddSkins.Designer.cs b/osu.Game/Migrations/20180219060912_AddSkins.Designer.cs index 124c61283f..cdc4ef2e66 100644 --- a/osu.Game/Migrations/20180219060912_AddSkins.Designer.cs +++ b/osu.Game/Migrations/20180219060912_AddSkins.Designer.cs @@ -128,8 +128,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs b/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs index 9cbd75ce2c..f28408bfb3 100644 --- a/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs +++ b/osu.Game/Migrations/20180529055154_RemoveUniqueHashConstraints.Designer.cs @@ -126,8 +126,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.Designer.cs b/osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.Designer.cs index 150bc2ecbc..aaa11e88b6 100644 --- a/osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.Designer.cs +++ b/osu.Game/Migrations/20180621044111_UpdateTaikoDefaultBindings.Designer.cs @@ -125,8 +125,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180628011956_RemoveNegativeSetIDs.Designer.cs b/osu.Game/Migrations/20180628011956_RemoveNegativeSetIDs.Designer.cs index 0a1db37c7f..7eeacd56d7 100644 --- a/osu.Game/Migrations/20180628011956_RemoveNegativeSetIDs.Designer.cs +++ b/osu.Game/Migrations/20180628011956_RemoveNegativeSetIDs.Designer.cs @@ -125,8 +125,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20180913080842_AddRankStatus.Designer.cs b/osu.Game/Migrations/20180913080842_AddRankStatus.Designer.cs index b04d36fac1..5ab43da046 100644 --- a/osu.Game/Migrations/20180913080842_AddRankStatus.Designer.cs +++ b/osu.Game/Migrations/20180913080842_AddRankStatus.Designer.cs @@ -127,8 +127,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20181007180454_StandardizePaths.Designer.cs b/osu.Game/Migrations/20181007180454_StandardizePaths.Designer.cs index aed946e577..b387a45ecf 100644 --- a/osu.Game/Migrations/20181007180454_StandardizePaths.Designer.cs +++ b/osu.Game/Migrations/20181007180454_StandardizePaths.Designer.cs @@ -127,8 +127,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs b/osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs index fe0594e542..120674671a 100644 --- a/osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs +++ b/osu.Game/Migrations/20181128100659_AddSkinInfoHash.Designer.cs @@ -127,8 +127,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20181130113755_AddScoreInfoTables.Designer.cs b/osu.Game/Migrations/20181130113755_AddScoreInfoTables.Designer.cs index efa64f014f..eee53182ce 100644 --- a/osu.Game/Migrations/20181130113755_AddScoreInfoTables.Designer.cs +++ b/osu.Game/Migrations/20181130113755_AddScoreInfoTables.Designer.cs @@ -127,8 +127,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs b/osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs index a950a54e39..8e1e3a59f3 100644 --- a/osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs +++ b/osu.Game/Migrations/20190225062029_AddUserIDColumn.Designer.cs @@ -127,8 +127,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs b/osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs index df2c434b4e..348c42adb9 100644 --- a/osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs +++ b/osu.Game/Migrations/20190525060824_SkinSettings.Designer.cs @@ -127,8 +127,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs b/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs index ea699edcc9..9477369aa0 100644 --- a/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs +++ b/osu.Game/Migrations/20190605091246_AddDateAddedColumnToBeatmapSet.Designer.cs @@ -127,8 +127,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.Designer.cs b/osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.Designer.cs index fb678178a2..c5fcc16f84 100644 --- a/osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.Designer.cs +++ b/osu.Game/Migrations/20190708070844_AddBPMAndLengthColumns.Designer.cs @@ -131,8 +131,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index 1725812d33..761dca2801 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -129,8 +129,6 @@ namespace osu.Game.Migrations b.Property("BackgroundFile"); - b.Property("VideoFile"); - b.Property("PreviewTime"); b.Property("Source"); From d2f7a653a8aecc198fb7cadaddbbe75e2888b855 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 31 Aug 2019 16:10:07 +0300 Subject: [PATCH 048/239] Fix nullref --- osu.Game/Screens/Play/DimmableVideo.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Play/DimmableVideo.cs b/osu.Game/Screens/Play/DimmableVideo.cs index 0452af8419..3e6b95d2cc 100644 --- a/osu.Game/Screens/Play/DimmableVideo.cs +++ b/osu.Game/Screens/Play/DimmableVideo.cs @@ -35,6 +35,9 @@ namespace osu.Game.Screens.Play private void initializeVideo(bool async) { + if (video == null) + return; + if (drawableVideo != null) return; From 94512fea8e82504f920a3e56a0a195029b831cdf Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 31 Aug 2019 16:20:33 +0300 Subject: [PATCH 049/239] Apply naming suggestions --- osu.Game/Beatmaps/IWorkingBeatmap.cs | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 1 - osu.Game/Configuration/OsuConfigManager.cs | 4 ++-- osu.Game/Graphics/Containers/UserDimContainer.cs | 2 +- .../Overlays/Settings/Sections/Graphics/DetailSettings.cs | 2 +- osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs | 2 +- 6 files changed, 6 insertions(+), 7 deletions(-) diff --git a/osu.Game/Beatmaps/IWorkingBeatmap.cs b/osu.Game/Beatmaps/IWorkingBeatmap.cs index b932e67bae..a087a52ada 100644 --- a/osu.Game/Beatmaps/IWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/IWorkingBeatmap.cs @@ -27,7 +27,7 @@ namespace osu.Game.Beatmaps Texture Background { get; } /// - /// Retrieves the video file for this . + /// Retrieves the video background file for this . /// VideoSprite Video { get; } diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index b489936556..bf3fa90d7b 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -185,7 +185,6 @@ namespace osu.Game.Beatmaps public bool BackgroundLoaded => background.IsResultAvailable; public Texture Background => background.Value; protected virtual bool BackgroundStillValid(Texture b) => b == null || b.Available; - protected abstract Texture GetBackground(); private readonly RecyclableLazy background; diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 357883da45..71a74a5558 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -69,7 +69,7 @@ namespace osu.Game.Configuration Set(OsuSetting.ShowFpsDisplay, false); Set(OsuSetting.ShowStoryboard, true); - Set(OsuSetting.ShowVideo, true); + Set(OsuSetting.ShowVideoBackground, true); Set(OsuSetting.BeatmapSkins, true); Set(OsuSetting.BeatmapHitsounds, true); @@ -137,7 +137,7 @@ namespace osu.Game.Configuration DimLevel, BlurLevel, ShowStoryboard, - ShowVideo, + ShowVideoBackground, KeyOverlay, ScoreMeter, FloatingComments, diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs index d0e932fac0..7683bbcd63 100644 --- a/osu.Game/Graphics/Containers/UserDimContainer.cs +++ b/osu.Game/Graphics/Containers/UserDimContainer.cs @@ -56,7 +56,7 @@ namespace osu.Game.Graphics.Containers { UserDimLevel = config.GetBindable(OsuSetting.DimLevel); ShowStoryboard = config.GetBindable(OsuSetting.ShowStoryboard); - ShowVideo = config.GetBindable(OsuSetting.ShowVideo); + ShowVideo = config.GetBindable(OsuSetting.ShowVideoBackground); EnableUserDim.ValueChanged += _ => UpdateVisuals(); UserDimLevel.ValueChanged += _ => UpdateVisuals(); diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs index 6d9870598f..56e56f6ca8 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics new SettingsCheckbox { LabelText = "Video", - Bindable = config.GetBindable(OsuSetting.ShowVideo) + Bindable = config.GetBindable(OsuSetting.ShowVideoBackground) }, new SettingsCheckbox { diff --git a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs index 5e47b730ad..ff64f35a18 100644 --- a/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs +++ b/osu.Game/Screens/Play/PlayerSettings/VisualSettings.cs @@ -50,7 +50,7 @@ namespace osu.Game.Screens.Play.PlayerSettings dimSliderBar.Bindable = config.GetBindable(OsuSetting.DimLevel); blurSliderBar.Bindable = config.GetBindable(OsuSetting.BlurLevel); showStoryboardToggle.Current = config.GetBindable(OsuSetting.ShowStoryboard); - showVideoToggle.Current = config.GetBindable(OsuSetting.ShowVideo); + showVideoToggle.Current = config.GetBindable(OsuSetting.ShowVideoBackground); beatmapSkinsToggle.Current = config.GetBindable(OsuSetting.BeatmapSkins); beatmapHitsoundsToggle.Current = config.GetBindable(OsuSetting.BeatmapHitsounds); } From a1c580f27ecae7f58bc6fbf6b58de8b6cef9b885 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 5 Sep 2019 05:56:21 +0300 Subject: [PATCH 050/239] Create "none selected" placeholder state --- osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs | 1 + osu.Game/Online/Leaderboards/Leaderboard.cs | 4 ++++ osu.Game/Online/Leaderboards/PlaceholderState.cs | 1 + .../Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 8 +++++++- 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs index 8e358a77db..186f27a8b2 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs @@ -42,6 +42,7 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep(@"No supporter", () => leaderboard.SetRetrievalState(PlaceholderState.NotSupporter)); AddStep(@"Not logged in", () => leaderboard.SetRetrievalState(PlaceholderState.NotLoggedIn)); AddStep(@"Unavailable", () => leaderboard.SetRetrievalState(PlaceholderState.Unavailable)); + AddStep(@"None selected", () => leaderboard.SetRetrievalState(PlaceholderState.NoneSelected)); foreach (BeatmapSetOnlineStatus status in Enum.GetValues(typeof(BeatmapSetOnlineStatus))) AddStep($"{status} beatmap", () => showBeatmapWithStatus(status)); } diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 98f15599fc..147556b78b 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -133,6 +133,10 @@ namespace osu.Game.Online.Leaderboards }); break; + case PlaceholderState.NoneSelected: + replacePlaceholder(new MessagePlaceholder(@"Please select a beatmap!")); + break; + case PlaceholderState.Unavailable: replacePlaceholder(new MessagePlaceholder(@"Leaderboards are not available for this beatmap!")); break; diff --git a/osu.Game/Online/Leaderboards/PlaceholderState.cs b/osu.Game/Online/Leaderboards/PlaceholderState.cs index 930e1df484..297241fa73 100644 --- a/osu.Game/Online/Leaderboards/PlaceholderState.cs +++ b/osu.Game/Online/Leaderboards/PlaceholderState.cs @@ -9,6 +9,7 @@ namespace osu.Game.Online.Leaderboards Retrieving, NetworkFailure, Unavailable, + NoneSelected, NoScores, NotLoggedIn, NotSupporter, diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index cb45c00f66..33f040755e 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -83,6 +83,12 @@ namespace osu.Game.Screens.Select.Leaderboards protected override APIRequest FetchScores(Action> scoresCallback) { + if (Beatmap == null) + { + PlaceholderState = PlaceholderState.NoneSelected; + return null; + } + if (Scope == BeatmapLeaderboardScope.Local) { var scores = scoreManager @@ -113,7 +119,7 @@ namespace osu.Game.Screens.Select.Leaderboards return null; } - if (Beatmap?.OnlineBeatmapID == null || Beatmap?.Status <= BeatmapSetOnlineStatus.Pending) + if (Beatmap.OnlineBeatmapID == null || Beatmap?.Status <= BeatmapSetOnlineStatus.Pending) { PlaceholderState = PlaceholderState.Unavailable; return null; From 1b0123a60cb22e89f009b2befbc024960dee706f Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 5 Sep 2019 05:56:52 +0300 Subject: [PATCH 051/239] Set beatmap of leaderboard to null if NoBeatmapsAvailable is selected --- osu.Game/Screens/Select/BeatmapDetailArea.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index b66a2ffe0f..bf8fc8cf07 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -27,8 +27,8 @@ namespace osu.Game.Screens.Select set { beatmap = value; - Leaderboard.Beatmap = beatmap?.BeatmapInfo; Details.Beatmap = beatmap?.BeatmapInfo; + Leaderboard.Beatmap = beatmap is NoBeatmapsAvailableWorkingBeatmap ? null : beatmap?.BeatmapInfo; } } From 374479f837b3e56e527b6682d9d7234f78ea4adf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Sep 2019 19:00:49 +0900 Subject: [PATCH 052/239] Add truncatino of long usernames in chat --- .../Online/TestSceneChatLineTruncation.cs | 108 ++++++++++++++++++ osu.Game/Overlays/Chat/ChatLine.cs | 10 +- 2 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs b/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs new file mode 100644 index 0000000000..888e55ab0a --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs @@ -0,0 +1,108 @@ +// Copyright (c) 2007-2018 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System; +using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Containers; +using osu.Game.Online.Chat; +using osu.Game.Overlays.Chat; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Online +{ + [TestFixture] + public class TestSceneChatLineTruncation : OsuTestScene + { + private readonly TestChatLineContainer textContainer; + + public override IReadOnlyList RequiredTypes => new[] + { + typeof(ChatLine), + typeof(Message), + typeof(LinkFlowContainer), + typeof(MessageFormatter) + }; + + public TestSceneChatLineTruncation() + { + Add(textContainer = new TestChatLineContainer + { + Padding = new MarginPadding { Left = 20, Right = 20 }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + }); + } + + [BackgroundDependencyLoader] + private void load() + { + testFormatting(); + } + + private void clear() => AddStep("clear messages", textContainer.Clear); + + private void addMessageWithChecks(string text, bool isAction = false, bool isImportant = false, string username = null) + { + int index = textContainer.Count + 1; + var newLine = new ChatLine(new DummyMessage(text, isAction, isImportant, index, username)); + textContainer.Add(newLine); + } + + private void testFormatting() + { + for (int a = 0; a < 25; a++) + addMessageWithChecks($"Wide {a} character username.", username: new string('w', a)); + addMessageWithChecks("Short name with spaces.", username: "sho rt name"); + addMessageWithChecks("Long name with spaces.", username: "long name with s p a c e s"); + } + + private class DummyMessage : Message + { + private static long messageCounter; + + internal static readonly User TEST_SENDER_BACKGROUND = new User + { + Username = @"i-am-important", + Id = 42, + Colour = "#250cc9", + }; + + internal static readonly User TEST_SENDER = new User + { + Username = @"Somebody", + Id = 1, + }; + + public new DateTimeOffset Timestamp = DateTimeOffset.Now; + + public DummyMessage(string text, bool isAction = false, bool isImportant = false, int number = 0, string username = null) + : base(messageCounter++) + { + Content = text; + IsAction = isAction; + Sender = new User + { + Username = username ?? $"user {number}", + Id = number, + Colour = isImportant ? "#250cc9" : null, + }; + } + } + + private class TestChatLineContainer : FillFlowContainer + { + protected override int Compare(Drawable x, Drawable y) + { + var xC = (ChatLine)x; + var yC = (ChatLine)y; + + return xC.Message.CompareTo(yC.Message); + } + } + } +} diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 2576b38ec8..a07b6472a3 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -31,6 +31,8 @@ namespace osu.Game.Overlays.Chat protected virtual float MessagePadding => default_message_padding; + private const float timestamp_padding = 70; + private const float default_horizontal_padding = 15; protected virtual float HorizontalPadding => default_horizontal_padding; @@ -87,7 +89,10 @@ namespace osu.Game.Overlays.Chat { Shadow = false, Colour = hasBackground ? customUsernameColour : username_colours[message.Sender.Id % username_colours.Length], - Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true) + Truncate = true, + EllipsisString = ".. :", + Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true), + RelativeSizeAxes = Axes.Both, }; if (hasBackground) @@ -141,7 +146,8 @@ namespace osu.Game.Overlays.Chat }, new MessageSender(message.Sender) { - AutoSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = timestamp_padding }, + RelativeSizeAxes = Axes.Both, Origin = Anchor.TopRight, Anchor = Anchor.TopRight, Child = effectedUsername, From c6b8f2db77313f29bdfa106a042a9ba211b009fc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 6 Sep 2019 19:05:50 +0900 Subject: [PATCH 053/239] Update historic licence header --- osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs | 4 ++-- osu.Game/Overlays/Chat/ChatLine.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs b/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs index 888e55ab0a..4773e84a5e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatLineTruncation.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2007-2018 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index a07b6472a3..d812e007a0 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Chat protected virtual float MessagePadding => default_message_padding; - private const float timestamp_padding = 70; + private const float timestamp_padding = 70; private const float default_horizontal_padding = 15; From 7f2d14416a16d7b849e7c9be682bd4f84493c024 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 7 Sep 2019 14:44:44 +0900 Subject: [PATCH 054/239] Reset DrawableHitObject lifetimes on state change --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index db87d4b4f2..e3390c8cf0 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -153,6 +153,9 @@ namespace osu.Game.Rulesets.Objects.Drawables if (UseTransformStateManagement) { + lifetimeStart = null; + LifetimeEnd = double.MaxValue; + double transformTime = HitObject.StartTime - InitialLifetimeOffset; base.ApplyTransformsAt(transformTime, true); From fdd36874371909a1dd4391dbf828bb015cf441cc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 8 Sep 2019 00:09:24 +0900 Subject: [PATCH 055/239] Fix catcher additive sprites staying on screen during rewind --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index ceda643335..592a45c865 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -197,6 +197,7 @@ namespace osu.Game.Rulesets.Catch.UI additive.Anchor = Anchor; additive.OriginPosition = additive.OriginPosition + new Vector2(DrawWidth / 2, 0); // also temporary to align sprite correctly. + additive.LifetimeStart = Clock.CurrentTime; additive.Position = Position; additive.Scale = Scale; additive.Colour = HyperDashing ? Color4.Red : Color4.White; From ec7a50b75f946453c76d351e181162136a7d88b5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 8 Sep 2019 00:10:31 +0900 Subject: [PATCH 056/239] Fix already caught osu!catch objects not correctly disappearing --- .../Objects/Drawable/DrawableCatchHitObject.cs | 4 ++++ osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 13 ++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index 00734810b3..ce90319846 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -50,6 +50,10 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable public Func CheckPosition; + public bool IsOnPlate; + + public override bool RemoveWhenNotAlive => IsOnPlate; + protected override void CheckForResult(bool userTriggered, double timeOffset) { if (CheckPosition == null) return; diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 592a45c865..330f6e6b24 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -69,6 +69,7 @@ namespace osu.Game.Rulesets.Catch.UI caughtFruit.RelativePositionAxes = Axes.None; caughtFruit.Position = new Vector2(MovableCatcher.ToLocalSpace(fruit.ScreenSpaceDrawQuad.Centre).X - MovableCatcher.DrawSize.X / 2, 0); + caughtFruit.IsOnPlate = true; caughtFruit.Anchor = Anchor.TopCentre; caughtFruit.Origin = Anchor.Centre; @@ -384,6 +385,12 @@ namespace osu.Game.Rulesets.Catch.UI X = hyperDashTargetPosition; SetHyperDashState(); } + + if (Clock.ElapsedFrameTime < 0) + { + AdditiveTarget.RemoveAll(d => Clock.CurrentTime < d.LifetimeStart); + caughtFruit.RemoveAll(d => d.HitObject.StartTime > Clock.CurrentTime); + } } /// @@ -407,7 +414,7 @@ namespace osu.Game.Rulesets.Catch.UI f.MoveToY(f.Y + 75, 750, Easing.InSine); f.FadeOut(750); - f.Expire(); + f.Expire(true); } } @@ -437,11 +444,11 @@ namespace osu.Game.Rulesets.Catch.UI ExplodingFruitTarget.Add(fruit); } + fruit.ClearTransforms(); fruit.MoveToY(fruit.Y - 50, 250, Easing.OutSine).Then().MoveToY(fruit.Y + 50, 500, Easing.InSine); fruit.MoveToX(fruit.X + originalX * 6, 1000); fruit.FadeOut(750); - - fruit.Expire(); + fruit.Expire(true); } } } From 9951011e6c5d469f149ee9b0d08405f0afb6a250 Mon Sep 17 00:00:00 2001 From: miterosan Date: Sun, 8 Sep 2019 16:27:25 +0200 Subject: [PATCH 057/239] Remove not needed androidnativelibrary itemgroup --- osu.Android.props | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Android.props b/osu.Android.props index adc340a734..51bfdca064 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -49,7 +49,6 @@ osu.licenseheader - From eeebd517f3e5cafc0245e60668407d1bb131f5e5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Sep 2019 12:08:59 +0900 Subject: [PATCH 058/239] Use MaxWidth specification --- osu.Game/Overlays/Chat/ChatLine.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index d812e007a0..4c37d626c0 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Chat protected virtual float MessagePadding => default_message_padding; - private const float timestamp_padding = 70; + private const float timestamp_padding = 65; private const float default_horizontal_padding = 15; @@ -92,7 +92,9 @@ namespace osu.Game.Overlays.Chat Truncate = true, EllipsisString = ".. :", Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true), - RelativeSizeAxes = Axes.Both, + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + MaxWidth = default_message_padding - timestamp_padding }; if (hasBackground) From 55afcc1e04ef4d48569cf7247195a32a15d0ec72 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Sep 2019 17:53:51 +0900 Subject: [PATCH 059/239] Add skin component for the legacy cursor trail --- osu.Game.Rulesets.Osu/OsuSkinComponents.cs | 1 + .../Skinning/LegacyCursorTrail.cs | 24 +++++++++++++++++++ .../Skinning/OsuLegacySkinTransformer.cs | 6 +++++ .../UI/Cursor/CursorTrail.cs | 22 +++++++++++++---- .../UI/Cursor/OsuCursorContainer.cs | 20 ++++++++++++---- 5 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs diff --git a/osu.Game.Rulesets.Osu/OsuSkinComponents.cs b/osu.Game.Rulesets.Osu/OsuSkinComponents.cs index 5971f053c2..8dd48eace0 100644 --- a/osu.Game.Rulesets.Osu/OsuSkinComponents.cs +++ b/osu.Game.Rulesets.Osu/OsuSkinComponents.cs @@ -8,6 +8,7 @@ namespace osu.Game.Rulesets.Osu HitCircle, FollowPoint, Cursor, + CursorTrail, SliderScorePoint, ApproachCircle, ReverseArrow, diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs new file mode 100644 index 0000000000..74746faa44 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs @@ -0,0 +1,24 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Osu.UI.Cursor; +using osu.Game.Skinning; + +namespace osu.Game.Rulesets.Osu.Skinning +{ + public class LegacyCursorTrail : CursorTrail + { + public LegacyCursorTrail() + { + Blending = BlendingParameters.Additive; + } + + [BackgroundDependencyLoader] + private void load(ISkinSource skin) + { + Texture = skin.GetTexture("cursortrail"); + } + } +} diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index 5957b81d7e..b5475f50ef 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -78,6 +78,12 @@ namespace osu.Game.Rulesets.Osu.Skinning return null; + case OsuSkinComponents.CursorTrail: + if (source.GetTexture("cursortrail") != null) + return new LegacyCursorTrail(); + + return null; + case OsuSkinComponents.HitCircleText: var font = GetConfig(OsuSkinConfiguration.HitCircleFont)?.Value ?? "default"; var overlap = GetConfig(OsuSkinConfiguration.HitCircleOverlap)?.Value ?? 0; diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index a50c3a2fea..acb7fb8251 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -20,14 +20,28 @@ using osuTK.Graphics.ES30; namespace osu.Game.Rulesets.Osu.UI.Cursor { - internal class CursorTrail : Drawable, IRequireHighFrequencyMousePosition + public class CursorTrail : Drawable, IRequireHighFrequencyMousePosition { private const int max_sprites = 2048; + private Texture texture = Texture.WhitePixel; + + public Texture Texture + { + get => texture; + set + { + if (texture == value) + return; + + texture = value; + Invalidate(Invalidation.DrawNode); + } + } + private readonly TrailPart[] parts = new TrailPart[max_sprites]; private int currentIndex; private IShader shader; - private Texture texture; private double timeOffset; private float time; @@ -47,11 +61,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor } [BackgroundDependencyLoader] - private void load(ShaderManager shaders, TextureStore textures) + private void load(ShaderManager shaders) { shader = shaders.Load(@"CursorTrail", FragmentShaderDescriptor.TEXTURE); - texture = textures.Get(@"Cursor/cursortrail"); - Scale = new Vector2(1 / texture.ScaleAdjust); } protected override void LoadComplete() diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index 893c7875fa..5d68d200ff 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -6,9 +6,12 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Textures; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Osu.Configuration; using osu.Game.Rulesets.UI; +using osu.Game.Skinning; +using osuTK; namespace osu.Game.Rulesets.Osu.UI.Cursor { @@ -22,17 +25,14 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private readonly Bindable showTrail = new Bindable(true); - private readonly CursorTrail cursorTrail; + private readonly Drawable cursorTrail; public OsuCursorContainer() { InternalChild = fadeContainer = new Container { RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - cursorTrail = new CursorTrail { Depth = 1 } - } + Child = cursorTrail = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.CursorTrail), _ => new DefaultCursorTrail()) }; } @@ -98,5 +98,15 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor fadeContainer.FadeTo(0.05f, 450, Easing.OutQuint); ActiveCursor.ScaleTo(0.8f, 450, Easing.OutQuint); } + + private class DefaultCursorTrail : CursorTrail + { + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + Texture = textures.Get(@"Cursor/cursortrail"); + Scale = new Vector2(1 / Texture.ScaleAdjust); + } + } } } From 2d636ce1472a9e19fa15698a012ac1b60b775f59 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 9 Sep 2019 17:54:53 +0900 Subject: [PATCH 060/239] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 896b10133d..f76297c197 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 5f2aad24dc..791d2fe285 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 5027a4ef8c..0560c45edf 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,8 +118,8 @@ - - + + From 195f101799d4ef63af86fdda28df71b6a5d7b52d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Sep 2019 19:00:42 +0900 Subject: [PATCH 061/239] Move complex property below ctor --- .../UI/Cursor/CursorTrail.cs | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index acb7fb8251..8164816f9f 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -24,21 +24,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { private const int max_sprites = 2048; - private Texture texture = Texture.WhitePixel; - - public Texture Texture - { - get => texture; - set - { - if (texture == value) - return; - - texture = value; - Invalidate(Invalidation.DrawNode); - } - } - private readonly TrailPart[] parts = new TrailPart[max_sprites]; private int currentIndex; private IShader shader; @@ -72,6 +57,21 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor resetTime(); } + private Texture texture = Texture.WhitePixel; + + public Texture Texture + { + get => texture; + set + { + if (texture == value) + return; + + texture = value; + Invalidate(Invalidation.DrawNode); + } + } + public override bool IsPresent => true; protected override void Update() From 1d225ba81e627128d14e16eb2aef9c34304d6f3d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Sep 2019 19:02:10 +0900 Subject: [PATCH 062/239] Add FadeDuration to control cursor trail fade --- osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 8164816f9f..91bc3278bf 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -72,6 +72,11 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor } } + /// + /// The amount of time to fade the cursor trail pieces. + /// + protected virtual double FadeDuration => 300; + public override bool IsPresent => true; protected override void Update() @@ -82,7 +87,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor const int fade_clock_reset_threshold = 1000000; - time = (float)(Time.Current - timeOffset) / 300f; + time = (float)((Time.Current - timeOffset) / FadeDuration); if (time > fade_clock_reset_threshold) resetTime(); } From 3b1b7910bbf50447b82b8d5ba7bce555255ad0a1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Sep 2019 19:22:27 +0900 Subject: [PATCH 063/239] Add toggle for cursor trail interpolation --- .../UI/Cursor/CursorTrail.cs | 45 +++++++++++++------ 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 91bc3278bf..0998b5d604 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -106,6 +106,11 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private Vector2 size => texture.Size * Scale; + /// + /// Whether to interpolate mouse movements and add trail pieces at intermediate points. + /// + protected virtual bool InterpolateMovements => true; + private Vector2? lastPosition; private readonly InputResampler resampler = new InputResampler(); @@ -126,29 +131,41 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor { Trace.Assert(lastPosition.HasValue); - // ReSharper disable once PossibleInvalidOperationException - Vector2 pos1 = lastPosition.Value; - Vector2 diff = pos2 - pos1; - float distance = diff.Length; - Vector2 direction = diff / distance; - - float interval = size.X / 2 * 0.9f; - - for (float d = interval; d < distance; d += interval) + if (InterpolateMovements) { - lastPosition = pos1 + direction * d; + // ReSharper disable once PossibleInvalidOperationException + Vector2 pos1 = lastPosition.Value; + Vector2 diff = pos2 - pos1; + float distance = diff.Length; + Vector2 direction = diff / distance; - parts[currentIndex].Position = lastPosition.Value; - parts[currentIndex].Time = time; - ++parts[currentIndex].InvalidationID; + float interval = size.X / 2 * 0.9f; - currentIndex = (currentIndex + 1) % max_sprites; + for (float d = interval; d < distance; d += interval) + { + lastPosition = pos1 + direction * d; + addPart(lastPosition.Value); + } + } + else + { + lastPosition = pos2; + addPart(lastPosition.Value); } } return base.OnMouseMove(e); } + private void addPart(Vector2 screenSpacePosition) + { + parts[currentIndex].Position = screenSpacePosition; + parts[currentIndex].Time = time; + ++parts[currentIndex].InvalidationID; + + currentIndex = (currentIndex + 1) % max_sprites; + } + protected override DrawNode CreateDrawNode() => new TrailDrawNode(this); private struct TrailPart From 292d50aacfed96eb19e83b6775515ef74b933c74 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Sep 2019 19:22:44 +0900 Subject: [PATCH 064/239] Don't confine the cursor trail --- osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs index 5d68d200ff..a944ff88c6 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/OsuCursorContainer.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor InternalChild = fadeContainer = new Container { RelativeSizeAxes = Axes.Both, - Child = cursorTrail = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.CursorTrail), _ => new DefaultCursorTrail()) + Child = cursorTrail = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.CursorTrail), _ => new DefaultCursorTrail(), confineMode: ConfineMode.NoScaling) }; } From a200485fbd0db1b2a4b429bb15620c8174cc4a9f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Sep 2019 19:23:02 +0900 Subject: [PATCH 065/239] Implement disjoint (old style) cursor trails --- .../Skinning/LegacyCursorTrail.cs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs index 74746faa44..d2018ea720 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs @@ -3,6 +3,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Input.Events; using osu.Game.Rulesets.Osu.UI.Cursor; using osu.Game.Skinning; @@ -10,6 +11,11 @@ namespace osu.Game.Rulesets.Osu.Skinning { public class LegacyCursorTrail : CursorTrail { + private const double disjoint_trail_time_separation = 1000 / 60.0; + + private bool disjointTrail; + private double lastTrailTime; + public LegacyCursorTrail() { Blending = BlendingParameters.Additive; @@ -19,6 +25,31 @@ namespace osu.Game.Rulesets.Osu.Skinning private void load(ISkinSource skin) { Texture = skin.GetTexture("cursortrail"); + disjointTrail = skin.GetTexture("cursormiddle") == null; + + if (disjointTrail && Texture != null) + { + // stable "magic ratio". see OsuPlayfieldAdjustmentContainer for full explanation. + Texture.ScaleAdjust *= 1.6f; + } + } + + protected override double FadeDuration => disjointTrail ? 150 : 500; + + protected override bool InterpolateMovements => !disjointTrail; + + protected override bool OnMouseMove(MouseMoveEvent e) + { + if (!disjointTrail) + return base.OnMouseMove(e); + + if (Time.Current - lastTrailTime >= disjoint_trail_time_separation) + { + lastTrailTime = Time.Current; + return base.OnMouseMove(e); + } + + return false; } } } From e3b972187e7bfa966b0efc1d29adabcdb9875088 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 9 Sep 2019 19:30:31 +0900 Subject: [PATCH 066/239] Fix incorrect cursor trail size + scale --- .../UI/Cursor/CursorTrail.cs | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 0998b5d604..7975982aec 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -5,6 +5,7 @@ using System; using System.Diagnostics; using System.Runtime.InteropServices; using osu.Framework.Allocation; +using osu.Framework.Caching; using osu.Framework.Graphics; using osu.Framework.Graphics.Batches; using osu.Framework.Graphics.OpenGL.Vertices; @@ -72,6 +73,20 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor } } + private readonly Cached partSizeCache = new Cached(); + + private Vector2 partSize => partSizeCache.IsValid + ? partSizeCache.Value + : (partSizeCache.Value = new Vector2(Texture.DisplayWidth, Texture.DisplayHeight) * DrawInfo.Matrix.ExtractScale().Xy); + + public override bool Invalidate(Invalidation invalidation = Invalidation.All, Drawable source = null, bool shallPropagate = true) + { + if ((invalidation & (Invalidation.DrawInfo | Invalidation.RequiredParentSizeToFit | Invalidation.Presence)) > 0) + partSizeCache.Invalidate(); + + return base.Invalidate(invalidation, source, shallPropagate); + } + /// /// The amount of time to fade the cursor trail pieces. /// @@ -104,8 +119,6 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor timeOffset = Time.Current; } - private Vector2 size => texture.Size * Scale; - /// /// Whether to interpolate mouse movements and add trail pieces at intermediate points. /// @@ -139,7 +152,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor float distance = diff.Length; Vector2 direction = diff / distance; - float interval = size.X / 2 * 0.9f; + float interval = partSize.X / 2 * 0.9f; for (float d = interval; d < distance; d += interval) { @@ -202,7 +215,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor shader = Source.shader; texture = Source.texture; - size = Source.size; + size = Source.partSize; time = Source.time; for (int i = 0; i < Source.parts.Length; ++i) From 0790e9e377582117b70688865efa2abcfba2859b Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2019 11:35:26 +0000 Subject: [PATCH 067/239] Bump ppy.osu.Framework.iOS from 2019.905.0 to 2019.909.0 Bumps [ppy.osu.Framework.iOS](https://github.com/ppy/osu-framework) from 2019.905.0 to 2019.909.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.905.0...2019.909.0) Signed-off-by: dependabot-preview[bot] --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index 5027a4ef8c..5645862bf7 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -119,7 +119,7 @@ - + From 7a7c3d21a1a158691daaf39005268e5acdd3b26d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2019 11:36:58 +0000 Subject: [PATCH 068/239] Bump ppy.osu.Framework from 2019.905.0 to 2019.909.0 Bumps [ppy.osu.Framework](https://github.com/ppy/osu-framework) from 2019.905.0 to 2019.909.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.905.0...2019.909.0) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 5f2aad24dc..791d2fe285 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 5027a4ef8c..77756dfd87 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,7 +118,7 @@ - + From 3b4750ab9e54033fed4a358041e9b15124feb643 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2019 11:37:09 +0000 Subject: [PATCH 069/239] Bump ppy.osu.Framework.Android from 2019.905.0 to 2019.909.0 Bumps [ppy.osu.Framework.Android](https://github.com/ppy/osu-framework) from 2019.905.0 to 2019.909.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.905.0...2019.909.0) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Android.props b/osu.Android.props index 896b10133d..f76297c197 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@ - + From 22fabef344c41920820a662bfc37009675c12207 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 9 Sep 2019 19:52:31 +0300 Subject: [PATCH 070/239] Use TestWorkingBeatmap in BeatmapDetailsArea tests --- .../SongSelect/TestSceneBeatmapDetailArea.cs | 80 +++++++++---------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs index 7b97a27732..ed9e01a67e 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs @@ -9,6 +9,7 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Screens.Select; +using osu.Game.Tests.Beatmaps; using osuTK; namespace osu.Game.Tests.Visual.SongSelect @@ -30,45 +31,44 @@ namespace osu.Game.Tests.Visual.SongSelect Size = new Vector2(550f, 450f), }); - AddStep("all metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) + AddStep("all metrics", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap + { + BeatmapInfo = { - BeatmapSetInfo = + BeatmapSet = new BeatmapSetInfo { Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } }, - BeatmapInfo = + Version = "All Metrics", + Metadata = new BeatmapMetadata { - Version = "All Metrics", - Metadata = new BeatmapMetadata - { - Source = "osu!lazer", - Tags = "this beatmap has all the metrics", - }, - BaseDifficulty = new BeatmapDifficulty - { - CircleSize = 7, - DrainRate = 1, - OverallDifficulty = 5.7f, - ApproachRate = 3.5f, - }, - StarDifficulty = 5.3f, - Metrics = new BeatmapMetrics - { - Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), - Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), - }, - } + Source = "osu!lazer", + Tags = "this beatmap has all the metrics", + }, + BaseDifficulty = new BeatmapDifficulty + { + CircleSize = 7, + DrainRate = 1, + OverallDifficulty = 5.7f, + ApproachRate = 3.5f, + }, + StarDifficulty = 5.3f, + Metrics = new BeatmapMetrics + { + Fails = Enumerable.Range(1, 100).Select(i => i % 12 - 6).ToArray(), + Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), + }, } - ); + })); - AddStep("all except source", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) + AddStep("all except source", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap { - BeatmapSetInfo = - { - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } - }, BeatmapInfo = { + BeatmapSet = new BeatmapSetInfo + { + Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } + }, Version = "All Metrics", Metadata = new BeatmapMetadata { @@ -88,16 +88,16 @@ namespace osu.Game.Tests.Visual.SongSelect Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, } - }); + })); - AddStep("ratings", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) + AddStep("ratings", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap { - BeatmapSetInfo = - { - Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } - }, BeatmapInfo = { + BeatmapSet = new BeatmapSetInfo + { + Metrics = new BeatmapSetMetrics { Ratings = Enumerable.Range(0, 11).ToArray() } + }, Version = "Only Ratings", Metadata = new BeatmapMetadata { @@ -113,9 +113,9 @@ namespace osu.Game.Tests.Visual.SongSelect }, StarDifficulty = 4.8f } - }); + })); - AddStep("fails+retries", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) + AddStep("fails+retries", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap { BeatmapInfo = { @@ -139,9 +139,9 @@ namespace osu.Game.Tests.Visual.SongSelect Retries = Enumerable.Range(-2, 100).Select(i => i % 12 - 6).ToArray(), }, } - }); + })); - AddStep("null metrics", () => detailsArea.Beatmap = new DummyWorkingBeatmap(null, null) + AddStep("null metrics", () => detailsArea.Beatmap = new TestWorkingBeatmap(new Beatmap { BeatmapInfo = { @@ -160,7 +160,7 @@ namespace osu.Game.Tests.Visual.SongSelect }, StarDifficulty = 1.97f, } - }); + })); AddStep("null beatmap", () => detailsArea.Beatmap = null); } From b77550625c86360b5c98618eb61dec642c4824dd Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Mon, 9 Sep 2019 20:04:04 +0300 Subject: [PATCH 071/239] Check if DummyWorkingBeatmap is selected instead --- osu.Game/Screens/Select/BeatmapDetailArea.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index bf8fc8cf07..5348de68d6 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -28,7 +28,7 @@ namespace osu.Game.Screens.Select { beatmap = value; Details.Beatmap = beatmap?.BeatmapInfo; - Leaderboard.Beatmap = beatmap is NoBeatmapsAvailableWorkingBeatmap ? null : beatmap?.BeatmapInfo; + Leaderboard.Beatmap = beatmap is DummyWorkingBeatmap ? null : beatmap?.BeatmapInfo; } } From 65869c7ebba728b9727d53fcf39caf11c68c9d67 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 10 Sep 2019 04:04:37 +0300 Subject: [PATCH 072/239] Refactor LeaderboardScopeSelector for more extensibility --- .../UserInterface/GradientLineTabControl.cs | 129 ++++++++++++++++++ .../BeatmapSet/LeaderboardScopeSelector.cs | 93 +------------ 2 files changed, 131 insertions(+), 91 deletions(-) create mode 100644 osu.Game/Graphics/UserInterface/GradientLineTabControl.cs diff --git a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs new file mode 100644 index 0000000000..f4c43b0222 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs @@ -0,0 +1,129 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osuTK; +using osu.Framework.Graphics.Shapes; +using osuTK.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Input.Events; +using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; + +namespace osu.Game.Graphics.UserInterface +{ + public class GradientLineTabControl : PageTabControl + { + protected override Dropdown CreateDropdown() => null; + + protected override TabItem CreateTabItem(TModel value) => new ScopeSelectorTabItem(value); + + protected Color4 LineColour + { + get => line.MainColour.Value; + set => line.MainColour.Value = value; + } + + private readonly GradientLine line; + + public GradientLineTabControl() + { + RelativeSizeAxes = Axes.X; + + AddInternal(line = new GradientLine + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + }); + } + + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(20, 0), + }; + + private class ScopeSelectorTabItem : PageTabItem + { + public ScopeSelectorTabItem(TModel value) + : base(value) + { + Text.Font = OsuFont.GetFont(size: 16); + } + + protected override bool OnHover(HoverEvent e) + { + Text.FadeColour(AccentColour); + + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + + Text.FadeColour(Color4.White); + } + } + + private class GradientLine : GridContainer + { + public readonly Bindable MainColour = new Bindable(); + + private readonly Box left; + private readonly Box middle; + private readonly Box right; + + public GradientLine() + { + RelativeSizeAxes = Axes.X; + Size = new Vector2(0.8f, 1.5f); + + ColumnDimensions = new[] + { + new Dimension(), + new Dimension(mode: GridSizeMode.Relative, size: 0.4f), + new Dimension(), + }; + + Content = new[] + { + new Drawable[] + { + left = new Box + { + RelativeSizeAxes = Axes.Both, + }, + middle = new Box + { + RelativeSizeAxes = Axes.Both, + }, + right = new Box + { + RelativeSizeAxes = Axes.Both, + }, + } + }; + } + + protected override void LoadComplete() + { + MainColour.BindValueChanged(onColourChanged, true); + base.LoadComplete(); + } + + private void onColourChanged(ValueChangedEvent colour) + { + left.Colour = ColourInfo.GradientHorizontal(colour.NewValue.Opacity(0), colour.NewValue); + middle.Colour = colour.NewValue; + right.Colour = ColourInfo.GradientHorizontal(colour.NewValue, colour.NewValue.Opacity(0)); + } + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs index dcd58db427..bdcd5c21b9 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs @@ -1,119 +1,30 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Graphics.UserInterface; using osu.Game.Screens.Select.Leaderboards; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osuTK; using osu.Game.Graphics.UserInterface; -using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Framework.Allocation; using osuTK.Graphics; -using osu.Framework.Graphics.Colour; -using osu.Framework.Input.Events; namespace osu.Game.Overlays.BeatmapSet { - public class LeaderboardScopeSelector : PageTabControl + public class LeaderboardScopeSelector : GradientLineTabControl { protected override bool AddEnumEntriesAutomatically => false; - protected override Dropdown CreateDropdown() => null; - - protected override TabItem CreateTabItem(BeatmapLeaderboardScope value) => new ScopeSelectorTabItem(value); - public LeaderboardScopeSelector() { - RelativeSizeAxes = Axes.X; - AddItem(BeatmapLeaderboardScope.Global); AddItem(BeatmapLeaderboardScope.Country); AddItem(BeatmapLeaderboardScope.Friend); - - AddInternal(new GradientLine - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - }); } [BackgroundDependencyLoader] private void load(OsuColour colours) { AccentColour = colours.Blue; - } - - protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(20, 0), - }; - - private class ScopeSelectorTabItem : PageTabItem - { - public ScopeSelectorTabItem(BeatmapLeaderboardScope value) - : base(value) - { - Text.Font = OsuFont.GetFont(size: 16); - } - - protected override bool OnHover(HoverEvent e) - { - Text.FadeColour(AccentColour); - - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - base.OnHoverLost(e); - - Text.FadeColour(Color4.White); - } - } - - private class GradientLine : GridContainer - { - public GradientLine() - { - RelativeSizeAxes = Axes.X; - Size = new Vector2(0.8f, 1.5f); - - ColumnDimensions = new[] - { - new Dimension(), - new Dimension(mode: GridSizeMode.Relative, size: 0.4f), - new Dimension(), - }; - - Content = new[] - { - new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(Color4.Transparent, Color4.Gray), - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Gray, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(Color4.Gray, Color4.Transparent), - }, - } - }; - } + LineColour = Color4.Gray; } } } From 03bd7ca8e72a88d2551887b742281374bec2ee14 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 10 Sep 2019 04:20:32 +0300 Subject: [PATCH 073/239] Implement RankingsScopeSelector --- .../Online/TestSceneRankingsScopeSelector.cs | 53 +++++++++++++++++++ .../UserInterface/GradientLineTabControl.cs | 26 --------- .../BeatmapSet/LeaderboardScopeSelector.cs | 28 ++++++++++ osu.Game/Overlays/RankingsScopeSelector.cs | 26 +++++++++ 4 files changed, 107 insertions(+), 26 deletions(-) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs create mode 100644 osu.Game/Overlays/RankingsScopeSelector.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs new file mode 100644 index 0000000000..1488addb09 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs @@ -0,0 +1,53 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Framework.Bindables; +using osu.Game.Overlays; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Allocation; +using osu.Game.Graphics; +using osu.Framework.Extensions.Color4Extensions; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsScopeSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(RankingsScopeSelector), + }; + + private readonly Box background; + + public TestSceneRankingsScopeSelector() + { + Bindable scope = new Bindable(); + + Add(background = new Box + { + RelativeSizeAxes = Axes.Both + }); + + Add(new RankingsScopeSelector + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Current = { BindTarget = scope } + }); + + AddStep(@"Select country", () => scope.Value = RankingsScope.Country); + AddStep(@"Select performance", () => scope.Value = RankingsScope.Performance); + AddStep(@"Select score", () => scope.Value = RankingsScope.Score); + AddStep(@"Select spotlights", () => scope.Value = RankingsScope.Spotlights); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.Yellow.Opacity(50); + } + } +} diff --git a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs index f4c43b0222..7cd8d2c5bd 100644 --- a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs +++ b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs @@ -8,7 +8,6 @@ using osuTK; using osu.Framework.Graphics.Shapes; using osuTK.Graphics; using osu.Framework.Graphics.Colour; -using osu.Framework.Input.Events; using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; @@ -18,8 +17,6 @@ namespace osu.Game.Graphics.UserInterface { protected override Dropdown CreateDropdown() => null; - protected override TabItem CreateTabItem(TModel value) => new ScopeSelectorTabItem(value); - protected Color4 LineColour { get => line.MainColour.Value; @@ -49,29 +46,6 @@ namespace osu.Game.Graphics.UserInterface Spacing = new Vector2(20, 0), }; - private class ScopeSelectorTabItem : PageTabItem - { - public ScopeSelectorTabItem(TModel value) - : base(value) - { - Text.Font = OsuFont.GetFont(size: 16); - } - - protected override bool OnHover(HoverEvent e) - { - Text.FadeColour(AccentColour); - - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - base.OnHoverLost(e); - - Text.FadeColour(Color4.White); - } - } - private class GradientLine : GridContainer { public readonly Bindable MainColour = new Bindable(); diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs index bdcd5c21b9..e2a725ec46 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs @@ -6,6 +6,9 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Graphics; using osu.Framework.Allocation; using osuTK.Graphics; +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; +using osu.Framework.Graphics; namespace osu.Game.Overlays.BeatmapSet { @@ -13,6 +16,8 @@ namespace osu.Game.Overlays.BeatmapSet { protected override bool AddEnumEntriesAutomatically => false; + protected override TabItem CreateTabItem(BeatmapLeaderboardScope value) => new ScopeSelectorTabItem(value); + public LeaderboardScopeSelector() { AddItem(BeatmapLeaderboardScope.Global); @@ -26,5 +31,28 @@ namespace osu.Game.Overlays.BeatmapSet AccentColour = colours.Blue; LineColour = Color4.Gray; } + + private class ScopeSelectorTabItem : PageTabItem + { + public ScopeSelectorTabItem(BeatmapLeaderboardScope value) + : base(value) + { + Text.Font = OsuFont.GetFont(size: 16); + } + + protected override bool OnHover(HoverEvent e) + { + Text.FadeColour(AccentColour); + + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + + Text.FadeColour(Color4.White); + } + } } } diff --git a/osu.Game/Overlays/RankingsScopeSelector.cs b/osu.Game/Overlays/RankingsScopeSelector.cs new file mode 100644 index 0000000000..5935876ec9 --- /dev/null +++ b/osu.Game/Overlays/RankingsScopeSelector.cs @@ -0,0 +1,26 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Graphics.UserInterface; +using osu.Framework.Allocation; +using osuTK.Graphics; + +namespace osu.Game.Overlays +{ + public class RankingsScopeSelector : GradientLineTabControl + { + [BackgroundDependencyLoader] + private void load() + { + AccentColour = LineColour = Color4.Black; + } + } + + public enum RankingsScope + { + Performance, + Spotlights, + Score, + Country + } +} From f505a3ff1d48efea15967e3c322f6203fb8bf1cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Sep 2019 11:44:11 +0900 Subject: [PATCH 074/239] Mark AutoGeneration tests as headless --- osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs index 20ac5eaa39..f260357df5 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs @@ -3,6 +3,7 @@ using System.Linq; using NUnit.Framework; +using osu.Framework.Testing; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Replays; @@ -12,6 +13,7 @@ using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Mania.Tests { [TestFixture] + [HeadlessTest] public class TestSceneAutoGeneration : OsuTestScene { [Test] From af3bb5a2cdf7084cc14a988a0610e636438ad4fc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Sep 2019 13:29:50 +0900 Subject: [PATCH 075/239] Centralise and share bar line generation code between rulesets --- .../TestSceneStage.cs | 4 +- osu.Game.Rulesets.Mania/Objects/BarLine.cs | 21 ------- .../Objects/Drawables/DrawableBarLine.cs | 9 ++- .../UI/DrawableManiaRuleset.cs | 33 +---------- osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs | 1 + osu.Game.Rulesets.Mania/UI/ManiaStage.cs | 1 + osu.Game.Rulesets.Taiko/Objects/BarLine.cs | 9 --- .../Objects/Drawables/DrawableBarLine.cs | 3 +- .../Objects/Drawables/DrawableBarLineMajor.cs | 1 + .../UI/DrawableTaikoRuleset.cs | 47 +-------------- osu.Game/Rulesets/Objects/BarLine.cs | 16 +++++ osu.Game/Rulesets/Objects/BarLineGenerator.cs | 58 +++++++++++++++++++ 12 files changed, 89 insertions(+), 114 deletions(-) delete mode 100644 osu.Game.Rulesets.Mania/Objects/BarLine.cs delete mode 100644 osu.Game.Rulesets.Taiko/Objects/BarLine.cs create mode 100644 osu.Game/Rulesets/Objects/BarLine.cs create mode 100644 osu.Game/Rulesets/Objects/BarLineGenerator.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs index 395e6daf0a..e7fd601abe 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneStage.cs @@ -15,6 +15,7 @@ using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.UI; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Tests.Visual; using osuTK; @@ -114,8 +115,7 @@ namespace osu.Game.Rulesets.Mania.Tests var obj = new BarLine { StartTime = Time.Current + 2000, - ControlPoint = new TimingControlPoint(), - BeatIndex = major ? 0 : 1 + Major = major, }; obj.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); diff --git a/osu.Game.Rulesets.Mania/Objects/BarLine.cs b/osu.Game.Rulesets.Mania/Objects/BarLine.cs deleted file mode 100644 index 4c644a8f09..0000000000 --- a/osu.Game.Rulesets.Mania/Objects/BarLine.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Game.Beatmaps.ControlPoints; - -namespace osu.Game.Rulesets.Mania.Objects -{ - public class BarLine : ManiaHitObject - { - /// - /// The control point which this bar line is part of. - /// - public TimingControlPoint ControlPoint; - - /// - /// The index of the beat which this bar line represents within the control point. - /// This is a "major" bar line if % == 0. - /// - public int BeatIndex; - } -} diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs index e9c352c97e..862af8d15b 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs @@ -4,6 +4,7 @@ using osuTK; using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osuTK.Graphics; @@ -13,7 +14,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// Visualises a . Although this derives DrawableManiaHitObject, /// this does not handle input/sound like a normal hit object. /// - public class DrawableBarLine : DrawableManiaHitObject + public class DrawableBarLine : DrawableHitObject { /// /// Height of major bar line triangles. @@ -40,9 +41,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Colour = new Color4(255, 204, 33, 255), }); - bool isMajor = barLine.BeatIndex % (int)barLine.ControlPoint.TimeSignature == 0; - - if (isMajor) + if (barLine.Major) { AddInternal(new EquilateralTriangle { @@ -65,7 +64,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables }); } - if (!isMajor && barLine.BeatIndex % 2 == 1) + if (!barLine.Major) Alpha = 0.2f; } diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs index f26526fe70..29863fba2e 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaRuleset.cs @@ -2,14 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; -using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Input; -using osu.Framework.MathUtils; using osu.Game.Beatmaps; -using osu.Game.Beatmaps.ControlPoints; using osu.Game.Input.Handlers; using osu.Game.Replays; using osu.Game.Rulesets.Mania.Beatmaps; @@ -19,8 +16,8 @@ using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; @@ -45,33 +42,7 @@ namespace osu.Game.Rulesets.Mania.UI public DrawableManiaRuleset(Ruleset ruleset, IWorkingBeatmap beatmap, IReadOnlyList mods) : base(ruleset, beatmap, mods) { - // Generate the bar lines - double lastObjectTime = (Objects.LastOrDefault() as IHasEndTime)?.EndTime ?? Objects.LastOrDefault()?.StartTime ?? double.MaxValue; - - var timingPoints = Beatmap.ControlPointInfo.TimingPoints; - var barLines = new List(); - - for (int i = 0; i < timingPoints.Count; i++) - { - TimingControlPoint point = timingPoints[i]; - - // Stop on the beat before the next timing point, or if there is no next timing point stop slightly past the last object - double endTime = i < timingPoints.Count - 1 ? timingPoints[i + 1].Time - point.BeatLength : lastObjectTime + point.BeatLength * (int)point.TimeSignature; - - int index = 0; - - for (double t = timingPoints[i].Time; Precision.DefinitelyBigger(endTime, t); t += point.BeatLength, index++) - { - barLines.Add(new BarLine - { - StartTime = t, - ControlPoint = point, - BeatIndex = index - }); - } - } - - BarLines = barLines; + BarLines = new BarLineGenerator(Beatmap).BarLines; } [BackgroundDependencyLoader] diff --git a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs index 5ab07416a6..12faa499ad 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaPlayfield.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI.Scrolling; using osuTK; diff --git a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs index a28de7ea58..98a4b7d0b6 100644 --- a/osu.Game.Rulesets.Mania/UI/ManiaStage.cs +++ b/osu.Game.Rulesets.Mania/UI/ManiaStage.cs @@ -12,6 +12,7 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; diff --git a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs b/osu.Game.Rulesets.Taiko/Objects/BarLine.cs deleted file mode 100644 index a07012fd71..0000000000 --- a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -namespace osu.Game.Rulesets.Taiko.Objects -{ - public class BarLine : TaikoHitObject - { - } -} diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs index bf89f7e15b..1a5a797f28 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Objects; using osuTK; using osu.Game.Rulesets.Objects.Drawables; @@ -11,7 +12,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables /// /// A line that scrolls alongside hit objects in the playfield and visualises control points. /// - public class DrawableBarLine : DrawableHitObject + public class DrawableBarLine : DrawableHitObject { /// /// The width of the line tracker. diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs index 4d3a1a3f8a..f5b75a781b 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLineMajor.cs @@ -5,6 +5,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osuTK; using osu.Framework.Graphics.Shapes; +using osu.Game.Rulesets.Objects; namespace osu.Game.Rulesets.Taiko.Objects.Drawables { diff --git a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs index b03bea578e..5caa9e4626 100644 --- a/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/UI/DrawableTaikoRuleset.cs @@ -5,19 +5,18 @@ using System.Collections.Generic; using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects.Drawables; using osu.Game.Rulesets.Taiko.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.Taiko.Replays; -using System.Linq; using osu.Framework.Input; using osu.Game.Configuration; using osu.Game.Input.Handlers; using osu.Game.Replays; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.UI.Scrolling; namespace osu.Game.Rulesets.Taiko.UI @@ -38,49 +37,7 @@ namespace osu.Game.Rulesets.Taiko.UI [BackgroundDependencyLoader] private void load() { - loadBarLines(); - } - - private void loadBarLines() - { - TaikoHitObject lastObject = Beatmap.HitObjects[Beatmap.HitObjects.Count - 1]; - double lastHitTime = 1 + ((lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime); - - var timingPoints = Beatmap.ControlPointInfo.TimingPoints.ToList(); - - if (timingPoints.Count == 0) - return; - - int currentIndex = 0; - int currentBeat = 0; - double time = timingPoints[currentIndex].Time; - - while (time <= lastHitTime) - { - int nextIndex = currentIndex + 1; - - if (nextIndex < timingPoints.Count && time > timingPoints[nextIndex].Time) - { - currentIndex = nextIndex; - time = timingPoints[currentIndex].Time; - currentBeat = 0; - } - - var currentPoint = timingPoints[currentIndex]; - - var barLine = new BarLine - { - StartTime = time, - }; - - barLine.ApplyDefaults(Beatmap.ControlPointInfo, Beatmap.BeatmapInfo.BaseDifficulty); - - bool isMajor = currentBeat % (int)currentPoint.TimeSignature == 0; - Playfield.Add(isMajor ? new DrawableBarLineMajor(barLine) : new DrawableBarLine(barLine)); - - time += currentPoint.BeatLength * (int)currentPoint.TimeSignature; - currentBeat++; - } + new BarLineGenerator(Beatmap).BarLines.ForEach(bar => Playfield.Add(bar.Major ? new DrawableBarLineMajor(bar) : new DrawableBarLine(bar))); } public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(this); diff --git a/osu.Game/Rulesets/Objects/BarLine.cs b/osu.Game/Rulesets/Objects/BarLine.cs new file mode 100644 index 0000000000..a5c716e127 --- /dev/null +++ b/osu.Game/Rulesets/Objects/BarLine.cs @@ -0,0 +1,16 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Rulesets.Objects +{ + /// + /// A hit object representing the end of a bar. + /// + public class BarLine : HitObject + { + /// + /// Whether this barline is a prominent beat (based on time signature of beatmap). + /// + public bool Major; + } +} diff --git a/osu.Game/Rulesets/Objects/BarLineGenerator.cs b/osu.Game/Rulesets/Objects/BarLineGenerator.cs new file mode 100644 index 0000000000..ce571d7b17 --- /dev/null +++ b/osu.Game/Rulesets/Objects/BarLineGenerator.cs @@ -0,0 +1,58 @@ +// Copyright (c) ppy Pty Ltd . 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 osu.Framework.MathUtils; +using osu.Game.Beatmaps; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Rulesets.Objects.Types; + +namespace osu.Game.Rulesets.Objects +{ + public class BarLineGenerator + { + /// + /// The generated bar lines. + /// + public readonly List BarLines = new List(); + + /// + /// Constructs and generates bar lines for provided beatmap. + /// + /// The beatmap to generate bar lines for. + public BarLineGenerator(IBeatmap beatmap) + { + if (beatmap.HitObjects.Count == 0) + return; + + HitObject lastObject = beatmap.HitObjects.Last(); + double lastHitTime = 1 + ((lastObject as IHasEndTime)?.EndTime ?? lastObject.StartTime); + + var timingPoints = beatmap.ControlPointInfo.TimingPoints; + + if (timingPoints.Count == 0) + return; + + for (int i = 0; i < timingPoints.Count; i++) + { + TimingControlPoint currentTimingPoint = timingPoints[i]; + int currentBeat = 0; + + // Stop on the beat before the next timing point, or if there is no next timing point stop slightly past the last object + double endTime = i < timingPoints.Count - 1 ? timingPoints[i + 1].Time - currentTimingPoint.BeatLength : lastHitTime + currentTimingPoint.BeatLength * (int)currentTimingPoint.TimeSignature; + + double barLength = currentTimingPoint.BeatLength * (int)currentTimingPoint.TimeSignature; + + for (double t = currentTimingPoint.Time; Precision.DefinitelyBigger(endTime, t); t += barLength, currentBeat++) + { + BarLines.Add(new BarLine + { + StartTime = t, + Major = currentBeat % (int)currentTimingPoint.TimeSignature == 0 + }); + } + } + } + } +} From ef90914f581311f17bc689dea4cf83b7f96e01de Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Sep 2019 15:27:40 +0900 Subject: [PATCH 076/239] Fix mania notes test scene not visually displaying --- osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs index 031abb08e2..8dae5e6d84 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -11,6 +11,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Timing; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; @@ -40,6 +41,7 @@ namespace osu.Game.Rulesets.Mania.Tests { Child = new FillFlowContainer { + Clock = new FramedClock(new ManualClock()), Anchor = Anchor.Centre, Origin = Anchor.Centre, AutoSizeAxes = Axes.Both, @@ -62,7 +64,7 @@ namespace osu.Game.Rulesets.Mania.Tests private Drawable createNoteDisplay(ScrollingDirection direction, int identifier, out DrawableNote hitObject) { - var note = new Note { StartTime = 999999999 }; + var note = new Note { StartTime = 0 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); return new ScrollingTestContainer(direction) @@ -77,7 +79,7 @@ namespace osu.Game.Rulesets.Mania.Tests private Drawable createHoldNoteDisplay(ScrollingDirection direction, int identifier, out DrawableHoldNote hitObject) { - var note = new HoldNote { StartTime = 999999999, Duration = 5000 }; + var note = new HoldNote { StartTime = 0, Duration = 5000 }; note.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); return new ScrollingTestContainer(direction) @@ -133,7 +135,7 @@ namespace osu.Game.Rulesets.Mania.Tests Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.Both, Width = 1.25f, - Colour = Color4.Black.Opacity(0.5f) + Colour = Color4.Green.Opacity(0.5f) }, content = new Container { RelativeSizeAxes = Axes.Both } } From 01fd08cba92f1e7c96878147259b1c2b6411abab Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 10 Sep 2019 17:11:16 +0900 Subject: [PATCH 077/239] Fix broken positioning of effected usernames --- osu.Game/Overlays/Chat/ChatLine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index 4c37d626c0..d125da8e92 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -148,8 +148,8 @@ namespace osu.Game.Overlays.Chat }, new MessageSender(message.Sender) { + AutoSizeAxes = Axes.Both, Padding = new MarginPadding { Left = timestamp_padding }, - RelativeSizeAxes = Axes.Both, Origin = Anchor.TopRight, Anchor = Anchor.TopRight, Child = effectedUsername, From 717a287d692e207e08231eec334f29076ad82b0c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 10 Sep 2019 17:11:26 +0900 Subject: [PATCH 078/239] Use real ellipsis character --- osu.Game/Overlays/Chat/ChatLine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Chat/ChatLine.cs b/osu.Game/Overlays/Chat/ChatLine.cs index d125da8e92..7596231a3d 100644 --- a/osu.Game/Overlays/Chat/ChatLine.cs +++ b/osu.Game/Overlays/Chat/ChatLine.cs @@ -90,7 +90,7 @@ namespace osu.Game.Overlays.Chat Shadow = false, Colour = hasBackground ? customUsernameColour : username_colours[message.Sender.Id % username_colours.Length], Truncate = true, - EllipsisString = ".. :", + EllipsisString = "… :", Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true), Anchor = Anchor.TopRight, Origin = Anchor.TopRight, From 36d3736e1dde496c2a1446f31a176dcf7d5a90f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 10 Sep 2019 18:06:24 +0900 Subject: [PATCH 079/239] Fix hitcircle font prefix not being read for legacy skins --- osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs | 2 +- osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index 5957b81d7e..6b6a08ed21 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -79,7 +79,7 @@ namespace osu.Game.Rulesets.Osu.Skinning return null; case OsuSkinComponents.HitCircleText: - var font = GetConfig(OsuSkinConfiguration.HitCircleFont)?.Value ?? "default"; + var font = GetConfig(OsuSkinConfiguration.HitCirclePrefix)?.Value ?? "default"; var overlap = GetConfig(OsuSkinConfiguration.HitCircleOverlap)?.Value ?? 0; return !hasFont(font) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs b/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs index a6b87150ae..e7b686d27d 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuSkinConfiguration.cs @@ -5,7 +5,7 @@ namespace osu.Game.Rulesets.Osu.Skinning { public enum OsuSkinConfiguration { - HitCircleFont, + HitCirclePrefix, HitCircleOverlap, SliderBorderSize, SliderPathRadius, From 1969c5b89bccc3788a295d14ecc8e83412b58da7 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 10 Sep 2019 16:36:05 +0300 Subject: [PATCH 080/239] Apply suggetsted changes --- .../Online/TestSceneRankingsScopeSelector.cs | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs index 1488addb09..93a00e1d06 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs @@ -9,7 +9,6 @@ using osu.Game.Overlays; using osu.Framework.Graphics.Shapes; using osu.Framework.Allocation; using osu.Game.Graphics; -using osu.Framework.Extensions.Color4Extensions; namespace osu.Game.Tests.Visual.Online { @@ -24,18 +23,20 @@ namespace osu.Game.Tests.Visual.Online public TestSceneRankingsScopeSelector() { - Bindable scope = new Bindable(); + var scope = new Bindable(); - Add(background = new Box + AddRange(new Drawable[] { - RelativeSizeAxes = Axes.Both - }); - - Add(new RankingsScopeSelector - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Current = { BindTarget = scope } + background = new Box + { + RelativeSizeAxes = Axes.Both + }, + new RankingsScopeSelector + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Current = { BindTarget = scope } + } }); AddStep(@"Select country", () => scope.Value = RankingsScope.Country); @@ -47,7 +48,7 @@ namespace osu.Game.Tests.Visual.Online [BackgroundDependencyLoader] private void load(OsuColour colours) { - background.Colour = colours.Yellow.Opacity(50); + background.Colour = colours.GreySeafoam; } } } From e682ca4fd9a17cf90ac083ec5ff8faf317606b59 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 12:51:54 +0900 Subject: [PATCH 081/239] Adjust osu!mania scroll speed defaults to be more sane --- .../Configuration/ManiaRulesetConfigManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs index b591f9da22..f5412dcfc5 100644 --- a/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs +++ b/osu.Game.Rulesets.Mania/Configuration/ManiaRulesetConfigManager.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mania.Configuration { base.InitialiseDefaults(); - Set(ManiaRulesetSetting.ScrollTime, 2250.0, 50.0, 10000.0, 50.0); + Set(ManiaRulesetSetting.ScrollTime, 1500.0, 50.0, 5000.0, 50.0); Set(ManiaRulesetSetting.ScrollDirection, ManiaScrollingDirection.Down); } From 70d39e9be47d7fae0250c0acc3c9fdf27e0f8ced Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 11 Sep 2019 13:28:36 +0900 Subject: [PATCH 082/239] Always apply stable's magic ratio --- osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs b/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs index d2018ea720..1885c76fcc 100644 --- a/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs +++ b/osu.Game.Rulesets.Osu/Skinning/LegacyCursorTrail.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Skinning Texture = skin.GetTexture("cursortrail"); disjointTrail = skin.GetTexture("cursormiddle") == null; - if (disjointTrail && Texture != null) + if (Texture != null) { // stable "magic ratio". see OsuPlayfieldAdjustmentContainer for full explanation. Texture.ScaleAdjust *= 1.6f; From 6c00d3936ae556af3184f587fffdf85afab58b61 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 11 Sep 2019 13:28:46 +0900 Subject: [PATCH 083/239] Reduce interval between cursor trail parts --- osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 7975982aec..b32dfd483f 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -152,7 +152,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor float distance = diff.Length; Vector2 direction = diff / distance; - float interval = partSize.X / 2 * 0.9f; + float interval = partSize.X / 2.5f; for (float d = interval; d < distance; d += interval) { From 562280ced02ed9c570a7b56a8a6e4cd9dbd95507 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 11 Sep 2019 13:30:07 +0900 Subject: [PATCH 084/239] Add cursor trail test scene --- .../TestSceneCursorTrail.cs | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs new file mode 100644 index 0000000000..dae75e5a9d --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs @@ -0,0 +1,120 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Framework.Audio.Sample; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Textures; +using osu.Framework.Testing.Input; +using osu.Game.Audio; +using osu.Game.Rulesets.Osu.Skinning; +using osu.Game.Rulesets.Osu.UI.Cursor; +using osu.Game.Skinning; +using osu.Game.Tests.Visual; +using osuTK; + +namespace osu.Game.Rulesets.Osu.Tests +{ + public class TestSceneCursorTrail : OsuTestScene + { + [Test] + public void TestSmoothCursorTrail() + { + createTest(() => new CursorTrail()); + } + + [Test] + public void TestLegacySmoothCursorTrail() + { + createTest(() => new LegacySkinContainer(false) + { + Child = new LegacyCursorTrail() + }); + } + + [Test] + public void TestLegacyDisjointCursorTrail() + { + createTest(() => new LegacySkinContainer(true) + { + Child = new LegacyCursorTrail() + }); + } + + private void createTest(Func createContent) => AddStep("create trail", () => + { + Clear(); + + Add(new Container + { + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.8f), + Child = new MovingCursorInputManager { Child = createContent?.Invoke() } + }); + }); + + [Cached(typeof(ISkinSource))] + private class LegacySkinContainer : Container, ISkinSource + { + private readonly bool disjoint; + + public LegacySkinContainer(bool disjoint) + { + this.disjoint = disjoint; + + RelativeSizeAxes = Axes.Both; + } + + public Drawable GetDrawableComponent(ISkinComponent component) => throw new NotImplementedException(); + + public Texture GetTexture(string componentName) + { + switch (componentName) + { + case "cursortrail": + var tex = new Texture(Texture.WhitePixel.TextureGL); + + if (disjoint) + tex.ScaleAdjust = 1 / 25f; + return tex; + + case "cursormiddle": + return disjoint ? null : Texture.WhitePixel; + } + + return null; + } + + public SampleChannel GetSample(ISampleInfo sampleInfo) => throw new NotImplementedException(); + + public IBindable GetConfig(TLookup lookup) => throw new NotImplementedException(); + + public event Action SourceChanged; + } + + private class MovingCursorInputManager : ManualInputManager + { + public MovingCursorInputManager() + { + UseParentInput = false; + } + + protected override void Update() + { + base.Update(); + + const double spin_duration = 1000; + double currentTime = Time.Current; + + double angle = (currentTime % spin_duration) / spin_duration * 2 * Math.PI; + Vector2 rPos = new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)); + + MoveMouseTo(ToScreenSpace(DrawSize / 2 + DrawSize / 3 * rPos)); + } + } + } +} From 6760e239a119b74661a9efc0b6bce63615d6fdcd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 13:39:21 +0900 Subject: [PATCH 085/239] Fix osu! hitcircle font textures being incorrectly sized --- osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs | 6 +++--- osu.Game/Skinning/LegacySpriteText.cs | 7 +------ 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index 6b6a08ed21..c978d95302 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -86,9 +86,9 @@ namespace osu.Game.Rulesets.Osu.Skinning ? null : new LegacySpriteText(source, font) { - // Spacing value was reverse-engineered from the ratio of the rendered sprite size in the visual inspector vs the actual texture size - Scale = new Vector2(0.96f), - Spacing = new Vector2(-overlap * 0.89f, 0) + // stable applies a blanket 0.8x scale to hitcircle fonts + Scale = new Vector2(0.8f), + Spacing = new Vector2(-overlap, 0) }; } diff --git a/osu.Game/Skinning/LegacySpriteText.cs b/osu.Game/Skinning/LegacySpriteText.cs index dbcec019d6..773a9dc5c6 100644 --- a/osu.Game/Skinning/LegacySpriteText.cs +++ b/osu.Game/Skinning/LegacySpriteText.cs @@ -4,7 +4,6 @@ using System.Threading.Tasks; using osu.Framework.Graphics.Sprites; using osu.Framework.Text; -using osu.Game.Graphics; using osu.Game.Graphics.Sprites; namespace osu.Game.Skinning @@ -18,7 +17,7 @@ namespace osu.Game.Skinning Shadow = false; UseFullGlyphHeight = false; - Font = new FontUsage(font, OsuFont.DEFAULT_FONT_SIZE); + Font = new FontUsage(font, 1); glyphStore = new LegacyGlyphStore(skin); } @@ -37,10 +36,6 @@ namespace osu.Game.Skinning { var texture = skin.GetTexture($"{fontName}-{character}"); - if (texture != null) - // Approximate value that brings character sizing roughly in-line with stable - texture.ScaleAdjust *= 18; - if (texture == null) return null; From e408efff4984be7d737c86a76221d9c5771c229d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 11 Sep 2019 13:40:53 +0900 Subject: [PATCH 086/239] Add scaling to the test --- osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs index dae75e5a9d..685a51d208 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneCursorTrail.cs @@ -24,7 +24,15 @@ namespace osu.Game.Rulesets.Osu.Tests [Test] public void TestSmoothCursorTrail() { - createTest(() => new CursorTrail()); + Container scalingContainer = null; + + createTest(() => scalingContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Child = new CursorTrail() + }); + + AddStep("set large scale", () => scalingContainer.Scale = new Vector2(10)); } [Test] From 96efc91b51a9b46a0045d246e7c2cc26e86fc6b2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 14:57:42 +0900 Subject: [PATCH 087/239] Fix follow points not displaying on some skins --- osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index 82181945a4..479c250eab 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -45,6 +45,9 @@ namespace osu.Game.Rulesets.Osu.Skinning switch (osuComponent.Component) { + case OsuSkinComponents.FollowPoint: + return this.GetAnimation(component.LookupName, true, false); + case OsuSkinComponents.SliderFollowCircle: return this.GetAnimation("sliderfollowcircle", true, true); From 95828b07efecaf83ef25127043f71ebb77e6c92f Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 11 Sep 2019 10:40:58 +0300 Subject: [PATCH 088/239] Implement HeaderFlag component for rankings overlay --- .../Online/TestSceneRankingsHeaderFlag.cs | 55 +++++++++++++++ osu.Game/Overlays/Rankings/HeaderFlag.cs | 68 +++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs create mode 100644 osu.Game/Overlays/Rankings/HeaderFlag.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs new file mode 100644 index 0000000000..d31e3011b8 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs @@ -0,0 +1,55 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Overlays.Rankings; +using osu.Game.Users; +using osuTK; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsHeaderFlag : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(HeaderFlag), + }; + + public TestSceneRankingsHeaderFlag() + { + HeaderFlag flag; + SpriteText text; + + AddRange(new Drawable[] + { + flag = new HeaderFlag + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(30, 20), + Country = new Country + { + FlagName = "BY", + FullName = "Belarus" + } + }, + text = new SpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = "Invoked", + Font = OsuFont.GetFont(size: 30), + Alpha = 0, + } + }); + + flag.Action += () => text.FadeIn().Then().FadeOut(1000, Easing.OutQuint); + + AddStep("Trigger click", () => flag.Click()); + } + } +} diff --git a/osu.Game/Overlays/Rankings/HeaderFlag.cs b/osu.Game/Overlays/Rankings/HeaderFlag.cs new file mode 100644 index 0000000000..5b00e3e487 --- /dev/null +++ b/osu.Game/Overlays/Rankings/HeaderFlag.cs @@ -0,0 +1,68 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Game.Users.Drawables; +using osuTK.Graphics; +using osuTK; +using osu.Framework.Input.Events; +using osu.Framework.Extensions.Color4Extensions; +using System; + +namespace osu.Game.Overlays.Rankings +{ + public class HeaderFlag : UpdateableFlag + { + private const int duration = 200; + + public Action Action; + + private readonly Container hoverContainer; + + public HeaderFlag() + { + AddInternal(hoverContainer = new Container + { + Alpha = 0, + Depth = -1, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(15), + Icon = FontAwesome.Solid.Times, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(100), + } + } + }); + } + + protected override bool OnHover(HoverEvent e) + { + hoverContainer.FadeIn(duration, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + hoverContainer.FadeOut(duration, Easing.OutQuint); + } + + protected override bool OnClick(ClickEvent e) + { + Action?.Invoke(); + return base.OnClick(e); + } + } +} From d610c903716356593f9b774c5e768412583e13c5 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 11 Sep 2019 10:43:51 +0300 Subject: [PATCH 089/239] Add more tests --- .../Online/TestSceneRankingsHeaderFlag.cs | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs index d31e3011b8..c9531e1016 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs @@ -24,6 +24,18 @@ namespace osu.Game.Tests.Visual.Online HeaderFlag flag; SpriteText text; + var countryA = new Country + { + FlagName = "BY", + FullName = "Belarus" + }; + + var countryB = new Country + { + FlagName = "US", + FullName = "United States" + }; + AddRange(new Drawable[] { flag = new HeaderFlag @@ -31,11 +43,7 @@ namespace osu.Game.Tests.Visual.Online Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(30, 20), - Country = new Country - { - FlagName = "BY", - FullName = "Belarus" - } + Country = countryA, }, text = new SpriteText { @@ -50,6 +58,8 @@ namespace osu.Game.Tests.Visual.Online flag.Action += () => text.FadeIn().Then().FadeOut(1000, Easing.OutQuint); AddStep("Trigger click", () => flag.Click()); + AddStep("Change to country 2", () => flag.Country = countryB); + AddStep("Change to country 1", () => flag.Country = countryA); } } } From 1d1da1bc13c7f1c613aa8bba35c8f5b90a819b15 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 11 Sep 2019 11:26:09 +0300 Subject: [PATCH 090/239] Visual improvements --- osu.Game/Overlays/Rankings/HeaderFlag.cs | 34 +++++++++--------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/osu.Game/Overlays/Rankings/HeaderFlag.cs b/osu.Game/Overlays/Rankings/HeaderFlag.cs index 5b00e3e487..8bd4bdf13f 100644 --- a/osu.Game/Overlays/Rankings/HeaderFlag.cs +++ b/osu.Game/Overlays/Rankings/HeaderFlag.cs @@ -20,49 +20,39 @@ namespace osu.Game.Overlays.Rankings public Action Action; - private readonly Container hoverContainer; + private readonly SpriteIcon hoverIcon; public HeaderFlag() { - AddInternal(hoverContainer = new Container + AddInternal(hoverIcon = new SpriteIcon { - Alpha = 0, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, Depth = -1, - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - new SpriteIcon - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(15), - Icon = FontAwesome.Solid.Times, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black.Opacity(100), - } - } + Alpha = 0, + Size = new Vector2(10), + Icon = FontAwesome.Solid.Times, }); } protected override bool OnHover(HoverEvent e) { - hoverContainer.FadeIn(duration, Easing.OutQuint); + hoverIcon.FadeIn(duration, Easing.OutQuint); + this.FadeColour(Color4.Gray, duration, Easing.OutQuint); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { base.OnHoverLost(e); - hoverContainer.FadeOut(duration, Easing.OutQuint); + hoverIcon.FadeOut(duration, Easing.OutQuint); + this.FadeColour(Color4.White, duration, Easing.OutQuint); } protected override bool OnClick(ClickEvent e) { Action?.Invoke(); - return base.OnClick(e); + return true; } } } From 825a34ecd3180d421aa6f6f8827df3a8269f5f70 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 17:34:03 +0900 Subject: [PATCH 091/239] Early return to avoid other potential fail cases --- .../Containers/OsuFocusedOverlayContainer.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 5c2efbc354..08164dbf3e 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; @@ -106,26 +106,26 @@ namespace osu.Game.Graphics.Containers protected override void UpdateState(ValueChangedEvent state) { - base.UpdateState(state); - switch (state.NewValue) { case Visibility.Visible: - if (OverlayActivationMode.Value != OverlayActivation.Disabled) + if (OverlayActivationMode.Value == OverlayActivation.Disabled) { - if (PlaySamplesOnStateChange) samplePopIn?.Play(); - if (BlockScreenWideMouse && DimMainContent) osuGame?.AddBlockingOverlay(this); + State.Value = Visibility.Hidden; + return; } - else - Hide(); + if (PlaySamplesOnStateChange) samplePopIn?.Play(); + if (BlockScreenWideMouse && DimMainContent) game?.AddBlockingOverlay(this); break; case Visibility.Hidden: if (PlaySamplesOnStateChange) samplePopOut?.Play(); - if (BlockScreenWideMouse) osuGame?.RemoveBlockingOverlay(this); + if (BlockScreenWideMouse) game?.RemoveBlockingOverlay(this); break; } + + base.UpdateState(state); } protected override void PopOut() From 2c09efa23b577bc5e15c3a4efea6558a490f7d62 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 17:34:28 +0900 Subject: [PATCH 092/239] Handle changes to OverlayActivationMode --- .../Containers/OsuFocusedOverlayContainer.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 08164dbf3e..0ce095d44f 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; @@ -32,7 +32,7 @@ namespace osu.Game.Graphics.Containers protected virtual bool DimMainContent => true; [Resolved(CanBeNull = true)] - private OsuGame osuGame { get; set; } + private OsuGame game { get; set; } [Resolved] private PreviewTrackManager previewTrackManager { get; set; } @@ -42,8 +42,14 @@ namespace osu.Game.Graphics.Containers [BackgroundDependencyLoader(true)] private void load(AudioManager audio) { - if (osuGame != null) - OverlayActivationMode.BindTo(osuGame.OverlayActivationMode); + OverlayActivationMode.ValueChanged += mode => + { + if (mode.NewValue == OverlayActivation.Disabled) + State.Value = Visibility.Hidden; + }; + + if (game != null) + OverlayActivationMode.BindTo(game.OverlayActivationMode); samplePopIn = audio.Samples.Get(@"UI/overlay-pop-in"); samplePopOut = audio.Samples.Get(@"UI/overlay-pop-out"); @@ -137,7 +143,7 @@ namespace osu.Game.Graphics.Containers protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - osuGame?.RemoveBlockingOverlay(this); + game?.RemoveBlockingOverlay(this); } } } From 660c678cdcbe74b8a6b6fe55555a60b2b778f820 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 11 Sep 2019 11:40:51 +0300 Subject: [PATCH 093/239] Remove unused using directives --- osu.Game/Overlays/Rankings/HeaderFlag.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Overlays/Rankings/HeaderFlag.cs b/osu.Game/Overlays/Rankings/HeaderFlag.cs index 8bd4bdf13f..6f641c74a5 100644 --- a/osu.Game/Overlays/Rankings/HeaderFlag.cs +++ b/osu.Game/Overlays/Rankings/HeaderFlag.cs @@ -2,14 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Users.Drawables; using osuTK.Graphics; using osuTK; using osu.Framework.Input.Events; -using osu.Framework.Extensions.Color4Extensions; using System; namespace osu.Game.Overlays.Rankings From 41ad44791bfc2918af739f05273e244e180b7f20 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 11 Sep 2019 11:58:18 +0300 Subject: [PATCH 094/239] Move RankingsScopeSelector to another namespace --- osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs | 2 +- osu.Game/Overlays/{ => Rankings}/RankingsScopeSelector.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename osu.Game/Overlays/{ => Rankings}/RankingsScopeSelector.cs (94%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs index 93a00e1d06..2081a6c0cb 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs @@ -5,10 +5,10 @@ using System; using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Bindables; -using osu.Game.Overlays; using osu.Framework.Graphics.Shapes; using osu.Framework.Allocation; using osu.Game.Graphics; +using osu.Game.Overlays.Rankings; namespace osu.Game.Tests.Visual.Online { diff --git a/osu.Game/Overlays/RankingsScopeSelector.cs b/osu.Game/Overlays/Rankings/RankingsScopeSelector.cs similarity index 94% rename from osu.Game/Overlays/RankingsScopeSelector.cs rename to osu.Game/Overlays/Rankings/RankingsScopeSelector.cs index 5935876ec9..2095bcc61c 100644 --- a/osu.Game/Overlays/RankingsScopeSelector.cs +++ b/osu.Game/Overlays/Rankings/RankingsScopeSelector.cs @@ -5,7 +5,7 @@ using osu.Game.Graphics.UserInterface; using osu.Framework.Allocation; using osuTK.Graphics; -namespace osu.Game.Overlays +namespace osu.Game.Overlays.Rankings { public class RankingsScopeSelector : GradientLineTabControl { From da6ba20fc80a7cb25badd75fcc0dfd23a2b4f0bb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 18:15:03 +0900 Subject: [PATCH 095/239] Reduce glow on notes --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 2cd81104a3..5aeaba717c 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Diagnostics; @@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Glow, - Colour = colour.NewValue.Lighten(1f).Opacity(0.6f), + Colour = colour.NewValue.Lighten(1f).Opacity(0.2f), Radius = 10, }; }, true); From 44d90a4e860fecb7891d295fe929fdc8dbc8d6f6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 18:16:14 +0900 Subject: [PATCH 096/239] Increase note height --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs | 4 +++- .../Objects/Drawables/Pieces/NotePiece.cs | 7 +++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs index 5aeaba717c..31221c05ee 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Diagnostics; @@ -18,6 +18,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables /// public class DrawableNote : DrawableManiaHitObject, IKeyBindingHandler { + public const float CORNER_RADIUS = NotePiece.NOTE_HEIGHT / 2; + private readonly NotePiece headPiece; public DrawableNote(Note hitObject) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs index bb33693783..4521af7dfb 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/Pieces/NotePiece.cs @@ -18,8 +18,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces /// internal class NotePiece : Container, IHasAccentColour { - public const float NOTE_HEIGHT = 10; - private const float head_colour_height = 6; + public const float NOTE_HEIGHT = 12; private readonly IBindable direction = new Bindable(); @@ -39,8 +38,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables.Pieces colouredBox = new Box { RelativeSizeAxes = Axes.X, - Height = head_colour_height, - Alpha = 0.2f + Height = NOTE_HEIGHT / 2, + Alpha = 0.1f } }; } From 8f6bc6fd5c8171152f308c937c2e3dff48894b97 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 18:12:43 +0900 Subject: [PATCH 097/239] Make osu!mania hit explosions more explodey --- .../TestSceneHitExplosion.cs | 84 ++++++++++++ osu.Game.Rulesets.Mania/UI/Column.cs | 9 +- osu.Game.Rulesets.Mania/UI/HitExplosion.cs | 123 +++++++++++++----- 3 files changed, 183 insertions(+), 33 deletions(-) create mode 100644 osu.Game.Rulesets.Mania.Tests/TestSceneHitExplosion.cs diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHitExplosion.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHitExplosion.cs new file mode 100644 index 0000000000..12159ca239 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHitExplosion.cs @@ -0,0 +1,84 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Mania.Objects; +using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.UI.Scrolling; +using osu.Game.Tests.Visual; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Mania.Tests +{ + [TestFixture] + public class TestSceneHitExplosion : OsuTestScene + { + private ScrollingTestContainer scrolling; + + public override IReadOnlyList RequiredTypes => new[] + { + typeof(DrawableNote), + typeof(DrawableManiaHitObject), + }; + + protected override void LoadComplete() + { + base.LoadComplete(); + + Child = scrolling = new ScrollingTestContainer(ScrollingDirection.Down) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativePositionAxes = Axes.Y, + Y = -0.25f, + Size = new Vector2(Column.COLUMN_WIDTH, NotePiece.NOTE_HEIGHT), + }; + + int runcount = 0; + + AddRepeatStep("explode", () => + { + runcount++; + + if (runcount % 15 > 12) + return; + + scrolling.AddRange(new Drawable[] + { + new HitExplosion((runcount / 15) % 2 == 0 ? new Color4(94, 0, 57, 255) : new Color4(6, 84, 0, 255), runcount % 6 != 0) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + } + }); + }, 100); + } + + private class TestNote : DrawableNote + { + protected override void CheckForResult(bool userTriggered, double timeOffset) + { + if (!userTriggered) + { + // force success + ApplyResult(r => r.Type = HitResult.Great); + } + else + base.CheckForResult(userTriggered, timeOffset); + } + + public TestNote(Note hitObject) + : base(hitObject) + { + AccentColour.Value = Color4.Pink; + } + } + } +} diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 91dd236ab1..fa14a0a293 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System.Linq; @@ -90,6 +90,8 @@ namespace osu.Game.Rulesets.Mania.UI Bottom = dir.NewValue == ScrollingDirection.Down ? ManiaStage.HIT_TARGET_POSITION : 0, }; + explosionContainer.Y = dir.NewValue == ScrollingDirection.Down ? -NotePiece.NOTE_HEIGHT : 0; + keyArea.Anchor = keyArea.Origin = dir.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; }, true); } @@ -163,9 +165,10 @@ namespace osu.Game.Rulesets.Mania.UI if (!result.IsHit || !judgedObject.DisplayResult || !DisplayJudgements.Value) return; - explosionContainer.Add(new HitExplosion(judgedObject) + explosionContainer.Add(new HitExplosion(judgedObject.AccentColour.Value, judgedObject is DrawableHoldNoteTick) { - Anchor = Direction.Value == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre + Anchor = Direction.Value == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre, + Origin = Direction.Value == ScrollingDirection.Up ? Anchor.BottomCentre : Anchor.TopCentre, }); } diff --git a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs index 48470add8b..21726206f1 100644 --- a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs @@ -1,16 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osuTK.Graphics; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; -using osu.Framework.Graphics.Shapes; using osu.Framework.MathUtils; -using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; -using osu.Game.Rulesets.Objects.Drawables; using osuTK; +using osuTK.Graphics; namespace osu.Game.Rulesets.Mania.UI { @@ -18,51 +16,116 @@ namespace osu.Game.Rulesets.Mania.UI { public override bool RemoveWhenNotAlive => true; - private readonly CircularContainer circle; + private readonly CircularContainer largeFaint; + private readonly CircularContainer mainGlow1; + private readonly CircularContainer mainGlow2; + private readonly CircularContainer mainGlow3; - public HitExplosion(DrawableHitObject judgedObject) + public HitExplosion(Color4 objectColour, bool isSmall = false) { - bool isTick = judgedObject is DrawableHoldNoteTick; - - Origin = Anchor.Centre; - RelativeSizeAxes = Axes.X; - Y = NotePiece.NOTE_HEIGHT / 2; Height = NotePiece.NOTE_HEIGHT; // scale roughly in-line with visual appearance of notes - Scale = new Vector2(isTick ? 0.4f : 0.8f); + Scale = new Vector2(1f, 0.6f); - InternalChild = circle = new CircularContainer + if (isSmall) + Scale *= 0.5f; + + const float angle_variangle = 15; // should be less than 45 + + const float roundness = 80; + + const float opacity = 1; + + const float initial_height = 10; + + var colour = Interpolation.ValueAt(0.4f, objectColour, Color4.White, 0, 1); + + InternalChildren = new Drawable[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Masking = true, - // we want our size to be very small so the glow dominates it. - Size = new Vector2(0.1f), - EdgeEffect = new EdgeEffectParameters + largeFaint = new CircularContainer { - Type = EdgeEffectType.Glow, - Colour = Interpolation.ValueAt(0.1f, judgedObject.AccentColour.Value, Color4.White, 0, 1), - Radius = 100, - }, - Child = new Box - { - Alpha = 0, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, - AlwaysPresent = true + Masking = true, + // we want our size to be very small so the glow dominates it. + Size = new Vector2(0.8f), + Blending = BlendingParameters.Additive, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Colour = Interpolation.ValueAt(0.1f, objectColour, Color4.White, 0, 1).Opacity(0.3f), + Roundness = 160, + Radius = 200, + }, + }, + mainGlow1 = new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Masking = true, + Blending = BlendingParameters.Additive, + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Colour = Interpolation.ValueAt(0.6f, objectColour, Color4.White, 0, 1), + Roundness = 20, + Radius = 50, + }, + }, + mainGlow2 = new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Masking = true, + Size = new Vector2(0.01f, initial_height), + Blending = BlendingParameters.Additive, + Rotation = RNG.NextSingle(-angle_variangle, angle_variangle), + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Colour = colour, + Roundness = roundness, + Radius = 40, + }, + }, + mainGlow3 = new CircularContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + Masking = true, + Size = new Vector2(0.01f, initial_height), + Blending = BlendingParameters.Additive, + Rotation = RNG.NextSingle(-angle_variangle, angle_variangle), + EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, + Colour = colour, + Roundness = roundness, + Radius = 40, + }, } }; } protected override void LoadComplete() { + const double duration = 200; + base.LoadComplete(); - circle.ResizeTo(circle.Size * new Vector2(4, 20), 1000, Easing.OutQuint); - this.FadeIn(16).Then().FadeOut(500, Easing.OutQuint); + largeFaint + .ResizeTo(largeFaint.Size * new Vector2(5, 1), duration, Easing.OutQuint) + .FadeOut(duration * 2); + mainGlow1.ScaleTo(1.4f, duration, Easing.OutQuint); + + this.FadeOut(duration, Easing.Out); Expire(true); } } From 6bfdadb22fb1dcaaf172e5694a955c812c4bd030 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 18:20:41 +0900 Subject: [PATCH 098/239] Increase column width --- osu.Game.Rulesets.Mania/UI/Column.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 91dd236ab1..0caee025b6 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -11,6 +11,8 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Mania.UI.Components; using osu.Game.Rulesets.UI.Scrolling; using osuTK; @@ -19,7 +21,7 @@ namespace osu.Game.Rulesets.Mania.UI { public class Column : ScrollingPlayfield, IKeyBindingHandler, IHasAccentColour { - private const float column_width = 45; + public const float COLUMN_WIDTH = 80; private const float special_column_width = 70; /// @@ -41,10 +43,7 @@ namespace osu.Game.Rulesets.Mania.UI Index = index; RelativeSizeAxes = Axes.Y; - Width = column_width; - - Masking = true; - CornerRadius = 5; + Width = COLUMN_WIDTH; background = new ColumnBackground { RelativeSizeAxes = Axes.Both }; @@ -67,7 +66,7 @@ namespace osu.Game.Rulesets.Mania.UI explosionContainer = new Container { Name = "Hit explosions", - RelativeSizeAxes = Axes.Both + RelativeSizeAxes = Axes.Both, } } }, @@ -108,7 +107,7 @@ namespace osu.Game.Rulesets.Mania.UI isSpecial = value; - Width = isSpecial ? special_column_width : column_width; + Width = isSpecial ? special_column_width : COLUMN_WIDTH; } } From c7186efd5339a954eaf67682c01fb184e669b455 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 18:21:29 +0900 Subject: [PATCH 099/239] Reduce opacity of judgement area --- osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs index a0d713067d..386bcbb724 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnHitObjectArea.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; +using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI.Scrolling; using osuTK.Graphics; @@ -17,7 +18,6 @@ namespace osu.Game.Rulesets.Mania.UI.Components { public class ColumnHitObjectArea : CompositeDrawable, IHasAccentColour { - private const float hit_target_height = 10; private const float hit_target_bar_height = 2; private readonly IBindable direction = new Bindable(); @@ -32,7 +32,8 @@ namespace osu.Game.Rulesets.Mania.UI.Components hitTargetBar = new Box { RelativeSizeAxes = Axes.X, - Height = hit_target_height, + Height = NotePiece.NOTE_HEIGHT, + Alpha = 0.6f, Colour = Color4.Black }, hitTargetLine = new Container From b9e71d26b285922d7c0d0a7e3f2d0bcc60628220 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 18:21:39 +0900 Subject: [PATCH 100/239] Dim column backgrounds further --- osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs index 5ee78aa496..57241da564 100644 --- a/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/UI/Components/ColumnBackground.cs @@ -35,7 +35,6 @@ namespace osu.Game.Rulesets.Mania.UI.Components { Name = "Background", RelativeSizeAxes = Axes.Both, - Alpha = 0.3f }, backgroundOverlay = new Box { @@ -82,7 +81,7 @@ namespace osu.Game.Rulesets.Mania.UI.Components if (!IsLoaded) return; - background.Colour = AccentColour; + background.Colour = AccentColour.Darken(5); var brightPoint = AccentColour.Opacity(0.6f); var dimPoint = AccentColour.Opacity(0); From 06618b6d02e7f358d1929cf5bf19b1e6f22c269a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 18:45:47 +0900 Subject: [PATCH 101/239] Fix osu!mania minor barline alpha not being respected --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs index 862af8d15b..be21610525 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs @@ -68,6 +68,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables Alpha = 0.2f; } + protected override void UpdateInitialTransforms() + { + } + protected override void UpdateStateTransforms(ArmedState state) { } From 039b5ec958fcac03296e31791721b2e786c17de7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 18:47:25 +0900 Subject: [PATCH 102/239] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index f76297c197..45c162a30e 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 791d2fe285..df8b11e653 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 0560c45edf..7c31744a14 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,8 +118,8 @@ - - + + From be66c0e9127982166e393e697daa9d4c2d5db938 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 19:06:31 +0900 Subject: [PATCH 103/239] Fix potential of toggle between load and LoadComplete --- .../Graphics/Containers/OsuFocusedOverlayContainer.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 0ce095d44f..a1df973b60 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -41,6 +41,12 @@ namespace osu.Game.Graphics.Containers [BackgroundDependencyLoader(true)] private void load(AudioManager audio) + { + samplePopIn = audio.Samples.Get(@"UI/overlay-pop-in"); + samplePopOut = audio.Samples.Get(@"UI/overlay-pop-out"); + } + + protected override void LoadComplete() { OverlayActivationMode.ValueChanged += mode => { @@ -51,8 +57,7 @@ namespace osu.Game.Graphics.Containers if (game != null) OverlayActivationMode.BindTo(game.OverlayActivationMode); - samplePopIn = audio.Samples.Get(@"UI/overlay-pop-in"); - samplePopOut = audio.Samples.Get(@"UI/overlay-pop-out"); + base.LoadComplete(); } /// From 55a071e8ba9bfe68ba237daa81a1024a43366d92 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 11 Sep 2019 19:12:55 +0900 Subject: [PATCH 104/239] Use BindValueChanged --- .../Graphics/Containers/OsuFocusedOverlayContainer.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index a1df973b60..2e8910213b 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -48,14 +48,14 @@ namespace osu.Game.Graphics.Containers protected override void LoadComplete() { - OverlayActivationMode.ValueChanged += mode => + if (game != null) + OverlayActivationMode.BindTo(game.OverlayActivationMode); + + OverlayActivationMode.BindValueChanged(mode => { if (mode.NewValue == OverlayActivation.Disabled) State.Value = Visibility.Hidden; - }; - - if (game != null) - OverlayActivationMode.BindTo(game.OverlayActivationMode); + }, true); base.LoadComplete(); } From dbfbd1262fd1caffd5d657d1bbf6ef24d2b66997 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 11 Sep 2019 23:39:22 +0300 Subject: [PATCH 105/239] Implement HeaderTitle component for RankingsOverlay --- .../Online/TestSceneRankingsHeaderTitle.cs | 60 ++++++++++ osu.Game/Overlays/Rankings/HeaderTitle.cs | 105 ++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs create mode 100644 osu.Game/Overlays/Rankings/HeaderTitle.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs new file mode 100644 index 0000000000..0f16b2592f --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs @@ -0,0 +1,60 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Overlays.Rankings; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsHeaderTitle : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(HeaderFlag), + typeof(HeaderTitle), + }; + + public TestSceneRankingsHeaderTitle() + { + var countryBindable = new Bindable(); + var scope = new Bindable(); + + Add(new HeaderTitle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Country = { BindTarget = countryBindable }, + Scope = { BindTarget = scope }, + }); + + var countryA = new Country + { + FlagName = "BY", + FullName = "Belarus" + }; + + var countryB = new Country + { + FlagName = "US", + FullName = "United States" + }; + + AddStep("Set country", () => countryBindable.Value = countryA); + AddAssert("Check scope is Performance", () => scope.Value == RankingsScope.Performance); + AddStep("Set scope to Score", () => scope.Value = RankingsScope.Score); + AddAssert("Check country is Null", () => countryBindable.Value == null); + + AddStep("Set country 1", () => countryBindable.Value = countryA); + AddStep("Set country 2", () => countryBindable.Value = countryB); + AddStep("Set null country", () => countryBindable.Value = null); + AddStep("Set scope to Performance", () => scope.Value = RankingsScope.Performance); + AddStep("Set scope to Spotlights", () => scope.Value = RankingsScope.Spotlights); + AddStep("Set scope to Score", () => scope.Value = RankingsScope.Score); + AddStep("Set scope to Country", () => scope.Value = RankingsScope.Country); + } + } +} diff --git a/osu.Game/Overlays/Rankings/HeaderTitle.cs b/osu.Game/Overlays/Rankings/HeaderTitle.cs new file mode 100644 index 0000000000..3f1feb10b8 --- /dev/null +++ b/osu.Game/Overlays/Rankings/HeaderTitle.cs @@ -0,0 +1,105 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Users; +using osu.Framework.Graphics; +using osuTK; +using osu.Game.Graphics; +using osu.Framework.Allocation; + +namespace osu.Game.Overlays.Rankings +{ + public class HeaderTitle : CompositeDrawable + { + private const int spacing = 10; + private const int flag_margin = 5; + private const int text_size = 40; + + public readonly Bindable Scope = new Bindable(); + public readonly Bindable Country = new Bindable(); + + private readonly SpriteText scopeText; + private readonly Container flagPlaceholder; + private readonly HeaderFlag flag; + + public HeaderTitle() + { + AutoSizeAxes = Axes.Both; + InternalChild = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(spacing, 0), + Children = new Drawable[] + { + flagPlaceholder = new Container + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Bottom = flag_margin }, + Child = flag = new HeaderFlag + { + Size = new Vector2(30, 20), + }, + }, + scopeText = new SpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Light) + }, + new SpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Light), + Text = @"Ranking" + } + } + }; + + flag.Action += () => Country.Value = null; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + scopeText.Colour = colours.Lime; + } + + protected override void LoadComplete() + { + Scope.BindValueChanged(scope => onScopeChanged(scope.NewValue), true); + Country.BindValueChanged(onCountryChanged, true); + base.LoadComplete(); + } + + private void onScopeChanged(RankingsScope scope) + { + scopeText.Text = scope.ToString(); + + if (scope != RankingsScope.Performance) + Country.Value = null; + } + + private void onCountryChanged(ValueChangedEvent country) + { + if (country.NewValue == null) + { + flagPlaceholder.Hide(); + return; + } + + Scope.Value = RankingsScope.Performance; + + if (country.OldValue == null) + flagPlaceholder.Show(); + + flag.Country = country.NewValue; + } + } +} From e0bf579b18eaddd62a85c9333a2375403b2d2e14 Mon Sep 17 00:00:00 2001 From: Joehu Date: Wed, 11 Sep 2019 15:35:47 -0700 Subject: [PATCH 106/239] Properly fix dialog overlay playing double samples on show/hide --- .../Containers/OsuFocusedOverlayContainer.cs | 6 ++---- osu.Game/Overlays/Dialog/PopupDialog.cs | 20 +------------------ osu.Game/Overlays/DialogOverlay.cs | 16 +++++++++++++-- 3 files changed, 17 insertions(+), 25 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs index 2e8910213b..b117d71006 100644 --- a/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs +++ b/osu.Game/Graphics/Containers/OsuFocusedOverlayContainer.cs @@ -21,8 +21,6 @@ namespace osu.Game.Graphics.Containers private SampleChannel samplePopIn; private SampleChannel samplePopOut; - protected virtual bool PlaySamplesOnStateChange => true; - protected override bool BlockNonPositionalInput => true; /// @@ -126,12 +124,12 @@ namespace osu.Game.Graphics.Containers return; } - if (PlaySamplesOnStateChange) samplePopIn?.Play(); + samplePopIn?.Play(); if (BlockScreenWideMouse && DimMainContent) game?.AddBlockingOverlay(this); break; case Visibility.Hidden: - if (PlaySamplesOnStateChange) samplePopOut?.Play(); + samplePopOut?.Play(); if (BlockScreenWideMouse) game?.RemoveBlockingOverlay(this); break; } diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index 1022edfe81..5c0ddb47b1 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -13,20 +13,17 @@ using osu.Framework.Input.Events; using osu.Game.Graphics; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; -using osu.Game.Input.Bindings; using osuTK; using osuTK.Graphics; using osuTK.Input; namespace osu.Game.Overlays.Dialog { - public class PopupDialog : OsuFocusedOverlayContainer + public class PopupDialog : VisibilityContainer { public static readonly float ENTER_DURATION = 500; public static readonly float EXIT_DURATION = 200; - protected override bool BlockPositionalInput => false; - private readonly Vector2 ringSize = new Vector2(100f); private readonly Vector2 ringMinifiedSize = new Vector2(20f); private readonly Vector2 buttonsEnterSpacing = new Vector2(0f, 50f); @@ -202,18 +199,6 @@ namespace osu.Game.Overlays.Dialog }; } - public override bool OnPressed(GlobalAction action) - { - switch (action) - { - case GlobalAction.Select: - Buttons.OfType().FirstOrDefault()?.Click(); - return true; - } - - return base.OnPressed(action); - } - protected override bool OnKeyDown(KeyDownEvent e) { if (e.Repeat) return false; @@ -238,8 +223,6 @@ namespace osu.Game.Overlays.Dialog protected override void PopIn() { - base.PopIn(); - actionInvoked = false; // Reset various animations but only if the dialog animation fully completed @@ -263,7 +246,6 @@ namespace osu.Game.Overlays.Dialog // This is presumed to always be a sane default "cancel" action. buttonsContainer.Last().Click(); - base.PopOut(); content.FadeOut(EXIT_DURATION, Easing.InSine); } diff --git a/osu.Game/Overlays/DialogOverlay.cs b/osu.Game/Overlays/DialogOverlay.cs index aaae7bcf5c..0d3c96c984 100644 --- a/osu.Game/Overlays/DialogOverlay.cs +++ b/osu.Game/Overlays/DialogOverlay.cs @@ -5,6 +5,8 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Overlays.Dialog; using osu.Game.Graphics.Containers; +using osu.Game.Input.Bindings; +using System.Linq; namespace osu.Game.Overlays { @@ -41,8 +43,6 @@ namespace osu.Game.Overlays Show(); } - protected override bool PlaySamplesOnStateChange => false; - protected override bool BlockNonPositionalInput => true; private void onDialogOnStateChanged(VisibilityContainer dialog, Visibility v) @@ -74,5 +74,17 @@ namespace osu.Game.Overlays this.FadeOut(PopupDialog.EXIT_DURATION, Easing.InSine); } + + public override bool OnPressed(GlobalAction action) + { + switch (action) + { + case GlobalAction.Select: + currentDialog.Buttons.OfType().FirstOrDefault()?.Click(); + return true; + } + + return base.OnPressed(action); + } } } From 77ac186cf803e02861197032cfda700383933667 Mon Sep 17 00:00:00 2001 From: Joehu Date: Wed, 11 Sep 2019 16:08:01 -0700 Subject: [PATCH 107/239] Add spacing to mod icons on leaderboards --- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 1 + osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs | 1 + .../Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 008f8208eb..0b84cfc28a 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -215,6 +215,7 @@ namespace osu.Game.Online.Leaderboards Origin = Anchor.BottomRight, AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, + Spacing = new Vector2(1), ChildrenEnumerable = score.Mods.Select(mod => new ModIcon(mod) { Scale = new Vector2(0.375f) }) }, }, diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 347522fb48..58f5f02956 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -171,6 +171,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Direction = FillDirection.Horizontal, AutoSizeAxes = Axes.Both, + Spacing = new Vector2(1), ChildrenEnumerable = score.Mods.Select(m => new ModIcon(m) { AutoSizeAxes = Axes.Both, diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs index 6761d0f710..b9664d7c2f 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs @@ -172,7 +172,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores : this(new FillFlowContainer { AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal + Direction = FillDirection.Horizontal, + Spacing = new Vector2(1), }) { } From c3c2efe35ca966df9cbde9925417fedbe0000637 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Sep 2019 05:03:59 +0300 Subject: [PATCH 108/239] Add ability to override text in PageTabItem --- osu.Game/Graphics/UserInterface/PageTabControl.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/PageTabControl.cs b/osu.Game/Graphics/UserInterface/PageTabControl.cs index a0d3745180..ddcb626701 100644 --- a/osu.Game/Graphics/UserInterface/PageTabControl.cs +++ b/osu.Game/Graphics/UserInterface/PageTabControl.cs @@ -63,7 +63,7 @@ namespace osu.Game.Graphics.UserInterface Margin = new MarginPadding { Top = 8, Bottom = 8 }, Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, - Text = (value as Enum)?.GetDescription() ?? value.ToString(), + Text = CreateText(), Font = OsuFont.GetFont(size: 14) }, box = new Box @@ -81,6 +81,8 @@ namespace osu.Game.Graphics.UserInterface Active.BindValueChanged(active => Text.Font = Text.Font.With(Typeface.Exo, weight: active.NewValue ? FontWeight.Bold : FontWeight.Medium), true); } + protected virtual string CreateText() => (Value as Enum)?.GetDescription() ?? Value.ToString(); + protected override bool OnHover(HoverEvent e) { if (!Active.Value) From 581508b8e75f51560398b06095d27e860afd89c1 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Sep 2019 05:06:51 +0300 Subject: [PATCH 109/239] Implement RankingsRulesetSelector --- .../TestSceneRankingsRulesetSelector.cs | 42 ++++++++++++++ .../Rankings/RankingsRulesetSelector.cs | 56 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs create mode 100644 osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs new file mode 100644 index 0000000000..8ad10c6a63 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs @@ -0,0 +1,42 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Game.Overlays.Rankings; +using osu.Framework.Graphics; +using osu.Game.Rulesets; +using osu.Framework.Bindables; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Mania; +using osu.Game.Rulesets.Taiko; +using osu.Game.Rulesets.Catch; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsRulesetSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(RankingsRulesetSelector), + }; + + public TestSceneRankingsRulesetSelector() + { + RankingsRulesetSelector selector; + var current = new Bindable(); + + Add(selector = new RankingsRulesetSelector + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Current = { BindTarget = current } + }); + + AddStep("Select osu!", () => current.Value = new OsuRuleset().RulesetInfo); + AddStep("Select mania", () => current.Value = new ManiaRuleset().RulesetInfo); + AddStep("Select taiko", () => current.Value = new TaikoRuleset().RulesetInfo); + AddStep("Select catch", () => current.Value = new CatchRuleset().RulesetInfo); + } + } +} diff --git a/osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs b/osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs new file mode 100644 index 0000000000..f1666507d1 --- /dev/null +++ b/osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs @@ -0,0 +1,56 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets; +using osuTK; +using System.Linq; + +namespace osu.Game.Overlays.Rankings +{ + public class RankingsRulesetSelector : PageTabControl + { + protected override TabItem CreateTabItem(RulesetInfo value) => new RankingsTabItem(value); + + protected override Dropdown CreateDropdown() => null; + + public RankingsRulesetSelector() + { + AutoSizeAxes = Axes.X; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours, RulesetStore Rulesets) + { + foreach (var r in Rulesets.AvailableRulesets) + AddItem(r); + + AccentColour = colours.Lime; + + SelectTab(TabContainer.FirstOrDefault()); + } + + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer + { + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(20, 0), + }; + + private class RankingsTabItem : PageTabItem + { + public RankingsTabItem(RulesetInfo value) + : base(value) + { + } + + protected override string CreateText() => $"{Value.Name}"; + } + } +} From 4bfb681db6f816fd623e0ef407e86c41980c1c5a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Sep 2019 05:16:56 +0300 Subject: [PATCH 110/239] CI fixes --- .../Visual/Online/TestSceneRankingsRulesetSelector.cs | 3 +-- osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs index 8ad10c6a63..84515bd3a4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs @@ -23,10 +23,9 @@ namespace osu.Game.Tests.Visual.Online public TestSceneRankingsRulesetSelector() { - RankingsRulesetSelector selector; var current = new Bindable(); - Add(selector = new RankingsRulesetSelector + Add(new RankingsRulesetSelector { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs b/osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs index f1666507d1..3d25e3995a 100644 --- a/osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs +++ b/osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs @@ -25,9 +25,9 @@ namespace osu.Game.Overlays.Rankings } [BackgroundDependencyLoader] - private void load(OsuColour colours, RulesetStore Rulesets) + private void load(OsuColour colours, RulesetStore rulesets) { - foreach (var r in Rulesets.AvailableRulesets) + foreach (var r in rulesets.AvailableRulesets) AddItem(r); AccentColour = colours.Lime; From b657e31f93b2b9fce626d0f151f6d36a565fd809 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Sep 2019 05:26:10 +0300 Subject: [PATCH 111/239] Merge dependent changes --- .../Online/TestSceneRankingsHeaderFlag.cs | 65 +++++++++++ .../Online/TestSceneRankingsHeaderTitle.cs | 60 ++++++++++ .../TestSceneRankingsRulesetSelector.cs | 41 +++++++ .../Online/TestSceneRankingsScopeSelector.cs | 54 +++++++++ .../UserInterface/GradientLineTabControl.cs | 103 +++++++++++++++++ .../Graphics/UserInterface/PageTabControl.cs | 4 +- .../BeatmapSet/LeaderboardScopeSelector.cs | 69 +----------- osu.Game/Overlays/Rankings/HeaderFlag.cs | 55 +++++++++ osu.Game/Overlays/Rankings/HeaderTitle.cs | 105 ++++++++++++++++++ .../Rankings/RankingsRulesetSelector.cs | 56 ++++++++++ .../Rankings/RankingsScopeSelector.cs | 26 +++++ 11 files changed, 572 insertions(+), 66 deletions(-) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs create mode 100644 osu.Game/Graphics/UserInterface/GradientLineTabControl.cs create mode 100644 osu.Game/Overlays/Rankings/HeaderFlag.cs create mode 100644 osu.Game/Overlays/Rankings/HeaderTitle.cs create mode 100644 osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs create mode 100644 osu.Game/Overlays/Rankings/RankingsScopeSelector.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs new file mode 100644 index 0000000000..c9531e1016 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs @@ -0,0 +1,65 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Overlays.Rankings; +using osu.Game.Users; +using osuTK; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsHeaderFlag : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(HeaderFlag), + }; + + public TestSceneRankingsHeaderFlag() + { + HeaderFlag flag; + SpriteText text; + + var countryA = new Country + { + FlagName = "BY", + FullName = "Belarus" + }; + + var countryB = new Country + { + FlagName = "US", + FullName = "United States" + }; + + AddRange(new Drawable[] + { + flag = new HeaderFlag + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(30, 20), + Country = countryA, + }, + text = new SpriteText + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Text = "Invoked", + Font = OsuFont.GetFont(size: 30), + Alpha = 0, + } + }); + + flag.Action += () => text.FadeIn().Then().FadeOut(1000, Easing.OutQuint); + + AddStep("Trigger click", () => flag.Click()); + AddStep("Change to country 2", () => flag.Country = countryB); + AddStep("Change to country 1", () => flag.Country = countryA); + } + } +} diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs new file mode 100644 index 0000000000..0f16b2592f --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs @@ -0,0 +1,60 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Overlays.Rankings; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsHeaderTitle : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(HeaderFlag), + typeof(HeaderTitle), + }; + + public TestSceneRankingsHeaderTitle() + { + var countryBindable = new Bindable(); + var scope = new Bindable(); + + Add(new HeaderTitle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Country = { BindTarget = countryBindable }, + Scope = { BindTarget = scope }, + }); + + var countryA = new Country + { + FlagName = "BY", + FullName = "Belarus" + }; + + var countryB = new Country + { + FlagName = "US", + FullName = "United States" + }; + + AddStep("Set country", () => countryBindable.Value = countryA); + AddAssert("Check scope is Performance", () => scope.Value == RankingsScope.Performance); + AddStep("Set scope to Score", () => scope.Value = RankingsScope.Score); + AddAssert("Check country is Null", () => countryBindable.Value == null); + + AddStep("Set country 1", () => countryBindable.Value = countryA); + AddStep("Set country 2", () => countryBindable.Value = countryB); + AddStep("Set null country", () => countryBindable.Value = null); + AddStep("Set scope to Performance", () => scope.Value = RankingsScope.Performance); + AddStep("Set scope to Spotlights", () => scope.Value = RankingsScope.Spotlights); + AddStep("Set scope to Score", () => scope.Value = RankingsScope.Score); + AddStep("Set scope to Country", () => scope.Value = RankingsScope.Country); + } + } +} diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs new file mode 100644 index 0000000000..84515bd3a4 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsRulesetSelector.cs @@ -0,0 +1,41 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Game.Overlays.Rankings; +using osu.Framework.Graphics; +using osu.Game.Rulesets; +using osu.Framework.Bindables; +using osu.Game.Rulesets.Osu; +using osu.Game.Rulesets.Mania; +using osu.Game.Rulesets.Taiko; +using osu.Game.Rulesets.Catch; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsRulesetSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(RankingsRulesetSelector), + }; + + public TestSceneRankingsRulesetSelector() + { + var current = new Bindable(); + + Add(new RankingsRulesetSelector + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Current = { BindTarget = current } + }); + + AddStep("Select osu!", () => current.Value = new OsuRuleset().RulesetInfo); + AddStep("Select mania", () => current.Value = new ManiaRuleset().RulesetInfo); + AddStep("Select taiko", () => current.Value = new TaikoRuleset().RulesetInfo); + AddStep("Select catch", () => current.Value = new CatchRuleset().RulesetInfo); + } + } +} diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs new file mode 100644 index 0000000000..2081a6c0cb --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs @@ -0,0 +1,54 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Framework.Bindables; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Allocation; +using osu.Game.Graphics; +using osu.Game.Overlays.Rankings; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsScopeSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(RankingsScopeSelector), + }; + + private readonly Box background; + + public TestSceneRankingsScopeSelector() + { + var scope = new Bindable(); + + AddRange(new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both + }, + new RankingsScopeSelector + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Current = { BindTarget = scope } + } + }); + + AddStep(@"Select country", () => scope.Value = RankingsScope.Country); + AddStep(@"Select performance", () => scope.Value = RankingsScope.Performance); + AddStep(@"Select score", () => scope.Value = RankingsScope.Score); + AddStep(@"Select spotlights", () => scope.Value = RankingsScope.Spotlights); + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + background.Colour = colours.GreySeafoam; + } + } +} diff --git a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs new file mode 100644 index 0000000000..7cd8d2c5bd --- /dev/null +++ b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs @@ -0,0 +1,103 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.UserInterface; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osuTK; +using osu.Framework.Graphics.Shapes; +using osuTK.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; + +namespace osu.Game.Graphics.UserInterface +{ + public class GradientLineTabControl : PageTabControl + { + protected override Dropdown CreateDropdown() => null; + + protected Color4 LineColour + { + get => line.MainColour.Value; + set => line.MainColour.Value = value; + } + + private readonly GradientLine line; + + public GradientLineTabControl() + { + RelativeSizeAxes = Axes.X; + + AddInternal(line = new GradientLine + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + }); + } + + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(20, 0), + }; + + private class GradientLine : GridContainer + { + public readonly Bindable MainColour = new Bindable(); + + private readonly Box left; + private readonly Box middle; + private readonly Box right; + + public GradientLine() + { + RelativeSizeAxes = Axes.X; + Size = new Vector2(0.8f, 1.5f); + + ColumnDimensions = new[] + { + new Dimension(), + new Dimension(mode: GridSizeMode.Relative, size: 0.4f), + new Dimension(), + }; + + Content = new[] + { + new Drawable[] + { + left = new Box + { + RelativeSizeAxes = Axes.Both, + }, + middle = new Box + { + RelativeSizeAxes = Axes.Both, + }, + right = new Box + { + RelativeSizeAxes = Axes.Both, + }, + } + }; + } + + protected override void LoadComplete() + { + MainColour.BindValueChanged(onColourChanged, true); + base.LoadComplete(); + } + + private void onColourChanged(ValueChangedEvent colour) + { + left.Colour = ColourInfo.GradientHorizontal(colour.NewValue.Opacity(0), colour.NewValue); + middle.Colour = colour.NewValue; + right.Colour = ColourInfo.GradientHorizontal(colour.NewValue, colour.NewValue.Opacity(0)); + } + } + } +} diff --git a/osu.Game/Graphics/UserInterface/PageTabControl.cs b/osu.Game/Graphics/UserInterface/PageTabControl.cs index a0d3745180..ddcb626701 100644 --- a/osu.Game/Graphics/UserInterface/PageTabControl.cs +++ b/osu.Game/Graphics/UserInterface/PageTabControl.cs @@ -63,7 +63,7 @@ namespace osu.Game.Graphics.UserInterface Margin = new MarginPadding { Top = 8, Bottom = 8 }, Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, - Text = (value as Enum)?.GetDescription() ?? value.ToString(), + Text = CreateText(), Font = OsuFont.GetFont(size: 14) }, box = new Box @@ -81,6 +81,8 @@ namespace osu.Game.Graphics.UserInterface Active.BindValueChanged(active => Text.Font = Text.Font.With(Typeface.Exo, weight: active.NewValue ? FontWeight.Bold : FontWeight.Medium), true); } + protected virtual string CreateText() => (Value as Enum)?.GetDescription() ?? Value.ToString(); + protected override bool OnHover(HoverEvent e) { if (!Active.Value) diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs index dcd58db427..e2a725ec46 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs @@ -1,60 +1,37 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Graphics.UserInterface; using osu.Game.Screens.Select.Leaderboards; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osuTK; using osu.Game.Graphics.UserInterface; -using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Framework.Allocation; using osuTK.Graphics; -using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; +using osu.Framework.Graphics; namespace osu.Game.Overlays.BeatmapSet { - public class LeaderboardScopeSelector : PageTabControl + public class LeaderboardScopeSelector : GradientLineTabControl { protected override bool AddEnumEntriesAutomatically => false; - protected override Dropdown CreateDropdown() => null; - protected override TabItem CreateTabItem(BeatmapLeaderboardScope value) => new ScopeSelectorTabItem(value); public LeaderboardScopeSelector() { - RelativeSizeAxes = Axes.X; - AddItem(BeatmapLeaderboardScope.Global); AddItem(BeatmapLeaderboardScope.Country); AddItem(BeatmapLeaderboardScope.Friend); - - AddInternal(new GradientLine - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - }); } [BackgroundDependencyLoader] private void load(OsuColour colours) { AccentColour = colours.Blue; + LineColour = Color4.Gray; } - protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - AutoSizeAxes = Axes.X, - RelativeSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(20, 0), - }; - private class ScopeSelectorTabItem : PageTabItem { public ScopeSelectorTabItem(BeatmapLeaderboardScope value) @@ -77,43 +54,5 @@ namespace osu.Game.Overlays.BeatmapSet Text.FadeColour(Color4.White); } } - - private class GradientLine : GridContainer - { - public GradientLine() - { - RelativeSizeAxes = Axes.X; - Size = new Vector2(0.8f, 1.5f); - - ColumnDimensions = new[] - { - new Dimension(), - new Dimension(mode: GridSizeMode.Relative, size: 0.4f), - new Dimension(), - }; - - Content = new[] - { - new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(Color4.Transparent, Color4.Gray), - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Gray, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(Color4.Gray, Color4.Transparent), - }, - } - }; - } - } } } diff --git a/osu.Game/Overlays/Rankings/HeaderFlag.cs b/osu.Game/Overlays/Rankings/HeaderFlag.cs new file mode 100644 index 0000000000..6f641c74a5 --- /dev/null +++ b/osu.Game/Overlays/Rankings/HeaderFlag.cs @@ -0,0 +1,55 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Framework.Graphics.Sprites; +using osu.Game.Users.Drawables; +using osuTK.Graphics; +using osuTK; +using osu.Framework.Input.Events; +using System; + +namespace osu.Game.Overlays.Rankings +{ + public class HeaderFlag : UpdateableFlag + { + private const int duration = 200; + + public Action Action; + + private readonly SpriteIcon hoverIcon; + + public HeaderFlag() + { + AddInternal(hoverIcon = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Depth = -1, + Alpha = 0, + Size = new Vector2(10), + Icon = FontAwesome.Solid.Times, + }); + } + + protected override bool OnHover(HoverEvent e) + { + hoverIcon.FadeIn(duration, Easing.OutQuint); + this.FadeColour(Color4.Gray, duration, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + base.OnHoverLost(e); + hoverIcon.FadeOut(duration, Easing.OutQuint); + this.FadeColour(Color4.White, duration, Easing.OutQuint); + } + + protected override bool OnClick(ClickEvent e) + { + Action?.Invoke(); + return true; + } + } +} diff --git a/osu.Game/Overlays/Rankings/HeaderTitle.cs b/osu.Game/Overlays/Rankings/HeaderTitle.cs new file mode 100644 index 0000000000..3f1feb10b8 --- /dev/null +++ b/osu.Game/Overlays/Rankings/HeaderTitle.cs @@ -0,0 +1,105 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Users; +using osu.Framework.Graphics; +using osuTK; +using osu.Game.Graphics; +using osu.Framework.Allocation; + +namespace osu.Game.Overlays.Rankings +{ + public class HeaderTitle : CompositeDrawable + { + private const int spacing = 10; + private const int flag_margin = 5; + private const int text_size = 40; + + public readonly Bindable Scope = new Bindable(); + public readonly Bindable Country = new Bindable(); + + private readonly SpriteText scopeText; + private readonly Container flagPlaceholder; + private readonly HeaderFlag flag; + + public HeaderTitle() + { + AutoSizeAxes = Axes.Both; + InternalChild = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(spacing, 0), + Children = new Drawable[] + { + flagPlaceholder = new Container + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Bottom = flag_margin }, + Child = flag = new HeaderFlag + { + Size = new Vector2(30, 20), + }, + }, + scopeText = new SpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Light) + }, + new SpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Light), + Text = @"Ranking" + } + } + }; + + flag.Action += () => Country.Value = null; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + scopeText.Colour = colours.Lime; + } + + protected override void LoadComplete() + { + Scope.BindValueChanged(scope => onScopeChanged(scope.NewValue), true); + Country.BindValueChanged(onCountryChanged, true); + base.LoadComplete(); + } + + private void onScopeChanged(RankingsScope scope) + { + scopeText.Text = scope.ToString(); + + if (scope != RankingsScope.Performance) + Country.Value = null; + } + + private void onCountryChanged(ValueChangedEvent country) + { + if (country.NewValue == null) + { + flagPlaceholder.Hide(); + return; + } + + Scope.Value = RankingsScope.Performance; + + if (country.OldValue == null) + flagPlaceholder.Show(); + + flag.Country = country.NewValue; + } + } +} diff --git a/osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs b/osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs new file mode 100644 index 0000000000..3d25e3995a --- /dev/null +++ b/osu.Game/Overlays/Rankings/RankingsRulesetSelector.cs @@ -0,0 +1,56 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.UserInterface; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; +using osu.Game.Rulesets; +using osuTK; +using System.Linq; + +namespace osu.Game.Overlays.Rankings +{ + public class RankingsRulesetSelector : PageTabControl + { + protected override TabItem CreateTabItem(RulesetInfo value) => new RankingsTabItem(value); + + protected override Dropdown CreateDropdown() => null; + + public RankingsRulesetSelector() + { + AutoSizeAxes = Axes.X; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours, RulesetStore rulesets) + { + foreach (var r in rulesets.AvailableRulesets) + AddItem(r); + + AccentColour = colours.Lime; + + SelectTab(TabContainer.FirstOrDefault()); + } + + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer + { + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(20, 0), + }; + + private class RankingsTabItem : PageTabItem + { + public RankingsTabItem(RulesetInfo value) + : base(value) + { + } + + protected override string CreateText() => $"{Value.Name}"; + } + } +} diff --git a/osu.Game/Overlays/Rankings/RankingsScopeSelector.cs b/osu.Game/Overlays/Rankings/RankingsScopeSelector.cs new file mode 100644 index 0000000000..2095bcc61c --- /dev/null +++ b/osu.Game/Overlays/Rankings/RankingsScopeSelector.cs @@ -0,0 +1,26 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Graphics.UserInterface; +using osu.Framework.Allocation; +using osuTK.Graphics; + +namespace osu.Game.Overlays.Rankings +{ + public class RankingsScopeSelector : GradientLineTabControl + { + [BackgroundDependencyLoader] + private void load() + { + AccentColour = LineColour = Color4.Black; + } + } + + public enum RankingsScope + { + Performance, + Spotlights, + Score, + Country + } +} From 0c6c8fdcd0e97e74979ae9d248241050f0bf5149 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Sep 2019 05:53:18 +0300 Subject: [PATCH 112/239] Implement RankingsHeader component --- .../Visual/Online/TestSceneRankingsHeader.cs | 52 ++++++++++++ osu.Game/Overlays/Rankings/RankingsHeader.cs | 84 +++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs create mode 100644 osu.Game/Overlays/Rankings/RankingsHeader.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs new file mode 100644 index 0000000000..81534e7d44 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs @@ -0,0 +1,52 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Overlays.Rankings; +using osu.Game.Rulesets; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsHeader : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(HeaderFlag), + typeof(HeaderTitle), + typeof(RankingsRulesetSelector), + typeof(RankingsScopeSelector), + typeof(RankingsHeader), + }; + + public TestSceneRankingsHeader() + { + var countryBindable = new Bindable(); + var ruleset = new Bindable(); + var scope = new Bindable(); + + Add(new RankingsHeader + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scope = { BindTarget = scope }, + Country = { BindTarget = countryBindable }, + Ruleset = { BindTarget = ruleset }, + }); + + var country = new Country + { + FlagName = "BY", + FullName = "Belarus" + }; + + AddStep("Set country", () => countryBindable.Value = country); + AddAssert("Check scope is Performance", () => scope.Value == RankingsScope.Performance); + AddStep("Set scope to Score", () => scope.Value = RankingsScope.Score); + AddAssert("Check country is Null", () => countryBindable.Value == null); + } + } +} diff --git a/osu.Game/Overlays/Rankings/RankingsHeader.cs b/osu.Game/Overlays/Rankings/RankingsHeader.cs new file mode 100644 index 0000000000..7fdc2ab9c8 --- /dev/null +++ b/osu.Game/Overlays/Rankings/RankingsHeader.cs @@ -0,0 +1,84 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Framework.Bindables; +using osu.Game.Rulesets; +using osu.Game.Users; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; + +namespace osu.Game.Overlays.Rankings +{ + public class RankingsHeader : CompositeDrawable + { + private const int content_height = 250; + + public readonly Bindable Scope = new Bindable(); + public readonly Bindable Ruleset = new Bindable(); + public readonly Bindable Country = new Bindable(); + + public RankingsHeader() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + AddInternal(new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new RankingsRulesetSelector + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Current = { BindTarget = Ruleset } + }, + new Container + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + Height = content_height, + Children = new Drawable[] + { + new HeaderBackground(), + new RankingsScopeSelector + { + Margin = new MarginPadding { Top = 10 }, + Current = { BindTarget = Scope } + }, + new HeaderTitle + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Scope = { BindTarget = Scope }, + Country = { BindTarget = Country }, + } + } + } + } + }); + } + + public class HeaderBackground : Sprite + { + public HeaderBackground() + { + RelativeSizeAxes = Axes.Both; + FillMode = FillMode.Fill; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + Texture = textures.Get(@"Headers/rankings"); + } + } + } +} From acdd26422dc4c006f88b2eb0028113622b23a4ad Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Sep 2019 06:36:17 +0300 Subject: [PATCH 113/239] Implement Spotlights logic --- .../Visual/Online/TestSceneRankingsHeader.cs | 18 +++++ osu.Game/Overlays/Rankings/RankingsHeader.cs | 74 +++++++++++++++++-- osu.Game/Overlays/Rankings/Spotlight.cs | 18 +++++ 3 files changed, 102 insertions(+), 8 deletions(-) create mode 100644 osu.Game/Overlays/Rankings/Spotlight.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs index 81534e7d44..e8ed94b59c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs @@ -35,6 +35,24 @@ namespace osu.Game.Tests.Visual.Online Scope = { BindTarget = scope }, Country = { BindTarget = countryBindable }, Ruleset = { BindTarget = ruleset }, + Spotlights = new[] + { + new Spotlight + { + Id = 1, + Text = "Spotlight 1" + }, + new Spotlight + { + Id = 2, + Text = "Spotlight 2" + }, + new Spotlight + { + Id = 3, + Text = "Spotlight 4" + } + } }); var country = new Country diff --git a/osu.Game/Overlays/Rankings/RankingsHeader.cs b/osu.Game/Overlays/Rankings/RankingsHeader.cs index 7fdc2ab9c8..6d55e92502 100644 --- a/osu.Game/Overlays/Rankings/RankingsHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsHeader.cs @@ -4,23 +4,38 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osu.Framework.Allocation; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; using osu.Framework.Bindables; using osu.Game.Rulesets; using osu.Game.Users; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osuTK; +using osu.Game.Graphics.UserInterface; +using System.Collections.Generic; namespace osu.Game.Overlays.Rankings { public class RankingsHeader : CompositeDrawable { private const int content_height = 250; + private const int dropdown_height = 50; + private const int spacing = 20; + private const int title_offset = 30; + private const int duration = 200; + + public IEnumerable Spotlights + { + get => dropdown.Items; + set => dropdown.Items = value; + } public readonly Bindable Scope = new Bindable(); public readonly Bindable Ruleset = new Bindable(); public readonly Bindable Country = new Bindable(); + public readonly Bindable Spotlight = new Bindable(); + + private readonly Container dropdownPlaceholder; + private readonly OsuDropdown dropdown; public RankingsHeader() { @@ -47,29 +62,72 @@ namespace osu.Game.Overlays.Rankings Height = content_height, Children = new Drawable[] { - new HeaderBackground(), + new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + Child = new HeaderBackground(), + }, new RankingsScopeSelector { Margin = new MarginPadding { Top = 10 }, Current = { BindTarget = Scope } }, - new HeaderTitle + new FillFlowContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Scope = { BindTarget = Scope }, - Country = { BindTarget = Country }, - } + Y = title_offset, + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, spacing), + Children = new Drawable[] + { + new HeaderTitle + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Scope = { BindTarget = Scope }, + Country = { BindTarget = Country }, + }, + dropdownPlaceholder = new Container + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + Height = dropdown_height, + Width = 0.8f, + AlwaysPresent = true, + Child = dropdown = new OsuDropdown + { + RelativeSizeAxes = Axes.X, + Current = { BindTarget = Spotlight }, + } + } + } + }, } } } }); } - public class HeaderBackground : Sprite + protected override void LoadComplete() + { + Scope.BindValueChanged(scope => onScopeChanged(scope.NewValue), true); + base.LoadComplete(); + } + + private void onScopeChanged(RankingsScope scope) => + dropdownPlaceholder.FadeTo(scope == RankingsScope.Spotlights ? 1 : 0, duration, Easing.OutQuint); + + private class HeaderBackground : Sprite { public HeaderBackground() { + Anchor = Anchor.Centre; + Origin = Anchor.Centre; RelativeSizeAxes = Axes.Both; FillMode = FillMode.Fill; } diff --git a/osu.Game/Overlays/Rankings/Spotlight.cs b/osu.Game/Overlays/Rankings/Spotlight.cs new file mode 100644 index 0000000000..e956b4f449 --- /dev/null +++ b/osu.Game/Overlays/Rankings/Spotlight.cs @@ -0,0 +1,18 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Newtonsoft.Json; + +namespace osu.Game.Overlays.Rankings +{ + public class Spotlight + { + [JsonProperty("id")] + public int Id; + + [JsonProperty("text")] + public string Text; + + public override string ToString() => Text; + } +} From b1c0b080ecced55aecae5aa4f28078418d8ecbd7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Sep 2019 13:52:27 +0900 Subject: [PATCH 114/239] Fix bad hit explosion anchoring --- osu.Game.Rulesets.Mania/UI/Column.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index fa14a0a293..8021660f77 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -11,6 +11,8 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Input.Bindings; using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mania.Objects.Drawables; +using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Mania.UI.Components; using osu.Game.Rulesets.UI.Scrolling; using osuTK; @@ -90,7 +92,11 @@ namespace osu.Game.Rulesets.Mania.UI Bottom = dir.NewValue == ScrollingDirection.Down ? ManiaStage.HIT_TARGET_POSITION : 0, }; - explosionContainer.Y = dir.NewValue == ScrollingDirection.Down ? -NotePiece.NOTE_HEIGHT : 0; + explosionContainer.Padding = new MarginPadding + { + Top = dir.NewValue == ScrollingDirection.Up ? NotePiece.NOTE_HEIGHT / 2 : 0, + Bottom = dir.NewValue == ScrollingDirection.Down ? NotePiece.NOTE_HEIGHT / 2 : 0 + }; keyArea.Anchor = keyArea.Origin = dir.NewValue == ScrollingDirection.Up ? Anchor.TopLeft : Anchor.BottomLeft; }, true); @@ -168,7 +174,7 @@ namespace osu.Game.Rulesets.Mania.UI explosionContainer.Add(new HitExplosion(judgedObject.AccentColour.Value, judgedObject is DrawableHoldNoteTick) { Anchor = Direction.Value == ScrollingDirection.Up ? Anchor.TopCentre : Anchor.BottomCentre, - Origin = Direction.Value == ScrollingDirection.Up ? Anchor.BottomCentre : Anchor.TopCentre, + Origin = Anchor.Centre }); } From bbf80f63aa920b3a86b51142cd2b54d782fe5182 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Sep 2019 13:53:05 +0900 Subject: [PATCH 115/239] Publicly expose column width constant --- osu.Game.Rulesets.Mania/UI/Column.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 8021660f77..910342a3b0 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Mania.UI { public class Column : ScrollingPlayfield, IKeyBindingHandler, IHasAccentColour { - private const float column_width = 45; + public const float COLUMN_WIDTH = 45; private const float special_column_width = 70; /// @@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Mania.UI Index = index; RelativeSizeAxes = Axes.Y; - Width = column_width; + Width = COLUMN_WIDTH; Masking = true; CornerRadius = 5; @@ -116,7 +116,7 @@ namespace osu.Game.Rulesets.Mania.UI isSpecial = value; - Width = isSpecial ? special_column_width : column_width; + Width = isSpecial ? special_column_width : COLUMN_WIDTH; } } From f9c969788a758f913001047dca99aff00a853de8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Sep 2019 13:56:23 +0900 Subject: [PATCH 116/239] Fix keys not reaching full brightness as soon as they should --- osu.Game/Screens/Play/KeyCounter.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 88a62ac8d4..ad5fcfcf24 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -130,15 +130,17 @@ namespace osu.Game.Screens.Play private void updateGlowSprite(bool show) { + double remainingFadeTime = FadeTime * (1 - glowSprite.Alpha); + if (show) { - glowSprite.FadeIn(FadeTime); - textLayer.FadeColour(KeyDownTextColor, FadeTime); + glowSprite.FadeIn(remainingFadeTime); + textLayer.FadeColour(KeyDownTextColor, remainingFadeTime); } else { - glowSprite.FadeOut(FadeTime); - textLayer.FadeColour(KeyUpTextColor, FadeTime); + glowSprite.FadeOut(remainingFadeTime); + textLayer.FadeColour(KeyUpTextColor, remainingFadeTime); } } From b941f12688eb2bb309e8d37cd3fc5f29beb582a1 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 12 Sep 2019 14:09:21 +0900 Subject: [PATCH 117/239] Cleanup --- .../TestSceneHitExplosion.cs | 22 ------------------- osu.Game.Rulesets.Mania/UI/HitExplosion.cs | 8 ++----- 2 files changed, 2 insertions(+), 28 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneHitExplosion.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneHitExplosion.cs index 12159ca239..26a1b1b1ec 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneHitExplosion.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneHitExplosion.cs @@ -5,11 +5,9 @@ using System; using System.Collections.Generic; using NUnit.Framework; using osu.Framework.Graphics; -using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Mania.UI; -using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Tests.Visual; using osuTK; @@ -60,25 +58,5 @@ namespace osu.Game.Rulesets.Mania.Tests }); }, 100); } - - private class TestNote : DrawableNote - { - protected override void CheckForResult(bool userTriggered, double timeOffset) - { - if (!userTriggered) - { - // force success - ApplyResult(r => r.Type = HitResult.Great); - } - else - base.CheckForResult(userTriggered, timeOffset); - } - - public TestNote(Note hitObject) - : base(hitObject) - { - AccentColour.Value = Color4.Pink; - } - } } } diff --git a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs index 21726206f1..ccbff226a9 100644 --- a/osu.Game.Rulesets.Mania/UI/HitExplosion.cs +++ b/osu.Game.Rulesets.Mania/UI/HitExplosion.cs @@ -18,8 +18,6 @@ namespace osu.Game.Rulesets.Mania.UI private readonly CircularContainer largeFaint; private readonly CircularContainer mainGlow1; - private readonly CircularContainer mainGlow2; - private readonly CircularContainer mainGlow3; public HitExplosion(Color4 objectColour, bool isSmall = false) { @@ -36,8 +34,6 @@ namespace osu.Game.Rulesets.Mania.UI const float roundness = 80; - const float opacity = 1; - const float initial_height = 10; var colour = Interpolation.ValueAt(0.4f, objectColour, Color4.White, 0, 1); @@ -76,7 +72,7 @@ namespace osu.Game.Rulesets.Mania.UI Radius = 50, }, }, - mainGlow2 = new CircularContainer + new CircularContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -93,7 +89,7 @@ namespace osu.Game.Rulesets.Mania.UI Radius = 40, }, }, - mainGlow3 = new CircularContainer + new CircularContainer { Anchor = Anchor.Centre, Origin = Anchor.Centre, From 158737e001e46bdfd4f8ed85a48ab53ba81f70a9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Sep 2019 14:27:29 +0900 Subject: [PATCH 118/239] Remove FadeTime customisation Also adjusts fade transitions to feel better, especially in fast forward scenarios. --- .../Visual/Gameplay/TestSceneKeyCounter.cs | 1 - osu.Game/Screens/Play/HUDOverlay.cs | 1 - osu.Game/Screens/Play/KeyCounter.cs | 14 +++++------ osu.Game/Screens/Play/KeyCounterDisplay.cs | 25 ++----------------- 4 files changed, 9 insertions(+), 32 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index 18088a9a5b..4643b82792 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -44,7 +44,6 @@ namespace osu.Game.Tests.Visual.Gameplay Key key = (Key)((int)Key.A + RNG.Next(26)); kc.Add(new KeyCounterKeyboard(key)); }); - AddSliderStep("Fade time", 0, 200, 50, v => kc.FadeTime = v); Key testKey = ((KeyCounterKeyboard)kc.Children.First()).Key; double time1 = 0; diff --git a/osu.Game/Screens/Play/HUDOverlay.cs b/osu.Game/Screens/Play/HUDOverlay.cs index eee7235a6e..0f9edf5606 100644 --- a/osu.Game/Screens/Play/HUDOverlay.cs +++ b/osu.Game/Screens/Play/HUDOverlay.cs @@ -231,7 +231,6 @@ namespace osu.Game.Screens.Play protected virtual KeyCounterDisplay CreateKeyCounter() => new KeyCounterDisplay { - FadeTime = 50, Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, Margin = new MarginPadding(10), diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index ad5fcfcf24..1930369299 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -65,7 +65,7 @@ namespace osu.Game.Screens.Play //further: change default values here and in KeyCounterCollection if needed, instead of passing them in every constructor public Color4 KeyDownTextColor { get; set; } = Color4.DarkGray; public Color4 KeyUpTextColor { get; set; } = Color4.White; - public int FadeTime { get; set; } + public double FadeTime { get; set; } protected KeyCounter(string name) { @@ -130,17 +130,17 @@ namespace osu.Game.Screens.Play private void updateGlowSprite(bool show) { - double remainingFadeTime = FadeTime * (1 - glowSprite.Alpha); - if (show) { - glowSprite.FadeIn(remainingFadeTime); - textLayer.FadeColour(KeyDownTextColor, remainingFadeTime); + double remainingFadeTime = FadeTime * (1 - glowSprite.Alpha); + glowSprite.FadeIn(remainingFadeTime, Easing.OutQuint); + textLayer.FadeColour(KeyDownTextColor, remainingFadeTime, Easing.OutQuint); } else { - glowSprite.FadeOut(remainingFadeTime); - textLayer.FadeColour(KeyUpTextColor, remainingFadeTime); + double remainingFadeTime = 8 * FadeTime * glowSprite.Alpha; + glowSprite.FadeOut(remainingFadeTime, Easing.OutQuint); + textLayer.FadeColour(KeyUpTextColor, remainingFadeTime, Easing.OutQuint); } } diff --git a/osu.Game/Screens/Play/KeyCounterDisplay.cs b/osu.Game/Screens/Play/KeyCounterDisplay.cs index d5967f5899..6b8fa5c75b 100644 --- a/osu.Game/Screens/Play/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/KeyCounterDisplay.cs @@ -17,6 +17,7 @@ namespace osu.Game.Screens.Play public class KeyCounterDisplay : FillFlowContainer { private const int duration = 100; + private const double key_fade_time = 80; public readonly Bindable Visible = new Bindable(true); private readonly Bindable configVisibility = new Bindable(); @@ -33,17 +34,11 @@ namespace osu.Game.Screens.Play base.Add(key); key.IsCounting = IsCounting; - key.FadeTime = FadeTime; + key.FadeTime = key_fade_time; key.KeyDownTextColor = KeyDownTextColor; key.KeyUpTextColor = KeyUpTextColor; } - public void ResetCount() - { - foreach (var counter in Children) - counter.ResetCount(); - } - [BackgroundDependencyLoader] private void load(OsuConfigManager config) { @@ -68,22 +63,6 @@ namespace osu.Game.Screens.Play } } - private int fadeTime; - - public int FadeTime - { - get => fadeTime; - set - { - if (value != fadeTime) - { - fadeTime = value; - foreach (var child in Children) - child.FadeTime = value; - } - } - } - private Color4 keyDownTextColor = Color4.DarkGray; public Color4 KeyDownTextColor From cb0cf6e2c5e14e37d37716a79cec9b02b89d2aae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Sep 2019 14:27:52 +0900 Subject: [PATCH 119/239] Remove reset functions --- osu.Game/Screens/Play/KeyCounter.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 1930369299..ad0858184e 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -144,12 +144,6 @@ namespace osu.Game.Screens.Play } } - public void ResetCount() - { - CountPresses = 0; - states.Clear(); - } - protected override void Update() { base.Update(); From 0cdf125c1e8f64fc5397fc1701e42cb21d1adaf2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Sep 2019 15:41:53 +0900 Subject: [PATCH 120/239] Handle key counter rewinding in a better way Use ElapsedFrameTime rather than storing state data --- .../Visual/Gameplay/TestSceneKeyCounter.cs | 40 ++------------- osu.Game/Rulesets/UI/RulesetInputManager.cs | 4 +- osu.Game/Screens/Play/KeyCounter.cs | 49 ++++++------------- osu.Game/Screens/Play/KeyCounterAction.cs | 22 ++++++--- osu.Game/Screens/Play/KeyCounterDisplay.cs | 5 -- osu.Game/Screens/Play/KeyCounterKeyboard.cs | 7 ++- osu.Game/Screens/Play/KeyCounterMouse.cs | 7 ++- 7 files changed, 50 insertions(+), 84 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index 4643b82792..6783a36ac3 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -7,7 +7,6 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.MathUtils; -using osu.Framework.Timing; using osu.Game.Screens.Play; using osuTK.Input; @@ -25,14 +24,15 @@ namespace osu.Game.Tests.Visual.Gameplay public TestSceneKeyCounter() { - KeyCounterKeyboard rewindTestKeyCounterKeyboard; + KeyCounterKeyboard testCounter; + KeyCounterDisplay kc = new KeyCounterDisplay { Origin = Anchor.Centre, Anchor = Anchor.Centre, Children = new KeyCounter[] { - rewindTestKeyCounterKeyboard = new KeyCounterKeyboard(Key.X), + testCounter = new KeyCounterKeyboard(Key.X), new KeyCounterKeyboard(Key.X), new KeyCounterMouse(MouseButton.Left), new KeyCounterMouse(MouseButton.Right), @@ -54,7 +54,7 @@ namespace osu.Game.Tests.Visual.Gameplay InputManager.ReleaseKey(testKey); }); - AddAssert($"Check {testKey} counter after keypress", () => rewindTestKeyCounterKeyboard.CountPresses == 1); + AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 1); AddStep($"Press {testKey} key", () => { @@ -63,39 +63,9 @@ namespace osu.Game.Tests.Visual.Gameplay time1 = Clock.CurrentTime; }); - AddAssert($"Check {testKey} counter after keypress", () => rewindTestKeyCounterKeyboard.CountPresses == 2); - - IFrameBasedClock oldClock = null; - - AddStep($"Rewind {testKey} counter once", () => - { - oldClock = rewindTestKeyCounterKeyboard.Clock; - rewindTestKeyCounterKeyboard.Clock = new FramedOffsetClock(new FixedClock(time1 - 10)); - }); - - AddAssert($"Check {testKey} counter after rewind", () => rewindTestKeyCounterKeyboard.CountPresses == 1); - - AddStep($"Rewind {testKey} counter to zero", () => rewindTestKeyCounterKeyboard.Clock = new FramedOffsetClock(new FixedClock(0))); - - AddAssert($"Check {testKey} counter after rewind", () => rewindTestKeyCounterKeyboard.CountPresses == 0); - - AddStep("Restore clock", () => rewindTestKeyCounterKeyboard.Clock = oldClock); + AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 2); Add(kc); } - - private class FixedClock : IClock - { - private readonly double time; - - public FixedClock(double time) - { - this.time = time; - } - - public double CurrentTime => time; - public double Rate => 1; - public bool IsRunning => false; - } } } diff --git a/osu.Game/Rulesets/UI/RulesetInputManager.cs b/osu.Game/Rulesets/UI/RulesetInputManager.cs index e25c3bd0e7..98e27240d3 100644 --- a/osu.Game/Rulesets/UI/RulesetInputManager.cs +++ b/osu.Game/Rulesets/UI/RulesetInputManager.cs @@ -137,9 +137,9 @@ namespace osu.Game.Rulesets.UI { } - public bool OnPressed(T action) => Target.Children.OfType>().Any(c => c.OnPressed(action)); + public bool OnPressed(T action) => Target.Children.OfType>().Any(c => c.OnPressed(action, Clock.ElapsedFrameTime > 0)); - public bool OnReleased(T action) => Target.Children.OfType>().Any(c => c.OnReleased(action)); + public bool OnReleased(T action) => Target.Children.OfType>().Any(c => c.OnReleased(action, Clock.ElapsedFrameTime > 0)); } #endregion diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index ad0858184e..1daf89d8f9 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -1,8 +1,6 @@ // Copyright (c) ppy Pty Ltd . 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 osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -22,9 +20,6 @@ namespace osu.Game.Screens.Play private Container textLayer; private SpriteText countSpriteText; - private readonly List states = new List(); - private KeyCounterState currentState; - public bool IsCounting { get; set; } = true; private int countPresses; @@ -52,16 +47,26 @@ namespace osu.Game.Screens.Play { isLit = value; updateGlowSprite(value); - - if (value && IsCounting) - { - CountPresses++; - saveState(); - } } } } + public void Increment() + { + if (!IsCounting) + return; + + CountPresses++; + } + + public void Decrement() + { + if (!IsCounting) + return; + + CountPresses--; + } + //further: change default values here and in KeyCounterCollection if needed, instead of passing them in every constructor public Color4 KeyDownTextColor { get; set; } = Color4.DarkGray; public Color4 KeyUpTextColor { get; set; } = Color4.White; @@ -143,27 +148,5 @@ namespace osu.Game.Screens.Play textLayer.FadeColour(KeyUpTextColor, remainingFadeTime, Easing.OutQuint); } } - - protected override void Update() - { - base.Update(); - - if (currentState?.Time > Clock.CurrentTime) - restoreStateTo(Clock.CurrentTime); - } - - private void saveState() - { - if (currentState == null || currentState.Time < Clock.CurrentTime) - states.Add(currentState = new KeyCounterState(Clock.CurrentTime, CountPresses)); - } - - private void restoreStateTo(double time) - { - states.RemoveAll(state => state.Time > time); - - currentState = states.LastOrDefault(); - CountPresses = currentState?.Count ?? 0; - } } } diff --git a/osu.Game/Screens/Play/KeyCounterAction.cs b/osu.Game/Screens/Play/KeyCounterAction.cs index 8deac653ad..f60ad7aa5a 100644 --- a/osu.Game/Screens/Play/KeyCounterAction.cs +++ b/osu.Game/Screens/Play/KeyCounterAction.cs @@ -1,11 +1,9 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Input.Bindings; - namespace osu.Game.Screens.Play { - public class KeyCounterAction : KeyCounter, IKeyBindingHandler + public class KeyCounterAction : KeyCounter where T : struct { public T Action { get; } @@ -16,15 +14,25 @@ namespace osu.Game.Screens.Play Action = action; } - public bool OnPressed(T action) + public bool OnPressed(T action, bool forwards) { - if (action.Equals(Action)) IsLit = true; + if (!action.Equals(Action)) + return false; + + IsLit = true; + if (forwards) + Increment(); return false; } - public bool OnReleased(T action) + public bool OnReleased(T action, bool forwards) { - if (action.Equals(Action)) IsLit = false; + if (!action.Equals(Action)) + return false; + + IsLit = false; + if (!forwards) + Decrement(); return false; } } diff --git a/osu.Game/Screens/Play/KeyCounterDisplay.cs b/osu.Game/Screens/Play/KeyCounterDisplay.cs index 6b8fa5c75b..1edb95ca46 100644 --- a/osu.Game/Screens/Play/KeyCounterDisplay.cs +++ b/osu.Game/Screens/Play/KeyCounterDisplay.cs @@ -102,11 +102,6 @@ namespace osu.Game.Screens.Play private Receptor receptor; - public Receptor GetReceptor() - { - return receptor ?? (receptor = new Receptor(this)); - } - public void SetReceptor(Receptor receptor) { if (this.receptor != null) diff --git a/osu.Game/Screens/Play/KeyCounterKeyboard.cs b/osu.Game/Screens/Play/KeyCounterKeyboard.cs index d9b6dca79d..29188b6b59 100644 --- a/osu.Game/Screens/Play/KeyCounterKeyboard.cs +++ b/osu.Game/Screens/Play/KeyCounterKeyboard.cs @@ -18,7 +18,12 @@ namespace osu.Game.Screens.Play protected override bool OnKeyDown(KeyDownEvent e) { - if (e.Key == Key) IsLit = true; + if (e.Key == Key) + { + IsLit = true; + Increment(); + } + return base.OnKeyDown(e); } diff --git a/osu.Game/Screens/Play/KeyCounterMouse.cs b/osu.Game/Screens/Play/KeyCounterMouse.cs index 95fa58e5c0..828441de6e 100644 --- a/osu.Game/Screens/Play/KeyCounterMouse.cs +++ b/osu.Game/Screens/Play/KeyCounterMouse.cs @@ -36,7 +36,12 @@ namespace osu.Game.Screens.Play protected override bool OnMouseDown(MouseDownEvent e) { - if (e.Button == Button) IsLit = true; + if (e.Button == Button) + { + IsLit = true; + Increment(); + } + return base.OnMouseDown(e); } From 831d04f339402020b0467bd38a7b940ab8031638 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Sep 2019 15:48:07 +0900 Subject: [PATCH 121/239] Don't use gameplay clock in KeyCounter --- osu.Game/Screens/Play/KeyCounter.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Screens/Play/KeyCounter.cs b/osu.Game/Screens/Play/KeyCounter.cs index 1daf89d8f9..f4109a63d0 100644 --- a/osu.Game/Screens/Play/KeyCounter.cs +++ b/osu.Game/Screens/Play/KeyCounter.cs @@ -78,11 +78,8 @@ namespace osu.Game.Screens.Play } [BackgroundDependencyLoader(true)] - private void load(TextureStore textures, GameplayClock clock) + private void load(TextureStore textures) { - if (clock != null) - Clock = clock; - Children = new Drawable[] { buttonSprite = new Sprite From 09a0c9f4d2fa8224651ff91d05881fe31f118ac1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Sep 2019 18:10:50 +0900 Subject: [PATCH 122/239] Add key counter rewind tests --- osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs | 9 ++++++++- .../Visual/Gameplay/TestSceneGameplayRewinding.cs | 7 +++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs index 452ac859de..e2b620ea98 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs @@ -21,7 +21,12 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void AddCheckSteps() { AddUntilStep("score above zero", () => ((ScoreAccessiblePlayer)Player).ScoreProcessor.TotalScore.Value > 0); - AddUntilStep("key counter counted keys", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 0)); + AddUntilStep("key counter counted keys", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 5)); + AddStep("rewind", () => + { + ((ScoreAccessiblePlayer)Player).GameplayClockContainer.Seek(0); + }); + AddUntilStep("key counter counted no", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0)); } private class ScoreAccessiblePlayer : TestPlayer @@ -29,6 +34,8 @@ namespace osu.Game.Tests.Visual.Gameplay public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; public new HUDOverlay HUDOverlay => base.HUDOverlay; + public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer; + public ScoreAccessiblePlayer() : base(false, false) { diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs index 237fee1594..ffc025a942 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneGameplayRewinding.cs @@ -14,6 +14,7 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu.Objects; +using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; using osu.Game.Screens.Play; using osuTK; @@ -47,9 +48,11 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("wait for track to start running", () => track.IsRunning); addSeekStep(3000); AddAssert("all judged", () => player.DrawableRuleset.Playfield.AllHitObjects.All(h => h.Judged)); + AddUntilStep("key counter counted keys", () => player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses >= 7)); AddStep("clear results", () => player.AppliedResults.Clear()); addSeekStep(0); AddAssert("none judged", () => player.DrawableRuleset.Playfield.AllHitObjects.All(h => !h.Judged)); + AddUntilStep("key counters reset", () => player.HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0)); AddAssert("no results triggered", () => player.AppliedResults.Count == 0); } @@ -90,6 +93,10 @@ namespace osu.Game.Tests.Visual.Gameplay { public readonly List AppliedResults = new List(); + public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + + public new HUDOverlay HUDOverlay => base.HUDOverlay; + public new GameplayClockContainer GameplayClockContainer => base.GameplayClockContainer; public new DrawableRuleset DrawableRuleset => base.DrawableRuleset; From acdfeef1dc44fcacad192926163e71ced4adc1e9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Sep 2019 18:33:46 +0900 Subject: [PATCH 123/239] Improve how osu!catch stores and replays key actions --- .../Replays/CatchAutoGenerator.cs | 29 ++++++++++------ .../Replays/CatchFramedReplayInputHandler.cs | 15 ++------- .../Replays/CatchReplayFrame.cs | 33 ++++++++++++++++--- .../Replays/ManiaReplayFrame.cs | 2 +- .../Replays/OsuReplayFrame.cs | 8 ++--- .../Replays/TaikoReplayFrame.cs | 10 +++--- .../Replays/Types/IConvertibleReplayFrame.cs | 5 +-- osu.Game/Scoring/Legacy/LegacyScoreParser.cs | 15 ++++++--- 8 files changed, 74 insertions(+), 43 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index 8dd00756f2..4ea1f22006 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -27,6 +27,8 @@ namespace osu.Game.Rulesets.Catch.Replays protected Replay Replay; + private CatchReplayFrame currentFrame; + public override Replay Generate() { // todo: add support for HT DT @@ -36,7 +38,7 @@ namespace osu.Game.Rulesets.Catch.Replays double lastTime = 0; // Todo: Realistically this shouldn't be needed, but the first frame is skipped with the way replays are currently handled - Replay.Frames.Add(new CatchReplayFrame(-100000, lastPosition)); + addFrame(-100000, lastPosition); void moveToNext(CatchHitObject h) { @@ -58,18 +60,18 @@ namespace osu.Game.Rulesets.Catch.Replays { //we are already in the correct range. lastTime = h.StartTime; - Replay.Frames.Add(new CatchReplayFrame(h.StartTime, lastPosition)); + addFrame(h.StartTime, lastPosition); return; } if (impossibleJump) { - Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X)); + addFrame(h.StartTime, h.X); } else if (h.HyperDash) { - Replay.Frames.Add(new CatchReplayFrame(h.StartTime - timeAvailable, lastPosition)); - Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X)); + addFrame(h.StartTime - timeAvailable, lastPosition); + addFrame(h.StartTime, h.X); } else if (dashRequired) { @@ -81,16 +83,16 @@ namespace osu.Game.Rulesets.Catch.Replays float midPosition = (float)Interpolation.Lerp(lastPosition, h.X, (float)timeAtDashSpeed / timeAvailable); //dash movement - Replay.Frames.Add(new CatchReplayFrame(h.StartTime - timeAvailable + 1, lastPosition, true)); - Replay.Frames.Add(new CatchReplayFrame(h.StartTime - timeAvailable + timeAtDashSpeed, midPosition)); - Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X)); + addFrame(h.StartTime - timeAvailable + 1, lastPosition, true); + addFrame(h.StartTime - timeAvailable + timeAtDashSpeed, midPosition); + addFrame(h.StartTime, h.X); } else { double timeBefore = positionChange / movement_speed; - Replay.Frames.Add(new CatchReplayFrame(h.StartTime - timeBefore, lastPosition)); - Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X)); + addFrame(h.StartTime - timeBefore, lastPosition); + addFrame(h.StartTime, h.X); } lastTime = h.StartTime; @@ -122,5 +124,12 @@ namespace osu.Game.Rulesets.Catch.Replays return Replay; } + + private void addFrame(double time, float? position = null, bool dashing = false) + { + var last = currentFrame; + currentFrame = new CatchReplayFrame(time, position, dashing, last); + Replay.Frames.Add(currentFrame); + } } } diff --git a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs index 103aa6c3f1..22532bc9ec 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchFramedReplayInputHandler.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using osu.Framework.Input.StateChanges; using osu.Framework.MathUtils; using osu.Game.Replays; @@ -17,7 +18,7 @@ namespace osu.Game.Rulesets.Catch.Replays { } - protected override bool IsImportant(CatchReplayFrame frame) => frame.Position > 0; + protected override bool IsImportant(CatchReplayFrame frame) => frame.Actions.Any(); protected float? Position { @@ -38,21 +39,11 @@ namespace osu.Game.Rulesets.Catch.Replays { if (!Position.HasValue) return new List(); - var actions = new List(); - - if (CurrentFrame.Dashing) - actions.Add(CatchAction.Dash); - - if (Position.Value > CurrentFrame.Position) - actions.Add(CatchAction.MoveRight); - else if (Position.Value < CurrentFrame.Position) - actions.Add(CatchAction.MoveLeft); - return new List { new CatchReplayState { - PressedActions = actions, + PressedActions = CurrentFrame?.Actions ?? new List(), CatcherX = Position.Value }, }; diff --git a/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs b/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs index 1e88b35c3b..19637f321b 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Replays.Legacy; using osu.Game.Rulesets.Catch.UI; @@ -11,6 +12,8 @@ namespace osu.Game.Rulesets.Catch.Replays { public class CatchReplayFrame : ReplayFrame, IConvertibleReplayFrame { + public List Actions = new List(); + public float Position; public bool Dashing; @@ -18,17 +21,39 @@ namespace osu.Game.Rulesets.Catch.Replays { } - public CatchReplayFrame(double time, float? position = null, bool dashing = false) + public CatchReplayFrame(double time, float? position = null, bool dashing = false, CatchReplayFrame lastFrame = null) : base(time) { Position = position ?? -1; Dashing = dashing; + + if (Dashing) + Actions.Add(CatchAction.Dash); + + if (lastFrame != null) + { + if (Position > lastFrame.Position) + Actions.Add(CatchAction.MoveRight); + else if (Position < lastFrame.Position) + Actions.Add(CatchAction.MoveLeft); + } } - public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap) + public void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, LegacyReplayFrame lastFrame = null) { - Position = legacyFrame.Position.X / CatchPlayfield.BASE_WIDTH; - Dashing = legacyFrame.ButtonState == ReplayButtonState.Left1; + Position = currentFrame.Position.X / CatchPlayfield.BASE_WIDTH; + Dashing = currentFrame.ButtonState == ReplayButtonState.Left1; + + if (Dashing) + Actions.Add(CatchAction.Dash); + + if (lastFrame != null) + { + if (currentFrame.Position.X > lastFrame.Position.X) + Actions.Add(CatchAction.MoveRight); + else if (currentFrame.Position.X < lastFrame.Position.X) + Actions.Add(CatchAction.MoveLeft); + } } } } diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs index f7277d3669..b2901f46c0 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Mania.Replays Actions.AddRange(actions); } - public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap) + public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap, LegacyReplayFrame lastFrame = null) { // We don't need to fully convert, just create the converter var converter = new ManiaBeatmapConverter(beatmap); diff --git a/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs b/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs index 4d90fcadd5..441b69ef2d 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs @@ -26,11 +26,11 @@ namespace osu.Game.Rulesets.Osu.Replays Actions.AddRange(actions); } - public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap) + public void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, LegacyReplayFrame lastFrame = null) { - Position = legacyFrame.Position; - if (legacyFrame.MouseLeft) Actions.Add(OsuAction.LeftButton); - if (legacyFrame.MouseRight) Actions.Add(OsuAction.RightButton); + Position = currentFrame.Position; + if (currentFrame.MouseLeft) Actions.Add(OsuAction.LeftButton); + if (currentFrame.MouseRight) Actions.Add(OsuAction.RightButton); } } } diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs index 5203415e90..6e43892777 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs @@ -23,12 +23,12 @@ namespace osu.Game.Rulesets.Taiko.Replays Actions.AddRange(actions); } - public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap) + public void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, LegacyReplayFrame lastFrame = null) { - if (legacyFrame.MouseRight1) Actions.Add(TaikoAction.LeftRim); - if (legacyFrame.MouseRight2) Actions.Add(TaikoAction.RightRim); - if (legacyFrame.MouseLeft1) Actions.Add(TaikoAction.LeftCentre); - if (legacyFrame.MouseLeft2) Actions.Add(TaikoAction.RightCentre); + if (currentFrame.MouseRight1) Actions.Add(TaikoAction.LeftRim); + if (currentFrame.MouseRight2) Actions.Add(TaikoAction.RightRim); + if (currentFrame.MouseLeft1) Actions.Add(TaikoAction.LeftCentre); + if (currentFrame.MouseLeft2) Actions.Add(TaikoAction.RightCentre); } } } diff --git a/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs b/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs index 7ecdc0715b..8fcdec6630 100644 --- a/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs +++ b/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs @@ -14,8 +14,9 @@ namespace osu.Game.Rulesets.Replays.Types /// /// Populates this using values from a . /// - /// The to extract values from. + /// The to extract values from. /// The beatmap. - void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap); + /// The last , used to fill in missing delta information. May be null. + void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, LegacyReplayFrame lastFrame = null); } } diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index 2e4b4b3a9a..5a90daa045 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -218,6 +218,7 @@ namespace osu.Game.Scoring.Legacy private void readLegacyReplay(Replay replay, StreamReader reader) { float lastTime = 0; + LegacyReplayFrame currentFrame = null; foreach (var l in reader.ReadToEnd().Split(',')) { @@ -240,23 +241,27 @@ namespace osu.Game.Scoring.Legacy if (diff < 0) continue; - replay.Frames.Add(convertFrame(new LegacyReplayFrame(lastTime, + var lastFrame = currentFrame; + + currentFrame = new LegacyReplayFrame(lastTime, Parsing.ParseFloat(split[1], Parsing.MAX_COORDINATE_VALUE), Parsing.ParseFloat(split[2], Parsing.MAX_COORDINATE_VALUE), - (ReplayButtonState)Parsing.ParseInt(split[3])))); + (ReplayButtonState)Parsing.ParseInt(split[3])); + + replay.Frames.Add(convertFrame(currentFrame, lastFrame)); } } - private ReplayFrame convertFrame(LegacyReplayFrame legacyFrame) + private ReplayFrame convertFrame(LegacyReplayFrame currentFrame, LegacyReplayFrame lastFrame) { var convertible = currentRuleset.CreateConvertibleReplayFrame(); if (convertible == null) throw new InvalidOperationException($"Legacy replay cannot be converted for the ruleset: {currentRuleset.Description}"); - convertible.ConvertFrom(legacyFrame, currentBeatmap); + convertible.ConvertFrom(currentFrame, currentBeatmap, lastFrame); var frame = (ReplayFrame)convertible; - frame.Time = legacyFrame.Time; + frame.Time = currentFrame.Time; return frame; } From 68feedbd159b677879e77260b7f2b1f40e789185 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Sep 2019 18:46:42 +0900 Subject: [PATCH 124/239] Fix unreported CI issue --- osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs index 6783a36ac3..ad747e88e1 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneKeyCounter.cs @@ -46,7 +46,6 @@ namespace osu.Game.Tests.Visual.Gameplay }); Key testKey = ((KeyCounterKeyboard)kc.Children.First()).Key; - double time1 = 0; AddStep($"Press {testKey} key", () => { @@ -60,7 +59,6 @@ namespace osu.Game.Tests.Visual.Gameplay { InputManager.PressKey(testKey); InputManager.ReleaseKey(testKey); - time1 = Clock.CurrentTime; }); AddAssert($"Check {testKey} counter after keypress", () => testCounter.CountPresses == 2); From f21e47d6d2a513451dff67eeaa0bf1f78426f69a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Sep 2019 19:29:08 +0900 Subject: [PATCH 125/239] Move expire to DrawableHitObject --- .../Drawable/DrawableCatchHitObject.cs | 4 +-- .../Drawables/DrawableManiaHitObject.cs | 4 +-- .../Objects/Drawables/DrawableHitCircle.cs | 26 +++++++++++++++---- .../Objects/Drawables/DrawableOsuHitObject.cs | 8 ++++++ .../Objects/Drawables/DrawableSlider.cs | 4 +-- .../Objects/Drawables/DrawableSpinner.cs | 6 ----- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 8 +----- .../Objects/Drawables/DrawableDrumRoll.cs | 2 +- .../Objects/Drawables/DrawableDrumRollTick.cs | 2 +- .../Objects/Drawables/DrawableHit.cs | 8 ++---- .../Objects/Drawables/DrawableSwell.cs | 2 -- .../Objects/Drawables/DrawableHitObject.cs | 5 +++- 12 files changed, 43 insertions(+), 36 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index 00734810b3..51deae6e85 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -71,11 +71,11 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable switch (state) { case ArmedState.Miss: - this.FadeOut(250).RotateTo(Rotation * 2, 250, Easing.Out).Expire(); + this.FadeOut(250).RotateTo(Rotation * 2, 250, Easing.Out); break; case ArmedState.Hit: - this.FadeOut().Expire(); + this.FadeOut(); break; } } diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs index e5b114ca81..5bfa07bd14 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs @@ -51,11 +51,11 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables switch (state) { case ArmedState.Miss: - this.FadeOut(150, Easing.In).Expire(); + this.FadeOut(150, Easing.In); break; case ArmedState.Hit: - this.FadeOut(150, Easing.OutQuint).Expire(); + this.FadeOut(150, Easing.OutQuint); break; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 985dcbca86..85fd68efdd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -86,6 +86,26 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables AccentColour.BindValueChanged(accent => ApproachCircle.Colour = accent.NewValue, true); } + public override double LifetimeStart + { + get => base.LifetimeStart; + set + { + base.LifetimeStart = value; + ApproachCircle.LifetimeStart = value; + } + } + + public override double LifetimeEnd + { + get => base.LifetimeEnd; + set + { + base.LifetimeEnd = value; + ApproachCircle.LifetimeEnd = value; + } + } + protected override void CheckForResult(bool userTriggered, double timeOffset) { Debug.Assert(HitObject.HitWindows != null); @@ -132,22 +152,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Expire(true); hitArea.HitAction = null; - - // override lifetime end as FadeIn may have been changed externally, causing out expiration to be too early. - LifetimeEnd = HitObject.StartTime + HitObject.HitWindows.WindowFor(HitResult.Miss); break; case ArmedState.Miss: ApproachCircle.FadeOut(50); this.FadeOut(100); - Expire(); break; case ArmedState.Hit: ApproachCircle.FadeOut(50); // todo: temporary / arbitrary - this.Delay(800).Expire(); + this.Delay(800).FadeOut(); break; } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index fcd42314fc..8a7e5117f9 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -41,6 +41,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected virtual void Shake(double maximumLength) => shakeContainer.Shake(maximumLength); + protected override void LoadComplete() + { + base.LoadComplete(); + + // Manually set to reduce the number of future alive objects to a bare minimum. + LifetimeStart = HitObject.StartTime - HitObject.TimePreempt; + } + protected override JudgementResult CreateResult(Judgement judgement) => new OsuJudgementResult(HitObject, judgement); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 00c953c393..65f1d5e15f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -219,10 +219,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables break; } - this.FadeOut(fade_out_time, Easing.OutQuint).Expire(); + this.FadeOut(fade_out_time, Easing.OutQuint); } - - Expire(true); } public Drawable ProxiedLayer => HeadCircle.ApproachCircle; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 49aaa2aaea..b1185ddba8 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -219,10 +219,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables switch (state) { - case ArmedState.Idle: - Expire(true); - break; - case ArmedState.Hit: sequence.ScaleTo(Scale * 1.2f, 320, Easing.Out); break; @@ -231,8 +227,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables sequence.ScaleTo(Scale * 0.8f, 320, Easing.In); break; } - - Expire(); } } } diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index ea7eee8bb8..df12ebc514 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -70,13 +70,7 @@ namespace osu.Game.Rulesets.Osu.UI base.Add(h); } - private void addApproachCircleProxy(Drawable d) - { - var proxy = d.CreateProxy(); - proxy.LifetimeStart = d.LifetimeStart; - proxy.LifetimeEnd = d.LifetimeEnd; - approachCircles.Add(proxy); - } + private void addApproachCircleProxy(Drawable d) => approachCircles.Add(d.CreateProxy()); public override void PostProcess() { diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs index f4407a7b54..8e16a21199 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs @@ -94,7 +94,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { case ArmedState.Hit: case ArmedState.Miss: - this.Delay(HitObject.Duration).FadeOut(100).Expire(); + this.Delay(HitObject.Duration).FadeOut(100); break; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs index cef9a53deb..25b6141a0e 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables switch (state) { case ArmedState.Hit: - this.ScaleTo(0, 100, Easing.OutQuint).Expire(); + this.ScaleTo(0, 100, Easing.OutQuint); break; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs index 676ecd5a0b..4b25ff0ecc 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs @@ -105,12 +105,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables validActionPressed = false; UnproxyContent(); - this.Delay(HitObject.HitWindows.WindowFor(HitResult.Miss)).Expire(); break; case ArmedState.Miss: - this.FadeOut(100) - .Expire(); + this.FadeOut(100); break; case ArmedState.Hit: @@ -129,9 +127,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables .Then() .MoveToY(gravity_travel_height * 2, gravity_time * 2, Easing.In); - this.FadeOut(800) - .Expire(); - + this.FadeOut(800); break; } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs index 094ad1230f..07af7fe7e0 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs @@ -208,8 +208,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables { this.FadeOut(transition_duration, Easing.Out); bodyContainer.ScaleTo(1.4f, transition_duration); - - Expire(); } break; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index e3390c8cf0..90c49a0144 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -153,7 +153,6 @@ namespace osu.Game.Rulesets.Objects.Drawables if (UseTransformStateManagement) { - lifetimeStart = null; LifetimeEnd = double.MaxValue; double transformTime = HitObject.StartTime - InitialLifetimeOffset; @@ -173,6 +172,9 @@ namespace osu.Game.Rulesets.Objects.Drawables state.Value = newState; } } + + if (state.Value != ArmedState.Idle && LifetimeEnd == double.MaxValue) + Expire(); } else state.Value = newState; @@ -203,6 +205,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// Apply transforms based on the current . Previous states are automatically cleared. + /// In the case of a non-idle , and if was not set during this call, will be invoked. /// /// The new armed state. protected virtual void UpdateStateTransforms(ArmedState state) From b81b162ee12a96b0668222ee57ac477567851a0a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 12 Sep 2019 19:30:27 +0900 Subject: [PATCH 126/239] Update InitialLifetimeOffset comment --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 90c49a0144..00b57f7249 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -314,7 +314,7 @@ namespace osu.Game.Rulesets.Objects.Drawables /// /// This is only used as an optimisation to delay the initial update of this and may be tuned more aggressively if required. /// It is indirectly used to decide the automatic transform offset provided to . - /// A more accurate should be set inside for an state. + /// A more accurate should be set for further optimisation (in , for example). /// protected virtual double InitialLifetimeOffset => 10000; From cafb5105bc4b4997bc0c75259c9c1ce587d0c768 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Sep 2019 16:44:15 +0300 Subject: [PATCH 127/239] Rename HeaderFlag to DismissableFlag --- ...aderFlag.cs => TestSceneRankingsDismissableFlag.cs} | 10 +++++----- .../Rankings/{HeaderFlag.cs => DismissableFlag.cs} | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) rename osu.Game.Tests/Visual/Online/{TestSceneRankingsHeaderFlag.cs => TestSceneRankingsDismissableFlag.cs} (88%) rename osu.Game/Overlays/Rankings/{HeaderFlag.cs => DismissableFlag.cs} (94%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsDismissableFlag.cs similarity index 88% rename from osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs rename to osu.Game.Tests/Visual/Online/TestSceneRankingsDismissableFlag.cs index c9531e1016..db6afa9bf3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsDismissableFlag.cs @@ -12,16 +12,16 @@ using osuTK; namespace osu.Game.Tests.Visual.Online { - public class TestSceneRankingsHeaderFlag : OsuTestScene + public class TestSceneRankingsDismissableFlag : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { - typeof(HeaderFlag), + typeof(DismissableFlag), }; - public TestSceneRankingsHeaderFlag() + public TestSceneRankingsDismissableFlag() { - HeaderFlag flag; + DismissableFlag flag; SpriteText text; var countryA = new Country @@ -38,7 +38,7 @@ namespace osu.Game.Tests.Visual.Online AddRange(new Drawable[] { - flag = new HeaderFlag + flag = new DismissableFlag { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Overlays/Rankings/HeaderFlag.cs b/osu.Game/Overlays/Rankings/DismissableFlag.cs similarity index 94% rename from osu.Game/Overlays/Rankings/HeaderFlag.cs rename to osu.Game/Overlays/Rankings/DismissableFlag.cs index 6f641c74a5..7a55b0bba6 100644 --- a/osu.Game/Overlays/Rankings/HeaderFlag.cs +++ b/osu.Game/Overlays/Rankings/DismissableFlag.cs @@ -11,7 +11,7 @@ using System; namespace osu.Game.Overlays.Rankings { - public class HeaderFlag : UpdateableFlag + public class DismissableFlag : UpdateableFlag { private const int duration = 200; @@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Rankings private readonly SpriteIcon hoverIcon; - public HeaderFlag() + public DismissableFlag() { AddInternal(hoverIcon = new SpriteIcon { From b17d097a39d7edd1d15f6d2744029d47c7f2b08d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Sep 2019 17:17:57 +0300 Subject: [PATCH 128/239] Simplify colour usage in GradientLine --- .../UserInterface/GradientLineTabControl.cs | 38 +++++-------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs index 7cd8d2c5bd..3523876fca 100644 --- a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs +++ b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs @@ -8,7 +8,6 @@ using osuTK; using osu.Framework.Graphics.Shapes; using osuTK.Graphics; using osu.Framework.Graphics.Colour; -using osu.Framework.Bindables; using osu.Framework.Extensions.Color4Extensions; namespace osu.Game.Graphics.UserInterface @@ -19,8 +18,8 @@ namespace osu.Game.Graphics.UserInterface protected Color4 LineColour { - get => line.MainColour.Value; - set => line.MainColour.Value = value; + get => line.Colour; + set => line.Colour = value; } private readonly GradientLine line; @@ -48,12 +47,6 @@ namespace osu.Game.Graphics.UserInterface private class GradientLine : GridContainer { - public readonly Bindable MainColour = new Bindable(); - - private readonly Box left; - private readonly Box middle; - private readonly Box right; - public GradientLine() { RelativeSizeAxes = Axes.X; @@ -70,34 +63,23 @@ namespace osu.Game.Graphics.UserInterface { new Drawable[] { - left = new Box + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(Color4.White.Opacity(0), Color4.White) + }, + new Box { RelativeSizeAxes = Axes.Both, }, - middle = new Box - { - RelativeSizeAxes = Axes.Both, - }, - right = new Box + new Box { RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(Color4.White, Color4.White.Opacity(0)) }, } }; } - - protected override void LoadComplete() - { - MainColour.BindValueChanged(onColourChanged, true); - base.LoadComplete(); - } - - private void onColourChanged(ValueChangedEvent colour) - { - left.Colour = ColourInfo.GradientHorizontal(colour.NewValue.Opacity(0), colour.NewValue); - middle.Colour = colour.NewValue; - right.Colour = ColourInfo.GradientHorizontal(colour.NewValue, colour.NewValue.Opacity(0)); - } } } } From 7ee01ee3233a5a3d7eee3b1f41a018d923567e35 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Sep 2019 18:11:48 +0300 Subject: [PATCH 129/239] Use assignment instead of binding --- osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs index 2081a6c0cb..178016c648 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs @@ -35,7 +35,7 @@ namespace osu.Game.Tests.Visual.Online { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Current = { BindTarget = scope } + Current = scope } }); From 99fc13b4d85a17e4dcf5c65012c857892674e36c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 12 Sep 2019 19:34:58 +0300 Subject: [PATCH 130/239] Update usage of the DismissableFlag --- osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs | 2 +- osu.Game/Overlays/Rankings/HeaderTitle.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs index 0f16b2592f..849ca2defc 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderTitle.cs @@ -14,7 +14,7 @@ namespace osu.Game.Tests.Visual.Online { public override IReadOnlyList RequiredTypes => new[] { - typeof(HeaderFlag), + typeof(DismissableFlag), typeof(HeaderTitle), }; diff --git a/osu.Game/Overlays/Rankings/HeaderTitle.cs b/osu.Game/Overlays/Rankings/HeaderTitle.cs index 3f1feb10b8..a00c6c6dcd 100644 --- a/osu.Game/Overlays/Rankings/HeaderTitle.cs +++ b/osu.Game/Overlays/Rankings/HeaderTitle.cs @@ -23,7 +23,7 @@ namespace osu.Game.Overlays.Rankings private readonly SpriteText scopeText; private readonly Container flagPlaceholder; - private readonly HeaderFlag flag; + private readonly DismissableFlag flag; public HeaderTitle() { @@ -41,7 +41,7 @@ namespace osu.Game.Overlays.Rankings Origin = Anchor.BottomLeft, AutoSizeAxes = Axes.Both, Margin = new MarginPadding { Bottom = flag_margin }, - Child = flag = new HeaderFlag + Child = flag = new DismissableFlag { Size = new Vector2(30, 20), }, From 2a8fa2f5936543aa1c77baed96836a26d9c8ef98 Mon Sep 17 00:00:00 2001 From: Joehu Date: Thu, 12 Sep 2019 14:01:12 -0700 Subject: [PATCH 131/239] Refactor modsContainer on profile scores --- .../Sections/Ranks/DrawableProfileScore.cs | 9 ++++---- .../Sections/Ranks/ScoreModsContainer.cs | 21 ------------------- 2 files changed, 5 insertions(+), 25 deletions(-) delete mode 100644 osu.Game/Overlays/Profile/Sections/Ranks/ScoreModsContainer.cs diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index e54ce44ca2..6362d3dfb0 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -12,12 +12,13 @@ using osu.Game.Rulesets.UI; using osu.Game.Scoring; using osu.Game.Beatmaps; using osu.Framework.Localisation; +using osu.Framework.Graphics.Containers; namespace osu.Game.Overlays.Profile.Sections.Ranks { public abstract class DrawableProfileScore : DrawableProfileRow { - private readonly ScoreModsContainer modsContainer; + private readonly FillFlowContainer modsContainer; protected readonly ScoreInfo Score; protected DrawableProfileScore(ScoreInfo score) @@ -28,12 +29,12 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks Height = 60; Children = new Drawable[] { - modsContainer = new ScoreModsContainer + modsContainer = new FillFlowContainer { - AutoSizeAxes = Axes.Y, + AutoSizeAxes = Axes.Both, Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, - Width = 60, + Spacing = new Vector2(1), Margin = new MarginPadding { Right = 160 } } }; diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/ScoreModsContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/ScoreModsContainer.cs deleted file mode 100644 index 1ce04effa8..0000000000 --- a/osu.Game/Overlays/Profile/Sections/Ranks/ScoreModsContainer.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osuTK; -using osu.Framework.Graphics.Containers; -using osu.Game.Rulesets.UI; -using System.Collections.Generic; -using System.Linq; - -namespace osu.Game.Overlays.Profile.Sections.Ranks -{ - public class ScoreModsContainer : FlowContainer - { - protected override IEnumerable ComputeLayoutPositions() - { - int count = FlowingChildren.Count(); - for (int i = 0; i < count; i++) - yield return new Vector2(DrawWidth * i * (count == 1 ? 0 : 1f / (count - 1)), 0); - } - } -} From b917f29cfe6cccf9158332edc694572cbb7c302b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 13:59:06 +0900 Subject: [PATCH 132/239] Make GradientLineTabControl abstract --- osu.Game/Graphics/UserInterface/GradientLineTabControl.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs index 3523876fca..a9bbda4194 100644 --- a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs +++ b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs @@ -12,10 +12,8 @@ using osu.Framework.Extensions.Color4Extensions; namespace osu.Game.Graphics.UserInterface { - public class GradientLineTabControl : PageTabControl + public abstract class GradientLineTabControl : PageTabControl { - protected override Dropdown CreateDropdown() => null; - protected Color4 LineColour { get => line.Colour; @@ -24,7 +22,7 @@ namespace osu.Game.Graphics.UserInterface private readonly GradientLine line; - public GradientLineTabControl() + protected GradientLineTabControl() { RelativeSizeAxes = Axes.X; @@ -35,6 +33,8 @@ namespace osu.Game.Graphics.UserInterface }); } + protected override Dropdown CreateDropdown() => null; + protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer { Anchor = Anchor.BottomCentre, From 0e679fb468a4ee27dc0b57bd6aefbcfbce67ccfc Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 14:06:19 +0900 Subject: [PATCH 133/239] Use colour constant rather than opacity helper function --- osu.Game/Graphics/UserInterface/GradientLineTabControl.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs index a9bbda4194..4fd4a2adbd 100644 --- a/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs +++ b/osu.Game/Graphics/UserInterface/GradientLineTabControl.cs @@ -8,7 +8,6 @@ using osuTK; using osu.Framework.Graphics.Shapes; using osuTK.Graphics; using osu.Framework.Graphics.Colour; -using osu.Framework.Extensions.Color4Extensions; namespace osu.Game.Graphics.UserInterface { @@ -66,7 +65,7 @@ namespace osu.Game.Graphics.UserInterface new Box { RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(Color4.White.Opacity(0), Color4.White) + Colour = ColourInfo.GradientHorizontal(Color4.Transparent, Color4.White) }, new Box { @@ -75,7 +74,7 @@ namespace osu.Game.Graphics.UserInterface new Box { RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(Color4.White, Color4.White.Opacity(0)) + Colour = ColourInfo.GradientHorizontal(Color4.White, Color4.Transparent) }, } }; From 44947aa9edece7d0c140aa8660aa6c342a28b54f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 15:27:29 +0900 Subject: [PATCH 134/239] Make PopupDialog abstract --- .../UserInterface/TestSceneDialogOverlay.cs | 8 +++++-- .../UserInterface/TestScenePopupDialog.cs | 23 ++++++++++++------- osu.Game/Overlays/Dialog/PopupDialog.cs | 2 +- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs index a6ff3462d4..cc4a57fb83 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDialogOverlay.cs @@ -17,7 +17,7 @@ namespace osu.Game.Tests.Visual.UserInterface Add(overlay = new DialogOverlay()); - AddStep("dialog #1", () => overlay.Push(new PopupDialog + AddStep("dialog #1", () => overlay.Push(new TestPopupDialog { Icon = FontAwesome.Regular.TrashAlt, HeaderText = @"Confirm deletion of", @@ -37,7 +37,7 @@ namespace osu.Game.Tests.Visual.UserInterface }, })); - AddStep("dialog #2", () => overlay.Push(new PopupDialog + AddStep("dialog #2", () => overlay.Push(new TestPopupDialog { Icon = FontAwesome.Solid.Cog, HeaderText = @"What do you want to do with", @@ -71,5 +71,9 @@ namespace osu.Game.Tests.Visual.UserInterface }, })); } + + private class TestPopupDialog : PopupDialog + { + } } } diff --git a/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs b/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs index 9ddd8f4038..3d39bb7003 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestScenePopupDialog.cs @@ -13,13 +13,22 @@ namespace osu.Game.Tests.Visual.UserInterface { public TestScenePopupDialog() { - var popup = new PopupDialog + Add(new TestPopupDialog { RelativeSizeAxes = Axes.Both, State = { Value = Framework.Graphics.Containers.Visibility.Visible }, - Icon = FontAwesome.Solid.AssistiveListeningSystems, - HeaderText = @"This is a test popup", - BodyText = "I can say lots of stuff and even wrap my words!", + }); + } + + private class TestPopupDialog : PopupDialog + { + public TestPopupDialog() + { + Icon = FontAwesome.Solid.AssistiveListeningSystems; + + HeaderText = @"This is a test popup"; + BodyText = "I can say lots of stuff and even wrap my words!"; + Buttons = new PopupDialogButton[] { new PopupDialogCancelButton @@ -30,10 +39,8 @@ namespace osu.Game.Tests.Visual.UserInterface { Text = @"You're a fake!", }, - } - }; - - Add(popup); + }; + } } } } diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index 5c0ddb47b1..37674a5dcb 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -19,7 +19,7 @@ using osuTK.Input; namespace osu.Game.Overlays.Dialog { - public class PopupDialog : VisibilityContainer + public abstract class PopupDialog : VisibilityContainer { public static readonly float ENTER_DURATION = 500; public static readonly float EXIT_DURATION = 200; From dc8c7a50414caa25b9304f7cc99a1a9d45ebea44 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 15:27:42 +0900 Subject: [PATCH 135/239] Add null check for safety --- osu.Game/Overlays/DialogOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/DialogOverlay.cs b/osu.Game/Overlays/DialogOverlay.cs index 0d3c96c984..6aaeff8554 100644 --- a/osu.Game/Overlays/DialogOverlay.cs +++ b/osu.Game/Overlays/DialogOverlay.cs @@ -80,7 +80,7 @@ namespace osu.Game.Overlays switch (action) { case GlobalAction.Select: - currentDialog.Buttons.OfType().FirstOrDefault()?.Click(); + currentDialog?.Buttons.OfType().FirstOrDefault()?.Click(); return true; } From c66e96370531ae6baf9c1779cbfa20eecb045ba4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 15:42:36 +0900 Subject: [PATCH 136/239] Make constructor private --- osu.Game/Overlays/Dialog/PopupDialog.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index 37674a5dcb..cff887865a 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -87,7 +87,7 @@ namespace osu.Game.Overlays.Dialog } } - public PopupDialog() + protected PopupDialog() { RelativeSizeAxes = Axes.Both; From cf2f841b4d00da43aa1c4dd496d34df0a80a0746 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Sep 2019 15:41:53 +0900 Subject: [PATCH 137/239] Fix player not correctly exiting after an unpause --- .../Visual/Gameplay/TestScenePause.cs | 10 ++++++++++ osu.Game/Screens/Play/Player.cs | 19 +++++++++++-------- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs index 5808a78056..50583e43c4 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePause.cs @@ -160,6 +160,15 @@ namespace osu.Game.Tests.Visual.Gameplay exitAndConfirm(); } + [Test] + public void TestRestartAfterResume() + { + pauseAndConfirm(); + resumeAndConfirm(); + restart(); + confirmExited(); + } + private void pauseAndConfirm() { pause(); @@ -198,6 +207,7 @@ namespace osu.Game.Tests.Visual.Gameplay AddUntilStep("player exited", () => !Player.IsCurrentScreen()); } + private void restart() => AddStep("restart", () => Player.Restart()); private void pause() => AddStep("pause", () => Player.Pause()); private void resume() => AddStep("resume", () => Player.Resume()); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 3f1603eabe..3fd0f0260c 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -502,15 +502,18 @@ namespace osu.Game.Screens.Play return true; } - if (pauseCooldownActive && !GameplayClockContainer.IsPaused.Value) - // still want to block if we are within the cooldown period and not already paused. - return true; - - if (HasFailed && ValidForResume && !FailOverlay.IsPresent) - // ValidForResume is false when restarting + // ValidForResume is false when restarting + if (ValidForResume) { - failAnimation.FinishTransforms(true); - return true; + if (pauseCooldownActive && !GameplayClockContainer.IsPaused.Value) + // still want to block if we are within the cooldown period and not already paused. + return true; + + if (HasFailed && !FailOverlay.IsPresent) + { + failAnimation.FinishTransforms(true); + return true; + } } GameplayClockContainer.ResetLocalAdjustments(); From 7818ecd71c1eab60b1c0f7f17b4dcc79f5357ad9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 16:03:44 +0900 Subject: [PATCH 138/239] Forward ValueChangedEvent instead --- osu.Game/Overlays/Rankings/HeaderTitle.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Rankings/HeaderTitle.cs b/osu.Game/Overlays/Rankings/HeaderTitle.cs index a00c6c6dcd..ed9dc99a79 100644 --- a/osu.Game/Overlays/Rankings/HeaderTitle.cs +++ b/osu.Game/Overlays/Rankings/HeaderTitle.cs @@ -73,16 +73,16 @@ namespace osu.Game.Overlays.Rankings protected override void LoadComplete() { - Scope.BindValueChanged(scope => onScopeChanged(scope.NewValue), true); + Scope.BindValueChanged(onScopeChanged, true); Country.BindValueChanged(onCountryChanged, true); base.LoadComplete(); } - private void onScopeChanged(RankingsScope scope) + private void onScopeChanged(ValueChangedEvent scope) { - scopeText.Text = scope.ToString(); + scopeText.Text = scope.NewValue.ToString(); - if (scope != RankingsScope.Performance) + if (scope.NewValue != RankingsScope.Performance) Country.Value = null; } From 78e7be919f7dc05f40b806a07d2e8847cb2275f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 16:25:25 +0900 Subject: [PATCH 139/239] Remove unnecessary container --- osu.Game/Overlays/Rankings/HeaderTitle.cs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/Rankings/HeaderTitle.cs b/osu.Game/Overlays/Rankings/HeaderTitle.cs index ed9dc99a79..efaf4225d5 100644 --- a/osu.Game/Overlays/Rankings/HeaderTitle.cs +++ b/osu.Game/Overlays/Rankings/HeaderTitle.cs @@ -22,7 +22,6 @@ namespace osu.Game.Overlays.Rankings public readonly Bindable Country = new Bindable(); private readonly SpriteText scopeText; - private readonly Container flagPlaceholder; private readonly DismissableFlag flag; public HeaderTitle() @@ -35,16 +34,12 @@ namespace osu.Game.Overlays.Rankings Spacing = new Vector2(spacing, 0), Children = new Drawable[] { - flagPlaceholder = new Container + flag = new DismissableFlag { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - AutoSizeAxes = Axes.Both, Margin = new MarginPadding { Bottom = flag_margin }, - Child = flag = new DismissableFlag - { - Size = new Vector2(30, 20), - }, + Size = new Vector2(30, 20), }, scopeText = new SpriteText { @@ -90,15 +85,13 @@ namespace osu.Game.Overlays.Rankings { if (country.NewValue == null) { - flagPlaceholder.Hide(); + flag.Hide(); return; } Scope.Value = RankingsScope.Performance; - if (country.OldValue == null) - flagPlaceholder.Show(); - + flag.Show(); flag.Country = country.NewValue; } } From 51f17ccb1b8caec176e2b712066cd76caf453c98 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 13 Sep 2019 10:48:02 +0300 Subject: [PATCH 140/239] Remove test duplicate --- .../Online/TestSceneRankingsHeaderFlag.cs | 65 ------------------- 1 file changed, 65 deletions(-) delete mode 100644 osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs deleted file mode 100644 index 17f6f8417b..0000000000 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeaderFlag.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using System.Collections.Generic; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; -using osu.Game.Graphics; -using osu.Game.Overlays.Rankings; -using osu.Game.Users; -using osuTK; - -namespace osu.Game.Tests.Visual.Online -{ - public class TestSceneRankingsHeaderFlag : OsuTestScene - { - public override IReadOnlyList RequiredTypes => new[] - { - typeof(DismissableFlag), - }; - - public TestSceneRankingsHeaderFlag() - { - DismissableFlag flag; - SpriteText text; - - var countryA = new Country - { - FlagName = "BY", - FullName = "Belarus" - }; - - var countryB = new Country - { - FlagName = "US", - FullName = "United States" - }; - - AddRange(new Drawable[] - { - flag = new DismissableFlag - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(30, 20), - Country = countryA, - }, - text = new SpriteText - { - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre, - Text = "Invoked", - Font = OsuFont.GetFont(size: 30), - Alpha = 0, - } - }); - - flag.Action += () => text.FadeIn().Then().FadeOut(1000, Easing.OutQuint); - - AddStep("Trigger click", () => flag.Click()); - AddStep("Change to country 2", () => flag.Country = countryB); - AddStep("Change to country 1", () => flag.Country = countryA); - } - } -} From c9ae4336f944b779becfcf7f880cef8293a19815 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 13 Sep 2019 10:50:26 +0300 Subject: [PATCH 141/239] Fix RankingsScope test --- osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs index fef9c3a7b1..3693d6b5b4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsScopeSelector.cs @@ -35,7 +35,7 @@ namespace osu.Game.Tests.Visual.Online { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Current = { BindTarget = scope } + Current = scope, } }); From 6867b3c23214a8a6f47d547cf6377cdf4d13919b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 13 Sep 2019 10:56:21 +0300 Subject: [PATCH 142/239] Update resources --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 45c162a30e..4167d07698 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,7 +62,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index df8b11e653..5703293caf 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -25,7 +25,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 7c31744a14..683dccf3ae 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -117,7 +117,7 @@ - + From 9a9654dbd1021614d95969231a4d09523699b663 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 13 Sep 2019 10:59:09 +0300 Subject: [PATCH 143/239] Fix the Test Scene --- osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs index e8ed94b59c..0ceb5f21d3 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs @@ -15,7 +15,7 @@ namespace osu.Game.Tests.Visual.Online { public override IReadOnlyList RequiredTypes => new[] { - typeof(HeaderFlag), + typeof(DismissableFlag), typeof(HeaderTitle), typeof(RankingsRulesetSelector), typeof(RankingsScopeSelector), @@ -50,7 +50,7 @@ namespace osu.Game.Tests.Visual.Online new Spotlight { Id = 3, - Text = "Spotlight 4" + Text = "Spotlight 3" } } }); From 7cb79dd7605f37e9c5fdd67ec98cda660e4a46b1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 17:15:33 +0900 Subject: [PATCH 144/239] Fix incorrect DI usage of IAPIProvider in many tests --- .../Visual/Menus/TestSceneDisclaimer.cs | 11 ++++---- .../Multiplayer/TestSceneMatchLeaderboard.cs | 2 +- .../Multiplayer/TestSceneMultiScreen.cs | 2 +- .../Online/TestSceneAccountCreationOverlay.cs | 14 +++++++---- .../Online/TestSceneBeatmapSetOverlay.cs | 2 +- .../Online/TestSceneChangelogOverlay.cs | 2 +- .../Visual/Online/TestSceneDirectOverlay.cs | 2 +- .../Online/TestSceneHistoricalSection.cs | 2 +- .../Visual/Online/TestSceneSocialOverlay.cs | 2 +- .../Online/TestSceneUserProfileHeader.cs | 2 +- .../Online/TestSceneUserProfileOverlay.cs | 2 +- .../Visual/Online/TestSceneUserRanks.cs | 2 +- ...tSceneUpdateableBeatmapBackgroundSprite.cs | 3 +-- osu.Game/Tests/Visual/OsuTestScene.cs | 25 ++++++++++++++----- 14 files changed, 44 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs b/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs index 13116de320..681bf1b40b 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneDisclaimer.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Game.Online.API; using osu.Game.Screens.Menu; using osu.Game.Users; @@ -11,17 +10,17 @@ namespace osu.Game.Tests.Visual.Menus public class TestSceneDisclaimer : ScreenTestScene { [BackgroundDependencyLoader] - private void load(IAPIProvider api) + private void load() { AddStep("load disclaimer", () => LoadScreen(new Disclaimer())); AddStep("toggle support", () => { - api.LocalUser.Value = new User + API.LocalUser.Value = new User { - Username = api.LocalUser.Value.Username, - Id = api.LocalUser.Value.Id, - IsSupporter = !api.LocalUser.Value.IsSupporter, + Username = API.LocalUser.Value.Username, + Id = API.LocalUser.Value.Id, + IsSupporter = !API.LocalUser.Value.IsSupporter, }; }); } diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs index 723e5fc03d..7ba1782a28 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMatchLeaderboard.cs @@ -14,7 +14,7 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneMatchLeaderboard : MultiplayerTestScene { - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; public TestSceneMatchLeaderboard() { diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiScreen.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiScreen.cs index b646433846..dfe61a4dda 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiScreen.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiScreen.cs @@ -12,7 +12,7 @@ namespace osu.Game.Tests.Visual.Multiplayer [TestFixture] public class TestSceneMultiScreen : ScreenTestScene { - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs index 66ab1fe18a..31eab7f74e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneAccountCreationOverlay.cs @@ -4,9 +4,9 @@ using System; using System.Collections.Generic; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Online.API; using osu.Game.Overlays; using osu.Game.Overlays.AccountCreation; using osu.Game.Users; @@ -27,6 +27,8 @@ namespace osu.Game.Tests.Visual.Online private readonly Container userPanelArea; + private Bindable localUser; + public TestSceneAccountCreationOverlay() { AccountCreationOverlay accountCreation; @@ -47,12 +49,14 @@ namespace osu.Game.Tests.Visual.Online } [BackgroundDependencyLoader] - private void load(IAPIProvider api) + private void load() { - api.Logout(); - api.LocalUser.BindValueChanged(user => { userPanelArea.Child = new UserPanel(user.NewValue) { Width = 200 }; }, true); + API.Logout(); - AddStep("logout", api.Logout); + localUser = API.LocalUser.GetBoundCopy(); + localUser.BindValueChanged(user => { userPanelArea.Child = new UserPanel(user.NewValue) { Width = 200 }; }, true); + + AddStep("logout", API.Logout); } } } diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index 5068064a1f..9f03d947b9 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual.Online typeof(BeatmapAvailability), }; - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; private RulesetInfo taikoRuleset; private RulesetInfo maniaRuleset; diff --git a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs index 324291c9d7..f555c276f4 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChangelogOverlay.cs @@ -27,7 +27,7 @@ namespace osu.Game.Tests.Visual.Online typeof(Comments), }; - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; protected override void LoadComplete() { diff --git a/osu.Game.Tests/Visual/Online/TestSceneDirectOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneDirectOverlay.cs index 14ae975806..d9873ea243 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneDirectOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneDirectOverlay.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tests.Visual.Online { private DirectOverlay direct; - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; protected override void LoadComplete() { diff --git a/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs b/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs index c98f98c23d..d3b037f499 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneHistoricalSection.cs @@ -17,7 +17,7 @@ namespace osu.Game.Tests.Visual.Online [TestFixture] public class TestSceneHistoricalSection : OsuTestScene { - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs index 806b36e855..dbd7544b38 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneSocialOverlay.cs @@ -13,7 +13,7 @@ namespace osu.Game.Tests.Visual.Online [TestFixture] public class TestSceneSocialOverlay : OsuTestScene { - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs index 555d5334d8..63b8acb234 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs @@ -17,7 +17,7 @@ namespace osu.Game.Tests.Visual.Online { public class TestSceneUserProfileHeader : OsuTestScene { - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; public override IReadOnlyList RequiredTypes => new[] { diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs index 42c8ffbf0a..93e6607ac5 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs @@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual.Online [TestFixture] public class TestSceneUserProfileOverlay : OsuTestScene { - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; private readonly TestUserProfileOverlay profile; diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs b/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs index d777f9766a..2951f6b63e 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserRanks.cs @@ -18,7 +18,7 @@ namespace osu.Game.Tests.Visual.Online [TestFixture] public class TestSceneUserRanks : OsuTestScene { - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; public override IReadOnlyList RequiredTypes => new[] { typeof(DrawableProfileScore), typeof(RanksSection) }; diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs index fdc50be3fa..d3359fd824 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs @@ -20,7 +20,7 @@ namespace osu.Game.Tests.Visual.UserInterface { public class TestSceneUpdateableBeatmapBackgroundSprite : OsuTestScene { - protected override bool RequiresAPIAccess => true; + protected override bool UseOnlineAPI => true; private BeatmapSetInfo testBeatmap; private IAPIProvider api; @@ -32,7 +32,6 @@ namespace osu.Game.Tests.Visual.UserInterface [BackgroundDependencyLoader] private void load(OsuGameBase osu, IAPIProvider api, RulesetStore rulesets) { - this.api = api; this.rulesets = rulesets; testBeatmap = ImportBeatmapTest.LoadOszIntoOsu(osu).Result; diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index dd68ed93e6..5a7fbd31e2 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -46,13 +46,27 @@ namespace osu.Game.Tests.Visual protected Storage LocalStorage => localStorage.Value; private readonly Lazy contextFactory; + + protected IAPIProvider API + { + get + { + if (UseOnlineAPI) + throw new Exception("Using the OsuTestScene dummy API is not supported when UseOnlineAPI is true"); + + return dummyAPI; + } + } + + private DummyAPIAccess dummyAPI; + protected DatabaseContextFactory ContextFactory => contextFactory.Value; /// - /// Whether this test scene requires API access - /// Setting this will cache an actual . + /// Whether this test scene requires real-world API access. + /// If true, this will bypass the local and use the provided one. /// - protected virtual bool RequiresAPIAccess => false; + protected virtual bool UseOnlineAPI => false; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) { @@ -66,10 +80,9 @@ namespace osu.Game.Tests.Visual Dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - if (!RequiresAPIAccess) + if (!UseOnlineAPI) { - var dummyAPI = new DummyAPIAccess(); - + dummyAPI = new DummyAPIAccess(); Dependencies.CacheAs(dummyAPI); Add(dummyAPI); } From 0cc21c9c747979052603576c25be1ec0bd502034 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 17:21:47 +0900 Subject: [PATCH 145/239] Fix changelog overlay potentially adding children after disposal --- osu.Game/Overlays/ChangelogOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/ChangelogOverlay.cs b/osu.Game/Overlays/ChangelogOverlay.cs index 7755c8a6a6..dfe3669813 100644 --- a/osu.Game/Overlays/ChangelogOverlay.cs +++ b/osu.Game/Overlays/ChangelogOverlay.cs @@ -170,7 +170,7 @@ namespace osu.Game.Overlays var tcs = new TaskCompletionSource(); var req = new GetChangelogRequest(); - req.Success += res => + req.Success += res => Schedule(() => { // remap streams to builds to ensure model equality res.Builds.ForEach(b => b.UpdateStream = res.Streams.Find(s => s.Id == b.UpdateStream.Id)); @@ -182,7 +182,7 @@ namespace osu.Game.Overlays header.Streams.Populate(res.Streams); tcs.SetResult(true); - }; + }); req.Failure += _ => initialFetchTask = null; req.Perform(API); From d681f43e29c2c45fa50c762c47955668e9872e21 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 13 Sep 2019 08:38:02 +0000 Subject: [PATCH 146/239] Bump ppy.osu.Game.Resources from 2019.904.0 to 2019.913.0 Bumps [ppy.osu.Game.Resources](https://github.com/ppy/osu-resources) from 2019.904.0 to 2019.913.0. - [Release notes](https://github.com/ppy/osu-resources/releases) - [Commits](https://github.com/ppy/osu-resources/compare/2019.904.0...2019.913.0) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 45c162a30e..4167d07698 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -62,7 +62,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index df8b11e653..5703293caf 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -25,7 +25,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 7c31744a14..683dccf3ae 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -117,7 +117,7 @@ - + From a7c59098ce51be6eb3828d9029f57bfe51e02688 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 17:38:04 +0900 Subject: [PATCH 147/239] Fix missing assignment --- .../UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs index d3359fd824..198cc70e01 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneUpdateableBeatmapBackgroundSprite.cs @@ -32,6 +32,7 @@ namespace osu.Game.Tests.Visual.UserInterface [BackgroundDependencyLoader] private void load(OsuGameBase osu, IAPIProvider api, RulesetStore rulesets) { + this.api = api; this.rulesets = rulesets; testBeatmap = ImportBeatmapTest.LoadOszIntoOsu(osu).Result; From 1e4f3507ed9c0529eda45ab530fe2430aa85cf07 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 18:07:52 +0900 Subject: [PATCH 148/239] Fix layout not matching web --- osu.Game/Overlays/Rankings/RankingsHeader.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/osu.Game/Overlays/Rankings/RankingsHeader.cs b/osu.Game/Overlays/Rankings/RankingsHeader.cs index 6d55e92502..18a0599036 100644 --- a/osu.Game/Overlays/Rankings/RankingsHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsHeader.cs @@ -20,7 +20,6 @@ namespace osu.Game.Overlays.Rankings private const int content_height = 250; private const int dropdown_height = 50; private const int spacing = 20; - private const int title_offset = 30; private const int duration = 200; public IEnumerable Spotlights @@ -68,27 +67,25 @@ namespace osu.Game.Overlays.Rankings Masking = true, Child = new HeaderBackground(), }, - new RankingsScopeSelector - { - Margin = new MarginPadding { Top = 10 }, - Current = { BindTarget = Scope } - }, new FillFlowContainer { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Y = title_offset, AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, Direction = FillDirection.Vertical, Spacing = new Vector2(0, spacing), Children = new Drawable[] { + new RankingsScopeSelector + { + Margin = new MarginPadding { Top = 10 }, + Current = { BindTarget = Scope } + }, new HeaderTitle { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Scope = { BindTarget = Scope }, + Margin = new MarginPadding { Top = 10 }, Country = { BindTarget = Country }, }, dropdownPlaceholder = new Container From 031f0ee1e7251308e1830ad86dcca94f69ee7656 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 18:09:15 +0900 Subject: [PATCH 149/239] Consume ValueChanged and inline some pointless constants --- osu.Game/Overlays/Rankings/RankingsHeader.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/Rankings/RankingsHeader.cs b/osu.Game/Overlays/Rankings/RankingsHeader.cs index 18a0599036..4e502fb7fe 100644 --- a/osu.Game/Overlays/Rankings/RankingsHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsHeader.cs @@ -19,8 +19,6 @@ namespace osu.Game.Overlays.Rankings { private const int content_height = 250; private const int dropdown_height = 50; - private const int spacing = 20; - private const int duration = 200; public IEnumerable Spotlights { @@ -72,7 +70,7 @@ namespace osu.Game.Overlays.Rankings AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, Direction = FillDirection.Vertical, - Spacing = new Vector2(0, spacing), + Spacing = new Vector2(0, 20), Children = new Drawable[] { new RankingsScopeSelector @@ -112,12 +110,12 @@ namespace osu.Game.Overlays.Rankings protected override void LoadComplete() { - Scope.BindValueChanged(scope => onScopeChanged(scope.NewValue), true); + Scope.BindValueChanged(onScopeChanged, true); base.LoadComplete(); } - private void onScopeChanged(RankingsScope scope) => - dropdownPlaceholder.FadeTo(scope == RankingsScope.Spotlights ? 1 : 0, duration, Easing.OutQuint); + private void onScopeChanged(ValueChangedEvent scope) => + dropdownPlaceholder.FadeTo(scope.NewValue == RankingsScope.Spotlights ? 1 : 0, 200, Easing.OutQuint); private class HeaderBackground : Sprite { From 614e68cdf960cd15667f4b2597012320239750a3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 18:10:52 +0900 Subject: [PATCH 150/239] Remove redundant BindTarget usage --- osu.Game/Overlays/Rankings/RankingsHeader.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Rankings/RankingsHeader.cs b/osu.Game/Overlays/Rankings/RankingsHeader.cs index 4e502fb7fe..fbf3097f4f 100644 --- a/osu.Game/Overlays/Rankings/RankingsHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsHeader.cs @@ -49,7 +49,7 @@ namespace osu.Game.Overlays.Rankings { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Current = { BindTarget = Ruleset } + Current = Ruleset }, new Container { @@ -76,14 +76,14 @@ namespace osu.Game.Overlays.Rankings new RankingsScopeSelector { Margin = new MarginPadding { Top = 10 }, - Current = { BindTarget = Scope } + Current = Scope }, new HeaderTitle { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Scope = { BindTarget = Scope }, Margin = new MarginPadding { Top = 10 }, + Scope = { BindTarget = Scope }, Country = { BindTarget = Country }, }, dropdownPlaceholder = new Container @@ -97,7 +97,7 @@ namespace osu.Game.Overlays.Rankings Child = dropdown = new OsuDropdown { RelativeSizeAxes = Axes.X, - Current = { BindTarget = Spotlight }, + Current = Spotlight, } } } From 5c2c055614d943f1cc46d8b8f1faf8f0bb17daa9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 13 Sep 2019 18:49:21 +0900 Subject: [PATCH 151/239] Set lifetime on initial state update --- .../Objects/Drawables/DrawableHitCircle.cs | 2 ++ .../Objects/Drawables/DrawableOsuHitObject.cs | 13 +++++++++---- .../Objects/Drawables/DrawableRepeatPoint.cs | 2 ++ .../Objects/Drawables/DrawableSlider.cs | 2 ++ .../Objects/Drawables/DrawableSliderTick.cs | 2 ++ .../Objects/Drawables/DrawableSpinner.cs | 2 ++ 6 files changed, 19 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 85fd68efdd..83646c561d 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -142,6 +142,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void UpdateStateTransforms(ArmedState state) { + base.UpdateStateTransforms(state); + Debug.Assert(HitObject.HitWindows != null); switch (state) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 8a7e5117f9..c46343c73c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -41,12 +41,17 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected virtual void Shake(double maximumLength) => shakeContainer.Shake(maximumLength); - protected override void LoadComplete() + protected override void UpdateStateTransforms(ArmedState state) { - base.LoadComplete(); + base.UpdateStateTransforms(state); - // Manually set to reduce the number of future alive objects to a bare minimum. - LifetimeStart = HitObject.StartTime - HitObject.TimePreempt; + switch (state) + { + case ArmedState.Idle: + // Manually set to reduce the number of future alive objects to a bare minimum. + LifetimeStart = HitObject.StartTime - HitObject.TimePreempt; + break; + } } protected override JudgementResult CreateResult(Judgement judgement) => new OsuJudgementResult(HitObject, judgement); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs index 00a943a67f..84d2a4af9b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableRepeatPoint.cs @@ -74,6 +74,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void UpdateStateTransforms(ArmedState state) { + base.UpdateStateTransforms(state); + switch (state) { case ArmedState.Idle: diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 65f1d5e15f..08b43b0345 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -202,6 +202,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void UpdateStateTransforms(ArmedState state) { + base.UpdateStateTransforms(state); + Ball.FadeIn(); Ball.ScaleTo(HitObject.Scale); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index ba931976a8..9d4d9958a1 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -75,6 +75,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void UpdateStateTransforms(ArmedState state) { + base.UpdateStateTransforms(state); + switch (state) { case ArmedState.Idle: diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index b1185ddba8..d1b9ee6cb4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -215,6 +215,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void UpdateStateTransforms(ArmedState state) { + base.UpdateStateTransforms(state); + var sequence = this.Delay(Spinner.Duration).FadeOut(160); switch (state) From a6420def9909b6e375c57f6f43e1b9f05edb401f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 19:29:49 +0900 Subject: [PATCH 152/239] Make hyperdash test automatic --- osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs index a603d96201..7b8c699f2c 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs @@ -16,6 +16,8 @@ namespace osu.Game.Rulesets.Catch.Tests { } + protected override bool Autoplay => true; + [Test] public void TestHyperDash() { From c13950fbbf801d92a8c62aa4075ef51e2dadc323 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 13 Sep 2019 13:43:21 +0300 Subject: [PATCH 153/239] Remove custom db additions --- osu.Game/Migrations/20171019041408_InitialCreate.cs | 1 - osu.Game/Migrations/20181007180454_StandardizePaths.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/osu.Game/Migrations/20171019041408_InitialCreate.cs b/osu.Game/Migrations/20171019041408_InitialCreate.cs index 3349998873..9b6881f98c 100644 --- a/osu.Game/Migrations/20171019041408_InitialCreate.cs +++ b/osu.Game/Migrations/20171019041408_InitialCreate.cs @@ -35,7 +35,6 @@ namespace osu.Game.Migrations AudioFile = table.Column(type: "TEXT", nullable: true), Author = table.Column(type: "TEXT", nullable: true), BackgroundFile = table.Column(type: "TEXT", nullable: true), - VideoFile = table.Column(type: "TEXT", nullable: true), PreviewTime = table.Column(type: "INTEGER", nullable: false), Source = table.Column(type: "TEXT", nullable: true), Tags = table.Column(type: "TEXT", nullable: true), diff --git a/osu.Game/Migrations/20181007180454_StandardizePaths.cs b/osu.Game/Migrations/20181007180454_StandardizePaths.cs index c106b839e2..274b8030a9 100644 --- a/osu.Game/Migrations/20181007180454_StandardizePaths.cs +++ b/osu.Game/Migrations/20181007180454_StandardizePaths.cs @@ -15,7 +15,6 @@ namespace osu.Game.Migrations migrationBuilder.Sql($"UPDATE `BeatmapInfo` SET `Path` = REPLACE(`Path`, '{windowsStyle}', '{standardized}')"); migrationBuilder.Sql($"UPDATE `BeatmapMetadata` SET `AudioFile` = REPLACE(`AudioFile`, '{windowsStyle}', '{standardized}')"); migrationBuilder.Sql($"UPDATE `BeatmapMetadata` SET `BackgroundFile` = REPLACE(`BackgroundFile`, '{windowsStyle}', '{standardized}')"); - migrationBuilder.Sql($"UPDATE `BeatmapMetadata` SET `VideoFile` = REPLACE(`VideoFile`, '{windowsStyle}', '{standardized}')"); migrationBuilder.Sql($"UPDATE `BeatmapSetFileInfo` SET `Filename` = REPLACE(`Filename`, '{windowsStyle}', '{standardized}')"); migrationBuilder.Sql($"UPDATE `SkinFileInfo` SET `Filename` = REPLACE(`Filename`, '{windowsStyle}', '{standardized}')"); } From 9e742839ac360f81f45c3db28c7587b1d4cd4002 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 13 Sep 2019 13:57:55 +0300 Subject: [PATCH 154/239] Use correct database migration --- ...20190913104727_AddBeatmapVideo.Designer.cs | 506 ++++++++++++++++++ .../20190913104727_AddBeatmapVideo.cs | 22 + .../Migrations/OsuDbContextModelSnapshot.cs | 4 +- 3 files changed, 531 insertions(+), 1 deletion(-) create mode 100644 osu.Game/Migrations/20190913104727_AddBeatmapVideo.Designer.cs create mode 100644 osu.Game/Migrations/20190913104727_AddBeatmapVideo.cs diff --git a/osu.Game/Migrations/20190913104727_AddBeatmapVideo.Designer.cs b/osu.Game/Migrations/20190913104727_AddBeatmapVideo.Designer.cs new file mode 100644 index 0000000000..826233a2b0 --- /dev/null +++ b/osu.Game/Migrations/20190913104727_AddBeatmapVideo.Designer.cs @@ -0,0 +1,506 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using osu.Game.Database; + +namespace osu.Game.Migrations +{ + [DbContext(typeof(OsuDbContext))] + [Migration("20190913104727_AddBeatmapVideo")] + partial class AddBeatmapVideo + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("ApproachRate"); + + b.Property("CircleSize"); + + b.Property("DrainRate"); + + b.Property("OverallDifficulty"); + + b.Property("SliderMultiplier"); + + b.Property("SliderTickRate"); + + b.HasKey("ID"); + + b.ToTable("BeatmapDifficulty"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("AudioLeadIn"); + + b.Property("BPM"); + + b.Property("BaseDifficultyID"); + + b.Property("BeatDivisor"); + + b.Property("BeatmapSetInfoID"); + + b.Property("Countdown"); + + b.Property("DistanceSpacing"); + + b.Property("GridSize"); + + b.Property("Hash"); + + b.Property("Hidden"); + + b.Property("Length"); + + b.Property("LetterboxInBreaks"); + + b.Property("MD5Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapID"); + + b.Property("Path"); + + b.Property("RulesetID"); + + b.Property("SpecialStyle"); + + b.Property("StackLeniency"); + + b.Property("StarDifficulty"); + + b.Property("Status"); + + b.Property("StoredBookmarks"); + + b.Property("TimelineZoom"); + + b.Property("Version"); + + b.Property("WidescreenStoryboard"); + + b.HasKey("ID"); + + b.HasIndex("BaseDifficultyID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("Hash"); + + b.HasIndex("MD5Hash"); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("BeatmapInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Artist"); + + b.Property("ArtistUnicode"); + + b.Property("AudioFile"); + + b.Property("AuthorString") + .HasColumnName("Author"); + + b.Property("BackgroundFile"); + + b.Property("PreviewTime"); + + b.Property("Source"); + + b.Property("Tags"); + + b.Property("Title"); + + b.Property("TitleUnicode"); + + b.Property("VideoFile"); + + b.HasKey("ID"); + + b.ToTable("BeatmapMetadata"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("BeatmapSetInfoID"); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.HasKey("ID"); + + b.HasIndex("BeatmapSetInfoID"); + + b.HasIndex("FileInfoID"); + + b.ToTable("BeatmapSetFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("DateAdded"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("MetadataID"); + + b.Property("OnlineBeatmapSetID"); + + b.Property("Protected"); + + b.Property("Status"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("MetadataID"); + + b.HasIndex("OnlineBeatmapSetID") + .IsUnique(); + + b.ToTable("BeatmapSetInfo"); + }); + + modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Key") + .HasColumnName("Key"); + + b.Property("RulesetID"); + + b.Property("SkinInfoID"); + + b.Property("StringValue") + .HasColumnName("Value"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("SkinInfoID"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("Settings"); + }); + + modelBuilder.Entity("osu.Game.IO.FileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Hash"); + + b.Property("ReferenceCount"); + + b.HasKey("ID"); + + b.HasIndex("Hash") + .IsUnique(); + + b.HasIndex("ReferenceCount"); + + b.ToTable("FileInfo"); + }); + + modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("IntAction") + .HasColumnName("Action"); + + b.Property("KeysString") + .HasColumnName("Keys"); + + b.Property("RulesetID"); + + b.Property("Variant"); + + b.HasKey("ID"); + + b.HasIndex("IntAction"); + + b.HasIndex("RulesetID", "Variant"); + + b.ToTable("KeyBinding"); + }); + + modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Available"); + + b.Property("InstantiationInfo"); + + b.Property("Name"); + + b.Property("ShortName"); + + b.HasKey("ID"); + + b.HasIndex("Available"); + + b.HasIndex("ShortName") + .IsUnique(); + + b.ToTable("RulesetInfo"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("ScoreInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("ScoreInfoID"); + + b.ToTable("ScoreFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Accuracy") + .HasColumnType("DECIMAL(1,4)"); + + b.Property("BeatmapInfoID"); + + b.Property("Combo"); + + b.Property("Date"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("MaxCombo"); + + b.Property("ModsJson") + .HasColumnName("Mods"); + + b.Property("OnlineScoreID"); + + b.Property("PP"); + + b.Property("Rank"); + + b.Property("RulesetID"); + + b.Property("StatisticsJson") + .HasColumnName("Statistics"); + + b.Property("TotalScore"); + + b.Property("UserID") + .HasColumnName("UserID"); + + b.Property("UserString") + .HasColumnName("User"); + + b.HasKey("ID"); + + b.HasIndex("BeatmapInfoID"); + + b.HasIndex("OnlineScoreID") + .IsUnique(); + + b.HasIndex("RulesetID"); + + b.ToTable("ScoreInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("FileInfoID"); + + b.Property("Filename") + .IsRequired(); + + b.Property("SkinInfoID"); + + b.HasKey("ID"); + + b.HasIndex("FileInfoID"); + + b.HasIndex("SkinInfoID"); + + b.ToTable("SkinFileInfo"); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b => + { + b.Property("ID") + .ValueGeneratedOnAdd(); + + b.Property("Creator"); + + b.Property("DeletePending"); + + b.Property("Hash"); + + b.Property("Name"); + + b.HasKey("ID"); + + b.HasIndex("DeletePending"); + + b.HasIndex("Hash") + .IsUnique(); + + b.ToTable("SkinInfo"); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty") + .WithMany() + .HasForeignKey("BaseDifficultyID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet") + .WithMany("Beatmaps") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("Beatmaps") + .HasForeignKey("MetadataID"); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo") + .WithMany("Files") + .HasForeignKey("BeatmapSetInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata") + .WithMany("BeatmapSets") + .HasForeignKey("MetadataID"); + }); + + modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b => + { + b.HasOne("osu.Game.Skinning.SkinInfo") + .WithMany("Settings") + .HasForeignKey("SkinInfoID"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Scoring.ScoreInfo") + .WithMany("Files") + .HasForeignKey("ScoreInfoID"); + }); + + modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b => + { + b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "Beatmap") + .WithMany("Scores") + .HasForeignKey("BeatmapInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset") + .WithMany() + .HasForeignKey("RulesetID") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => + { + b.HasOne("osu.Game.IO.FileInfo", "FileInfo") + .WithMany() + .HasForeignKey("FileInfoID") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("osu.Game.Skinning.SkinInfo") + .WithMany("Files") + .HasForeignKey("SkinInfoID") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/osu.Game/Migrations/20190913104727_AddBeatmapVideo.cs b/osu.Game/Migrations/20190913104727_AddBeatmapVideo.cs new file mode 100644 index 0000000000..9ed0943acd --- /dev/null +++ b/osu.Game/Migrations/20190913104727_AddBeatmapVideo.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace osu.Game.Migrations +{ + public partial class AddBeatmapVideo : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "VideoFile", + table: "BeatmapMetadata", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "VideoFile", + table: "BeatmapMetadata"); + } + } +} diff --git a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs index 761dca2801..a6d9d1f3cb 100644 --- a/osu.Game/Migrations/OsuDbContextModelSnapshot.cs +++ b/osu.Game/Migrations/OsuDbContextModelSnapshot.cs @@ -14,7 +14,7 @@ namespace osu.Game.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.4-servicing-10062"); + .HasAnnotation("ProductVersion", "2.2.6-servicing-10079"); modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b => { @@ -139,6 +139,8 @@ namespace osu.Game.Migrations b.Property("TitleUnicode"); + b.Property("VideoFile"); + b.HasKey("ID"); b.ToTable("BeatmapMetadata"); From 744085fa549766b74d2bcb9f78e8a841225fe936 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 20:25:08 +0900 Subject: [PATCH 155/239] Fix exploding fruit not getting correct lifetime --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 330f6e6b24..40d2f64f6a 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -74,6 +74,7 @@ namespace osu.Game.Rulesets.Catch.UI caughtFruit.Anchor = Anchor.TopCentre; caughtFruit.Origin = Anchor.Centre; caughtFruit.Scale *= 0.7f; + caughtFruit.LifetimeStart = caughtFruit.HitObject.StartTime; caughtFruit.LifetimeEnd = double.MaxValue; MovableCatcher.Add(caughtFruit); @@ -414,7 +415,10 @@ namespace osu.Game.Rulesets.Catch.UI f.MoveToY(f.Y + 75, 750, Easing.InSine); f.FadeOut(750); - f.Expire(true); + + // todo: this shouldn't exist once DrawableHitObject's ClearTransformsAfter overrides are repaired. + f.LifetimeStart = Time.Current; + f.Expire(); } } @@ -448,7 +452,10 @@ namespace osu.Game.Rulesets.Catch.UI fruit.MoveToY(fruit.Y - 50, 250, Easing.OutSine).Then().MoveToY(fruit.Y + 50, 500, Easing.InSine); fruit.MoveToX(fruit.X + originalX * 6, 1000); fruit.FadeOut(750); - fruit.Expire(true); + + // todo: this shouldn't exist once DrawableHitObject's ClearTransformsAfter overrides are repaired. + fruit.LifetimeStart = Time.Current; + fruit.Expire(); } } } From d385c35955aa89f604c606e8d7051761d5808374 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 21:55:45 +0900 Subject: [PATCH 156/239] Apply suggestions from code review Co-Authored-By: Salman Ahmed --- osu.Game/Tests/Visual/OsuTestScene.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 5a7fbd31e2..b382fdb3c0 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -52,7 +52,7 @@ namespace osu.Game.Tests.Visual get { if (UseOnlineAPI) - throw new Exception("Using the OsuTestScene dummy API is not supported when UseOnlineAPI is true"); + throw new Exception($"Using the {nameof(OsuTestScene)} dummy API is not supported when {nameof(UseOnlineAPI)} is true"); return dummyAPI; } @@ -64,7 +64,7 @@ namespace osu.Game.Tests.Visual /// /// Whether this test scene requires real-world API access. - /// If true, this will bypass the local and use the provided one. + /// If true, this will bypass the local and use the provided one. /// protected virtual bool UseOnlineAPI => false; From 2379b665e3e81cee3eb91bef8bcebc1a0a66c61b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 22:15:11 +0900 Subject: [PATCH 157/239] Use InvalidOperationException --- osu.Game/Tests/Visual/OsuTestScene.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index b382fdb3c0..2b8baab57c 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -52,7 +52,7 @@ namespace osu.Game.Tests.Visual get { if (UseOnlineAPI) - throw new Exception($"Using the {nameof(OsuTestScene)} dummy API is not supported when {nameof(UseOnlineAPI)} is true"); + throw new InvalidOperationException($"Using the {nameof(OsuTestScene)} dummy API is not supported when {nameof(UseOnlineAPI)} is true"); return dummyAPI; } From 82561aa44a30dd0986e79b402168c709218a6527 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 22:44:40 +0900 Subject: [PATCH 158/239] Fix catcher additive sprite rewinding and remove unnecessary update code --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 40d2f64f6a..56c8b33e02 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -199,7 +199,6 @@ namespace osu.Game.Rulesets.Catch.UI additive.Anchor = Anchor; additive.OriginPosition = additive.OriginPosition + new Vector2(DrawWidth / 2, 0); // also temporary to align sprite correctly. - additive.LifetimeStart = Clock.CurrentTime; additive.Position = Position; additive.Scale = Scale; additive.Colour = HyperDashing ? Color4.Red : Color4.White; @@ -208,7 +207,8 @@ namespace osu.Game.Rulesets.Catch.UI AdditiveTarget.Add(additive); - additive.FadeTo(0.4f).FadeOut(800, Easing.OutQuint).Expire(); + additive.FadeTo(0.4f).FadeOut(800, Easing.OutQuint); + additive.Expire(true); Scheduler.AddDelayed(beginTrail, HyperDashing ? 25 : 50); } @@ -303,6 +303,7 @@ namespace osu.Game.Rulesets.Catch.UI { this.FadeColour(Color4.White, hyper_dash_transition_length, Easing.OutQuint); this.FadeTo(1, hyper_dash_transition_length, Easing.OutQuint); + Trail &= Dashing; } } else @@ -386,12 +387,6 @@ namespace osu.Game.Rulesets.Catch.UI X = hyperDashTargetPosition; SetHyperDashState(); } - - if (Clock.ElapsedFrameTime < 0) - { - AdditiveTarget.RemoveAll(d => Clock.CurrentTime < d.LifetimeStart); - caughtFruit.RemoveAll(d => d.HitObject.StartTime > Clock.CurrentTime); - } } /// From 624e5644a4f582d66df2b9ecdc7c2216f5a29394 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 13 Sep 2019 23:05:47 +0900 Subject: [PATCH 159/239] Change osu!catch key trigger to occur on frame before positional change --- .../Replays/CatchReplayFrame.cs | 15 ++++++++------- .../Replays/ManiaReplayFrame.cs | 2 +- osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs | 2 +- .../Replays/TaikoReplayFrame.cs | 2 +- .../Replays/Types/IConvertibleReplayFrame.cs | 4 ++-- osu.Game/Scoring/Legacy/LegacyScoreParser.cs | 12 +++++------- 6 files changed, 18 insertions(+), 19 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs b/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs index 19637f321b..b41a5e0612 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchReplayFrame.cs @@ -33,13 +33,13 @@ namespace osu.Game.Rulesets.Catch.Replays if (lastFrame != null) { if (Position > lastFrame.Position) - Actions.Add(CatchAction.MoveRight); + lastFrame.Actions.Add(CatchAction.MoveRight); else if (Position < lastFrame.Position) - Actions.Add(CatchAction.MoveLeft); + lastFrame.Actions.Add(CatchAction.MoveLeft); } } - public void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, LegacyReplayFrame lastFrame = null) + public void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame lastFrame = null) { Position = currentFrame.Position.X / CatchPlayfield.BASE_WIDTH; Dashing = currentFrame.ButtonState == ReplayButtonState.Left1; @@ -47,11 +47,12 @@ namespace osu.Game.Rulesets.Catch.Replays if (Dashing) Actions.Add(CatchAction.Dash); - if (lastFrame != null) + // this probably needs some cross-checking with osu-stable to ensure it is actually correct. + if (lastFrame is CatchReplayFrame lastCatchFrame) { - if (currentFrame.Position.X > lastFrame.Position.X) - Actions.Add(CatchAction.MoveRight); - else if (currentFrame.Position.X < lastFrame.Position.X) + if (Position > lastCatchFrame.Position) + lastCatchFrame.Actions.Add(CatchAction.MoveRight); + else if (Position < lastCatchFrame.Position) Actions.Add(CatchAction.MoveLeft); } } diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs index b2901f46c0..70ba5cd938 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs @@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Mania.Replays Actions.AddRange(actions); } - public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap, LegacyReplayFrame lastFrame = null) + public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap, ReplayFrame lastFrame = null) { // We don't need to fully convert, just create the converter var converter = new ManiaBeatmapConverter(beatmap); diff --git a/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs b/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs index 441b69ef2d..e6c6db5e61 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuReplayFrame.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Osu.Replays Actions.AddRange(actions); } - public void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, LegacyReplayFrame lastFrame = null) + public void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame lastFrame = null) { Position = currentFrame.Position; if (currentFrame.MouseLeft) Actions.Add(OsuAction.LeftButton); diff --git a/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs b/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs index 6e43892777..c5ebefc397 100644 --- a/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs +++ b/osu.Game.Rulesets.Taiko/Replays/TaikoReplayFrame.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.Replays Actions.AddRange(actions); } - public void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, LegacyReplayFrame lastFrame = null) + public void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame lastFrame = null) { if (currentFrame.MouseRight1) Actions.Add(TaikoAction.LeftRim); if (currentFrame.MouseRight2) Actions.Add(TaikoAction.RightRim); diff --git a/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs b/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs index 8fcdec6630..c2947c0aca 100644 --- a/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs +++ b/osu.Game/Rulesets/Replays/Types/IConvertibleReplayFrame.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Replays.Types /// /// The to extract values from. /// The beatmap. - /// The last , used to fill in missing delta information. May be null. - void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, LegacyReplayFrame lastFrame = null); + /// The last post-conversion , used to fill in missing delta information. May be null. + void ConvertFrom(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame lastFrame = null); } } diff --git a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs index 5a90daa045..2cdd0c4b5e 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreParser.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreParser.cs @@ -218,7 +218,7 @@ namespace osu.Game.Scoring.Legacy private void readLegacyReplay(Replay replay, StreamReader reader) { float lastTime = 0; - LegacyReplayFrame currentFrame = null; + ReplayFrame currentFrame = null; foreach (var l in reader.ReadToEnd().Split(',')) { @@ -241,18 +241,16 @@ namespace osu.Game.Scoring.Legacy if (diff < 0) continue; - var lastFrame = currentFrame; - - currentFrame = new LegacyReplayFrame(lastTime, + currentFrame = convertFrame(new LegacyReplayFrame(lastTime, Parsing.ParseFloat(split[1], Parsing.MAX_COORDINATE_VALUE), Parsing.ParseFloat(split[2], Parsing.MAX_COORDINATE_VALUE), - (ReplayButtonState)Parsing.ParseInt(split[3])); + (ReplayButtonState)Parsing.ParseInt(split[3])), currentFrame); - replay.Frames.Add(convertFrame(currentFrame, lastFrame)); + replay.Frames.Add(currentFrame); } } - private ReplayFrame convertFrame(LegacyReplayFrame currentFrame, LegacyReplayFrame lastFrame) + private ReplayFrame convertFrame(LegacyReplayFrame currentFrame, ReplayFrame lastFrame) { var convertible = currentRuleset.CreateConvertibleReplayFrame(); if (convertible == null) From 65aa7b20169e6a92444713fa010ce65582a591c1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 14 Sep 2019 00:07:06 +0900 Subject: [PATCH 160/239] Recreate beatmap video on each consumption Should not be shared over multiple usages --- osu.Game/Beatmaps/WorkingBeatmap.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index bf3fa90d7b..3fc33e9f52 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -44,7 +44,6 @@ namespace osu.Game.Beatmaps track = new RecyclableLazy(() => GetTrack() ?? GetVirtualTrack()); background = new RecyclableLazy(GetBackground, BackgroundStillValid); - video = new RecyclableLazy(GetVideo); waveform = new RecyclableLazy(GetWaveform); storyboard = new RecyclableLazy(GetStoryboard); skin = new RecyclableLazy(GetSkin); @@ -188,11 +187,9 @@ namespace osu.Game.Beatmaps protected abstract Texture GetBackground(); private readonly RecyclableLazy background; - public bool VideoLoaded => video.IsResultAvailable; - public VideoSprite Video => video.Value; + public VideoSprite Video => GetVideo(); protected abstract VideoSprite GetVideo(); - private readonly RecyclableLazy video; public bool TrackLoaded => track.IsResultAvailable; public Track Track => track.Value; From 9a94405b3a195d18ddcfaf2e1a01a683bff7bd52 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 14 Sep 2019 06:05:09 +0300 Subject: [PATCH 161/239] Fix video playback is stretched on client resize --- osu.Game/Screens/Play/DimmableVideo.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/DimmableVideo.cs b/osu.Game/Screens/Play/DimmableVideo.cs index 3e6b95d2cc..4981c3457f 100644 --- a/osu.Game/Screens/Play/DimmableVideo.cs +++ b/osu.Game/Screens/Play/DimmableVideo.cs @@ -59,8 +59,12 @@ namespace osu.Game.Screens.Play RelativeSizeAxes = Axes.Both; Masking = true; - AddInternal(video); video.RelativeSizeAxes = Axes.Both; + video.FillMode = FillMode.Fill; + video.Anchor = Anchor.Centre; + video.Origin = Anchor.Centre; + + AddInternal(video); } [BackgroundDependencyLoader] From 8ad782a82d71b03d6f17bec85b35bbacf6e30102 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 14 Sep 2019 06:16:25 +0300 Subject: [PATCH 162/239] Fix RankingsHeader dropdown can be clickable when not visible --- osu.Game/Overlays/Rankings/RankingsHeader.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Rankings/RankingsHeader.cs b/osu.Game/Overlays/Rankings/RankingsHeader.cs index fbf3097f4f..13c1f0fe40 100644 --- a/osu.Game/Overlays/Rankings/RankingsHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsHeader.cs @@ -31,7 +31,6 @@ namespace osu.Game.Overlays.Rankings public readonly Bindable Country = new Bindable(); public readonly Bindable Spotlight = new Bindable(); - private readonly Container dropdownPlaceholder; private readonly OsuDropdown dropdown; public RankingsHeader() @@ -86,14 +85,13 @@ namespace osu.Game.Overlays.Rankings Scope = { BindTarget = Scope }, Country = { BindTarget = Country }, }, - dropdownPlaceholder = new Container + new Container { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.X, Height = dropdown_height, Width = 0.8f, - AlwaysPresent = true, Child = dropdown = new OsuDropdown { RelativeSizeAxes = Axes.X, @@ -115,7 +113,7 @@ namespace osu.Game.Overlays.Rankings } private void onScopeChanged(ValueChangedEvent scope) => - dropdownPlaceholder.FadeTo(scope.NewValue == RankingsScope.Spotlights ? 1 : 0, 200, Easing.OutQuint); + dropdown.FadeTo(scope.NewValue == RankingsScope.Spotlights ? 1 : 0, 200, Easing.OutQuint); private class HeaderBackground : Sprite { From a36c80868247ff5a7fe1c180378e34e95732a905 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 14 Sep 2019 06:28:59 +0300 Subject: [PATCH 163/239] Use Fit FillFode --- osu.Game/Screens/Play/DimmableVideo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/DimmableVideo.cs b/osu.Game/Screens/Play/DimmableVideo.cs index 4981c3457f..628871b164 100644 --- a/osu.Game/Screens/Play/DimmableVideo.cs +++ b/osu.Game/Screens/Play/DimmableVideo.cs @@ -60,7 +60,7 @@ namespace osu.Game.Screens.Play Masking = true; video.RelativeSizeAxes = Axes.Both; - video.FillMode = FillMode.Fill; + video.FillMode = FillMode.Fit; video.Anchor = Anchor.Centre; video.Origin = Anchor.Centre; From 9febeb1f3def1c30e07c825785f5c2557bbdcb26 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 14 Sep 2019 06:32:00 +0300 Subject: [PATCH 164/239] Add black background --- osu.Game/Screens/Play/DimmableVideo.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/DimmableVideo.cs b/osu.Game/Screens/Play/DimmableVideo.cs index 628871b164..4d6c10d69d 100644 --- a/osu.Game/Screens/Play/DimmableVideo.cs +++ b/osu.Game/Screens/Play/DimmableVideo.cs @@ -4,8 +4,10 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Video; using osu.Game.Graphics.Containers; +using osuTK.Graphics; namespace osu.Game.Screens.Play { @@ -64,7 +66,15 @@ namespace osu.Game.Screens.Play video.Anchor = Anchor.Centre; video.Origin = Anchor.Centre; - AddInternal(video); + AddRangeInternal(new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + }, + video, + }); } [BackgroundDependencyLoader] From 2783ae62ef7b409b5b6a5d9f4f3867d1553d2bf6 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sat, 14 Sep 2019 06:34:57 +0300 Subject: [PATCH 165/239] Remove useless container --- osu.Game/Overlays/Rankings/RankingsHeader.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/osu.Game/Overlays/Rankings/RankingsHeader.cs b/osu.Game/Overlays/Rankings/RankingsHeader.cs index 13c1f0fe40..6aa3e75df9 100644 --- a/osu.Game/Overlays/Rankings/RankingsHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsHeader.cs @@ -18,7 +18,6 @@ namespace osu.Game.Overlays.Rankings public class RankingsHeader : CompositeDrawable { private const int content_height = 250; - private const int dropdown_height = 50; public IEnumerable Spotlights { @@ -85,18 +84,13 @@ namespace osu.Game.Overlays.Rankings Scope = { BindTarget = Scope }, Country = { BindTarget = Country }, }, - new Container + dropdown = new OsuDropdown { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.X, - Height = dropdown_height, Width = 0.8f, - Child = dropdown = new OsuDropdown - { - RelativeSizeAxes = Axes.X, - Current = Spotlight, - } + Current = Spotlight, } } }, From 8456861b8d58f5b4bb7695d81aaee02a952717d8 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Sat, 14 Sep 2019 17:08:56 +0300 Subject: [PATCH 166/239] Wait for cursor hiding using ManualResetEventSlim --- osu.Game/Graphics/ScreenshotManager.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index f532302de2..02d928ec66 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -83,11 +83,19 @@ namespace osu.Game.Graphics const int frames_to_wait = 3; int framesWaited = 0; - ScheduledDelegate waitDelegate = host.DrawThread.Scheduler.AddDelayed(() => framesWaited++, 0, true); - while (framesWaited < frames_to_wait) - Thread.Sleep(10); - waitDelegate.Cancel(); + using (var framesWaitedEvent = new ManualResetEventSlim(false)) + { + ScheduledDelegate waitDelegate = host.DrawThread.Scheduler.AddDelayed(() => + { + if (framesWaited++ < frames_to_wait) + // ReSharper disable once AccessToDisposedClosure + framesWaitedEvent.Set(); + }, 10, true); + + framesWaitedEvent.Wait(); + waitDelegate.Cancel(); + } } using (var image = await host.TakeScreenshotAsync()) From babd34470ea38ca7b38cc80fbbb6a00f8ed7bfaf Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 15 Sep 2019 02:33:21 +0300 Subject: [PATCH 167/239] Fix DrawableFlag returns empty texture if there's no flag avaliable for needed country --- osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs | 7 +++++++ osu.Game/Users/Drawables/DrawableFlag.cs | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs index 0ceb5f21d3..c0da605cdb 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsHeader.cs @@ -61,10 +61,17 @@ namespace osu.Game.Tests.Visual.Online FullName = "Belarus" }; + var unknownCountry = new Country + { + FlagName = "CK", + FullName = "Cook Islands" + }; + AddStep("Set country", () => countryBindable.Value = country); AddAssert("Check scope is Performance", () => scope.Value == RankingsScope.Performance); AddStep("Set scope to Score", () => scope.Value = RankingsScope.Score); AddAssert("Check country is Null", () => countryBindable.Value == null); + AddStep("Set country with no flag", () => countryBindable.Value = unknownCountry); } } } diff --git a/osu.Game/Users/Drawables/DrawableFlag.cs b/osu.Game/Users/Drawables/DrawableFlag.cs index 368354e48e..fab561c1af 100644 --- a/osu.Game/Users/Drawables/DrawableFlag.cs +++ b/osu.Game/Users/Drawables/DrawableFlag.cs @@ -26,7 +26,7 @@ namespace osu.Game.Users.Drawables if (ts == null) throw new ArgumentNullException(nameof(ts)); - Texture = ts.Get($@"Flags/{country?.FlagName ?? @"__"}"); + Texture = ts.Get($@"Flags/{country?.FlagName ?? @"__"}") ?? ts.Get($@"Flags/__"); } } } From 96453d8197be660721540348198819d551bf04ef Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Sun, 15 Sep 2019 02:46:28 +0300 Subject: [PATCH 168/239] Remove redundant string interpolation --- osu.Game/Users/Drawables/DrawableFlag.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Users/Drawables/DrawableFlag.cs b/osu.Game/Users/Drawables/DrawableFlag.cs index fab561c1af..1d648e46b6 100644 --- a/osu.Game/Users/Drawables/DrawableFlag.cs +++ b/osu.Game/Users/Drawables/DrawableFlag.cs @@ -26,7 +26,7 @@ namespace osu.Game.Users.Drawables if (ts == null) throw new ArgumentNullException(nameof(ts)); - Texture = ts.Get($@"Flags/{country?.FlagName ?? @"__"}") ?? ts.Get($@"Flags/__"); + Texture = ts.Get($@"Flags/{country?.FlagName ?? @"__"}") ?? ts.Get(@"Flags/__"); } } } From 2381b4c00365e8d59003b9fc235f25e953618cb7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 16 Sep 2019 00:20:56 +0900 Subject: [PATCH 169/239] Move video behind storyboard --- osu.Game/Screens/Play/Player.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 5c7ac9e762..309f4837e5 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -143,8 +143,8 @@ namespace osu.Game.Screens.Play private void addUnderlayComponents(Container target) { - target.Add(DimmableStoryboard = new DimmableStoryboard(Beatmap.Value.Storyboard) { RelativeSizeAxes = Axes.Both }); target.Add(DimmableVideo = new DimmableVideo(Beatmap.Value.Video) { RelativeSizeAxes = Axes.Both }); + target.Add(DimmableStoryboard = new DimmableStoryboard(Beatmap.Value.Storyboard) { RelativeSizeAxes = Axes.Both }); } private void addGameplayComponents(Container target, WorkingBeatmap working) From 43760bdfcdfffd6301a4cba30c2d86c131b8a2c2 Mon Sep 17 00:00:00 2001 From: HoLLy-HaCKeR Date: Sun, 15 Sep 2019 18:29:14 +0200 Subject: [PATCH 170/239] Specify Rider analysis rules explicitly --- osu.Android.sln.DotSettings | 21 ++++++++++++++++++++- osu.iOS.sln.DotSettings | 22 +++++++++++++++++++++- osu.sln.DotSettings | 12 ++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/osu.Android.sln.DotSettings b/osu.Android.sln.DotSettings index 3f5bd9d34d..5a97fc7518 100644 --- a/osu.Android.sln.DotSettings +++ b/osu.Android.sln.DotSettings @@ -1,4 +1,4 @@ - + True True True @@ -167,6 +167,14 @@ WARNING <?xml version="1.0" encoding="utf-16"?><Profile name="Code Cleanup (peppy)"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="False" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" /><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSArrangeQualifiers>True</CSArrangeQualifiers></Profile> Code Cleanup (peppy) + Required + Required + Required + Explicit + ExpressionBody + ExpressionBody + True + NEXT_LINE True True True @@ -176,12 +184,22 @@ True True NEXT_LINE + 1 + 1 + NEXT_LINE + MULTILINE NEXT_LINE + 1 + 1 True + NEXT_LINE NEVER NEVER + True False + True NEVER + False False True False @@ -189,6 +207,7 @@ True True False + False CHOP_IF_LONG True 200 diff --git a/osu.iOS.sln.DotSettings b/osu.iOS.sln.DotSettings index 3b2b851d45..752b817910 100644 --- a/osu.iOS.sln.DotSettings +++ b/osu.iOS.sln.DotSettings @@ -1,4 +1,4 @@ - + True True True @@ -165,8 +165,17 @@ HINT HINT WARNING + WARNING <?xml version="1.0" encoding="utf-16"?><Profile name="Code Cleanup (peppy)"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="False" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" /><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSArrangeQualifiers>True</CSArrangeQualifiers></Profile> Code Cleanup (peppy) + Required + Required + Required + Explicit + ExpressionBody + ExpressionBody + True + NEXT_LINE True True True @@ -176,12 +185,22 @@ True True NEXT_LINE + 1 + 1 + NEXT_LINE + MULTILINE NEXT_LINE + 1 + 1 True + NEXT_LINE NEVER NEVER + True False + True NEVER + False False True False @@ -189,6 +208,7 @@ True True False + False CHOP_IF_LONG True 200 diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index c3e274569d..ed162eed6e 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -218,9 +218,14 @@ WARNING <?xml version="1.0" encoding="utf-16"?><Profile name="Code Cleanup (peppy)"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="False" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" /><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSArrangeQualifiers>True</CSArrangeQualifiers></Profile> Code Cleanup (peppy) + Required + Required + Required + Explicit ExpressionBody ExpressionBody True + NEXT_LINE True True True @@ -232,14 +237,20 @@ NEXT_LINE 1 1 + NEXT_LINE + MULTILINE NEXT_LINE 1 1 True + NEXT_LINE NEVER NEVER + True False + True NEVER + False False True False @@ -247,6 +258,7 @@ True True False + False CHOP_IF_LONG True 200 From a407e267a238575d1418a94f3d912479a84f0bca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 15 Sep 2019 22:55:25 +0200 Subject: [PATCH 171/239] Fix PF/SD legacy mod conversion Upon investigating an user report in #6091 that indicated that viewing replays using the Perfect mod would also display the Sudden Death mod icon despite Perfect being the more restrictive of the two, it turned out that the logic of importing legacy scores was missing that corner case. A similar case of Double Time/Nightcore mutual exclusion was handled, but PF/SD was missed. Add analogous handling of PF/SD legacy mods for all four rulesets, and additionally cover a tiny fraction of all cases with unit tests. The most problematic cases (NC+HD and PF+SD) are covered in all four basic rulesets. --- .../CatchLegacyModConversionTest.cs | 29 +++++++++++++++ osu.Game.Rulesets.Catch/CatchRuleset.cs | 11 +++--- .../ManiaLegacyModConversionTest.cs | 30 ++++++++++++++++ osu.Game.Rulesets.Mania/ManiaRuleset.cs | 11 +++--- .../OsuLegacyModConversionTest.cs | 30 ++++++++++++++++ osu.Game.Rulesets.Osu/OsuRuleset.cs | 11 +++--- .../TaikoLegacyModConversionTest.cs | 29 +++++++++++++++ osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 11 +++--- .../Tests/Beatmaps/LegacyModConversionTest.cs | 35 +++++++++++++++++++ 9 files changed, 173 insertions(+), 24 deletions(-) create mode 100644 osu.Game.Rulesets.Catch.Tests/CatchLegacyModConversionTest.cs create mode 100644 osu.Game.Rulesets.Mania.Tests/ManiaLegacyModConversionTest.cs create mode 100644 osu.Game.Rulesets.Osu.Tests/OsuLegacyModConversionTest.cs create mode 100644 osu.Game.Rulesets.Taiko.Tests/TaikoLegacyModConversionTest.cs create mode 100644 osu.Game/Tests/Beatmaps/LegacyModConversionTest.cs diff --git a/osu.Game.Rulesets.Catch.Tests/CatchLegacyModConversionTest.cs b/osu.Game.Rulesets.Catch.Tests/CatchLegacyModConversionTest.cs new file mode 100644 index 0000000000..04e6dea376 --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests/CatchLegacyModConversionTest.cs @@ -0,0 +1,29 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using NUnit.Framework; +using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets.Catch.Mods; +using osu.Game.Tests.Beatmaps; + +namespace osu.Game.Rulesets.Catch.Tests +{ + [TestFixture] + public class CatchLegacyModConversionTest : LegacyModConversionTest + { + [TestCase(LegacyMods.Easy, new[] { typeof(CatchModEasy) })] + [TestCase(LegacyMods.HardRock | LegacyMods.DoubleTime, new[] { typeof(CatchModHardRock), typeof(CatchModDoubleTime) })] + [TestCase(LegacyMods.DoubleTime, new[] { typeof(CatchModDoubleTime) })] + [TestCase(LegacyMods.Nightcore, new[] { typeof(CatchModNightcore) })] + [TestCase(LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(CatchModNightcore) })] + [TestCase(LegacyMods.Flashlight | LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(CatchModFlashlight), typeof(CatchModNightcore) })] + [TestCase(LegacyMods.Perfect, new[] { typeof(CatchModPerfect) })] + [TestCase(LegacyMods.SuddenDeath, new[] { typeof(CatchModSuddenDeath) })] + [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath, new[] { typeof(CatchModPerfect) })] + [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath | LegacyMods.DoubleTime, new[] { typeof(CatchModDoubleTime), typeof(CatchModPerfect) })] + public new void Test(LegacyMods legacyMods, Type[] expectedMods) => base.Test(legacyMods, expectedMods); + + protected override Ruleset CreateRuleset() => new CatchRuleset(); + } +} diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 5428b4eeb8..71d68ace94 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -46,6 +46,11 @@ namespace osu.Game.Rulesets.Catch else if (mods.HasFlag(LegacyMods.DoubleTime)) yield return new CatchModDoubleTime(); + if (mods.HasFlag(LegacyMods.Perfect)) + yield return new CatchModPerfect(); + else if (mods.HasFlag(LegacyMods.SuddenDeath)) + yield return new CatchModSuddenDeath(); + if (mods.HasFlag(LegacyMods.Autoplay)) yield return new CatchModAutoplay(); @@ -67,14 +72,8 @@ namespace osu.Game.Rulesets.Catch if (mods.HasFlag(LegacyMods.NoFail)) yield return new CatchModNoFail(); - if (mods.HasFlag(LegacyMods.Perfect)) - yield return new CatchModPerfect(); - if (mods.HasFlag(LegacyMods.Relax)) yield return new CatchModRelax(); - - if (mods.HasFlag(LegacyMods.SuddenDeath)) - yield return new CatchModSuddenDeath(); } public override IEnumerable GetModsFor(ModType type) diff --git a/osu.Game.Rulesets.Mania.Tests/ManiaLegacyModConversionTest.cs b/osu.Game.Rulesets.Mania.Tests/ManiaLegacyModConversionTest.cs new file mode 100644 index 0000000000..957743c5f1 --- /dev/null +++ b/osu.Game.Rulesets.Mania.Tests/ManiaLegacyModConversionTest.cs @@ -0,0 +1,30 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using NUnit.Framework; +using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets.Mania.Mods; +using osu.Game.Tests.Beatmaps; + +namespace osu.Game.Rulesets.Mania.Tests +{ + [TestFixture] + public class ManiaLegacyModConversionTest : LegacyModConversionTest + { + [TestCase(LegacyMods.Easy, new[] { typeof(ManiaModEasy) })] + [TestCase(LegacyMods.HardRock | LegacyMods.DoubleTime, new[] { typeof(ManiaModHardRock), typeof(ManiaModDoubleTime) })] + [TestCase(LegacyMods.DoubleTime, new[] { typeof(ManiaModDoubleTime) })] + [TestCase(LegacyMods.Nightcore, new[] { typeof(ManiaModNightcore) })] + [TestCase(LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(ManiaModNightcore) })] + [TestCase(LegacyMods.Flashlight | LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(ManiaModFlashlight), typeof(ManiaModNightcore) })] + [TestCase(LegacyMods.Perfect, new[] { typeof(ManiaModPerfect) })] + [TestCase(LegacyMods.SuddenDeath, new[] { typeof(ManiaModSuddenDeath) })] + [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath, new[] { typeof(ManiaModPerfect) })] + [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath | LegacyMods.DoubleTime, new[] { typeof(ManiaModDoubleTime), typeof(ManiaModPerfect) })] + [TestCase(LegacyMods.Random | LegacyMods.SuddenDeath, new[] { typeof(ManiaModRandom), typeof(ManiaModSuddenDeath) })] + public new void Test(LegacyMods legacyMods, Type[] expectedMods) => base.Test(legacyMods, expectedMods); + + protected override Ruleset CreateRuleset() => new ManiaRuleset(); + } +} diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 0c4e7d4858..c74a292331 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -46,6 +46,11 @@ namespace osu.Game.Rulesets.Mania else if (mods.HasFlag(LegacyMods.DoubleTime)) yield return new ManiaModDoubleTime(); + if (mods.HasFlag(LegacyMods.Perfect)) + yield return new ManiaModPerfect(); + else if (mods.HasFlag(LegacyMods.SuddenDeath)) + yield return new ManiaModSuddenDeath(); + if (mods.HasFlag(LegacyMods.Autoplay)) yield return new ManiaModAutoplay(); @@ -97,14 +102,8 @@ namespace osu.Game.Rulesets.Mania if (mods.HasFlag(LegacyMods.NoFail)) yield return new ManiaModNoFail(); - if (mods.HasFlag(LegacyMods.Perfect)) - yield return new ManiaModPerfect(); - if (mods.HasFlag(LegacyMods.Random)) yield return new ManiaModRandom(); - - if (mods.HasFlag(LegacyMods.SuddenDeath)) - yield return new ManiaModSuddenDeath(); } public override IEnumerable GetModsFor(ModType type) diff --git a/osu.Game.Rulesets.Osu.Tests/OsuLegacyModConversionTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuLegacyModConversionTest.cs new file mode 100644 index 0000000000..495f2738b5 --- /dev/null +++ b/osu.Game.Rulesets.Osu.Tests/OsuLegacyModConversionTest.cs @@ -0,0 +1,30 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using NUnit.Framework; +using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Tests.Beatmaps; + +namespace osu.Game.Rulesets.Osu.Tests +{ + [TestFixture] + public class OsuLegacyModConversionTest : LegacyModConversionTest + { + [TestCase(LegacyMods.Easy, new[] { typeof(OsuModEasy) })] + [TestCase(LegacyMods.HardRock | LegacyMods.DoubleTime, new[] { typeof(OsuModHardRock), typeof(OsuModDoubleTime) })] + [TestCase(LegacyMods.DoubleTime, new[] { typeof(OsuModDoubleTime) })] + [TestCase(LegacyMods.Nightcore, new[] { typeof(OsuModNightcore) })] + [TestCase(LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(OsuModNightcore) })] + [TestCase(LegacyMods.Flashlight | LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(OsuModFlashlight), typeof(OsuModFlashlight) })] + [TestCase(LegacyMods.Perfect, new[] { typeof(OsuModPerfect) })] + [TestCase(LegacyMods.SuddenDeath, new[] { typeof(OsuModSuddenDeath) })] + [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath, new[] { typeof(OsuModPerfect) })] + [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath | LegacyMods.DoubleTime, new[] { typeof(OsuModDoubleTime), typeof(OsuModPerfect) })] + [TestCase(LegacyMods.SpunOut | LegacyMods.Easy, new[] { typeof(OsuModSpunOut), typeof(OsuModEasy) })] + public new void Test(LegacyMods legacyMods, Type[] expectedMods) => base.Test(legacyMods, expectedMods); + + protected override Ruleset CreateRuleset() => new OsuRuleset(); + } +} diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index ceb9ed9343..df2ae81a5a 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -52,6 +52,11 @@ namespace osu.Game.Rulesets.Osu else if (mods.HasFlag(LegacyMods.DoubleTime)) yield return new OsuModDoubleTime(); + if (mods.HasFlag(LegacyMods.Perfect)) + yield return new OsuModPerfect(); + else if (mods.HasFlag(LegacyMods.SuddenDeath)) + yield return new OsuModSuddenDeath(); + if (mods.HasFlag(LegacyMods.Autopilot)) yield return new OsuModAutopilot(); @@ -76,18 +81,12 @@ namespace osu.Game.Rulesets.Osu if (mods.HasFlag(LegacyMods.NoFail)) yield return new OsuModNoFail(); - if (mods.HasFlag(LegacyMods.Perfect)) - yield return new OsuModPerfect(); - if (mods.HasFlag(LegacyMods.Relax)) yield return new OsuModRelax(); if (mods.HasFlag(LegacyMods.SpunOut)) yield return new OsuModSpunOut(); - if (mods.HasFlag(LegacyMods.SuddenDeath)) - yield return new OsuModSuddenDeath(); - if (mods.HasFlag(LegacyMods.Target)) yield return new OsuModTarget(); diff --git a/osu.Game.Rulesets.Taiko.Tests/TaikoLegacyModConversionTest.cs b/osu.Game.Rulesets.Taiko.Tests/TaikoLegacyModConversionTest.cs new file mode 100644 index 0000000000..a59544386b --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests/TaikoLegacyModConversionTest.cs @@ -0,0 +1,29 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using NUnit.Framework; +using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets.Taiko.Mods; +using osu.Game.Tests.Beatmaps; + +namespace osu.Game.Rulesets.Taiko.Tests +{ + [TestFixture] + public class TaikoLegacyModConversionTest : LegacyModConversionTest + { + [TestCase(LegacyMods.Easy, new[] { typeof(TaikoModEasy) })] + [TestCase(LegacyMods.HardRock | LegacyMods.DoubleTime, new[] { typeof(TaikoModHardRock), typeof(TaikoModDoubleTime) })] + [TestCase(LegacyMods.DoubleTime, new[] { typeof(TaikoModDoubleTime) })] + [TestCase(LegacyMods.Nightcore, new[] { typeof(TaikoModNightcore) })] + [TestCase(LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(TaikoModNightcore) })] + [TestCase(LegacyMods.Flashlight | LegacyMods.Nightcore | LegacyMods.DoubleTime, new[] { typeof(TaikoModFlashlight), typeof(TaikoModNightcore) })] + [TestCase(LegacyMods.Perfect, new[] { typeof(TaikoModPerfect) })] + [TestCase(LegacyMods.SuddenDeath, new[] { typeof(TaikoModSuddenDeath) })] + [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath, new[] { typeof(TaikoModPerfect) })] + [TestCase(LegacyMods.Perfect | LegacyMods.SuddenDeath | LegacyMods.DoubleTime, new[] { typeof(TaikoModDoubleTime), typeof(TaikoModPerfect) })] + public new void Test(LegacyMods legacyMods, Type[] expectedMods) => base.Test(legacyMods, expectedMods); + + protected override Ruleset CreateRuleset() => new TaikoRuleset(); + } +} diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 7fdb823388..b2655f592c 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -45,6 +45,11 @@ namespace osu.Game.Rulesets.Taiko else if (mods.HasFlag(LegacyMods.DoubleTime)) yield return new TaikoModDoubleTime(); + if (mods.HasFlag(LegacyMods.Perfect)) + yield return new TaikoModPerfect(); + else if (mods.HasFlag(LegacyMods.SuddenDeath)) + yield return new TaikoModSuddenDeath(); + if (mods.HasFlag(LegacyMods.Autoplay)) yield return new TaikoModAutoplay(); @@ -66,14 +71,8 @@ namespace osu.Game.Rulesets.Taiko if (mods.HasFlag(LegacyMods.NoFail)) yield return new TaikoModNoFail(); - if (mods.HasFlag(LegacyMods.Perfect)) - yield return new TaikoModPerfect(); - if (mods.HasFlag(LegacyMods.Relax)) yield return new TaikoModRelax(); - - if (mods.HasFlag(LegacyMods.SuddenDeath)) - yield return new TaikoModSuddenDeath(); } public override IEnumerable GetModsFor(ModType type) diff --git a/osu.Game/Tests/Beatmaps/LegacyModConversionTest.cs b/osu.Game/Tests/Beatmaps/LegacyModConversionTest.cs new file mode 100644 index 0000000000..e9251f8011 --- /dev/null +++ b/osu.Game/Tests/Beatmaps/LegacyModConversionTest.cs @@ -0,0 +1,35 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Linq; +using NUnit.Framework; +using osu.Game.Beatmaps.Legacy; +using osu.Game.Rulesets; + +namespace osu.Game.Tests.Beatmaps +{ + /// + /// Base class for tests of converting enumeration flags to ruleset mod instances. + /// + public abstract class LegacyModConversionTest + { + /// + /// Creates the whose legacy mod conversion is to be tested. + /// + /// + protected abstract Ruleset CreateRuleset(); + + protected void Test(LegacyMods legacyMods, Type[] expectedMods) + { + var ruleset = CreateRuleset(); + var mods = ruleset.ConvertLegacyMods(legacyMods).ToList(); + Assert.AreEqual(expectedMods.Length, mods.Count); + + foreach (var modType in expectedMods) + { + Assert.IsNotNull(mods.SingleOrDefault(mod => mod.GetType() == modType)); + } + } + } +} From efedfefe635e63c8cad19c73ff56e29482741be9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Sep 2019 15:54:11 +0900 Subject: [PATCH 172/239] Fix disclaimer potentially pushing a null screen --- osu.Game/Screens/Menu/Disclaimer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Menu/Disclaimer.cs b/osu.Game/Screens/Menu/Disclaimer.cs index 073ab639e3..17f999d519 100644 --- a/osu.Game/Screens/Menu/Disclaimer.cs +++ b/osu.Game/Screens/Menu/Disclaimer.cs @@ -173,7 +173,11 @@ namespace osu.Game.Screens.Menu .Then(5500) .FadeOut(250) .ScaleTo(0.9f, 250, Easing.InQuint) - .Finally(d => this.Push(nextScreen)); + .Finally(d => + { + if (nextScreen != null) + this.Push(nextScreen); + }); } } } From f0bcb2b9337a94fa429b9aa609c5444f95dbab34 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 17 Sep 2019 16:12:18 +0900 Subject: [PATCH 173/239] Debounce user-requested replay seeks --- osu.Game/Screens/Play/SongProgressBar.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/SongProgressBar.cs b/osu.Game/Screens/Play/SongProgressBar.cs index dd7b5826d5..33c7595b37 100644 --- a/osu.Game/Screens/Play/SongProgressBar.cs +++ b/osu.Game/Screens/Play/SongProgressBar.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; using osu.Framework.MathUtils; +using osu.Framework.Threading; namespace osu.Game.Screens.Play { @@ -121,6 +122,12 @@ namespace osu.Game.Screens.Play handleBase.X = newX; } - protected override void OnUserChange(double value) => OnSeek?.Invoke(value); + private ScheduledDelegate scheduledSeek; + + protected override void OnUserChange(double value) + { + scheduledSeek?.Cancel(); + scheduledSeek = Schedule(() => OnSeek?.Invoke(value)); + } } } From 77947e83097164eb73adc4b380fd2b80fcf643e4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Sep 2019 22:33:27 +0900 Subject: [PATCH 174/239] Fix rewind tests failing --- .../Replays/CatchAutoGenerator.cs | 1 + .../Replays/ManiaAutoGenerator.cs | 1 + .../Visual/Gameplay/TestSceneAutoplay.cs | 19 ++++++++++++++----- osu.Game/Screens/Play/GameplayClock.cs | 2 ++ osu.Game/Tests/Visual/OsuTestScene.cs | 4 ++-- 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index 4ea1f22006..7f972a25ae 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -39,6 +39,7 @@ namespace osu.Game.Rulesets.Catch.Replays // Todo: Realistically this shouldn't be needed, but the first frame is skipped with the way replays are currently handled addFrame(-100000, lastPosition); + addFrame(0, lastPosition); void moveToNext(CatchHitObject h) { diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index 7b8bbc2095..5d333e2047 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -49,6 +49,7 @@ namespace osu.Game.Rulesets.Mania.Replays { // Todo: Realistically this shouldn't be needed, but the first frame is skipped with the way replays are currently handled Replay.Frames.Add(new ManiaReplayFrame(-100000, 0)); + Replay.Frames.Add(new ManiaReplayFrame(0, 0)); var pointGroups = generateActionPoints().GroupBy(a => a.Time).OrderBy(g => g.First().Time); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs index e2b620ea98..883aa9fc36 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs @@ -3,6 +3,7 @@ using System.ComponentModel; using System.Linq; +using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Rulesets.Scoring; using osu.Game.Screens.Play; @@ -12,6 +13,8 @@ namespace osu.Game.Tests.Visual.Gameplay [Description("Player instantiated with an autoplay mod.")] public class TestSceneAutoplay : AllPlayersTestScene { + private ClockBackedTestWorkingBeatmap.TrackVirtualManual track; + protected override Player CreatePlayer(Ruleset ruleset) { Mods.Value = Mods.Value.Concat(new[] { ruleset.GetAutoplayMod() }).ToArray(); @@ -22,11 +25,17 @@ namespace osu.Game.Tests.Visual.Gameplay { AddUntilStep("score above zero", () => ((ScoreAccessiblePlayer)Player).ScoreProcessor.TotalScore.Value > 0); AddUntilStep("key counter counted keys", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 5)); - AddStep("rewind", () => - { - ((ScoreAccessiblePlayer)Player).GameplayClockContainer.Seek(0); - }); - AddUntilStep("key counter counted no", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0)); + AddStep("rewind", () => track.Seek(-10000)); + AddUntilStep("key counter reset", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0)); + } + + protected override WorkingBeatmap CreateWorkingBeatmap(IBeatmap beatmap) + { + var working = base.CreateWorkingBeatmap(beatmap); + + track = (ClockBackedTestWorkingBeatmap.TrackVirtualManual)working.Track; + + return working; } private class ScoreAccessiblePlayer : TestPlayer diff --git a/osu.Game/Screens/Play/GameplayClock.cs b/osu.Game/Screens/Play/GameplayClock.cs index b1948d02d5..379c4c89ed 100644 --- a/osu.Game/Screens/Play/GameplayClock.cs +++ b/osu.Game/Screens/Play/GameplayClock.cs @@ -42,5 +42,7 @@ namespace osu.Game.Screens.Play public double FramesPerSecond => underlyingClock.FramesPerSecond; public FrameTimeInfo TimeInfo => underlyingClock.TimeInfo; + + public IClock Source => underlyingClock; } } diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 2b8baab57c..32a32cfa43 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -239,7 +239,7 @@ namespace osu.Game.Tests.Visual public override bool Seek(double seek) { - offset = MathHelper.Clamp(seek, 0, Length); + offset = Math.Min(seek, Length); lastReferenceTime = null; return offset == seek; From 057c4aa795657654822ce73c086352e75a9677f3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Sep 2019 22:42:20 +0900 Subject: [PATCH 175/239] Remove unused using statement --- osu.Game/Tests/Visual/OsuTestScene.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 32a32cfa43..2bc9273f69 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -20,7 +20,6 @@ using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Tests.Beatmaps; -using osuTK; namespace osu.Game.Tests.Visual { From 3ab352ffe51b0a37fef9af64569b91c9bbc0d2b0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Sep 2019 23:08:37 +0900 Subject: [PATCH 176/239] Randomise beatmap playback order on startup Closes #6135. --- osu.Game/Overlays/Music/PlaylistList.cs | 18 ++++++++++-------- osu.Game/Overlays/MusicController.cs | 21 +++++++++++---------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index 539601c359..6ad0aa23ec 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; @@ -44,6 +45,8 @@ namespace osu.Game.Overlays.Music private class ItemsScrollContainer : OsuScrollContainer { + private BindableList beatmaps; + public Action Selected; public Action OrderChanged; @@ -73,20 +76,19 @@ namespace osu.Game.Overlays.Music } [BackgroundDependencyLoader] - private void load(BeatmapManager beatmaps, IBindable beatmap) + private void load(MusicController musicController, IBindable beatmap) { - beatmaps.GetAllUsableBeatmapSets().ForEach(addBeatmapSet); - beatmaps.ItemAdded += addBeatmapSet; - beatmaps.ItemRemoved += removeBeatmapSet; + beatmaps = musicController.BeatmapSets.GetBoundCopy(); + + beatmaps.ItemsAdded += i => i.ForEach(addBeatmapSet); + beatmaps.ItemsRemoved += i => i.ForEach(removeBeatmapSet); + beatmaps.ForEach(addBeatmapSet); beatmapBacking.BindTo(beatmap); beatmapBacking.ValueChanged += _ => updateSelectedSet(); } - private void addBeatmapSet(BeatmapSetInfo obj) => Schedule(() => - { - items.Insert(items.Count - 1, new PlaylistItem(obj) { OnSelect = set => Selected?.Invoke(set) }); - }); + private void addBeatmapSet(BeatmapSetInfo obj) => Schedule(() => { items.Insert(items.Count - 1, new PlaylistItem(obj) { OnSelect = set => Selected?.Invoke(set) }); }); private void removeBeatmapSet(BeatmapSetInfo obj) => Schedule(() => { diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 6ad147735b..92246dfc62 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -8,6 +8,7 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; +using osu.Framework.MathUtils; using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Input.Bindings; @@ -24,7 +25,7 @@ namespace osu.Game.Overlays [Resolved] private BeatmapManager beatmaps { get; set; } - private List beatmapSets; + public readonly BindableList BeatmapSets = new BindableList(); public bool IsUserPaused { get; private set; } @@ -46,7 +47,7 @@ namespace osu.Game.Overlays [BackgroundDependencyLoader] private void load() { - beatmapSets = beatmaps.GetAllUsableBeatmapSets(); + BeatmapSets.AddRange(beatmaps.GetAllUsableBeatmapSets().OrderBy(_ => RNG.Next())); beatmaps.ItemAdded += handleBeatmapAdded; beatmaps.ItemRemoved += handleBeatmapRemoved; } @@ -65,8 +66,8 @@ namespace osu.Game.Overlays /// The new position. public void ChangeBeatmapSetPosition(BeatmapSetInfo beatmapSetInfo, int index) { - beatmapSets.Remove(beatmapSetInfo); - beatmapSets.Insert(index, beatmapSetInfo); + BeatmapSets.Remove(beatmapSetInfo); + BeatmapSets.Insert(index, beatmapSetInfo); } /// @@ -75,10 +76,10 @@ namespace osu.Game.Overlays public bool IsPlaying => beatmap.Value.Track.IsRunning; private void handleBeatmapAdded(BeatmapSetInfo set) => - Schedule(() => beatmapSets.Add(set)); + Schedule(() => BeatmapSets.Add(set)); private void handleBeatmapRemoved(BeatmapSetInfo set) => - Schedule(() => beatmapSets.RemoveAll(s => s.ID == set.ID)); + Schedule(() => BeatmapSets.RemoveAll(s => s.ID == set.ID)); private ScheduledDelegate seekDelegate; @@ -140,7 +141,7 @@ namespace osu.Game.Overlays { queuedDirection = TrackChangeDirection.Prev; - var playable = beatmapSets.TakeWhile(i => i.ID != current.BeatmapSetInfo.ID).LastOrDefault() ?? beatmapSets.LastOrDefault(); + var playable = BeatmapSets.TakeWhile(i => i.ID != current.BeatmapSetInfo.ID).LastOrDefault() ?? BeatmapSets.LastOrDefault(); if (playable != null) { @@ -165,7 +166,7 @@ namespace osu.Game.Overlays if (!instant) queuedDirection = TrackChangeDirection.Next; - var playable = beatmapSets.SkipWhile(i => i.ID != current.BeatmapSetInfo.ID).Skip(1).FirstOrDefault() ?? beatmapSets.FirstOrDefault(); + var playable = BeatmapSets.SkipWhile(i => i.ID != current.BeatmapSetInfo.ID).Skip(1).FirstOrDefault() ?? BeatmapSets.FirstOrDefault(); if (playable != null) { @@ -200,8 +201,8 @@ namespace osu.Game.Overlays else { //figure out the best direction based on order in playlist. - var last = beatmapSets.TakeWhile(b => b.ID != current.BeatmapSetInfo?.ID).Count(); - var next = beatmap.NewValue == null ? -1 : beatmapSets.TakeWhile(b => b.ID != beatmap.NewValue.BeatmapSetInfo?.ID).Count(); + var last = BeatmapSets.TakeWhile(b => b.ID != current.BeatmapSetInfo?.ID).Count(); + var next = beatmap.NewValue == null ? -1 : BeatmapSets.TakeWhile(b => b.ID != beatmap.NewValue.BeatmapSetInfo?.ID).Count(); direction = last > next ? TrackChangeDirection.Prev : TrackChangeDirection.Next; } From b5b29a21e783b93d21ea955d473fce33d59c8d47 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 02:15:18 +0900 Subject: [PATCH 177/239] Move menu cursor rotation to more appropriate settings section --- .../Overlays/Settings/Sections/Graphics/DetailSettings.cs | 5 ----- .../{MainMenuSettings.cs => UserInterfaceSettings.cs} | 7 ++++++- osu.Game/Overlays/Settings/Sections/GraphicsSection.cs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) rename osu.Game/Overlays/Settings/Sections/Graphics/{MainMenuSettings.cs => UserInterfaceSettings.cs} (71%) diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs index 56e56f6ca8..9be34c3073 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs @@ -26,11 +26,6 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics LabelText = "Video", Bindable = config.GetBindable(OsuSetting.ShowVideoBackground) }, - new SettingsCheckbox - { - LabelText = "Rotate cursor when dragging", - Bindable = config.GetBindable(OsuSetting.CursorRotation) - }, new SettingsEnumDropdown { LabelText = "Screenshot format", diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs similarity index 71% rename from osu.Game/Overlays/Settings/Sections/Graphics/MainMenuSettings.cs rename to osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs index 92f64d0e14..dd822fedb6 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/MainMenuSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/UserInterfaceSettings.cs @@ -6,7 +6,7 @@ using osu.Game.Configuration; namespace osu.Game.Overlays.Settings.Sections.Graphics { - public class MainMenuSettings : SettingsSubsection + public class UserInterfaceSettings : SettingsSubsection { protected override string Header => "User Interface"; @@ -15,6 +15,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics { Children = new[] { + new SettingsCheckbox + { + LabelText = "Rotate cursor when dragging", + Bindable = config.GetBindable(OsuSetting.CursorRotation) + }, new SettingsCheckbox { LabelText = "Parallax", diff --git a/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs b/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs index 3d6086d3ea..89caa3dc8f 100644 --- a/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs +++ b/osu.Game/Overlays/Settings/Sections/GraphicsSection.cs @@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Settings.Sections new RendererSettings(), new LayoutSettings(), new DetailSettings(), - new MainMenuSettings(), + new UserInterfaceSettings(), }; } } From 63cc8d4f90b29a165f43eb704cc9c0a057766a5f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 02:16:57 +0900 Subject: [PATCH 178/239] Add hit lighting setting --- osu.Game/Configuration/OsuConfigManager.cs | 5 ++++- .../Overlays/Settings/Sections/Graphics/DetailSettings.cs | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index e26021d930..4cbf2b4d94 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -81,6 +81,8 @@ namespace osu.Game.Configuration Set(OsuSetting.DimLevel, 0.3, 0, 1, 0.01); Set(OsuSetting.BlurLevel, 0, 0, 1, 0.01); + Set(OsuSetting.HitLighting, true); + Set(OsuSetting.ShowInterface, true); Set(OsuSetting.ShowHealthDisplayWhenCantFail, true); Set(OsuSetting.KeyOverlay, false); @@ -180,6 +182,7 @@ namespace osu.Game.Configuration ScalingSizeX, ScalingSizeY, UIScale, - IntroSequence + IntroSequence, + HitLighting } } diff --git a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs index 56e56f6ca8..5189d573cc 100644 --- a/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Graphics/DetailSettings.cs @@ -27,6 +27,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics Bindable = config.GetBindable(OsuSetting.ShowVideoBackground) }, new SettingsCheckbox + { + LabelText = "Hit Lighting", + Bindable = config.GetBindable(OsuSetting.HitLighting) + }, + new SettingsCheckbox { LabelText = "Rotate cursor when dragging", Bindable = config.GetBindable(OsuSetting.CursorRotation) From ba76f09c99df0c59c37c85c32ccbdc24875a9d30 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 02:49:54 +0900 Subject: [PATCH 179/239] Add initial implementation of hit lighting Requires a supporting skin, like osu!classic for now. --- .../Objects/Drawables/DrawableOsuJudgement.cs | 44 +++++++++++++++++++ .../Rulesets/Judgements/DrawableJudgement.cs | 8 +++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs index 938a2293ba..022e9ea12b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs @@ -1,22 +1,66 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Configuration; using osuTK; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Scoring; +using osu.Game.Skinning; +using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableOsuJudgement : DrawableJudgement { + private SkinnableSprite lighting; + private Bindable lightingColour; + public DrawableOsuJudgement(JudgementResult result, DrawableHitObject judgedObject) : base(result, judgedObject) { } + [BackgroundDependencyLoader] + private void load(OsuConfigManager config) + { + if (config.Get(OsuSetting.HitLighting) && Result.Type != HitResult.Miss) + { + AddInternal(lighting = new SkinnableSprite("lighting") + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Blending = BlendingParameters.Additive, + Depth = float.MaxValue + }); + + if (JudgedObject != null) + { + lightingColour = JudgedObject.AccentColour.GetBoundCopy(); + lightingColour.BindValueChanged(colour => lighting.Colour = colour.NewValue, true); + } + else + { + lighting.Colour = Color4.White; + } + } + } + + protected override double FadeOutDelay => lighting == null ? base.FadeOutDelay : 1400; + protected override void ApplyHitAnimations() { + if (lighting != null) + { + JudgementBody.Delay(FadeInDuration).FadeOut(400); + + lighting.ScaleTo(0.8f).ScaleTo(1.2f, 600, Easing.Out); + lighting.FadeIn(200).Then().Delay(200).FadeOut(1000); + } + JudgementText?.TransformSpacingTo(new Vector2(14, 0), 1800, Easing.OutQuint); base.ApplyHitAnimations(); } diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 4f8cb7660b..4c503ea59c 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -34,10 +34,14 @@ namespace osu.Game.Rulesets.Judgements /// /// Duration of initial fade in. - /// Default fade out will start immediately after this duration. /// protected virtual double FadeInDuration => 100; + /// + /// Duration to wait until fade out begins. Defaults to . + /// + protected virtual double FadeOutDelay => FadeInDuration; + /// /// Creates a drawable which visualises a . /// @@ -76,7 +80,7 @@ namespace osu.Game.Rulesets.Judgements JudgementBody.ScaleTo(0.9f); JudgementBody.ScaleTo(1, 500, Easing.OutElastic); - this.Delay(FadeInDuration).FadeOut(400); + this.Delay(FadeOutDelay).FadeOut(400); } protected override void LoadComplete() From 26eca5b1f425403df404da0ab4b4157e9f5fce52 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 02:56:03 +0900 Subject: [PATCH 180/239] Fix judgement sizes not matching skins stable --- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 2 +- osu.Game/Rulesets/Judgements/DrawableJudgement.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index df12ebc514..d1757de445 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Osu.UI { Origin = Anchor.Centre, Position = ((OsuHitObject)judgedObject.HitObject).StackedEndPosition, - Scale = new Vector2(((OsuHitObject)judgedObject.HitObject).Scale * 1.65f) + Scale = new Vector2(((OsuHitObject)judgedObject.HitObject).Scale) }; judgementLayer.Add(explosion); diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 4f8cb7660b..061c8cb3e1 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Judgements /// public class DrawableJudgement : CompositeDrawable { - private const float judgement_size = 80; + private const float judgement_size = 128; private OsuColour colours; @@ -64,7 +64,7 @@ namespace osu.Game.Rulesets.Judgements Child = new SkinnableDrawable(new GameplaySkinComponent(Result.Type), _ => JudgementText = new OsuSpriteText { Text = Result.Type.GetDescription().ToUpperInvariant(), - Font = OsuFont.Numeric.With(size: 12), + Font = OsuFont.Numeric.With(size: 20), Colour = judgementColour(Result.Type), Scale = new Vector2(0.85f, 1), }) From adc2dfa6c6ffecf27ae299d0cecd1e2844d380f3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 03:00:17 +0900 Subject: [PATCH 181/239] Fix HitCircleLongCombo test stacking off-screen --- osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs index 399cf22599..95c2810e94 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLongCombo.cs @@ -29,7 +29,8 @@ namespace osu.Game.Rulesets.Osu.Tests }; for (int i = 0; i < 512; i++) - beatmap.HitObjects.Add(new HitCircle { Position = new Vector2(256, 192), StartTime = i * 100 }); + if (i % 32 < 20) + beatmap.HitObjects.Add(new HitCircle { Position = new Vector2(256, 192), StartTime = i * 100 }); return beatmap; } From 7e791f7cd78e2fed4e67f91a739e8a6411da891a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 13:14:33 +0900 Subject: [PATCH 182/239] Expose as IBindableList --- osu.Game/Overlays/MusicController.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 92246dfc62..db94b0278f 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -25,7 +25,9 @@ namespace osu.Game.Overlays [Resolved] private BeatmapManager beatmaps { get; set; } - public readonly BindableList BeatmapSets = new BindableList(); + public IBindableList BeatmapSets => beatmapSets; + + private readonly BindableList beatmapSets = new BindableList(); public bool IsUserPaused { get; private set; } @@ -47,7 +49,7 @@ namespace osu.Game.Overlays [BackgroundDependencyLoader] private void load() { - BeatmapSets.AddRange(beatmaps.GetAllUsableBeatmapSets().OrderBy(_ => RNG.Next())); + beatmapSets.AddRange(beatmaps.GetAllUsableBeatmapSets().OrderBy(_ => RNG.Next())); beatmaps.ItemAdded += handleBeatmapAdded; beatmaps.ItemRemoved += handleBeatmapRemoved; } @@ -66,8 +68,8 @@ namespace osu.Game.Overlays /// The new position. public void ChangeBeatmapSetPosition(BeatmapSetInfo beatmapSetInfo, int index) { - BeatmapSets.Remove(beatmapSetInfo); - BeatmapSets.Insert(index, beatmapSetInfo); + beatmapSets.Remove(beatmapSetInfo); + beatmapSets.Insert(index, beatmapSetInfo); } /// @@ -76,10 +78,10 @@ namespace osu.Game.Overlays public bool IsPlaying => beatmap.Value.Track.IsRunning; private void handleBeatmapAdded(BeatmapSetInfo set) => - Schedule(() => BeatmapSets.Add(set)); + Schedule(() => beatmapSets.Add(set)); private void handleBeatmapRemoved(BeatmapSetInfo set) => - Schedule(() => BeatmapSets.RemoveAll(s => s.ID == set.ID)); + Schedule(() => beatmapSets.RemoveAll(s => s.ID == set.ID)); private ScheduledDelegate seekDelegate; From 91bdece9af42fe2848d9fef7b56432cdaaee279c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 13:15:39 +0900 Subject: [PATCH 183/239] Localise OrderChanged handling and fix callbacks The dragged item's position now only updates after the drag finishes. Local handling changes were required to ignore the bindable remove/add events that are fired as a result. --- osu.Game/Overlays/Music/PlaylistList.cs | 42 +++++++++++++++++----- osu.Game/Overlays/Music/PlaylistOverlay.cs | 8 ----- osu.Game/Overlays/NowPlayingOverlay.cs | 1 - 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index 6ad0aa23ec..636945edd2 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -19,7 +19,6 @@ namespace osu.Game.Overlays.Music public class PlaylistList : CompositeDrawable { public Action Selected; - public Action OrderChanged; private readonly ItemsScrollContainer items; @@ -29,7 +28,6 @@ namespace osu.Game.Overlays.Music { RelativeSizeAxes = Axes.Both, Selected = set => Selected?.Invoke(set), - OrderChanged = (s, i) => OrderChanged?.Invoke(s, i) }; } @@ -45,16 +43,17 @@ namespace osu.Game.Overlays.Music private class ItemsScrollContainer : OsuScrollContainer { - private BindableList beatmaps; + private IBindableList beatmaps; public Action Selected; - public Action OrderChanged; private readonly SearchContainer search; private readonly FillFlowContainer items; private readonly IBindable beatmapBacking = new Bindable(); + private MusicController musicController; + public ItemsScrollContainer() { Children = new Drawable[] @@ -78,6 +77,8 @@ namespace osu.Game.Overlays.Music [BackgroundDependencyLoader] private void load(MusicController musicController, IBindable beatmap) { + this.musicController = musicController; + beatmaps = musicController.BeatmapSets.GetBoundCopy(); beatmaps.ItemsAdded += i => i.ForEach(addBeatmapSet); @@ -88,10 +89,21 @@ namespace osu.Game.Overlays.Music beatmapBacking.ValueChanged += _ => updateSelectedSet(); } - private void addBeatmapSet(BeatmapSetInfo obj) => Schedule(() => { items.Insert(items.Count - 1, new PlaylistItem(obj) { OnSelect = set => Selected?.Invoke(set) }); }); + private void addBeatmapSet(BeatmapSetInfo obj) => Schedule(() => + { + if (obj == draggedItem?.BeatmapSetInfo) + { + draggedItem = null; + return; + } + + items.Insert(items.Count - 1, new PlaylistItem(obj) { OnSelect = set => Selected?.Invoke(set) }); + }); private void removeBeatmapSet(BeatmapSetInfo obj) => Schedule(() => { + if (obj == draggedItem?.BeatmapSetInfo) return; + var itemToRemove = items.FirstOrDefault(i => i.BeatmapSetInfo.ID == obj.ID); if (itemToRemove != null) items.Remove(itemToRemove); @@ -114,6 +126,8 @@ namespace osu.Game.Overlays.Music private Vector2 nativeDragPosition; private PlaylistItem draggedItem; + private int? dragDestination; + protected override bool OnDragStart(DragStartEvent e) { nativeDragPosition = e.ScreenSpaceMousePosition; @@ -133,10 +147,20 @@ namespace osu.Game.Overlays.Music protected override bool OnDragEnd(DragEndEvent e) { nativeDragPosition = e.ScreenSpaceMousePosition; - var handled = draggedItem != null || base.OnDragEnd(e); - draggedItem = null; - return handled; + if (draggedItem != null) + { + if (dragDestination != null) + { + // draggedItem is nulled when the BindableList's add event is received so we can quietly ignore the callbacks. + musicController.ChangeBeatmapSetPosition(draggedItem.BeatmapSetInfo, dragDestination.Value); + dragDestination = null; + } + + return true; + } + + return base.OnDragEnd(e); } protected override void Update() @@ -212,7 +236,7 @@ namespace osu.Game.Overlays.Music } items.SetLayoutPosition(draggedItem, dstIndex); - OrderChanged?.Invoke(draggedItem.BeatmapSetInfo, dstIndex); + dragDestination = dstIndex; } private class ItemSearchContainer : FillFlowContainer, IHasFilterableChildren diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index ec3d708645..ae81a6c117 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -22,12 +21,6 @@ namespace osu.Game.Overlays.Music private const float transition_duration = 600; private const float playlist_height = 510; - /// - /// Invoked when the order of an item in the list has changed. - /// The second parameter indicates the new index of the item. - /// - public Action OrderChanged; - private readonly Bindable beatmap = new Bindable(); private BeatmapManager beatmaps; @@ -65,7 +58,6 @@ namespace osu.Game.Overlays.Music RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = 95, Bottom = 10, Right = 10 }, Selected = itemSelected, - OrderChanged = (s, i) => OrderChanged?.Invoke(s, i) }, filter = new FilterControl { diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index cf42c8005a..6b79f2af07 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -81,7 +81,6 @@ namespace osu.Game.Overlays { RelativeSizeAxes = Axes.X, Y = player_height + 10, - OrderChanged = musicController.ChangeBeatmapSetPosition }, playerContainer = new Container { From 2db1e236a7180174ffa78318e29d92c0e9b6842f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 14:08:09 +0900 Subject: [PATCH 184/239] Fix frame count dependent tests regressing --- .../TestSceneAutoGeneration.cs | 101 ++++++++++-------- 1 file changed, 54 insertions(+), 47 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs index f260357df5..8206e33c7c 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs @@ -16,6 +16,11 @@ namespace osu.Game.Rulesets.Mania.Tests [HeadlessTest] public class TestSceneAutoGeneration : OsuTestScene { + /// + /// The number of frames which are generated at the start of a replay regardless of hitobject content. + /// + private const int frame_offset = 2; + [Test] public void TestSingleNote() { @@ -28,11 +33,11 @@ namespace osu.Game.Rulesets.Mania.Tests var generated = new ManiaAutoGenerator(beatmap).Generate(); - Assert.IsTrue(generated.Frames.Count == 3, "Replay must have 3 frames"); - Assert.AreEqual(1000, generated.Frames[1].Time, "Incorrect hit time"); - Assert.AreEqual(1000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[2].Time, "Incorrect release time"); - Assert.IsTrue(checkContains(generated.Frames[1], ManiaAction.Special1), "Special1 has not been pressed"); - Assert.IsFalse(checkContains(generated.Frames[2], ManiaAction.Special1), "Special1 has not been released"); + Assert.IsTrue(generated.Frames.Count == frame_offset + 2, "Replay must have 3 frames"); + Assert.AreEqual(1000, generated.Frames[frame_offset].Time, "Incorrect hit time"); + Assert.AreEqual(1000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[frame_offset + 1].Time, "Incorrect release time"); + Assert.IsTrue(checkContains(generated.Frames[frame_offset], ManiaAction.Special1), "Special1 has not been pressed"); + Assert.IsFalse(checkContains(generated.Frames[frame_offset + 1], ManiaAction.Special1), "Special1 has not been released"); } [Test] @@ -49,11 +54,11 @@ namespace osu.Game.Rulesets.Mania.Tests var generated = new ManiaAutoGenerator(beatmap).Generate(); - Assert.IsTrue(generated.Frames.Count == 3, "Replay must have 3 frames"); - Assert.AreEqual(1000, generated.Frames[1].Time, "Incorrect hit time"); - Assert.AreEqual(3000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[2].Time, "Incorrect release time"); - Assert.IsTrue(checkContains(generated.Frames[1], ManiaAction.Special1), "Special1 has not been pressed"); - Assert.IsFalse(checkContains(generated.Frames[2], ManiaAction.Special1), "Special1 has not been released"); + Assert.IsTrue(generated.Frames.Count == frame_offset + 2, "Replay must have 3 frames"); + Assert.AreEqual(1000, generated.Frames[frame_offset].Time, "Incorrect hit time"); + Assert.AreEqual(3000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[frame_offset + 1].Time, "Incorrect release time"); + Assert.IsTrue(checkContains(generated.Frames[frame_offset], ManiaAction.Special1), "Special1 has not been pressed"); + Assert.IsFalse(checkContains(generated.Frames[frame_offset + 1], ManiaAction.Special1), "Special1 has not been released"); } [Test] @@ -69,11 +74,11 @@ namespace osu.Game.Rulesets.Mania.Tests var generated = new ManiaAutoGenerator(beatmap).Generate(); - Assert.IsTrue(generated.Frames.Count == 3, "Replay must have 3 frames"); - Assert.AreEqual(1000, generated.Frames[1].Time, "Incorrect hit time"); - Assert.AreEqual(1000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[2].Time, "Incorrect release time"); - Assert.IsTrue(checkContains(generated.Frames[1], ManiaAction.Key1, ManiaAction.Key2), "Key1 & Key2 have not been pressed"); - Assert.IsFalse(checkContains(generated.Frames[2], ManiaAction.Key1, ManiaAction.Key2), "Key1 & Key2 have not been released"); + Assert.IsTrue(generated.Frames.Count == frame_offset + 2, "Replay must have 3 frames"); + Assert.AreEqual(1000, generated.Frames[frame_offset].Time, "Incorrect hit time"); + Assert.AreEqual(1000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[frame_offset + 1].Time, "Incorrect release time"); + Assert.IsTrue(checkContains(generated.Frames[frame_offset], ManiaAction.Key1, ManiaAction.Key2), "Key1 & Key2 have not been pressed"); + Assert.IsFalse(checkContains(generated.Frames[frame_offset + 1], ManiaAction.Key1, ManiaAction.Key2), "Key1 & Key2 have not been released"); } [Test] @@ -91,11 +96,13 @@ namespace osu.Game.Rulesets.Mania.Tests var generated = new ManiaAutoGenerator(beatmap).Generate(); - Assert.IsTrue(generated.Frames.Count == 3, "Replay must have 3 frames"); - Assert.AreEqual(1000, generated.Frames[1].Time, "Incorrect hit time"); - Assert.AreEqual(3000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[2].Time, "Incorrect release time"); - Assert.IsTrue(checkContains(generated.Frames[1], ManiaAction.Key1, ManiaAction.Key2), "Key1 & Key2 have not been pressed"); - Assert.IsFalse(checkContains(generated.Frames[2], ManiaAction.Key1, ManiaAction.Key2), "Key1 & Key2 have not been released"); + Assert.IsTrue(generated.Frames.Count == frame_offset + 2, "Replay must have 3 frames"); + + Assert.AreEqual(1000, generated.Frames[frame_offset].Time, "Incorrect hit time"); + Assert.AreEqual(3000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[frame_offset + 1].Time, "Incorrect release time"); + + Assert.IsTrue(checkContains(generated.Frames[frame_offset], ManiaAction.Key1, ManiaAction.Key2), "Key1 & Key2 have not been pressed"); + Assert.IsFalse(checkContains(generated.Frames[frame_offset + 1], ManiaAction.Key1, ManiaAction.Key2), "Key1 & Key2 have not been released"); } [Test] @@ -112,15 +119,15 @@ namespace osu.Game.Rulesets.Mania.Tests var generated = new ManiaAutoGenerator(beatmap).Generate(); - Assert.IsTrue(generated.Frames.Count == 5, "Replay must have 5 frames"); - Assert.AreEqual(1000, generated.Frames[1].Time, "Incorrect first note hit time"); - Assert.AreEqual(1000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[2].Time, "Incorrect first note release time"); - Assert.AreEqual(2000, generated.Frames[3].Time, "Incorrect second note hit time"); - Assert.AreEqual(2000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[4].Time, "Incorrect second note release time"); - Assert.IsTrue(checkContains(generated.Frames[1], ManiaAction.Key1), "Key1 has not been pressed"); - Assert.IsFalse(checkContains(generated.Frames[2], ManiaAction.Key1), "Key1 has not been released"); - Assert.IsTrue(checkContains(generated.Frames[3], ManiaAction.Key2), "Key2 has not been pressed"); - Assert.IsFalse(checkContains(generated.Frames[4], ManiaAction.Key2), "Key2 has not been released"); + Assert.IsTrue(generated.Frames.Count == frame_offset + 4, "Replay must have 4 generated frames"); + Assert.AreEqual(1000, generated.Frames[frame_offset].Time, "Incorrect first note hit time"); + Assert.AreEqual(1000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[frame_offset + 1].Time, "Incorrect first note release time"); + Assert.AreEqual(2000, generated.Frames[frame_offset + 2].Time, "Incorrect second note hit time"); + Assert.AreEqual(2000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[frame_offset + 3].Time, "Incorrect second note release time"); + Assert.IsTrue(checkContains(generated.Frames[frame_offset], ManiaAction.Key1), "Key1 has not been pressed"); + Assert.IsFalse(checkContains(generated.Frames[frame_offset + 1], ManiaAction.Key1), "Key1 has not been released"); + Assert.IsTrue(checkContains(generated.Frames[frame_offset + 2], ManiaAction.Key2), "Key2 has not been pressed"); + Assert.IsFalse(checkContains(generated.Frames[frame_offset + 3], ManiaAction.Key2), "Key2 has not been released"); } [Test] @@ -139,16 +146,16 @@ namespace osu.Game.Rulesets.Mania.Tests var generated = new ManiaAutoGenerator(beatmap).Generate(); - Assert.IsTrue(generated.Frames.Count == 5, "Replay must have 5 frames"); - Assert.AreEqual(1000, generated.Frames[1].Time, "Incorrect first note hit time"); - Assert.AreEqual(3000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[3].Time, "Incorrect first note release time"); - Assert.AreEqual(2000, generated.Frames[2].Time, "Incorrect second note hit time"); - Assert.AreEqual(4000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[4].Time, "Incorrect second note release time"); - Assert.IsTrue(checkContains(generated.Frames[1], ManiaAction.Key1), "Key1 has not been pressed"); - Assert.IsTrue(checkContains(generated.Frames[2], ManiaAction.Key1, ManiaAction.Key2), "Key1 & Key2 have not been pressed"); - Assert.IsFalse(checkContains(generated.Frames[3], ManiaAction.Key1), "Key1 has not been released"); - Assert.IsTrue(checkContains(generated.Frames[3], ManiaAction.Key2), "Key2 has been released"); - Assert.IsFalse(checkContains(generated.Frames[4], ManiaAction.Key2), "Key2 has not been released"); + Assert.IsTrue(generated.Frames.Count == frame_offset + 4, "Replay must have 4 generated frames"); + Assert.AreEqual(1000, generated.Frames[frame_offset].Time, "Incorrect first note hit time"); + Assert.AreEqual(3000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[frame_offset + 2].Time, "Incorrect first note release time"); + Assert.AreEqual(2000, generated.Frames[frame_offset + 1].Time, "Incorrect second note hit time"); + Assert.AreEqual(4000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[frame_offset + 3].Time, "Incorrect second note release time"); + Assert.IsTrue(checkContains(generated.Frames[frame_offset], ManiaAction.Key1), "Key1 has not been pressed"); + Assert.IsTrue(checkContains(generated.Frames[frame_offset + 1], ManiaAction.Key1, ManiaAction.Key2), "Key1 & Key2 have not been pressed"); + Assert.IsFalse(checkContains(generated.Frames[frame_offset + 2], ManiaAction.Key1), "Key1 has not been released"); + Assert.IsTrue(checkContains(generated.Frames[frame_offset + 2], ManiaAction.Key2), "Key2 has been released"); + Assert.IsFalse(checkContains(generated.Frames[frame_offset + 3], ManiaAction.Key2), "Key2 has not been released"); } [Test] @@ -166,14 +173,14 @@ namespace osu.Game.Rulesets.Mania.Tests var generated = new ManiaAutoGenerator(beatmap).Generate(); - Assert.IsTrue(generated.Frames.Count == 4, "Replay must have 4 frames"); - Assert.AreEqual(1000, generated.Frames[1].Time, "Incorrect first note hit time"); - Assert.AreEqual(3000, generated.Frames[2].Time, "Incorrect second note press time + first note release time"); - Assert.AreEqual(3000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[3].Time, "Incorrect second note release time"); - Assert.IsTrue(checkContains(generated.Frames[1], ManiaAction.Key1), "Key1 has not been pressed"); - Assert.IsFalse(checkContains(generated.Frames[2], ManiaAction.Key1), "Key1 has not been released"); - Assert.IsTrue(checkContains(generated.Frames[2], ManiaAction.Key2), "Key2 has not been pressed"); - Assert.IsFalse(checkContains(generated.Frames[3], ManiaAction.Key2), "Key2 has not been released"); + Assert.IsTrue(generated.Frames.Count == frame_offset + 3, "Replay must have 3 generated frames"); + Assert.AreEqual(1000, generated.Frames[frame_offset].Time, "Incorrect first note hit time"); + Assert.AreEqual(3000, generated.Frames[frame_offset + 1].Time, "Incorrect second note press time + first note release time"); + Assert.AreEqual(3000 + ManiaAutoGenerator.RELEASE_DELAY, generated.Frames[frame_offset + 2].Time, "Incorrect second note release time"); + Assert.IsTrue(checkContains(generated.Frames[frame_offset], ManiaAction.Key1), "Key1 has not been pressed"); + Assert.IsFalse(checkContains(generated.Frames[frame_offset + 1], ManiaAction.Key1), "Key1 has not been released"); + Assert.IsTrue(checkContains(generated.Frames[frame_offset + 1], ManiaAction.Key2), "Key2 has not been pressed"); + Assert.IsFalse(checkContains(generated.Frames[frame_offset + 2], ManiaAction.Key2), "Key2 has not been released"); } private bool checkContains(ReplayFrame frame, params ManiaAction[] actions) => actions.All(action => ((ManiaReplayFrame)frame).Actions.Contains(action)); From 2046f64b22b31c753390da30bc71d33b59381c96 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 16:07:02 +0900 Subject: [PATCH 185/239] Revert clamping logic --- osu.Game/Tests/Visual/OsuTestScene.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/OsuTestScene.cs b/osu.Game/Tests/Visual/OsuTestScene.cs index 2bc9273f69..8e98d51962 100644 --- a/osu.Game/Tests/Visual/OsuTestScene.cs +++ b/osu.Game/Tests/Visual/OsuTestScene.cs @@ -20,6 +20,7 @@ using osu.Game.Online.API; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Tests.Beatmaps; +using osuTK; namespace osu.Game.Tests.Visual { @@ -238,7 +239,7 @@ namespace osu.Game.Tests.Visual public override bool Seek(double seek) { - offset = Math.Min(seek, Length); + offset = MathHelper.Clamp(seek, 0, Length); lastReferenceTime = null; return offset == seek; From 381daffe527afef49687cbd1aed9ba026f718ef2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 16:07:29 +0900 Subject: [PATCH 186/239] Generate better temporary frames to support framed handling flaws --- osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs | 8 ++++---- osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs | 2 +- osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs | 8 ++++---- osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs | 3 ++- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs index 7f972a25ae..6c8515eb90 100644 --- a/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs +++ b/osu.Game.Rulesets.Catch/Replays/CatchAutoGenerator.cs @@ -37,10 +37,6 @@ namespace osu.Game.Rulesets.Catch.Replays float lastPosition = 0.5f; double lastTime = 0; - // Todo: Realistically this shouldn't be needed, but the first frame is skipped with the way replays are currently handled - addFrame(-100000, lastPosition); - addFrame(0, lastPosition); - void moveToNext(CatchHitObject h) { float positionChange = Math.Abs(lastPosition - h.X); @@ -128,6 +124,10 @@ namespace osu.Game.Rulesets.Catch.Replays private void addFrame(double time, float? position = null, bool dashing = false) { + // todo: can be removed once FramedReplayInputHandler correctly handles rewinding before first frame. + if (Replay.Frames.Count == 0) + Replay.Frames.Add(new CatchReplayFrame(time - 1, position, false, null)); + var last = currentFrame; currentFrame = new CatchReplayFrame(time, position, dashing, last); Replay.Frames.Add(currentFrame); diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs index 8206e33c7c..a5248c7712 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneAutoGeneration.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mania.Tests /// /// The number of frames which are generated at the start of a replay regardless of hitobject content. /// - private const int frame_offset = 2; + private const int frame_offset = 1; [Test] public void TestSingleNote() diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs index 5d333e2047..2b336ca16d 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaAutoGenerator.cs @@ -47,10 +47,6 @@ namespace osu.Game.Rulesets.Mania.Replays public override Replay Generate() { - // Todo: Realistically this shouldn't be needed, but the first frame is skipped with the way replays are currently handled - Replay.Frames.Add(new ManiaReplayFrame(-100000, 0)); - Replay.Frames.Add(new ManiaReplayFrame(0, 0)); - var pointGroups = generateActionPoints().GroupBy(a => a.Time).OrderBy(g => g.First().Time); var actions = new List(); @@ -71,6 +67,10 @@ namespace osu.Game.Rulesets.Mania.Replays } } + // todo: can be removed once FramedReplayInputHandler correctly handles rewinding before first frame. + if (Replay.Frames.Count == 0) + Replay.Frames.Add(new ManiaReplayFrame(group.First().Time - 1)); + Replay.Frames.Add(new ManiaReplayFrame(group.First().Time, actions.ToArray())); } diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs index 70ba5cd938..72c7eb60e0 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs @@ -21,7 +21,8 @@ namespace osu.Game.Rulesets.Mania.Replays public ManiaReplayFrame(double time, params ManiaAction[] actions) : base(time) { - Actions.AddRange(actions); + if (actions.Length > 0) + Actions.AddRange(actions); } public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap, ReplayFrame lastFrame = null) From e17cd9e964e5eaeded62b3b2a4584a813bec5470 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 16:14:31 +0900 Subject: [PATCH 187/239] Reduce length of tests --- osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs index 883aa9fc36..f94071a7a9 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneAutoplay.cs @@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void AddCheckSteps() { AddUntilStep("score above zero", () => ((ScoreAccessiblePlayer)Player).ScoreProcessor.TotalScore.Value > 0); - AddUntilStep("key counter counted keys", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 5)); + AddUntilStep("key counter counted keys", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 2)); AddStep("rewind", () => track.Seek(-10000)); AddUntilStep("key counter reset", () => ((ScoreAccessiblePlayer)Player).HUDOverlay.KeyCounter.Children.All(kc => kc.CountPresses == 0)); } From 61b396f235bedbd8306a26f84cbf5472df9f92d8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 17:09:43 +0900 Subject: [PATCH 188/239] Remove redundant length check --- osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs index 72c7eb60e0..70ba5cd938 100644 --- a/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs +++ b/osu.Game.Rulesets.Mania/Replays/ManiaReplayFrame.cs @@ -21,8 +21,7 @@ namespace osu.Game.Rulesets.Mania.Replays public ManiaReplayFrame(double time, params ManiaAction[] actions) : base(time) { - if (actions.Length > 0) - Actions.AddRange(actions); + Actions.AddRange(actions); } public void ConvertFrom(LegacyReplayFrame legacyFrame, IBeatmap beatmap, ReplayFrame lastFrame = null) From cfdac956c2b28acd95829b6cac682d803e9fea67 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 20:04:49 +0900 Subject: [PATCH 189/239] Fix issues with colour and skin application --- osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 23 +++++++++++-------- .../Objects/Drawables/DrawableHitCircle.cs | 8 +++---- .../Objects/Drawables/DrawableSlider.cs | 4 ++-- .../Objects/Drawables/DrawableHitObject.cs | 15 +++++++++++- 4 files changed, 33 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index 7c75bd608e..10a6334479 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -5,12 +5,12 @@ using System; using System.Linq; using osu.Framework.Bindables; using System.Collections.Generic; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics.Sprites; using osu.Game.Configuration; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables; -using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Mods { @@ -22,7 +22,8 @@ namespace osu.Game.Rulesets.Osu.Mods public override ModType Type => ModType.Fun; public override string Description => "Put your faith in the approach circles..."; public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden), typeof(OsuModeObjectScaleTween) }; + + public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden), typeof(OsuModSpinIn) }; private Bindable increaseFirstObjectVisibility = new Bindable(); public void ReadFromConfig(OsuConfigManager config) @@ -38,26 +39,28 @@ namespace osu.Game.Rulesets.Osu.Mods protected void ApplyTraceableState(DrawableHitObject drawable, ArmedState state) { - if (!(drawable is DrawableOsuHitObject d)) + if (!(drawable is DrawableOsuHitObject drawableOsu)) return; - var h = d.HitObject; + var h = drawableOsu.HitObject; switch (drawable) { case DrawableHitCircle circle: // we only want to see the approach circle using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true)) - { - circle.ApproachCircle.Show(); - } + circle.CirclePiece.Hide(); break; case DrawableSlider slider: - ApplyTraceableState(slider.HeadCircle, state); - slider.Body.AccentColour = Color4.Transparent; - slider.Body.BorderColour = slider.HeadCircle.AccentColour.Value; + slider.AccentColour.BindValueChanged(_ => + { + //will trigger on skin change. + slider.Body.AccentColour = slider.AccentColour.Value.Opacity(0); + slider.Body.BorderColour = slider.AccentColour.Value; + }, true); + break; case DrawableSpinner spinner: diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 83646c561d..c90f230f93 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableHitCircle : DrawableOsuHitObject, IDrawableHitObjectWithProxiedApproach { - public ApproachCircle ApproachCircle; + public ApproachCircle ApproachCircle { get; } private readonly IBindable positionBindable = new Bindable(); private readonly IBindable stackHeightBindable = new Bindable(); @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private readonly HitArea hitArea; - private readonly SkinnableDrawable mainContent; + public SkinnableDrawable CirclePiece { get; } public DrawableHitCircle(HitCircle h) : base(h) @@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables return true; }, }, - mainContent = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.HitCircle), _ => new MainCirclePiece(HitObject.IndexInCurrentCombo)), + CirclePiece = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.HitCircle), _ => new MainCirclePiece(HitObject.IndexInCurrentCombo)), ApproachCircle = new ApproachCircle { Alpha = 0, @@ -133,7 +133,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.UpdateInitialTransforms(); - mainContent.FadeInFromZero(HitObject.TimeFadeIn); + CirclePiece.FadeInFromZero(HitObject.TimeFadeIn); ApproachCircle.FadeIn(Math.Min(HitObject.TimeFadeIn * 2, HitObject.TimePreempt)); ApproachCircle.ScaleTo(1f, HitObject.TimePreempt); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 08b43b0345..643a0f7336 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -163,9 +163,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private float sliderPathRadius; - protected override void SkinChanged(ISkinSource skin, bool allowFallback) + protected override void ApplySkin(ISkinSource skin, bool allowFallback) { - base.SkinChanged(skin, allowFallback); + base.ApplySkin(skin, allowFallback); Body.BorderSize = skin.GetConfig(OsuSkinConfiguration.SliderBorderSize)?.Value ?? SliderBody.DEFAULT_BORDER_SIZE; sliderPathRadius = skin.GetConfig(OsuSkinConfiguration.SliderPathRadius)?.Value ?? OsuHitObject.OBJECT_RADIUS; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 00b57f7249..9a7f1e8522 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -240,7 +240,7 @@ namespace osu.Game.Rulesets.Objects.Drawables #endregion - protected override void SkinChanged(ISkinSource skin, bool allowFallback) + protected sealed override void SkinChanged(ISkinSource skin, bool allowFallback) { base.SkinChanged(skin, allowFallback); @@ -250,6 +250,19 @@ namespace osu.Game.Rulesets.Objects.Drawables AccentColour.Value = comboColours?.Count > 0 ? comboColours[combo.ComboIndex % comboColours.Count] : Color4.White; } + + ApplySkin(skin, allowFallback); + + updateState(State.Value, true); + } + + /// + /// Called when a change is made to the skin. + /// + /// The new skin. + /// Whether fallback to default skin should be allowed if the custom skin is missing this resource. + protected virtual void ApplySkin(ISkinSource skin, bool allowFallback) + { } /// From aa1a6256431f0e6ac5a6cd793d3d57112e346faf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 20:07:44 +0900 Subject: [PATCH 190/239] Add back incompatibility marker --- osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs | 3 +-- osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs index 10a6334479..7e20feba02 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs @@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override string Description => "Put your faith in the approach circles..."; public override double ScoreMultiplier => 1; - public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden), typeof(OsuModSpinIn) }; + public override Type[] IncompatibleMods => new[] { typeof(OsuModHidden), typeof(OsuModSpinIn), typeof(OsuModeObjectScaleTween) }; private Bindable increaseFirstObjectVisibility = new Bindable(); public void ReadFromConfig(OsuConfigManager config) @@ -65,7 +65,6 @@ namespace osu.Game.Rulesets.Osu.Mods case DrawableSpinner spinner: spinner.Disc.Hide(); - //spinner.Ticks.Hide(); // do they contribute to the theme? debatable spinner.Background.Hide(); break; } diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs b/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs index e926ade41b..923278f484 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModeObjectScaleTween.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Osu.Mods private Bindable increaseFirstObjectVisibility = new Bindable(); - public override Type[] IncompatibleMods => new[] { typeof(OsuModSpinIn) }; + public override Type[] IncompatibleMods => new[] { typeof(OsuModSpinIn), typeof(OsuModTraceable) }; public void ReadFromConfig(OsuConfigManager config) { From 5901a915e7850fb064cde851cbb5d5a4d8af193b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Sep 2019 20:19:57 +0900 Subject: [PATCH 191/239] Always update drawable hitobject state on skin change --- .../Objects/Drawables/DrawableSlider.cs | 4 ++-- .../Objects/Drawables/DrawableHitObject.cs | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 08b43b0345..643a0f7336 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -163,9 +163,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables private float sliderPathRadius; - protected override void SkinChanged(ISkinSource skin, bool allowFallback) + protected override void ApplySkin(ISkinSource skin, bool allowFallback) { - base.SkinChanged(skin, allowFallback); + base.ApplySkin(skin, allowFallback); Body.BorderSize = skin.GetConfig(OsuSkinConfiguration.SliderBorderSize)?.Value ?? SliderBody.DEFAULT_BORDER_SIZE; sliderPathRadius = skin.GetConfig(OsuSkinConfiguration.SliderPathRadius)?.Value ?? OsuHitObject.OBJECT_RADIUS; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 00b57f7249..9a7f1e8522 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -240,7 +240,7 @@ namespace osu.Game.Rulesets.Objects.Drawables #endregion - protected override void SkinChanged(ISkinSource skin, bool allowFallback) + protected sealed override void SkinChanged(ISkinSource skin, bool allowFallback) { base.SkinChanged(skin, allowFallback); @@ -250,6 +250,19 @@ namespace osu.Game.Rulesets.Objects.Drawables AccentColour.Value = comboColours?.Count > 0 ? comboColours[combo.ComboIndex % comboColours.Count] : Color4.White; } + + ApplySkin(skin, allowFallback); + + updateState(State.Value, true); + } + + /// + /// Called when a change is made to the skin. + /// + /// The new skin. + /// Whether fallback to default skin should be allowed if the custom skin is missing this resource. + protected virtual void ApplySkin(ISkinSource skin, bool allowFallback) + { } /// From 646a64792a8a7be0f00b202b545cd4421d6ffce1 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2019 14:36:31 +0000 Subject: [PATCH 192/239] Bump ppy.osu.Framework.Android from 2019.911.0 to 2019.918.0 Bumps [ppy.osu.Framework.Android](https://github.com/ppy/osu-framework) from 2019.911.0 to 2019.918.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.911.0...2019.918.0) Signed-off-by: dependabot-preview[bot] --- osu.Android.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Android.props b/osu.Android.props index 4167d07698..85e8cb9ceb 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -63,6 +63,6 @@ - + From 1d7377df65c29f90712bb9a97630acd05b9bab3a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2019 14:51:01 +0000 Subject: [PATCH 193/239] Bump ppy.osu.Framework from 2019.911.0 to 2019.918.0 Bumps [ppy.osu.Framework](https://github.com/ppy/osu-framework) from 2019.911.0 to 2019.918.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.911.0...2019.918.0) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 5703293caf..a733a0e7f9 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 683dccf3ae..f70853d70b 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -118,7 +118,7 @@ - + From 5dc5181c9014f8f75ab32b6b17d16de5092e3e2c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2019 15:27:39 +0000 Subject: [PATCH 194/239] Bump ppy.osu.Framework.iOS from 2019.911.0 to 2019.918.0 Bumps [ppy.osu.Framework.iOS](https://github.com/ppy/osu-framework) from 2019.911.0 to 2019.918.0. - [Release notes](https://github.com/ppy/osu-framework/releases) - [Commits](https://github.com/ppy/osu-framework/compare/2019.911.0...2019.918.0) Signed-off-by: dependabot-preview[bot] --- osu.iOS.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.iOS.props b/osu.iOS.props index f70853d70b..4bfa1ebcd0 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -119,7 +119,7 @@ - + From 1150e9fdfbc14254816c5f26b978d6104decf147 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 01:45:42 +0900 Subject: [PATCH 195/239] Bring other mods up-to-date --- osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs | 1 + osu.Game/Rulesets/Mods/ModAutoplay.cs | 2 ++ osu.Game/Rulesets/Mods/ModBlockFail.cs | 2 ++ 3 files changed, 5 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs index ca72f18e9c..65d7acc911 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs @@ -25,6 +25,7 @@ namespace osu.Game.Rulesets.Osu.Mods public override Type[] IncompatibleMods => new[] { typeof(OsuModSpunOut), typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail), typeof(ModAutoplay) }; public bool AllowFail => false; + public bool RestartOnFail => false; private OsuInputManager inputManager; diff --git a/osu.Game/Rulesets/Mods/ModAutoplay.cs b/osu.Game/Rulesets/Mods/ModAutoplay.cs index f0dffa60ce..070a10b1c8 100644 --- a/osu.Game/Rulesets/Mods/ModAutoplay.cs +++ b/osu.Game/Rulesets/Mods/ModAutoplay.cs @@ -26,8 +26,10 @@ namespace osu.Game.Rulesets.Mods public override ModType Type => ModType.Automation; public override string Description => "Watch a perfect automated play through the song."; public override double ScoreMultiplier => 1; + public bool AllowFail => false; public bool RestartOnFail => false; + public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail) }; public override bool HasImplementation => GetType().GenericTypeArguments.Length == 0; diff --git a/osu.Game/Rulesets/Mods/ModBlockFail.cs b/osu.Game/Rulesets/Mods/ModBlockFail.cs index 26efc3932d..55c074bde2 100644 --- a/osu.Game/Rulesets/Mods/ModBlockFail.cs +++ b/osu.Game/Rulesets/Mods/ModBlockFail.cs @@ -16,6 +16,8 @@ namespace osu.Game.Rulesets.Mods /// public bool AllowFail => false; + public virtual bool RestartOnFail => false; + public void ReadFromConfig(OsuConfigManager config) { showHealthBar = config.GetBindable(OsuSetting.ShowHealthDisplayWhenCantFail); From 2fcc8c2d720d60bbd6431e720628f056f41594a1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 01:45:59 +0900 Subject: [PATCH 196/239] Simplify implementation, play fail animation during restart --- osu.Game/Screens/Play/Player.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index ca17e8a7bc..dac5561a45 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -360,7 +360,9 @@ namespace osu.Game.Screens.Play private bool onFail() { - if (Mods.Value.OfType().Any(m => !m.AllowFail)) + var failOverrideMods = Mods.Value.OfType(); + + if (failOverrideMods.Any(m => !m.AllowFail)) return false; HasFailed = true; @@ -371,13 +373,10 @@ namespace osu.Game.Screens.Play if (PauseOverlay.State.Value == Visibility.Visible) PauseOverlay.Hide(); - if (Beatmap.Value.Mods.Value.OfType().Any(m => m.RestartOnFail)) - { - Restart(); - return true; - } - failAnimation.Start(); + if (failOverrideMods.Any(m => m.RestartOnFail)) + Restart(); + return true; } From 2296ea75d7e64183b6b625810da21c3ef5b46458 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 02:03:30 +0900 Subject: [PATCH 197/239] Add reference to xmldoc Co-Authored-By: Salman Ahmed --- osu.Game/Rulesets/Mods/IApplicableFailOverride.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs b/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs index ae5903f085..120bfc9a23 100644 --- a/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs +++ b/osu.Game/Rulesets/Mods/IApplicableFailOverride.cs @@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mods bool AllowFail { get; } /// - /// Whether we want to restart on fail. Only used if AllowFail is true. + /// Whether we want to restart on fail. Only used if is true. /// bool RestartOnFail { get; } } From 92556db9cd8bae5df028a295338d8ad1065e2a55 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 02:37:35 +0900 Subject: [PATCH 198/239] Add query-based filter modes to song select search field --- osu.Game/Beatmaps/BeatmapManager.cs | 1 + .../Select/Carousel/CarouselBeatmap.cs | 24 +++- osu.Game/Screens/Select/FilterControl.cs | 118 ++++++++++++++++-- osu.Game/Screens/Select/FilterCriteria.cs | 33 ++++- 4 files changed, 163 insertions(+), 13 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index b9ed3664ef..02d7b2d98f 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -301,6 +301,7 @@ namespace osu.Game.Beatmaps var ruleset = rulesets.GetRuleset(beatmap.BeatmapInfo.RulesetID); beatmap.BeatmapInfo.Ruleset = ruleset; + // TODO: this should be done in a better place once we actually need to dynamically update it. beatmap.BeatmapInfo.StarDifficulty = ruleset?.CreateInstance().CreateDifficultyCalculator(new DummyConversionBeatmap(beatmap)).Calculate().StarRating ?? 0; beatmap.BeatmapInfo.Length = calculateLength(beatmap); diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 712ab7b571..60e556a261 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -24,12 +24,26 @@ namespace osu.Game.Screens.Select.Carousel { base.Filter(criteria); - bool match = criteria.Ruleset == null || Beatmap.RulesetID == criteria.Ruleset.ID || (Beatmap.RulesetID == 0 && criteria.Ruleset.ID > 0 && criteria.AllowConvertedBeatmaps); + bool match = + criteria.Ruleset == null || + Beatmap.RulesetID == criteria.Ruleset.ID || + (Beatmap.RulesetID == 0 && criteria.Ruleset.ID > 0 && criteria.AllowConvertedBeatmaps); - foreach (var criteriaTerm in criteria.SearchTerms) - match &= - Beatmap.Metadata.SearchableTerms.Any(term => term.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0) || - Beatmap.Version.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0; + match &= criteria.StarDifficulty.IsInRange(Beatmap.StarDifficulty); + match &= criteria.ApproachRate.IsInRange(Beatmap.BaseDifficulty.ApproachRate); + match &= criteria.DrainRate.IsInRange(Beatmap.BaseDifficulty.DrainRate); + match &= criteria.CircleSize.IsInRange(Beatmap.BaseDifficulty.CircleSize); + match &= criteria.Length.IsInRange(Beatmap.Length); + match &= criteria.BPM.IsInRange(Beatmap.BPM); + + match &= !criteria.BeatDivisor.HasValue || criteria.BeatDivisor == Beatmap.BeatDivisor; + match &= !criteria.OnlineStatus.HasValue || criteria.OnlineStatus == Beatmap.Status; + + if (match) + foreach (var criteriaTerm in criteria.SearchTerms) + match &= + Beatmap.Metadata.SearchableTerms.Any(term => term.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0) || + Beatmap.Version.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0; Filtered.Value = !match; } diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index ed74b01fc9..01e7ed9383 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -16,6 +16,8 @@ using Container = osu.Framework.Graphics.Containers.Container; using osu.Framework.Graphics.Shapes; using osu.Game.Configuration; using osu.Game.Rulesets; +using System.Text.RegularExpressions; +using osu.Game.Beatmaps; namespace osu.Game.Screens.Select { @@ -33,14 +35,24 @@ namespace osu.Game.Screens.Select private Bindable groupMode; - public FilterCriteria CreateCriteria() => new FilterCriteria + public FilterCriteria CreateCriteria() { - Group = groupMode.Value, - Sort = sortMode.Value, - SearchText = searchTextBox.Text, - AllowConvertedBeatmaps = showConverted.Value, - Ruleset = ruleset.Value - }; + var query = searchTextBox.Text; + + var criteria = new FilterCriteria + { + Group = groupMode.Value, + Sort = sortMode.Value, + AllowConvertedBeatmaps = showConverted.Value, + Ruleset = ruleset.Value + }; + + applyQueries(criteria, ref query); + + criteria.SearchText = query; + + return criteria; + } public Action Exit; @@ -169,5 +181,97 @@ namespace osu.Game.Screens.Select } private void updateCriteria() => FilterChanged?.Invoke(CreateCriteria()); + + private static readonly Regex query_syntax_regex = new Regex( + @"\b(?stars|ar|dr|cs|divisor|length|objects|bpm|status)(?[:><]+)(?\S*)", + RegexOptions.Compiled | RegexOptions.IgnoreCase); + + private void applyQueries(FilterCriteria criteria, ref string query) + { + foreach (Match match in query_syntax_regex.Matches(query)) + { + var key = match.Groups["key"].Value.ToLower(); + var op = match.Groups["op"].Value; + var value = match.Groups["value"].Value; + + switch (key) + { + case "stars" when double.TryParse(value, out var stars): + updateCriteriaRange(ref criteria.StarDifficulty, op, stars, 0.5); + break; + + case "ar" when double.TryParse(value, out var ar): + updateCriteriaRange(ref criteria.ApproachRate, op, ar, 0.3); + break; + + case "dr" when double.TryParse(value, out var dr): + updateCriteriaRange(ref criteria.DrainRate, op, dr, 0.3); + break; + + case "cs" when double.TryParse(value, out var cs): + updateCriteriaRange(ref criteria.CircleSize, op, cs, 0.3); + break; + + case "bpm" when double.TryParse(value, out var bpm): + updateCriteriaRange(ref criteria.BPM, op, bpm, 0.3); + break; + + case "length" when double.TryParse(value.TrimEnd('m', 's', 'h'), out var length): + var scale = + value.EndsWith("ms") ? 1 : + value.EndsWith("s") ? 1000 : + value.EndsWith("m") ? 60000 : + value.EndsWith("h") ? 3600000 : 1000; + + updateCriteriaRange(ref criteria.Length, op, length * scale, scale / 2.0); + break; + + case "divisor" when op == ":" && int.TryParse(value, out var divisor): + criteria.BeatDivisor = divisor; + break; + + case "status" when op == ":" && Enum.TryParse(value, ignoreCase: true, out var statusValue): + criteria.OnlineStatus = statusValue; + break; + } + + query = query.Remove(match.Index, match.Length); + } + } + + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double equalityToleration = 0) + { + switch (op) + { + default: + return; + + case ":": + range.IsInclusive = true; + range.Min = value - equalityToleration; + range.Max = value + equalityToleration; + break; + + case ">": + range.IsInclusive = false; + range.Min = value; + break; + + case ">:": + range.IsInclusive = true; + range.Min = value; + break; + + case "<": + range.IsInclusive = false; + range.Max = value; + break; + + case "<:": + range.IsInclusive = true; + range.Max = value; + break; + } + } } } diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 140010ff54..84d63c16e0 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Screens.Select.Filter; @@ -13,6 +14,17 @@ namespace osu.Game.Screens.Select public GroupMode Group; public SortMode Sort; + public OptionalRange StarDifficulty; + public OptionalRange ApproachRate; + public OptionalRange DrainRate; + public OptionalRange CircleSize; + public OptionalRange Length; + public OptionalRange BPM; + + public int? BeatDivisor; + + public BeatmapSetOnlineStatus? OnlineStatus; + public string[] SearchTerms = Array.Empty(); public RulesetInfo Ruleset; @@ -26,8 +38,27 @@ namespace osu.Game.Screens.Select set { searchText = value; - SearchTerms = searchText.Split(',', ' ', '!').Where(s => !string.IsNullOrEmpty(s)).ToArray(); + SearchTerms = searchText.Split(new[] { ',', ' ', '!' }, StringSplitOptions.RemoveEmptyEntries).ToArray(); } } + + public struct OptionalRange : IEquatable + { + public bool IsInRange(double value) + { + if (Min.HasValue && (IsInclusive ? value < Min.Value : value <= Min.Value)) + return false; + if (Max.HasValue && (IsInclusive ? value > Max.Value : value >= Max.Value)) + return false; + + return true; + } + + public double? Min; + public double? Max; + public bool IsInclusive; + + public bool Equals(OptionalRange range) => Min == range.Min && Max == range.Max; + } } } From ecd721e8c5be287068bc1f51d2f85b4a44c225b3 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 18 Sep 2019 22:49:28 +0300 Subject: [PATCH 199/239] Add bypass fail property to Player --- osu.Game/Screens/Play/Player.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 309f4837e5..fbaab61b42 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -86,6 +86,11 @@ namespace osu.Game.Screens.Play [Cached(Type = typeof(IBindable>))] protected new readonly Bindable> Mods = new Bindable>(Array.Empty()); + /// + /// Whether to block the player from failing. + /// + protected virtual bool BypassFail => false; + private readonly bool allowPause; private readonly bool showResults; @@ -360,7 +365,7 @@ namespace osu.Game.Screens.Play private bool onFail() { - if (Mods.Value.OfType().Any(m => !m.AllowFail)) + if (Mods.Value.OfType().Any(m => !m.AllowFail) || BypassFail) return false; HasFailed = true; From 775b90e06643da66c6ebc72218e2163bbf15c8de Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 18 Sep 2019 22:49:48 +0300 Subject: [PATCH 200/239] Bypass fail on replays --- osu.Game/Screens/Play/ReplayPlayer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Screens/Play/ReplayPlayer.cs b/osu.Game/Screens/Play/ReplayPlayer.cs index a9c0ee3a15..da9f558c16 100644 --- a/osu.Game/Screens/Play/ReplayPlayer.cs +++ b/osu.Game/Screens/Play/ReplayPlayer.cs @@ -9,6 +9,9 @@ namespace osu.Game.Screens.Play { private readonly Score score; + // Block replays from failing. (see https://github.com/ppy/osu/issues/6108) + protected override bool BypassFail => true; + public ReplayPlayer(Score score, bool allowPause = true, bool showResults = true) : base(allowPause, showResults) { From 871adb16e0ba068e305ca79e342623bfff2b6e34 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 18 Sep 2019 22:51:03 +0300 Subject: [PATCH 201/239] Add asserts for fail bypassing --- osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs index 3fbce9d43c..d89304cf44 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs @@ -26,12 +26,14 @@ namespace osu.Game.Tests.Visual.Gameplay { AddUntilStep("score above zero", () => ((ScoreAccessibleReplayPlayer)Player).ScoreProcessor.TotalScore.Value > 0); AddUntilStep("key counter counted keys", () => ((ScoreAccessibleReplayPlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 0)); + AddAssert("cannot fail", () => ((ScoreAccessibleReplayPlayer)Player).BypassFail); } private class ScoreAccessibleReplayPlayer : ReplayPlayer { public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; public new HUDOverlay HUDOverlay => base.HUDOverlay; + public new bool BypassFail => base.BypassFail; protected override bool PauseOnFocusLost => false; From ea6318ed73c22607c2aace18d7fa9cc7a659ebd1 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 18 Sep 2019 23:17:24 +0300 Subject: [PATCH 202/239] Fix failing test --- .../Visual/Gameplay/TestSceneFailJudgement.cs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs index d57ec44f39..e6d302a5ca 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs @@ -17,9 +17,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override Player CreatePlayer(Ruleset ruleset) { Mods.Value = Array.Empty(); - - var beatmap = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo, Array.Empty()); - return new FailPlayer(ruleset.GetAutoplayMod().CreateReplayScore(beatmap)); + return new FailPlayer(); } protected override void AddCheckSteps() @@ -29,16 +27,12 @@ namespace osu.Game.Tests.Visual.Gameplay AddAssert("total judgements == 1", () => ((FailPlayer)Player).ScoreProcessor.JudgedHits == 1); } - private class FailPlayer : ReplayPlayer + private class FailPlayer : TestPlayer { - public new DrawableRuleset DrawableRuleset => base.DrawableRuleset; - public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; - protected override bool PauseOnFocusLost => false; - - public FailPlayer(Score score) - : base(score, false, false) + public FailPlayer() + : base(false, false) { } From 3efcf0493c45c95b5a648bbcce99ab4af831ac7d Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Wed, 18 Sep 2019 23:28:48 +0300 Subject: [PATCH 203/239] Remove redundant using directive --- osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs index e6d302a5ca..cca6301b02 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailJudgement.cs @@ -6,8 +6,6 @@ using System.Linq; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.UI; -using osu.Game.Scoring; using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual.Gameplay From 3fa1b53b2ae3d670bc7f1f2a6f8b55cb57659b93 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 12:39:15 +0900 Subject: [PATCH 204/239] Add back combo colours for osu!classic --- osu.Game/Skinning/DefaultLegacySkin.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Skinning/DefaultLegacySkin.cs b/osu.Game/Skinning/DefaultLegacySkin.cs index 98f158c725..4b6eea6b6e 100644 --- a/osu.Game/Skinning/DefaultLegacySkin.cs +++ b/osu.Game/Skinning/DefaultLegacySkin.cs @@ -13,6 +13,13 @@ namespace osu.Game.Skinning : base(Info, storage, audioManager, string.Empty) { Configuration.CustomColours["SliderBall"] = new Color4(2, 170, 255, 255); + Configuration.ComboColours.AddRange(new[] + { + new Color4(255, 192, 0, 255), + new Color4(0, 202, 0, 255), + new Color4(18, 124, 255, 255), + new Color4(242, 24, 57, 255), + }); } public static SkinInfo Info { get; } = new SkinInfo From e5509cd3908175a866809317576b0d896b53afe8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 13:19:48 +0900 Subject: [PATCH 205/239] Rename test --- ...stSceneLeaderboard.cs => TestSceneBeatmapLeaderboard.cs} | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) rename osu.Game.Tests/Visual/SongSelect/{TestSceneLeaderboard.cs => TestSceneBeatmapLeaderboard.cs} (98%) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs similarity index 98% rename from osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs rename to osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index 186f27a8b2..cb4cd63266 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Online.Leaderboards; @@ -14,8 +13,7 @@ using osuTK; namespace osu.Game.Tests.Visual.SongSelect { - [Description("PlaySongSelect leaderboard")] - public class TestSceneLeaderboard : OsuTestScene + public class TestSceneBeatmapLeaderboard : OsuTestScene { public override IReadOnlyList RequiredTypes => new[] { @@ -26,7 +24,7 @@ namespace osu.Game.Tests.Visual.SongSelect private readonly FailableLeaderboard leaderboard; - public TestSceneLeaderboard() + public TestSceneBeatmapLeaderboard() { Add(leaderboard = new FailableLeaderboard { From 0644443979bde65a602504c34eeecbbfcff332f9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 13:51:50 +0900 Subject: [PATCH 206/239] Use resolved attribute for music controller --- osu.Game/Overlays/Music/PlaylistList.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index 636945edd2..cd9c91f3af 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -43,8 +43,6 @@ namespace osu.Game.Overlays.Music private class ItemsScrollContainer : OsuScrollContainer { - private IBindableList beatmaps; - public Action Selected; private readonly SearchContainer search; @@ -52,7 +50,10 @@ namespace osu.Game.Overlays.Music private readonly IBindable beatmapBacking = new Bindable(); - private MusicController musicController; + private IBindableList beatmaps; + + [Resolved] + private MusicController musicController { get; set; } public ItemsScrollContainer() { @@ -75,12 +76,9 @@ namespace osu.Game.Overlays.Music } [BackgroundDependencyLoader] - private void load(MusicController musicController, IBindable beatmap) + private void load(IBindable beatmap) { - this.musicController = musicController; - beatmaps = musicController.BeatmapSets.GetBoundCopy(); - beatmaps.ItemsAdded += i => i.ForEach(addBeatmapSet); beatmaps.ItemsRemoved += i => i.ForEach(removeBeatmapSet); beatmaps.ForEach(addBeatmapSet); From 4b97327b37ad910b93bb3a835a19201369dc6730 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 13:53:52 +0900 Subject: [PATCH 207/239] Cleanup draggedItem usages and make them more safe --- osu.Game/Overlays/Music/PlaylistList.cs | 50 ++++++++++++------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index cd9c91f3af..5b528c5ab2 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -87,25 +87,24 @@ namespace osu.Game.Overlays.Music beatmapBacking.ValueChanged += _ => updateSelectedSet(); } - private void addBeatmapSet(BeatmapSetInfo obj) => Schedule(() => - { - if (obj == draggedItem?.BeatmapSetInfo) - { - draggedItem = null; - return; - } - - items.Insert(items.Count - 1, new PlaylistItem(obj) { OnSelect = set => Selected?.Invoke(set) }); - }); - - private void removeBeatmapSet(BeatmapSetInfo obj) => Schedule(() => + private void addBeatmapSet(BeatmapSetInfo obj) { if (obj == draggedItem?.BeatmapSetInfo) return; - var itemToRemove = items.FirstOrDefault(i => i.BeatmapSetInfo.ID == obj.ID); - if (itemToRemove != null) - items.Remove(itemToRemove); - }); + Schedule(() => items.Insert(items.Count - 1, new PlaylistItem(obj) { OnSelect = set => Selected?.Invoke(set) })); + } + + private void removeBeatmapSet(BeatmapSetInfo obj) + { + if (obj == draggedItem?.BeatmapSetInfo) return; + + Schedule(() => + { + var itemToRemove = items.FirstOrDefault(i => i.BeatmapSetInfo.ID == obj.ID); + if (itemToRemove != null) + items.Remove(itemToRemove); + }); + } private void updateSelectedSet() { @@ -146,19 +145,16 @@ namespace osu.Game.Overlays.Music { nativeDragPosition = e.ScreenSpaceMousePosition; - if (draggedItem != null) - { - if (dragDestination != null) - { - // draggedItem is nulled when the BindableList's add event is received so we can quietly ignore the callbacks. - musicController.ChangeBeatmapSetPosition(draggedItem.BeatmapSetInfo, dragDestination.Value); - dragDestination = null; - } + if (draggedItem == null) + return base.OnDragEnd(e); - return true; - } + if (dragDestination != null) + musicController.ChangeBeatmapSetPosition(draggedItem.BeatmapSetInfo, dragDestination.Value); - return base.OnDragEnd(e); + draggedItem = null; + dragDestination = null; + + return true; } protected override void Update() From 9de0bcae1eef5ff0beaa2fb70f26d66a62cb725e Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 19 Sep 2019 07:58:54 +0300 Subject: [PATCH 208/239] Check for blocking fail mods by default --- osu.Game/Screens/Play/Player.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index fbaab61b42..e8134253f5 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -87,9 +87,11 @@ namespace osu.Game.Screens.Play protected new readonly Bindable> Mods = new Bindable>(Array.Empty()); /// - /// Whether to block the player from failing. + /// Whether failing should be allowed. + /// + /// By default, this checks whether any selected mod disallows failing. /// - protected virtual bool BypassFail => false; + protected virtual bool AllowFail => !Mods.Value.OfType().Any(m => !m.AllowFail); private readonly bool allowPause; private readonly bool showResults; @@ -365,7 +367,7 @@ namespace osu.Game.Screens.Play private bool onFail() { - if (Mods.Value.OfType().Any(m => !m.AllowFail) || BypassFail) + if (!AllowFail) return false; HasFailed = true; From e793854735a812acb0d4e01ddbff87c5d20922d3 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 19 Sep 2019 08:00:41 +0300 Subject: [PATCH 209/239] Invert BypassFail usage --- osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs | 4 ++-- osu.Game/Screens/Play/ReplayPlayer.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs index d89304cf44..36335bc54a 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplay.cs @@ -26,14 +26,14 @@ namespace osu.Game.Tests.Visual.Gameplay { AddUntilStep("score above zero", () => ((ScoreAccessibleReplayPlayer)Player).ScoreProcessor.TotalScore.Value > 0); AddUntilStep("key counter counted keys", () => ((ScoreAccessibleReplayPlayer)Player).HUDOverlay.KeyCounter.Children.Any(kc => kc.CountPresses > 0)); - AddAssert("cannot fail", () => ((ScoreAccessibleReplayPlayer)Player).BypassFail); + AddAssert("cannot fail", () => !((ScoreAccessibleReplayPlayer)Player).AllowFail); } private class ScoreAccessibleReplayPlayer : ReplayPlayer { public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; public new HUDOverlay HUDOverlay => base.HUDOverlay; - public new bool BypassFail => base.BypassFail; + public new bool AllowFail => base.AllowFail; protected override bool PauseOnFocusLost => false; diff --git a/osu.Game/Screens/Play/ReplayPlayer.cs b/osu.Game/Screens/Play/ReplayPlayer.cs index da9f558c16..b040549efc 100644 --- a/osu.Game/Screens/Play/ReplayPlayer.cs +++ b/osu.Game/Screens/Play/ReplayPlayer.cs @@ -9,8 +9,8 @@ namespace osu.Game.Screens.Play { private readonly Score score; - // Block replays from failing. (see https://github.com/ppy/osu/issues/6108) - protected override bool BypassFail => true; + // Disallow replays from failing. (see https://github.com/ppy/osu/issues/6108) + protected override bool AllowFail => false; public ReplayPlayer(Score score, bool allowPause = true, bool showResults = true) : base(allowPause, showResults) From 762adb783ae359a5d3f1d5bebeabd1ec3ef79be8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 14:15:06 +0900 Subject: [PATCH 210/239] Fix duplicate invocation of updateState on load complete --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 9a7f1e8522..b94de0df89 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -253,7 +253,8 @@ namespace osu.Game.Rulesets.Objects.Drawables ApplySkin(skin, allowFallback); - updateState(State.Value, true); + if (IsLoaded) + updateState(State.Value, true); } /// From a7b6895d4c9c79119922792b6d688faa48ee2166 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 14:26:15 +0900 Subject: [PATCH 211/239] Revert changes to BeatmapDetailArea --- .../SongSelect/TestSceneBeatmapDetailArea.cs | 1 - osu.Game/Screens/Select/BeatmapDetailArea.cs | 77 ++++++++----------- osu.Game/Screens/Select/SongSelect.cs | 1 - 3 files changed, 30 insertions(+), 49 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs index ee47888d99..ed9e01a67e 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetailArea.cs @@ -163,7 +163,6 @@ namespace osu.Game.Tests.Visual.SongSelect })); AddStep("null beatmap", () => detailsArea.Beatmap = null); - AddStep("Toggle top score visibility", () => detailsArea.TopScore.ToggleVisibility()); } } } diff --git a/osu.Game/Screens/Select/BeatmapDetailArea.cs b/osu.Game/Screens/Select/BeatmapDetailArea.cs index 648dae68bc..5348de68d6 100644 --- a/osu.Game/Screens/Select/BeatmapDetailArea.cs +++ b/osu.Game/Screens/Select/BeatmapDetailArea.cs @@ -1,21 +1,23 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Beatmaps; -using osu.Game.Screens.Select.Details; using osu.Game.Screens.Select.Leaderboards; namespace osu.Game.Screens.Select { public class BeatmapDetailArea : Container { - private const float padding = 10; + private const float details_padding = 10; + + private readonly Container content; + protected override Container Content => content; public readonly BeatmapDetails Details; public readonly BeatmapLeaderboard Leaderboard; - public readonly UserTopScoreContainer TopScore; private WorkingBeatmap beatmap; @@ -27,13 +29,12 @@ namespace osu.Game.Screens.Select beatmap = value; Details.Beatmap = beatmap?.BeatmapInfo; Leaderboard.Beatmap = beatmap is DummyWorkingBeatmap ? null : beatmap?.BeatmapInfo; - TopScore.Hide(); } } public BeatmapDetailArea() { - Children = new Drawable[] + AddRangeInternal(new Drawable[] { new BeatmapDetailAreaTabControl { @@ -57,51 +58,33 @@ namespace osu.Game.Screens.Select } }, }, - new Container + content = new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = BeatmapDetailAreaTabControl.HEIGHT }, + }, + }); + + AddRange(new Drawable[] + { + Details = new BeatmapDetails + { + RelativeSizeAxes = Axes.X, + Alpha = 0, + Margin = new MarginPadding { Top = details_padding }, + }, + Leaderboard = new BeatmapLeaderboard { - Padding = new MarginPadding { Top = BeatmapDetailAreaTabControl.HEIGHT, Bottom = padding }, RelativeSizeAxes = Axes.Both, - Child = new GridContainer - { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] - { - new Dimension(GridSizeMode.Distributed), - new Dimension(GridSizeMode.AutoSize), - }, - Content = new[] - { - new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.Both, - Children = new Drawable[] - { - Details = new BeatmapDetails - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - Padding = new MarginPadding { Top = padding }, - }, - Leaderboard = new BeatmapLeaderboard - { - RelativeSizeAxes = Axes.Both, - } - } - } - }, - new Drawable[] - { - TopScore = new UserTopScoreContainer - { - Score = { BindTarget = Leaderboard.TopScore } - } - } - }, - }, } - }; + }); + } + + protected override void UpdateAfterChildren() + { + base.UpdateAfterChildren(); + + Details.Height = Math.Min(DrawHeight - details_padding * 3 - BeatmapDetailAreaTabControl.HEIGHT, 450); } } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 173442384e..7f9804c6a3 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -226,7 +226,6 @@ namespace osu.Game.Screens.Select void displayScore(ScoreInfo score) => this.Push(new SoloResults(score)); BeatmapDetails.Leaderboard.ScoreSelected += displayScore; - BeatmapDetails.TopScore.ScoreSelected += displayScore; } [BackgroundDependencyLoader(true)] From da4d83063e73c4cda5a705fa0500f4153388a029 Mon Sep 17 00:00:00 2001 From: iiSaLMaN Date: Thu, 19 Sep 2019 08:31:11 +0300 Subject: [PATCH 212/239] Simplify LINQ expression --- osu.Game/Screens/Play/Player.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index e8134253f5..30d6cfbf68 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -89,9 +89,9 @@ namespace osu.Game.Screens.Play /// /// Whether failing should be allowed. /// - /// By default, this checks whether any selected mod disallows failing. + /// By default, this checks whether all selected mods allow failing. /// - protected virtual bool AllowFail => !Mods.Value.OfType().Any(m => !m.AllowFail); + protected virtual bool AllowFail => Mods.Value.OfType().All(m => m.AllowFail); private readonly bool allowPause; private readonly bool showResults; From 4967ffd8e557291a261a6b678026a91a2901965f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 14:52:31 +0900 Subject: [PATCH 213/239] Move inside leaderboard --- osu.Game/Online/Leaderboards/Leaderboard.cs | 39 ++++++++++++++++--- .../Select/Leaderboards/BeatmapLeaderboard.cs | 12 ++++++ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 147556b78b..d66a9a7535 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -35,6 +35,10 @@ namespace osu.Game.Online.Leaderboards private bool scoresLoadedOnce; + private readonly Container content; + + protected override Container Content => content; + private IEnumerable scores; public IEnumerable Scores @@ -60,13 +64,13 @@ namespace osu.Game.Online.Leaderboards // ensure placeholder is hidden when displaying scores PlaceholderState = PlaceholderState.Successful; - var sf = CreateScoreFlow(); - sf.ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1)); + var scoreFlow = CreateScoreFlow(); + scoreFlow.ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1)); // schedule because we may not be loaded yet (LoadComponentAsync complains). - showScoresDelegate = Schedule(() => LoadComponentAsync(sf, _ => + showScoresDelegate = Schedule(() => LoadComponentAsync(scoreFlow, _ => { - scrollContainer.Add(scrollFlow = sf); + scrollContainer.Add(scrollFlow = scoreFlow); int i = 0; @@ -164,10 +168,33 @@ namespace osu.Game.Online.Leaderboards { Children = new Drawable[] { - scrollContainer = new OsuScrollContainer + new GridContainer { RelativeSizeAxes = Axes.Both, - ScrollbarVisible = false, + RowDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.AutoSize), + }, + Content = new[] + { + new Drawable[] + { + scrollContainer = new OsuScrollContainer + { + RelativeSizeAxes = Axes.Both, + ScrollbarVisible = false, + } + }, + new Drawable[] + { + content = new Container + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + }, + } + }, }, loading = new LoadingAnimation(), placeholderContainer = new Container diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 4e4def4911..0eef784279 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -80,6 +80,18 @@ namespace osu.Game.Screens.Select.Leaderboards if (filterMods) UpdateScores(); }; + + TopScore.BindValueChanged(newTopScore); + } + + private void newTopScore(ValueChangedEvent score) + { + Content.Clear(); + + if (score.NewValue != null) + { + + } } protected override bool IsOnlineScope => Scope != BeatmapLeaderboardScope.Local; From c76e27549a6db11e251376d5d15c2a3d710545b9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 14:56:52 +0900 Subject: [PATCH 214/239] Remove spacing --- osu.Game/Screens/Play/Player.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 30d6cfbf68..4b234ab296 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -88,7 +88,6 @@ namespace osu.Game.Screens.Play /// /// Whether failing should be allowed. - /// /// By default, this checks whether all selected mods allow failing. /// protected virtual bool AllowFail => Mods.Value.OfType().All(m => m.AllowFail); From 098e89cb66a2896d673c0cb924eecfc92147ff56 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 15:23:33 +0900 Subject: [PATCH 215/239] Improve state reset flow --- osu.Game/Online/Leaderboards/Leaderboard.cs | 13 ++++--- .../Select/Details/UserTopScoreContainer.cs | 22 ++++++------ .../Select/Leaderboards/BeatmapLeaderboard.cs | 36 ++++++++++++------- 3 files changed, 42 insertions(+), 29 deletions(-) diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index d66a9a7535..83de0635fb 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -120,9 +120,7 @@ namespace osu.Game.Online.Leaderboards { if (value != PlaceholderState.Successful) { - getScoresRequest?.Cancel(); - getScoresRequest = null; - Scores = null; + Reset(); } if (value == placeholderState) @@ -166,7 +164,7 @@ namespace osu.Game.Online.Leaderboards protected Leaderboard() { - Children = new Drawable[] + InternalChildren = new Drawable[] { new GridContainer { @@ -204,6 +202,13 @@ namespace osu.Game.Online.Leaderboards }; } + protected virtual void Reset() + { + getScoresRequest?.Cancel(); + getScoresRequest = null; + Scores = null; + } + private IAPIProvider api; private ScheduledDelegate pendingUpdateScores; diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index c10f4d4fd4..959fbb927a 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -17,9 +17,8 @@ namespace osu.Game.Screens.Select.Details public class UserTopScoreContainer : VisibilityContainer { private const int height = 90; - private const int duration = 800; + private const int duration = 500; - private readonly Container contentContainer; private readonly Container scoreContainer; public Bindable Score = new Bindable(); @@ -38,7 +37,7 @@ namespace osu.Game.Screens.Select.Details Children = new Drawable[] { - contentContainer = new Container + new Container { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, @@ -74,15 +73,12 @@ namespace osu.Game.Screens.Select.Details { var newScore = score.NewValue; - if (newScore == null) - { - Hide(); - return; - } - scoreContainer.Clear(); loadScoreCancellation?.Cancel(); + if (newScore == null) + return; + LoadComponentAsync(new LeaderboardScore(newScore.Score, newScore.Position) { Action = () => ScoreSelected?.Invoke(newScore.Score) @@ -93,12 +89,14 @@ namespace osu.Game.Screens.Select.Details }, (loadScoreCancellation = new CancellationTokenSource()).Token); } - protected override void PopIn() => this.ResizeHeightTo(height, duration / 4f, Easing.OutQuint).OnComplete(_ => contentContainer.FadeIn(duration, Easing.OutQuint)); + protected override void PopIn() + { + this.FadeIn(duration, Easing.OutQuint); + } protected override void PopOut() { - this.ResizeHeightTo(0); - contentContainer.FadeOut(duration / 4f, Easing.OutQuint); + this.FadeOut(duration, Easing.OutQuint); } } } diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 0eef784279..d038049504 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -14,13 +14,12 @@ using osu.Game.Online.Leaderboards; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Scoring; +using osu.Game.Screens.Select.Details; namespace osu.Game.Screens.Select.Leaderboards { public class BeatmapLeaderboard : Leaderboard { - public Bindable TopScore = new Bindable(); - public Action ScoreSelected; private BeatmapInfo beatmap; @@ -40,8 +39,25 @@ namespace osu.Game.Screens.Select.Leaderboards } } + public APILegacyUserTopScoreInfo TopScore + { + get => topScoreContainer.Score.Value; + set + { + if (value == null) + topScoreContainer.Hide(); + else + { + topScoreContainer.Show(); + topScoreContainer.Score.Value = value; + } + } + } + private bool filterMods; + private UserTopScoreContainer topScoreContainer; + /// /// Whether to apply the game's currently selected mods as a filter when retrieving scores. /// @@ -81,25 +97,19 @@ namespace osu.Game.Screens.Select.Leaderboards UpdateScores(); }; - TopScore.BindValueChanged(newTopScore); + Content.Add(topScoreContainer = new UserTopScoreContainer()); } - private void newTopScore(ValueChangedEvent score) + protected override void Reset() { - Content.Clear(); - - if (score.NewValue != null) - { - - } + base.Reset(); + TopScore = null; } protected override bool IsOnlineScope => Scope != BeatmapLeaderboardScope.Local; protected override APIRequest FetchScores(Action> scoresCallback) { - TopScore.Value = null; - if (Beatmap == null) { PlaceholderState = PlaceholderState.NoneSelected; @@ -161,7 +171,7 @@ namespace osu.Game.Screens.Select.Leaderboards req.Success += r => { scoresCallback?.Invoke(r.Scores); - TopScore.Value = r.UserScore; + TopScore = r.UserScore; }; return req; From 9b35de9ce17c1fbe85ccabbc4e58bba81bef805f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 15:23:37 +0900 Subject: [PATCH 216/239] Update tests --- .../SongSelect/TestSceneBeatmapLeaderboard.cs | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index cb4cd63266..bbd874fcd7 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -5,8 +5,12 @@ using System; using System.Collections.Generic; using osu.Framework.Graphics; using osu.Game.Beatmaps; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Osu.Mods; using osu.Game.Scoring; +using osu.Game.Screens.Select.Details; using osu.Game.Screens.Select.Leaderboards; using osu.Game.Users; using osuTK; @@ -20,6 +24,8 @@ namespace osu.Game.Tests.Visual.SongSelect typeof(Placeholder), typeof(MessagePlaceholder), typeof(RetrievalFailurePlaceholder), + typeof(UserTopScoreContainer), + typeof(Leaderboard), }; private readonly FailableLeaderboard leaderboard; @@ -35,6 +41,7 @@ namespace osu.Game.Tests.Visual.SongSelect }); AddStep(@"New Scores", newScores); + AddStep(@"Show personal best", showPersonalBest); AddStep(@"Empty Scores", () => leaderboard.SetRetrievalState(PlaceholderState.NoScores)); AddStep(@"Network failure", () => leaderboard.SetRetrievalState(PlaceholderState.NetworkFailure)); AddStep(@"No supporter", () => leaderboard.SetRetrievalState(PlaceholderState.NotSupporter)); @@ -45,6 +52,32 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep($"{status} beatmap", () => showBeatmapWithStatus(status)); } + private void showPersonalBest() + { + leaderboard.TopScore = new APILegacyUserTopScoreInfo + { + Position = 999, + Score = new APILegacyScoreInfo + { + Rank = ScoreRank.XH, + Accuracy = 1, + MaxCombo = 244, + TotalScore = 1707827, + Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, + User = new User + { + Id = 6602580, + Username = @"waaiiru", + Country = new Country + { + FullName = @"Spain", + FlagName = @"ES", + }, + }, + } + }; + } + private void newScores() { var scores = new[] From 80f46e02d8578ed0c23db9bb68bd7806f637663c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 15:33:49 +0900 Subject: [PATCH 217/239] Add equals (=) query operator variants --- osu.Game/Screens/Select/FilterControl.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 01e7ed9383..b25e65092e 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -183,7 +183,7 @@ namespace osu.Game.Screens.Select private void updateCriteria() => FilterChanged?.Invoke(CreateCriteria()); private static readonly Regex query_syntax_regex = new Regex( - @"\b(?stars|ar|dr|cs|divisor|length|objects|bpm|status)(?[:><]+)(?\S*)", + @"\b(?stars|ar|dr|cs|divisor|length|objects|bpm|status)(?[=:><]+)(?\S*)", RegexOptions.Compiled | RegexOptions.IgnoreCase); private void applyQueries(FilterCriteria criteria, ref string query) @@ -246,6 +246,7 @@ namespace osu.Game.Screens.Select default: return; + case "=": case ":": range.IsInclusive = true; range.Min = value - equalityToleration; @@ -257,6 +258,7 @@ namespace osu.Game.Screens.Select range.Min = value; break; + case ">=": case ">:": range.IsInclusive = true; range.Min = value; @@ -267,6 +269,7 @@ namespace osu.Game.Screens.Select range.Max = value; break; + case "<=": case "<:": range.IsInclusive = true; range.Max = value; From e0fd8609d1f96f5fd0169248a3e6b2d3611097f2 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 15:34:46 +0900 Subject: [PATCH 218/239] Fix margins and clean up implementation --- .../Select/Details/UserTopScoreContainer.cs | 28 ++++++------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs index 959fbb927a..9d03f8439a 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs @@ -16,7 +16,6 @@ namespace osu.Game.Screens.Select.Details { public class UserTopScoreContainer : VisibilityContainer { - private const int height = 90; private const int duration = 500; private readonly Container scoreContainer; @@ -30,33 +29,30 @@ namespace osu.Game.Screens.Select.Details public UserTopScoreContainer() { RelativeSizeAxes = Axes.X; - Height = height; + AutoSizeAxes = Axes.Y; - Anchor = Anchor.BottomLeft; - Origin = Anchor.BottomLeft; + Margin = new MarginPadding { Vertical = 5 }; Children = new Drawable[] { - new Container + new FillFlowContainer { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, RelativeSizeAxes = Axes.X, - Height = height, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, Children = new Drawable[] { new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, - Margin = new MarginPadding { Top = 5 }, Text = @"your personal best".ToUpper(), Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold), }, scoreContainer = new Container { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, } @@ -89,14 +85,8 @@ namespace osu.Game.Screens.Select.Details }, (loadScoreCancellation = new CancellationTokenSource()).Token); } - protected override void PopIn() - { - this.FadeIn(duration, Easing.OutQuint); - } + protected override void PopIn() => this.FadeIn(duration, Easing.OutQuint); - protected override void PopOut() - { - this.FadeOut(duration, Easing.OutQuint); - } + protected override void PopOut() => this.FadeOut(duration, Easing.OutQuint); } } From 2b6c9aeb266e4f352fddebabb066314527ff658e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 15:38:40 +0900 Subject: [PATCH 219/239] Move top score container to more local namespace --- .../Visual/SongSelect/TestSceneBeatmapLeaderboard.cs | 1 - .../Visual/SongSelect/TestSceneUserTopScoreContainer.cs | 2 +- osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 1 - .../{Details => Leaderboards}/UserTopScoreContainer.cs | 6 +++--- 4 files changed, 4 insertions(+), 6 deletions(-) rename osu.Game/Screens/Select/{Details => Leaderboards}/UserTopScoreContainer.cs (98%) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index bbd874fcd7..fb27ec7654 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -10,7 +10,6 @@ using osu.Game.Online.Leaderboards; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Scoring; -using osu.Game.Screens.Select.Details; using osu.Game.Screens.Select.Leaderboards; using osu.Game.Users; using osuTK; diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs index 38ebb58e76..7fac45e0f1 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneUserTopScoreContainer.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Game.Screens.Select.Details; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -10,6 +9,7 @@ using osu.Game.Online.API.Requests.Responses; using osu.Game.Scoring; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu.Mods; +using osu.Game.Screens.Select.Leaderboards; using osu.Game.Users; namespace osu.Game.Tests.Visual.SongSelect diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index d038049504..71aa8a8a31 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -14,7 +14,6 @@ using osu.Game.Online.Leaderboards; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Scoring; -using osu.Game.Screens.Select.Details; namespace osu.Game.Screens.Select.Leaderboards { diff --git a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs similarity index 98% rename from osu.Game/Screens/Select/Details/UserTopScoreContainer.cs rename to osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs index 9d03f8439a..301b3a6ae1 100644 --- a/osu.Game/Screens/Select/Details/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using System.Threading; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -9,10 +11,8 @@ using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; using osu.Game.Scoring; -using System; -using System.Threading; -namespace osu.Game.Screens.Select.Details +namespace osu.Game.Screens.Select.Leaderboards { public class UserTopScoreContainer : VisibilityContainer { From 033c68a428bc74c126466d8b39b0bb119e8611dd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 15:44:00 +0900 Subject: [PATCH 220/239] Fade in score, not container --- osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs index 301b3a6ae1..c5872e271d 100644 --- a/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -81,7 +81,7 @@ namespace osu.Game.Screens.Select.Leaderboards }, drawableScore => { scoreContainer.Child = drawableScore; - Show(); + drawableScore.FadeInFromZero(duration, Easing.OutQuint); }, (loadScoreCancellation = new CancellationTokenSource()).Token); } From 36d0695e5c243e2012b2f128364a52574665117b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 15:44:05 +0900 Subject: [PATCH 221/239] Add spacing --- osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs b/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs index c5872e271d..da8f676cd0 100644 --- a/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs +++ b/osu.Game/Screens/Select/Leaderboards/UserTopScoreContainer.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; @@ -11,6 +11,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.Leaderboards; using osu.Game.Scoring; +using osuTK; namespace osu.Game.Screens.Select.Leaderboards { @@ -40,6 +41,7 @@ namespace osu.Game.Screens.Select.Leaderboards RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, + Spacing = new Vector2(5), Children = new Drawable[] { new OsuSpriteText From c1daa187fe2aa68426341c6786b18bbee4c621df Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 15:44:14 +0900 Subject: [PATCH 222/239] Reduce default tolerance --- osu.Game/Screens/Select/FilterControl.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index b25e65092e..4c91208aec 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -197,23 +197,23 @@ namespace osu.Game.Screens.Select switch (key) { case "stars" when double.TryParse(value, out var stars): - updateCriteriaRange(ref criteria.StarDifficulty, op, stars, 0.5); + updateCriteriaRange(ref criteria.StarDifficulty, op, stars); break; case "ar" when double.TryParse(value, out var ar): - updateCriteriaRange(ref criteria.ApproachRate, op, ar, 0.3); + updateCriteriaRange(ref criteria.ApproachRate, op, ar); break; case "dr" when double.TryParse(value, out var dr): - updateCriteriaRange(ref criteria.DrainRate, op, dr, 0.3); + updateCriteriaRange(ref criteria.DrainRate, op, dr); break; case "cs" when double.TryParse(value, out var cs): - updateCriteriaRange(ref criteria.CircleSize, op, cs, 0.3); + updateCriteriaRange(ref criteria.CircleSize, op, cs); break; case "bpm" when double.TryParse(value, out var bpm): - updateCriteriaRange(ref criteria.BPM, op, bpm, 0.3); + updateCriteriaRange(ref criteria.BPM, op, bpm); break; case "length" when double.TryParse(value.TrimEnd('m', 's', 'h'), out var length): @@ -239,7 +239,7 @@ namespace osu.Game.Screens.Select } } - private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double equalityToleration = 0) + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double tolerance = 0.05) { switch (op) { @@ -249,8 +249,8 @@ namespace osu.Game.Screens.Select case "=": case ":": range.IsInclusive = true; - range.Min = value - equalityToleration; - range.Max = value + equalityToleration; + range.Min = value - tolerance; + range.Max = value + tolerance; break; case ">": From 48ee95955b80ea7a385e55649fcd71e308d2b197 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 15:45:08 +0900 Subject: [PATCH 223/239] Remove unnecessary redirection --- osu.Game/Screens/Select/SongSelect.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 7f9804c6a3..fca801ce78 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -223,9 +223,7 @@ namespace osu.Game.Screens.Select }); } - void displayScore(ScoreInfo score) => this.Push(new SoloResults(score)); - - BeatmapDetails.Leaderboard.ScoreSelected += displayScore; + BeatmapDetails.Leaderboard.ScoreSelected += score => this.Push(new SoloResults(score)); } [BackgroundDependencyLoader(true)] From e2f7d4bc629defae3f03c64040be75857594c27f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 15:45:43 +0900 Subject: [PATCH 224/239] Remove unnecessary ToMetric avoidance --- osu.Game/Online/Leaderboards/LeaderboardScore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index e21ad413b6..9387482f14 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -80,7 +80,7 @@ namespace osu.Game.Online.Leaderboards Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.GetFont(size: 20, italics: true), - Text = rank <= 999 ? rank.ToString() : rank.ToMetric(decimals: rank < 100000 ? 1 : 0), + Text = rank.ToMetric(decimals: rank < 100000 ? 1 : 0), }, }, }, From 3c21b68b738af2d902341d934f4c34f920b5c5b8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 16:51:57 +0900 Subject: [PATCH 225/239] Make OptionalRange generic --- osu.Game/Screens/Select/FilterControl.cs | 27 ++++++++---- osu.Game/Screens/Select/FilterCriteria.cs | 51 ++++++++++++++++------- 2 files changed, 56 insertions(+), 22 deletions(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 4c91208aec..8fda6c6a97 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -196,19 +196,19 @@ namespace osu.Game.Screens.Select switch (key) { - case "stars" when double.TryParse(value, out var stars): + case "stars" when float.TryParse(value, out var stars): updateCriteriaRange(ref criteria.StarDifficulty, op, stars); break; - case "ar" when double.TryParse(value, out var ar): + case "ar" when float.TryParse(value, out var ar): updateCriteriaRange(ref criteria.ApproachRate, op, ar); break; - case "dr" when double.TryParse(value, out var dr): + case "dr" when float.TryParse(value, out var dr): updateCriteriaRange(ref criteria.DrainRate, op, dr); break; - case "cs" when double.TryParse(value, out var cs): + case "cs" when float.TryParse(value, out var cs): updateCriteriaRange(ref criteria.CircleSize, op, cs); break; @@ -239,7 +239,8 @@ namespace osu.Game.Screens.Select } } - private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double tolerance = 0.05) + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, T value, double tolerance = 0.05f) + where T : struct, IComparable { switch (op) { @@ -249,8 +250,20 @@ namespace osu.Game.Screens.Select case "=": case ":": range.IsInclusive = true; - range.Min = value - tolerance; - range.Max = value + tolerance; + + switch (value) + { + case float _: + range.Min = (T)(object)((float)(object)value - tolerance); + range.Max = (T)(object)((float)(object)value + tolerance); + break; + + case double _: + range.Min = (T)(object)((double)(object)value - tolerance); + range.Max = (T)(object)((double)(object)value + tolerance); + break; + } + break; case ">": diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 84d63c16e0..4867f27c0b 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -14,12 +14,12 @@ namespace osu.Game.Screens.Select public GroupMode Group; public SortMode Sort; - public OptionalRange StarDifficulty; - public OptionalRange ApproachRate; - public OptionalRange DrainRate; - public OptionalRange CircleSize; - public OptionalRange Length; - public OptionalRange BPM; + public OptionalRange StarDifficulty; + public OptionalRange ApproachRate; + public OptionalRange DrainRate; + public OptionalRange CircleSize; + public OptionalRange Length; + public OptionalRange BPM; public int? BeatDivisor; @@ -42,23 +42,44 @@ namespace osu.Game.Screens.Select } } - public struct OptionalRange : IEquatable + public struct OptionalRange : IEquatable> + where T : struct, IComparable { - public bool IsInRange(double value) + public bool IsInRange(T value) { - if (Min.HasValue && (IsInclusive ? value < Min.Value : value <= Min.Value)) - return false; - if (Max.HasValue && (IsInclusive ? value > Max.Value : value >= Max.Value)) - return false; + if (Min.HasValue) + { + int comparison = value.CompareTo(Min.Value); + + if (comparison < 0) + return false; + + if (!IsInclusive && comparison == 0) + return false; + } + + if (Max.HasValue) + { + int comparison = value.CompareTo(Max.Value); + + if (comparison > 0) + return false; + + if (!IsInclusive && comparison == 0) + return false; + } return true; } - public double? Min; - public double? Max; + public T? Min; + public T? Max; public bool IsInclusive; - public bool Equals(OptionalRange range) => Min == range.Min && Max == range.Max; + public bool Equals(OptionalRange other) + => Min.Equals(other.Min) + && Max.Equals(other.Max) + && IsInclusive.Equals(other.IsInclusive); } } } From 0915a94470bd67b3d1cdcabb21bd12c6d3e66373 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 16:53:27 +0900 Subject: [PATCH 226/239] Make BeatDivisor use OptionalRange --- osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs | 2 +- osu.Game/Screens/Select/FilterControl.cs | 4 ++-- osu.Game/Screens/Select/FilterCriteria.cs | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 60e556a261..7017310018 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -36,7 +36,7 @@ namespace osu.Game.Screens.Select.Carousel match &= criteria.Length.IsInRange(Beatmap.Length); match &= criteria.BPM.IsInRange(Beatmap.BPM); - match &= !criteria.BeatDivisor.HasValue || criteria.BeatDivisor == Beatmap.BeatDivisor; + match &= criteria.BeatDivisor.IsInRange(Beatmap.BeatDivisor); match &= !criteria.OnlineStatus.HasValue || criteria.OnlineStatus == Beatmap.Status; if (match) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 8fda6c6a97..829f16d622 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -226,8 +226,8 @@ namespace osu.Game.Screens.Select updateCriteriaRange(ref criteria.Length, op, length * scale, scale / 2.0); break; - case "divisor" when op == ":" && int.TryParse(value, out var divisor): - criteria.BeatDivisor = divisor; + case "divisor" when int.TryParse(value, out var divisor): + updateCriteriaRange(ref criteria.BeatDivisor, op, divisor); break; case "status" when op == ":" && Enum.TryParse(value, ignoreCase: true, out var statusValue): diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 4867f27c0b..4584c63c2e 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -20,8 +20,7 @@ namespace osu.Game.Screens.Select public OptionalRange CircleSize; public OptionalRange Length; public OptionalRange BPM; - - public int? BeatDivisor; + public OptionalRange BeatDivisor; public BeatmapSetOnlineStatus? OnlineStatus; From 167bb9fcc16751087fc687d3424e7ea7cfafa555 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:11:28 +0900 Subject: [PATCH 227/239] Fix ugly casts --- osu.Game/Screens/Select/FilterControl.cs | 46 +++++++++++++++--------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 829f16d622..6ada0e4980 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -239,8 +239,36 @@ namespace osu.Game.Screens.Select } } - private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, T value, double tolerance = 0.05f) - where T : struct, IComparable + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, float value, float tolerance = 0.05f) + { + switch (op) + { + case "=": + case ":": + range.Min = value - tolerance; + range.Max = value + tolerance; + break; + } + + updateCriteriaRange(ref range, op, value); + } + + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double tolerance = 0.05f) + { + switch (op) + { + case "=": + case ":": + range.Min = value - tolerance; + range.Max = value + tolerance; + break; + } + + updateCriteriaRange(ref range, op, value); + } + + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, T value) + where T : struct, IComparable { switch (op) { @@ -250,20 +278,6 @@ namespace osu.Game.Screens.Select case "=": case ":": range.IsInclusive = true; - - switch (value) - { - case float _: - range.Min = (T)(object)((float)(object)value - tolerance); - range.Max = (T)(object)((float)(object)value + tolerance); - break; - - case double _: - range.Min = (T)(object)((double)(object)value - tolerance); - range.Max = (T)(object)((double)(object)value + tolerance); - break; - } - break; case ">": From d7831d8f5d6cdced76b9ff070b1d0d55c932818b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:11:43 +0900 Subject: [PATCH 228/239] Use non-generic IComparable interface --- osu.Game/Screens/Select/FilterCriteria.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 4584c63c2e..ff55ef5b12 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets; @@ -42,13 +43,13 @@ namespace osu.Game.Screens.Select } public struct OptionalRange : IEquatable> - where T : struct, IComparable + where T : struct, IComparable { public bool IsInRange(T value) { - if (Min.HasValue) + if (Min != null) { - int comparison = value.CompareTo(Min.Value); + int comparison = Comparer.Default.Compare(value, Min.Value); if (comparison < 0) return false; @@ -57,9 +58,9 @@ namespace osu.Game.Screens.Select return false; } - if (Max.HasValue) + if (Max != null) { - int comparison = value.CompareTo(Max.Value); + int comparison = Comparer.Default.Compare(value, Max.Value); if (comparison > 0) return false; From 7683f7ff23198fc782135b4959550abe13236c97 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:12:07 +0900 Subject: [PATCH 229/239] Make OnlineStatus use OptionalRange --- osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs | 2 +- osu.Game/Screens/Select/FilterControl.cs | 4 ++-- osu.Game/Screens/Select/FilterCriteria.cs | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 7017310018..9cc84c8bdd 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -37,7 +37,7 @@ namespace osu.Game.Screens.Select.Carousel match &= criteria.BPM.IsInRange(Beatmap.BPM); match &= criteria.BeatDivisor.IsInRange(Beatmap.BeatDivisor); - match &= !criteria.OnlineStatus.HasValue || criteria.OnlineStatus == Beatmap.Status; + match &= criteria.OnlineStatus.IsInRange(Beatmap.Status); if (match) foreach (var criteriaTerm in criteria.SearchTerms) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 6ada0e4980..f1c8bb3a4e 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -230,8 +230,8 @@ namespace osu.Game.Screens.Select updateCriteriaRange(ref criteria.BeatDivisor, op, divisor); break; - case "status" when op == ":" && Enum.TryParse(value, ignoreCase: true, out var statusValue): - criteria.OnlineStatus = statusValue; + case "status" when Enum.TryParse(value, true, out var statusValue): + updateCriteriaRange(ref criteria.OnlineStatus, op, statusValue); break; } diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index ff55ef5b12..674f64efb4 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -22,8 +22,7 @@ namespace osu.Game.Screens.Select public OptionalRange Length; public OptionalRange BPM; public OptionalRange BeatDivisor; - - public BeatmapSetOnlineStatus? OnlineStatus; + public OptionalRange OnlineStatus; public string[] SearchTerms = Array.Empty(); From e075dd7ea84258862fac010f95e4a56d62d6ea0c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:16:34 +0900 Subject: [PATCH 230/239] Fix equals operator not working --- osu.Game/Screens/Select/FilterControl.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index f1c8bb3a4e..cd958a9503 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -241,6 +241,8 @@ namespace osu.Game.Screens.Select private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, float value, float tolerance = 0.05f) { + updateCriteriaRange(ref range, op, value); + switch (op) { case "=": @@ -249,12 +251,12 @@ namespace osu.Game.Screens.Select range.Max = value + tolerance; break; } - - updateCriteriaRange(ref range, op, value); } - private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double tolerance = 0.05f) + private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, double value, double tolerance = 0.05) { + updateCriteriaRange(ref range, op, value); + switch (op) { case "=": @@ -263,8 +265,6 @@ namespace osu.Game.Screens.Select range.Max = value + tolerance; break; } - - updateCriteriaRange(ref range, op, value); } private void updateCriteriaRange(ref FilterCriteria.OptionalRange range, string op, T value) @@ -278,6 +278,8 @@ namespace osu.Game.Screens.Select case "=": case ":": range.IsInclusive = true; + range.Min = value; + range.Max = value; break; case ">": From 96ea507320f6b10a9b902f5c1cc6f2df17a9c07a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:21:22 +0900 Subject: [PATCH 231/239] Reorder comparison for readability --- osu.Game/Screens/Select/FilterCriteria.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 674f64efb4..a3fa1b10ca 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -53,7 +53,7 @@ namespace osu.Game.Screens.Select if (comparison < 0) return false; - if (!IsInclusive && comparison == 0) + if (comparison == 0 && !IsInclusive) return false; } @@ -64,7 +64,7 @@ namespace osu.Game.Screens.Select if (comparison > 0) return false; - if (!IsInclusive && comparison == 0) + if (comparison == 0 && !IsInclusive) return false; } From e6c36a8bc7974e5c2b3f31c7e41467bc53809d7f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 17:27:54 +0900 Subject: [PATCH 232/239] Fix scaling mode being applied to judgements --- osu.Game/Rulesets/Judgements/DrawableJudgement.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 061c8cb3e1..b77fc1cfb0 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Judgements Font = OsuFont.Numeric.With(size: 20), Colour = judgementColour(Result.Type), Scale = new Vector2(0.85f, 1), - }) + }, confineMode: ConfineMode.NoScaling) }; } From 5120d82ef84cba05df1b775cd1689b1e7d60a562 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:36:42 +0900 Subject: [PATCH 233/239] Fix crash with multiple range criterias --- osu.Game/Screens/Select/FilterControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index cd958a9503..e3c23f7e22 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -235,7 +235,7 @@ namespace osu.Game.Screens.Select break; } - query = query.Remove(match.Index, match.Length); + query = query.Replace(match.ToString(), ""); } } From da15b900f7d628f4790dfd263c045382cdcd4f51 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:44:24 +0900 Subject: [PATCH 234/239] Remove virtual member from ModBlockFail --- osu.Game/Rulesets/Mods/ModBlockFail.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModBlockFail.cs b/osu.Game/Rulesets/Mods/ModBlockFail.cs index 55c074bde2..7d7ecfa416 100644 --- a/osu.Game/Rulesets/Mods/ModBlockFail.cs +++ b/osu.Game/Rulesets/Mods/ModBlockFail.cs @@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Mods /// public bool AllowFail => false; - public virtual bool RestartOnFail => false; + public bool RestartOnFail => false; public void ReadFromConfig(OsuConfigManager config) { From 65276cd235a0026170d4e06b2faffc515b045c06 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 17:58:10 +0900 Subject: [PATCH 235/239] Remove whitespace --- osu.Game/Rulesets/Mods/ModBlockFail.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Rulesets/Mods/ModBlockFail.cs b/osu.Game/Rulesets/Mods/ModBlockFail.cs index 7d7ecfa416..957a8d3348 100644 --- a/osu.Game/Rulesets/Mods/ModBlockFail.cs +++ b/osu.Game/Rulesets/Mods/ModBlockFail.cs @@ -15,7 +15,6 @@ namespace osu.Game.Rulesets.Mods /// We never fail, 'yo. /// public bool AllowFail => false; - public bool RestartOnFail => false; public void ReadFromConfig(OsuConfigManager config) From bc9941a990ea7430f2f8f1d87714beb8517e1dab Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 18:00:11 +0900 Subject: [PATCH 236/239] Newline required when xmldocs are involved --- osu.Game/Rulesets/Mods/ModBlockFail.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Rulesets/Mods/ModBlockFail.cs b/osu.Game/Rulesets/Mods/ModBlockFail.cs index 957a8d3348..7d7ecfa416 100644 --- a/osu.Game/Rulesets/Mods/ModBlockFail.cs +++ b/osu.Game/Rulesets/Mods/ModBlockFail.cs @@ -15,6 +15,7 @@ namespace osu.Game.Rulesets.Mods /// We never fail, 'yo. /// public bool AllowFail => false; + public bool RestartOnFail => false; public void ReadFromConfig(OsuConfigManager config) From ddff9882cf25e447df3e5632b0bc65f65d125d73 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 17:35:45 +0900 Subject: [PATCH 237/239] Fix importing archives which are nested in a single folder within a zip --- .../Beatmaps/IO/ImportBeatmapTest.cs | 50 ++++++++++++++++++- osu.Game/Database/ArchiveModelManager.cs | 7 ++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs index ad0ed00989..8b39946ab0 100644 --- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs +++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs @@ -15,7 +15,10 @@ using osu.Framework.Logging; using osu.Game.Beatmaps; using osu.Game.IO; using osu.Game.Tests.Resources; +using SharpCompress.Archives; using SharpCompress.Archives.Zip; +using SharpCompress.Common; +using SharpCompress.Writers.Zip; namespace osu.Game.Tests.Beatmaps.IO { @@ -135,7 +138,7 @@ namespace osu.Game.Tests.Beatmaps.IO using (var zip = ZipArchive.Open(brokenOsz)) { zip.AddEntry("broken.osu", brokenOsu, false); - zip.SaveTo(outStream, SharpCompress.Common.CompressionType.Deflate); + zip.SaveTo(outStream, CompressionType.Deflate); } // this will trigger purging of the existing beatmap (online set id match) but should rollback due to broken osu. @@ -366,6 +369,51 @@ namespace osu.Game.Tests.Beatmaps.IO } } + [Test] + public async Task TestImportNestedStructure() + { + using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportNestedStructure")) + { + try + { + var osu = loadOsu(host); + + var temp = TestResources.GetTestBeatmapForImport(); + + string extractedFolder = $"{temp}_extracted"; + string subfolder = Path.Combine(extractedFolder, "subfolder"); + + Directory.CreateDirectory(subfolder); + + try + { + using (var zip = ZipArchive.Open(temp)) + zip.WriteToDirectory(subfolder); + + using (var zip = ZipArchive.Create()) + { + zip.AddAllFromDirectory(extractedFolder); + zip.SaveTo(temp, new ZipWriterOptions(CompressionType.Deflate)); + } + + var imported = await osu.Dependencies.Get().Import(temp); + + ensureLoaded(osu); + + Assert.IsFalse(imported.Files.Any(f => f.Filename.Contains("subfolder")), "Files contain common subfolder"); + } + finally + { + Directory.Delete(extractedFolder, true); + } + } + finally + { + host.Exit(); + } + } + } + public static async Task LoadOszIntoOsu(OsuGameBase osu, string path = null) { var temp = path ?? TestResources.GetTestBeatmapForImport(); diff --git a/osu.Game/Database/ArchiveModelManager.cs b/osu.Game/Database/ArchiveModelManager.cs index 52d3f013ce..6c79b0d472 100644 --- a/osu.Game/Database/ArchiveModelManager.cs +++ b/osu.Game/Database/ArchiveModelManager.cs @@ -11,6 +11,7 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using osu.Framework; using osu.Framework.Extensions; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.IO.File; using osu.Framework.Logging; using osu.Framework.Platform; @@ -481,12 +482,16 @@ namespace osu.Game.Database { var fileInfos = new List(); + string prefix = reader.Filenames.GetCommonPrefix(); + if (!(prefix.EndsWith("/") || prefix.EndsWith("\\"))) + prefix = string.Empty; + // import files to manager foreach (string file in reader.Filenames) using (Stream s = reader.GetStream(file)) fileInfos.Add(new TFileModel { - Filename = FileSafety.PathStandardise(file), + Filename = FileSafety.PathStandardise(file.Substring(prefix.Length)), FileInfo = files.Add(s) }); From cffee1fd5e39c0857d877793be0a5184bce5cc3b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Sep 2019 20:02:45 +0900 Subject: [PATCH 238/239] Fix imported beatmap paths not correctly matching files --- osu.Game/Beatmaps/BeatmapManager.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 02d7b2d98f..55b8b80e44 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -89,7 +89,7 @@ namespace osu.Game.Beatmaps protected override Task Populate(BeatmapSetInfo beatmapSet, ArchiveReader archive, CancellationToken cancellationToken = default) { if (archive != null) - beatmapSet.Beatmaps = createBeatmapDifficulties(archive); + beatmapSet.Beatmaps = createBeatmapDifficulties(beatmapSet.Files); foreach (BeatmapInfo b in beatmapSet.Beatmaps) { @@ -279,13 +279,13 @@ namespace osu.Game.Beatmaps /// /// Create all required s for the provided archive. /// - private List createBeatmapDifficulties(ArchiveReader reader) + private List createBeatmapDifficulties(List files) { var beatmapInfos = new List(); - foreach (var name in reader.Filenames.Where(f => f.EndsWith(".osu"))) + foreach (var file in files.Where(f => f.Filename.EndsWith(".osu"))) { - using (var raw = reader.GetStream(name)) + using (var raw = Files.Store.GetStream(file.FileInfo.StoragePath)) using (var ms = new MemoryStream()) //we need a memory stream so we can seek using (var sr = new StreamReader(ms)) { @@ -295,7 +295,7 @@ namespace osu.Game.Beatmaps var decoder = Decoder.GetDecoder(sr); IBeatmap beatmap = decoder.Decode(sr); - beatmap.BeatmapInfo.Path = name; + beatmap.BeatmapInfo.Path = file.Filename; beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash(); beatmap.BeatmapInfo.MD5Hash = ms.ComputeMD5Hash(); From 94d3bcc612b96c63814e6fb5523f3b794ee12877 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 19 Sep 2019 20:47:33 +0900 Subject: [PATCH 239/239] Fix top score not being selectable --- osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 71aa8a8a31..337d46ecdd 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -96,7 +96,10 @@ namespace osu.Game.Screens.Select.Leaderboards UpdateScores(); }; - Content.Add(topScoreContainer = new UserTopScoreContainer()); + Content.Add(topScoreContainer = new UserTopScoreContainer + { + ScoreSelected = s => ScoreSelected?.Invoke(s) + }); } protected override void Reset()