From 544685be4863631b47df94f19d4f6307cb014d71 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Feb 2020 14:58:29 +0900 Subject: [PATCH] Add support for reading skin frame rate from configuration file --- .../Skinning/OsuLegacySkinTransformer.cs | 9 ++- osu.Game/Skinning/GlobalSkinConfiguration.cs | 1 + osu.Game/Skinning/LegacySkinExtensions.cs | 72 +++++++++++-------- 3 files changed, 51 insertions(+), 31 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index 266b619334..d6c3f443eb 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -46,17 +46,20 @@ namespace osu.Game.Rulesets.Osu.Skinning switch (osuComponent.Component) { case OsuSkinComponents.FollowPoint: - return this.GetAnimation(component.LookupName, true, false); + return this.GetAnimation(component.LookupName, true, false, true); case OsuSkinComponents.SliderFollowCircle: - var followCircle = this.GetAnimation("sliderfollowcircle", true, true); + var followCircle = this.GetAnimation("sliderfollowcircle", true, true, true); if (followCircle != null) // follow circles are 2x the hitcircle resolution in legacy skins (since they are scaled down from >1x followCircle.Scale *= 0.5f; return followCircle; case OsuSkinComponents.SliderBall: - var sliderBallContent = this.GetAnimation("sliderb", true, true, ""); + var sliderBallContent = this.GetAnimation("sliderb", true, true, animationSeparator: ""); + + // 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) { diff --git a/osu.Game/Skinning/GlobalSkinConfiguration.cs b/osu.Game/Skinning/GlobalSkinConfiguration.cs index 0532e64546..8774fe5a97 100644 --- a/osu.Game/Skinning/GlobalSkinConfiguration.cs +++ b/osu.Game/Skinning/GlobalSkinConfiguration.cs @@ -5,5 +5,6 @@ namespace osu.Game.Skinning { public enum GlobalSkinConfiguration { + AnimationFramerate } } diff --git a/osu.Game/Skinning/LegacySkinExtensions.cs b/osu.Game/Skinning/LegacySkinExtensions.cs index c758b699ed..fa4de21eec 100644 --- a/osu.Game/Skinning/LegacySkinExtensions.cs +++ b/osu.Game/Skinning/LegacySkinExtensions.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Sprites; @@ -10,48 +12,62 @@ namespace osu.Game.Skinning { public static class LegacySkinExtensions { - public static Drawable GetAnimation(this ISkin source, string componentName, bool animatable, bool looping, string animationSeparator = "-") + public static Drawable GetAnimation(this ISkin source, string componentName, bool animatable, bool looping, bool applyConfigFrameRate = false, string animationSeparator = "-") { - const double default_frame_time = 1000 / 60d; - Texture texture; - Texture getFrameTexture(int frame) => source.GetTexture($"{componentName}{animationSeparator}{frame}"); - - TextureAnimation animation = null; - if (animatable) { - for (int i = 0; true; i++) + var textures = getTextures().ToArray(); + + if (textures.Length > 0) { - if ((texture = getFrameTexture(i)) == null) - break; - - if (animation == null) + var animation = new TextureAnimation { - animation = new TextureAnimation - { - DefaultFrameLength = default_frame_time, - Repeat = looping - }; - } + DefaultFrameLength = getFrameLength(source, applyConfigFrameRate, textures), + Repeat = looping, + }; - animation.AddFrame(texture); + foreach (var t in textures) + animation.AddFrame(t); + + return animation; } } - if (animation != null) - return animation; - + // if an animation was not allowed or not found, fall back to a sprite retrieval. if ((texture = source.GetTexture(componentName)) != null) - { - return new Sprite - { - Texture = texture - }; - } + return new Sprite { Texture = texture }; return null; + + IEnumerable getTextures() + { + for (int i = 0; true; i++) + { + if ((texture = source.GetTexture($"{componentName}{animationSeparator}{i}")) == null) + break; + + yield return texture; + } + } + } + + private const double default_frame_time = 1000 / 60d; + + private static double getFrameLength(ISkin source, bool applyConfigFrameRate, Texture[] textures) + { + if (applyConfigFrameRate) + { + var iniRate = source.GetConfig(GlobalSkinConfiguration.AnimationFramerate); + + if (iniRate != null) + return 1000f / iniRate.Value; + + return 1000f / textures.Length; + } + + return default_frame_time; } } }