From 2e7922c3f9a98a985dbc3f9e2cb453a534b3f9e9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 15 Jun 2019 23:53:28 +0900 Subject: [PATCH 01/11] Fix 0-length sliders not getting correct lengths --- .../Objects/Legacy/Catch/ConvertHitObjectParser.cs | 3 ++- .../Rulesets/Objects/Legacy/ConvertHitObjectParser.cs | 9 +++++++-- .../Objects/Legacy/Mania/ConvertHitObjectParser.cs | 3 ++- .../Objects/Legacy/Osu/ConvertHitObjectParser.cs | 6 +++--- .../Objects/Legacy/Taiko/ConvertHitObjectParser.cs | 3 ++- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs index 48f637dfe8..c968fe469a 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs @@ -37,7 +37,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch }; } - protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples) + protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, + List> nodeSamples) { newCombo |= forceNewCombo; comboOffset += extraComboOffset; diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs index c14f3b6a42..36ae15efcc 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs @@ -72,7 +72,7 @@ namespace osu.Game.Rulesets.Objects.Legacy else if (type.HasFlag(ConvertHitObjectType.Slider)) { PathType pathType = PathType.Catmull; - double length = 0; + double? length = null; string[] pointSplit = split[5].Split('|'); @@ -130,7 +130,11 @@ namespace osu.Game.Rulesets.Objects.Legacy repeatCount = Math.Max(0, repeatCount - 1); if (split.Length > 7) + { length = Math.Max(0, Parsing.ParseDouble(split[7])); + if (length == 0) + length = null; + } if (split.Length > 10) readCustomSampleBanks(split[10], bankInfo); @@ -291,7 +295,8 @@ namespace osu.Game.Rulesets.Objects.Legacy /// The slider repeat count. /// The samples to be played when the slider nodes are hit. This includes the head and tail of the slider. /// The hit object. - protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples); + protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, + List> nodeSamples); /// /// Creates a legacy Spinner-type hit object. diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs index 8a3e232e60..5acc085ba1 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs @@ -26,7 +26,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania }; } - protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples) + protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, + List> nodeSamples) { return new ConvertSlider { diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs index b98de32bd0..d46e1fa86a 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using osuTK; using osu.Game.Rulesets.Objects.Types; using System.Collections.Generic; @@ -38,7 +37,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu }; } - protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples) + protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, + List> nodeSamples) { newCombo |= forceNewCombo; comboOffset += extraComboOffset; @@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu Position = position, NewCombo = FirstObject || newCombo, ComboOffset = comboOffset, - Path = new SliderPath(pathType, controlPoints, Math.Max(0, length)), + Path = new SliderPath(pathType, controlPoints, length), NodeSamples = nodeSamples, RepeatCount = repeatCount }; diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs index bab21b31ad..39fb9e3b3a 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs @@ -23,7 +23,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko return new ConvertHit(); } - protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples) + protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount, + List> nodeSamples) { return new ConvertSlider { From 3d12c709a53bf0d8343797c327daf8296644f15d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 5 Jul 2019 15:40:47 +0930 Subject: [PATCH 02/11] Add test case --- .../OsuDifficultyCalculatorTest.cs | 1 + .../Testing/Beatmaps/zero-length-sliders.osu | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/zero-length-sliders.osu diff --git a/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs index e55dc1f902..693faee3b7 100644 --- a/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs @@ -15,6 +15,7 @@ namespace osu.Game.Rulesets.Osu.Tests protected override string ResourceAssembly => "osu.Game.Rulesets.Osu"; [TestCase(6.931145117263422, "diffcalc-test")] + [TestCase(1.0736587013228804d, "zero-length-sliders")] public void Test(double expected, string name) => base.Test(expected, name); diff --git a/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/zero-length-sliders.osu b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/zero-length-sliders.osu new file mode 100644 index 0000000000..18736043b5 --- /dev/null +++ b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/zero-length-sliders.osu @@ -0,0 +1,28 @@ +osu file format v14 + +[Difficulty] +HPDrainRate:3 +CircleSize:3 +OverallDifficulty:3 +ApproachRate:4.5 +SliderMultiplier:0.799999999999999 +SliderTickRate:1 + +[TimingPoints] +800,260.869565217391,3,2,10,60,1,0 + +[HitObjects] +// Linear +78,193,2365,2,0,L|330:193,1,0 +78,193,3669,2,0,L|330:193,1,0 +78,193,4973,2,0,L|330:193,1,0 + +// Perfect-curve +151,206,6278,2,0,P|293:75|345:204,1,0 +151,206,8104,2,0,P|293:75|345:204,1,0 +151,206,9930,2,0,P|293:75|345:204,1,0 + +// Bezier +76,191,11756,2,0,B|176:59|358:340|438:190,1,0 +76,191,13582,2,0,B|176:59|358:340|438:190,1,0 +76,191,15408,2,0,B|176:59|358:340|438:190,1,0 From 9c1badd2e3771a36c2eea89d090c0db873991f71 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 15 Jul 2019 15:42:54 +0900 Subject: [PATCH 03/11] Fix rulesets not matching in dictionary lookups due to missing GetHashCode implementation --- osu.Game/Rulesets/RulesetInfo.cs | 14 ++++++++++++++ osu.Game/Rulesets/RulesetStore.cs | 6 +++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index ca331ec339..8eb2abec79 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics.CodeAnalysis; using Newtonsoft.Json; namespace osu.Game.Rulesets @@ -23,6 +24,19 @@ namespace osu.Game.Rulesets public bool Equals(RulesetInfo other) => other != null && ID == other.ID && Available == other.Available && Name == other.Name && InstantiationInfo == other.InstantiationInfo; + [SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode")] + public override int GetHashCode() + { + unchecked + { + var hashCode = ID.HasValue ? ID.GetHashCode() : 0; + hashCode = (hashCode * 397) ^ (InstantiationInfo != null ? InstantiationInfo.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (Name != null ? Name.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ Available.GetHashCode(); + return hashCode; + } + } + public override string ToString() => $"{Name} ({ShortName}) ID: {ID}"; } } diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs index fd42f96c92..2d8c9f5b49 100644 --- a/osu.Game/Rulesets/RulesetStore.cs +++ b/osu.Game/Rulesets/RulesetStore.cs @@ -32,7 +32,7 @@ namespace osu.Game.Rulesets public RulesetStore(IDatabaseContextFactory factory) : base(factory) { - AddMissingRulesets(); + addMissingRulesets(); } /// @@ -52,13 +52,13 @@ namespace osu.Game.Rulesets /// /// All available rulesets. /// - public IEnumerable AvailableRulesets; + public IEnumerable AvailableRulesets { get; private set; } private static Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args) => loaded_assemblies.Keys.FirstOrDefault(a => a.FullName == args.Name); private const string ruleset_library_prefix = "osu.Game.Rulesets"; - protected void AddMissingRulesets() + private void addMissingRulesets() { using (var usage = ContextFactory.GetForWrite()) { From d0c8aaba4e1f6442e188f7042deb4d8a0a5b5b3f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 15 Jul 2019 15:50:50 +0900 Subject: [PATCH 04/11] Override basic equality function too --- osu.Game/Rulesets/RulesetInfo.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs index 8eb2abec79..d9cff86265 100644 --- a/osu.Game/Rulesets/RulesetInfo.cs +++ b/osu.Game/Rulesets/RulesetInfo.cs @@ -24,6 +24,8 @@ namespace osu.Game.Rulesets public bool Equals(RulesetInfo other) => other != null && ID == other.ID && Available == other.Available && Name == other.Name && InstantiationInfo == other.InstantiationInfo; + public override bool Equals(object obj) => obj is RulesetInfo rulesetInfo && Equals(rulesetInfo); + [SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode")] public override int GetHashCode() { From d4c1005c7e820bfa7d7cb1a5b1791e3ba1b0a5a3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 15 Jul 2019 15:53:19 +0900 Subject: [PATCH 05/11] Fix incorrect comparison in line updating logic --- osu.Game/OsuGame.cs | 2 +- osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs | 2 +- osu.Game/Screens/Select/SongSelect.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 361ff62155..2a484fc122 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -248,7 +248,7 @@ namespace osu.Game } // Use first beatmap available for current ruleset, else switch ruleset. - var first = databasedSet.Beatmaps.Find(b => b.Ruleset == Ruleset.Value) ?? databasedSet.Beatmaps.First(); + var first = databasedSet.Beatmaps.Find(b => b.Ruleset.Equals(Ruleset.Value)) ?? databasedSet.Beatmaps.First(); Ruleset.Value = first.Ruleset; Beatmap.Value = BeatmapManager.GetWorkingBeatmap(first); diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs index f4272ab15c..bf0cd91321 100644 --- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs +++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs @@ -73,7 +73,7 @@ namespace osu.Game.Overlays.Toolbar { foreach (var tabItem in TabContainer) { - if (tabItem.Value == Current.Value) + if (tabItem.Value.Equals(Current.Value)) { ModeButtonLine.MoveToX(tabItem.DrawPosition.X, !hasInitialPosition ? 0 : 200, Easing.OutQuint); break; diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 0eeffda5eb..b3c3925a26 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -329,7 +329,7 @@ namespace osu.Game.Screens.Select if (this.IsCurrentScreen() && !Carousel.SelectBeatmap(e.NewValue?.BeatmapInfo, false)) // If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch - if (e.NewValue?.BeatmapInfo?.Ruleset != null && e.NewValue.BeatmapInfo.Ruleset != decoupledRuleset.Value) + if (e.NewValue?.BeatmapInfo?.Ruleset != null && !e.NewValue.BeatmapInfo.Ruleset.Equals(decoupledRuleset.Value)) { Ruleset.Value = e.NewValue.BeatmapInfo.Ruleset; Carousel.SelectBeatmap(e.NewValue.BeatmapInfo); From ed203cb0ffc3d22659e322976da02b2855864c68 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 16 Jul 2019 13:45:59 +0900 Subject: [PATCH 06/11] Delay intial hitobject updates --- .../Objects/Drawables/DrawableOsuHitObject.cs | 3 ++ .../Objects/Drawables/DrawableHitObject.cs | 42 ++++++++++++++----- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index f372cb65ce..4533e08a2b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -29,6 +29,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables ShakeDuration = 30, RelativeSizeAxes = Axes.Both }); + Alpha = 0; } @@ -38,6 +39,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void ClearInternal(bool disposeChildren = true) => shakeContainer.Clear(disposeChildren); protected override bool RemoveInternal(Drawable drawable) => shakeContainer.Remove(drawable); + protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt; + protected sealed override void UpdateState(ArmedState state) { double transformTime = HitObject.StartTime - HitObject.TimePreempt; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 1f6ca4dd73..76233eabf2 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -179,6 +179,38 @@ namespace osu.Game.Rulesets.Objects.Drawables UpdateResult(false); } + private double? lifetimeStart; + + public override double LifetimeStart + { + get => lifetimeStart ?? (HitObject.StartTime - InitialLifetimeOffset); + set + { + base.LifetimeStart = value; + lifetimeStart = value; + } + } + + /// + /// A safe offset prior to the start time of at which this may begin displaying contents. + /// By default, s are assumed to display their contents within 10 seconds prior to the start time of . + /// + /// + /// This is only used as an optimisation to delay the initial update of this and may be tuned more aggressively if required. + /// A more accurate should be set inside for an state. + /// + protected virtual double InitialLifetimeOffset => 10000; + + /// + /// Will called at least once after the of this has been passed. + /// + internal void OnLifetimeEnd() + { + foreach (var nested in NestedHitObjects) + nested.OnLifetimeEnd(); + UpdateResult(false); + } + protected virtual void AddNested(DrawableHitObject h) { h.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r); @@ -223,16 +255,6 @@ namespace osu.Game.Rulesets.Objects.Drawables OnNewResult?.Invoke(this, Result); } - /// - /// Will called at least once after the of this has been passed. - /// - internal void OnLifetimeEnd() - { - foreach (var nested in NestedHitObjects) - nested.OnLifetimeEnd(); - UpdateResult(false); - } - /// /// Processes this , checking if a scoring result has occurred. /// From 7634e3cc813c43d317c518dda349878bd94b7013 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 16 Jul 2019 14:57:11 +0900 Subject: [PATCH 07/11] Fix song select iterating over all beatmaps in database unnnecessarily --- osu.Game/Screens/Select/SongSelect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index b3c3925a26..260867b1ea 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -253,7 +253,7 @@ namespace osu.Game.Screens.Select Schedule(() => { // if we have no beatmaps but osu-stable is found, let's prompt the user to import. - if (!beatmaps.GetAllUsableBeatmapSets().Any() && beatmaps.StableInstallationAvailable) + if (!beatmaps.GetAllUsableBeatmapSetsEnumerable().Any() && beatmaps.StableInstallationAvailable) dialogOverlay.Push(new ImportFromStablePopup(() => { Task.Run(beatmaps.ImportFromStableAsync).ContinueWith(_ => scores.ImportFromStableAsync(), TaskContinuationOptions.OnlyOnRanToCompletion); From b0415dc30abb7aec345c535988097be14446271b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 16 Jul 2019 17:33:14 +0900 Subject: [PATCH 08/11] Remove cursortrail drawnode allocs --- .../UI/Cursor/CursorTrail.cs | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index b986076593..6a70728c50 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -162,7 +162,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private readonly TrailPart[] parts = new TrailPart[max_sprites]; private Vector2 size; - private readonly VertexBatch vertexBatch = new QuadBatch(max_sprites, 1); + private readonly CustomBatch vertexBatch = new CustomBatch(max_sprites, 1); public TrailDrawNode(CursorTrail source) : base(source) @@ -197,20 +197,14 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor for (int i = 0; i < parts.Length; ++i) { Vector2 pos = parts[i].Position; - float localTime = parts[i].Time; + vertexBatch.DrawTime = parts[i].Time; DrawQuad( texture, new Quad(pos.X - size.X / 2, pos.Y - size.Y / 2, size.X, size.Y), DrawColourInfo.Colour, null, - v => vertexBatch.Add(new TexturedTrailVertex - { - Position = v.Position, - TexturePosition = v.TexturePosition, - Time = localTime + 1, - Colour = v.Colour, - })); + vertexBatch.AddAction); } shader.Unbind(); @@ -222,6 +216,27 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor vertexBatch.Dispose(); } + + private class CustomBatch : QuadBatch + { + public new readonly Action AddAction; + + public float DrawTime; + + public CustomBatch(int size, int maxBuffers) + : base(size, maxBuffers) + { + AddAction = add; + } + + private void add(TexturedVertex2D vertex) => Add(new TexturedTrailVertex + { + Position = vertex.Position, + TexturePosition = vertex.TexturePosition, + Time = DrawTime + 1, + Colour = vertex.Colour, + }); + } } [StructLayout(LayoutKind.Sequential)] From 62b867018d555d6c034ce00991768bb35bcc2338 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 16 Jul 2019 17:50:03 +0900 Subject: [PATCH 09/11] Refactor a bit --- .../UI/Cursor/CursorTrail.cs | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs index 6a70728c50..05eb0ffdbf 100644 --- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs +++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs @@ -162,7 +162,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor private readonly TrailPart[] parts = new TrailPart[max_sprites]; private Vector2 size; - private readonly CustomBatch vertexBatch = new CustomBatch(max_sprites, 1); + private readonly TrailBatch vertexBatch = new TrailBatch(max_sprites, 1); public TrailDrawNode(CursorTrail source) : base(source) @@ -196,9 +196,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor for (int i = 0; i < parts.Length; ++i) { - Vector2 pos = parts[i].Position; vertexBatch.DrawTime = parts[i].Time; + Vector2 pos = parts[i].Position; + DrawQuad( texture, new Quad(pos.X - size.X / 2, pos.Y - size.Y / 2, size.X, size.Y), @@ -217,25 +218,23 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor vertexBatch.Dispose(); } - private class CustomBatch : QuadBatch + // Todo: This shouldn't exist, but is currently used to reduce allocations by caching variable-capturing closures. + private class TrailBatch : QuadBatch { public new readonly Action AddAction; - public float DrawTime; - public CustomBatch(int size, int maxBuffers) + public TrailBatch(int size, int maxBuffers) : base(size, maxBuffers) { - AddAction = add; + AddAction = v => Add(new TexturedTrailVertex + { + Position = v.Position, + TexturePosition = v.TexturePosition, + Time = DrawTime + 1, + Colour = v.Colour, + }); } - - private void add(TexturedVertex2D vertex) => Add(new TexturedTrailVertex - { - Position = vertex.Position, - TexturePosition = vertex.TexturePosition, - Time = DrawTime + 1, - Colour = vertex.Colour, - }); } } From 7c5a227fc53c4e750e19ff630719e15101d22e4b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 17 Jul 2019 14:46:25 +0900 Subject: [PATCH 10/11] Fix crashes when presenting replays --- osu.Game/Screens/Select/FooterButtonMods.cs | 16 ++++++++++------ osu.Game/Screens/Select/SongSelect.cs | 11 ++++++++--- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs index c96c5022c0..fce4d1b2e2 100644 --- a/osu.Game/Screens/Select/FooterButtonMods.cs +++ b/osu.Game/Screens/Select/FooterButtonMods.cs @@ -9,18 +9,25 @@ using osu.Game.Rulesets.Mods; using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics; using osuTK; using osuTK.Input; namespace osu.Game.Screens.Select { - public class FooterButtonMods : FooterButton + public class FooterButtonMods : FooterButton, IHasCurrentValue> { - public FooterButtonMods(Bindable> mods) + public Bindable> Current { - FooterModDisplay modDisplay; + get => modDisplay.Current; + set => modDisplay.Current = value; + } + private readonly FooterModDisplay modDisplay; + + public FooterButtonMods() + { Add(new Container { Anchor = Anchor.CentreLeft, @@ -33,9 +40,6 @@ namespace osu.Game.Screens.Select AutoSizeAxes = Axes.Both, Margin = new MarginPadding { Left = 70 } }); - - if (mods != null) - modDisplay.Current = mods; } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 260867b1ea..20dbcf2693 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -221,11 +221,9 @@ namespace osu.Game.Screens.Select [BackgroundDependencyLoader(true)] private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores) { - mods.BindTo(Mods); - if (Footer != null) { - Footer.AddButton(new FooterButtonMods(mods), ModSelect); + Footer.AddButton(new FooterButtonMods { Current = mods }, ModSelect); Footer.AddButton(new FooterButtonRandom { Action = triggerRandom }); Footer.AddButton(new FooterButtonOptions(), BeatmapOptions); @@ -263,6 +261,13 @@ namespace osu.Game.Screens.Select } } + protected override void LoadComplete() + { + base.LoadComplete(); + + mods.BindTo(Mods); + } + private DependencyContainer dependencies; protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) From 66036508b607348d1f88daf0845bc5aeffbc2c71 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 Jul 2019 17:39:04 +0900 Subject: [PATCH 11/11] Fix potential crash when displaying leaderbaords --- osu.Game/Online/Leaderboards/Leaderboard.cs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index 35f7ba1c1b..18c827707a 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -51,7 +51,6 @@ namespace osu.Game.Online.Leaderboards loading.Hide(); - // schedule because we may not be loaded yet (LoadComponentAsync complains). showScoresDelegate?.Cancel(); showScoresCancellationSource?.Cancel(); @@ -61,28 +60,22 @@ namespace osu.Game.Online.Leaderboards // ensure placeholder is hidden when displaying scores PlaceholderState = PlaceholderState.Successful; - scrollFlow = CreateScoreFlow(); - scrollFlow.ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1)); + var sf = CreateScoreFlow(); + sf.ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1)); - if (!IsLoaded) - showScoresDelegate = Schedule(showScores); - else - showScores(); - - void showScores() => LoadComponentAsync(scrollFlow, _ => + // schedule because we may not be loaded yet (LoadComponentAsync complains). + showScoresDelegate = Schedule(() => LoadComponentAsync(sf, _ => { - scrollContainer.Add(scrollFlow); + scrollContainer.Add(scrollFlow = sf); int i = 0; foreach (var s in scrollFlow.Children) - { using (s.BeginDelayedSequence(i++ * 50, true)) s.Show(); - } scrollContainer.ScrollTo(0f, false); - }, (showScoresCancellationSource = new CancellationTokenSource()).Token); + }, (showScoresCancellationSource = new CancellationTokenSource()).Token)); } }