From 66ebdbbe4cf0e2aa9614c086ce1efb600dde7035 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 May 2019 18:13:07 +0900 Subject: [PATCH 01/36] Fix control points with same timestamp potentially being parsed incorrectly --- osu.Game/Beatmaps/ControlPoints/ControlPoint.cs | 5 +++++ osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 14 +++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index 825b60ae5f..5e538126b3 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -12,6 +12,11 @@ namespace osu.Game.Beatmaps.ControlPoints /// public double Time; + /// + /// Whether this timing point was generated internally, as opposed to parsed from the underlying beatmap. + /// + internal bool AutoGenerated; + public int CompareTo(ControlPoint other) => Time.CompareTo(other.Time); /// diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index b489b5e6d9..46a6197546 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -374,14 +374,16 @@ namespace osu.Game.Beatmaps.Formats handleDifficultyControlPoint(new DifficultyControlPoint { Time = time, - SpeedMultiplier = speedMultiplier + SpeedMultiplier = speedMultiplier, + AutoGenerated = timingChange }); handleEffectControlPoint(new EffectControlPoint { Time = time, KiaiMode = kiaiMode, - OmitFirstBarLine = omitFirstBarSignature + OmitFirstBarLine = omitFirstBarSignature, + AutoGenerated = timingChange }); handleSampleControlPoint(new LegacySampleControlPoint @@ -389,7 +391,8 @@ namespace osu.Game.Beatmaps.Formats Time = time, SampleBank = stringSampleSet, SampleVolume = sampleVolume, - CustomSampleBank = customSampleBank + CustomSampleBank = customSampleBank, + AutoGenerated = timingChange }); } catch (FormatException) @@ -419,6 +422,11 @@ namespace osu.Game.Beatmaps.Formats if (newPoint.EquivalentTo(existing)) return; + // autogenerated points should not replace non-autogenerated. + // this allows for incorrectly ordered timing points to still be correctly handled. + if (newPoint.AutoGenerated && !existing.AutoGenerated) + return; + if (existing.Time == newPoint.Time) beatmap.ControlPointInfo.DifficultyPoints.Remove(existing); From 92f6f4d21a858ad6319c7849e6cab33d5a5a6282 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 13 May 2019 19:04:12 +0900 Subject: [PATCH 02/36] Apply same fix to other methods which were missed --- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 46a6197546..a5c3d8a4de 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -410,7 +410,14 @@ namespace osu.Game.Beatmaps.Formats var existing = beatmap.ControlPointInfo.TimingPointAt(newPoint.Time); if (existing.Time == newPoint.Time) + { + // autogenerated points should not replace non-autogenerated. + // this allows for incorrectly ordered timing points to still be correctly handled. + if (newPoint.AutoGenerated && !existing.AutoGenerated) + return; + beatmap.ControlPointInfo.TimingPoints.Remove(existing); + } beatmap.ControlPointInfo.TimingPoints.Add(newPoint); } @@ -422,13 +429,15 @@ namespace osu.Game.Beatmaps.Formats if (newPoint.EquivalentTo(existing)) return; - // autogenerated points should not replace non-autogenerated. - // this allows for incorrectly ordered timing points to still be correctly handled. - if (newPoint.AutoGenerated && !existing.AutoGenerated) - return; - if (existing.Time == newPoint.Time) + { + // autogenerated points should not replace non-autogenerated. + // this allows for incorrectly ordered timing points to still be correctly handled. + if (newPoint.AutoGenerated && !existing.AutoGenerated) + return; + beatmap.ControlPointInfo.DifficultyPoints.Remove(existing); + } beatmap.ControlPointInfo.DifficultyPoints.Add(newPoint); } @@ -441,7 +450,14 @@ namespace osu.Game.Beatmaps.Formats return; if (existing.Time == newPoint.Time) + { + // autogenerated points should not replace non-autogenerated. + // this allows for incorrectly ordered timing points to still be correctly handled. + if (newPoint.AutoGenerated && !existing.AutoGenerated) + return; + beatmap.ControlPointInfo.EffectPoints.Remove(existing); + } beatmap.ControlPointInfo.EffectPoints.Add(newPoint); } @@ -454,7 +470,14 @@ namespace osu.Game.Beatmaps.Formats return; if (existing.Time == newPoint.Time) + { + // autogenerated points should not replace non-autogenerated. + // this allows for incorrectly ordered timing points to still be correctly handled. + if (newPoint.AutoGenerated && !existing.AutoGenerated) + return; + beatmap.ControlPointInfo.SamplePoints.Remove(existing); + } beatmap.ControlPointInfo.SamplePoints.Add(newPoint); } From 7aa10956b582f741f006f4df959041c5b873f93a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 May 2019 09:46:42 +0900 Subject: [PATCH 03/36] Add unit test --- .../Formats/LegacyBeatmapDecoderTest.cs | 28 +++++++++++++++++++ .../Resources/overlapping-control-points.osu | 11 ++++++++ 2 files changed, 39 insertions(+) create mode 100644 osu.Game.Tests/Resources/overlapping-control-points.osu diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 3c1f48b7a4..7e7ddb12d2 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -194,6 +194,34 @@ namespace osu.Game.Tests.Beatmaps.Formats } } + [Test] + public void TestDecodeOverlappingTimingPoints() + { + var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false }; + + using (var resStream = TestResources.OpenResource("overlapping-control-points.osu")) + using (var stream = new StreamReader(resStream)) + { + var controlPoints = decoder.Decode(stream).ControlPointInfo; + + Assert.That(controlPoints.DifficultyPoints, Has.Count.EqualTo(2)); + Assert.That(controlPoints.DifficultyPoints[0].SpeedMultiplier, Is.EqualTo(1.5).Within(0.1)); + Assert.That(controlPoints.DifficultyPoints[1].SpeedMultiplier, Is.EqualTo(0.75).Within(0.1)); + + Assert.That(controlPoints.EffectPoints, Has.Count.EqualTo(2)); + Assert.That(controlPoints.EffectPoints[0].KiaiMode, Is.True); + Assert.That(controlPoints.EffectPoints[1].KiaiMode, Is.True); + + Assert.That(controlPoints.SamplePoints, Has.Count.EqualTo(2)); + Assert.That(controlPoints.SamplePoints[0].SampleBank, Is.EqualTo("drum")); + Assert.That(controlPoints.SamplePoints[1].SampleBank, Is.EqualTo("normal")); + + Assert.That(controlPoints.TimingPoints, Has.Count.EqualTo(2)); + Assert.That(controlPoints.TimingPoints[0].BeatLength, Is.EqualTo(500)); + Assert.That(controlPoints.TimingPoints[1].BeatLength, Is.EqualTo(250)); + } + } + [Test] public void TestDecodeBeatmapColours() { diff --git a/osu.Game.Tests/Resources/overlapping-control-points.osu b/osu.Game.Tests/Resources/overlapping-control-points.osu new file mode 100644 index 0000000000..d96db72bd7 --- /dev/null +++ b/osu.Game.Tests/Resources/overlapping-control-points.osu @@ -0,0 +1,11 @@ +osu file format v14 + +[TimingPoints] + +// Timing -> Inherited +0,500,4,2,0,100,1,0 +0,-66.6666666666667,4,3,0,100,0,1 + +// Inherited -> Timing +1000,-133.333333333333,4,1,0,100,0,1 +1000,250,4,2,0,100,1,0 From 19bc6b72cc7ef1a9a059322ae0e76ed19b601705 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 14 May 2019 10:13:42 +0900 Subject: [PATCH 04/36] More tests to showcase failures --- .../Formats/LegacyBeatmapDecoderTest.cs | 28 +++++++++++-------- .../Resources/overlapping-control-points.osu | 16 ++++++++--- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 7e7ddb12d2..42e421d1ad 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -204,21 +204,25 @@ namespace osu.Game.Tests.Beatmaps.Formats { var controlPoints = decoder.Decode(stream).ControlPointInfo; - Assert.That(controlPoints.DifficultyPoints, Has.Count.EqualTo(2)); - Assert.That(controlPoints.DifficultyPoints[0].SpeedMultiplier, Is.EqualTo(1.5).Within(0.1)); - Assert.That(controlPoints.DifficultyPoints[1].SpeedMultiplier, Is.EqualTo(0.75).Within(0.1)); + Assert.That(controlPoints.DifficultyPointAt(500).SpeedMultiplier, Is.EqualTo(1.5).Within(0.1)); + Assert.That(controlPoints.DifficultyPointAt(1500).SpeedMultiplier, Is.EqualTo(1.5).Within(0.1)); + Assert.That(controlPoints.DifficultyPointAt(2500).SpeedMultiplier, Is.EqualTo(0.75).Within(0.1)); + Assert.That(controlPoints.DifficultyPointAt(3500).SpeedMultiplier, Is.EqualTo(1.5).Within(0.1)); - Assert.That(controlPoints.EffectPoints, Has.Count.EqualTo(2)); - Assert.That(controlPoints.EffectPoints[0].KiaiMode, Is.True); - Assert.That(controlPoints.EffectPoints[1].KiaiMode, Is.True); + Assert.That(controlPoints.EffectPointAt(500).KiaiMode, Is.True); + Assert.That(controlPoints.EffectPointAt(1500).KiaiMode, Is.True); + Assert.That(controlPoints.EffectPointAt(2500).KiaiMode, Is.False); + Assert.That(controlPoints.EffectPointAt(3500).KiaiMode, Is.True); - Assert.That(controlPoints.SamplePoints, Has.Count.EqualTo(2)); - Assert.That(controlPoints.SamplePoints[0].SampleBank, Is.EqualTo("drum")); - Assert.That(controlPoints.SamplePoints[1].SampleBank, Is.EqualTo("normal")); + Assert.That(controlPoints.SamplePointAt(500).SampleBank, Is.EqualTo("drum")); + Assert.That(controlPoints.SamplePointAt(1500).SampleBank, Is.EqualTo("drum")); + Assert.That(controlPoints.SamplePointAt(2500).SampleBank, Is.EqualTo("normal")); + Assert.That(controlPoints.SamplePointAt(3500).SampleBank, Is.EqualTo("drum")); - Assert.That(controlPoints.TimingPoints, Has.Count.EqualTo(2)); - Assert.That(controlPoints.TimingPoints[0].BeatLength, Is.EqualTo(500)); - Assert.That(controlPoints.TimingPoints[1].BeatLength, Is.EqualTo(250)); + Assert.That(controlPoints.TimingPointAt(500).BeatLength, Is.EqualTo(500)); + Assert.That(controlPoints.TimingPointAt(1500).BeatLength, Is.EqualTo(500)); + Assert.That(controlPoints.TimingPointAt(2500).BeatLength, Is.EqualTo(250)); + Assert.That(controlPoints.TimingPointAt(3500).BeatLength, Is.EqualTo(500)); } } diff --git a/osu.Game.Tests/Resources/overlapping-control-points.osu b/osu.Game.Tests/Resources/overlapping-control-points.osu index d96db72bd7..31d38a3d01 100644 --- a/osu.Game.Tests/Resources/overlapping-control-points.osu +++ b/osu.Game.Tests/Resources/overlapping-control-points.osu @@ -2,10 +2,18 @@ osu file format v14 [TimingPoints] -// Timing -> Inherited +// Timing then inherited 0,500,4,2,0,100,1,0 0,-66.6666666666667,4,3,0,100,0,1 -// Inherited -> Timing -1000,-133.333333333333,4,1,0,100,0,1 -1000,250,4,2,0,100,1,0 +// Inherited then timing (equivalent to previous) +1000,-66.6666666666667,4,3,0,100,0,1 +1000,500,4,2,0,100,1,0 + +// Inherited then timing (different to previous) +2000,-133.333333333333,4,1,0,100,0,0 +2000,250,4,2,0,100,1,0 + +// Timing then inherited (different to previous) +3000,500,4,2,0,100,1,0 +3000,-66.6666666666667,4,3,0,100,0,1 From 958598d13ba38841a86ac46029d4e363aae88a9c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 May 2019 19:39:36 +0900 Subject: [PATCH 05/36] Fix crash on switching from main menu to gameplay too fast --- osu.Game/Screens/Menu/MainMenu.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 788cad3bad..3afe9b9371 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -155,9 +155,11 @@ namespace osu.Game.Screens.Menu protected override void LogoSuspending(OsuLogo logo) { - logo.FadeOut(300, Easing.InSine) - .ScaleTo(0.2f, 300, Easing.InSine) - .OnComplete(l => buttons.SetOsuLogo(null)); + var seq = logo.FadeOut(300, Easing.InSine) + .ScaleTo(0.2f, 300, Easing.InSine); + + seq.OnComplete(_ => buttons.SetOsuLogo(null)); + seq.OnAbort(_ => buttons.SetOsuLogo(null)); } private void beatmap_ValueChanged(ValueChangedEvent e) From 359e5b71a5cffbb806592d8ccd5cf80a20038676 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 16 May 2019 17:13:03 +0900 Subject: [PATCH 06/36] Fix race condition causing player to never restart --- osu.Game/Screens/Play/Player.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 60054f38fa..30214d1b9c 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -249,6 +249,10 @@ namespace osu.Game.Screens.Play if (!this.IsCurrentScreen()) return; sampleRestart?.Play(); + + // if a restart has been requested, cancel any pending completion (user has shown intent to restart). + onCompletionEvent = null; + ValidForResume = false; RestartRequested?.Invoke(); this.Exit(); From ccbf3ff81209ffcaa637390d4486faf794739411 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 17 May 2019 22:35:23 +0900 Subject: [PATCH 07/36] Update framework --- .../Visual/Gameplay/TestScenePlayerReferenceLeaking.cs | 8 ++++++-- osu.Game/osu.Game.csproj | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs index d941ad54c0..c75fb2567b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs @@ -24,7 +24,9 @@ namespace osu.Game.Tests.Visual.Gameplay GC.WaitForPendingFinalizers(); int count = 0; - workingWeakReferences.ForEachAlive(_ => count++); + foreach (var unused in workingWeakReferences) + count++; + return count == 1; }); @@ -34,7 +36,9 @@ namespace osu.Game.Tests.Visual.Gameplay GC.WaitForPendingFinalizers(); int count = 0; - playerWeakReferences.ForEachAlive(_ => count++); + foreach (var unused in playerWeakReferences) + count++; + return count == 1; }); } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 66d298f8c1..fcfaf71d6a 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + From a538c94feddce714e266403df7ab881194551ff8 Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Fri, 17 May 2019 21:40:46 +0300 Subject: [PATCH 08/36] Update NuGet packages --- .../osu.Game.Rulesets.Catch.Tests.csproj | 4 ++-- .../osu.Game.Rulesets.Mania.Tests.csproj | 4 ++-- .../osu.Game.Rulesets.Osu.Tests.csproj | 4 ++-- .../osu.Game.Rulesets.Taiko.Tests.csproj | 4 ++-- osu.Game.Tests/osu.Game.Tests.csproj | 4 ++-- osu.Game/osu.Game.csproj | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index 3f8b3bf086..265ecb7688 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -2,8 +2,8 @@ - - + + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index fd17285a38..dbade6ff8d 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -2,8 +2,8 @@ - - + + diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index 8c31db9a7d..a99a93c3e9 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -2,8 +2,8 @@ - - + + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index 72ce6c947b..216cc0222f 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -2,8 +2,8 @@ - - + + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 938e1ae0f8..11d70ee7be 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -3,8 +3,8 @@ - - + + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 66d298f8c1..7c005980c6 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -17,7 +17,7 @@ - + From 9106200c65edde6363e0542b2b6f79634936980d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 18 May 2019 12:08:22 +0900 Subject: [PATCH 09/36] Bump framework version --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index fcfaf71d6a..0cff6117d8 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index ccec475d98..d947d0dfb9 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From 5e499cf55d1f2ea5378b939f1a0c96c221535b54 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 18 May 2019 12:45:06 +0900 Subject: [PATCH 10/36] Update resources --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index bf76fbcc94..e18f4b8771 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -14,7 +14,7 @@ - + From d407981ae4f065cda08b1c95eff155ef71c22145 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 18 May 2019 12:58:13 +0900 Subject: [PATCH 11/36] Increase fastlane processing interval This seems to be getting longer as we go. May be related to having many versions released under one testflight build? --- fastlane/Fastfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 3f64bcdf19..48c16caf0f 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -35,7 +35,7 @@ platform :ios do changelog.gsub!('$BUILD_ID', options[:build]) pilot( - wait_processing_interval: 900, + wait_processing_interval: 1800, changelog: changelog, ipa: './osu.iOS/bin/iPhone/Release/osu.iOS.ipa' ) From 85a41cf6c3bf4cad37b8f06b9e84ffc36059051a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 May 2019 17:36:29 +0900 Subject: [PATCH 12/36] Allow chaining of loadComponentSingleFile --- osu.Game/OsuGame.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index d108bb45f3..8cdddd6736 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.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; @@ -588,7 +588,7 @@ namespace osu.Game private Task asyncLoadStream; - private void loadComponentSingleFile(T d, Action add, bool cache = false) + private T loadComponentSingleFile(T d, Action add, bool cache = false) where T : Drawable { if (cache) @@ -636,6 +636,8 @@ namespace osu.Game } }); }); + + return d; } public bool OnPressed(GlobalAction action) From bc962bf8f0bf6db4660217163e7a85a601709606 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 19 May 2019 11:28:24 +0900 Subject: [PATCH 13/36] Move TooltipText to OsuClickableContainer --- osu.Game/Graphics/Containers/OsuClickableContainer.cs | 5 ++++- osu.Game/Online/Chat/DrawableLinkCompiler.cs | 5 +---- osu.Game/Overlays/BeatmapSet/AuthorInfo.cs | 7 ------- .../Profile/Header/Components/ProfileHeaderButton.cs | 5 +---- .../Overlays/Profile/Sections/BeatmapMetadataContainer.cs | 5 +---- osu.Game/Users/Avatar.cs | 5 ++--- 6 files changed, 9 insertions(+), 23 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuClickableContainer.cs b/osu.Game/Graphics/Containers/OsuClickableContainer.cs index e4d30cebb7..6dbe340efb 100644 --- a/osu.Game/Graphics/Containers/OsuClickableContainer.cs +++ b/osu.Game/Graphics/Containers/OsuClickableContainer.cs @@ -4,11 +4,12 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Cursor; using osu.Game.Graphics.UserInterface; namespace osu.Game.Graphics.Containers { - public class OsuClickableContainer : ClickableContainer + public class OsuClickableContainer : ClickableContainer, IHasTooltip { private readonly HoverSampleSet sampleSet; @@ -23,6 +24,8 @@ namespace osu.Game.Graphics.Containers this.sampleSet = sampleSet; } + public virtual string TooltipText { get; set; } + [BackgroundDependencyLoader] private void load() { diff --git a/osu.Game/Online/Chat/DrawableLinkCompiler.cs b/osu.Game/Online/Chat/DrawableLinkCompiler.cs index d34ec8091c..d27a3fbffe 100644 --- a/osu.Game/Online/Chat/DrawableLinkCompiler.cs +++ b/osu.Game/Online/Chat/DrawableLinkCompiler.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.Framework.Graphics.Cursor; using System.Collections.Generic; using System.Linq; using osu.Framework.Allocation; @@ -16,7 +15,7 @@ namespace osu.Game.Online.Chat /// /// An invisible drawable that brings multiple pieces together to form a consumable clickable link. /// - public class DrawableLinkCompiler : OsuHoverContainer, IHasTooltip + public class DrawableLinkCompiler : OsuHoverContainer { /// /// Each word part of a chat link (split for word-wrap support). @@ -40,8 +39,6 @@ namespace osu.Game.Online.Chat protected override IEnumerable EffectTargets => Parts; - public string TooltipText { get; set; } - private class LinkHoverSounds : HoverClickSounds { private readonly List parts; diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs index abe954aa80..7331faa618 100644 --- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs +++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs @@ -9,8 +9,6 @@ using osu.Game.Graphics.Sprites; using osu.Game.Users; using osuTK; using osuTK.Graphics; -using osu.Game.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; @@ -129,10 +127,5 @@ namespace osu.Game.Overlays.BeatmapSet }; } } - - private class ClickableArea : OsuClickableContainer, IHasTooltip - { - public string TooltipText => @"View Profile"; - } } } diff --git a/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs b/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs index 1650f11523..ddcf011277 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ProfileHeaderButton.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -12,10 +11,8 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header.Components { - public abstract class ProfileHeaderButton : OsuHoverContainer, IHasTooltip + public abstract class ProfileHeaderButton : OsuHoverContainer { - public abstract string TooltipText { get; } - private readonly Box background; private readonly Container content; diff --git a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs index bb55816880..16326900f1 100644 --- a/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/BeatmapMetadataContainer.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Graphics; @@ -16,7 +15,7 @@ namespace osu.Game.Overlays.Profile.Sections /// /// Display artist/title/mapper information, commonly used as the left portion of a profile or score display row (see ). /// - public class BeatmapMetadataContainer : OsuHoverContainer, IHasTooltip + public class BeatmapMetadataContainer : OsuHoverContainer { private readonly BeatmapInfo beatmap; @@ -27,8 +26,6 @@ namespace osu.Game.Overlays.Profile.Sections TooltipText = $"{beatmap.Metadata.Artist} - {beatmap.Metadata.Title}"; } - public string TooltipText { get; } - [BackgroundDependencyLoader(true)] private void load(BeatmapSetOverlay beatmapSetOverlay) { diff --git a/osu.Game/Users/Avatar.cs b/osu.Game/Users/Avatar.cs index 3df5957ff9..8937f94768 100644 --- a/osu.Game/Users/Avatar.cs +++ b/osu.Game/Users/Avatar.cs @@ -6,7 +6,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Input.Events; @@ -72,9 +71,9 @@ namespace osu.Game.Users game?.ShowUser(user.Id); } - private class ClickableArea : OsuClickableContainer, IHasTooltip + private class ClickableArea : OsuClickableContainer { - public string TooltipText => Enabled.Value ? @"View Profile" : null; + public override string TooltipText => Enabled.Value ? @"View Profile" : null; protected override bool OnClick(ClickEvent e) { From 247dad7e86515e0872d62882de10fc996430b727 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 May 2019 15:58:40 +0900 Subject: [PATCH 14/36] Use OsuColour for profile overlay --- osu.Game/Graphics/OsuColour.cs | 10 ---------- .../Overlays/Profile/Header/BottomHeaderContainer.cs | 4 ++-- .../Overlays/Profile/Header/CentreHeaderContainer.cs | 2 +- .../Profile/Header/Components/ExpandDetailsButton.cs | 4 ++-- .../Overlays/Profile/Header/Components/RankGraph.cs | 4 ++-- .../Profile/Header/Components/SupporterIcon.cs | 2 +- .../Overlays/Profile/Header/DetailHeaderContainer.cs | 2 +- .../Overlays/Profile/Header/MedalHeaderContainer.cs | 2 +- osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs | 6 +++--- osu.Game/Overlays/Profile/ProfileHeader.cs | 4 ++-- 10 files changed, 15 insertions(+), 25 deletions(-) diff --git a/osu.Game/Graphics/OsuColour.cs b/osu.Game/Graphics/OsuColour.cs index a73a8bcbc1..53693a1e38 100644 --- a/osu.Game/Graphics/OsuColour.cs +++ b/osu.Game/Graphics/OsuColour.cs @@ -136,15 +136,5 @@ namespace osu.Game.Graphics public readonly Color4 ChatBlue = FromHex(@"17292e"); public readonly Color4 ContextMenuGray = FromHex(@"223034"); - - public readonly Color4 CommunityUserGreenLight = FromHex(@"deff87"); - public readonly Color4 CommunityUserGreen = FromHex(@"05ffa2"); - public readonly Color4 CommunityUserGreenDark = FromHex(@"a6cc00"); - public readonly Color4 CommunityUserGrayGreenLighter = FromHex(@"9ebab1"); - public readonly Color4 CommunityUserGrayGreenLight = FromHex(@"77998e"); - public readonly Color4 CommunityUserGrayGreen = FromHex(@"4e7466"); - public readonly Color4 CommunityUserGrayGreenDark = FromHex(@"33413c"); - public readonly Color4 CommunityUserGrayGreenDarker = FromHex(@"2c3532"); - public readonly Color4 CommunityUserGrayGreenDarkest = FromHex(@"1e2422"); } } diff --git a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs index 633085960b..ffbb9ad218 100644 --- a/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/BottomHeaderContainer.cs @@ -35,14 +35,14 @@ namespace osu.Game.Overlays.Profile.Header [BackgroundDependencyLoader] private void load(OsuColour colours) { - iconColour = colours.CommunityUserGrayGreenLighter; + iconColour = colours.GreySeafoamLighter; InternalChildren = new Drawable[] { new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.CommunityUserGrayGreenDarker, + Colour = colours.GreySeafoamDark, }, new FillFlowContainer { diff --git a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs index b441775393..68fd77dd84 100644 --- a/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/CentreHeaderContainer.cs @@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Profile.Header new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.CommunityUserGrayGreenDark + Colour = colours.GreySeafoam }, new FillFlowContainer { diff --git a/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs b/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs index 089228b2cd..46d24608ed 100644 --- a/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs +++ b/osu.Game/Overlays/Profile/Header/Components/ExpandDetailsButton.cs @@ -27,8 +27,8 @@ namespace osu.Game.Overlays.Profile.Header.Components [BackgroundDependencyLoader] private void load(OsuColour colours) { - IdleColour = colours.CommunityUserGrayGreen; - HoverColour = colours.CommunityUserGrayGreen.Darken(0.2f); + IdleColour = colours.GreySeafoamLight; + HoverColour = colours.GreySeafoamLight.Darken(0.2f); Child = icon = new SpriteIcon { diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index 1dabf167e3..85ea2a175a 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -154,7 +154,7 @@ namespace osu.Game.Overlays.Profile.Header.Components [BackgroundDependencyLoader] private void load(OsuColour colours) { - ballBg.Colour = colours.CommunityUserGrayGreenDarkest; + ballBg.Colour = colours.GreySeafoamDarker; movingBall.BorderColour = colours.Yellow; movingBar.Colour = colours.Yellow; } @@ -249,7 +249,7 @@ namespace osu.Game.Overlays.Profile.Header.Components [BackgroundDependencyLoader] private void load(OsuColour colours) { - background.Colour = colours.CommunityUserGrayGreenDarker; + background.Colour = colours.GreySeafoamDark; } public void Refresh() diff --git a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs index 97454d7327..c5e61f68f4 100644 --- a/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs +++ b/osu.Game/Overlays/Profile/Header/Components/SupporterIcon.cs @@ -80,7 +80,7 @@ namespace osu.Game.Overlays.Profile.Header.Components private void load(OsuColour colours) { background.Colour = colours.Pink; - iconContainer.Colour = colours.CommunityUserGrayGreenDark; + iconContainer.Colour = colours.GreySeafoam; } } } diff --git a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs index e41c90be45..f26cc360a2 100644 --- a/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/DetailHeaderContainer.cs @@ -65,7 +65,7 @@ namespace osu.Game.Overlays.Profile.Header new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.CommunityUserGrayGreenDarkest, + Colour = colours.GreySeafoamDarker, }, fillFlow = new FillFlowContainer { diff --git a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs index 25d04195b2..67229a80c0 100644 --- a/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/MedalHeaderContainer.cs @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.Profile.Header new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.CommunityUserGrayGreenDarkest, + Colour = colours.GreySeafoamDarker, }, new Container //artificial shadow { diff --git a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs index 2ac7f3cc96..6fe55e2368 100644 --- a/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs +++ b/osu.Game/Overlays/Profile/Header/TopHeaderContainer.cs @@ -41,7 +41,7 @@ namespace osu.Game.Overlays.Profile.Header new Box { RelativeSizeAxes = Axes.Both, - Colour = colours.CommunityUserGrayGreenDarker, + Colour = colours.GreySeafoamDark, }, new FillFlowContainer { @@ -107,7 +107,7 @@ namespace osu.Game.Overlays.Profile.Header RelativeSizeAxes = Axes.X, Height = 1.5f, Margin = new MarginPadding { Top = 10 }, - Colour = colours.CommunityUserGrayGreenLighter, + Colour = colours.GreySeafoamLighter, }, new Container { @@ -125,7 +125,7 @@ namespace osu.Game.Overlays.Profile.Header Margin = new MarginPadding { Left = 40 }, Origin = Anchor.CentreLeft, Anchor = Anchor.CentreLeft, - Colour = colours.CommunityUserGrayGreenLighter, + Colour = colours.GreySeafoamLighter, } } }, diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 2d8c47b11a..f2ac94b7ff 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -124,7 +124,7 @@ namespace osu.Game.Overlays.Profile [BackgroundDependencyLoader] private void load(OsuColour colours) { - infoTabControl.AccentColour = colours.CommunityUserGreen; + infoTabControl.AccentColour = colours.Seafoam; } public Bindable User = new Bindable(); @@ -145,7 +145,7 @@ namespace osu.Game.Overlays.Profile [BackgroundDependencyLoader] private void load(OsuColour colours) { - AccentColour = colours.CommunityUserGreen; + AccentColour = colours.Seafoam; } } } From 5a9c3ab9fa203d228a579c850c22e30ffd2af435 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 20 May 2019 18:02:13 +0900 Subject: [PATCH 15/36] Move UserProfileOverlay's header into an abstract implementation --- .../Online/TestSceneUserProfileHeader.cs | 2 +- osu.Game/Overlays/OverlayHeader.cs | 71 ++++++++ ...eaderTabControl.cs => HeaderTabControl.cs} | 12 +- osu.Game/Overlays/Profile/ProfileHeader.cs | 165 +++++++----------- 4 files changed, 142 insertions(+), 108 deletions(-) create mode 100644 osu.Game/Overlays/OverlayHeader.cs rename osu.Game/Overlays/Profile/Header/{ProfileHeaderTabControl.cs => HeaderTabControl.cs} (92%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs index 14c81558c1..730140faed 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs @@ -21,7 +21,7 @@ namespace osu.Game.Tests.Visual.Online typeof(ProfileHeader), typeof(RankGraph), typeof(LineGraph), - typeof(ProfileHeaderTabControl), + typeof(HeaderTabControl), typeof(CentreHeaderContainer), typeof(BottomHeaderContainer), typeof(DetailHeaderContainer), diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs new file mode 100644 index 0000000000..fe50d4a2be --- /dev/null +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -0,0 +1,71 @@ +// 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.UserInterface; +using osu.Game.Overlays.Profile.Header; + +namespace osu.Game.Overlays +{ + public abstract class OverlayHeader : Container + { + protected readonly HeaderTabControl TabControl; + + private const float cover_height = 150; + private const float cover_info_height = 75; + + protected OverlayHeader() + { + RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.X, + Height = cover_height, + Masking = true, + Child = CreateBackground() + }, + new Container + { + Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }, + Y = cover_height, + Height = cover_info_height, + RelativeSizeAxes = Axes.X, + Anchor = Anchor.TopLeft, + Origin = Anchor.BottomLeft, + Depth = -float.MaxValue, + Children = new Drawable[] + { + CreateTitle().With(t => t.X = -ScreenTitle.ICON_WIDTH), + TabControl = new HeaderTabControl + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + RelativeSizeAxes = Axes.X, + Height = cover_info_height - 30, + Margin = new MarginPadding { Left = -UserProfileOverlay.CONTENT_X_MARGIN }, + Padding = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN } + } + } + }, + new Container + { + Margin = new MarginPadding { Top = cover_height }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Child = CreateContent() + } + }; + } + + protected abstract Drawable CreateBackground(); + + protected abstract Drawable CreateContent(); + + protected abstract ScreenTitle CreateTitle(); + } +} diff --git a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs b/osu.Game/Overlays/Profile/Header/HeaderTabControl.cs similarity index 92% rename from osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs rename to osu.Game/Overlays/Profile/Header/HeaderTabControl.cs index 3b16b102d5..1169ef7013 100644 --- a/osu.Game/Overlays/Profile/Header/ProfileHeaderTabControl.cs +++ b/osu.Game/Overlays/Profile/Header/HeaderTabControl.cs @@ -13,7 +13,7 @@ using osuTK.Graphics; namespace osu.Game.Overlays.Profile.Header { - public class ProfileHeaderTabControl : TabControl + public class HeaderTabControl : TabControl { private readonly Box bar; @@ -32,7 +32,7 @@ namespace osu.Game.Overlays.Profile.Header foreach (TabItem tabItem in TabContainer) { - ((ProfileHeaderTabItem)tabItem).AccentColour = value; + ((HeaderTabItem)tabItem).AccentColour = value; } } } @@ -43,7 +43,7 @@ namespace osu.Game.Overlays.Profile.Header set => TabContainer.Padding = value; } - public ProfileHeaderTabControl() + public HeaderTabControl() { TabContainer.Masking = false; TabContainer.Spacing = new Vector2(15, 0); @@ -59,12 +59,12 @@ namespace osu.Game.Overlays.Profile.Header protected override Dropdown CreateDropdown() => null; - protected override TabItem CreateTabItem(string value) => new ProfileHeaderTabItem(value) + protected override TabItem CreateTabItem(string value) => new HeaderTabItem(value) { AccentColour = AccentColour }; - private class ProfileHeaderTabItem : TabItem + private class HeaderTabItem : TabItem { private readonly OsuSpriteText text; private readonly Drawable bar; @@ -86,7 +86,7 @@ namespace osu.Game.Overlays.Profile.Header } } - public ProfileHeaderTabItem(string value) + public HeaderTabItem(string value) : base(value) { AutoSizeAxes = Axes.X; diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index f2ac94b7ff..702bd6c2c4 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -15,124 +15,85 @@ using osu.Game.Users; namespace osu.Game.Overlays.Profile { - public class ProfileHeader : Container + public class ProfileHeader : OverlayHeader { - private readonly UserCoverBackground coverContainer; - private readonly ProfileHeaderTabControl infoTabControl; + private UserCoverBackground coverContainer; - private const float cover_height = 150; - private const float cover_info_height = 75; + public Bindable User = new Bindable(); + + private CentreHeaderContainer centreHeaderContainer; + private DetailHeaderContainer detailHeaderContainer; public ProfileHeader() { - CentreHeaderContainer centreHeaderContainer; - DetailHeaderContainer detailHeaderContainer; + User.ValueChanged += e => updateDisplay(e.NewValue); - RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; - - Children = new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.X, - Height = cover_height, - Masking = true, - Children = new Drawable[] - { - coverContainer = new UserCoverBackground - { - RelativeSizeAxes = Axes.Both, - }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(OsuColour.FromHex("222").Opacity(0.8f), OsuColour.FromHex("222").Opacity(0.2f)) - }, - } - }, - new Container - { - Margin = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN }, - Y = cover_height, - Height = cover_info_height, - RelativeSizeAxes = Axes.X, - Anchor = Anchor.TopLeft, - Origin = Anchor.BottomLeft, - Depth = -float.MaxValue, - Children = new Drawable[] - { - new ProfileHeaderTitle - { - X = -ScreenTitle.ICON_WIDTH, - }, - infoTabControl = new ProfileHeaderTabControl - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - Height = cover_info_height - 30, - Margin = new MarginPadding { Left = -UserProfileOverlay.CONTENT_X_MARGIN }, - Padding = new MarginPadding { Left = UserProfileOverlay.CONTENT_X_MARGIN } - } - } - }, - new FillFlowContainer - { - Margin = new MarginPadding { Top = cover_height }, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] - { - new TopHeaderContainer - { - RelativeSizeAxes = Axes.X, - User = { BindTarget = User }, - }, - centreHeaderContainer = new CentreHeaderContainer - { - RelativeSizeAxes = Axes.X, - User = { BindTarget = User }, - }, - detailHeaderContainer = new DetailHeaderContainer - { - RelativeSizeAxes = Axes.X, - User = { BindTarget = User }, - }, - new MedalHeaderContainer - { - RelativeSizeAxes = Axes.X, - User = { BindTarget = User }, - }, - new BottomHeaderContainer - { - RelativeSizeAxes = Axes.X, - User = { BindTarget = User }, - }, - } - } - }; - - infoTabControl.AddItem("Info"); - infoTabControl.AddItem("Modding"); + TabControl.AddItem("Info"); + TabControl.AddItem("Modding"); centreHeaderContainer.DetailsVisible.BindValueChanged(visible => detailHeaderContainer.Expanded = visible.NewValue, true); - User.ValueChanged += e => updateDisplay(e.NewValue); } [BackgroundDependencyLoader] private void load(OsuColour colours) { - infoTabControl.AccentColour = colours.Seafoam; + TabControl.AccentColour = colours.Seafoam; } - public Bindable User = new Bindable(); + protected override Drawable CreateBackground() => + new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + coverContainer = new UserCoverBackground + { + RelativeSizeAxes = Axes.Both, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(OsuColour.FromHex("222").Opacity(0.8f), OsuColour.FromHex("222").Opacity(0.2f)) + }, + } + }; - private void updateDisplay(User user) + protected override Drawable CreateContent() => new FillFlowContainer { - coverContainer.User = user; - } + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + new TopHeaderContainer + { + RelativeSizeAxes = Axes.X, + User = { BindTarget = User }, + }, + centreHeaderContainer = new CentreHeaderContainer + { + RelativeSizeAxes = Axes.X, + User = { BindTarget = User }, + }, + detailHeaderContainer = new DetailHeaderContainer + { + RelativeSizeAxes = Axes.X, + User = { BindTarget = User }, + }, + new MedalHeaderContainer + { + RelativeSizeAxes = Axes.X, + User = { BindTarget = User }, + }, + new BottomHeaderContainer + { + RelativeSizeAxes = Axes.X, + User = { BindTarget = User }, + }, + } + }; + + protected override ScreenTitle CreateTitle() => new ProfileHeaderTitle(); private class ProfileHeaderTitle : ScreenTitle { @@ -148,5 +109,7 @@ namespace osu.Game.Overlays.Profile AccentColour = colours.Seafoam; } } + + private void updateDisplay(User user) => coverContainer.User = user; } } From aba945934dceb67a30c89b6f07b2887bf497135f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 13:36:21 +0900 Subject: [PATCH 16/36] Move OverlayHeaderTabControl to correct namespace --- osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs | 3 ++- osu.Game/Overlays/OverlayHeader.cs | 5 ++--- .../HeaderTabControl.cs => OverlayHeaderTabControl.cs} | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) rename osu.Game/Overlays/{Profile/Header/HeaderTabControl.cs => OverlayHeaderTabControl.cs} (97%) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs index 730140faed..d9230090fc 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs @@ -7,6 +7,7 @@ using osu.Framework.Allocation; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Online.API.Requests; +using osu.Game.Overlays; using osu.Game.Overlays.Profile; using osu.Game.Overlays.Profile.Header; using osu.Game.Overlays.Profile.Header.Components; @@ -21,7 +22,7 @@ namespace osu.Game.Tests.Visual.Online typeof(ProfileHeader), typeof(RankGraph), typeof(LineGraph), - typeof(HeaderTabControl), + typeof(OverlayHeaderTabControl), typeof(CentreHeaderContainer), typeof(BottomHeaderContainer), typeof(DetailHeaderContainer), diff --git a/osu.Game/Overlays/OverlayHeader.cs b/osu.Game/Overlays/OverlayHeader.cs index fe50d4a2be..2e032db2ba 100644 --- a/osu.Game/Overlays/OverlayHeader.cs +++ b/osu.Game/Overlays/OverlayHeader.cs @@ -4,13 +4,12 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics.UserInterface; -using osu.Game.Overlays.Profile.Header; namespace osu.Game.Overlays { public abstract class OverlayHeader : Container { - protected readonly HeaderTabControl TabControl; + protected readonly OverlayHeaderTabControl TabControl; private const float cover_height = 150; private const float cover_info_height = 75; @@ -41,7 +40,7 @@ namespace osu.Game.Overlays Children = new Drawable[] { CreateTitle().With(t => t.X = -ScreenTitle.ICON_WIDTH), - TabControl = new HeaderTabControl + TabControl = new OverlayHeaderTabControl { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, diff --git a/osu.Game/Overlays/Profile/Header/HeaderTabControl.cs b/osu.Game/Overlays/OverlayHeaderTabControl.cs similarity index 97% rename from osu.Game/Overlays/Profile/Header/HeaderTabControl.cs rename to osu.Game/Overlays/OverlayHeaderTabControl.cs index 1169ef7013..0587a9bb2b 100644 --- a/osu.Game/Overlays/Profile/Header/HeaderTabControl.cs +++ b/osu.Game/Overlays/OverlayHeaderTabControl.cs @@ -11,9 +11,9 @@ using osu.Game.Graphics.UserInterface; using osuTK; using osuTK.Graphics; -namespace osu.Game.Overlays.Profile.Header +namespace osu.Game.Overlays { - public class HeaderTabControl : TabControl + public class OverlayHeaderTabControl : TabControl { private readonly Box bar; @@ -43,7 +43,7 @@ namespace osu.Game.Overlays.Profile.Header set => TabContainer.Padding = value; } - public HeaderTabControl() + public OverlayHeaderTabControl() { TabContainer.Masking = false; TabContainer.Spacing = new Vector2(15, 0); From db817b3b2510385d11a46828892fa4b6f0cb6635 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 12:45:20 +0900 Subject: [PATCH 17/36] Set HeaderTabControl's default AccentColour to non-transparent Avoids items disappearing if no accent colour is set. --- osu.Game/Overlays/OverlayHeaderTabControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/OverlayHeaderTabControl.cs b/osu.Game/Overlays/OverlayHeaderTabControl.cs index 0587a9bb2b..21b42cfbf4 100644 --- a/osu.Game/Overlays/OverlayHeaderTabControl.cs +++ b/osu.Game/Overlays/OverlayHeaderTabControl.cs @@ -17,7 +17,7 @@ namespace osu.Game.Overlays { private readonly Box bar; - private Color4 accentColour; + private Color4 accentColour = Color4.White; public Color4 AccentColour { From e3ae858c876cc5f7db899d8c78e609be6184e718 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 21 May 2019 14:01:41 +0900 Subject: [PATCH 18/36] Adjust testcase to avoid potential rounding issues --- .../Beatmaps/Formats/LegacyBeatmapDecoderTest.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index 42e421d1ad..d6259a1fdf 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -219,10 +219,10 @@ namespace osu.Game.Tests.Beatmaps.Formats Assert.That(controlPoints.SamplePointAt(2500).SampleBank, Is.EqualTo("normal")); Assert.That(controlPoints.SamplePointAt(3500).SampleBank, Is.EqualTo("drum")); - Assert.That(controlPoints.TimingPointAt(500).BeatLength, Is.EqualTo(500)); - Assert.That(controlPoints.TimingPointAt(1500).BeatLength, Is.EqualTo(500)); - Assert.That(controlPoints.TimingPointAt(2500).BeatLength, Is.EqualTo(250)); - Assert.That(controlPoints.TimingPointAt(3500).BeatLength, Is.EqualTo(500)); + Assert.That(controlPoints.TimingPointAt(500).BeatLength, Is.EqualTo(500).Within(0.1)); + Assert.That(controlPoints.TimingPointAt(1500).BeatLength, Is.EqualTo(500).Within(0.1)); + Assert.That(controlPoints.TimingPointAt(2500).BeatLength, Is.EqualTo(250).Within(0.1)); + Assert.That(controlPoints.TimingPointAt(3500).BeatLength, Is.EqualTo(500).Within(0.1)); } } From 89e62c3d3025d743f187c4897e29709903897312 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 14:07:40 +0900 Subject: [PATCH 19/36] Only play OsuHoverContainer hover effect if action is present --- osu.Game/Graphics/Containers/OsuHoverContainer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Graphics/Containers/OsuHoverContainer.cs b/osu.Game/Graphics/Containers/OsuHoverContainer.cs index d5ae7cba57..b1fe1e81f1 100644 --- a/osu.Game/Graphics/Containers/OsuHoverContainer.cs +++ b/osu.Game/Graphics/Containers/OsuHoverContainer.cs @@ -22,7 +22,8 @@ namespace osu.Game.Graphics.Containers protected override bool OnHover(HoverEvent e) { - EffectTargets.ForEach(d => d.FadeColour(HoverColour, FADE_DURATION, Easing.OutQuint)); + if (Action != null) + EffectTargets.ForEach(d => d.FadeColour(HoverColour, FADE_DURATION, Easing.OutQuint)); return base.OnHover(e); } From 587e4bb5d54585428d4ba3fadbedf2790f4e85bf Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 11:13:36 +0900 Subject: [PATCH 20/36] Remove unnecessary getters from ScreenTitle --- osu.Game/Graphics/UserInterface/ScreenTitle.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ScreenTitle.cs b/osu.Game/Graphics/UserInterface/ScreenTitle.cs index b9d9b5427d..18b79d9ec2 100644 --- a/osu.Game/Graphics/UserInterface/ScreenTitle.cs +++ b/osu.Game/Graphics/UserInterface/ScreenTitle.cs @@ -19,19 +19,16 @@ namespace osu.Game.Graphics.UserInterface protected IconUsage Icon { - get => iconSprite.Icon; set => iconSprite.Icon = value; } protected string Title { - get => titleText.Text; set => titleText.Text = value; } protected string Section { - get => pageText.Text; set => pageText.Text = value; } From e0da919fe920ad2688b2b95471dc76f30b8f38fa Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 11:50:03 +0900 Subject: [PATCH 21/36] Allow custom icon specification in ScreenTitle Not all icons are available in fonts so IconUsage alone is not enough to cover all scenarios. --- .../Graphics/UserInterface/ScreenTitle.cs | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/ScreenTitle.cs b/osu.Game/Graphics/UserInterface/ScreenTitle.cs index 18b79d9ec2..fe1936d4e8 100644 --- a/osu.Game/Graphics/UserInterface/ScreenTitle.cs +++ b/osu.Game/Graphics/UserInterface/ScreenTitle.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 osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -12,14 +13,24 @@ namespace osu.Game.Graphics.UserInterface { public abstract class ScreenTitle : CompositeDrawable, IHasAccentColour { - private readonly SpriteIcon iconSprite; + public const float ICON_WIDTH = ICON_SIZE + icon_spacing; + + protected const float ICON_SIZE = 25; + + private SpriteIcon iconSprite; private readonly OsuSpriteText titleText, pageText; - public const float ICON_WIDTH = icon_size + icon_spacing; - private const float icon_size = 25, icon_spacing = 10; + + private const float icon_spacing = 10; protected IconUsage Icon { - set => iconSprite.Icon = value; + set + { + if (iconSprite == null) + throw new InvalidOperationException($"Cannot use {nameof(Icon)} with a custom {nameof(CreateIcon)} function."); + + iconSprite.Icon = value; + } } protected string Title @@ -38,6 +49,11 @@ namespace osu.Game.Graphics.UserInterface set => pageText.Colour = value; } + protected virtual Drawable CreateIcon() => iconSprite = new SpriteIcon + { + Size = new Vector2(ICON_SIZE), + }; + protected ScreenTitle() { AutoSizeAxes = Axes.Both; @@ -48,12 +64,9 @@ namespace osu.Game.Graphics.UserInterface { AutoSizeAxes = Axes.Both, Spacing = new Vector2(icon_spacing, 0), - Children = new Drawable[] + Children = new[] { - iconSprite = new SpriteIcon - { - Size = new Vector2(icon_size), - }, + CreateIcon(), new FillFlowContainer { AutoSizeAxes = Axes.Both, From 4ac2acbfc0a969d9693c3bf62d3af7fd5f542956 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 14:13:52 +0900 Subject: [PATCH 22/36] Fix usages of SpriteText (instead of OsuSpriteText) --- osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs | 4 ++-- .../Visual/Background/TestSceneBackgroundScreenBeatmap.cs | 4 ++-- osu.Game.Tests/Visual/Gameplay/TestSceneScoreCounter.cs | 3 ++- osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs | 4 ++-- osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs | 3 ++- osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs | 4 ++-- .../Visual/UserInterface/TestSceneNotificationOverlay.cs | 3 ++- osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs | 2 +- 8 files changed, 15 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs index 0d143198dd..b2613a59d5 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneNotes.cs @@ -11,10 +11,10 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables; @@ -138,7 +138,7 @@ namespace osu.Game.Rulesets.Mania.Tests content = new Container { RelativeSizeAxes = Axes.Both } } }, - new SpriteText + new OsuSpriteText { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs index 10e3dc10c8..c9bdcf928f 100644 --- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs +++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs @@ -9,7 +9,6 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; using osu.Framework.Input.States; using osu.Framework.Platform; @@ -19,6 +18,7 @@ using osu.Game.Configuration; using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; using osu.Game.Rulesets; using osu.Game.Rulesets.Osu.Mods; using osu.Game.Scoring; @@ -240,7 +240,7 @@ namespace osu.Game.Tests.Visual.Background { player.StoryboardEnabled.Value = false; player.ReplacesBackground.Value = false; - player.CurrentStoryboardContainer.Add(new SpriteText + player.CurrentStoryboardContainer.Add(new OsuSpriteText { Size = new Vector2(250, 50), Alpha = 1, diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneScoreCounter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneScoreCounter.cs index 0c9e3fcd73..080a287b48 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneScoreCounter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneScoreCounter.cs @@ -5,6 +5,7 @@ using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.MathUtils; +using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Play.HUD; using osuTK; @@ -53,7 +54,7 @@ namespace osu.Game.Tests.Visual.Gameplay }; Add(stars); - SpriteText starsLabel = new SpriteText + SpriteText starsLabel = new OsuSpriteText { Origin = Anchor.BottomLeft, Anchor = Anchor.BottomLeft, diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs index 7d6edd0d12..c7a0df6e9f 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkinReloadable.cs @@ -7,9 +7,9 @@ using osu.Framework.Audio.Sample; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; -using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; using osu.Game.Skinning; using osuTK.Graphics; @@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual.Gameplay Colour = Color4.Black, RelativeSizeAxes = Axes.Both, }, - new SpriteText + new OsuSpriteText { Font = OsuFont.Default.With(size: 40), Anchor = Anchor.Centre, diff --git a/osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs b/osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs index d93daba4d4..364c986723 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChannelTabControl.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.MathUtils; +using osu.Game.Graphics.Sprites; using osu.Game.Online.Chat; using osu.Game.Overlays.Chat.Tabs; using osu.Game.Users; @@ -61,7 +62,7 @@ namespace osu.Game.Tests.Visual.Online Anchor = Anchor.TopLeft, Children = new Drawable[] { - currentText = new SpriteText + currentText = new OsuSpriteText { Text = "Currently selected channel:" } diff --git a/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs b/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs index 53ce25ebb3..a68fd0ef40 100644 --- a/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs +++ b/osu.Game.Tests/Visual/TestSceneOsuScreenStack.cs @@ -4,9 +4,9 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Sprites; using osu.Framework.Screens; using osu.Framework.Testing; +using osu.Game.Graphics.Sprites; using osu.Game.Screens; using osu.Game.Screens.Play; using osuTK.Graphics; @@ -54,7 +54,7 @@ namespace osu.Game.Tests.Visual [BackgroundDependencyLoader] private void load() { - AddInternal(new SpriteText + AddInternal(new OsuSpriteText { Text = screenText, Colour = Color4.White, diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs index 0cb7c2484d..71033fcd2f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneNotificationOverlay.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; using osu.Framework.MathUtils; +using osu.Game.Graphics.Sprites; using osu.Game.Overlays; using osu.Game.Overlays.Notifications; @@ -40,7 +41,7 @@ namespace osu.Game.Tests.Visual.UserInterface Origin = Anchor.TopRight }); - SpriteText displayedCount = new SpriteText(); + SpriteText displayedCount = new OsuSpriteText(); Content.Add(displayedCount); diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index e70bf4c572..89da0fc254 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -83,7 +83,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, }, - date = new SpriteText + date = new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, From 7e38aabe7518e47ef3dd010c4f77241a424bfc5a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 21 May 2019 14:27:41 +0900 Subject: [PATCH 23/36] Remove equivalence check from controlpoint parsing --- .../Formats/LegacyBeatmapDecoderTest.cs | 57 ++++++++++++++++--- .../Beatmaps/Formats/LegacyBeatmapDecoder.cs | 9 --- 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs index d6259a1fdf..5fd5fe342d 100644 --- a/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs +++ b/osu.Game.Tests/Beatmaps/Formats/LegacyBeatmapDecoderTest.cs @@ -170,27 +170,66 @@ namespace osu.Game.Tests.Beatmaps.Formats var controlPoints = beatmap.ControlPointInfo; Assert.AreEqual(4, controlPoints.TimingPoints.Count); - var timingPoint = controlPoints.TimingPoints[0]; + Assert.AreEqual(42, controlPoints.DifficultyPoints.Count); + Assert.AreEqual(42, controlPoints.SamplePoints.Count); + Assert.AreEqual(42, controlPoints.EffectPoints.Count); + + var timingPoint = controlPoints.TimingPointAt(0); + Assert.AreEqual(956, timingPoint.Time); + Assert.AreEqual(329.67032967033, timingPoint.BeatLength); + Assert.AreEqual(TimeSignatures.SimpleQuadruple, timingPoint.TimeSignature); + + timingPoint = controlPoints.TimingPointAt(48428); Assert.AreEqual(956, timingPoint.Time); Assert.AreEqual(329.67032967033d, timingPoint.BeatLength); Assert.AreEqual(TimeSignatures.SimpleQuadruple, timingPoint.TimeSignature); - Assert.AreEqual(5, controlPoints.DifficultyPoints.Count); - var difficultyPoint = controlPoints.DifficultyPoints[0]; - Assert.AreEqual(116999, difficultyPoint.Time); - Assert.AreEqual(0.75000000000000189d, difficultyPoint.SpeedMultiplier); + timingPoint = controlPoints.TimingPointAt(119637); + Assert.AreEqual(119637, timingPoint.Time); + Assert.AreEqual(659.340659340659, timingPoint.BeatLength); + Assert.AreEqual(TimeSignatures.SimpleQuadruple, timingPoint.TimeSignature); - Assert.AreEqual(34, controlPoints.SamplePoints.Count); - var soundPoint = controlPoints.SamplePoints[0]; + var difficultyPoint = controlPoints.DifficultyPointAt(0); + Assert.AreEqual(0, difficultyPoint.Time); + Assert.AreEqual(1.0, difficultyPoint.SpeedMultiplier); + + difficultyPoint = controlPoints.DifficultyPointAt(48428); + Assert.AreEqual(48428, difficultyPoint.Time); + Assert.AreEqual(1.0, difficultyPoint.SpeedMultiplier); + + difficultyPoint = controlPoints.DifficultyPointAt(116999); + Assert.AreEqual(116999, difficultyPoint.Time); + Assert.AreEqual(0.75, difficultyPoint.SpeedMultiplier, 0.1); + + var soundPoint = controlPoints.SamplePointAt(0); Assert.AreEqual(956, soundPoint.Time); Assert.AreEqual("soft", soundPoint.SampleBank); Assert.AreEqual(60, soundPoint.SampleVolume); - Assert.AreEqual(8, controlPoints.EffectPoints.Count); - var effectPoint = controlPoints.EffectPoints[0]; + soundPoint = controlPoints.SamplePointAt(53373); + Assert.AreEqual(53373, soundPoint.Time); + Assert.AreEqual("soft", soundPoint.SampleBank); + Assert.AreEqual(60, soundPoint.SampleVolume); + + soundPoint = controlPoints.SamplePointAt(119637); + Assert.AreEqual(119637, soundPoint.Time); + Assert.AreEqual("soft", soundPoint.SampleBank); + Assert.AreEqual(80, soundPoint.SampleVolume); + + var effectPoint = controlPoints.EffectPointAt(0); + Assert.AreEqual(0, effectPoint.Time); + Assert.IsFalse(effectPoint.KiaiMode); + Assert.IsFalse(effectPoint.OmitFirstBarLine); + + effectPoint = controlPoints.EffectPointAt(53703); Assert.AreEqual(53703, effectPoint.Time); Assert.IsTrue(effectPoint.KiaiMode); Assert.IsFalse(effectPoint.OmitFirstBarLine); + + effectPoint = controlPoints.EffectPointAt(119637); + Assert.AreEqual(119637, effectPoint.Time); + Assert.IsFalse(effectPoint.KiaiMode); + Assert.IsFalse(effectPoint.OmitFirstBarLine); } } diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index a5c3d8a4de..3cd425ea44 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -426,9 +426,6 @@ namespace osu.Game.Beatmaps.Formats { var existing = beatmap.ControlPointInfo.DifficultyPointAt(newPoint.Time); - if (newPoint.EquivalentTo(existing)) - return; - if (existing.Time == newPoint.Time) { // autogenerated points should not replace non-autogenerated. @@ -446,9 +443,6 @@ namespace osu.Game.Beatmaps.Formats { var existing = beatmap.ControlPointInfo.EffectPointAt(newPoint.Time); - if (newPoint.EquivalentTo(existing)) - return; - if (existing.Time == newPoint.Time) { // autogenerated points should not replace non-autogenerated. @@ -466,9 +460,6 @@ namespace osu.Game.Beatmaps.Formats { var existing = beatmap.ControlPointInfo.SamplePointAt(newPoint.Time); - if (newPoint.EquivalentTo(existing)) - return; - if (existing.Time == newPoint.Time) { // autogenerated points should not replace non-autogenerated. From 7a56fe84f20433063d811290c5afedb381cd7d5f Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 21 May 2019 14:27:57 +0900 Subject: [PATCH 24/36] Remove ControlPoint.EquivalentTo --- osu.Game/Beatmaps/ControlPoints/ControlPoint.cs | 10 +--------- .../Beatmaps/ControlPoints/DifficultyControlPoint.cs | 10 +++++----- .../Beatmaps/ControlPoints/EffectControlPoint.cs | 12 ++++++------ .../Beatmaps/ControlPoints/SampleControlPoint.cs | 11 +++++------ .../Beatmaps/ControlPoints/TimingControlPoint.cs | 11 +++++------ osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 9 ++++----- 6 files changed, 26 insertions(+), 37 deletions(-) diff --git a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs index 5e538126b3..abe7e5e803 100644 --- a/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/ControlPoint.cs @@ -19,15 +19,7 @@ namespace osu.Game.Beatmaps.ControlPoints public int CompareTo(ControlPoint other) => Time.CompareTo(other.Time); - /// - /// Whether this provides the same parametric changes as another . - /// Basically an equality check without considering the . - /// - /// The to compare to. - /// Whether this is equivalent to . - public virtual bool EquivalentTo(ControlPoint other) => true; - public bool Equals(ControlPoint other) - => EquivalentTo(other) && Time.Equals(other?.Time); + => Time.Equals(other?.Time); } } diff --git a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs index 013271d597..a3e3121575 100644 --- a/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/DifficultyControlPoint.cs @@ -1,11 +1,12 @@ // 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 osuTK; namespace osu.Game.Beatmaps.ControlPoints { - public class DifficultyControlPoint : ControlPoint + public class DifficultyControlPoint : ControlPoint, IEquatable { /// /// The speed multiplier at this control point. @@ -18,9 +19,8 @@ namespace osu.Game.Beatmaps.ControlPoints private double speedMultiplier = 1; - public override bool EquivalentTo(ControlPoint other) - => base.EquivalentTo(other) - && other is DifficultyControlPoint difficulty - && SpeedMultiplier.Equals(difficulty.SpeedMultiplier); + public bool Equals(DifficultyControlPoint other) + => base.Equals(other) + && SpeedMultiplier.Equals(other?.SpeedMultiplier); } } diff --git a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs index 3978b7b4b0..354d86dc13 100644 --- a/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/EffectControlPoint.cs @@ -1,9 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; + namespace osu.Game.Beatmaps.ControlPoints { - public class EffectControlPoint : ControlPoint + public class EffectControlPoint : ControlPoint, IEquatable { /// /// Whether this control point enables Kiai mode. @@ -15,10 +17,8 @@ namespace osu.Game.Beatmaps.ControlPoints /// public bool OmitFirstBarLine; - public override bool EquivalentTo(ControlPoint other) - => base.EquivalentTo(other) - && other is EffectControlPoint effect - && KiaiMode.Equals(effect.KiaiMode) - && OmitFirstBarLine.Equals(effect.OmitFirstBarLine); + public bool Equals(EffectControlPoint other) + => base.Equals(other) + && KiaiMode == other?.KiaiMode && OmitFirstBarLine == other.OmitFirstBarLine; } } diff --git a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs index 241ce90740..4c45bef862 100644 --- a/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/SampleControlPoint.cs @@ -1,11 +1,12 @@ // 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.Game.Audio; namespace osu.Game.Beatmaps.ControlPoints { - public class SampleControlPoint : ControlPoint + public class SampleControlPoint : ControlPoint, IEquatable { public const string DEFAULT_BANK = "normal"; @@ -44,10 +45,8 @@ namespace osu.Game.Beatmaps.ControlPoints return newSampleInfo; } - public override bool EquivalentTo(ControlPoint other) - => base.EquivalentTo(other) - && other is SampleControlPoint sample - && SampleBank.Equals(sample.SampleBank) - && SampleVolume.Equals(sample.SampleVolume); + public bool Equals(SampleControlPoint other) + => base.Equals(other) + && string.Equals(SampleBank, other?.SampleBank) && SampleVolume == other?.SampleVolume; } } diff --git a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs index 9ec27bdfdf..e5815a3f3b 100644 --- a/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs +++ b/osu.Game/Beatmaps/ControlPoints/TimingControlPoint.cs @@ -1,12 +1,13 @@ // 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 osuTK; using osu.Game.Beatmaps.Timing; namespace osu.Game.Beatmaps.ControlPoints { - public class TimingControlPoint : ControlPoint + public class TimingControlPoint : ControlPoint, IEquatable { /// /// The time signature at this control point. @@ -24,10 +25,8 @@ namespace osu.Game.Beatmaps.ControlPoints private double beatLength = 1000; - public override bool EquivalentTo(ControlPoint other) - => base.EquivalentTo(other) - && other is TimingControlPoint timing - && TimeSignature.Equals(timing.TimeSignature) - && BeatLength.Equals(timing.BeatLength); + public bool Equals(TimingControlPoint other) + => base.Equals(other) + && TimeSignature == other?.TimeSignature && beatLength.Equals(other.beatLength); } } diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index ad5089958c..854d3b41d6 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -189,7 +189,7 @@ namespace osu.Game.Beatmaps.Formats Foreground = 3 } - internal class LegacySampleControlPoint : SampleControlPoint + internal class LegacySampleControlPoint : SampleControlPoint, IEquatable { public int CustomSampleBank; @@ -203,10 +203,9 @@ namespace osu.Game.Beatmaps.Formats return baseInfo; } - public override bool EquivalentTo(ControlPoint other) - => base.EquivalentTo(other) - && other is LegacySampleControlPoint legacy - && CustomSampleBank == legacy.CustomSampleBank; + public bool Equals(LegacySampleControlPoint other) + => base.Equals(other) + && CustomSampleBank == other?.CustomSampleBank; } } } From aed4634fe00fd91343bcff6701f84cfc85976814 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 21 May 2019 14:48:14 +0900 Subject: [PATCH 25/36] Consolidate loader animation tests --- .../Visual/Menus/TestSceneLoaderAnimation.cs | 32 ++----------------- 1 file changed, 3 insertions(+), 29 deletions(-) diff --git a/osu.Game.Tests/Visual/Menus/TestSceneLoaderAnimation.cs b/osu.Game.Tests/Visual/Menus/TestSceneLoaderAnimation.cs index 813d4df708..000832b784 100644 --- a/osu.Game.Tests/Visual/Menus/TestSceneLoaderAnimation.cs +++ b/osu.Game.Tests/Visual/Menus/TestSceneLoaderAnimation.cs @@ -53,38 +53,12 @@ namespace osu.Game.Tests.Visual.Menus } [Test] - public void TestShortLoad() + public void TestDelayedLoad() { - bool logoVisible = false; - AddStep("begin loading", () => LoadScreen(loader = new TestLoader())); - AddWaitStep("wait", 3); - AddStep("finish loading", () => - { - logoVisible = loader.Logo?.Alpha > 0; - loader.AllowLoad.Set(); - }); - + AddUntilStep("wait for logo visible", () => loader.Logo?.Alpha > 0); + AddStep("finish loading", () => loader.AllowLoad.Set()); AddAssert("loaded", () => loader.Logo != null && loader.ScreenLoaded); - AddAssert("logo was visible", () => logoVisible); - AddUntilStep("logo gone", () => loader.Logo?.Alpha == 0); - } - - [Test] - public void TestLongLoad() - { - bool logoVisible = false; - - AddStep("begin loading", () => LoadScreen(loader = new TestLoader())); - AddWaitStep("wait", 10); - AddStep("finish loading", () => - { - logoVisible = loader.Logo?.Alpha > 0; - loader.AllowLoad.Set(); - }); - - AddAssert("loaded", () => loader.Logo != null && loader.ScreenLoaded); - AddAssert("logo was visible", () => logoVisible); AddUntilStep("logo gone", () => loader.Logo?.Alpha == 0); } From 5ed1540a12bac009c075e6cbd77744824d203acd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 15:02:31 +0900 Subject: [PATCH 26/36] Handle unhover state change better --- .../Graphics/Containers/OsuHoverContainer.cs | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/Containers/OsuHoverContainer.cs b/osu.Game/Graphics/Containers/OsuHoverContainer.cs index b1fe1e81f1..c4f85926ee 100644 --- a/osu.Game/Graphics/Containers/OsuHoverContainer.cs +++ b/osu.Game/Graphics/Containers/OsuHoverContainer.cs @@ -20,19 +20,41 @@ namespace osu.Game.Graphics.Containers protected virtual IEnumerable EffectTargets => new[] { Content }; + public OsuHoverContainer() + { + Enabled.ValueChanged += e => + { + if (!e.NewValue) unhover(); + }; + } + + private bool isHovered; + protected override bool OnHover(HoverEvent e) { - if (Action != null) - EffectTargets.ForEach(d => d.FadeColour(HoverColour, FADE_DURATION, Easing.OutQuint)); + if (!Enabled.Value) + return false; + + EffectTargets.ForEach(d => d.FadeColour(HoverColour, FADE_DURATION, Easing.OutQuint)); + isHovered = true; + return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { - EffectTargets.ForEach(d => d.FadeColour(IdleColour, FADE_DURATION, Easing.OutQuint)); + unhover(); base.OnHoverLost(e); } + private void unhover() + { + if (!isHovered) return; + + isHovered = false; + EffectTargets.ForEach(d => d.FadeColour(IdleColour, FADE_DURATION, Easing.OutQuint)); + } + [BackgroundDependencyLoader] private void load(OsuColour colours) { From 236b8cec279f4e415330e5d736b3e064984e05b1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 21 May 2019 15:31:36 +0900 Subject: [PATCH 27/36] Update framework --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e18f4b8771..98b158134d 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index d947d0dfb9..b7549eeaef 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From e76d785c10542947a6ccf8773035b4ea6ee64319 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 21 May 2019 16:05:59 +0900 Subject: [PATCH 28/36] Move method above nested class --- osu.Game/Overlays/Profile/ProfileHeader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 702bd6c2c4..76613c156d 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -95,6 +95,8 @@ namespace osu.Game.Overlays.Profile protected override ScreenTitle CreateTitle() => new ProfileHeaderTitle(); + private void updateDisplay(User user) => coverContainer.User = user; + private class ProfileHeaderTitle : ScreenTitle { public ProfileHeaderTitle() @@ -109,7 +111,5 @@ namespace osu.Game.Overlays.Profile AccentColour = colours.Seafoam; } } - - private void updateDisplay(User user) => coverContainer.User = user; } } From 1d5b7cdec0240dab30d65d24b10b490d54a76674 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 22 May 2019 16:44:47 +0900 Subject: [PATCH 29/36] Add ExpandingBar UI element --- .../UserInterface/TestSceneExpandingBar.cs | 50 +++++++++ .../Graphics/UserInterface/ExpandingBar.cs | 101 ++++++++++++++++++ osu.Game/Overlays/OverlayHeaderTabControl.cs | 17 ++- 3 files changed, 159 insertions(+), 9 deletions(-) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs create mode 100644 osu.Game/Graphics/UserInterface/ExpandingBar.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs new file mode 100644 index 0000000000..974dbf0282 --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs @@ -0,0 +1,50 @@ +// 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.Game.Graphics.UserInterface; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneExpandingBar : OsuTestScene + { + public TestSceneExpandingBar() + { + Container container; + ExpandingBar expandingBar; + + Add(container = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new Drawable[] + { + new Box + { + Colour = Color4.Gray, + Alpha = 0.5f, + RelativeSizeAxes = Axes.Both, + }, + expandingBar = new ExpandingBar + { + Anchor = Anchor.Centre, + ExpandedSize = 10, + CollapsedSize = 2, + Colour = Color4.DeepSkyBlue, + } + } + }); + + AddStep(@"Collapse", () => expandingBar.Collapse()); + AddStep(@"Uncollapse", () => expandingBar.Expand()); + AddSliderStep(@"Resize container", 1, 300, 150, value => container.ResizeTo(value)); + AddStep(@"Horizontal", () => expandingBar.RelativeSizeAxes = Axes.X); + AddStep(@"Anchor top", () => expandingBar.Anchor = Anchor.TopCentre); + AddStep(@"Vertical", () => expandingBar.RelativeSizeAxes = Axes.Y); + AddStep(@"Anchor left", () => expandingBar.Anchor = Anchor.CentreLeft); + } + } +} diff --git a/osu.Game/Graphics/UserInterface/ExpandingBar.cs b/osu.Game/Graphics/UserInterface/ExpandingBar.cs new file mode 100644 index 0000000000..439a6002d8 --- /dev/null +++ b/osu.Game/Graphics/UserInterface/ExpandingBar.cs @@ -0,0 +1,101 @@ +// 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.Shapes; +using osuTK; + +namespace osu.Game.Graphics.UserInterface +{ + /// + /// A rounded bar which can be expanded or collapsed. + /// Generally used for tabs or breadcrumbs. + /// + public class ExpandingBar : Circle + { + private bool isCollapsed; + + public bool IsCollapsed + { + get => isCollapsed; + set + { + if (value == isCollapsed) + return; + + isCollapsed = value; + updateState(); + } + } + + private float expandedSize = 4; + + public float ExpandedSize + { + get => expandedSize; + set + { + if (value == expandedSize) + return; + + expandedSize = value; + updateState(); + } + } + + private float collapsedSize = 2; + + public float CollapsedSize + { + get => collapsedSize; + set + { + if (value == collapsedSize) + return; + + collapsedSize = value; + updateState(); + } + } + + public override Axes RelativeSizeAxes + { + get => base.RelativeSizeAxes; + set + { + base.RelativeSizeAxes = Axes.None; + Size = Vector2.Zero; + + base.RelativeSizeAxes = value; + updateState(); + } + } + + public ExpandingBar() + { + RelativeSizeAxes = Axes.X; + Origin = Anchor.Centre; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + updateState(); + } + + public void Collapse() => IsCollapsed = true; + + public void Expand() => IsCollapsed = false; + + private void updateState() + { + float newSize = IsCollapsed ? CollapsedSize : ExpandedSize; + Easing easingType = IsCollapsed ? Easing.Out : Easing.OutElastic; + + if (RelativeSizeAxes == Axes.X) + this.ResizeHeightTo(newSize, 400, easingType); + else + this.ResizeWidthTo(newSize, 400, easingType); + } + } +} diff --git a/osu.Game/Overlays/OverlayHeaderTabControl.cs b/osu.Game/Overlays/OverlayHeaderTabControl.cs index 21b42cfbf4..dfe7e52420 100644 --- a/osu.Game/Overlays/OverlayHeaderTabControl.cs +++ b/osu.Game/Overlays/OverlayHeaderTabControl.cs @@ -67,7 +67,7 @@ namespace osu.Game.Overlays private class HeaderTabItem : TabItem { private readonly OsuSpriteText text; - private readonly Drawable bar; + private readonly ExpandingBar bar; private Color4 accentColour; @@ -92,7 +92,7 @@ namespace osu.Game.Overlays AutoSizeAxes = Axes.X; RelativeSizeAxes = Axes.Y; - Children = new[] + Children = new Drawable[] { text = new OsuSpriteText { @@ -102,12 +102,11 @@ namespace osu.Game.Overlays Text = value, Font = OsuFont.GetFont() }, - bar = new Circle + bar = new ExpandingBar { - RelativeSizeAxes = Axes.X, - Height = 0, - Origin = Anchor.CentreLeft, - Anchor = Anchor.BottomLeft, + Anchor = Anchor.BottomCentre, + ExpandedSize = 7.5f, + CollapsedSize = 0 }, new HoverClickSounds() }; @@ -138,7 +137,7 @@ namespace osu.Game.Overlays if (Active.Value || IsHovered) { text.FadeColour(Color4.White, 120, Easing.InQuad); - bar.ResizeHeightTo(7.5f, 120, Easing.InQuad); + bar.Expand(); if (Active.Value) text.Font = text.Font.With(weight: FontWeight.Bold); @@ -146,7 +145,7 @@ namespace osu.Game.Overlays else { text.FadeColour(AccentColour, 120, Easing.InQuad); - bar.ResizeHeightTo(0, 120, Easing.InQuad); + bar.Collapse(); text.Font = text.Font.With(weight: FontWeight.Medium); } } From 372c5b081c985261d3f8cc0e43247600a6a646e9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 23 May 2019 12:07:22 +0900 Subject: [PATCH 30/36] Fix audio preview buttons not correctly handling load failure states Closes #4593. --- osu.Game/Audio/PreviewTrack.cs | 25 ++++++++++++++++--------- osu.Game/Overlays/Direct/PlayButton.cs | 10 ++++++++-- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/osu.Game/Audio/PreviewTrack.cs b/osu.Game/Audio/PreviewTrack.cs index 3b21bdefc4..22ce7d4711 100644 --- a/osu.Game/Audio/PreviewTrack.cs +++ b/osu.Game/Audio/PreviewTrack.cs @@ -28,7 +28,8 @@ namespace osu.Game.Audio private void load() { track = GetTrack(); - track.Completed += () => Schedule(Stop); + if (track != null) + track.Completed += () => Schedule(Stop); } /// @@ -56,19 +57,25 @@ namespace osu.Game.Audio /// /// Starts playing this . /// - public void Start() => startDelegate = Schedule(() => + /// Whether the track is started or already playing. + public bool Start() { if (track == null) - return; + return false; - if (hasStarted) - return; + startDelegate = Schedule(() => + { + if (hasStarted) + return; - hasStarted = true; + hasStarted = true; - track.Restart(); - Started?.Invoke(); - }); + track.Restart(); + Started?.Invoke(); + }); + + return true; + } /// /// Stops playing this . diff --git a/osu.Game/Overlays/Direct/PlayButton.cs b/osu.Game/Overlays/Direct/PlayButton.cs index 6daebb3c15..2a77e7ca26 100644 --- a/osu.Game/Overlays/Direct/PlayButton.cs +++ b/osu.Game/Overlays/Direct/PlayButton.cs @@ -129,7 +129,7 @@ namespace osu.Game.Overlays.Direct if (Preview != null) { - Preview.Start(); + attemptStart(); return; } @@ -147,7 +147,7 @@ namespace osu.Game.Overlays.Direct // user may have changed their mind. if (Playing.Value) - preview.Start(); + attemptStart(); }); } else @@ -157,6 +157,12 @@ namespace osu.Game.Overlays.Direct } } + private void attemptStart() + { + if (Preview?.Start() != true) + Playing.Value = false; + } + protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); From edfe47fb0268fdadd0848595cdcc1c7f046a32ed Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 23 May 2019 13:37:25 +0900 Subject: [PATCH 31/36] Rename button --- osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs index 974dbf0282..f92aae43d2 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneExpandingBar.cs @@ -39,7 +39,7 @@ namespace osu.Game.Tests.Visual.UserInterface }); AddStep(@"Collapse", () => expandingBar.Collapse()); - AddStep(@"Uncollapse", () => expandingBar.Expand()); + AddStep(@"Expand", () => expandingBar.Expand()); AddSliderStep(@"Resize container", 1, 300, 150, value => container.ResizeTo(value)); AddStep(@"Horizontal", () => expandingBar.RelativeSizeAxes = Axes.X); AddStep(@"Anchor top", () => expandingBar.Anchor = Anchor.TopCentre); From 7971261fbc6ea50a6b488b082538e16349057896 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 23 May 2019 15:59:22 +0900 Subject: [PATCH 32/36] Don't create a new drawable for the first background --- .../Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index bd80919851..2d83c1de01 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -39,7 +39,7 @@ namespace osu.Game.Beatmaps.Drawables { // If DelayedLoadUnloadWrapper is attempting to RELOAD the same content (Beatmap), that means that it was // previously UNLOADED and thus its children have been disposed of, so we need to recreate them here. - if (lastModel == Beatmap.Value) + if (lastModel != null && lastModel == Beatmap.Value) return CreateDrawable(Beatmap.Value); // If the model has changed since the previous unload (or if there was no load), then we can safely use the given content From f0d7728e81d91d4704bf180998e20b286a505574 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 23 May 2019 17:01:13 +0900 Subject: [PATCH 33/36] Fix failures with a null-model --- .../Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs index 2d83c1de01..96786f5f49 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapBackgroundSprite.cs @@ -32,6 +32,7 @@ namespace osu.Game.Beatmaps.Drawables protected virtual double UnloadDelay => 10000; private BeatmapInfo lastModel; + private bool firstLoad = true; protected override DelayedLoadWrapper CreateDelayedLoadWrapper(Drawable content, double timeBeforeLoad) { @@ -39,11 +40,12 @@ namespace osu.Game.Beatmaps.Drawables { // If DelayedLoadUnloadWrapper is attempting to RELOAD the same content (Beatmap), that means that it was // previously UNLOADED and thus its children have been disposed of, so we need to recreate them here. - if (lastModel != null && lastModel == Beatmap.Value) + if (!firstLoad && lastModel == Beatmap.Value) return CreateDrawable(Beatmap.Value); // If the model has changed since the previous unload (or if there was no load), then we can safely use the given content lastModel = Beatmap.Value; + firstLoad = false; return content; }, timeBeforeLoad, UnloadDelay); } From 9c6fbebb67040cf8ce367480cbda5a29ef647652 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 23 May 2019 17:55:18 +0900 Subject: [PATCH 34/36] Update framework --- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 98b158134d..b77c724d1b 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -15,7 +15,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index b7549eeaef..fc047aa5f0 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -105,8 +105,8 @@ - - + + From cda97a61fa751d6f2b2b643d37a6fa994d1b9b86 Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Fri, 24 May 2019 19:43:53 +0300 Subject: [PATCH 35/36] Add a bit of smoothness to the rank graph --- .../Visual/Online/TestSceneRankGraph.cs | 25 ++++++++ .../Profile/Header/Components/RankGraph.cs | 63 ++++++++++--------- 2 files changed, 58 insertions(+), 30 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs b/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs index c04a4249cc..709e75ab13 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankGraph.cs @@ -31,6 +31,7 @@ namespace osu.Game.Tests.Visual.Online var data = new int[89]; var dataWithZeros = new int[89]; var smallData = new int[89]; + var edgyData = new int[89]; for (int i = 0; i < 89; i++) data[i] = dataWithZeros[i] = (i + 1) * 1000; @@ -41,6 +42,14 @@ namespace osu.Game.Tests.Visual.Online for (int i = 79; i < 89; i++) smallData[i] = 100000 - i * 1000; + bool edge = true; + + for (int i = 0; i < 20; i++) + { + edgyData[i] = 100000 + (edge ? 1000 : -1000) * (i + 1); + edge = !edge; + } + Add(new Container { Anchor = Anchor.Centre, @@ -120,6 +129,22 @@ namespace osu.Game.Tests.Visual.Online } }; }); + + AddStep("graph with edges", () => + { + graph.User.Value = new User + { + Statistics = new UserStatistics + { + Ranks = new UserStatistics.UserRanks { Global = 12000 }, + PP = 12345, + }, + RankHistory = new User.RankHistoryData + { + Data = edgyData, + } + }; + }); } } } diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index 85ea2a175a..5ad6db9ff1 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -96,7 +96,7 @@ namespace osu.Game.Overlays.Profile.Header.Components if (ranks?.Length > 1) { graph.UpdateBallPosition(e.MousePosition.X); - graph.ShowBall(); + graph.ShowBar(); } return base.OnHover(e); @@ -114,7 +114,7 @@ namespace osu.Game.Overlays.Profile.Header.Components { if (ranks?.Length > 1) { - graph.HideBall(); + graph.HideBar(); } base.OnHoverLost(e); @@ -123,31 +123,41 @@ namespace osu.Game.Overlays.Profile.Header.Components private class RankChartLineGraph : LineGraph { private readonly CircularContainer movingBall; + private readonly Container bar; private readonly Box ballBg; - private readonly Box movingBar; + private readonly Box line; public Action OnBallMove; public RankChartLineGraph() { - Add(movingBar = new Box + Add(bar = new Container { Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.Y, - Width = 1.5f, + AutoSizeAxes = Axes.X, Alpha = 0, RelativePositionAxes = Axes.Both, - }); - - Add(movingBall = new CircularContainer - { - Origin = Anchor.Centre, - Size = new Vector2(18), - Alpha = 0, - Masking = true, - BorderThickness = 4, - RelativePositionAxes = Axes.Both, - Child = ballBg = new Box { RelativeSizeAxes = Axes.Both } + Children = new Drawable[] + { + line = new Box + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + Width = 1.5f, + }, + movingBall = new CircularContainer + { + Anchor = Anchor.TopCentre, + Origin = Anchor.Centre, + Size = new Vector2(18), + Masking = true, + BorderThickness = 4, + RelativePositionAxes = Axes.Y, + Child = ballBg = new Box { RelativeSizeAxes = Axes.Both } + } + } }); } @@ -155,29 +165,22 @@ namespace osu.Game.Overlays.Profile.Header.Components private void load(OsuColour colours) { ballBg.Colour = colours.GreySeafoamDarker; - movingBall.BorderColour = colours.Yellow; - movingBar.Colour = colours.Yellow; + movingBall.BorderColour = line.Colour = colours.Yellow; } public void UpdateBallPosition(float mouseXPosition) { + int duration = 200; int index = calculateIndex(mouseXPosition); - movingBall.Position = calculateBallPosition(index); - movingBar.X = movingBall.X; + Vector2 position = calculateBallPosition(index); + movingBall.MoveToY(position.Y, duration, Easing.OutQuint); + bar.MoveToX(position.X, duration, Easing.OutQuint); OnBallMove.Invoke(index); } - public void ShowBall() - { - movingBall.FadeIn(fade_duration); - movingBar.FadeIn(fade_duration); - } + public void ShowBar() => bar.FadeIn(fade_duration); - public void HideBall() - { - movingBall.FadeOut(fade_duration); - movingBar.FadeOut(fade_duration); - } + public void HideBar() => bar.FadeOut(fade_duration); private int calculateIndex(float mouseXPosition) => (int)Math.Round(mouseXPosition / DrawWidth * (DefaultValueCount - 1)); From 69ada11f4137ec09a2ffd22276a2f6e0680c4cbc Mon Sep 17 00:00:00 2001 From: EVAST9919 Date: Fri, 24 May 2019 20:01:47 +0300 Subject: [PATCH 36/36] use constant value --- osu.Game/Overlays/Profile/Header/Components/RankGraph.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs index 5ad6db9ff1..5f79386b76 100644 --- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs +++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs @@ -170,7 +170,7 @@ namespace osu.Game.Overlays.Profile.Header.Components public void UpdateBallPosition(float mouseXPosition) { - int duration = 200; + const int duration = 200; int index = calculateIndex(mouseXPosition); Vector2 position = calculateBallPosition(index); movingBall.MoveToY(position.Y, duration, Easing.OutQuint);