diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 78f7e34649..21bf049ccc 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -110,14 +110,14 @@ namespace osu.Game.Rulesets.Catch.UI comboDisplay.X = Catcher.X; if (!lastHyperDashState && Catcher.HyperDashing && Time.Elapsed > 0) - catcherTrails.DisplayHyperDashAfterImage(Catcher.CurrentState, Catcher.X, Catcher.BodyScale); + displayCatcherTrail(CatcherTrailAnimation.HyperDashAfterimage); if (Catcher.Dashing || Catcher.HyperDashing) { double generationInterval = Catcher.HyperDashing ? 25 : 50; if (Time.Current - catcherTrails.LastDashTrailTime >= generationInterval) - catcherTrails.DisplayDashTrail(Catcher.CurrentState, Catcher.X, Catcher.BodyScale, Catcher.HyperDashing); + displayCatcherTrail(Catcher.HyperDashing ? CatcherTrailAnimation.HyperDashing : CatcherTrailAnimation.Dashing); } lastHyperDashState = Catcher.HyperDashing; @@ -173,5 +173,7 @@ namespace osu.Game.Rulesets.Catch.UI break; } } + + private void displayCatcherTrail(CatcherTrailAnimation animation) => catcherTrails.Add(new CatcherTrailEntry(Time.Current, Catcher.CurrentState, Catcher.X, Catcher.BodyScale, animation)); } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs index ff1a7d7a61..a7a2941a7a 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrail.cs @@ -2,8 +2,8 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; -using osu.Framework.Graphics.Pooling; using osu.Framework.Timing; +using osu.Game.Rulesets.Objects.Pooling; using osuTK; namespace osu.Game.Rulesets.Catch.UI @@ -12,13 +12,8 @@ namespace osu.Game.Rulesets.Catch.UI /// A trail of the catcher. /// It also represents a hyper dash afterimage. /// - public class CatcherTrail : PoolableDrawable + public class CatcherTrail : PoolableDrawableWithLifetime { - public CatcherAnimationState AnimationState - { - set => body.AnimationState.Value = value; - } - private readonly SkinnableCatcher body; public CatcherTrail() @@ -34,11 +29,40 @@ namespace osu.Game.Rulesets.Catch.UI }; } - protected override void FreeAfterUse() + protected override void OnApply(CatcherTrailEntry entry) + { + Scale = entry.Scale; + Position = new Vector2(entry.Position, 0); + Alpha = 1; + + body.AnimationState.Value = entry.CatcherState; + + using (BeginAbsoluteSequence(entry.LifetimeStart, false)) + applyTransforms(entry.Animation); + } + + protected override void OnFree(CatcherTrailEntry entry) { ClearTransforms(); - Alpha = 1; - base.FreeAfterUse(); + } + + private void applyTransforms(CatcherTrailAnimation animation) + { + switch (animation) + { + case CatcherTrailAnimation.Dashing: + case CatcherTrailAnimation.HyperDashing: + this.FadeTo(0.4f).FadeOut(800, Easing.OutQuint); + break; + + case CatcherTrailAnimation.HyperDashAfterimage: + this.MoveToOffset(new Vector2(0, -10), 1200, Easing.In); + this.ScaleTo(Scale * 0.95f).ScaleTo(Scale * 1.2f, 1200, Easing.In); + this.FadeOut(1200); + break; + } + + Expire(); } } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs new file mode 100644 index 0000000000..3ea99badc1 --- /dev/null +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailAnimation.cs @@ -0,0 +1,12 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Rulesets.Catch.UI +{ + public enum CatcherTrailAnimation + { + Dashing, + HyperDashing, + HyperDashAfterimage + } +} diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs index abc76fc925..f451f84c95 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailDisplay.cs @@ -2,12 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Pooling; using osu.Game.Rulesets.Catch.Skinning; +using osu.Game.Rulesets.Objects.Pooling; using osu.Game.Skinning; -using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.UI @@ -16,7 +17,7 @@ namespace osu.Game.Rulesets.Catch.UI /// Represents a component responsible for displaying /// the appropriate catcher trails when requested to. /// - public class CatcherTrailDisplay : SkinReloadableDrawable + public class CatcherTrailDisplay : PooledDrawableWithLifetimeContainer { /// /// The most recent time a dash trail was added to this container. @@ -29,12 +30,17 @@ namespace osu.Game.Rulesets.Catch.UI public Color4 HyperDashAfterImageColour => hyperDashAfterImages.Colour; + protected override bool RemoveRewoundEntry => true; + private readonly DrawablePool trailPool; private readonly Container dashTrails; private readonly Container hyperDashTrails; private readonly Container hyperDashAfterImages; + [Resolved] + private ISkinSource skin { get; set; } + public CatcherTrailDisplay() { RelativeSizeAxes = Axes.Both; @@ -48,50 +54,60 @@ namespace osu.Game.Rulesets.Catch.UI }; } - protected override void SkinChanged(ISkinSource skin) + protected override void LoadComplete() { - base.SkinChanged(skin); + base.LoadComplete(); + skin.SourceChanged += skinSourceChanged; + skinSourceChanged(); + } + + private void skinSourceChanged() + { hyperDashTrails.Colour = skin.GetConfig(CatchSkinColour.HyperDash)?.Value ?? Catcher.DEFAULT_HYPER_DASH_COLOUR; hyperDashAfterImages.Colour = skin.GetConfig(CatchSkinColour.HyperDashAfterImage)?.Value ?? hyperDashTrails.Colour; } - /// - /// Displays a hyper-dash after-image of the catcher. - /// - public void DisplayHyperDashAfterImage(CatcherAnimationState animationState, float x, Vector2 scale) + protected override void AddDrawable(CatcherTrailEntry entry, CatcherTrail drawable) { - var trail = createTrail(animationState, x, scale); + switch (entry.Animation) + { + case CatcherTrailAnimation.Dashing: + dashTrails.Add(drawable); + break; - hyperDashAfterImages.Add(trail); + case CatcherTrailAnimation.HyperDashing: + hyperDashTrails.Add(drawable); + break; - trail.MoveToOffset(new Vector2(0, -10), 1200, Easing.In); - trail.ScaleTo(trail.Scale * 0.95f).ScaleTo(trail.Scale * 1.2f, 1200, Easing.In); - trail.FadeOut(1200); - trail.Expire(true); + case CatcherTrailAnimation.HyperDashAfterimage: + hyperDashAfterImages.Add(drawable); + break; + } } - public void DisplayDashTrail(CatcherAnimationState animationState, float x, Vector2 scale, bool hyperDashing) + protected override void RemoveDrawable(CatcherTrailEntry entry, CatcherTrail drawable) { - var trail = createTrail(animationState, x, scale); + switch (entry.Animation) + { + case CatcherTrailAnimation.Dashing: + dashTrails.Remove(drawable); + break; - if (hyperDashing) - hyperDashTrails.Add(trail); - else - dashTrails.Add(trail); + case CatcherTrailAnimation.HyperDashing: + hyperDashTrails.Remove(drawable); + break; - trail.FadeTo(0.4f).FadeOut(800, Easing.OutQuint); - trail.Expire(true); + case CatcherTrailAnimation.HyperDashAfterimage: + hyperDashAfterImages.Remove(drawable); + break; + } } - private CatcherTrail createTrail(CatcherAnimationState animationState, float x, Vector2 scale) + protected override CatcherTrail GetDrawable(CatcherTrailEntry entry) { CatcherTrail trail = trailPool.Get(); - - trail.AnimationState = animationState; - trail.Scale = scale; - trail.Position = new Vector2(x, 0); - + trail.Apply(entry); return trail; } @@ -107,5 +123,13 @@ namespace osu.Game.Rulesets.Catch.UI return maxTime; } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (skin != null) + skin.SourceChanged -= skinSourceChanged; + } } } diff --git a/osu.Game.Rulesets.Catch/UI/CatcherTrailEntry.cs b/osu.Game.Rulesets.Catch/UI/CatcherTrailEntry.cs new file mode 100644 index 0000000000..3a40ab26cc --- /dev/null +++ b/osu.Game.Rulesets.Catch/UI/CatcherTrailEntry.cs @@ -0,0 +1,31 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics.Performance; +using osuTK; + +namespace osu.Game.Rulesets.Catch.UI +{ + public class CatcherTrailEntry : LifetimeEntry + { + public readonly CatcherAnimationState CatcherState; + + public readonly float Position; + + /// + /// The scaling of the catcher body. It also represents a flipped catcher (negative x component). + /// + public readonly Vector2 Scale; + + public readonly CatcherTrailAnimation Animation; + + public CatcherTrailEntry(double startTime, CatcherAnimationState catcherState, float position, Vector2 scale, CatcherTrailAnimation animation) + { + LifetimeStart = startTime; + CatcherState = catcherState; + Position = position; + Scale = scale; + Animation = animation; + } + } +}