From c32d17d16a4db072151b369590ccf261e23b8afd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 18 Jun 2019 01:32:52 +0900 Subject: [PATCH 1/4] Fix audio not dimming after race condition Also adjusts transition slightly for smoother effect. --- osu.Game/OsuGame.cs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index f38eecef81..d856e6b935 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -181,9 +181,9 @@ namespace osu.Game configSkin.ValueChanged += skinId => SkinManager.CurrentSkinInfo.Value = SkinManager.Query(s => s.ID == skinId.NewValue) ?? SkinInfo.Default; configSkin.TriggerChange(); - LocalConfig.BindWith(OsuSetting.VolumeInactive, userInactiveVolume); - IsActive.BindValueChanged(active => updateActiveState(active.NewValue), true); + + Audio.AddAdjustment(AdjustableProperty.Volume, inactiveVolumeFade); } private ExternalLinkOpener externalLinkOpener; @@ -688,22 +688,14 @@ namespace osu.Game #region Inactive audio dimming - private readonly BindableDouble userInactiveVolume = new BindableDouble(); - private readonly BindableDouble inactiveVolumeFade = new BindableDouble(); private void updateActiveState(bool isActive) { if (isActive) - { - this.TransformBindableTo(inactiveVolumeFade, 1, 500, Easing.OutQuint) - .Finally(_ => Audio.RemoveAdjustment(AdjustableProperty.Volume, inactiveVolumeFade)); //wait for the transition to finish to remove the inactive audio adjustment - } + this.TransformBindableTo(inactiveVolumeFade, 1, 400, Easing.OutQuint); else - { - Audio.AddAdjustment(AdjustableProperty.Volume, inactiveVolumeFade); - this.TransformBindableTo(inactiveVolumeFade, userInactiveVolume.Value, 1500, Easing.OutSine); - } + this.TransformBindableTo(inactiveVolumeFade, LocalConfig.Get(OsuSetting.VolumeInactive), 4000, Easing.OutQuint); } #endregion From de59e038acd84a8374618bbef4fba68b3f872230 Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 21 Jun 2019 14:29:16 +0900 Subject: [PATCH 2/4] Prevent non-combo affecting judgements from triggering sudden death --- .../TestSceneTaikoSuddenDeath.cs | 65 +++++++++++++++++++ .../Visual/Gameplay/TestSceneFailAnimation.cs | 2 +- osu.Game/Rulesets/Mods/ModPerfect.cs | 3 +- osu.Game/Rulesets/Mods/ModSuddenDeath.cs | 3 +- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 8 +-- 5 files changed, 74 insertions(+), 7 deletions(-) create mode 100644 osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs new file mode 100644 index 0000000000..ca3c477594 --- /dev/null +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.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.Linq; +using NUnit.Framework; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Scoring; +using osu.Game.Rulesets.Taiko.Beatmaps; +using osu.Game.Rulesets.Taiko.Mods; +using osu.Game.Rulesets.Taiko.Objects; +using osu.Game.Screens.Play; +using osu.Game.Tests.Visual; + +namespace osu.Game.Rulesets.Taiko.Tests +{ + public class TestSceneTaikoSuddenDeath : PlayerTestScene + { + public TestSceneTaikoSuddenDeath() + : base(new TaikoRuleset()) + { + } + + protected override bool AllowFail => true; + + protected override Player CreatePlayer(Ruleset ruleset) => new ScoreAccessiblePlayer(); + + protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => + new TaikoBeatmap + { + HitObjects = + { + new Swell { StartTime = 1500 }, + new Hit { StartTime = 100000 }, + }, + BeatmapInfo = + { + Ruleset = new TaikoRuleset().RulesetInfo + } + }; + + [Test] + public void TestSpinnerDoesNotFail() + { + bool judged = false; + AddStep("Setup judgements", () => + { + judged = false; + Mods.Value = Mods.Value.Concat(new[] { new TaikoModSuddenDeath() }).ToArray(); + ((ScoreAccessiblePlayer)Player).ScoreProcessor.NewJudgement += b => judged = true; + }); + AddUntilStep("swell judged", () => judged); + AddAssert("not failed", () => !Player.HasFailed); + } + + private class ScoreAccessiblePlayer : TestPlayer + { + public ScoreAccessiblePlayer() + : base(false, false) + { + } + + public new ScoreProcessor ScoreProcessor => base.ScoreProcessor; + } + } +} diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs index f06f72615b..f4e8a68819 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneFailAnimation.cs @@ -43,7 +43,7 @@ namespace osu.Game.Tests.Visual.Gameplay protected override void LoadComplete() { base.LoadComplete(); - ScoreProcessor.FailConditions += _ => true; + ScoreProcessor.FailConditions += (_, __) => true; } } } diff --git a/osu.Game/Rulesets/Mods/ModPerfect.cs b/osu.Game/Rulesets/Mods/ModPerfect.cs index e984fb8574..0994d1f7d3 100644 --- a/osu.Game/Rulesets/Mods/ModPerfect.cs +++ b/osu.Game/Rulesets/Mods/ModPerfect.cs @@ -3,6 +3,7 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mods @@ -14,6 +15,6 @@ namespace osu.Game.Rulesets.Mods public override IconUsage Icon => OsuIcon.ModPerfect; public override string Description => "SS or quit."; - protected override bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Accuracy.Value != 1; + protected override bool FailCondition(ScoreProcessor scoreProcessor, JudgementResult result) => scoreProcessor.Accuracy.Value != 1; } } diff --git a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs index 809661db8e..e332abd914 100644 --- a/osu.Game/Rulesets/Mods/ModSuddenDeath.cs +++ b/osu.Game/Rulesets/Mods/ModSuddenDeath.cs @@ -4,6 +4,7 @@ using System; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; @@ -27,6 +28,6 @@ namespace osu.Game.Rulesets.Mods public ScoreRank AdjustRank(ScoreRank rank, double accuracy) => rank; - protected virtual bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Combo.Value == 0; + protected virtual bool FailCondition(ScoreProcessor scoreProcessor, JudgementResult result) => scoreProcessor.Combo.Value == 0 && result.Judgement.AffectsCombo; } } diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index ce94ca9c7d..47ce28db4c 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Scoring /// /// Additional conditions on top of that cause a failing state. /// - public event Func FailConditions; + public event Func FailConditions; /// /// The current total score. @@ -151,12 +151,12 @@ namespace osu.Game.Rulesets.Scoring /// This can only ever notify subscribers once. /// /// - protected void UpdateFailed() + protected void UpdateFailed(JudgementResult result) { if (HasFailed) return; - if (!DefaultFailCondition && FailConditions?.Invoke(this) != true) + if (!DefaultFailCondition && FailConditions?.Invoke(this, result) != true) return; if (Failed?.Invoke() != false) @@ -287,7 +287,7 @@ namespace osu.Game.Rulesets.Scoring ApplyResult(result); updateScore(); - UpdateFailed(); + UpdateFailed(result); NotifyNewJudgement(result); } From 8fecd8dcdc570f4ffb71706ca475950066eb6a4f Mon Sep 17 00:00:00 2001 From: David Zhao Date: Fri, 21 Jun 2019 16:37:06 +0900 Subject: [PATCH 3/4] Fix sudden death not being applied on first run --- osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs index ca3c477594..d0db193738 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoSuddenDeath.cs @@ -22,7 +22,11 @@ namespace osu.Game.Rulesets.Taiko.Tests protected override bool AllowFail => true; - protected override Player CreatePlayer(Ruleset ruleset) => new ScoreAccessiblePlayer(); + protected override Player CreatePlayer(Ruleset ruleset) + { + Mods.Value = Mods.Value.Concat(new[] { new TaikoModSuddenDeath() }).ToArray(); + return new ScoreAccessiblePlayer(); + } protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TaikoBeatmap @@ -45,7 +49,6 @@ namespace osu.Game.Rulesets.Taiko.Tests AddStep("Setup judgements", () => { judged = false; - Mods.Value = Mods.Value.Concat(new[] { new TaikoModSuddenDeath() }).ToArray(); ((ScoreAccessiblePlayer)Player).ScoreProcessor.NewJudgement += b => judged = true; }); AddUntilStep("swell judged", () => judged); From c2b451a55f37008fd5145b571f89b0961f275594 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Jun 2019 17:51:25 +0900 Subject: [PATCH 4/4] Fix ModSelectOverlay tests failing due to asynchronous loading --- .../TestSceneModSelectOverlay.cs | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs index 5a903b9417..80408ab43b 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs @@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual.UserInterface public void TestOsuMods() { var ruleset = rulesets.AvailableRulesets.First(r => r.ID == 0); - AddStep("change ruleset", () => { Ruleset.Value = ruleset; }); + changeRuleset(ruleset); var instance = ruleset.CreateInstance(); @@ -108,7 +108,7 @@ namespace osu.Game.Tests.Visual.UserInterface public void TestManiaMods() { var ruleset = rulesets.AvailableRulesets.First(r => r.ID == 3); - AddStep("change ruleset", () => { Ruleset.Value = ruleset; }); + changeRuleset(ruleset); testRankedText(ruleset.CreateInstance().GetModsFor(ModType.Conversion).First(m => m is ManiaModRandom)); } @@ -119,7 +119,7 @@ namespace osu.Game.Tests.Visual.UserInterface var rulesetOsu = rulesets.AvailableRulesets.First(r => r.ID == 0); var rulesetMania = rulesets.AvailableRulesets.First(r => r.ID == 3); - AddStep("change ruleset to null", () => { Ruleset.Value = null; }); + changeRuleset(null); var instance = rulesetOsu.CreateInstance(); var easierMods = instance.GetModsFor(ModType.DifficultyReduction); @@ -127,15 +127,15 @@ namespace osu.Game.Tests.Visual.UserInterface AddStep("set mods externally", () => { modDisplay.Current.Value = new[] { noFailMod }; }); - AddStep("change ruleset to osu", () => { Ruleset.Value = rulesetOsu; }); + changeRuleset(rulesetOsu); AddAssert("ensure mods still selected", () => modDisplay.Current.Value.Single(m => m is OsuModNoFail) != null); - AddStep("change ruleset to mania", () => { Ruleset.Value = rulesetMania; }); + changeRuleset(rulesetMania); AddAssert("ensure mods not selected", () => !modDisplay.Current.Value.Any(m => m is OsuModNoFail)); - AddStep("change ruleset to osu", () => { Ruleset.Value = rulesetOsu; }); + changeRuleset(rulesetOsu); AddAssert("ensure mods not selected", () => !modDisplay.Current.Value.Any()); } @@ -216,14 +216,11 @@ namespace osu.Game.Tests.Visual.UserInterface private void testRankedText(Mod mod) { - waitForLoad(); - AddAssert("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0); + AddUntilStep("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0); selectNext(mod); - waitForLoad(); - AddAssert("check for unranked", () => modSelect.UnrankedLabel.Alpha != 0); + AddUntilStep("check for unranked", () => modSelect.UnrankedLabel.Alpha != 0); selectPrevious(mod); - waitForLoad(); - AddAssert("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0); + AddUntilStep("check for ranked", () => modSelect.UnrankedLabel.Alpha == 0); } private void selectNext(Mod mod) => AddStep($"left click {mod.Name}", () => modSelect.GetModButton(mod)?.SelectNext(1)); @@ -232,7 +229,6 @@ namespace osu.Game.Tests.Visual.UserInterface private void checkSelected(Mod mod) { - waitForLoad(); AddAssert($"check {mod.Name} is selected", () => { var button = modSelect.GetModButton(mod); @@ -240,14 +236,17 @@ namespace osu.Game.Tests.Visual.UserInterface }); } - private void waitForLoad() + private void changeRuleset(RulesetInfo ruleset) { - AddUntilStep("wait for icons to load", () => modSelect.AllLoaded); + AddStep($"change ruleset to {ruleset}", () => { Ruleset.Value = ruleset; }); + waitForLoad(); } + private void waitForLoad() => + AddUntilStep("wait for icons to load", () => modSelect.AllLoaded); + private void checkNotSelected(Mod mod) { - waitForLoad(); AddAssert($"check {mod.Name} is not selected", () => { var button = modSelect.GetModButton(mod);