From 80ce78e05dc2e97947c21520fb9fc7264259a9ea Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 19 Oct 2023 13:59:07 +0300 Subject: [PATCH 1/9] Remove animation support from osu! hit circle overlay --- .../Skinning/Legacy/LegacyMainCirclePiece.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs index 3ec914596a..d8d86d1802 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyMainCirclePiece.cs @@ -14,6 +14,7 @@ using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Skinning; +using osuTK; using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Skinning.Legacy @@ -62,12 +63,14 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy // otherwise fall back to the default prefix "hitcircle". string circleName = (priorityLookupPrefix != null && skin.GetTexture(priorityLookupPrefix) != null) ? priorityLookupPrefix : @"hitcircle"; + Vector2 maxSize = OsuHitObject.OBJECT_DIMENSIONS * 2; + // at this point, any further texture fetches should be correctly using the priority source if the base texture was retrieved using it. // the conditional above handles the case where a sliderendcircle.png is retrieved from the skin, but sliderendcircleoverlay.png doesn't exist. // expected behaviour in this scenario is not showing the overlay, rather than using hitcircleoverlay.png. InternalChildren = new[] { - CircleSprite = new LegacyKiaiFlashingDrawable(() => new Sprite { Texture = skin.GetTexture(circleName)?.WithMaximumSize(OsuHitObject.OBJECT_DIMENSIONS * 2) }) + CircleSprite = new LegacyKiaiFlashingDrawable(() => new Sprite { Texture = skin.GetTexture(circleName)?.WithMaximumSize(maxSize) }) { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -76,7 +79,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Child = OverlaySprite = new LegacyKiaiFlashingDrawable(() => skin.GetAnimation(@$"{circleName}overlay", true, true, frameLength: 1000 / 2d, maxSize: OsuHitObject.OBJECT_DIMENSIONS * 2)) + Child = OverlaySprite = new LegacyKiaiFlashingDrawable(() => new Sprite { Texture = skin.GetTexture(@$"{circleName}overlay")?.WithMaximumSize(maxSize) }) { Anchor = Anchor.Centre, Origin = Anchor.Centre, From 2a70c331b9f9730c6e775fe3962cf1bf1c1e5fd1 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 19 Oct 2023 14:01:13 +0300 Subject: [PATCH 2/9] Remove animation support from osu! slider reverse arrow --- .../Skinning/Legacy/LegacyReverseArrow.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyReverseArrow.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyReverseArrow.cs index a535fbdbc3..780084115d 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyReverseArrow.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacyReverseArrow.cs @@ -8,6 +8,7 @@ using osu.Framework.Bindables; using osu.Framework.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects.Drawables; @@ -41,11 +42,12 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy var skin = skinSource.FindProvider(s => s.GetTexture(lookupName) != null); - InternalChild = arrow = (skin?.GetAnimation(lookupName, true, true, maxSize: OsuHitObject.OBJECT_DIMENSIONS * 2) ?? Empty()).With(d => + InternalChild = arrow = new Sprite { - d.Anchor = Anchor.Centre; - d.Origin = Anchor.Centre; - }); + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Texture = skin?.GetTexture(lookupName)?.WithMaximumSize(maxSize: OsuHitObject.OBJECT_DIMENSIONS * 2), + }; textureIsDefaultSkin = skin is ISkinTransformer transformer && transformer.Skin is DefaultLegacySkin; From badb1310a38484955250757f78c3103be93d38c2 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 19 Oct 2023 14:00:13 +0300 Subject: [PATCH 3/9] Adjust frame length of osu!mania judgement animation --- .../Skinning/Legacy/ManiaLegacySkinTransformer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs index 446dfae0f6..73c521b2ed 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/ManiaLegacySkinTransformer.cs @@ -138,7 +138,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy string filename = this.GetManiaSkinConfig(hit_result_mapping[result])?.Value ?? default_hit_result_skin_filenames[result]; - var animation = this.GetAnimation(filename, true, true); + var animation = this.GetAnimation(filename, true, true, frameLength: 1000 / 20d); return animation == null ? null : new LegacyManiaJudgementPiece(result, animation); } From 517d0f65b646daa784423dfdf1aae528f8448aaa Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 21 Oct 2023 00:22:29 +0300 Subject: [PATCH 4/9] Adjust frame length of osu!mania hold-note body animation --- osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs index 66e67136df..ee274fc45e 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs @@ -91,7 +91,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy direction.BindTo(scrollingInfo.Direction); isHitting.BindTo(holdNote.IsHitting); - bodySprite = skin.GetAnimation(imageName, wrapMode, wrapMode, true, true).With(d => + bodySprite = skin.GetAnimation(imageName, wrapMode, wrapMode, true, true, frameLength: 30).With(d => { if (d == null) return; From 491f119988f37e6264ccb7ebe3dfe3bb9e9d4b36 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Wed, 18 Oct 2023 20:56:17 +0300 Subject: [PATCH 5/9] Add animation support for legacy osu!mania column lights --- .../special-skin/mania/stage-light-0.png | Bin 0 -> 5122 bytes .../special-skin/mania/stage-light-1.png | Bin 0 -> 5124 bytes .../special-skin/mania/stage-light-2.png | Bin 0 -> 5126 bytes .../special-skin/mania/stage-light-3.png | Bin 0 -> 5125 bytes .../Resources/special-skin/skin.ini | 2 ++ .../Skinning/Legacy/LegacyColumnBackground.cs | 22 +++++++++--------- .../Skinning/LegacyManiaSkinConfiguration.cs | 1 + .../LegacyManiaSkinConfigurationLookup.cs | 3 ++- osu.Game/Skinning/LegacyManiaSkinDecoder.cs | 5 ++++ osu.Game/Skinning/LegacySkin.cs | 3 +++ 10 files changed, 24 insertions(+), 12 deletions(-) create mode 100644 osu.Game.Rulesets.Mania.Tests/Resources/special-skin/mania/stage-light-0.png create mode 100644 osu.Game.Rulesets.Mania.Tests/Resources/special-skin/mania/stage-light-1.png create mode 100644 osu.Game.Rulesets.Mania.Tests/Resources/special-skin/mania/stage-light-2.png create mode 100644 osu.Game.Rulesets.Mania.Tests/Resources/special-skin/mania/stage-light-3.png diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/special-skin/mania/stage-light-0.png b/osu.Game.Rulesets.Mania.Tests/Resources/special-skin/mania/stage-light-0.png new file mode 100644 index 0000000000000000000000000000000000000000..5044c2d15f038bd606159113b8d44da9b86557e4 GIT binary patch literal 5122 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 HJumaW3u|fS literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/special-skin/mania/stage-light-3.png b/osu.Game.Rulesets.Mania.Tests/Resources/special-skin/mania/stage-light-3.png new file mode 100644 index 0000000000000000000000000000000000000000..8f9155b8f770ee62fa9cbe53ffc6f7fb191a561d GIT binary patch literal 5125 zcmeHLc~}$I77vT42nYy@NHIn%0!}iSWCDpqf=PskQDhZ`*2!c7QL>OsAmV}|%BCP7 zDvQFiDrze}A8r*~sQS5!yrQ&dm4~&Ix=@$atv-7bP~pA)q2E{k<9^>HlY7tkopXNo zH|NWp-0+zp_O|Y}6bi*&5-N%S-w3!~46y;9x3gT5C=|L zq$Q|?QK_I%jBWQz!~W&rV<+zX>YFfu^HdpkNpa52V8(HVSM;*z+H-Xw1xZ7u_+&Zq z1gr1f%1}I8A-c%)LYpRZ=B%IY8{hoUSaW1yp0aiF&?;tnX?9!_Md%gw_`gq-Lw+AKMv?A?VZY$~P&ktRxt>-`PhO4up zb5+-8jqkp7&hh9!9Bm&@@NznEHboFqL^asoYuiX`JCeP7=aq-n7SCO35`F!?yKwc% z?5@%cOLqMB^QyGDxrKQRgSbK03m*wyl%02YwXw9M%JcYnY4_-H$HW<>-0Y^KiTAed zSQFk^x9dzy>hN^?ut`GC_PGVCx5C)uQSvjp9#nH=h4x=ZjM@YLm!>D8S z3uZUpY+aS?VKu~QLrj3s(z1Hm*7ZK_bxz~fIS5>9>%7!d!S29zFYh8d&SA+M_sBH| zef@+U)HAq^vu~VTa$eMl>5`OXlem||qno$wj*}+jUz@}wE^+65RwzUFxy*nn%I59+ zrQ_Vyx{CTydspSRH@6h$yE3-7vxFvY~wSh6+@({c6GOZzEf`)Em0D zw>AoGZWb10+m9t$^64Ji{SwmeT%aF6AMIVxwjTbrrL0C;MO^bnd9A!uMH@&)-9(pdelma5 zvrmtledTm$e%Gooujya^^UBha8+&g|nLXyNe~bUVmm_Pdr#0TM__yEUJJ%#T4jvBr z)$XP$N0WI=_1gbQtedk(>2FQ1hsWs|Rq?}r%A`;%vXnw$xI`#?qk5qA%B4m8(31kU z)wg!!Mfhf>IvUP~Z=RHs7qGxJFMM2!?H=By_!onv?!_*nLK+XWw>QbIHlB`)9UL3% z_=iP`Atiz=ay}kr3&|R8AI^Sy?CG5clLb3BmMIKttjg6DyF~F9<*}!0W3#S=jBqP1 zBQ8oJoR8hU>uGW9)@kF0j327L2)PtzHzem&-9=c{Vc*duz24q1%L5a~O_<{C$?D2H zRTv)|xa@YkHm<$QiM6@hyTCDj6(^=`ldE*CF)v{E0^XfrqYI-i&#OG3D@D7{eeQO- z%kM&b4Z6m96WYA!#+jg>Urf;X{OG%)2)A%eT9**?Z0sKo z_LNpt{#yJ^O7-K@DO08`uT7|)t*`9H&nPP?jfw5kHP8JF^M5LNGB+&W)8gp$6Q>Pf zk-sm$@X7r4bL*tvmuBwITHpv8V14RkC&>ZOu9)6BR$aBrGs(5Pk;av`5KM;cBQYIFpZO=r_#NNiN5BD5*C)IgnF!HW=0>xBTn z__QRF)bbdNw6rvO8jG&cB{G;?E|&o#3&?TG8k>d;^nNR^!J&4Ne7cxX54S(xlq99SJ(we;h z+5Id@rQ#h~{cP;vl;a{N(Tj6Q;9zfKB_t1JwX# zF_TaMfY}2S!xQQVjMV6&G@4{S&6E?>o`Gbg zd5KCj>z0S%JwfzXDj_!q0)9P9coL>gB)|jStEe~g%D>nxf`!SM1i^whI0`5x6kLd_ z;1G~PA%_EG{&E(A{|~xeqaf2T9TA)eDh1U51(~a%PVC{*r++eONrZ_g7-2z77-9xQ zAutc+@=(+dX7ON{#`yR(0vQn)#tDF!CM~gnv>_RcA`nOlh?|9=1pDuO+Jfy*z;;%G zL%tbuE7WeOsJwx-GP0wpwd5-od5u@iAbrH6x$jrX>s3+7?qA02;B6gGw|vj>XlYKV z&ye>YXQ5NhW31nEY;%**hav0o4n?GnvgkKPHx1kJ*`VF=lTXr3>`BBkMYU7sXZ{I_ C94z$! literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Mania.Tests/Resources/special-skin/skin.ini b/osu.Game.Rulesets.Mania.Tests/Resources/special-skin/skin.ini index 7c51036d69..3a9d465f8d 100644 --- a/osu.Game.Rulesets.Mania.Tests/Resources/special-skin/skin.ini +++ b/osu.Game.Rulesets.Mania.Tests/Resources/special-skin/skin.ini @@ -4,6 +4,7 @@ Version: 2.5 [Mania] Keys: 4 ColumnLineWidth: 3,1,3,1,1 +LightFramePerSecond: 15 // some skins found in the wild had configuration keys where the @2x suffix was included in the values. // the expected compatibility behaviour is that the presence of the @2x suffix shouldn't change anything // if @2x assets are present. @@ -15,5 +16,6 @@ Hit300: mania/hit300@2x Hit300g: mania/hit300g@2x StageLeft: mania/stage-left StageRight: mania/stage-right +StageLight: mania/stage-light NoteImage0L: LongNoteTailWang NoteImage1L: LongNoteTailWang diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs index ab996519a7..4c65707d70 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs @@ -5,7 +5,6 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Bindings; using osu.Framework.Input.Events; using osu.Game.Rulesets.UI.Scrolling; @@ -20,7 +19,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy private readonly IBindable direction = new Bindable(); private Container lightContainer = null!; - private Sprite light = null!; + private Drawable? light = null!; public LegacyColumnBackground() { @@ -39,6 +38,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy Color4 lightColour = GetColumnSkinConfig(skin, LegacyManiaSkinConfigurationLookups.ColumnLightColour)?.Value ?? Color4.White; + int lightFramePerSecond = skin.GetManiaSkinConfig(LegacyManiaSkinConfigurationLookups.LightFramePerSecond)?.Value ?? 60; + InternalChildren = new[] { lightContainer = new Container @@ -46,16 +47,15 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy Origin = Anchor.BottomCentre, RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Bottom = lightPosition }, - Child = light = new Sprite + Child = light = skin.GetAnimation(lightImage, true, true, frameLength: 1000d / lightFramePerSecond)?.With(l => { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Colour = LegacyColourCompatibility.DisallowZeroAlpha(lightColour), - Texture = skin.GetTexture(lightImage), - RelativeSizeAxes = Axes.X, - Width = 1, - Alpha = 0 - } + l.Anchor = Anchor.BottomCentre; + l.Origin = Anchor.BottomCentre; + l.Colour = LegacyColourCompatibility.DisallowZeroAlpha(lightColour); + l.RelativeSizeAxes = Axes.X; + l.Width = 1; + l.Alpha = 0; + }) ?? Empty(), } }; diff --git a/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs b/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs index f1c99a315d..9acb29a793 100644 --- a/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs +++ b/osu.Game/Skinning/LegacyManiaSkinConfiguration.cs @@ -40,6 +40,7 @@ namespace osu.Game.Skinning public float ScorePosition = 300 * POSITION_SCALE_FACTOR; public bool ShowJudgementLine = true; public bool KeysUnderNotes; + public int LightFramePerSecond = 60; public LegacyNoteBodyStyle? NoteBodyStyle; diff --git a/osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs b/osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs index 784e57708e..cacca0de23 100644 --- a/osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs +++ b/osu.Game/Skinning/LegacyManiaSkinConfigurationLookup.cs @@ -74,6 +74,7 @@ namespace osu.Game.Skinning Hit50, Hit0, KeysUnderNotes, - NoteBodyStyle + NoteBodyStyle, + LightFramePerSecond } } diff --git a/osu.Game/Skinning/LegacyManiaSkinDecoder.cs b/osu.Game/Skinning/LegacyManiaSkinDecoder.cs index e880e3c1ed..b472afb74f 100644 --- a/osu.Game/Skinning/LegacyManiaSkinDecoder.cs +++ b/osu.Game/Skinning/LegacyManiaSkinDecoder.cs @@ -123,6 +123,11 @@ namespace osu.Game.Skinning currentConfig.WidthForNoteHeightScale = (float.Parse(pair.Value, CultureInfo.InvariantCulture)) * LegacyManiaSkinConfiguration.POSITION_SCALE_FACTOR; break; + case "LightFramePerSecond": + int lightFramePerSecond = int.Parse(pair.Value, CultureInfo.InvariantCulture); + currentConfig.LightFramePerSecond = lightFramePerSecond > 0 ? lightFramePerSecond : 24; + break; + case string when pair.Key.StartsWith("Colour", StringComparison.Ordinal): HandleColours(currentConfig, line, true); break; diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 76190d0abe..dc683f1dae 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -273,6 +273,9 @@ namespace osu.Game.Skinning case LegacyManiaSkinConfigurationLookups.KeysUnderNotes: return SkinUtils.As(new Bindable(existing.KeysUnderNotes)); + + case LegacyManiaSkinConfigurationLookups.LightFramePerSecond: + return SkinUtils.As(new Bindable(existing.LightFramePerSecond)); } return null; From ab3b51e4a0a9042d1b20d08d64b2c47b2b6848bb Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 19 Oct 2023 14:02:46 +0300 Subject: [PATCH 6/9] Refactor osu!taiko circle piece logic to read better --- .../Skinning/Legacy/LegacyCirclePiece.cs | 48 +++++++++++-------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs index 4dce3f1d4a..b512a46ce1 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy private static readonly Vector2 max_circle_sprite_size = new Vector2(160); private Drawable backgroundLayer = null!; - private Drawable? foregroundLayer; + private TextureAnimation? foregroundLayer; private Bindable currentCombo { get; } = new BindableInt(); @@ -48,40 +48,44 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy [BackgroundDependencyLoader] private void load(ISkinSource skin, DrawableHitObject drawableHitObject, IBeatSyncProvider? beatSyncProvider) { - Drawable? getDrawableFor(string lookup) + Drawable? getDrawableFor(string lookup, bool animatable) { const string normal_hit = "taikohit"; const string big_hit = "taikobig"; string prefix = ((drawableHitObject.HitObject as TaikoStrongableHitObject)?.IsStrong ?? false) ? big_hit : normal_hit; - return skin.GetAnimation($"{prefix}{lookup}", true, false, maxSize: max_circle_sprite_size) ?? + return skin.GetAnimation($"{prefix}{lookup}", animatable, false, maxSize: max_circle_sprite_size) ?? // fallback to regular size if "big" version doesn't exist. - skin.GetAnimation($"{normal_hit}{lookup}", true, false, maxSize: max_circle_sprite_size); + skin.GetAnimation($"{normal_hit}{lookup}", animatable, false, maxSize: max_circle_sprite_size); } // backgroundLayer is guaranteed to exist due to the pre-check in TaikoLegacySkinTransformer. - AddInternal(backgroundLayer = new LegacyKiaiFlashingDrawable(() => getDrawableFor("circle"))); + AddInternal(backgroundLayer = new LegacyKiaiFlashingDrawable(() => getDrawableFor("circle", false)) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }); + + foregroundLayer = (TextureAnimation?)getDrawableFor("circleoverlay", true); - foregroundLayer = getDrawableFor("circleoverlay"); if (foregroundLayer != null) + { + foregroundLayer.Anchor = Anchor.Centre; + foregroundLayer.Origin = Anchor.Centre; + + // Animations in taiko skins are used in a custom way (>150 combo and animating in time with beat). + // For now just stop at first frame for sanity. + foregroundLayer.Stop(); + AddInternal(foregroundLayer); + } drawableHitObject.StartTimeBindable.BindValueChanged(startTime => { timingPoint = beatSyncProvider?.ControlPoints?.TimingPointAt(startTime.NewValue) ?? TimingControlPoint.DEFAULT; }, true); - // Animations in taiko skins are used in a custom way (>150 combo and animating in time with beat). - // For now just stop at first frame for sanity. - foreach (var c in InternalChildren) - { - (c as IFramedAnimation)?.Stop(); - - c.Anchor = Anchor.Centre; - c.Origin = Anchor.Centre; - } - if (gameplayState != null) currentCombo.BindTo(gameplayState.ScoreProcessor.Combo); } @@ -101,12 +105,14 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy foreach (var c in InternalChildren) c.Scale = new Vector2(DrawHeight / circle_piece_size.Y); - if (foregroundLayer is IFramedAnimation animatableForegroundLayer) - animateForegroundLayer(animatableForegroundLayer); + animateForegroundLayer(); } - private void animateForegroundLayer(IFramedAnimation animatableForegroundLayer) + private void animateForegroundLayer() { + if (foregroundLayer == null) + return; + int multiplier; if (currentCombo.Value >= 150) @@ -119,12 +125,12 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy } else { - animatableForegroundLayer.GotoFrame(0); + foregroundLayer.GotoFrame(0); return; } animationFrame = Math.Abs(Time.Current - timingPoint.Time) % ((timingPoint.BeatLength * 2) / multiplier) >= timingPoint.BeatLength / multiplier ? 0 : 1; - animatableForegroundLayer.GotoFrame(animationFrame); + foregroundLayer.GotoFrame(animationFrame); } private Color4 accentColour; From 976ae62214a2314f2d2baa1249f6276374327e7e Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Sat, 21 Oct 2023 01:10:06 +0300 Subject: [PATCH 7/9] Fix incorrect nullability specification --- .../Skinning/Legacy/LegacyColumnBackground.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs index 4c65707d70..914ed79234 100644 --- a/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs +++ b/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyColumnBackground.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy private readonly IBindable direction = new Bindable(); private Container lightContainer = null!; - private Drawable? light = null!; + private Drawable light = null!; public LegacyColumnBackground() { From bcbb77d3839028edf18535ac7976668c02cc7c6f Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 24 Oct 2023 02:29:07 +0300 Subject: [PATCH 8/9] Fix incorrect assumption in taiko circle piece logic --- .../Skinning/Legacy/LegacyCirclePiece.cs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs index b512a46ce1..dbc8718f02 100644 --- a/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs +++ b/osu.Game.Rulesets.Taiko/Skinning/Legacy/LegacyCirclePiece.cs @@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy private static readonly Vector2 max_circle_sprite_size = new Vector2(160); private Drawable backgroundLayer = null!; - private TextureAnimation? foregroundLayer; + private Drawable? foregroundLayer; private Bindable currentCombo { get; } = new BindableInt(); @@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy Origin = Anchor.Centre }); - foregroundLayer = (TextureAnimation?)getDrawableFor("circleoverlay", true); + foregroundLayer = getDrawableFor("circleoverlay", true); if (foregroundLayer != null) { @@ -76,7 +76,8 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy // Animations in taiko skins are used in a custom way (>150 combo and animating in time with beat). // For now just stop at first frame for sanity. - foregroundLayer.Stop(); + if (foregroundLayer is IFramedAnimation animatedForegroundLayer) + animatedForegroundLayer.Stop(); AddInternal(foregroundLayer); } @@ -105,14 +106,12 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy foreach (var c in InternalChildren) c.Scale = new Vector2(DrawHeight / circle_piece_size.Y); - animateForegroundLayer(); + if (foregroundLayer is IFramedAnimation animatedForegroundLayer) + animateForegroundLayer(animatedForegroundLayer); } - private void animateForegroundLayer() + private void animateForegroundLayer(IFramedAnimation animation) { - if (foregroundLayer == null) - return; - int multiplier; if (currentCombo.Value >= 150) @@ -125,12 +124,12 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy } else { - foregroundLayer.GotoFrame(0); + animation.GotoFrame(0); return; } animationFrame = Math.Abs(Time.Current - timingPoint.Time) % ((timingPoint.BeatLength * 2) / multiplier) >= timingPoint.BeatLength / multiplier ? 0 : 1; - foregroundLayer.GotoFrame(animationFrame); + animation.GotoFrame(animationFrame); } private Color4 accentColour; From e949b1f613a3015c4a8ae91a76e87e2229711570 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Thu, 26 Oct 2023 10:36:57 +0300 Subject: [PATCH 9/9] Fix failing tests --- osu.Game.Rulesets.Osu.Tests/LegacyMainCirclePieceTest.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu.Tests/LegacyMainCirclePieceTest.cs b/osu.Game.Rulesets.Osu.Tests/LegacyMainCirclePieceTest.cs index baaa24959f..5ad268a77b 100644 --- a/osu.Game.Rulesets.Osu.Tests/LegacyMainCirclePieceTest.cs +++ b/osu.Game.Rulesets.Osu.Tests/LegacyMainCirclePieceTest.cs @@ -93,7 +93,7 @@ namespace osu.Game.Rulesets.Osu.Tests Child = piece = new TestLegacyMainCirclePiece(priorityLookup), }; - var sprites = this.ChildrenOfType().Where(s => !string.IsNullOrEmpty(s.Texture.AssetName)).DistinctBy(s => s.Texture.AssetName).ToArray(); + var sprites = this.ChildrenOfType().Where(s => !string.IsNullOrEmpty(s.Texture?.AssetName)).DistinctBy(s => s.Texture.AssetName).ToArray(); Debug.Assert(sprites.Length <= 2); }); @@ -103,8 +103,8 @@ namespace osu.Game.Rulesets.Osu.Tests private partial class TestLegacyMainCirclePiece : LegacyMainCirclePiece { - public new Sprite? CircleSprite => base.CircleSprite.ChildrenOfType().DistinctBy(s => s.Texture.AssetName).SingleOrDefault(); - public new Sprite? OverlaySprite => base.OverlaySprite.ChildrenOfType().DistinctBy(s => s.Texture.AssetName).SingleOrDefault(); + public new Sprite? CircleSprite => base.CircleSprite.ChildrenOfType().Where(s => !string.IsNullOrEmpty(s.Texture?.AssetName)).DistinctBy(s => s.Texture.AssetName).SingleOrDefault(); + public new Sprite? OverlaySprite => base.OverlaySprite.ChildrenOfType().Where(s => !string.IsNullOrEmpty(s.Texture?.AssetName)).DistinctBy(s => s.Texture.AssetName).SingleOrDefault(); public TestLegacyMainCirclePiece(string? priorityLookupPrefix) : base(priorityLookupPrefix, false)