From 8be31f4805385708909b4405dd3c2aeb427bda15 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 17 Nov 2020 23:55:21 +0900 Subject: [PATCH 01/18] Adjust legacy skin judgement transforms to match stable --- osu.Game/Skinning/LegacyJudgementPiece.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/LegacyJudgementPiece.cs b/osu.Game/Skinning/LegacyJudgementPiece.cs index 3def37e22c..44aa5106e2 100644 --- a/osu.Game/Skinning/LegacyJudgementPiece.cs +++ b/osu.Game/Skinning/LegacyJudgementPiece.cs @@ -14,6 +14,8 @@ namespace osu.Game.Skinning { private readonly HitResult result; + private bool hasParticle; + public LegacyJudgementPiece(HitResult result, Drawable drawable) { this.result = result; @@ -37,6 +39,8 @@ namespace osu.Game.Skinning if (animation?.FrameCount > 1) return; + const double animation_length = 500; + switch (result) { case HitResult.Miss: @@ -49,8 +53,19 @@ namespace osu.Game.Skinning break; default: - this.ScaleTo(0.9f); - this.ScaleTo(1, 500, Easing.OutElastic); + if (!hasParticle) + { + this.ScaleTo(0.6f).Then() + .ScaleTo(1.1f, animation_length * 0.8f).Then() + .ScaleTo(0.9f, animation_length * 0.4f).Then() + .ScaleTo(1f, animation_length * 0.2f); + } + else + { + this.ScaleTo(0.9f); + this.ScaleTo(1.05f, animation_length); + } + break; } } From 5bd4ace37f73cffd0550812e455bb7c3335cf623 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Nov 2020 15:38:26 +0900 Subject: [PATCH 02/18] Split out new and old style legacy judgement pieces --- osu.Game/Skinning/LegacyJudgementPieceNew.cs | 93 +++++++++++++++++++ ...entPiece.cs => LegacyJudgementPieceOld.cs} | 31 +++---- osu.Game/Skinning/LegacySkin.cs | 30 +++++- 3 files changed, 133 insertions(+), 21 deletions(-) create mode 100644 osu.Game/Skinning/LegacyJudgementPieceNew.cs rename osu.Game/Skinning/{LegacyJudgementPiece.cs => LegacyJudgementPieceOld.cs} (61%) diff --git a/osu.Game/Skinning/LegacyJudgementPieceNew.cs b/osu.Game/Skinning/LegacyJudgementPieceNew.cs new file mode 100644 index 0000000000..de77df9e10 --- /dev/null +++ b/osu.Game/Skinning/LegacyJudgementPieceNew.cs @@ -0,0 +1,93 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Animations; +using osu.Framework.Graphics.Containers; +using osu.Game.Rulesets.Judgements; +using osu.Game.Rulesets.Scoring; +using osuTK; + +namespace osu.Game.Skinning +{ + public class LegacyJudgementPieceNew : CompositeDrawable, IAnimatableJudgement + { + private readonly HitResult result; + + private readonly LegacyJudgementPieceOld temporaryOldStyle; + + private readonly Drawable mainPiece; + + public LegacyJudgementPieceNew(HitResult result, Func createMainDrawable, Drawable particleDrawable) + { + this.result = result; + + AutoSizeAxes = Axes.Both; + Origin = Anchor.Centre; + + InternalChildren = new[] + { + mainPiece = createMainDrawable().With(d => + { + d.Anchor = Anchor.Centre; + d.Origin = Anchor.Centre; + }) + }; + + if (result != HitResult.Miss) + { + //new judgement shows old as a temporary effect + AddInternal(temporaryOldStyle = new LegacyJudgementPieceOld(result, createMainDrawable, 1.05f) + { + Blending = BlendingParameters.Additive, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + }); + } + } + + public void PlayAnimation() + { + var animation = mainPiece as IFramedAnimation; + + animation?.GotoFrame(0); + + this.RotateTo(0); + this.MoveTo(Vector2.Zero); + + if (temporaryOldStyle != null) + { + temporaryOldStyle.PlayAnimation(); + + temporaryOldStyle.Hide(); + temporaryOldStyle.Delay(-16) + .FadeTo(0.5f, 56, Easing.Out).Then() + .FadeOut(300); + } + + // legacy judgements don't play any transforms if they are an animation. + if (animation?.FrameCount > 1) + return; + + switch (result) + { + case HitResult.Miss: + mainPiece.ScaleTo(1.6f); + mainPiece.ScaleTo(1, 100, Easing.In); + + mainPiece.MoveToOffset(new Vector2(0, 100), 800, Easing.InQuint); + + mainPiece.RotateTo(40, 800, Easing.InQuint); + break; + + default: + const double animation_length = 1100; + + mainPiece.ScaleTo(0.9f); + mainPiece.ScaleTo(1.05f, animation_length); + break; + } + } + } +} diff --git a/osu.Game/Skinning/LegacyJudgementPiece.cs b/osu.Game/Skinning/LegacyJudgementPieceOld.cs similarity index 61% rename from osu.Game/Skinning/LegacyJudgementPiece.cs rename to osu.Game/Skinning/LegacyJudgementPieceOld.cs index 44aa5106e2..63d2c44dd9 100644 --- a/osu.Game/Skinning/LegacyJudgementPiece.cs +++ b/osu.Game/Skinning/LegacyJudgementPieceOld.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Containers; @@ -10,20 +11,21 @@ using osuTK; namespace osu.Game.Skinning { - public class LegacyJudgementPiece : CompositeDrawable, IAnimatableJudgement + public class LegacyJudgementPieceOld : CompositeDrawable, IAnimatableJudgement { private readonly HitResult result; - private bool hasParticle; + private readonly float finalScale; - public LegacyJudgementPiece(HitResult result, Drawable drawable) + public LegacyJudgementPieceOld(HitResult result, Func createMainDrawable, float finalScale = 1f) { this.result = result; + this.finalScale = finalScale; AutoSizeAxes = Axes.Both; Origin = Anchor.Centre; - InternalChild = drawable; + InternalChild = createMainDrawable(); } public virtual void PlayAnimation() @@ -39,8 +41,6 @@ namespace osu.Game.Skinning if (animation?.FrameCount > 1) return; - const double animation_length = 500; - switch (result) { case HitResult.Miss: @@ -53,19 +53,14 @@ namespace osu.Game.Skinning break; default: - if (!hasParticle) - { - this.ScaleTo(0.6f).Then() - .ScaleTo(1.1f, animation_length * 0.8f).Then() - .ScaleTo(0.9f, animation_length * 0.4f).Then() - .ScaleTo(1f, animation_length * 0.2f); - } - else - { - this.ScaleTo(0.9f); - this.ScaleTo(1.05f, animation_length); - } + const double animation_length = 120; + this.ScaleTo(0.6f).Then() + .ScaleTo(1.1f, animation_length * 0.8f).Then() + // this is actually correct to match stable; there were overlapping transforms. + .ScaleTo(0.9f).Delay(animation_length * 0.2f) + .ScaleTo(1.1f).ScaleTo(0.9f, animation_length * 0.2f).Then() + .ScaleTo(0.95f).ScaleTo(finalScale, animation_length * 0.2f); break; } } diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index ca8bb58023..ce1a736f0a 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -371,9 +371,16 @@ namespace osu.Game.Skinning } case GameplaySkinComponent resultComponent: - var drawable = getJudgementAnimation(resultComponent.Component); - if (drawable != null) - return new LegacyJudgementPiece(resultComponent.Component, drawable); + Func createDrawable = () => getJudgementAnimation(resultComponent.Component); + + if (createDrawable() != null) + { + var particles = getParticleTexture(resultComponent.Component); + if (particles != null) + return new LegacyJudgementPieceNew(resultComponent.Component, createDrawable, getParticleTexture(resultComponent.Component)); + else + return new LegacyJudgementPieceOld(resultComponent.Component, createDrawable); + } break; } @@ -381,6 +388,23 @@ namespace osu.Game.Skinning return this.GetAnimation(component.LookupName, false, false); } + private Drawable getParticleTexture(HitResult result) + { + switch (result) + { + case HitResult.Meh: + return this.GetAnimation("particle50", false, false); + + case HitResult.Ok: + return this.GetAnimation("particle100", false, false); + + case HitResult.Great: + return this.GetAnimation("particle300", false, false); + } + + return null; + } + private Drawable getJudgementAnimation(HitResult result) { switch (result) From 94886a09b23b2c7d850781eaa20c07b0697a2d3c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Nov 2020 15:39:02 +0900 Subject: [PATCH 03/18] Remove fades from DrawableJudgement itself --- .../UI/DrawableManiaJudgement.cs | 7 +++---- .../Objects/Drawables/DrawableOsuJudgement.cs | 14 +++----------- osu.Game/Rulesets/Judgements/DrawableJudgement.cs | 11 +++++++---- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs index ebce40a785..a341cdd8ec 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs @@ -19,15 +19,14 @@ namespace osu.Game.Rulesets.Mania.UI { } - protected override double FadeInDuration => 50; - protected override void ApplyHitAnimations() { JudgementBody.ScaleTo(0.8f); JudgementBody.ScaleTo(1, 250, Easing.OutElastic); - JudgementBody.Delay(FadeInDuration).ScaleTo(0.75f, 250); - this.Delay(FadeInDuration).FadeOut(200); + JudgementBody.Delay(50) + .ScaleTo(0.75f, 250) + .FadeOut(200); } protected override Drawable CreateDefaultJudgement(HitResult result) => new ManiaJudgementPiece(result); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs index 47fb53379f..90133fb01c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs @@ -44,26 +44,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } - private double fadeOutDelay; - protected override double FadeOutDelay => fadeOutDelay; - protected override void ApplyHitAnimations() { bool hitLightingEnabled = config.Get(OsuSetting.HitLighting); if (hitLightingEnabled) { - JudgementBody.FadeIn().Delay(FadeInDuration).FadeOut(400); - Lighting.ScaleTo(0.8f).ScaleTo(1.2f, 600, Easing.Out); Lighting.FadeIn(200).Then().Delay(200).FadeOut(1000); - } - else - { - JudgementBody.Alpha = 1; - } - fadeOutDelay = hitLightingEnabled ? 1400 : base.FadeOutDelay; + // extend the lifetime to cover lighting fade + LifetimeEnd = 1400; + } base.ApplyHitAnimations(); } diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 468b3190b0..09b8353c63 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Diagnostics; using JetBrains.Annotations; using osu.Framework.Allocation; @@ -32,11 +33,13 @@ namespace osu.Game.Rulesets.Judgements /// /// Duration of initial fade in. /// + [Obsolete("Apply any animations manually via ApplyHitAnimations / ApplyMissAnimations. Defaults were moved inside skinned components.")] protected virtual double FadeInDuration => 100; /// /// Duration to wait until fade out begins. Defaults to . /// + [Obsolete("Apply any animations manually via ApplyHitAnimations / ApplyMissAnimations. Defaults were moved inside skinned components.")] protected virtual double FadeOutDelay => FadeInDuration; /// @@ -73,7 +76,6 @@ namespace osu.Game.Rulesets.Judgements /// protected virtual void ApplyHitAnimations() { - this.Delay(FadeOutDelay).FadeOut(400); } /// @@ -112,8 +114,6 @@ namespace osu.Game.Rulesets.Judgements // not sure if this should remain going forward. skinnableJudgement.ResetAnimation(); - this.FadeInFromZero(FadeInDuration, Easing.OutQuint); - switch (Result.Type) { case HitResult.None: @@ -134,7 +134,10 @@ namespace osu.Game.Rulesets.Judgements animatable.PlayAnimation(); } - Expire(true); + JudgementBody.Expire(true); + + LifetimeStart = JudgementBody.LifetimeStart; + LifetimeEnd = JudgementBody.LifetimeEnd; } private HitResult? currentDrawableType; From 25d4511e49d6c7db38eb8e6ab349bbfd2434a56b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Nov 2020 16:09:51 +0900 Subject: [PATCH 04/18] Fix judgement test scene always using hitobjects at t=0 --- osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs index 646f12f710..7ea2ef3a78 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs @@ -89,7 +89,13 @@ namespace osu.Game.Rulesets.Osu.Tests Children = new Drawable[] { pool, - pool.Get(j => j.Apply(new JudgementResult(new HitObject(), new Judgement()) { Type = result }, null)).With(j => + pool.Get(j => j.Apply(new JudgementResult(new HitObject + { + StartTime = Time.Current + }, new Judgement()) + { + Type = result, + }, null)).With(j => { j.Anchor = Anchor.Centre; j.Origin = Anchor.Centre; From 72a15ef2dc51f877dd1416128a43af38f2b718fd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Nov 2020 15:51:09 +0900 Subject: [PATCH 05/18] Handle DrawableJudgement lifetime more flexibly --- .../Objects/Drawables/DrawableOsuJudgement.cs | 2 +- .../Rulesets/Judgements/DrawableJudgement.cs | 51 +++++++++++-------- .../Judgements/IAnimatableJudgement.cs | 4 +- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs index 90133fb01c..b06c55102c 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs @@ -54,7 +54,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Lighting.FadeIn(200).Then().Delay(200).FadeOut(1000); // extend the lifetime to cover lighting fade - LifetimeEnd = 1400; + LifetimeEnd = Lighting.LatestTransformEndTime; } base.ApplyHitAnimations(); diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 09b8353c63..45b3e229f3 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -89,7 +89,6 @@ namespace osu.Game.Rulesets.Judgements /// protected virtual void ApplyMissAnimations() { - this.Delay(600).FadeOut(200); } /// @@ -111,33 +110,43 @@ namespace osu.Game.Rulesets.Judgements prepareDrawables(); - // not sure if this should remain going forward. - skinnableJudgement.ResetAnimation(); + LifetimeStart = Result.TimeAbsolute; - switch (Result.Type) + using (BeginAbsoluteSequence(Result.TimeAbsolute, true)) { - case HitResult.None: - break; + // not sure if this should remain going forward. + skinnableJudgement.ResetAnimation(); - case HitResult.Miss: - ApplyMissAnimations(); - break; + switch (Result.Type) + { + case HitResult.None: + break; - default: - ApplyHitAnimations(); - break; - } + case HitResult.Miss: + ApplyMissAnimations(); + break; + + default: + ApplyHitAnimations(); + break; + } + + if (skinnableJudgement.Drawable is IAnimatableJudgement animatable) + { + var drawableAnimation = (Drawable)animatable; + + drawableAnimation.ClearTransforms(); - if (skinnableJudgement.Drawable is IAnimatableJudgement animatable) - { - using (BeginAbsoluteSequence(Result.TimeAbsolute)) animatable.PlayAnimation(); + + drawableAnimation.Expire(true); + + // a derived version of DrawableJudgement may be adjusting lifetime. + // if not adjusted (or the skinned portion requires greater bounds than calculated) use the skinned source's lifetime. + if (LifetimeEnd == double.MaxValue || drawableAnimation.LifetimeEnd > LifetimeEnd) + LifetimeEnd = drawableAnimation.LifetimeEnd; + } } - - JudgementBody.Expire(true); - - LifetimeStart = JudgementBody.LifetimeStart; - LifetimeEnd = JudgementBody.LifetimeEnd; } private HitResult? currentDrawableType; diff --git a/osu.Game/Rulesets/Judgements/IAnimatableJudgement.cs b/osu.Game/Rulesets/Judgements/IAnimatableJudgement.cs index 3d5bbe6dad..32312f1115 100644 --- a/osu.Game/Rulesets/Judgements/IAnimatableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/IAnimatableJudgement.cs @@ -1,12 +1,14 @@ // 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; + namespace osu.Game.Rulesets.Judgements { /// /// A skinnable judgement element which supports playing an animation from the current point in time. /// - public interface IAnimatableJudgement + public interface IAnimatableJudgement : IDrawable { void PlayAnimation(); } From 9d0a6de26e6039cf87dfd8c64f1f0ffb7f3643d1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Nov 2020 16:18:27 +0900 Subject: [PATCH 06/18] Fix SkinnableSprite initialising a drawable even when the texture is not available --- osu.Game/Skinning/SkinnableSprite.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/osu.Game/Skinning/SkinnableSprite.cs b/osu.Game/Skinning/SkinnableSprite.cs index 5352928ec6..1340d1474c 100644 --- a/osu.Game/Skinning/SkinnableSprite.cs +++ b/osu.Game/Skinning/SkinnableSprite.cs @@ -24,7 +24,15 @@ namespace osu.Game.Skinning { } - protected override Drawable CreateDefault(ISkinComponent component) => new Sprite { Texture = textures.Get(component.LookupName) }; + protected override Drawable CreateDefault(ISkinComponent component) + { + var texture = textures.Get(component.LookupName); + + if (texture == null) + return null; + + return new Sprite { Texture = texture }; + } private class SpriteComponent : ISkinComponent { From 9d3de5bca0441ea4b04cab337c9ccdc074b170ae Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Nov 2020 16:18:58 +0900 Subject: [PATCH 07/18] Fix hit lighting dictating lifetime even when not present in skin --- .../Objects/Drawables/DrawableOsuJudgement.cs | 2 +- osu.Game/Rulesets/Judgements/DrawableJudgement.cs | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs index b06c55102c..c81cfd97dd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs @@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { bool hitLightingEnabled = config.Get(OsuSetting.HitLighting); - if (hitLightingEnabled) + if (hitLightingEnabled && Lighting.Drawable != null) { Lighting.ScaleTo(0.8f).ScaleTo(1.2f, 600, Easing.Out); Lighting.FadeIn(200).Then().Delay(200).FadeOut(1000); diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 45b3e229f3..c0fcb1eb3c 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -139,12 +139,14 @@ namespace osu.Game.Rulesets.Judgements animatable.PlayAnimation(); - drawableAnimation.Expire(true); - // a derived version of DrawableJudgement may be adjusting lifetime. // if not adjusted (or the skinned portion requires greater bounds than calculated) use the skinned source's lifetime. - if (LifetimeEnd == double.MaxValue || drawableAnimation.LifetimeEnd > LifetimeEnd) - LifetimeEnd = drawableAnimation.LifetimeEnd; + double lastTransformTime = drawableAnimation.LatestTransformEndTime; + + if (LifetimeEnd == double.MaxValue || lastTransformTime > LifetimeEnd) + { + LifetimeEnd = lastTransformTime; + } } } } From c47e70da9b4c6ac4ac337221b747f09ce3f5ab9c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Nov 2020 17:15:45 +0900 Subject: [PATCH 08/18] Update animations for new/old miss style and add fades --- .../Judgements/DefaultJudgementPiece.cs | 8 ++++-- osu.Game/Skinning/LegacyJudgementPieceNew.cs | 28 +++++++++++++------ osu.Game/Skinning/LegacyJudgementPieceOld.cs | 25 ++++++++++------- osu.Game/Skinning/LegacySkin.cs | 8 +++--- 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs b/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs index 7fe3917893..b89c1f4e4f 100644 --- a/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs +++ b/osu.Game/Rulesets/Judgements/DefaultJudgementPiece.cs @@ -47,18 +47,18 @@ namespace osu.Game.Rulesets.Judgements public virtual void PlayAnimation() { - this.RotateTo(0); - this.MoveTo(Vector2.Zero); - switch (Result) { case HitResult.Miss: this.ScaleTo(1.6f); this.ScaleTo(1, 100, Easing.In); + this.MoveTo(Vector2.Zero); this.MoveToOffset(new Vector2(0, 100), 800, Easing.InQuint); + this.RotateTo(0); this.RotateTo(40, 800, Easing.InQuint); + break; default: @@ -66,6 +66,8 @@ namespace osu.Game.Rulesets.Judgements this.ScaleTo(1, 500, Easing.OutElastic); break; } + + this.FadeOutFromOne(800); } } } diff --git a/osu.Game/Skinning/LegacyJudgementPieceNew.cs b/osu.Game/Skinning/LegacyJudgementPieceNew.cs index de77df9e10..d0a2f1d4eb 100644 --- a/osu.Game/Skinning/LegacyJudgementPieceNew.cs +++ b/osu.Game/Skinning/LegacyJudgementPieceNew.cs @@ -5,6 +5,7 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Containers; +using osu.Framework.Utils; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; using osuTK; @@ -53,9 +54,14 @@ namespace osu.Game.Skinning animation?.GotoFrame(0); - this.RotateTo(0); - this.MoveTo(Vector2.Zero); + const double fade_in_length = 120; + const double fade_out_delay = 500; + const double fade_out_length = 600; + this.FadeInFromZero(fade_in_length); + this.Delay(fade_out_delay).FadeOut(fade_out_length); + + // new style non-miss judgements show the original style temporarily, with additive colour. if (temporaryOldStyle != null) { temporaryOldStyle.PlayAnimation(); @@ -73,19 +79,23 @@ namespace osu.Game.Skinning switch (result) { case HitResult.Miss: - mainPiece.ScaleTo(1.6f); - mainPiece.ScaleTo(1, 100, Easing.In); + this.ScaleTo(1.6f); + this.ScaleTo(1, 100, Easing.In); - mainPiece.MoveToOffset(new Vector2(0, 100), 800, Easing.InQuint); + //todo: this only applies to osu! ruleset apparently. + this.MoveTo(new Vector2(0, -2)); + this.MoveToOffset(new Vector2(0, 20), fade_out_delay + fade_out_length, Easing.In); - mainPiece.RotateTo(40, 800, Easing.InQuint); + float rotation = RNG.NextSingle(-8.6f, 8.6f); + + this.RotateTo(0); + this.RotateTo(rotation, fade_in_length) + .Then().RotateTo(rotation * 2, fade_out_delay + fade_out_length - fade_in_length, Easing.In); break; default: - const double animation_length = 1100; - mainPiece.ScaleTo(0.9f); - mainPiece.ScaleTo(1.05f, animation_length); + mainPiece.ScaleTo(1.05f, fade_out_delay + fade_out_length); break; } } diff --git a/osu.Game/Skinning/LegacyJudgementPieceOld.cs b/osu.Game/Skinning/LegacyJudgementPieceOld.cs index 63d2c44dd9..3486dce081 100644 --- a/osu.Game/Skinning/LegacyJudgementPieceOld.cs +++ b/osu.Game/Skinning/LegacyJudgementPieceOld.cs @@ -5,9 +5,9 @@ using System; using osu.Framework.Graphics; using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Containers; +using osu.Framework.Utils; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; -using osuTK; namespace osu.Game.Skinning { @@ -34,8 +34,12 @@ namespace osu.Game.Skinning animation?.GotoFrame(0); - this.RotateTo(0); - this.MoveTo(Vector2.Zero); + const double fade_in_length = 120; + const double fade_out_delay = 500; + const double fade_out_length = 600; + + this.FadeInFromZero(fade_in_length); + this.Delay(fade_out_delay).FadeOut(fade_out_length); // legacy judgements don't play any transforms if they are an animation. if (animation?.FrameCount > 1) @@ -47,20 +51,21 @@ namespace osu.Game.Skinning this.ScaleTo(1.6f); this.ScaleTo(1, 100, Easing.In); - this.MoveToOffset(new Vector2(0, 100), 800, Easing.InQuint); + float rotation = RNG.NextSingle(-8.6f, 8.6f); - this.RotateTo(40, 800, Easing.InQuint); + this.RotateTo(0); + this.RotateTo(rotation, fade_in_length) + .Then().RotateTo(rotation * 2, fade_out_delay + fade_out_length - fade_in_length, Easing.In); break; default: - const double animation_length = 120; this.ScaleTo(0.6f).Then() - .ScaleTo(1.1f, animation_length * 0.8f).Then() + .ScaleTo(1.1f, fade_in_length * 0.8f).Then() // this is actually correct to match stable; there were overlapping transforms. - .ScaleTo(0.9f).Delay(animation_length * 0.2f) - .ScaleTo(1.1f).ScaleTo(0.9f, animation_length * 0.2f).Then() - .ScaleTo(0.95f).ScaleTo(finalScale, animation_length * 0.2f); + .ScaleTo(0.9f).Delay(fade_in_length * 0.2f) + .ScaleTo(1.1f).ScaleTo(0.9f, fade_in_length * 0.2f).Then() + .ScaleTo(0.95f).ScaleTo(finalScale, fade_in_length * 0.2f); break; } } diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index ce1a736f0a..9fbf3de043 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -373,11 +373,11 @@ namespace osu.Game.Skinning case GameplaySkinComponent resultComponent: Func createDrawable = () => getJudgementAnimation(resultComponent.Component); + // kind of wasteful that we throw this away, but should do for now. if (createDrawable() != null) { - var particles = getParticleTexture(resultComponent.Component); - if (particles != null) - return new LegacyJudgementPieceNew(resultComponent.Component, createDrawable, getParticleTexture(resultComponent.Component)); + if (Configuration.LegacyVersion > 1) + return new LegacyJudgementPieceNew(resultComponent.Component, createDrawable, getParticleDrawable(resultComponent.Component)); else return new LegacyJudgementPieceOld(resultComponent.Component, createDrawable); } @@ -388,7 +388,7 @@ namespace osu.Game.Skinning return this.GetAnimation(component.LookupName, false, false); } - private Drawable getParticleTexture(HitResult result) + private Drawable getParticleDrawable(HitResult result) { switch (result) { From d017e725fb87a1c3b22dfe17809defc002925db7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Nov 2020 17:15:53 +0900 Subject: [PATCH 09/18] Add comment for future todo task --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs index c81cfd97dd..9699fb72a4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs @@ -50,6 +50,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables if (hitLightingEnabled && Lighting.Drawable != null) { + // todo: this animation changes slightly based on new/old legacy skin versions. Lighting.ScaleTo(0.8f).ScaleTo(1.2f, 600, Easing.Out); Lighting.FadeIn(200).Then().Delay(200).FadeOut(1000); From ee8804b50b86e6d2bb85c18908f715fec0b599f3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Nov 2020 17:53:27 +0900 Subject: [PATCH 10/18] Fix animation playback not running on skin change --- .../Rulesets/Judgements/DrawableJudgement.cs | 39 ++++++++++++++++--- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index c0fcb1eb3c..85875e2f2a 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -28,8 +28,13 @@ namespace osu.Game.Rulesets.Judgements protected Container JudgementBody { get; private set; } + public override bool RemoveCompletedTransforms => false; + private SkinnableDrawable skinnableJudgement; + [Resolved] + private ISkinSource skinSource { get; set; } + /// /// Duration of initial fade in. /// @@ -65,6 +70,27 @@ namespace osu.Game.Rulesets.Judgements prepareDrawables(); } + protected override void LoadComplete() + { + base.LoadComplete(); + skinSource.SourceChanged += onSkinChanged; + } + + private void onSkinChanged() + { + // on a skin change, the child component will update but not get correctly triggered to play its animation. + // we need to trigger a reinitialisation to make things right. + currentDrawableType = null; + + PrepareForUse(); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + skinSource.SourceChanged -= onSkinChanged; + } + /// /// Apply top-level animations to the current judgement when successfully hit. /// Generally used for fading, defaulting to a simple fade out based on . @@ -110,6 +136,12 @@ namespace osu.Game.Rulesets.Judgements prepareDrawables(); + runAnimation(); + } + + private void runAnimation() + { + ClearTransforms(true); LifetimeStart = Result.TimeAbsolute; using (BeginAbsoluteSequence(Result.TimeAbsolute, true)) @@ -135,18 +167,13 @@ namespace osu.Game.Rulesets.Judgements { var drawableAnimation = (Drawable)animatable; - drawableAnimation.ClearTransforms(); - animatable.PlayAnimation(); - // a derived version of DrawableJudgement may be adjusting lifetime. + // a derived version of DrawableJudgement may be proposing a lifetime. // if not adjusted (or the skinned portion requires greater bounds than calculated) use the skinned source's lifetime. double lastTransformTime = drawableAnimation.LatestTransformEndTime; - if (LifetimeEnd == double.MaxValue || lastTransformTime > LifetimeEnd) - { LifetimeEnd = lastTransformTime; - } } } } From 1fd582d33341c396919d7f23920a18e55a00b982 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Nov 2020 19:12:29 +0900 Subject: [PATCH 11/18] Update lighting tests to not require lighting (some test skins are missing it) --- osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs index 7ea2ef3a78..b0119edc14 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs @@ -43,10 +43,8 @@ namespace osu.Game.Rulesets.Osu.Tests showResult(HitResult.Great); AddUntilStep("judgements shown", () => this.ChildrenOfType().Any()); - AddAssert("judgement body immediately visible", - () => this.ChildrenOfType().All(judgement => judgement.JudgementBody.Alpha == 1)); AddAssert("hit lighting hidden", - () => this.ChildrenOfType().All(judgement => judgement.Lighting.Alpha == 0)); + () => this.ChildrenOfType().All(judgement => !judgement.Lighting.Transforms.Any())); } [Test] @@ -57,10 +55,8 @@ namespace osu.Game.Rulesets.Osu.Tests showResult(HitResult.Great); AddUntilStep("judgements shown", () => this.ChildrenOfType().Any()); - AddAssert("judgement body not immediately visible", - () => this.ChildrenOfType().All(judgement => judgement.JudgementBody.Alpha > 0 && judgement.JudgementBody.Alpha < 1)); AddAssert("hit lighting shown", - () => this.ChildrenOfType().All(judgement => judgement.Lighting.Alpha > 0)); + () => this.ChildrenOfType().Any(judgement => judgement.Lighting.Transforms.Any())); } private void showResult(HitResult result) From 20bb64c627edd4043f6ff72886a2e91de506536c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Nov 2020 19:34:00 +0900 Subject: [PATCH 12/18] Fix mania misses not correctly animating (temporary solution) --- .../Skinning/TestSceneDrawableJudgement.cs | 5 +++- .../UI/DrawableManiaJudgement.cs | 28 +++++++++++++++++-- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneDrawableJudgement.cs index a4d4ec50f8..11536ac8c3 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneDrawableJudgement.cs @@ -24,7 +24,10 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning if (hitWindows.IsHitResultAllowed(result)) { AddStep("Show " + result.GetDescription(), () => SetContents(() => - new DrawableManiaJudgement(new JudgementResult(new HitObject(), new Judgement()) { Type = result }, null) + new DrawableManiaJudgement(new JudgementResult(new HitObject + { + StartTime = Time.Current + }, new Judgement()) { Type = result }, null) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs index a341cdd8ec..a3dcd0e57f 100644 --- a/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/UI/DrawableManiaJudgement.cs @@ -5,6 +5,7 @@ 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 { @@ -19,6 +20,27 @@ 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); @@ -29,11 +51,11 @@ namespace osu.Game.Rulesets.Mania.UI .FadeOut(200); } - protected override Drawable CreateDefaultJudgement(HitResult result) => new ManiaJudgementPiece(result); + protected override Drawable CreateDefaultJudgement(HitResult result) => new DefaultManiaJudgementPiece(result); - private class ManiaJudgementPiece : DefaultJudgementPiece + private class DefaultManiaJudgementPiece : DefaultJudgementPiece { - public ManiaJudgementPiece(HitResult result) + public DefaultManiaJudgementPiece(HitResult result) : base(result) { } From 8522ddc61e4d9a795feb290a66f1f3be6a948dfb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Nov 2020 19:34:27 +0900 Subject: [PATCH 13/18] Reduce nesting of skinned component to reduce exposed surface --- .../TestSceneDrawableJudgement.cs | 2 +- osu.Game/Rulesets/Judgements/DrawableJudgement.cs | 15 +++++---------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs index b0119edc14..1339d11ab6 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs @@ -108,7 +108,7 @@ namespace osu.Game.Rulesets.Osu.Tests private class TestDrawableOsuJudgement : DrawableOsuJudgement { public new SkinnableSprite Lighting => base.Lighting; - public new Container JudgementBody => base.JudgementBody; + public new SkinnableDrawable JudgementBody => base.JudgementBody; } } } diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 85875e2f2a..72ffa3a34b 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -6,7 +6,6 @@ using System.Diagnostics; using JetBrains.Annotations; using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Pooling; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Scoring; @@ -26,11 +25,9 @@ namespace osu.Game.Rulesets.Judgements public DrawableHitObject JudgedObject { get; private set; } - protected Container JudgementBody { get; private set; } - public override bool RemoveCompletedTransforms => false; - private SkinnableDrawable skinnableJudgement; + protected SkinnableDrawable JudgementBody { get; private set; } [Resolved] private ISkinSource skinSource { get; set; } @@ -147,7 +144,7 @@ namespace osu.Game.Rulesets.Judgements using (BeginAbsoluteSequence(Result.TimeAbsolute, true)) { // not sure if this should remain going forward. - skinnableJudgement.ResetAnimation(); + JudgementBody.ResetAnimation(); switch (Result.Type) { @@ -163,7 +160,7 @@ namespace osu.Game.Rulesets.Judgements break; } - if (skinnableJudgement.Drawable is IAnimatableJudgement animatable) + if (JudgementBody.Drawable is IAnimatableJudgement animatable) { var drawableAnimation = (Drawable)animatable; @@ -192,13 +189,11 @@ namespace osu.Game.Rulesets.Judgements if (JudgementBody != null) RemoveInternal(JudgementBody); - AddInternal(JudgementBody = new Container + AddInternal(JudgementBody = new SkinnableDrawable(new GameplaySkinComponent(type), _ => + CreateDefaultJudgement(type), confineMode: ConfineMode.NoScaling) { Anchor = Anchor.Centre, Origin = Anchor.Centre, - RelativeSizeAxes = Axes.Both, - Child = skinnableJudgement = new SkinnableDrawable(new GameplaySkinComponent(type), _ => - CreateDefaultJudgement(type), confineMode: ConfineMode.NoScaling) }); currentDrawableType = type; From b3bec81b79b5fa88edbce4ab7b322b10a9fb0db0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Nov 2020 19:38:38 +0900 Subject: [PATCH 14/18] Update xmldoc to match new behaviour --- osu.Game/Rulesets/Judgements/DrawableJudgement.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 72ffa3a34b..6407cb40aa 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -90,8 +90,7 @@ namespace osu.Game.Rulesets.Judgements /// /// Apply top-level animations to the current judgement when successfully hit. - /// Generally used for fading, defaulting to a simple fade out based on . - /// This will be used to calculate the lifetime of the judgement. + /// If displaying components which require lifetime extensions, manually adjusting is required. /// /// /// For animating the actual "default skin" judgement itself, it is recommended to use . @@ -103,8 +102,7 @@ namespace osu.Game.Rulesets.Judgements /// /// Apply top-level animations to the current judgement when missed. - /// Generally used for fading, defaulting to a simple fade out based on . - /// This will be used to calculate the lifetime of the judgement. + /// If displaying components which require lifetime extensions, manually adjusting is required. /// /// /// For animating the actual "default skin" judgement itself, it is recommended to use . From 191b95810ce519e6b9b3990ae105867b113f753a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 18 Nov 2020 19:47:35 +0900 Subject: [PATCH 15/18] Fix whitespace issues --- .../Skinning/TestSceneDrawableJudgement.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneDrawableJudgement.cs index 11536ac8c3..dcb25f21ba 100644 --- a/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Mania.Tests/Skinning/TestSceneDrawableJudgement.cs @@ -24,10 +24,10 @@ namespace osu.Game.Rulesets.Mania.Tests.Skinning if (hitWindows.IsHitResultAllowed(result)) { AddStep("Show " + result.GetDescription(), () => SetContents(() => - new DrawableManiaJudgement(new JudgementResult(new HitObject + new DrawableManiaJudgement(new JudgementResult(new HitObject { StartTime = Time.Current }, new Judgement()) { - StartTime = Time.Current - }, new Judgement()) { Type = result }, null) + Type = result + }, null) { Anchor = Anchor.Centre, Origin = Anchor.Centre, From 85c5c68dfac097bc15c9218853de000816b74f58 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Nov 2020 13:20:21 +0900 Subject: [PATCH 16/18] Provide particle drawable as a function (for future use) --- osu.Game/Skinning/LegacyJudgementPieceNew.cs | 2 +- osu.Game/Skinning/LegacySkin.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Skinning/LegacyJudgementPieceNew.cs b/osu.Game/Skinning/LegacyJudgementPieceNew.cs index d0a2f1d4eb..b5e1de337a 100644 --- a/osu.Game/Skinning/LegacyJudgementPieceNew.cs +++ b/osu.Game/Skinning/LegacyJudgementPieceNew.cs @@ -20,7 +20,7 @@ namespace osu.Game.Skinning private readonly Drawable mainPiece; - public LegacyJudgementPieceNew(HitResult result, Func createMainDrawable, Drawable particleDrawable) + public LegacyJudgementPieceNew(HitResult result, Func createMainDrawable, Func createParticleDrawable) { this.result = result; diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 9fbf3de043..6faee8c2e7 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -377,7 +377,7 @@ namespace osu.Game.Skinning if (createDrawable() != null) { if (Configuration.LegacyVersion > 1) - return new LegacyJudgementPieceNew(resultComponent.Component, createDrawable, getParticleDrawable(resultComponent.Component)); + return new LegacyJudgementPieceNew(resultComponent.Component, createDrawable, () => getParticleDrawable(resultComponent.Component)); else return new LegacyJudgementPieceOld(resultComponent.Component, createDrawable); } From ba735584faac6f0c5ab081cbd1fed06b3b0ec7ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Nov 2020 14:04:43 +0900 Subject: [PATCH 17/18] Add null check for disposal safety --- osu.Game/Rulesets/Judgements/DrawableJudgement.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs index 6407cb40aa..4aed38e689 100644 --- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs +++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs @@ -85,7 +85,9 @@ namespace osu.Game.Rulesets.Judgements protected override void Dispose(bool isDisposing) { base.Dispose(isDisposing); - skinSource.SourceChanged -= onSkinChanged; + + if (skinSource != null) + skinSource.SourceChanged -= onSkinChanged; } /// From 3024ae6d867b4eae0014aaba8d2ed7dbf0470bc5 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 19 Nov 2020 14:10:07 +0900 Subject: [PATCH 18/18] Add better test coverage of hit lighting (and ensure reset after animation reapplication) --- osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs | 7 +++---- .../Objects/Drawables/DrawableOsuJudgement.cs | 2 ++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs index 1339d11ab6..e4158d8f07 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs @@ -43,8 +43,8 @@ namespace osu.Game.Rulesets.Osu.Tests showResult(HitResult.Great); AddUntilStep("judgements shown", () => this.ChildrenOfType().Any()); - AddAssert("hit lighting hidden", - () => this.ChildrenOfType().All(judgement => !judgement.Lighting.Transforms.Any())); + AddAssert("hit lighting has no transforms", () => this.ChildrenOfType().All(judgement => !judgement.Lighting.Transforms.Any())); + AddAssert("hit lighting hidden", () => this.ChildrenOfType().All(judgement => judgement.Lighting.Alpha == 0)); } [Test] @@ -55,8 +55,7 @@ namespace osu.Game.Rulesets.Osu.Tests showResult(HitResult.Great); AddUntilStep("judgements shown", () => this.ChildrenOfType().Any()); - AddAssert("hit lighting shown", - () => this.ChildrenOfType().Any(judgement => judgement.Lighting.Transforms.Any())); + AddUntilStep("hit lighting shown", () => this.ChildrenOfType().Any(judgement => judgement.Lighting.Alpha > 0)); } private void showResult(HitResult result) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs index 9699fb72a4..13f5960bd4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuJudgement.cs @@ -48,6 +48,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { bool hitLightingEnabled = config.Get(OsuSetting.HitLighting); + Lighting.Alpha = 0; + if (hitLightingEnabled && Lighting.Drawable != null) { // todo: this animation changes slightly based on new/old legacy skin versions.