From 56721a6fa9aec7d9ae55091931e474186862d6b7 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 12:48:13 +0900 Subject: [PATCH 01/73] Compute object position in stack via a pure function --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index a806e623af..76c5afeda7 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -447,8 +447,10 @@ namespace osu.Game.Rulesets.Catch.UI if (caughtObject == null) return; + var positionInStack = computePositionInStack(new Vector2(source.X - X, 0), caughtObject.DisplayRadius); + caughtObject.RelativePositionAxes = Axes.None; - caughtObject.X = source.X - X; + caughtObject.Position = positionInStack; caughtObject.IsOnPlate = true; caughtObject.Anchor = Anchor.TopCentre; @@ -457,8 +459,6 @@ namespace osu.Game.Rulesets.Catch.UI caughtObject.LifetimeStart = source.StartTime; caughtObject.LifetimeEnd = double.MaxValue; - adjustPositionInStack(caughtObject); - caughtFruitContainer.Add(caughtObject); addLighting(caughtObject); @@ -467,22 +467,22 @@ namespace osu.Game.Rulesets.Catch.UI removeFromPlate(caughtObject, DroppedObjectAnimation.Explode); } - private void adjustPositionInStack(DrawablePalpableCatchHitObject caughtObject) + private Vector2 computePositionInStack(Vector2 position, float displayRadius) { const float radius_div_2 = CatchHitObject.OBJECT_RADIUS / 2; const float allowance = 10; - float caughtObjectRadius = caughtObject.DisplayRadius; - - while (caughtFruitContainer.Any(f => Vector2Extensions.Distance(f.Position, caughtObject.Position) < (caughtObjectRadius + radius_div_2) / (allowance / 2))) + while (caughtFruitContainer.Any(f => Vector2Extensions.Distance(f.Position, position) < (displayRadius + radius_div_2) / (allowance / 2))) { - float diff = (caughtObjectRadius + radius_div_2) / allowance; + float diff = (displayRadius + radius_div_2) / allowance; - caughtObject.X += (RNG.NextSingle() - 0.5f) * diff * 2; - caughtObject.Y -= RNG.NextSingle() * diff; + position.X += (RNG.NextSingle() - 0.5f) * diff * 2; + position.Y -= RNG.NextSingle() * diff; } - caughtObject.X = Math.Clamp(caughtObject.X, -CatcherArea.CATCHER_SIZE / 2, CatcherArea.CATCHER_SIZE / 2); + position.X = Math.Clamp(position.X, -CatcherArea.CATCHER_SIZE / 2, CatcherArea.CATCHER_SIZE / 2); + + return position; } private void addLighting(DrawablePalpableCatchHitObject caughtObject) From 004c705aa9da1024078af02f8ef6c87c8468d804 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 20:05:18 +0900 Subject: [PATCH 02/73] Remove ScaleContainer and flatten the Drawable tree of catch DHO --- .../TestSceneFruitRandomness.cs | 47 +++++-------------- .../Objects/Drawables/DrawableBanana.cs | 14 +++--- .../Objects/Drawables/DrawableDroplet.cs | 6 +-- .../Objects/Drawables/DrawableFruit.cs | 6 +-- .../DrawablePalpableCatchHitObject.cs | 14 +----- 5 files changed, 28 insertions(+), 59 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs index 2ffebb7de1..e1d817b314 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs @@ -11,13 +11,13 @@ namespace osu.Game.Rulesets.Catch.Tests { public class TestSceneFruitRandomness : OsuTestScene { - private readonly TestDrawableFruit drawableFruit; - private readonly TestDrawableBanana drawableBanana; + private readonly DrawableFruit drawableFruit; + private readonly DrawableBanana drawableBanana; public TestSceneFruitRandomness() { - drawableFruit = new TestDrawableFruit(new Fruit()); - drawableBanana = new TestDrawableBanana(new Banana()); + drawableFruit = new DrawableFruit(new Fruit()); + drawableBanana = new DrawableBanana(new Banana()); Add(new TestDrawableCatchHitObjectSpecimen(drawableFruit) { X = -200 }); Add(new TestDrawableCatchHitObjectSpecimen(drawableBanana)); @@ -44,9 +44,9 @@ namespace osu.Game.Rulesets.Catch.Tests { drawableFruit.HitObject.StartTime = drawableBanana.HitObject.StartTime = initial_start_time; - fruitRotation = drawableFruit.InnerRotation; - bananaRotation = drawableBanana.InnerRotation; - bananaScale = drawableBanana.InnerScale; + fruitRotation = drawableFruit.Rotation; + bananaRotation = drawableBanana.Rotation; + bananaScale = drawableBanana.Scale.X; bananaColour = drawableBanana.AccentColour.Value; }); @@ -55,9 +55,9 @@ namespace osu.Game.Rulesets.Catch.Tests drawableFruit.HitObject.StartTime = drawableBanana.HitObject.StartTime = another_start_time; }); - AddAssert("fruit rotation is changed", () => drawableFruit.InnerRotation != fruitRotation); - AddAssert("banana rotation is changed", () => drawableBanana.InnerRotation != bananaRotation); - AddAssert("banana scale is changed", () => drawableBanana.InnerScale != bananaScale); + AddAssert("fruit rotation is changed", () => drawableFruit.Rotation != fruitRotation); + AddAssert("banana rotation is changed", () => drawableBanana.Rotation != bananaRotation); + AddAssert("banana scale is changed", () => drawableBanana.Scale.X != bananaScale); AddAssert("banana colour is changed", () => drawableBanana.AccentColour.Value != bananaColour); AddStep("reset start time", () => @@ -66,31 +66,10 @@ namespace osu.Game.Rulesets.Catch.Tests }); AddAssert("rotation and scale restored", () => - drawableFruit.InnerRotation == fruitRotation && - drawableBanana.InnerRotation == bananaRotation && - drawableBanana.InnerScale == bananaScale && + drawableFruit.Rotation == fruitRotation && + drawableBanana.Rotation == bananaRotation && + drawableBanana.Scale.X == bananaScale && drawableBanana.AccentColour.Value == bananaColour); } - - private class TestDrawableFruit : DrawableFruit - { - public float InnerRotation => ScaleContainer.Rotation; - - public TestDrawableFruit(Fruit h) - : base(h) - { - } - } - - private class TestDrawableBanana : DrawableBanana - { - public float InnerRotation => ScaleContainer.Rotation; - public float InnerScale => ScaleContainer.Scale.X; - - public TestDrawableBanana(Banana h) - : base(h) - { - } - } } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs index 2a543a0e04..4bc5da2396 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs @@ -24,9 +24,9 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables [BackgroundDependencyLoader] private void load() { - ScaleContainer.Child = new SkinnableDrawable( + AddInternal(new SkinnableDrawable( new CatchSkinComponent(CatchSkinComponents.Banana), - _ => new BananaPiece()); + _ => new BananaPiece())); } protected override void LoadComplete() @@ -44,12 +44,12 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables const float end_scale = 0.6f; const float random_scale_range = 1.6f; - ScaleContainer.ScaleTo(HitObject.Scale * (end_scale + random_scale_range * RandomSingle(3))) - .Then().ScaleTo(HitObject.Scale * end_scale, HitObject.TimePreempt); + this.ScaleTo(HitObject.Scale * (end_scale + random_scale_range * RandomSingle(3))) + .Then().ScaleTo(HitObject.Scale * end_scale, HitObject.TimePreempt); - ScaleContainer.RotateTo(getRandomAngle(1)) - .Then() - .RotateTo(getRandomAngle(2), HitObject.TimePreempt); + this.RotateTo(getRandomAngle(1)) + .Then() + .RotateTo(getRandomAngle(2), HitObject.TimePreempt); float getRandomAngle(int series) => 180 * (RandomSingle(series) * 2 - 1); } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs index 81c8de2e59..d96b1c8902 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs @@ -26,9 +26,9 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables [BackgroundDependencyLoader] private void load() { - ScaleContainer.Child = new SkinnableDrawable( + AddInternal(new SkinnableDrawable( new CatchSkinComponent(CatchSkinComponents.Droplet), - _ => new DropletPiece()); + _ => new DropletPiece())); } protected override void UpdateInitialTransforms() @@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables float startRotation = RandomSingle(1) * 20; double duration = HitObject.TimePreempt + 2000; - ScaleContainer.RotateTo(startRotation).RotateTo(startRotation + 720, duration); + this.RotateTo(startRotation).RotateTo(startRotation + 720, duration); } } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs index 0fcd319a93..8135a31b43 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs @@ -32,16 +32,16 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables VisualRepresentation.Value = (FruitVisualRepresentation)(change.NewValue % 4); }, true); - ScaleContainer.Child = new SkinnableDrawable( + AddInternal(new SkinnableDrawable( new CatchSkinComponent(CatchSkinComponents.Fruit), - _ => new FruitPiece()); + _ => new FruitPiece())); } protected override void UpdateInitialTransforms() { base.UpdateInitialTransforms(); - ScaleContainer.RotateTo((RandomSingle(1) - 0.5f) * 40); + this.RotateTo((RandomSingle(1) - 0.5f) * 40); } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs index 0877b5e248..b99710ae8e 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs @@ -5,7 +5,6 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osuTK; namespace osu.Game.Rulesets.Catch.Objects.Drawables @@ -21,7 +20,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables public readonly Bindable IndexInBeatmap = new Bindable(); /// - /// The multiplicative factor applied to scale relative to scale. + /// The multiplicative factor applied to relative to scale. /// protected virtual float ScaleFactor => 1; @@ -32,20 +31,11 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables public float DisplayRadius => CatchHitObject.OBJECT_RADIUS * HitObject.Scale * ScaleFactor; - protected readonly Container ScaleContainer; - protected DrawablePalpableCatchHitObject([CanBeNull] CatchHitObject h) : base(h) { Origin = Anchor.Centre; Size = new Vector2(CatchHitObject.OBJECT_RADIUS * 2); - - AddInternal(ScaleContainer = new Container - { - RelativeSizeAxes = Axes.Both, - Origin = Anchor.Centre, - Anchor = Anchor.Centre, - }); } [BackgroundDependencyLoader] @@ -58,7 +48,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables ScaleBindable.BindValueChanged(scale => { - ScaleContainer.Scale = new Vector2(scale.NewValue * ScaleFactor); + Scale = new Vector2(scale.NewValue * ScaleFactor); }, true); IndexInBeatmap.BindValueChanged(_ => UpdateComboColour()); From 94a59ac3b240c75a00e440f2062ddbd7d9cec6e5 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 20:41:26 +0900 Subject: [PATCH 03/73] Make catch hit lighting logic not dependent on caught object --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 33 +++++++++++++++------------ 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 76c5afeda7..ac0f25e21b 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -215,10 +215,19 @@ namespace osu.Game.Rulesets.Catch.UI catchResult.CatcherAnimationState = CurrentState; catchResult.CatcherHyperDash = HyperDashing; - if (!(drawableObject.HitObject is PalpableCatchHitObject hitObject)) return; + if (!(drawableObject is DrawablePalpableCatchHitObject palpableObject)) return; + + var hitObject = palpableObject.HitObject; if (result.IsHit) - placeCaughtObject(hitObject); + { + var positionInStack = computePositionInStack(new Vector2(palpableObject.X - X, 0), palpableObject.DisplayRadius); + + placeCaughtObject(hitObject, positionInStack); + + if (hitLighting.Value) + addLighting(hitObject, positionInStack.X, drawableObject.AccentColour.Value); + } // droplet doesn't affect the catcher state if (hitObject is TinyDroplet) return; @@ -441,16 +450,14 @@ namespace osu.Game.Rulesets.Catch.UI updateCatcher(); } - private void placeCaughtObject(PalpableCatchHitObject source) + private void placeCaughtObject(PalpableCatchHitObject source, Vector2 position) { var caughtObject = createCaughtObject(source); if (caughtObject == null) return; - var positionInStack = computePositionInStack(new Vector2(source.X - X, 0), caughtObject.DisplayRadius); - caughtObject.RelativePositionAxes = Axes.None; - caughtObject.Position = positionInStack; + caughtObject.Position = position; caughtObject.IsOnPlate = true; caughtObject.Anchor = Anchor.TopCentre; @@ -461,8 +468,6 @@ namespace osu.Game.Rulesets.Catch.UI caughtFruitContainer.Add(caughtObject); - addLighting(caughtObject); - if (!caughtObject.StaysOnPlate) removeFromPlate(caughtObject, DroppedObjectAnimation.Explode); } @@ -485,15 +490,13 @@ namespace osu.Game.Rulesets.Catch.UI return position; } - private void addLighting(DrawablePalpableCatchHitObject caughtObject) + private void addLighting(CatchHitObject hitObject, float x, Color4 colour) { - if (!hitLighting.Value) return; - HitExplosion hitExplosion = hitExplosionPool.Get(); - hitExplosion.HitObject = caughtObject.HitObject; - hitExplosion.X = caughtObject.X; - hitExplosion.Scale = new Vector2(caughtObject.HitObject.Scale); - hitExplosion.ObjectColour = caughtObject.AccentColour.Value; + hitExplosion.HitObject = hitObject; + hitExplosion.X = x; + hitExplosion.Scale = new Vector2(hitObject.Scale); + hitExplosion.ObjectColour = colour; hitExplosionContainer.Add(hitExplosion); } From ed50fd445e81589df6375b284fbb003617bd129a Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 21:07:12 +0900 Subject: [PATCH 04/73] Fix hit lighting colour not applied in TestSceneCatcher --- .../TestSceneCatcher.cs | 59 +++++++++++++------ 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index cf6011d721..94cd0ec8a7 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -18,6 +18,7 @@ using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; +using osu.Game.Skinning; using osu.Game.Tests.Visual; namespace osu.Game.Rulesets.Catch.Tests @@ -65,13 +66,11 @@ namespace osu.Game.Rulesets.Catch.Tests JudgementResult result2 = null; AddStep("catch hyper fruit", () => { - drawableObject1 = createDrawableObject(new Fruit { HyperDashTarget = new Fruit { X = 100 } }); - result1 = attemptCatch(drawableObject1); + attemptCatch(new Fruit { HyperDashTarget = new Fruit { X = 100 } }, out drawableObject1, out result1); }); AddStep("catch normal fruit", () => { - drawableObject2 = createDrawableObject(new Fruit()); - result2 = attemptCatch(drawableObject2); + attemptCatch(new Fruit(), out drawableObject2, out result2); }); AddStep("revert second result", () => { @@ -92,8 +91,7 @@ namespace osu.Game.Rulesets.Catch.Tests JudgementResult result = null; AddStep("catch kiai fruit", () => { - drawableObject = createDrawableObject(new TestKiaiFruit()); - result = attemptCatch(drawableObject); + attemptCatch(new TestKiaiFruit(), out drawableObject, out result); }); checkState(CatcherAnimationState.Kiai); AddStep("revert result", () => @@ -200,13 +198,22 @@ namespace osu.Game.Rulesets.Catch.Tests AddAssert("fruits are dropped", () => !catcher.CaughtObjects.Any() && droppedObjectContainer.Count == 10); } - [TestCase(true)] - [TestCase(false)] - public void TestHitLighting(bool enabled) + [Test] + public void TestHitLightingColour() { - AddStep($"{(enabled ? "enable" : "disable")} hit lighting", () => config.Set(OsuSetting.HitLighting, enabled)); + var fruitColour = SkinConfiguration.DefaultComboColours[1]; + AddStep("enable hit lighting", () => config.Set(OsuSetting.HitLighting, true)); AddStep("catch fruit", () => attemptCatch(new Fruit())); - AddAssert("check hit lighting", () => catcher.ChildrenOfType().Any() == enabled); + AddAssert("correct hit lighting colour", () => + catcher.ChildrenOfType().First()?.ObjectColour == fruitColour); + } + + [Test] + public void TestHitLightingDisabled() + { + AddStep("disable hit lighting", () => config.Set(OsuSetting.HitLighting, false)); + AddStep("catch fruit", () => attemptCatch(new Fruit())); + AddAssert("no hit lighting", () => !catcher.ChildrenOfType().Any()); } private void checkPlate(int count) => AddAssert($"{count} objects on the plate", () => catcher.CaughtObjects.Count() == count); @@ -218,18 +225,34 @@ namespace osu.Game.Rulesets.Catch.Tests private void attemptCatch(CatchHitObject hitObject, int count = 1) { for (var i = 0; i < count; i++) - attemptCatch(createDrawableObject(hitObject)); + attemptCatch(hitObject, out _, out _); } - private JudgementResult attemptCatch(DrawableCatchHitObject drawableObject) + private void attemptCatch(CatchHitObject hitObject, out DrawableCatchHitObject drawableObject, out JudgementResult result) { - drawableObject.HitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); - var result = new CatchJudgementResult(drawableObject.HitObject, drawableObject.HitObject.CreateJudgement()) + hitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + drawableObject = createDrawableObject(hitObject); + result = createResult(hitObject); + applyResult(drawableObject, result); + } + + private void applyResult(DrawableCatchHitObject drawableObject, JudgementResult result) + { + // Load DHO to set colour of hit explosion correctly + Add(drawableObject); + drawableObject.OnLoadComplete += _ => { - Type = catcher.CanCatch(drawableObject.HitObject) ? HitResult.Great : HitResult.Miss + catcher.OnNewResult(drawableObject, result); + drawableObject.Expire(); + }; + } + + private JudgementResult createResult(CatchHitObject hitObject) + { + return new CatchJudgementResult(hitObject, hitObject.CreateJudgement()) + { + Type = catcher.CanCatch(hitObject) ? HitResult.Great : HitResult.Miss }; - catcher.OnNewResult(drawableObject, result); - return result; } private DrawableCatchHitObject createDrawableObject(CatchHitObject hitObject) From c301223d8cf12897e6d0327b11c505b59798be3d Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 20:34:08 +0900 Subject: [PATCH 05/73] Make object on the catcher plate separate CaughtObject class --- .../TestSceneCatcher.cs | 2 +- .../Objects/Drawables/CaughtObject.cs | 83 +++++++++++++++++++ .../Drawables/DrawableCatchHitObject.cs | 4 - .../Objects/Drawables/DrawableDroplet.cs | 2 - .../DrawablePalpableCatchHitObject.cs | 7 +- .../Skinning/Default/CatchHitObjectPiece.cs | 16 +++- .../Skinning/Default/FruitPiece.cs | 4 + .../Skinning/Legacy/LegacyFruitPiece.cs | 4 + .../Skinning/LegacyCatchHitObjectPiece.cs | 7 ++ osu.Game.Rulesets.Catch/UI/Catcher.cs | 76 ++++++----------- 10 files changed, 141 insertions(+), 64 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index 94cd0ec8a7..2747524503 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -275,7 +275,7 @@ namespace osu.Game.Rulesets.Catch.Tests public class TestCatcher : Catcher { - public IEnumerable CaughtObjects => this.ChildrenOfType(); + public IEnumerable CaughtObjects => this.ChildrenOfType(); public TestCatcher(Container trailsTarget, Container droppedObjectTarget, BeatmapDifficulty difficulty) : base(trailsTarget, droppedObjectTarget, difficulty) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs new file mode 100644 index 0000000000..0f3a143553 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs @@ -0,0 +1,83 @@ +// 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.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Rulesets.Catch.Skinning.Default; +using osu.Game.Skinning; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Catch.Objects.Drawables +{ + [Cached(typeof(CaughtObject))] + public abstract class CaughtObject : SkinnableDrawable + { + public readonly Bindable AccentColour = new Bindable(); + + public CatchHitObject HitObject { get; private set; } + + /// + /// Whether this hit object should stay on the catcher plate when the object is caught by the catcher. + /// + public virtual bool StaysOnPlate => true; + + public override bool RemoveWhenNotAlive => true; + + protected CaughtObject(CatchSkinComponents skinComponent, Func defaultImplementation) + : base(new CatchSkinComponent(skinComponent), defaultImplementation) + { + Anchor = Anchor.TopCentre; + Origin = Anchor.Centre; + + RelativeSizeAxes = Axes.None; + Size = new Vector2(CatchHitObject.OBJECT_RADIUS * 2); + } + + public virtual void CopyFrom(DrawablePalpableCatchHitObject drawableObject) + { + HitObject = drawableObject.HitObject; + Scale = drawableObject.Scale / 2; + Rotation = drawableObject.Rotation; + AccentColour.Value = drawableObject.AccentColour.Value; + } + } + + public class CaughtFruit : CaughtObject + { + public readonly Bindable VisualRepresentation = new Bindable(); + + public CaughtFruit() + : base(CatchSkinComponents.Fruit, _ => new FruitPiece()) + { + } + + public override void CopyFrom(DrawablePalpableCatchHitObject drawableObject) + { + base.CopyFrom(drawableObject); + + var drawableFruit = (DrawableFruit)drawableObject; + VisualRepresentation.Value = drawableFruit.VisualRepresentation.Value; + } + } + + public class CaughtBanana : CaughtObject + { + public CaughtBanana() + : base(CatchSkinComponents.Banana, _ => new BananaPiece()) + { + } + } + + public class CaughtDroplet : CaughtObject + { + public override bool StaysOnPlate => false; + + public CaughtDroplet() + : base(CatchSkinComponents.Droplet, _ => new DropletPiece()) + { + } + } +} diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs index 70efe9cf29..bfd124c691 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs @@ -50,10 +50,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables public Func CheckPosition; - public bool IsOnPlate; - - public override bool RemoveWhenNotAlive => IsOnPlate; - protected override JudgementResult CreateResult(Judgement judgement) => new CatchJudgementResult(HitObject, judgement); protected override void CheckForResult(bool userTriggered, double timeOffset) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs index d96b1c8902..c5f0bb8b18 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs @@ -11,8 +11,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables { public class DrawableDroplet : DrawablePalpableCatchHitObject { - public override bool StaysOnPlate => false; - public DrawableDroplet() : this(null) { diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs index b99710ae8e..34d9cf820e 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs @@ -24,11 +24,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables /// protected virtual float ScaleFactor => 1; - /// - /// Whether this hit object should stay on the catcher plate when the object is caught by the catcher. - /// - public virtual bool StaysOnPlate => true; - public float DisplayRadius => CatchHitObject.OBJECT_RADIUS * HitObject.Scale * ScaleFactor; protected DrawablePalpableCatchHitObject([CanBeNull] CatchHitObject h) @@ -43,7 +38,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables { XBindable.BindValueChanged(x => { - if (!IsOnPlate) X = x.NewValue; + X = x.NewValue; }, true); ScaleBindable.BindValueChanged(scale => diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs index d59b6cc0de..cb326b77e2 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs @@ -21,6 +21,10 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default [CanBeNull] protected DrawableHitObject DrawableHitObject { get; private set; } + [Resolved(canBeNull: true)] + [CanBeNull] + protected CaughtObject CaughtObject { get; private set; } + /// /// A part of this piece that will be faded out while falling in the playfield. /// @@ -45,6 +49,9 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default HyperDash.BindTo(hitObject.HyperDash); } + if (CaughtObject != null) + AccentColour.BindTo(CaughtObject.AccentColour); + HyperDash.BindValueChanged(hyper => { if (HyperBorderPiece != null) @@ -54,8 +61,13 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default protected override void Update() { - if (BorderPiece != null && DrawableHitObject?.HitObject != null) - BorderPiece.Alpha = (float)Math.Clamp((DrawableHitObject.HitObject.StartTime - Time.Current) / 500, 0, 1); + if (BorderPiece != null) + { + if (DrawableHitObject?.HitObject != null) + BorderPiece.Alpha = (float)Math.Clamp((DrawableHitObject.HitObject.StartTime - Time.Current) / 500, 0, 1); + else + BorderPiece.Alpha = 0; + } } } } diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs index 2e3803a31a..8c705cec4f 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs @@ -43,6 +43,10 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default if (fruit != null) VisualRepresentation.BindTo(fruit.VisualRepresentation); + + var caughtFruit = (CaughtFruit)CaughtObject; + if (caughtFruit != null) + VisualRepresentation.BindTo(caughtFruit.VisualRepresentation); } } } diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs index 6f93e68594..5140c62d3e 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs @@ -19,6 +19,10 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy if (fruit != null) VisualRepresentation.BindTo(fruit.VisualRepresentation); + var caughtFruit = (CaughtFruit)CaughtObject; + if (caughtFruit != null) + VisualRepresentation.BindTo(caughtFruit.VisualRepresentation); + VisualRepresentation.BindValueChanged(visual => setTexture(visual.NewValue), true); } diff --git a/osu.Game.Rulesets.Catch/Skinning/LegacyCatchHitObjectPiece.cs b/osu.Game.Rulesets.Catch/Skinning/LegacyCatchHitObjectPiece.cs index 1e68439402..9527f15ff1 100644 --- a/osu.Game.Rulesets.Catch/Skinning/LegacyCatchHitObjectPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/LegacyCatchHitObjectPiece.cs @@ -33,6 +33,10 @@ namespace osu.Game.Rulesets.Catch.Skinning [CanBeNull] protected DrawableHitObject DrawableHitObject { get; private set; } + [Resolved(canBeNull: true)] + [CanBeNull] + protected CaughtObject CaughtObject { get; private set; } + protected LegacyCatchHitObjectPiece() { RelativeSizeAxes = Axes.Both; @@ -73,6 +77,9 @@ namespace osu.Game.Rulesets.Catch.Skinning HyperDash.BindTo(hitObject.HyperDash); } + if (CaughtObject != null) + AccentColour.BindTo(CaughtObject.AccentColour); + hyperSprite.Colour = Skin.GetConfig(CatchSkinColour.HyperDashFruit)?.Value ?? Skin.GetConfig(CatchSkinColour.HyperDash)?.Value ?? Catcher.DEFAULT_HYPER_DASH_COLOUR; diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index ac0f25e21b..756582e3f2 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Catch.UI private readonly Container droppedObjectTarget; - private readonly Container caughtFruitContainer; + private readonly Container caughtFruitContainer; public CatcherAnimationState CurrentState { get; private set; } @@ -124,7 +124,7 @@ namespace osu.Game.Rulesets.Catch.UI InternalChildren = new Drawable[] { hitExplosionPool = new DrawablePool(10), - caughtFruitContainer = new Container + caughtFruitContainer = new Container { Anchor = Anchor.TopCentre, Origin = Anchor.BottomCentre, @@ -223,7 +223,7 @@ namespace osu.Game.Rulesets.Catch.UI { var positionInStack = computePositionInStack(new Vector2(palpableObject.X - X, 0), palpableObject.DisplayRadius); - placeCaughtObject(hitObject, positionInStack); + placeCaughtObject(palpableObject, positionInStack); if (hitLighting.Value) addLighting(hitObject, positionInStack.X, drawableObject.AccentColour.Value); @@ -450,21 +450,14 @@ namespace osu.Game.Rulesets.Catch.UI updateCatcher(); } - private void placeCaughtObject(PalpableCatchHitObject source, Vector2 position) + private void placeCaughtObject(DrawablePalpableCatchHitObject drawableObject, Vector2 position) { - var caughtObject = createCaughtObject(source); + var caughtObject = createCaughtObject(drawableObject.HitObject); if (caughtObject == null) return; - caughtObject.RelativePositionAxes = Axes.None; + caughtObject.CopyFrom(drawableObject); caughtObject.Position = position; - caughtObject.IsOnPlate = true; - - caughtObject.Anchor = Anchor.TopCentre; - caughtObject.Origin = Anchor.Centre; - caughtObject.Scale *= 0.5f; - caughtObject.LifetimeStart = source.StartTime; - caughtObject.LifetimeEnd = double.MaxValue; caughtFruitContainer.Add(caughtObject); @@ -500,21 +493,18 @@ namespace osu.Game.Rulesets.Catch.UI hitExplosionContainer.Add(hitExplosion); } - private DrawablePalpableCatchHitObject createCaughtObject(PalpableCatchHitObject source) + private CaughtObject createCaughtObject(PalpableCatchHitObject source) { switch (source) { - case Banana banana: - return new DrawableBanana(banana); + case Fruit _: + return new CaughtFruit(); - case Fruit fruit: - return new DrawableFruit(fruit); + case Banana _: + return new CaughtBanana(); - case TinyDroplet tiny: - return new DrawableTinyDroplet(tiny); - - case Droplet droplet: - return new DrawableDroplet(droplet); + case Droplet _: + return new CaughtDroplet(); default: return null; @@ -532,7 +522,7 @@ namespace osu.Game.Rulesets.Catch.UI drop(caughtObject, animation); } - private void removeFromPlate(DrawablePalpableCatchHitObject caughtObject, DroppedObjectAnimation animation) + private void removeFromPlate(CaughtObject caughtObject, DroppedObjectAnimation animation) { if (!caughtFruitContainer.Remove(caughtObject)) throw new InvalidOperationException("Can only drop a caught object on the plate"); @@ -542,40 +532,28 @@ namespace osu.Game.Rulesets.Catch.UI drop(caughtObject, animation); } - private void drop(DrawablePalpableCatchHitObject d, DroppedObjectAnimation animation) + private void drop(CaughtObject d, DroppedObjectAnimation animation) { var originalX = d.X * Scale.X; - var startTime = Clock.CurrentTime; d.Anchor = Anchor.TopLeft; d.Position = caughtFruitContainer.ToSpaceOfOtherDrawable(d.DrawPosition, droppedObjectTarget); - // we cannot just apply the transforms because DHO clears transforms when state is updated - d.ApplyCustomUpdateState += (o, state) => animate(o, animation, originalX, startTime); - if (d.IsLoaded) - animate(d, animation, originalX, startTime); - } - - private void animate(Drawable d, DroppedObjectAnimation animation, float originalX, double startTime) - { - using (d.BeginAbsoluteSequence(startTime)) + switch (animation) { - switch (animation) - { - case DroppedObjectAnimation.Drop: - d.MoveToY(d.Y + 75, 750, Easing.InSine); - d.FadeOut(750); - break; + case DroppedObjectAnimation.Drop: + d.MoveToY(d.Y + 75, 750, Easing.InSine); + d.FadeOut(750); + break; - case DroppedObjectAnimation.Explode: - d.MoveToY(d.Y - 50, 250, Easing.OutSine).Then().MoveToY(d.Y + 50, 500, Easing.InSine); - d.MoveToX(d.X + originalX * 6, 1000); - d.FadeOut(750); - break; - } - - d.Expire(); + case DroppedObjectAnimation.Explode: + d.MoveToY(d.Y - 50, 250, Easing.OutSine).Then().MoveToY(d.Y + 50, 500, Easing.InSine); + d.MoveToX(d.X + originalX * 6, 1000); + d.FadeOut(750); + break; } + + d.Expire(); } private enum DroppedObjectAnimation From a32dac00ddf388f2359dd97ebd23fc7faa68d687 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 21:29:03 +0900 Subject: [PATCH 06/73] Introduce IHasCatchObjectState implemented by DHO and CaughtObject --- .../Objects/Drawables/CaughtObject.cs | 31 ++++++++++--------- .../Objects/Drawables/DrawableBanana.cs | 2 +- .../Objects/Drawables/DrawableDroplet.cs | 2 +- .../Objects/Drawables/DrawableFruit.cs | 4 +-- ...s => DrawablePalpableHasCatchHitObject.cs} | 14 ++++++--- .../Objects/Drawables/IHasCatchObjectState.cs | 24 ++++++++++++++ .../Skinning/Default/CatchHitObjectPiece.cs | 31 ++++--------------- .../Skinning/Default/FruitPiece.cs | 10 ++---- .../Skinning/Legacy/LegacyFruitPiece.cs | 10 ++---- .../Skinning/LegacyCatchHitObjectPiece.cs | 23 +++----------- osu.Game.Rulesets.Catch/UI/Catcher.cs | 5 +-- 11 files changed, 70 insertions(+), 86 deletions(-) rename osu.Game.Rulesets.Catch/Objects/Drawables/{DrawablePalpableCatchHitObject.cs => DrawablePalpableHasCatchHitObject.cs} (78%) create mode 100644 osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs index 0f3a143553..d3555ea771 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs @@ -12,12 +12,12 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects.Drawables { - [Cached(typeof(CaughtObject))] - public abstract class CaughtObject : SkinnableDrawable + [Cached(typeof(IHasCatchObjectState))] + public abstract class CaughtObject : SkinnableDrawable, IHasCatchObjectState { - public readonly Bindable AccentColour = new Bindable(); - public CatchHitObject HitObject { get; private set; } + public Bindable AccentColour { get; } = new Bindable(); + public Bindable HyperDash { get; } = new Bindable(); /// /// Whether this hit object should stay on the catcher plate when the object is caught by the catcher. @@ -36,30 +36,31 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables Size = new Vector2(CatchHitObject.OBJECT_RADIUS * 2); } - public virtual void CopyFrom(DrawablePalpableCatchHitObject drawableObject) + public virtual void CopyFrom(IHasCatchObjectState objectState) { - HitObject = drawableObject.HitObject; - Scale = drawableObject.Scale / 2; - Rotation = drawableObject.Rotation; - AccentColour.Value = drawableObject.AccentColour.Value; + HitObject = objectState.HitObject; + Scale = objectState.Scale; + Rotation = objectState.Rotation; + AccentColour.Value = objectState.AccentColour.Value; + HyperDash.Value = objectState.HyperDash.Value; } } - public class CaughtFruit : CaughtObject + public class CaughtFruit : CaughtObject, IHasFruitState { - public readonly Bindable VisualRepresentation = new Bindable(); + public Bindable VisualRepresentation { get; } = new Bindable(); public CaughtFruit() : base(CatchSkinComponents.Fruit, _ => new FruitPiece()) { } - public override void CopyFrom(DrawablePalpableCatchHitObject drawableObject) + public override void CopyFrom(IHasCatchObjectState objectState) { - base.CopyFrom(drawableObject); + base.CopyFrom(objectState); - var drawableFruit = (DrawableFruit)drawableObject; - VisualRepresentation.Value = drawableFruit.VisualRepresentation.Value; + var fruitState = (IHasFruitState)objectState; + VisualRepresentation.Value = fruitState.VisualRepresentation.Value; } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs index 4bc5da2396..34d89eb188 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs @@ -9,7 +9,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Catch.Objects.Drawables { - public class DrawableBanana : DrawablePalpableCatchHitObject + public class DrawableBanana : DrawablePalpableHasCatchHitObject { public DrawableBanana() : this(null) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs index c5f0bb8b18..acdb3bb38c 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs @@ -9,7 +9,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Catch.Objects.Drawables { - public class DrawableDroplet : DrawablePalpableCatchHitObject + public class DrawableDroplet : DrawablePalpableHasCatchHitObject { public DrawableDroplet() : this(null) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs index 8135a31b43..6ec46f6535 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs @@ -10,9 +10,9 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Catch.Objects.Drawables { - public class DrawableFruit : DrawablePalpableCatchHitObject + public class DrawableFruit : DrawablePalpableHasCatchHitObject, IHasFruitState { - public readonly Bindable VisualRepresentation = new Bindable(); + public Bindable VisualRepresentation { get; } = new Bindable(); public DrawableFruit() : this(null) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableHasCatchHitObject.cs similarity index 78% rename from osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs rename to osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableHasCatchHitObject.cs index 34d9cf820e..ee893f7880 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableHasCatchHitObject.cs @@ -6,18 +6,22 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osuTK; +using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects.Drawables { - public abstract class DrawablePalpableCatchHitObject : DrawableCatchHitObject + [Cached(typeof(IHasCatchObjectState))] + public abstract class DrawablePalpableHasCatchHitObject : DrawableCatchHitObject, IHasCatchObjectState { public new PalpableCatchHitObject HitObject => (PalpableCatchHitObject)base.HitObject; - public readonly Bindable HyperDash = new Bindable(); + Bindable IHasCatchObjectState.AccentColour => AccentColour; - public readonly Bindable ScaleBindable = new Bindable(1); + public Bindable HyperDash { get; } = new Bindable(); - public readonly Bindable IndexInBeatmap = new Bindable(); + public Bindable ScaleBindable { get; } = new Bindable(1); + + public Bindable IndexInBeatmap { get; } = new Bindable(); /// /// The multiplicative factor applied to relative to scale. @@ -26,7 +30,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables public float DisplayRadius => CatchHitObject.OBJECT_RADIUS * HitObject.Scale * ScaleFactor; - protected DrawablePalpableCatchHitObject([CanBeNull] CatchHitObject h) + protected DrawablePalpableHasCatchHitObject([CanBeNull] CatchHitObject h) : base(h) { Origin = Anchor.Centre; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs new file mode 100644 index 0000000000..01d833b61a --- /dev/null +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs @@ -0,0 +1,24 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Catch.Objects.Drawables +{ + public interface IHasCatchObjectState + { + CatchHitObject HitObject { get; } + Bindable AccentColour { get; } + Bindable HyperDash { get; } + + float Rotation { get; } + Vector2 Scale { get; } + } + + public interface IHasFruitState : IHasCatchObjectState + { + Bindable VisualRepresentation { get; } + } +} diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs index cb326b77e2..b105fb4034 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs @@ -7,7 +7,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Game.Rulesets.Catch.Objects.Drawables; -using osu.Game.Rulesets.Objects.Drawables; using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Skinning.Default @@ -17,13 +16,8 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default public readonly Bindable AccentColour = new Bindable(); public readonly Bindable HyperDash = new Bindable(); - [Resolved(canBeNull: true)] - [CanBeNull] - protected DrawableHitObject DrawableHitObject { get; private set; } - - [Resolved(canBeNull: true)] - [CanBeNull] - protected CaughtObject CaughtObject { get; private set; } + [Resolved] + protected IHasCatchObjectState ObjectState { get; private set; } /// /// A part of this piece that will be faded out while falling in the playfield. @@ -41,16 +35,8 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default { base.LoadComplete(); - var hitObject = (DrawablePalpableCatchHitObject)DrawableHitObject; - - if (hitObject != null) - { - AccentColour.BindTo(hitObject.AccentColour); - HyperDash.BindTo(hitObject.HyperDash); - } - - if (CaughtObject != null) - AccentColour.BindTo(CaughtObject.AccentColour); + AccentColour.BindTo(ObjectState.AccentColour); + HyperDash.BindTo(ObjectState.HyperDash); HyperDash.BindValueChanged(hyper => { @@ -61,13 +47,8 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default protected override void Update() { - if (BorderPiece != null) - { - if (DrawableHitObject?.HitObject != null) - BorderPiece.Alpha = (float)Math.Clamp((DrawableHitObject.HitObject.StartTime - Time.Current) / 500, 0, 1); - else - BorderPiece.Alpha = 0; - } + if (BorderPiece != null && ObjectState?.HitObject != null) + BorderPiece.Alpha = (float)Math.Clamp((ObjectState.HitObject.StartTime - Time.Current) / 500, 0, 1); } } } diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs index 8c705cec4f..49f128c960 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/FruitPiece.cs @@ -39,14 +39,8 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default { base.LoadComplete(); - var fruit = (DrawableFruit)DrawableHitObject; - - if (fruit != null) - VisualRepresentation.BindTo(fruit.VisualRepresentation); - - var caughtFruit = (CaughtFruit)CaughtObject; - if (caughtFruit != null) - VisualRepresentation.BindTo(caughtFruit.VisualRepresentation); + var fruitState = (IHasFruitState)ObjectState; + VisualRepresentation.BindTo(fruitState.VisualRepresentation); } } } diff --git a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs index 5140c62d3e..969cc38e5b 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Legacy/LegacyFruitPiece.cs @@ -14,14 +14,8 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy { base.LoadComplete(); - var fruit = (DrawableFruit)DrawableHitObject; - - if (fruit != null) - VisualRepresentation.BindTo(fruit.VisualRepresentation); - - var caughtFruit = (CaughtFruit)CaughtObject; - if (caughtFruit != null) - VisualRepresentation.BindTo(caughtFruit.VisualRepresentation); + var fruitState = (IHasFruitState)ObjectState; + VisualRepresentation.BindTo(fruitState.VisualRepresentation); VisualRepresentation.BindValueChanged(visual => setTexture(visual.NewValue), true); } diff --git a/osu.Game.Rulesets.Catch/Skinning/LegacyCatchHitObjectPiece.cs b/osu.Game.Rulesets.Catch/Skinning/LegacyCatchHitObjectPiece.cs index 9527f15ff1..4b1f5a4724 100644 --- a/osu.Game.Rulesets.Catch/Skinning/LegacyCatchHitObjectPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/LegacyCatchHitObjectPiece.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 JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -10,7 +9,6 @@ using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Rulesets.Catch.UI; -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Skinning; using osuTK; using osuTK.Graphics; @@ -29,13 +27,8 @@ namespace osu.Game.Rulesets.Catch.Skinning [Resolved] protected ISkinSource Skin { get; private set; } - [Resolved(canBeNull: true)] - [CanBeNull] - protected DrawableHitObject DrawableHitObject { get; private set; } - - [Resolved(canBeNull: true)] - [CanBeNull] - protected CaughtObject CaughtObject { get; private set; } + [Resolved] + protected IHasCatchObjectState ObjectState { get; private set; } protected LegacyCatchHitObjectPiece() { @@ -69,16 +62,8 @@ namespace osu.Game.Rulesets.Catch.Skinning { base.LoadComplete(); - var hitObject = (DrawablePalpableCatchHitObject)DrawableHitObject; - - if (hitObject != null) - { - AccentColour.BindTo(hitObject.AccentColour); - HyperDash.BindTo(hitObject.HyperDash); - } - - if (CaughtObject != null) - AccentColour.BindTo(CaughtObject.AccentColour); + AccentColour.BindTo(ObjectState.AccentColour); + HyperDash.BindTo(ObjectState.HyperDash); hyperSprite.Colour = Skin.GetConfig(CatchSkinColour.HyperDashFruit)?.Value ?? Skin.GetConfig(CatchSkinColour.HyperDash)?.Value ?? diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 756582e3f2..4d540bce03 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -215,7 +215,7 @@ namespace osu.Game.Rulesets.Catch.UI catchResult.CatcherAnimationState = CurrentState; catchResult.CatcherHyperDash = HyperDashing; - if (!(drawableObject is DrawablePalpableCatchHitObject palpableObject)) return; + if (!(drawableObject is DrawablePalpableHasCatchHitObject palpableObject)) return; var hitObject = palpableObject.HitObject; @@ -450,7 +450,7 @@ namespace osu.Game.Rulesets.Catch.UI updateCatcher(); } - private void placeCaughtObject(DrawablePalpableCatchHitObject drawableObject, Vector2 position) + private void placeCaughtObject(DrawablePalpableHasCatchHitObject drawableObject, Vector2 position) { var caughtObject = createCaughtObject(drawableObject.HitObject); @@ -458,6 +458,7 @@ namespace osu.Game.Rulesets.Catch.UI caughtObject.CopyFrom(drawableObject); caughtObject.Position = position; + caughtObject.Scale /= 2; caughtFruitContainer.Add(caughtObject); From 749d5380ca5a1c5bd118307e4f9459cd7df00130 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 22:38:10 +0900 Subject: [PATCH 07/73] Pool caught objects and dropped objects --- .../TestSceneCatcherArea.cs | 5 +- .../Objects/Drawables/CaughtObject.cs | 14 ++++- .../Objects/Drawables/IHasCatchObjectState.cs | 2 +- osu.Game.Rulesets.Catch/UI/Catcher.cs | 52 +++++++++++++------ 4 files changed, 53 insertions(+), 20 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs index 8602c7aad1..3d5e44476e 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs @@ -73,7 +73,10 @@ namespace osu.Game.Rulesets.Catch.Tests SetContents(() => { - var droppedObjectContainer = new Container(); + var droppedObjectContainer = new Container + { + RelativeSizeAxes = Axes.Both + }; return new CatchInputManager(catchRuleset) { diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs index d3555ea771..f36d287126 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables [Cached(typeof(IHasCatchObjectState))] public abstract class CaughtObject : SkinnableDrawable, IHasCatchObjectState { - public CatchHitObject HitObject { get; private set; } + public PalpableCatchHitObject HitObject { get; private set; } public Bindable AccentColour { get; } = new Bindable(); public Bindable HyperDash { get; } = new Bindable(); @@ -29,7 +29,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables protected CaughtObject(CatchSkinComponents skinComponent, Func defaultImplementation) : base(new CatchSkinComponent(skinComponent), defaultImplementation) { - Anchor = Anchor.TopCentre; Origin = Anchor.Centre; RelativeSizeAxes = Axes.None; @@ -44,6 +43,17 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables AccentColour.Value = objectState.AccentColour.Value; HyperDash.Value = objectState.HyperDash.Value; } + + protected override void FreeAfterUse() + { + ClearTransforms(); + + Alpha = 1; + LifetimeStart = double.MinValue; + LifetimeEnd = double.MaxValue; + + base.FreeAfterUse(); + } } public class CaughtFruit : CaughtObject, IHasFruitState diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs index 01d833b61a..a282bc5da0 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs @@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables { public interface IHasCatchObjectState { - CatchHitObject HitObject { get; } + PalpableCatchHitObject HitObject { get; } Bindable AccentColour { get; } Bindable HyperDash { get; } diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 4d540bce03..7aecd95efd 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -108,6 +108,10 @@ namespace osu.Game.Rulesets.Catch.UI private readonly DrawablePool hitExplosionPool; private readonly Container hitExplosionContainer; + private readonly DrawablePool caughtFruitPool; + private readonly DrawablePool caughtBananaPool; + private readonly DrawablePool caughtDropletPool; + public Catcher([NotNull] Container trailsTarget, [NotNull] Container droppedObjectTarget, BeatmapDifficulty difficulty = null) { this.trailsTarget = trailsTarget; @@ -124,6 +128,10 @@ namespace osu.Game.Rulesets.Catch.UI InternalChildren = new Drawable[] { hitExplosionPool = new DrawablePool(10), + caughtFruitPool = new DrawablePool(50), + caughtBananaPool = new DrawablePool(100), + // less capacity is needed compared to fruit because droplet is not stacked + caughtDropletPool = new DrawablePool(25), caughtFruitContainer = new Container { Anchor = Anchor.TopCentre, @@ -452,11 +460,12 @@ namespace osu.Game.Rulesets.Catch.UI private void placeCaughtObject(DrawablePalpableHasCatchHitObject drawableObject, Vector2 position) { - var caughtObject = createCaughtObject(drawableObject.HitObject); + var caughtObject = getCaughtObject(drawableObject.HitObject); if (caughtObject == null) return; caughtObject.CopyFrom(drawableObject); + caughtObject.Anchor = Anchor.TopCentre; caughtObject.Position = position; caughtObject.Scale /= 2; @@ -494,52 +503,62 @@ namespace osu.Game.Rulesets.Catch.UI hitExplosionContainer.Add(hitExplosion); } - private CaughtObject createCaughtObject(PalpableCatchHitObject source) + private CaughtObject getCaughtObject(PalpableCatchHitObject source) { switch (source) { case Fruit _: - return new CaughtFruit(); + return caughtFruitPool.Get(); case Banana _: - return new CaughtBanana(); + return caughtBananaPool.Get(); case Droplet _: - return new CaughtDroplet(); + return caughtDropletPool.Get(); default: return null; } } + private CaughtObject getDroppedObject(CaughtObject caughtObject) + { + var droppedObject = getCaughtObject(caughtObject.HitObject); + + droppedObject.CopyFrom(caughtObject); + droppedObject.Anchor = Anchor.TopLeft; + droppedObject.Position = caughtFruitContainer.ToSpaceOfOtherDrawable(caughtObject.DrawPosition, droppedObjectTarget); + + return droppedObject; + } + private void clearPlate(DroppedObjectAnimation animation) { var caughtObjects = caughtFruitContainer.Children.ToArray(); + var droppedObjects = caughtObjects.Select(getDroppedObject).ToArray(); + caughtFruitContainer.Clear(false); - droppedObjectTarget.AddRange(caughtObjects); + droppedObjectTarget.AddRange(droppedObjects); - foreach (var caughtObject in caughtObjects) - drop(caughtObject, animation); + foreach (var droppedObject in droppedObjects) + applyDropAnimation(droppedObject, animation); } private void removeFromPlate(CaughtObject caughtObject, DroppedObjectAnimation animation) { + var droppedObject = getDroppedObject(caughtObject); + if (!caughtFruitContainer.Remove(caughtObject)) throw new InvalidOperationException("Can only drop a caught object on the plate"); - droppedObjectTarget.Add(caughtObject); + droppedObjectTarget.Add(droppedObject); - drop(caughtObject, animation); + applyDropAnimation(droppedObject, animation); } - private void drop(CaughtObject d, DroppedObjectAnimation animation) + private void applyDropAnimation(Drawable d, DroppedObjectAnimation animation) { - var originalX = d.X * Scale.X; - - d.Anchor = Anchor.TopLeft; - d.Position = caughtFruitContainer.ToSpaceOfOtherDrawable(d.DrawPosition, droppedObjectTarget); - switch (animation) { case DroppedObjectAnimation.Drop: @@ -548,6 +567,7 @@ namespace osu.Game.Rulesets.Catch.UI break; case DroppedObjectAnimation.Explode: + var originalX = droppedObjectTarget.ToSpaceOfOtherDrawable(d.DrawPosition, caughtFruitContainer).X * Scale.X; d.MoveToY(d.Y - 50, 250, Easing.OutSine).Then().MoveToY(d.Y + 50, 500, Easing.InSine); d.MoveToX(d.X + originalX * 6, 1000); d.FadeOut(750); From 1f36bbecd180049026e62f592201434c3cf2c283 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 23:07:30 +0900 Subject: [PATCH 08/73] Fix dropped objects not removed on revert result --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 7aecd95efd..d2930af1ca 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -274,7 +274,7 @@ namespace osu.Game.Rulesets.Catch.UI } caughtFruitContainer.RemoveAll(d => d.HitObject == drawableObject.HitObject); - droppedObjectTarget.RemoveAll(d => (d as DrawableCatchHitObject)?.HitObject == drawableObject.HitObject); + droppedObjectTarget.RemoveAll(d => (d as CaughtObject)?.HitObject == drawableObject.HitObject); hitExplosionContainer.RemoveAll(d => d.HitObject == drawableObject.HitObject); } From 5ca98b00334946cf1f0e0a876cd268374f3a7267 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 23:11:22 +0900 Subject: [PATCH 09/73] Add doc comments a bit --- osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs | 3 +++ .../Objects/Drawables/IHasCatchObjectState.cs | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs index f36d287126..01bf943e1a 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs @@ -12,6 +12,9 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects.Drawables { + /// + /// Represents a caught by the catcher. + /// [Cached(typeof(IHasCatchObjectState))] public abstract class CaughtObject : SkinnableDrawable, IHasCatchObjectState { diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs index a282bc5da0..0a75fb2224 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs @@ -7,6 +7,9 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects.Drawables { + /// + /// Provides a visual state of a . + /// public interface IHasCatchObjectState { PalpableCatchHitObject HitObject { get; } @@ -17,6 +20,9 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables Vector2 Scale { get; } } + /// + /// Provides a visual state of a . + /// public interface IHasFruitState : IHasCatchObjectState { Bindable VisualRepresentation { get; } From 1212ffd24f7c6aae776b796fdab47dec3673d2e8 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Tue, 8 Dec 2020 23:35:24 +0900 Subject: [PATCH 10/73] Rename to CopyStateFrom, and add comment --- .../Objects/Drawables/CaughtObject.cs | 9 ++++++--- osu.Game.Rulesets.Catch/UI/Catcher.cs | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs index 01bf943e1a..87319a4498 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs @@ -38,7 +38,10 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables Size = new Vector2(CatchHitObject.OBJECT_RADIUS * 2); } - public virtual void CopyFrom(IHasCatchObjectState objectState) + /// + /// Copies the hit object visual state from another object. + /// + public virtual void CopyStateFrom(IHasCatchObjectState objectState) { HitObject = objectState.HitObject; Scale = objectState.Scale; @@ -68,9 +71,9 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables { } - public override void CopyFrom(IHasCatchObjectState objectState) + public override void CopyStateFrom(IHasCatchObjectState objectState) { - base.CopyFrom(objectState); + base.CopyStateFrom(objectState); var fruitState = (IHasFruitState)objectState; VisualRepresentation.Value = fruitState.VisualRepresentation.Value; diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index d2930af1ca..c9580ca5f8 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -464,7 +464,7 @@ namespace osu.Game.Rulesets.Catch.UI if (caughtObject == null) return; - caughtObject.CopyFrom(drawableObject); + caughtObject.CopyStateFrom(drawableObject); caughtObject.Anchor = Anchor.TopCentre; caughtObject.Position = position; caughtObject.Scale /= 2; @@ -525,7 +525,7 @@ namespace osu.Game.Rulesets.Catch.UI { var droppedObject = getCaughtObject(caughtObject.HitObject); - droppedObject.CopyFrom(caughtObject); + droppedObject.CopyStateFrom(caughtObject); droppedObject.Anchor = Anchor.TopLeft; droppedObject.Position = caughtFruitContainer.ToSpaceOfOtherDrawable(caughtObject.DrawPosition, droppedObjectTarget); From b80204642e52a31163805731db903d1327419a49 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 9 Dec 2020 10:25:35 +0900 Subject: [PATCH 11/73] Revert rename error --- osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs | 2 +- osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs | 2 +- osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs | 2 +- ...HasCatchHitObject.cs => DrawablePalpableCatchHitObject.cs} | 4 ++-- osu.Game.Rulesets.Catch/UI/Catcher.cs | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) rename osu.Game.Rulesets.Catch/Objects/Drawables/{DrawablePalpableHasCatchHitObject.cs => DrawablePalpableCatchHitObject.cs} (92%) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs index 34d89eb188..4bc5da2396 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs @@ -9,7 +9,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Catch.Objects.Drawables { - public class DrawableBanana : DrawablePalpableHasCatchHitObject + public class DrawableBanana : DrawablePalpableCatchHitObject { public DrawableBanana() : this(null) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs index acdb3bb38c..c5f0bb8b18 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs @@ -9,7 +9,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Catch.Objects.Drawables { - public class DrawableDroplet : DrawablePalpableHasCatchHitObject + public class DrawableDroplet : DrawablePalpableCatchHitObject { public DrawableDroplet() : this(null) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs index 6ec46f6535..57f27d01b8 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs @@ -10,7 +10,7 @@ using osu.Game.Skinning; namespace osu.Game.Rulesets.Catch.Objects.Drawables { - public class DrawableFruit : DrawablePalpableHasCatchHitObject, IHasFruitState + public class DrawableFruit : DrawablePalpableCatchHitObject, IHasFruitState { public Bindable VisualRepresentation { get; } = new Bindable(); diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableHasCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs similarity index 92% rename from osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableHasCatchHitObject.cs rename to osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs index ee893f7880..aea9d2c082 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableHasCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs @@ -11,7 +11,7 @@ using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects.Drawables { [Cached(typeof(IHasCatchObjectState))] - public abstract class DrawablePalpableHasCatchHitObject : DrawableCatchHitObject, IHasCatchObjectState + public abstract class DrawablePalpableCatchHitObject : DrawableCatchHitObject, IHasCatchObjectState { public new PalpableCatchHitObject HitObject => (PalpableCatchHitObject)base.HitObject; @@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables public float DisplayRadius => CatchHitObject.OBJECT_RADIUS * HitObject.Scale * ScaleFactor; - protected DrawablePalpableHasCatchHitObject([CanBeNull] CatchHitObject h) + protected DrawablePalpableCatchHitObject([CanBeNull] CatchHitObject h) : base(h) { Origin = Anchor.Centre; diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index c9580ca5f8..30a5832c4f 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -223,7 +223,7 @@ namespace osu.Game.Rulesets.Catch.UI catchResult.CatcherAnimationState = CurrentState; catchResult.CatcherHyperDash = HyperDashing; - if (!(drawableObject is DrawablePalpableHasCatchHitObject palpableObject)) return; + if (!(drawableObject is DrawablePalpableCatchHitObject palpableObject)) return; var hitObject = palpableObject.HitObject; @@ -458,7 +458,7 @@ namespace osu.Game.Rulesets.Catch.UI updateCatcher(); } - private void placeCaughtObject(DrawablePalpableHasCatchHitObject drawableObject, Vector2 position) + private void placeCaughtObject(DrawablePalpableCatchHitObject drawableObject, Vector2 position) { var caughtObject = getCaughtObject(drawableObject.HitObject); From df9de7a8ddee1986df712deb138c7d4238f41bed Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 9 Dec 2020 10:28:42 +0900 Subject: [PATCH 12/73] Remove null check that is not required anymore --- osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs b/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs index b105fb4034..51c06c8e37 100644 --- a/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs +++ b/osu.Game.Rulesets.Catch/Skinning/Default/CatchHitObjectPiece.cs @@ -47,7 +47,7 @@ namespace osu.Game.Rulesets.Catch.Skinning.Default protected override void Update() { - if (BorderPiece != null && ObjectState?.HitObject != null) + if (BorderPiece != null) BorderPiece.Alpha = (float)Math.Clamp((ObjectState.HitObject.StartTime - Time.Current) / 500, 0, 1); } } From ccca7e0b25a97f52d9ef6d754d2f39fe6132a65b Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 9 Dec 2020 10:35:01 +0900 Subject: [PATCH 13/73] more specific type droppedObjectContainer --- osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs | 6 +++--- .../TestSceneCatcherArea.cs | 4 ++-- .../TestSceneHyperDashColouring.cs | 2 +- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 2 +- osu.Game.Rulesets.Catch/UI/Catcher.cs | 14 ++++++++++---- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- 6 files changed, 18 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index 2747524503..e8bb57cdf3 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Catch.Tests [Resolved] private OsuConfigManager config { get; set; } - private Container droppedObjectContainer; + private Container droppedObjectContainer; private TestCatcher catcher; @@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Catch.Tests }; var trailContainer = new Container(); - droppedObjectContainer = new Container(); + droppedObjectContainer = new Container(); catcher = new TestCatcher(trailContainer, droppedObjectContainer, difficulty); Child = new Container @@ -277,7 +277,7 @@ namespace osu.Game.Rulesets.Catch.Tests { public IEnumerable CaughtObjects => this.ChildrenOfType(); - public TestCatcher(Container trailsTarget, Container droppedObjectTarget, BeatmapDifficulty difficulty) + public TestCatcher(Container trailsTarget, Container droppedObjectTarget, BeatmapDifficulty difficulty) : base(trailsTarget, droppedObjectTarget, difficulty) { } diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs index 3d5e44476e..31c285ef22 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs @@ -73,7 +73,7 @@ namespace osu.Game.Rulesets.Catch.Tests SetContents(() => { - var droppedObjectContainer = new Container + var droppedObjectContainer = new Container { RelativeSizeAxes = Axes.Both }; @@ -102,7 +102,7 @@ namespace osu.Game.Rulesets.Catch.Tests private class TestCatcherArea : CatcherArea { - public TestCatcherArea(Container droppedObjectContainer, BeatmapDifficulty beatmapDifficulty) + public TestCatcherArea(Container droppedObjectContainer, BeatmapDifficulty beatmapDifficulty) : base(droppedObjectContainer, beatmapDifficulty) { } diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs index d78dc2d2b5..683a776dcc 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDashColouring.cs @@ -118,7 +118,7 @@ namespace osu.Game.Rulesets.Catch.Tests AddStep("create hyper-dashing catcher", () => { - Child = setupSkinHierarchy(catcherArea = new CatcherArea(new Container()) + Child = setupSkinHierarchy(catcherArea = new CatcherArea(new Container()) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index fdc12bf088..73420a9eda 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Catch.UI public CatchPlayfield(BeatmapDifficulty difficulty, Func> createDrawableRepresentation) { - var droppedObjectContainer = new Container + var droppedObjectContainer = new Container { RelativeSizeAxes = Axes.Both, }; diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 30a5832c4f..2893fcee92 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -53,10 +53,16 @@ namespace osu.Game.Rulesets.Catch.UI private CatcherTrailDisplay trails; - private readonly Container droppedObjectTarget; - + /// + /// Contains caught objects on the plate. + /// private readonly Container caughtFruitContainer; + /// + /// Contains objects dropped from the plate. + /// + private readonly Container droppedObjectTarget; + public CatcherAnimationState CurrentState { get; private set; } /// @@ -112,7 +118,7 @@ namespace osu.Game.Rulesets.Catch.UI private readonly DrawablePool caughtBananaPool; private readonly DrawablePool caughtDropletPool; - public Catcher([NotNull] Container trailsTarget, [NotNull] Container droppedObjectTarget, BeatmapDifficulty difficulty = null) + public Catcher([NotNull] Container trailsTarget, [NotNull] Container droppedObjectTarget, BeatmapDifficulty difficulty = null) { this.trailsTarget = trailsTarget; this.droppedObjectTarget = droppedObjectTarget; @@ -274,7 +280,7 @@ namespace osu.Game.Rulesets.Catch.UI } caughtFruitContainer.RemoveAll(d => d.HitObject == drawableObject.HitObject); - droppedObjectTarget.RemoveAll(d => (d as CaughtObject)?.HitObject == drawableObject.HitObject); + droppedObjectTarget.RemoveAll(d => d.HitObject == drawableObject.HitObject); hitExplosionContainer.RemoveAll(d => d.HitObject == drawableObject.HitObject); } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 857d9141c9..44adbd5512 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Catch.UI public readonly Catcher MovableCatcher; private readonly CatchComboDisplay comboDisplay; - public CatcherArea(Container droppedObjectContainer, BeatmapDifficulty difficulty = null) + public CatcherArea(Container droppedObjectContainer, BeatmapDifficulty difficulty = null) { Size = new Vector2(CatchPlayfield.WIDTH, CATCHER_SIZE); Children = new Drawable[] From c8b0934573c029e7568d63927533dcbddcde9099 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 9 Dec 2020 10:35:36 +0900 Subject: [PATCH 14/73] Rename caughtFruitContainer -> caughtObjectContainer --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 2893fcee92..475fca7f1c 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Catch.UI /// /// Contains caught objects on the plate. /// - private readonly Container caughtFruitContainer; + private readonly Container caughtObjectContainer; /// /// Contains objects dropped from the plate. @@ -138,7 +138,7 @@ namespace osu.Game.Rulesets.Catch.UI caughtBananaPool = new DrawablePool(100), // less capacity is needed compared to fruit because droplet is not stacked caughtDropletPool = new DrawablePool(25), - caughtFruitContainer = new Container + caughtObjectContainer = new Container { Anchor = Anchor.TopCentre, Origin = Anchor.BottomCentre, @@ -186,7 +186,7 @@ namespace osu.Game.Rulesets.Catch.UI /// /// Creates proxied content to be displayed beneath hitobjects. /// - public Drawable CreateProxiedContent() => caughtFruitContainer.CreateProxy(); + public Drawable CreateProxiedContent() => caughtObjectContainer.CreateProxy(); /// /// Calculates the scale of the catcher based off the provided beatmap difficulty. @@ -279,7 +279,7 @@ namespace osu.Game.Rulesets.Catch.UI SetHyperDashState(); } - caughtFruitContainer.RemoveAll(d => d.HitObject == drawableObject.HitObject); + caughtObjectContainer.RemoveAll(d => d.HitObject == drawableObject.HitObject); droppedObjectTarget.RemoveAll(d => d.HitObject == drawableObject.HitObject); hitExplosionContainer.RemoveAll(d => d.HitObject == drawableObject.HitObject); } @@ -475,7 +475,7 @@ namespace osu.Game.Rulesets.Catch.UI caughtObject.Position = position; caughtObject.Scale /= 2; - caughtFruitContainer.Add(caughtObject); + caughtObjectContainer.Add(caughtObject); if (!caughtObject.StaysOnPlate) removeFromPlate(caughtObject, DroppedObjectAnimation.Explode); @@ -486,7 +486,7 @@ namespace osu.Game.Rulesets.Catch.UI const float radius_div_2 = CatchHitObject.OBJECT_RADIUS / 2; const float allowance = 10; - while (caughtFruitContainer.Any(f => Vector2Extensions.Distance(f.Position, position) < (displayRadius + radius_div_2) / (allowance / 2))) + while (caughtObjectContainer.Any(f => Vector2Extensions.Distance(f.Position, position) < (displayRadius + radius_div_2) / (allowance / 2))) { float diff = (displayRadius + radius_div_2) / allowance; @@ -533,17 +533,17 @@ namespace osu.Game.Rulesets.Catch.UI droppedObject.CopyStateFrom(caughtObject); droppedObject.Anchor = Anchor.TopLeft; - droppedObject.Position = caughtFruitContainer.ToSpaceOfOtherDrawable(caughtObject.DrawPosition, droppedObjectTarget); + droppedObject.Position = caughtObjectContainer.ToSpaceOfOtherDrawable(caughtObject.DrawPosition, droppedObjectTarget); return droppedObject; } private void clearPlate(DroppedObjectAnimation animation) { - var caughtObjects = caughtFruitContainer.Children.ToArray(); + var caughtObjects = caughtObjectContainer.Children.ToArray(); var droppedObjects = caughtObjects.Select(getDroppedObject).ToArray(); - caughtFruitContainer.Clear(false); + caughtObjectContainer.Clear(false); droppedObjectTarget.AddRange(droppedObjects); @@ -555,7 +555,7 @@ namespace osu.Game.Rulesets.Catch.UI { var droppedObject = getDroppedObject(caughtObject); - if (!caughtFruitContainer.Remove(caughtObject)) + if (!caughtObjectContainer.Remove(caughtObject)) throw new InvalidOperationException("Can only drop a caught object on the plate"); droppedObjectTarget.Add(droppedObject); @@ -573,7 +573,7 @@ namespace osu.Game.Rulesets.Catch.UI break; case DroppedObjectAnimation.Explode: - var originalX = droppedObjectTarget.ToSpaceOfOtherDrawable(d.DrawPosition, caughtFruitContainer).X * Scale.X; + var originalX = droppedObjectTarget.ToSpaceOfOtherDrawable(d.DrawPosition, caughtObjectContainer).X * Scale.X; d.MoveToY(d.Y - 50, 250, Easing.OutSine).Then().MoveToY(d.Y + 50, 500, Easing.InSine); d.MoveToX(d.X + originalX * 6, 1000); d.FadeOut(750); From 86445e7c2304eb54193c2278ac306e938b0a525e Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 9 Dec 2020 10:36:54 +0900 Subject: [PATCH 15/73] Remove unnecessary copy --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 475fca7f1c..e885881c42 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -540,8 +540,7 @@ namespace osu.Game.Rulesets.Catch.UI private void clearPlate(DroppedObjectAnimation animation) { - var caughtObjects = caughtObjectContainer.Children.ToArray(); - var droppedObjects = caughtObjects.Select(getDroppedObject).ToArray(); + var droppedObjects = caughtObjectContainer.Children.Select(getDroppedObject).ToArray(); caughtObjectContainer.Clear(false); From b52e279702a879eebd333efa734aae9b3b1a2820 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 9 Dec 2020 10:38:11 +0900 Subject: [PATCH 16/73] Reword exception message --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index e885881c42..125f735a60 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -555,7 +555,7 @@ namespace osu.Game.Rulesets.Catch.UI var droppedObject = getDroppedObject(caughtObject); if (!caughtObjectContainer.Remove(caughtObject)) - throw new InvalidOperationException("Can only drop a caught object on the plate"); + throw new InvalidOperationException("Can only drop objects that were previously caught on the plate"); droppedObjectTarget.Add(droppedObject); From da2f3d4473a0583b53cfc76671b48e209f21f321 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 9 Dec 2020 10:40:42 +0900 Subject: [PATCH 17/73] Move classes to separate files --- .../Objects/Drawables/CaughtBanana.cs | 18 +++++++++ .../Objects/Drawables/CaughtDroplet.cs | 20 ++++++++++ .../Objects/Drawables/CaughtFruit.cs | 29 +++++++++++++++ .../Objects/Drawables/CaughtObject.cs | 37 ------------------- .../Objects/Drawables/IHasCatchObjectState.cs | 8 ---- .../Objects/Drawables/IHasFruitState.cs | 15 ++++++++ 6 files changed, 82 insertions(+), 45 deletions(-) create mode 100644 osu.Game.Rulesets.Catch/Objects/Drawables/CaughtBanana.cs create mode 100644 osu.Game.Rulesets.Catch/Objects/Drawables/CaughtDroplet.cs create mode 100644 osu.Game.Rulesets.Catch/Objects/Drawables/CaughtFruit.cs create mode 100644 osu.Game.Rulesets.Catch/Objects/Drawables/IHasFruitState.cs diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtBanana.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtBanana.cs new file mode 100644 index 0000000000..8a91f82437 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtBanana.cs @@ -0,0 +1,18 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Catch.Skinning.Default; + +namespace osu.Game.Rulesets.Catch.Objects.Drawables +{ + /// + /// Represents a caught by the catcher. + /// + public class CaughtBanana : CaughtObject + { + public CaughtBanana() + : base(CatchSkinComponents.Banana, _ => new BananaPiece()) + { + } + } +} diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtDroplet.cs new file mode 100644 index 0000000000..4a3397feff --- /dev/null +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtDroplet.cs @@ -0,0 +1,20 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Catch.Skinning.Default; + +namespace osu.Game.Rulesets.Catch.Objects.Drawables +{ + /// + /// Represents a caught by the catcher. + /// + public class CaughtDroplet : CaughtObject + { + public override bool StaysOnPlate => false; + + public CaughtDroplet() + : base(CatchSkinComponents.Droplet, _ => new DropletPiece()) + { + } + } +} diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtFruit.cs new file mode 100644 index 0000000000..140b411c88 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtFruit.cs @@ -0,0 +1,29 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; +using osu.Game.Rulesets.Catch.Skinning.Default; + +namespace osu.Game.Rulesets.Catch.Objects.Drawables +{ + /// + /// Represents a caught by the catcher. + /// + public class CaughtFruit : CaughtObject, IHasFruitState + { + public Bindable VisualRepresentation { get; } = new Bindable(); + + public CaughtFruit() + : base(CatchSkinComponents.Fruit, _ => new FruitPiece()) + { + } + + public override void CopyStateFrom(IHasCatchObjectState objectState) + { + base.CopyStateFrom(objectState); + + var fruitState = (IHasFruitState)objectState; + VisualRepresentation.Value = fruitState.VisualRepresentation.Value; + } + } +} diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs index 87319a4498..e597d1a4cd 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs @@ -5,7 +5,6 @@ using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; -using osu.Game.Rulesets.Catch.Skinning.Default; using osu.Game.Skinning; using osuTK; using osuTK.Graphics; @@ -61,40 +60,4 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables base.FreeAfterUse(); } } - - public class CaughtFruit : CaughtObject, IHasFruitState - { - public Bindable VisualRepresentation { get; } = new Bindable(); - - public CaughtFruit() - : base(CatchSkinComponents.Fruit, _ => new FruitPiece()) - { - } - - public override void CopyStateFrom(IHasCatchObjectState objectState) - { - base.CopyStateFrom(objectState); - - var fruitState = (IHasFruitState)objectState; - VisualRepresentation.Value = fruitState.VisualRepresentation.Value; - } - } - - public class CaughtBanana : CaughtObject - { - public CaughtBanana() - : base(CatchSkinComponents.Banana, _ => new BananaPiece()) - { - } - } - - public class CaughtDroplet : CaughtObject - { - public override bool StaysOnPlate => false; - - public CaughtDroplet() - : base(CatchSkinComponents.Droplet, _ => new DropletPiece()) - { - } - } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs index 0a75fb2224..55ca502877 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs @@ -19,12 +19,4 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables float Rotation { get; } Vector2 Scale { get; } } - - /// - /// Provides a visual state of a . - /// - public interface IHasFruitState : IHasCatchObjectState - { - Bindable VisualRepresentation { get; } - } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/IHasFruitState.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasFruitState.cs new file mode 100644 index 0000000000..2d4de543c3 --- /dev/null +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasFruitState.cs @@ -0,0 +1,15 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Bindables; + +namespace osu.Game.Rulesets.Catch.Objects.Drawables +{ + /// + /// Provides a visual state of a . + /// + public interface IHasFruitState : IHasCatchObjectState + { + Bindable VisualRepresentation { get; } + } +} From 775c4bad973c3f9afba809851b0b63add97929a1 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 9 Dec 2020 10:47:04 +0900 Subject: [PATCH 18/73] Remove unneeded lifetime assignment --- osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs index e597d1a4cd..fb83b73212 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs @@ -52,10 +52,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables protected override void FreeAfterUse() { ClearTransforms(); - Alpha = 1; - LifetimeStart = double.MinValue; - LifetimeEnd = double.MaxValue; base.FreeAfterUse(); } From a8e2f35b622a5797837115eeef7f2b96fd4a9169 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Wed, 9 Dec 2020 10:50:35 +0900 Subject: [PATCH 19/73] Remove unneeded check of caught object removal The logic was public but now it is private so the condition is ensured by the caller --- osu.Game.Rulesets.Catch/UI/Catcher.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 125f735a60..64dacd09e6 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -554,8 +554,7 @@ namespace osu.Game.Rulesets.Catch.UI { var droppedObject = getDroppedObject(caughtObject); - if (!caughtObjectContainer.Remove(caughtObject)) - throw new InvalidOperationException("Can only drop objects that were previously caught on the plate"); + caughtObjectContainer.Remove(caughtObject); droppedObjectTarget.Add(droppedObject); From cc996ec7fcbe360b451ec786c81f6a243703af7d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 10 Dec 2020 16:32:14 +0900 Subject: [PATCH 20/73] Ensure player is consumed at the point of scheduled push running the first time --- osu.Game/Screens/Play/PlayerLoader.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 42074ac241..c26195b09c 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -274,6 +274,13 @@ namespace osu.Game.Screens.Play } } + private Player consumePlayer() + { + var consumed = player; + player = null; + return consumed; + } + private void prepareNewPlayer() { if (!this.IsCurrentScreen()) @@ -331,6 +338,8 @@ namespace osu.Game.Screens.Play scheduledPushPlayer = Scheduler.AddDelayed(() => { contentOut(); + // ensure that once we have reached this "point of no return", readyForPush will be false for all future checks (until a new player instance is prepared). + var consumedPlayer = consumePlayer(); TransformSequence pushSequence = this.Delay(250); @@ -362,8 +371,6 @@ namespace osu.Game.Screens.Play // Note that this may change if the player we load requested a re-run. ValidForResume = false; - if (player.LoadedBeatmapSuccessfully) - this.Push(player); else this.Exit(); }); @@ -373,6 +380,8 @@ namespace osu.Game.Screens.Play { Schedule(pushWhenLoaded); } + if (consumedPlayer.LoadedBeatmapSuccessfully) + this.Push(consumedPlayer); } private void cancelLoad() From 491ab7405942009e17012d326aa90ae88fea46ff Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 10 Dec 2020 16:33:28 +0900 Subject: [PATCH 21/73] Schedule pushWhenLoaded once ever Previously it was being scheduled another time each OnResume, resulting in more and more calls as a user retries the same beatmap multiple times. To simplify things I've decided to just schedule once ever. This means that on resuming there's no 400ms delay any more, but in testing this isn't really an issue (load time is still high enough that it will never really be below that anyway). Even if gameplay was to load faster, the animation should gracefully proceed. --- osu.Game/Screens/Play/PlayerLoader.cs | 95 +++++++++++++-------------- 1 file changed, 46 insertions(+), 49 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index c26195b09c..d9c7afdc3c 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -179,7 +179,10 @@ namespace osu.Game.Screens.Play contentIn(); MetadataInfo.Delay(750).FadeIn(500); - this.Delay(1800).Schedule(pushWhenLoaded); + + // after an initial delay, start the debounced load check. + // this will continue to execute even after resuming back on restart. + Scheduler.Add(new ScheduledDelegate(pushWhenLoaded, 1800, 0)); showMuteWarningIfNeeded(); } @@ -189,8 +192,6 @@ namespace osu.Game.Screens.Play base.OnResuming(last); contentIn(); - - this.Delay(400).Schedule(pushWhenLoaded); } public override void OnSuspending(IScreen next) @@ -322,66 +323,62 @@ namespace osu.Game.Screens.Play { if (!this.IsCurrentScreen()) return; - try + if (!readyForPush) { - if (!readyForPush) - { - // as the pushDebounce below has a delay, we need to keep checking and cancel a future debounce - // if we become unready for push during the delay. - cancelLoad(); - return; - } + // as the pushDebounce below has a delay, we need to keep checking and cancel a future debounce + // if we become unready for push during the delay. + cancelLoad(); + return; + } - if (scheduledPushPlayer != null) - return; + // if a push has already been scheduled, no further action is required. + // this value is reset via cancelLoad() to allow a second usage of the same PlayerLoader screen. + if (scheduledPushPlayer != null) + return; - scheduledPushPlayer = Scheduler.AddDelayed(() => - { - contentOut(); + scheduledPushPlayer = Scheduler.AddDelayed(() => + { // ensure that once we have reached this "point of no return", readyForPush will be false for all future checks (until a new player instance is prepared). var consumedPlayer = consumePlayer(); - TransformSequence pushSequence = this.Delay(250); + contentOut(); - // only show if the warning was created (i.e. the beatmap needs it) - // and this is not a restart of the map (the warning expires after first load). - if (epilepsyWarning?.IsAlive == true) - { - const double epilepsy_display_length = 3000; + TransformSequence pushSequence = this.Delay(250); - pushSequence - .Schedule(() => epilepsyWarning.State.Value = Visibility.Visible) - .TransformBindableTo(volumeAdjustment, 0.25, EpilepsyWarning.FADE_DURATION, Easing.OutQuint) - .Delay(epilepsy_display_length) - .Schedule(() => - { - epilepsyWarning.Hide(); - epilepsyWarning.Expire(); - }) - .Delay(EpilepsyWarning.FADE_DURATION); - } + // only show if the warning was created (i.e. the beatmap needs it) + // and this is not a restart of the map (the warning expires after first load). + if (epilepsyWarning?.IsAlive == true) + { + const double epilepsy_display_length = 3000; - pushSequence.Schedule(() => - { - if (!this.IsCurrentScreen()) return; + pushSequence + .Schedule(() => epilepsyWarning.State.Value = Visibility.Visible) + .TransformBindableTo(volumeAdjustment, 0.25, EpilepsyWarning.FADE_DURATION, Easing.OutQuint) + .Delay(epilepsy_display_length) + .Schedule(() => + { + epilepsyWarning.Hide(); + epilepsyWarning.Expire(); + }) + .Delay(EpilepsyWarning.FADE_DURATION); + } - LoadTask = null; + pushSequence.Schedule(() => + { + if (!this.IsCurrentScreen()) return; - // By default, we want to load the player and never be returned to. - // Note that this may change if the player we load requested a re-run. - ValidForResume = false; + LoadTask = null; + + // By default, we want to load the player and never be returned to. + // Note that this may change if the player we load requested a re-run. + ValidForResume = false; - else - this.Exit(); - }); - }, 500); - } - finally - { - Schedule(pushWhenLoaded); - } if (consumedPlayer.LoadedBeatmapSuccessfully) this.Push(consumedPlayer); + else + this.Exit(); + }); + }, 500); } private void cancelLoad() From 67dd7be71a549822b47562be9a4cfc106b338a12 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 10 Dec 2020 16:34:58 +0900 Subject: [PATCH 22/73] Move cancelLoad call to OnResuming This has no real effect; it just feels more readable to me. --- osu.Game/Screens/Play/PlayerLoader.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index d9c7afdc3c..f3575b01b4 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -191,6 +191,7 @@ namespace osu.Game.Screens.Play { base.OnResuming(last); + cancelLoad(); contentIn(); } @@ -198,8 +199,6 @@ namespace osu.Game.Screens.Play { base.OnSuspending(next); - cancelLoad(); - BackgroundBrightnessReduction = false; // we're moving to player, so a period of silence is upcoming. From 437c0506cec8ee2b2ba1ee3ed71bb57ea50dd04b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 10 Dec 2020 16:56:56 +0900 Subject: [PATCH 23/73] Refactor to allow for special disposal handling to still work --- osu.Game/Screens/Play/PlayerLoader.cs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index f3575b01b4..729119fa36 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using JetBrains.Annotations; @@ -71,8 +72,9 @@ namespace osu.Game.Screens.Play } private bool readyForPush => + !playerConsumed // don't push unless the player is completely loaded - player?.LoadState == LoadState.Ready + && player?.LoadState == LoadState.Ready // don't push if the user is hovering one of the panes, unless they are idle. && (IsHovered || idleTracker.IsIdle.Value) // don't push if the user is dragging a slider or otherwise. @@ -84,6 +86,11 @@ namespace osu.Game.Screens.Play private Player player; + /// + /// Whether the curent player instance has been consumed via . + /// + private bool playerConsumed; + private LogoTrackingContainer content; private bool hideOverlays; @@ -191,7 +198,11 @@ namespace osu.Game.Screens.Play { base.OnResuming(last); + // prepare for a retry. + player = null; + playerConsumed = false; cancelLoad(); + contentIn(); } @@ -276,9 +287,10 @@ namespace osu.Game.Screens.Play private Player consumePlayer() { - var consumed = player; - player = null; - return consumed; + Debug.Assert(!playerConsumed); + + playerConsumed = true; + return player; } private void prepareNewPlayer() @@ -395,7 +407,7 @@ namespace osu.Game.Screens.Play if (isDisposing) { // if the player never got pushed, we should explicitly dispose it. - DisposalTask = LoadTask?.ContinueWith(_ => player.Dispose()); + DisposalTask = LoadTask?.ContinueWith(_ => player?.Dispose()); } } From 679a550d833c9d6e12160c4a77ac81fa2662cca5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 10 Dec 2020 17:42:28 +0900 Subject: [PATCH 24/73] Fix single threaded seeking not working due to unnecessary seek call --- osu.Game/Screens/Play/GameplayClockContainer.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 2c83161614..5d11cdf21d 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -154,13 +154,16 @@ namespace osu.Game.Screens.Play public void Start() { - // Seeking the decoupled clock to its current time ensures that its source clock will be seeked to the same time - // This accounts for the audio clock source potentially taking time to enter a completely stopped state - Seek(GameplayClock.CurrentTime); - adjustableClock.Start(); - IsPaused.Value = false; + if (!adjustableClock.IsRunning) + { + // Seeking the decoupled clock to its current time ensures that its source clock will be seeked to the same time + // This accounts for the audio clock source potentially taking time to enter a completely stopped state + Seek(GameplayClock.CurrentTime); this.TransformBindableTo(pauseFreqAdjust, 1, 200, Easing.In); + adjustableClock.Start(); + } + IsPaused.Value = false; } /// From 01bd765384e9f9d2b61118fcab7e75132a7c3cf0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 10 Dec 2020 17:42:47 +0900 Subject: [PATCH 25/73] Simplify pause handling by moving transform logic to bindable change event --- osu.Game/Screens/Play/GameplayClockContainer.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 5d11cdf21d..0bbdc980db 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -95,6 +95,16 @@ namespace osu.Game.Screens.Play localGameplayClock = new LocalGameplayClock(userOffsetClock); GameplayClock.IsPaused.BindTo(IsPaused); + + IsPaused.BindValueChanged(onPaused); + } + + private void onPaused(ValueChangedEvent isPaused) + { + if (isPaused.NewValue) + this.TransformBindableTo(pauseFreqAdjust, 0, 200, Easing.Out).OnComplete(_ => adjustableClock.Stop()); + else + this.TransformBindableTo(pauseFreqAdjust, 1, 200, Easing.In); } private double totalOffset => userOffsetClock.Offset + platformOffsetClock.Offset; @@ -160,9 +170,9 @@ namespace osu.Game.Screens.Play // This accounts for the audio clock source potentially taking time to enter a completely stopped state Seek(GameplayClock.CurrentTime); - this.TransformBindableTo(pauseFreqAdjust, 1, 200, Easing.In); adjustableClock.Start(); } + IsPaused.Value = false; } @@ -202,8 +212,6 @@ namespace osu.Game.Screens.Play public void Stop() { - this.TransformBindableTo(pauseFreqAdjust, 0, 200, Easing.Out).OnComplete(_ => adjustableClock.Stop()); - IsPaused.Value = true; } From e097b6e61c2796f0c5071704d90b7119134fca0c Mon Sep 17 00:00:00 2001 From: ekrctb Date: Thu, 10 Dec 2020 19:42:01 +0900 Subject: [PATCH 26/73] Add ScalingContainer back Don't want to set DHO.Scale or DHO.Rotation because because DHO may be transformed by mods. DHO.Size is also assigned for drawable visualizer --- .../Objects/Drawables/CaughtObject.cs | 4 +++- .../Objects/Drawables/DrawableBanana.cs | 14 ++++++------- .../Objects/Drawables/DrawableDroplet.cs | 6 +++--- .../Objects/Drawables/DrawableFruit.cs | 6 +++--- .../DrawablePalpableCatchHitObject.cs | 20 ++++++++++++++++++- .../Objects/Drawables/IHasCatchObjectState.cs | 3 +-- 6 files changed, 36 insertions(+), 17 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs index fb83b73212..22fb338229 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs @@ -21,6 +21,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables public Bindable AccentColour { get; } = new Bindable(); public Bindable HyperDash { get; } = new Bindable(); + float IHasCatchObjectState.Scale => Scale.X; + /// /// Whether this hit object should stay on the catcher plate when the object is caught by the catcher. /// @@ -43,7 +45,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables public virtual void CopyStateFrom(IHasCatchObjectState objectState) { HitObject = objectState.HitObject; - Scale = objectState.Scale; + Scale = new Vector2(objectState.Scale); Rotation = objectState.Rotation; AccentColour.Value = objectState.AccentColour.Value; HyperDash.Value = objectState.HyperDash.Value; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs index 4bc5da2396..c1b41a7afc 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableBanana.cs @@ -24,9 +24,9 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables [BackgroundDependencyLoader] private void load() { - AddInternal(new SkinnableDrawable( + ScalingContainer.Child = new SkinnableDrawable( new CatchSkinComponent(CatchSkinComponents.Banana), - _ => new BananaPiece())); + _ => new BananaPiece()); } protected override void LoadComplete() @@ -44,12 +44,12 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables const float end_scale = 0.6f; const float random_scale_range = 1.6f; - this.ScaleTo(HitObject.Scale * (end_scale + random_scale_range * RandomSingle(3))) - .Then().ScaleTo(HitObject.Scale * end_scale, HitObject.TimePreempt); + ScalingContainer.ScaleTo(HitObject.Scale * (end_scale + random_scale_range * RandomSingle(3))) + .Then().ScaleTo(HitObject.Scale * end_scale, HitObject.TimePreempt); - this.RotateTo(getRandomAngle(1)) - .Then() - .RotateTo(getRandomAngle(2), HitObject.TimePreempt); + ScalingContainer.RotateTo(getRandomAngle(1)) + .Then() + .RotateTo(getRandomAngle(2), HitObject.TimePreempt); float getRandomAngle(int series) => 180 * (RandomSingle(series) * 2 - 1); } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs index c5f0bb8b18..2dce9507a5 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableDroplet.cs @@ -24,9 +24,9 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables [BackgroundDependencyLoader] private void load() { - AddInternal(new SkinnableDrawable( + ScalingContainer.Child = new SkinnableDrawable( new CatchSkinComponent(CatchSkinComponents.Droplet), - _ => new DropletPiece())); + _ => new DropletPiece()); } protected override void UpdateInitialTransforms() @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables float startRotation = RandomSingle(1) * 20; double duration = HitObject.TimePreempt + 2000; - this.RotateTo(startRotation).RotateTo(startRotation + 720, duration); + ScalingContainer.RotateTo(startRotation).RotateTo(startRotation + 720, duration); } } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs index 57f27d01b8..0b89c46480 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableFruit.cs @@ -32,16 +32,16 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables VisualRepresentation.Value = (FruitVisualRepresentation)(change.NewValue % 4); }, true); - AddInternal(new SkinnableDrawable( + ScalingContainer.Child = new SkinnableDrawable( new CatchSkinComponent(CatchSkinComponents.Fruit), - _ => new FruitPiece())); + _ => new FruitPiece()); } protected override void UpdateInitialTransforms() { base.UpdateInitialTransforms(); - this.RotateTo((RandomSingle(1) - 0.5f) * 40); + ScalingContainer.RotateTo((RandomSingle(1) - 0.5f) * 40); } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs index aea9d2c082..9ddf56a9cd 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs @@ -5,6 +5,7 @@ using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osuTK; using osuTK.Graphics; @@ -30,11 +31,27 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables public float DisplayRadius => CatchHitObject.OBJECT_RADIUS * HitObject.Scale * ScaleFactor; + /// + /// The container internal transforms (such as scaling based on the circle size) are applied to. + /// + protected readonly Container ScalingContainer; + + float IHasCatchObjectState.Scale => HitObject.Scale * ScaleFactor; + + float IHasCatchObjectState.Rotation => ScalingContainer.Rotation; + protected DrawablePalpableCatchHitObject([CanBeNull] CatchHitObject h) : base(h) { Origin = Anchor.Centre; Size = new Vector2(CatchHitObject.OBJECT_RADIUS * 2); + + AddInternal(ScalingContainer = new Container + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(CatchHitObject.OBJECT_RADIUS * 2) + }); } [BackgroundDependencyLoader] @@ -47,7 +64,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables ScaleBindable.BindValueChanged(scale => { - Scale = new Vector2(scale.NewValue * ScaleFactor); + ScalingContainer.Scale = new Vector2(scale.NewValue * ScaleFactor); + Size = ScalingContainer.Size * ScalingContainer.Scale; }, true); IndexInBeatmap.BindValueChanged(_ => UpdateComboColour()); diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs index 55ca502877..fac0249985 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; -using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects.Drawables @@ -17,6 +16,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables Bindable HyperDash { get; } float Rotation { get; } - Vector2 Scale { get; } + float Scale { get; } } } From 2634c6b8d9dc18f34ae7eb81dd114d36a71adb21 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Thu, 10 Dec 2020 20:43:01 +0900 Subject: [PATCH 27/73] Combine DisplayRadius and Scale to DisplaySize --- .../TestSceneFruitRandomness.cs | 23 ++++++++++--------- .../Objects/Drawables/CaughtObject.cs | 8 ++++--- .../DrawablePalpableCatchHitObject.cs | 8 +++---- .../Objects/Drawables/IHasCatchObjectState.cs | 5 ++-- osu.Game.Rulesets.Catch/UI/Catcher.cs | 2 +- 5 files changed, 24 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs index e1d817b314..c888dc0a65 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneFruitRandomness.cs @@ -5,6 +5,7 @@ using NUnit.Framework; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects.Drawables; using osu.Game.Tests.Visual; +using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Tests @@ -37,16 +38,16 @@ namespace osu.Game.Rulesets.Catch.Tests float fruitRotation = 0; float bananaRotation = 0; - float bananaScale = 0; + Vector2 bananaSize = new Vector2(); Color4 bananaColour = new Color4(); AddStep("Initialize start time", () => { drawableFruit.HitObject.StartTime = drawableBanana.HitObject.StartTime = initial_start_time; - fruitRotation = drawableFruit.Rotation; - bananaRotation = drawableBanana.Rotation; - bananaScale = drawableBanana.Scale.X; + fruitRotation = drawableFruit.DisplayRotation; + bananaRotation = drawableBanana.DisplayRotation; + bananaSize = drawableBanana.DisplaySize; bananaColour = drawableBanana.AccentColour.Value; }); @@ -55,9 +56,9 @@ namespace osu.Game.Rulesets.Catch.Tests drawableFruit.HitObject.StartTime = drawableBanana.HitObject.StartTime = another_start_time; }); - AddAssert("fruit rotation is changed", () => drawableFruit.Rotation != fruitRotation); - AddAssert("banana rotation is changed", () => drawableBanana.Rotation != bananaRotation); - AddAssert("banana scale is changed", () => drawableBanana.Scale.X != bananaScale); + AddAssert("fruit rotation is changed", () => drawableFruit.DisplayRotation != fruitRotation); + AddAssert("banana rotation is changed", () => drawableBanana.DisplayRotation != bananaRotation); + AddAssert("banana size is changed", () => drawableBanana.DisplaySize != bananaSize); AddAssert("banana colour is changed", () => drawableBanana.AccentColour.Value != bananaColour); AddStep("reset start time", () => @@ -65,10 +66,10 @@ namespace osu.Game.Rulesets.Catch.Tests drawableFruit.HitObject.StartTime = drawableBanana.HitObject.StartTime = initial_start_time; }); - AddAssert("rotation and scale restored", () => - drawableFruit.Rotation == fruitRotation && - drawableBanana.Rotation == bananaRotation && - drawableBanana.Scale.X == bananaScale && + AddAssert("rotation and size restored", () => + drawableFruit.DisplayRotation == fruitRotation && + drawableBanana.DisplayRotation == bananaRotation && + drawableBanana.DisplaySize == bananaSize && drawableBanana.AccentColour.Value == bananaColour); } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs index 22fb338229..524505d588 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/CaughtObject.cs @@ -21,7 +21,9 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables public Bindable AccentColour { get; } = new Bindable(); public Bindable HyperDash { get; } = new Bindable(); - float IHasCatchObjectState.Scale => Scale.X; + public Vector2 DisplaySize => Size * Scale; + + public float DisplayRotation => Rotation; /// /// Whether this hit object should stay on the catcher plate when the object is caught by the catcher. @@ -45,8 +47,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables public virtual void CopyStateFrom(IHasCatchObjectState objectState) { HitObject = objectState.HitObject; - Scale = new Vector2(objectState.Scale); - Rotation = objectState.Rotation; + Scale = Vector2.Divide(objectState.DisplaySize, Size); + Rotation = objectState.DisplayRotation; AccentColour.Value = objectState.AccentColour.Value; HyperDash.Value = objectState.HyperDash.Value; } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs index 9ddf56a9cd..7df06bd92d 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs @@ -29,16 +29,14 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables /// protected virtual float ScaleFactor => 1; - public float DisplayRadius => CatchHitObject.OBJECT_RADIUS * HitObject.Scale * ScaleFactor; - /// /// The container internal transforms (such as scaling based on the circle size) are applied to. /// protected readonly Container ScalingContainer; - float IHasCatchObjectState.Scale => HitObject.Scale * ScaleFactor; + public Vector2 DisplaySize => ScalingContainer.Size * ScalingContainer.Scale; - float IHasCatchObjectState.Rotation => ScalingContainer.Rotation; + public float DisplayRotation => ScalingContainer.Rotation; protected DrawablePalpableCatchHitObject([CanBeNull] CatchHitObject h) : base(h) @@ -65,7 +63,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables ScaleBindable.BindValueChanged(scale => { ScalingContainer.Scale = new Vector2(scale.NewValue * ScaleFactor); - Size = ScalingContainer.Size * ScalingContainer.Scale; + Size = DisplaySize; }, true); IndexInBeatmap.BindValueChanged(_ => UpdateComboColour()); diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs index fac0249985..d68e32aca9 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Bindables; +using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects.Drawables @@ -15,7 +16,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables Bindable AccentColour { get; } Bindable HyperDash { get; } - float Rotation { get; } - float Scale { get; } + Vector2 DisplaySize { get; } + float DisplayRotation { get; } } } diff --git a/osu.Game.Rulesets.Catch/UI/Catcher.cs b/osu.Game.Rulesets.Catch/UI/Catcher.cs index 64dacd09e6..f164c2655a 100644 --- a/osu.Game.Rulesets.Catch/UI/Catcher.cs +++ b/osu.Game.Rulesets.Catch/UI/Catcher.cs @@ -235,7 +235,7 @@ namespace osu.Game.Rulesets.Catch.UI if (result.IsHit) { - var positionInStack = computePositionInStack(new Vector2(palpableObject.X - X, 0), palpableObject.DisplayRadius); + var positionInStack = computePositionInStack(new Vector2(palpableObject.X - X, 0), palpableObject.DisplaySize.X / 2); placeCaughtObject(palpableObject, positionInStack); From b3d834731586f16cff8ea513ab1a361283b38078 Mon Sep 17 00:00:00 2001 From: Firmatorenio Date: Thu, 10 Dec 2020 20:11:08 +0600 Subject: [PATCH 28/73] add support for ScorePosition into LegacyManiaSkin --- osu.Game/Skinning/LegacyManiaSkinConfiguration.cs | 1 + osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs | 1 + osu.Game/Skinning/LegacyManiaSkinDecoder.cs | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs b/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs index 35a6140cbc..a8225a5bea 100644 --- a/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs +++ b/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs @@ -35,6 +35,7 @@ namespace osu.Game.Skinning public float HitPosition = (480 - 402) * POSITION_SCALE_FACTOR; public float LightPosition = (480 - 413) * POSITION_SCALE_FACTOR; + public float ScorePosition = (480 - 402 + 150) * POSITION_SCALE_FACTOR; public bool ShowJudgementLine = true; public bool KeysUnderNotes; diff --git a/osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs b/osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs index a99710ea96..9db6c8bf66 100644 --- a/osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs +++ b/osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs @@ -25,6 +25,7 @@ namespace osu.Game.Skinning LeftLineWidth, RightLineWidth, HitPosition, + ScorePosition, LightPosition, HitTargetImage, ShowJudgementLine, diff --git a/osu.Game/Skinning/LegacyManiaSkinDecoder.cs b/osu.Game/Skinning/LegacyManiaSkinDecoder.cs index 3dbec23194..49feb9c3f0 100644 --- a/osu.Game/Skinning/LegacyManiaSkinDecoder.cs +++ b/osu.Game/Skinning/LegacyManiaSkinDecoder.cs @@ -94,6 +94,10 @@ namespace osu.Game.Skinning currentConfig.LightPosition = (480 - float.Parse(pair.Value, CultureInfo.InvariantCulture)) * LegacyManiaSkinConfiguration.POSITION_SCALE_FACTOR; break; + case "ScorePosition": + currentConfig.ScorePosition = (480 - float.Parse(pair.Value, CultureInfo.InvariantCulture)) * LegacyManiaSkinConfiguration.POSITION_SCALE_FACTOR; + break; + case "JudgementLine": currentConfig.ShowJudgementLine = pair.Value == "1"; break; From 2dd591125673b4b4d6b130204995bfe41cf54de9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 11 Dec 2020 14:44:01 +0900 Subject: [PATCH 29/73] Rename method to better match purpose --- osu.Game/Screens/Play/GameplayClockContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 0bbdc980db..0248432917 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -96,10 +96,10 @@ namespace osu.Game.Screens.Play GameplayClock.IsPaused.BindTo(IsPaused); - IsPaused.BindValueChanged(onPaused); + IsPaused.BindValueChanged(onPauseChanged); } - private void onPaused(ValueChangedEvent isPaused) + private void onPauseChanged(ValueChangedEvent isPaused) { if (isPaused.NewValue) this.TransformBindableTo(pauseFreqAdjust, 0, 200, Easing.Out).OnComplete(_ => adjustableClock.Stop()); From c0d20d8ce430a2ee7257c7ac8cf34eeefd54489f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 11 Dec 2020 16:43:00 +0900 Subject: [PATCH 30/73] Add some spacing to interface class --- .../Objects/Drawables/IHasCatchObjectState.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs index d68e32aca9..81b61f0959 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/IHasCatchObjectState.cs @@ -13,10 +13,13 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables public interface IHasCatchObjectState { PalpableCatchHitObject HitObject { get; } + Bindable AccentColour { get; } + Bindable HyperDash { get; } Vector2 DisplaySize { get; } + float DisplayRotation { get; } } } From a35060ea7a3c7c825b826b4ad7a65a898249d8bb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 11 Dec 2020 17:56:00 +0900 Subject: [PATCH 31/73] Add a simple cache-busting query string to online.db retrieval As we are finally pushing updates for this database, this adds a minimum level of guarantee that a client will request a new version (without having to worry about multiple levels of server-side caching). --- osu.Game/Beatmaps/BeatmapManager_BeatmapOnlineLookupQueue.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapManager_BeatmapOnlineLookupQueue.cs b/osu.Game/Beatmaps/BeatmapManager_BeatmapOnlineLookupQueue.cs index c4563d5844..e90ccbb805 100644 --- a/osu.Game/Beatmaps/BeatmapManager_BeatmapOnlineLookupQueue.cs +++ b/osu.Game/Beatmaps/BeatmapManager_BeatmapOnlineLookupQueue.cs @@ -104,7 +104,7 @@ namespace osu.Game.Beatmaps string cacheFilePath = storage.GetFullPath(cache_database_name); string compressedCacheFilePath = $"{cacheFilePath}.bz2"; - cacheDownloadRequest = new FileWebRequest(compressedCacheFilePath, $"https://assets.ppy.sh/client-resources/{cache_database_name}.bz2"); + cacheDownloadRequest = new FileWebRequest(compressedCacheFilePath, $"https://assets.ppy.sh/client-resources/{cache_database_name}.bz2?{DateTimeOffset.UtcNow:yyyyMMdd}"); cacheDownloadRequest.Failed += ex => { From b5f6baf3412128bc142d966affffc433abfbe490 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 11 Dec 2020 18:03:48 +0900 Subject: [PATCH 32/73] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 9a3d42d6b7..e0bf1867b9 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,6 +52,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 9d37ceee6c..bd8a7c73b2 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index ab03393836..c5e7c45eda 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -88,7 +88,7 @@ - + From f20c5a2bda5f3d4a199af516e22b8caf1e97526a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 12 Dec 2020 15:29:21 +0900 Subject: [PATCH 33/73] Update framework (again) --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index e0bf1867b9..eaedcb7bc3 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,6 +52,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index bd8a7c73b2..b4c7dca12f 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index c5e7c45eda..7542aded86 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -88,7 +88,7 @@ - + From 8292c746ea82e35412f717fe8d6db6921661e54e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 12 Dec 2020 22:42:40 +0100 Subject: [PATCH 34/73] Leverage hitobject model for strong hit instead of creating own --- osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs index e4c0766844..c1b422452e 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Utils; @@ -9,7 +10,6 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Objects; @@ -126,7 +126,7 @@ namespace osu.Game.Rulesets.Taiko.Tests var cpi = new ControlPointInfo(); cpi.Add(0, new EffectControlPoint { KiaiMode = kiai }); - Hit hit = new Hit(); + Hit hit = new Hit { IsStrong = true }; hit.ApplyDefaults(cpi, new BeatmapDifficulty()); var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Ok ? -0.1f : -0.05f, hitResult == HitResult.Ok ? 0.1f : 0.05f) }; @@ -134,7 +134,7 @@ namespace osu.Game.Rulesets.Taiko.Tests DrawableRuleset.Playfield.Add(h); ((TaikoPlayfield)DrawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new HitObject(), new TaikoJudgement()) { Type = hitResult }); - ((TaikoPlayfield)DrawableRuleset.Playfield).OnNewResult(new TestStrongNestedHit(h), new JudgementResult(new HitObject(), new TaikoStrongJudgement()) { Type = HitResult.Great }); + ((TaikoPlayfield)DrawableRuleset.Playfield).OnNewResult(h.NestedHitObjects.Single(), new JudgementResult(new HitObject(), new TaikoStrongJudgement()) { Type = HitResult.Great }); } private void addMissJudgement() @@ -210,15 +210,5 @@ namespace osu.Game.Rulesets.Taiko.Tests DrawableRuleset.Playfield.Add(new DrawableHit(h)); } - - private class TestStrongNestedHit : DrawableStrongNestedHit - { - public TestStrongNestedHit(DrawableHitObject mainObject) - : base(new StrongHitObject { StartTime = mainObject.HitObject.StartTime }, mainObject) - { - } - - public override bool OnPressed(TaikoAction action) => false; - } } } From 34e7a36b382ba88d4e2ae74fceb8ad7833133090 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 12 Dec 2020 22:48:22 +0100 Subject: [PATCH 35/73] Fix kiai hit steps not working correctly --- osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs | 7 +++++-- osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs | 14 ++------------ 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs b/osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs index fb0917341e..f048cad18c 100644 --- a/osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs +++ b/osu.Game.Rulesets.Taiko.Tests/DrawableTestHit.cs @@ -13,12 +13,15 @@ namespace osu.Game.Rulesets.Taiko.Tests { public readonly HitResult Type; - public DrawableTestHit(Hit hit, HitResult type = HitResult.Great) + public DrawableTestHit(Hit hit, HitResult type = HitResult.Great, bool kiai = false) : base(hit) { Type = type; - HitObject.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); + var controlPoints = new ControlPointInfo(); + controlPoints.Add(0, new EffectControlPoint { KiaiMode = kiai }); + + HitObject.ApplyDefaults(controlPoints, new BeatmapDifficulty()); } protected override void UpdateInitialTransforms() diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs index c1b422452e..14a127ac82 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs @@ -106,13 +106,8 @@ namespace osu.Game.Rulesets.Taiko.Tests { HitResult hitResult = RNG.Next(2) == 0 ? HitResult.Ok : HitResult.Great; - var cpi = new ControlPointInfo(); - cpi.Add(0, new EffectControlPoint { KiaiMode = kiai }); - Hit hit = new Hit(); - hit.ApplyDefaults(cpi, new BeatmapDifficulty()); - - var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Ok ? -0.1f : -0.05f, hitResult == HitResult.Ok ? 0.1f : 0.05f) }; + var h = new DrawableTestHit(hit, kiai: kiai) { X = RNG.NextSingle(hitResult == HitResult.Ok ? -0.1f : -0.05f, hitResult == HitResult.Ok ? 0.1f : 0.05f) }; DrawableRuleset.Playfield.Add(h); @@ -123,13 +118,8 @@ namespace osu.Game.Rulesets.Taiko.Tests { HitResult hitResult = RNG.Next(2) == 0 ? HitResult.Ok : HitResult.Great; - var cpi = new ControlPointInfo(); - cpi.Add(0, new EffectControlPoint { KiaiMode = kiai }); - Hit hit = new Hit { IsStrong = true }; - hit.ApplyDefaults(cpi, new BeatmapDifficulty()); - - var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Ok ? -0.1f : -0.05f, hitResult == HitResult.Ok ? 0.1f : 0.05f) }; + var h = new DrawableTestHit(hit, kiai: kiai) { X = RNG.NextSingle(hitResult == HitResult.Ok ? -0.1f : -0.05f, hitResult == HitResult.Ok ? 0.1f : 0.05f) }; DrawableRuleset.Playfield.Add(h); From 76193e221754455ac9638f7974437c2259b9fc5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 12 Dec 2020 22:52:01 +0100 Subject: [PATCH 36/73] Fix miss step not working --- osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs index 14a127ac82..d257712553 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs @@ -130,8 +130,11 @@ namespace osu.Game.Rulesets.Taiko.Tests private void addMissJudgement() { DrawableTestHit h; - DrawableRuleset.Playfield.Add(h = new DrawableTestHit(new Hit(), HitResult.Miss)); - ((TaikoPlayfield)DrawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new HitObject(), new TaikoJudgement()) { Type = HitResult.Miss }); + DrawableRuleset.Playfield.Add(h = new DrawableTestHit(new Hit { StartTime = DrawableRuleset.Playfield.Time.Current }, HitResult.Miss) + { + Alpha = 0 + }); + ((TaikoPlayfield)DrawableRuleset.Playfield).OnNewResult(h, new JudgementResult(h.HitObject, new TaikoJudgement()) { Type = HitResult.Miss }); } private void addBarLine(bool major, double delay = scroll_time) From 43c0e2191deaad07687704619d69b2c10056c0a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 12 Dec 2020 23:50:12 +0100 Subject: [PATCH 37/73] Apply local fix for strong/colour not being applied correctly --- .../TestSceneHits.cs | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs index d257712553..1d51020a6f 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs @@ -2,10 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; using osu.Framework.Utils; +using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; @@ -118,7 +120,11 @@ namespace osu.Game.Rulesets.Taiko.Tests { HitResult hitResult = RNG.Next(2) == 0 ? HitResult.Ok : HitResult.Great; - Hit hit = new Hit { IsStrong = true }; + Hit hit = new Hit + { + IsStrong = true, + Samples = createSamples(strong: true) + }; var h = new DrawableTestHit(hit, kiai: kiai) { X = RNG.NextSingle(hitResult == HitResult.Ok ? -0.1f : -0.05f, hitResult == HitResult.Ok ? 0.1f : 0.05f) }; DrawableRuleset.Playfield.Add(h); @@ -166,6 +172,7 @@ namespace osu.Game.Rulesets.Taiko.Tests { StartTime = DrawableRuleset.Playfield.Time.Current + scroll_time, IsStrong = strong, + Samples = createSamples(strong: strong), Duration = duration, TickRate = 8, }; @@ -183,7 +190,8 @@ namespace osu.Game.Rulesets.Taiko.Tests Hit h = new Hit { StartTime = DrawableRuleset.Playfield.Time.Current + scroll_time, - IsStrong = strong + IsStrong = strong, + Samples = createSamples(HitType.Centre, strong) }; h.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); @@ -196,12 +204,27 @@ namespace osu.Game.Rulesets.Taiko.Tests Hit h = new Hit { StartTime = DrawableRuleset.Playfield.Time.Current + scroll_time, - IsStrong = strong + IsStrong = strong, + Samples = createSamples(HitType.Rim, strong) }; h.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty()); DrawableRuleset.Playfield.Add(new DrawableHit(h)); } + + // TODO: can be removed if a better way of handling colour/strong type and samples is developed + private IList createSamples(HitType? hitType = null, bool strong = false) + { + var samples = new List(); + + if (hitType == HitType.Rim) + samples.Add(new HitSampleInfo(HitSampleInfo.HIT_CLAP)); + + if (strong) + samples.Add(new HitSampleInfo(HitSampleInfo.HIT_FINISH)); + + return samples; + } } } From 3a3b32186ee62acc40a66f9047a777d4d2b72b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 13 Dec 2020 00:00:37 +0100 Subject: [PATCH 38/73] Make height test steps work better --- .../DrawableTaikoRulesetTestScene.cs | 8 +++++--- osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Taiko.Tests/DrawableTaikoRulesetTestScene.cs b/osu.Game.Rulesets.Taiko.Tests/DrawableTaikoRulesetTestScene.cs index d1c4a1c56d..783636a62d 100644 --- a/osu.Game.Rulesets.Taiko.Tests/DrawableTaikoRulesetTestScene.cs +++ b/osu.Game.Rulesets.Taiko.Tests/DrawableTaikoRulesetTestScene.cs @@ -16,6 +16,8 @@ namespace osu.Game.Rulesets.Taiko.Tests { public abstract class DrawableTaikoRulesetTestScene : OsuTestScene { + protected const int DEFAULT_PLAYFIELD_CONTAINER_HEIGHT = 768; + protected DrawableTaikoRuleset DrawableRuleset { get; private set; } protected Container PlayfieldContainer { get; private set; } @@ -44,10 +46,10 @@ namespace osu.Game.Rulesets.Taiko.Tests Add(PlayfieldContainer = new Container { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.X, - Height = 768, + Height = DEFAULT_PLAYFIELD_CONTAINER_HEIGHT, Children = new[] { DrawableRuleset = new DrawableTaikoRuleset(new TaikoRuleset(), beatmap.GetPlayableBeatmap(new TaikoRuleset().RulesetInfo)) } }); } diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs index 1d51020a6f..c3fa03d404 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneHits.cs @@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Taiko.Tests break; case 6: - PlayfieldContainer.Delay(delay).ResizeTo(new Vector2(1, TaikoPlayfield.DEFAULT_HEIGHT), 500); + PlayfieldContainer.Delay(delay).ResizeTo(new Vector2(1, DEFAULT_PLAYFIELD_CONTAINER_HEIGHT), 500); break; } } From 60379b09dbc22a1b8229c45a5a74a8f384a2bb39 Mon Sep 17 00:00:00 2001 From: Firmatorenio Date: Sun, 13 Dec 2020 18:14:41 +0600 Subject: [PATCH 39/73] added a container for the judgements to move up or down --- ...awableManiaJudgementAdjustmentContainer.cs | 23 +++++++++++++++++++ osu.Game.Rulesets.Mania/UI/Stage.cs | 8 +------ 2 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/UI/DrawableManiaJudgementAdjustmentContainer.cs diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgementAdjustmentContainer.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgementAdjustmentContainer.cs new file mode 100644 index 0000000000..b5abd9fb10 --- /dev/null +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgementAdjustmentContainer.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; +using osu.Game.Rulesets.UI; +using osu.Framework.Graphics; + +namespace osu.Game.Rulesets.Mania.UI +{ + public class DrawableManiaJudgementAdjustmentContainer : JudgementContainer + { + private float scorePosition => 0; + public DrawableManiaJudgementAdjustmentContainer(float hitTargetPosition) + { + Anchor = Anchor.TopCentre; + Origin = Anchor.Centre; + RelativeSizeAxes = Axes.Both; + Y = hitTargetPosition + 150; + } + + public DrawableManiaJudgementAdjustmentContainer() + : this(110) { } + } +} diff --git a/osu.Game.Rulesets.Mania/UI/Stage.cs b/osu.Game.Rulesets.Mania/UI/Stage.cs index 3d7960ffe3..73af205a37 100644 --- a/osu.Game.Rulesets.Mania/UI/Stage.cs +++ b/osu.Game.Rulesets.Mania/UI/Stage.cs @@ -101,13 +101,7 @@ namespace osu.Game.Rulesets.Mania.UI { RelativeSizeAxes = Axes.Both }, - judgements = new JudgementContainer - { - Anchor = Anchor.TopCentre, - Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Y = HIT_TARGET_POSITION + 150, - }, + judgements = new DrawableManiaJudgementAdjustmentContainer(HIT_TARGET_POSITION), topLevelContainer = new Container { RelativeSizeAxes = Axes.Both } } } From 7d2b77cdbdf2f09b5c4938d3c87fe5b181682ab8 Mon Sep 17 00:00:00 2001 From: Graham Johnson Date: Sun, 13 Dec 2020 07:58:58 -0500 Subject: [PATCH 40/73] improve selection box rotation UX --- .../Screens/Edit/Compose/Components/SelectionBox.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs index 742d433760..347d9e3ba7 100644 --- a/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs +++ b/osu.Game/Screens/Edit/Compose/Components/SelectionBox.cs @@ -191,7 +191,7 @@ namespace osu.Game.Screens.Edit.Compose.Components { Anchor = Anchor.TopCentre, Y = -separation, - HandleDrag = e => OnRotation?.Invoke(e.Delta.X), + HandleDrag = e => OnRotation?.Invoke(convertDragEventToAngleOfRotation(e)), OperationStarted = operationStarted, OperationEnded = operationEnded } @@ -242,6 +242,15 @@ namespace osu.Game.Screens.Edit.Compose.Components private int activeOperations; + private float convertDragEventToAngleOfRotation(DragEvent e) + { + // Adjust coordinate system to the center of SelectionBox + float startAngle = MathF.Atan2(e.LastMousePosition.Y - DrawHeight / 2, e.LastMousePosition.X - DrawWidth / 2); + float endAngle = MathF.Atan2(e.MousePosition.Y - DrawHeight / 2, e.MousePosition.X - DrawWidth / 2); + + return (endAngle - startAngle) * 180 / MathF.PI; + } + private void operationEnded() { if (--activeOperations == 0) From acd07017d1cf3b9c3497b73915363ed3be109725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 13 Dec 2020 16:36:09 +0100 Subject: [PATCH 41/73] Replace now-default SDL run config with legacy osuTK config --- .../{osu_SDL.xml => osu___legacy_osuTK_.xml} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename .idea/.idea.osu.Desktop/.idea/runConfigurations/{osu_SDL.xml => osu___legacy_osuTK_.xml} (79%) diff --git a/.idea/.idea.osu.Desktop/.idea/runConfigurations/osu_SDL.xml b/.idea/.idea.osu.Desktop/.idea/runConfigurations/osu___legacy_osuTK_.xml similarity index 79% rename from .idea/.idea.osu.Desktop/.idea/runConfigurations/osu_SDL.xml rename to .idea/.idea.osu.Desktop/.idea/runConfigurations/osu___legacy_osuTK_.xml index 31f1fda09d..811fd9cc6d 100644 --- a/.idea/.idea.osu.Desktop/.idea/runConfigurations/osu_SDL.xml +++ b/.idea/.idea.osu.Desktop/.idea/runConfigurations/osu___legacy_osuTK_.xml @@ -1,7 +1,7 @@ - + /// /// This value is the original value specified in the beatmap, not affected by beatmap processing. + /// It should be used instead of when working on a beatmap, not a gameplay. /// public float OriginalX { @@ -32,6 +33,9 @@ namespace osu.Game.Rulesets.Catch.Objects float IHasXPosition.X => OriginalX; + /// + /// An alias of setter. + /// public float X { set => OriginalX = value; From 7cbbd74df247626ae917f766bcc6f03cd5e37a27 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 14 Dec 2020 11:38:07 +0900 Subject: [PATCH 62/73] Remove X setter from CatchHitObject --- .../Mods/TestSceneCatchModRelax.cs | 8 +++---- .../TestSceneAutoJuiceStream.cs | 2 +- .../TestSceneCatchModHidden.cs | 2 +- .../TestSceneCatchStacker.cs | 2 +- .../TestSceneCatcher.cs | 22 +++++++++---------- .../TestSceneCatcherArea.cs | 2 +- .../TestSceneDrawableHitObjects.cs | 6 ++--- .../TestSceneHyperDash.cs | 14 ++++++------ .../TestSceneJuiceStream.cs | 4 ++-- .../Beatmaps/CatchBeatmapConverter.cs | 4 ++-- .../Objects/CatchHitObject.cs | 8 ------- .../Objects/JuiceStream.cs | 6 ++--- 12 files changed, 36 insertions(+), 44 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModRelax.cs b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModRelax.cs index c01aff0aa0..da4834aa73 100644 --- a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModRelax.cs +++ b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModRelax.cs @@ -32,22 +32,22 @@ namespace osu.Game.Rulesets.Catch.Tests.Mods { new Fruit { - X = CatchPlayfield.CENTER_X, + OriginalX = CatchPlayfield.CENTER_X, StartTime = 0 }, new Fruit { - X = 0, + OriginalX = 0, StartTime = 1000 }, new Fruit { - X = CatchPlayfield.WIDTH, + OriginalX = CatchPlayfield.WIDTH, StartTime = 2000 }, new JuiceStream { - X = CatchPlayfield.CENTER_X, + OriginalX = CatchPlayfield.CENTER_X, StartTime = 3000, Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, Vector2.UnitY * 200 }) } diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs index f552c3c27b..45cf5095f6 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Catch.Tests beatmap.HitObjects.Add(new JuiceStream { - X = CatchPlayfield.CENTER_X - width / 2, + OriginalX = CatchPlayfield.CENTER_X - width / 2, Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs index f15da29993..6af9c88088 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Catch.Tests { StartTime = 1000, Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, new Vector2(0, -192) }), - X = CatchPlayfield.WIDTH / 2 + OriginalX = CatchPlayfield.WIDTH / 2 } } }, diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs index 1ff31697b8..d7835bd8c4 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Catch.Tests { beatmap.HitObjects.Add(new Fruit { - X = (0.5f + i / 2048f * (i % 10 - 5)) * CatchPlayfield.WIDTH, + OriginalX = (0.5f + i / 2048f * (i % 10 - 5)) * CatchPlayfield.WIDTH, StartTime = i * 100, NewCombo = i % 8 == 0 }); diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index e8bb57cdf3..d57e8e027e 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Catch.Tests JudgementResult result2 = null; AddStep("catch hyper fruit", () => { - attemptCatch(new Fruit { HyperDashTarget = new Fruit { X = 100 } }, out drawableObject1, out result1); + attemptCatch(new Fruit { HyperDashTarget = new Fruit { OriginalX = 100 } }, out drawableObject1, out result1); }); AddStep("catch normal fruit", () => { @@ -107,14 +107,14 @@ namespace osu.Game.Rulesets.Catch.Tests var halfWidth = Catcher.CalculateCatchWidth(new BeatmapDifficulty { CircleSize = 0 }) / 2; AddStep("catch fruit", () => { - attemptCatch(new Fruit { X = -halfWidth + 1 }); - attemptCatch(new Fruit { X = halfWidth - 1 }); + attemptCatch(new Fruit { OriginalX = -halfWidth + 1 }); + attemptCatch(new Fruit { OriginalX = halfWidth - 1 }); }); checkPlate(2); AddStep("miss fruit", () => { - attemptCatch(new Fruit { X = -halfWidth - 1 }); - attemptCatch(new Fruit { X = halfWidth + 1 }); + attemptCatch(new Fruit { OriginalX = -halfWidth - 1 }); + attemptCatch(new Fruit { OriginalX = halfWidth + 1 }); }); checkPlate(2); } @@ -122,7 +122,7 @@ namespace osu.Game.Rulesets.Catch.Tests [Test] public void TestFruitChangesCatcherState() { - AddStep("miss fruit", () => attemptCatch(new Fruit { X = 100 })); + AddStep("miss fruit", () => attemptCatch(new Fruit { OriginalX = 100 })); checkState(CatcherAnimationState.Fail); AddStep("catch fruit", () => attemptCatch(new Fruit())); checkState(CatcherAnimationState.Idle); @@ -135,7 +135,7 @@ namespace osu.Game.Rulesets.Catch.Tests { AddStep("catch hyper fruit", () => attemptCatch(new Fruit { - HyperDashTarget = new Fruit { X = 100 } + HyperDashTarget = new Fruit { OriginalX = 100 } })); checkHyperDash(true); AddStep("catch normal fruit", () => attemptCatch(new Fruit())); @@ -147,10 +147,10 @@ namespace osu.Game.Rulesets.Catch.Tests { AddStep("catch hyper kiai fruit", () => attemptCatch(new TestKiaiFruit { - HyperDashTarget = new Fruit { X = 100 } + HyperDashTarget = new Fruit { OriginalX = 100 } })); AddStep("catch tiny droplet", () => attemptCatch(new TinyDroplet())); - AddStep("miss tiny droplet", () => attemptCatch(new TinyDroplet { X = 100 })); + AddStep("miss tiny droplet", () => attemptCatch(new TinyDroplet { OriginalX = 100 })); // catcher state and hyper dash state is preserved checkState(CatcherAnimationState.Kiai); checkHyperDash(true); @@ -161,9 +161,9 @@ namespace osu.Game.Rulesets.Catch.Tests { AddStep("catch hyper kiai fruit", () => attemptCatch(new TestKiaiFruit { - HyperDashTarget = new Fruit { X = 100 } + HyperDashTarget = new Fruit { OriginalX = 100 } })); - AddStep("miss banana", () => attemptCatch(new Banana { X = 100 })); + AddStep("miss banana", () => attemptCatch(new Banana { OriginalX = 100 })); // catcher state is preserved but hyper dash state is reset checkState(CatcherAnimationState.Kiai); checkHyperDash(false); diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs index 5079e57e5e..423c3b7a13 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs @@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Catch.Tests AddStep("catch fruit", () => attemptCatch(new Fruit())); AddStep("catch fruit last in combo", () => attemptCatch(new Fruit { LastInCombo = true })); AddStep("catch kiai fruit", () => attemptCatch(new TestSceneCatcher.TestKiaiFruit())); - AddStep("miss last in combo", () => attemptCatch(new Fruit { X = 100, LastInCombo = true })); + AddStep("miss last in combo", () => attemptCatch(new Fruit { OriginalX = 100, LastInCombo = true })); } private void attemptCatch(Fruit fruit) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs index 3e4995482d..2db534e8c9 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs @@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.Catch.Tests { var fruit = new Fruit { - X = getXCoords(hit), + OriginalX = getXCoords(hit), LastInCombo = i % 4 == 0, StartTime = playfieldTime + 800 + (200 * i) }; @@ -122,7 +122,7 @@ namespace osu.Game.Rulesets.Catch.Tests var juice = new JuiceStream { - X = xCoords, + OriginalX = xCoords, StartTime = playfieldTime + 1000, Path = new SliderPath(PathType.Linear, new[] { @@ -145,7 +145,7 @@ namespace osu.Game.Rulesets.Catch.Tests { var banana = new Banana { - X = getXCoords(hit), + OriginalX = getXCoords(hit), LastInCombo = i % 4 == 0, StartTime = playfieldTime + 800 + (200 * i) }; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs index db09b2bc6b..67af3c4420 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs @@ -70,20 +70,20 @@ namespace osu.Game.Rulesets.Catch.Tests beatmap.ControlPointInfo.Add(0, new TimingControlPoint()); // Should produce a hyper-dash (edge case test) - beatmap.HitObjects.Add(new Fruit { StartTime = 1816, X = 56, NewCombo = true }); - beatmap.HitObjects.Add(new Fruit { StartTime = 2008, X = 308, NewCombo = true }); + beatmap.HitObjects.Add(new Fruit { StartTime = 1816, OriginalX = 56, NewCombo = true }); + beatmap.HitObjects.Add(new Fruit { StartTime = 2008, OriginalX = 308, NewCombo = true }); double startTime = 3000; const float left_x = 0.02f * CatchPlayfield.WIDTH; const float right_x = 0.98f * CatchPlayfield.WIDTH; - createObjects(() => new Fruit { X = left_x }); + createObjects(() => new Fruit { OriginalX = left_x }); createObjects(() => new TestJuiceStream(right_x), 1); createObjects(() => new TestJuiceStream(left_x), 1); - createObjects(() => new Fruit { X = right_x }); - createObjects(() => new Fruit { X = left_x }); - createObjects(() => new Fruit { X = right_x }); + createObjects(() => new Fruit { OriginalX = right_x }); + createObjects(() => new Fruit { OriginalX = left_x }); + createObjects(() => new Fruit { OriginalX = right_x }); createObjects(() => new TestJuiceStream(left_x), 1); beatmap.ControlPointInfo.Add(startTime, new TimingControlPoint @@ -121,7 +121,7 @@ namespace osu.Game.Rulesets.Catch.Tests { public TestJuiceStream(float x) { - X = x; + OriginalX = x; Path = new SliderPath(new[] { diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs index 269e783899..dbcf382d62 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Catch.Tests { new JuiceStream { - X = CatchPlayfield.CENTER_X, + OriginalX = CatchPlayfield.CENTER_X, Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Catch.Tests }, new Banana { - X = CatchPlayfield.CENTER_X, + OriginalX = CatchPlayfield.CENTER_X, StartTime = 1000, NewCombo = true } diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index 34964fc4ae..55e86a7be2 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps Path = curveData.Path, NodeSamples = curveData.NodeSamples, RepeatCount = curveData.RepeatCount, - X = positionData?.X ?? 0, + OriginalX = positionData?.X ?? 0, NewCombo = comboData?.NewCombo ?? false, ComboOffset = comboData?.ComboOffset ?? 0, LegacyLastTickOffset = (obj as IHasLegacyLastTickOffset)?.LegacyLastTickOffset ?? 0 @@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps Samples = obj.Samples, NewCombo = comboData?.NewCombo ?? false, ComboOffset = comboData?.ComboOffset ?? 0, - X = positionData?.X ?? 0 + OriginalX = positionData?.X ?? 0 }.Yield(); } } diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index e689d6a178..ebbbd44960 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -33,14 +33,6 @@ namespace osu.Game.Rulesets.Catch.Objects float IHasXPosition.X => OriginalX; - /// - /// An alias of setter. - /// - public float X - { - set => OriginalX = value; - } - public readonly Bindable EffectiveXBindable = new Bindable(); /// diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index 35fd58826e..bda0457c83 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -75,7 +75,7 @@ namespace osu.Game.Rulesets.Catch.Objects AddNested(new TinyDroplet { StartTime = t + lastEvent.Value.Time, - X = OriginalX + Path.PositionAt( + OriginalX = OriginalX + Path.PositionAt( lastEvent.Value.PathProgress + (t / sinceLastTick) * (e.PathProgress - lastEvent.Value.PathProgress)).X, }); } @@ -93,7 +93,7 @@ namespace osu.Game.Rulesets.Catch.Objects { Samples = dropletSamples, StartTime = e.Time, - X = OriginalX + Path.PositionAt(e.PathProgress).X, + OriginalX = OriginalX + Path.PositionAt(e.PathProgress).X, }); break; @@ -104,7 +104,7 @@ namespace osu.Game.Rulesets.Catch.Objects { Samples = this.GetNodeSamples(nodeIndex++), StartTime = e.Time, - X = OriginalX + Path.PositionAt(e.PathProgress).X, + OriginalX = OriginalX + Path.PositionAt(e.PathProgress).X, }); break; } From 1794bfeddba4b8533d10f9854f06a0f5e9731cc7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 14 Dec 2020 13:07:55 +0900 Subject: [PATCH 63/73] Move offset into legacy mania judgement --- .../Legacy/LegacyManiaJudgementPiece.cs | 84 +++++++++++++++++++ .../Legacy/ManiaLegacySkinTransformer.cs | 3 +- .../UI/DrawableManiaJudgement.cs | 53 +++++------- osu.Game.Rulesets.Mania/UI/Stage.cs | 8 +- .../UI/Scrolling/ScrollingPlayfield.cs | 9 -- 5 files changed, 108 insertions(+), 49 deletions(-) create mode 100644 osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaJudgementPiece.cs diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaJudgementPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaJudgementPiece.cs new file mode 100644 index 0000000000..464d754205 --- /dev/null +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaJudgementPiece.cs @@ -0,0 +1,84 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Animations; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Mania.UI; +using osu.Game.Rulesets.Scoring; +using osu.Game.Skinning; +using osuTK; + +namespace osu.Game.Rulesets.Mania.Skinning.Legacy +{ + public class LegacyManiaJudgementPiece : CompositeDrawable, IAnimatableJudgement + { + private readonly HitResult result; + private readonly Drawable animation; + + public LegacyManiaJudgementPiece(HitResult result, Drawable animation) + { + this.result = result; + this.animation = animation; + + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + + AutoSizeAxes = Axes.Both; + } + + [BackgroundDependencyLoader] + private void load(ISkinSource skin) + { + float? scorePosition = skin.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.ScorePosition)?.Value; + + if (scorePosition != null) + scorePosition -= Stage.HIT_TARGET_POSITION + 150; + + Y = scorePosition ?? 0; + + if (animation != null) + InternalChild = animation; + } + + public void PlayAnimation() + { + if (animation == null) + return; + + (animation as IFramedAnimation)?.GotoFrame(0); + + switch (result) + { + case HitResult.None: + break; + + case HitResult.Miss: + animation.ScaleTo(1.6f); + animation.ScaleTo(1, 100, Easing.In); + + animation.MoveTo(Vector2.Zero); + animation.MoveToOffset(new Vector2(0, 100), 800, Easing.InQuint); + + animation.RotateTo(0); + animation.RotateTo(40, 800, Easing.InQuint); + + this.FadeOutFromOne(800); + break; + + default: + animation.ScaleTo(0.8f); + animation.ScaleTo(1, 250, Easing.OutElastic); + + animation.Delay(50).ScaleTo(0.75f, 250); + + this.Delay(50).FadeOut(200); + break; + } + } + + public Drawable GetAboveHitObjectsProxiedContent() => null; + } +} diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs index 89f639e2fe..7e2a8823b6 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs @@ -136,7 +136,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy string filename = this.GetManiaSkinConfig(hitresult_mapping[result])?.Value ?? default_hitresult_skin_filenames[result]; - return this.GetAnimation(filename, true, true); + var animation = this.GetAnimation(filename, true, true); + return animation == null ? null : new LegacyManiaJudgementPiece(result, animation); } public override SampleChannel GetSample(ISampleInfo sampleInfo) diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs index a3dcd0e57f..34d972e60f 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs @@ -5,7 +5,6 @@ using osu.Framework.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; -using osuTK; namespace osu.Game.Rulesets.Mania.UI { @@ -20,37 +19,6 @@ namespace osu.Game.Rulesets.Mania.UI { } - protected override void ApplyMissAnimations() - { - if (!(JudgementBody.Drawable is DefaultManiaJudgementPiece)) - { - // this is temporary logic until mania's skin transformer returns IAnimatableJudgements - JudgementBody.ScaleTo(1.6f); - JudgementBody.ScaleTo(1, 100, Easing.In); - - JudgementBody.MoveTo(Vector2.Zero); - JudgementBody.MoveToOffset(new Vector2(0, 100), 800, Easing.InQuint); - - JudgementBody.RotateTo(0); - JudgementBody.RotateTo(40, 800, Easing.InQuint); - JudgementBody.FadeOutFromOne(800); - - LifetimeEnd = JudgementBody.LatestTransformEndTime; - } - - base.ApplyMissAnimations(); - } - - protected override void ApplyHitAnimations() - { - JudgementBody.ScaleTo(0.8f); - JudgementBody.ScaleTo(1, 250, Easing.OutElastic); - - JudgementBody.Delay(50) - .ScaleTo(0.75f, 250) - .FadeOut(200); - } - protected override Drawable CreateDefaultJudgement(HitResult result) => new DefaultManiaJudgementPiece(result); private class DefaultManiaJudgementPiece : DefaultJudgementPiece @@ -66,6 +34,27 @@ namespace osu.Game.Rulesets.Mania.UI JudgementText.Font = JudgementText.Font.With(size: 25); } + + public override void PlayAnimation() + { + base.PlayAnimation(); + + switch (Result) + { + case HitResult.None: + case HitResult.Miss: + break; + + default: + this.ScaleTo(0.8f); + this.ScaleTo(1, 250, Easing.OutElastic); + + this.Delay(50) + .ScaleTo(0.75f, 250) + .FadeOut(200); + break; + } + } } } } diff --git a/osu.Game.Rulesets.Mania/UI/Stage.cs b/osu.Game.Rulesets.Mania/UI/Stage.cs index d2f5e6902a..dc34bffab1 100644 --- a/osu.Game.Rulesets.Mania/UI/Stage.cs +++ b/osu.Game.Rulesets.Mania/UI/Stage.cs @@ -10,7 +10,6 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects.Drawables; -using osu.Game.Rulesets.Mania.Skinning; using osu.Game.Rulesets.Mania.UI.Components; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.UI; @@ -107,6 +106,7 @@ namespace osu.Game.Rulesets.Mania.UI Anchor = Anchor.TopCentre, Origin = Anchor.Centre, RelativeSizeAxes = Axes.Both, + Y = HIT_TARGET_POSITION + 150 }, topLevelContainer = new Container { RelativeSizeAxes = Axes.Both } } @@ -181,12 +181,6 @@ namespace osu.Game.Rulesets.Mania.UI })); } - protected override void OnSkinChanged() - { - judgements.Y = CurrentSkin.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.ScorePosition) - ?.Value ?? HIT_TARGET_POSITION + 150; - } - protected override void Update() { // Due to masking differences, it is not possible to get the width of the columns container automatically diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index 4f76198b9f..844a249769 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -20,20 +20,11 @@ namespace osu.Game.Rulesets.UI.Scrolling [Resolved] protected IScrollingInfo ScrollingInfo { get; private set; } - protected ISkinSource CurrentSkin { get; private set; } [BackgroundDependencyLoader] private void load(ISkinSource skin) { Direction.BindTo(ScrollingInfo.Direction); - CurrentSkin = skin; - - skin.SourceChanged += OnSkinChanged; - OnSkinChanged(); - } - - protected virtual void OnSkinChanged() - { } /// From 028909353c8dc5b027a05ae5fb995ee278db9ede Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 14 Dec 2020 13:15:52 +0900 Subject: [PATCH 64/73] Revert one more change --- osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index 844a249769..475300c483 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.UI.Scrolling protected IScrollingInfo ScrollingInfo { get; private set; } [BackgroundDependencyLoader] - private void load(ISkinSource skin) + private void load() { Direction.BindTo(ScrollingInfo.Direction); } From d96399ea42130f3727d0188aa1ec8a0855c0b4b7 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 14 Dec 2020 13:18:14 +0900 Subject: [PATCH 65/73] Revert "Remove X setter from CatchHitObject" This reverts commit 7cbbd74d --- .../Mods/TestSceneCatchModRelax.cs | 8 +++---- .../TestSceneAutoJuiceStream.cs | 2 +- .../TestSceneCatchModHidden.cs | 2 +- .../TestSceneCatchStacker.cs | 2 +- .../TestSceneCatcher.cs | 22 +++++++++---------- .../TestSceneCatcherArea.cs | 2 +- .../TestSceneDrawableHitObjects.cs | 6 ++--- .../TestSceneHyperDash.cs | 14 ++++++------ .../TestSceneJuiceStream.cs | 4 ++-- .../Beatmaps/CatchBeatmapConverter.cs | 4 ++-- .../Objects/CatchHitObject.cs | 8 +++++++ .../Objects/JuiceStream.cs | 6 ++--- 12 files changed, 44 insertions(+), 36 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModRelax.cs b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModRelax.cs index da4834aa73..c01aff0aa0 100644 --- a/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModRelax.cs +++ b/osu.Game.Rulesets.Catch.Tests/Mods/TestSceneCatchModRelax.cs @@ -32,22 +32,22 @@ namespace osu.Game.Rulesets.Catch.Tests.Mods { new Fruit { - OriginalX = CatchPlayfield.CENTER_X, + X = CatchPlayfield.CENTER_X, StartTime = 0 }, new Fruit { - OriginalX = 0, + X = 0, StartTime = 1000 }, new Fruit { - OriginalX = CatchPlayfield.WIDTH, + X = CatchPlayfield.WIDTH, StartTime = 2000 }, new JuiceStream { - OriginalX = CatchPlayfield.CENTER_X, + X = CatchPlayfield.CENTER_X, StartTime = 3000, Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, Vector2.UnitY * 200 }) } diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs index 45cf5095f6..f552c3c27b 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneAutoJuiceStream.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Catch.Tests beatmap.HitObjects.Add(new JuiceStream { - OriginalX = CatchPlayfield.CENTER_X - width / 2, + X = CatchPlayfield.CENTER_X - width / 2, Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs index 6af9c88088..f15da29993 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchModHidden.cs @@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Catch.Tests { StartTime = 1000, Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, new Vector2(0, -192) }), - OriginalX = CatchPlayfield.WIDTH / 2 + X = CatchPlayfield.WIDTH / 2 } } }, diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs index d7835bd8c4..1ff31697b8 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatchStacker.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Catch.Tests { beatmap.HitObjects.Add(new Fruit { - OriginalX = (0.5f + i / 2048f * (i % 10 - 5)) * CatchPlayfield.WIDTH, + X = (0.5f + i / 2048f * (i % 10 - 5)) * CatchPlayfield.WIDTH, StartTime = i * 100, NewCombo = i % 8 == 0 }); diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs index d57e8e027e..e8bb57cdf3 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcher.cs @@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Catch.Tests JudgementResult result2 = null; AddStep("catch hyper fruit", () => { - attemptCatch(new Fruit { HyperDashTarget = new Fruit { OriginalX = 100 } }, out drawableObject1, out result1); + attemptCatch(new Fruit { HyperDashTarget = new Fruit { X = 100 } }, out drawableObject1, out result1); }); AddStep("catch normal fruit", () => { @@ -107,14 +107,14 @@ namespace osu.Game.Rulesets.Catch.Tests var halfWidth = Catcher.CalculateCatchWidth(new BeatmapDifficulty { CircleSize = 0 }) / 2; AddStep("catch fruit", () => { - attemptCatch(new Fruit { OriginalX = -halfWidth + 1 }); - attemptCatch(new Fruit { OriginalX = halfWidth - 1 }); + attemptCatch(new Fruit { X = -halfWidth + 1 }); + attemptCatch(new Fruit { X = halfWidth - 1 }); }); checkPlate(2); AddStep("miss fruit", () => { - attemptCatch(new Fruit { OriginalX = -halfWidth - 1 }); - attemptCatch(new Fruit { OriginalX = halfWidth + 1 }); + attemptCatch(new Fruit { X = -halfWidth - 1 }); + attemptCatch(new Fruit { X = halfWidth + 1 }); }); checkPlate(2); } @@ -122,7 +122,7 @@ namespace osu.Game.Rulesets.Catch.Tests [Test] public void TestFruitChangesCatcherState() { - AddStep("miss fruit", () => attemptCatch(new Fruit { OriginalX = 100 })); + AddStep("miss fruit", () => attemptCatch(new Fruit { X = 100 })); checkState(CatcherAnimationState.Fail); AddStep("catch fruit", () => attemptCatch(new Fruit())); checkState(CatcherAnimationState.Idle); @@ -135,7 +135,7 @@ namespace osu.Game.Rulesets.Catch.Tests { AddStep("catch hyper fruit", () => attemptCatch(new Fruit { - HyperDashTarget = new Fruit { OriginalX = 100 } + HyperDashTarget = new Fruit { X = 100 } })); checkHyperDash(true); AddStep("catch normal fruit", () => attemptCatch(new Fruit())); @@ -147,10 +147,10 @@ namespace osu.Game.Rulesets.Catch.Tests { AddStep("catch hyper kiai fruit", () => attemptCatch(new TestKiaiFruit { - HyperDashTarget = new Fruit { OriginalX = 100 } + HyperDashTarget = new Fruit { X = 100 } })); AddStep("catch tiny droplet", () => attemptCatch(new TinyDroplet())); - AddStep("miss tiny droplet", () => attemptCatch(new TinyDroplet { OriginalX = 100 })); + AddStep("miss tiny droplet", () => attemptCatch(new TinyDroplet { X = 100 })); // catcher state and hyper dash state is preserved checkState(CatcherAnimationState.Kiai); checkHyperDash(true); @@ -161,9 +161,9 @@ namespace osu.Game.Rulesets.Catch.Tests { AddStep("catch hyper kiai fruit", () => attemptCatch(new TestKiaiFruit { - HyperDashTarget = new Fruit { OriginalX = 100 } + HyperDashTarget = new Fruit { X = 100 } })); - AddStep("miss banana", () => attemptCatch(new Banana { OriginalX = 100 })); + AddStep("miss banana", () => attemptCatch(new Banana { X = 100 })); // catcher state is preserved but hyper dash state is reset checkState(CatcherAnimationState.Kiai); checkHyperDash(false); diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs index 423c3b7a13..5079e57e5e 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs @@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Catch.Tests AddStep("catch fruit", () => attemptCatch(new Fruit())); AddStep("catch fruit last in combo", () => attemptCatch(new Fruit { LastInCombo = true })); AddStep("catch kiai fruit", () => attemptCatch(new TestSceneCatcher.TestKiaiFruit())); - AddStep("miss last in combo", () => attemptCatch(new Fruit { OriginalX = 100, LastInCombo = true })); + AddStep("miss last in combo", () => attemptCatch(new Fruit { X = 100, LastInCombo = true })); } private void attemptCatch(Fruit fruit) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs index 2db534e8c9..3e4995482d 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneDrawableHitObjects.cs @@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.Catch.Tests { var fruit = new Fruit { - OriginalX = getXCoords(hit), + X = getXCoords(hit), LastInCombo = i % 4 == 0, StartTime = playfieldTime + 800 + (200 * i) }; @@ -122,7 +122,7 @@ namespace osu.Game.Rulesets.Catch.Tests var juice = new JuiceStream { - OriginalX = xCoords, + X = xCoords, StartTime = playfieldTime + 1000, Path = new SliderPath(PathType.Linear, new[] { @@ -145,7 +145,7 @@ namespace osu.Game.Rulesets.Catch.Tests { var banana = new Banana { - OriginalX = getXCoords(hit), + X = getXCoords(hit), LastInCombo = i % 4 == 0, StartTime = playfieldTime + 800 + (200 * i) }; diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs index 67af3c4420..db09b2bc6b 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneHyperDash.cs @@ -70,20 +70,20 @@ namespace osu.Game.Rulesets.Catch.Tests beatmap.ControlPointInfo.Add(0, new TimingControlPoint()); // Should produce a hyper-dash (edge case test) - beatmap.HitObjects.Add(new Fruit { StartTime = 1816, OriginalX = 56, NewCombo = true }); - beatmap.HitObjects.Add(new Fruit { StartTime = 2008, OriginalX = 308, NewCombo = true }); + beatmap.HitObjects.Add(new Fruit { StartTime = 1816, X = 56, NewCombo = true }); + beatmap.HitObjects.Add(new Fruit { StartTime = 2008, X = 308, NewCombo = true }); double startTime = 3000; const float left_x = 0.02f * CatchPlayfield.WIDTH; const float right_x = 0.98f * CatchPlayfield.WIDTH; - createObjects(() => new Fruit { OriginalX = left_x }); + createObjects(() => new Fruit { X = left_x }); createObjects(() => new TestJuiceStream(right_x), 1); createObjects(() => new TestJuiceStream(left_x), 1); - createObjects(() => new Fruit { OriginalX = right_x }); - createObjects(() => new Fruit { OriginalX = left_x }); - createObjects(() => new Fruit { OriginalX = right_x }); + createObjects(() => new Fruit { X = right_x }); + createObjects(() => new Fruit { X = left_x }); + createObjects(() => new Fruit { X = right_x }); createObjects(() => new TestJuiceStream(left_x), 1); beatmap.ControlPointInfo.Add(startTime, new TimingControlPoint @@ -121,7 +121,7 @@ namespace osu.Game.Rulesets.Catch.Tests { public TestJuiceStream(float x) { - OriginalX = x; + X = x; Path = new SliderPath(new[] { diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs index dbcf382d62..269e783899 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs @@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Catch.Tests { new JuiceStream { - OriginalX = CatchPlayfield.CENTER_X, + X = CatchPlayfield.CENTER_X, Path = new SliderPath(PathType.Linear, new[] { Vector2.Zero, @@ -41,7 +41,7 @@ namespace osu.Game.Rulesets.Catch.Tests }, new Banana { - OriginalX = CatchPlayfield.CENTER_X, + X = CatchPlayfield.CENTER_X, StartTime = 1000, NewCombo = true } diff --git a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs index 55e86a7be2..34964fc4ae 100644 --- a/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs +++ b/osu.Game.Rulesets.Catch/Beatmaps/CatchBeatmapConverter.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps Path = curveData.Path, NodeSamples = curveData.NodeSamples, RepeatCount = curveData.RepeatCount, - OriginalX = positionData?.X ?? 0, + X = positionData?.X ?? 0, NewCombo = comboData?.NewCombo ?? false, ComboOffset = comboData?.ComboOffset ?? 0, LegacyLastTickOffset = (obj as IHasLegacyLastTickOffset)?.LegacyLastTickOffset ?? 0 @@ -59,7 +59,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps Samples = obj.Samples, NewCombo = comboData?.NewCombo ?? false, ComboOffset = comboData?.ComboOffset ?? 0, - OriginalX = positionData?.X ?? 0 + X = positionData?.X ?? 0 }.Yield(); } } diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index ebbbd44960..e689d6a178 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -33,6 +33,14 @@ namespace osu.Game.Rulesets.Catch.Objects float IHasXPosition.X => OriginalX; + /// + /// An alias of setter. + /// + public float X + { + set => OriginalX = value; + } + public readonly Bindable EffectiveXBindable = new Bindable(); /// diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index bda0457c83..35fd58826e 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -75,7 +75,7 @@ namespace osu.Game.Rulesets.Catch.Objects AddNested(new TinyDroplet { StartTime = t + lastEvent.Value.Time, - OriginalX = OriginalX + Path.PositionAt( + X = OriginalX + Path.PositionAt( lastEvent.Value.PathProgress + (t / sinceLastTick) * (e.PathProgress - lastEvent.Value.PathProgress)).X, }); } @@ -93,7 +93,7 @@ namespace osu.Game.Rulesets.Catch.Objects { Samples = dropletSamples, StartTime = e.Time, - OriginalX = OriginalX + Path.PositionAt(e.PathProgress).X, + X = OriginalX + Path.PositionAt(e.PathProgress).X, }); break; @@ -104,7 +104,7 @@ namespace osu.Game.Rulesets.Catch.Objects { Samples = this.GetNodeSamples(nodeIndex++), StartTime = e.Time, - OriginalX = OriginalX + Path.PositionAt(e.PathProgress).X, + X = OriginalX + Path.PositionAt(e.PathProgress).X, }); break; } From 0ad256a7626c6aa28c97f64ecc9bc9a1940c2f87 Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 14 Dec 2020 13:18:32 +0900 Subject: [PATCH 66/73] Fix comment --- osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index e689d6a178..6267eca7de 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Catch.Objects private float xOffset; /// - /// A random offset applied to the horizontal value, set by the . + /// A random offset applied to the horizontal position, set by the . /// internal float XOffset { From 2e88e283d84c0547fd2f8272be87de6ccd8375d2 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 14 Dec 2020 13:20:51 +0900 Subject: [PATCH 67/73] Remove unused using --- osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs index 475300c483..2b75f93f9e 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingPlayfield.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Rulesets.Objects.Drawables; -using osu.Game.Skinning; using osuTK; namespace osu.Game.Rulesets.UI.Scrolling From 5b5e883904298074b80671e87e0b88eca883127c Mon Sep 17 00:00:00 2001 From: ekrctb Date: Mon, 14 Dec 2020 13:39:07 +0900 Subject: [PATCH 68/73] Remove EffectiveXBindable (setting Value was not handled) And use orthogonal `OriginalXBindable` and `XOffsetBindable`. --- .../TestSceneCatcherArea.cs | 2 +- .../Objects/CatchHitObject.cs | 52 +++++++------------ .../Drawables/DrawableCatchHitObject.cs | 9 ++-- .../DrawablePalpableCatchHitObject.cs | 6 +-- 4 files changed, 29 insertions(+), 40 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs index 5079e57e5e..1cbfa6338e 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneCatcherArea.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Catch.Tests private void attemptCatch(Fruit fruit) { - fruit.OriginalX += catcher.X; + fruit.X = fruit.OriginalX + catcher.X; fruit.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = circleSize diff --git a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs index 6267eca7de..ae45182960 100644 --- a/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/CatchHitObject.cs @@ -4,7 +4,6 @@ using osu.Framework.Bindables; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; -using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; @@ -21,46 +20,40 @@ namespace osu.Game.Rulesets.Catch.Objects /// /// The horizontal position of the hit object between 0 and . /// - /// - /// This value is the original value specified in the beatmap, not affected by beatmap processing. - /// It should be used instead of when working on a beatmap, not a gameplay. - /// - public float OriginalX + public float X { - get => OriginalXBindable.Value; set => OriginalXBindable.Value = value; } - float IHasXPosition.X => OriginalX; + float IHasXPosition.X => OriginalXBindable.Value; + + public readonly Bindable XOffsetBindable = new Bindable(); /// - /// An alias of setter. + /// A random offset applied to the horizontal position, set by the beatmap processing. /// - public float X + public float XOffset { - set => OriginalX = value; + set => XOffsetBindable.Value = value; } - public readonly Bindable EffectiveXBindable = new Bindable(); + /// + /// The horizontal position of the hit object between 0 and . + /// + /// + /// This value is the original value specified in the beatmap, not affected by the beatmap processing. + /// Use for a gameplay. + /// + public float OriginalX => OriginalXBindable.Value; /// /// The effective horizontal position of the hit object between 0 and . /// - public float EffectiveX => EffectiveXBindable.Value; - - private float xOffset; - - /// - /// A random offset applied to the horizontal position, set by the . - /// - internal float XOffset - { - set - { - xOffset = value; - EffectiveXBindable.Value = OriginalX + xOffset; - } - } + /// + /// This value is the original value plus the offset applied by the beatmap processing. + /// Use if a value not affected by the offset is desired. + /// + public float EffectiveX => OriginalXBindable.Value + XOffsetBindable.Value; public double TimePreempt = 1000; @@ -127,10 +120,5 @@ namespace osu.Game.Rulesets.Catch.Objects } protected override HitWindows CreateHitWindows() => HitWindows.Empty; - - protected CatchHitObject() - { - OriginalXBindable.BindValueChanged(change => EffectiveXBindable.Value = change.NewValue + xOffset); - } } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs index edd607a443..0c065948ef 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs @@ -15,7 +15,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables { public abstract class DrawableCatchHitObject : DrawableHitObject { - public readonly Bindable EffectiveXBindable = new Bindable(); + public readonly Bindable OriginalXBindable = new Bindable(); + public readonly Bindable XOffsetBindable = new Bindable(); protected override double InitialLifetimeOffset => HitObject.TimePreempt; @@ -38,14 +39,16 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables { base.OnApply(); - EffectiveXBindable.BindTo(HitObject.EffectiveXBindable); + OriginalXBindable.BindTo(HitObject.OriginalXBindable); + XOffsetBindable.BindTo(HitObject.XOffsetBindable); } protected override void OnFree() { base.OnFree(); - EffectiveXBindable.UnbindFrom(HitObject.EffectiveXBindable); + OriginalXBindable.UnbindFrom(HitObject.OriginalXBindable); + XOffsetBindable.UnbindFrom(HitObject.XOffsetBindable); } public Func CheckPosition; diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs index d3fa43c6b6..84af7922f9 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs @@ -55,10 +55,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables [BackgroundDependencyLoader] private void load() { - EffectiveXBindable.BindValueChanged(x => - { - X = x.NewValue; - }, true); + OriginalXBindable.BindValueChanged(_ => X = OriginalXBindable.Value + XOffsetBindable.Value); + XOffsetBindable.BindValueChanged(_ => X = OriginalXBindable.Value + XOffsetBindable.Value, true); ScaleBindable.BindValueChanged(scale => { From b81dbfc1921dabe9b846d752c7b4ca2a2a347c6d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Dec 2020 13:56:46 +0900 Subject: [PATCH 69/73] Move shared implementation to a named function --- .../Objects/Drawables/DrawablePalpableCatchHitObject.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs index 84af7922f9..27cd7ed2bc 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawablePalpableCatchHitObject.cs @@ -55,8 +55,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables [BackgroundDependencyLoader] private void load() { - OriginalXBindable.BindValueChanged(_ => X = OriginalXBindable.Value + XOffsetBindable.Value); - XOffsetBindable.BindValueChanged(_ => X = OriginalXBindable.Value + XOffsetBindable.Value, true); + OriginalXBindable.BindValueChanged(updateXPosition); + XOffsetBindable.BindValueChanged(updateXPosition, true); ScaleBindable.BindValueChanged(scale => { @@ -67,6 +67,11 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables IndexInBeatmap.BindValueChanged(_ => UpdateComboColour()); } + private void updateXPosition(ValueChangedEvent _) + { + X = OriginalXBindable.Value + XOffsetBindable.Value; + } + protected override void OnApply() { base.OnApply(); From a835ca9612e29fa71d66c852a0e4f5401bd3a465 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 14 Dec 2020 14:20:43 +0900 Subject: [PATCH 70/73] Fix anchors/origins for legacy pieces --- .../Skinning/Legacy/LegacyManiaJudgementPiece.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaJudgementPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaJudgementPiece.cs index 464d754205..9684cbb167 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaJudgementPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyManiaJudgementPiece.cs @@ -40,7 +40,13 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy Y = scorePosition ?? 0; if (animation != null) - InternalChild = animation; + { + InternalChild = animation.With(d => + { + d.Anchor = Anchor.Centre; + d.Origin = Anchor.Centre; + }); + } } public void PlayAnimation() From 0d7f53b0b9b8d83835ac16aaf32d032c15b68dc9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Dec 2020 14:21:21 +0900 Subject: [PATCH 71/73] Fix gameplay loading too fast the first time entering a beatmap --- osu.Game/Screens/Play/PlayerLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs index 729119fa36..f59b36bc42 100644 --- a/osu.Game/Screens/Play/PlayerLoader.cs +++ b/osu.Game/Screens/Play/PlayerLoader.cs @@ -189,7 +189,7 @@ namespace osu.Game.Screens.Play // after an initial delay, start the debounced load check. // this will continue to execute even after resuming back on restart. - Scheduler.Add(new ScheduledDelegate(pushWhenLoaded, 1800, 0)); + Scheduler.Add(new ScheduledDelegate(pushWhenLoaded, Clock.CurrentTime + 1800, 0)); showMuteWarningIfNeeded(); } From 704150306324135bbb6ba4957627619fa294548c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Dec 2020 15:34:32 +0900 Subject: [PATCH 72/73] Avoid intermediary delegate --- .../Objects/Drawables/DrawableBarLine.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs index e7dd9a18c2..9e50faabc1 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs @@ -111,13 +111,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables protected override void LoadComplete() { base.LoadComplete(); - major.BindValueChanged(majorChanged => updateMajor(majorChanged.NewValue), true); + major.BindValueChanged(updateMajor); } - private void updateMajor(bool major) + private void updateMajor(ValueChangedEvent major) { - line.Alpha = major ? 1f : 0.75f; - triangleContainer.Alpha = major ? 1 : 0; + line.Alpha = major.NewValue ? 1f : 0.75f; + triangleContainer.Alpha = major.NewValue ? 1 : 0; } protected override void OnApply() From 79768f0aa412f00fa6d8e45101038cd8417e2c78 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 14 Dec 2020 17:52:38 +0900 Subject: [PATCH 73/73] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index eaedcb7bc3..2a08cb7867 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -52,6 +52,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b4c7dca12f..960959f367 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -26,7 +26,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 7542aded86..a5bcb91c74 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -88,7 +88,7 @@ - +