diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs index 593a0d18dd..afc23921bf 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/LegacySliderBall.cs @@ -1,8 +1,10 @@ // 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.Extensions.ObjectExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -15,31 +17,41 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy { public partial class LegacySliderBall : CompositeDrawable { - private readonly Drawable animationContent; - private readonly ISkin skin; [Resolved(canBeNull: true)] private DrawableHitObject? parentObject { get; set; } - public Color4 BallColour => animationContent.Colour; - private Sprite layerNd = null!; + private Drawable ball = null!; private Sprite layerSpec = null!; - public LegacySliderBall(Drawable animationContent, ISkin skin) + public Color4 BallColour => ball.Colour; + + public LegacySliderBall(ISkin skin) { - this.animationContent = animationContent; this.skin = skin; AutoSizeAxes = Axes.Both; } [BackgroundDependencyLoader] - private void load() + private void load(DrawableHitObject drawableHitObject) { var ballColour = skin.GetConfig(OsuSkinColour.SliderBall)?.Value ?? Color4.White; + DrawableSlider drawableSlider = (DrawableSlider)drawableHitObject; + + // stable apparently calculates slider velocity in units of seconds rather than milliseconds. + double stableSliderVelocity = drawableSlider.HitObject.Velocity * 1000; + + double ballAnimationRate = Math.Max( + 150 / stableSliderVelocity * LegacySkinExtensions.SIXTY_FRAME_TIME, + LegacySkinExtensions.SIXTY_FRAME_TIME); + + ball = skin.GetAnimation("sliderb", true, true, animationSeparator: "", frameLength: ballAnimationRate, + maxSize: OsuLegacySkinTransformer.MAX_FOLLOW_CIRCLE_AREA_SIZE).AsNonNull(); + InternalChildren = new[] { layerNd = new Sprite @@ -49,7 +61,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy Texture = skin.GetTexture("sliderb-nd")?.WithMaximumSize(OsuLegacySkinTransformer.MAX_FOLLOW_CIRCLE_AREA_SIZE), Colour = new Color4(5, 5, 5, 255), }, - LegacyColourCompatibility.ApplyWithDoubledAlpha(animationContent.With(d => + LegacyColourCompatibility.ApplyWithDoubledAlpha(ball.With(d => { d.Anchor = Anchor.Centre; d.Origin = Anchor.Centre; @@ -78,7 +90,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy if (skin.GetConfig(SkinConfiguration.LegacySetting.AllowSliderBallTint)?.Value == true) { accentColour.BindTo(parentObject.AccentColour); - accentColour.BindValueChanged(a => animationContent.Colour = a.NewValue, true); + accentColour.BindValueChanged(a => ball.Colour = a.NewValue, true); } } } diff --git a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs index 3002cbe0ae..1de8fefaae 100644 --- a/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/Legacy/OsuLegacySkinTransformer.cs @@ -59,13 +59,8 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy return null; case OsuSkinComponents.SliderBall: - var sliderBallContent = this.GetAnimation("sliderb", true, true, animationSeparator: "", maxSize: MAX_FOLLOW_CIRCLE_AREA_SIZE); - - // todo: slider ball has a custom frame delay based on velocity - // Math.Max((150 / Velocity) * GameBase.SIXTY_FRAME_TIME, GameBase.SIXTY_FRAME_TIME); - - if (sliderBallContent != null) - return new LegacySliderBall(sliderBallContent, this); + if (GetTexture("sliderb") != null || GetTexture("sliderb0") != null) + return new LegacySliderBall(this); return null; diff --git a/osu.Game/Skinning/LegacySkinExtensions.cs b/osu.Game/Skinning/LegacySkinExtensions.cs index 868f36fb34..62197fa8a7 100644 --- a/osu.Game/Skinning/LegacySkinExtensions.cs +++ b/osu.Game/Skinning/LegacySkinExtensions.cs @@ -200,7 +200,11 @@ namespace osu.Game.Skinning } } - private const double default_frame_time = 1000 / 60d; + /// + /// The frame length of each frame at a 60 FPS rate. + /// Default frame rate for legacy skin animations. + /// + public const double SIXTY_FRAME_TIME = 1000 / 60d; private static double getFrameLength(ISkin source, bool applyConfigFrameRate, Texture[] textures) { @@ -214,7 +218,7 @@ namespace osu.Game.Skinning return 1000f / textures.Length; } - return default_frame_time; + return SIXTY_FRAME_TIME; } } }