Use SkinnableSprite to avoid unnecessary reloads

This commit is contained in:
Bartłomiej Dach 2020-10-19 22:27:59 +02:00
parent f41fc71e42
commit e54836a63e
2 changed files with 24 additions and 67 deletions

View File

@ -2,13 +2,12 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using System.Collections.Generic;
using System.IO;
using osuTK; using osuTK;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Animations;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using osu.Framework.Utils; using osu.Framework.Utils;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
@ -16,18 +15,10 @@ using osu.Game.Skinning;
namespace osu.Game.Storyboards.Drawables namespace osu.Game.Storyboards.Drawables
{ {
public class DrawableStoryboardAnimation : SkinReloadableDrawable, IFlippable, IVectorScalable public class DrawableStoryboardAnimation : DrawableAnimation, IFlippable, IVectorScalable
{ {
public StoryboardAnimation Animation { get; } public StoryboardAnimation Animation { get; }
private TextureAnimation drawableTextureAnimation;
[Resolved]
private TextureStore storyboardTextureStore { get; set; }
private readonly List<string> texturePathsRaw = new List<string>();
private readonly List<string> texturePaths = new List<string>();
private bool flipH; private bool flipH;
public bool FlipH public bool FlipH
@ -119,48 +110,31 @@ namespace osu.Game.Storyboards.Drawables
Animation = animation; Animation = animation;
Origin = animation.Origin; Origin = animation.Origin;
Position = animation.InitialPosition; Position = animation.InitialPosition;
Loop = animation.LoopType == AnimationLoopType.LoopForever;
LifetimeStart = animation.StartTime; LifetimeStart = animation.StartTime;
LifetimeEnd = animation.EndTime; LifetimeEnd = animation.EndTime;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(IBindable<WorkingBeatmap> beatmap) private void load(IBindable<WorkingBeatmap> beatmap, TextureStore textureStore)
{ {
InternalChild = drawableTextureAnimation = new TextureAnimation
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Loop = Animation.LoopType == AnimationLoopType.LoopForever
};
for (var frame = 0; frame < Animation.FrameCount; frame++) for (var frame = 0; frame < Animation.FrameCount; frame++)
{ {
var framePath = Animation.Path.Replace(".", frame + "."); var framePath = Animation.Path.Replace(".", frame + ".");
texturePathsRaw.Add(Path.GetFileNameWithoutExtension(framePath));
var path = beatmap.Value.BeatmapSetInfo.Files.Find(f => f.Filename.Equals(framePath, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath; var storyboardPath = beatmap.Value.BeatmapSetInfo.Files.Find(f => f.Filename.Equals(framePath, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath;
texturePaths.Add(path); var frameSprite = storyboardPath != null
? (Drawable)new Sprite
{
Texture = textureStore.Get(storyboardPath)
}
: new SkinnableSprite(framePath); // fall back to skin textures if not found in storyboard files.
AddFrame(frameSprite, Animation.FrameDelay);
} }
Animation.ApplyTransforms(this); Animation.ApplyTransforms(this);
} }
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
{
base.SkinChanged(skin, allowFallback);
drawableTextureAnimation.ClearFrames();
for (var frame = 0; frame < Animation.FrameCount; frame++)
{
var texture = skin?.GetTexture(texturePathsRaw[frame]) ?? storyboardTextureStore?.Get(texturePaths[frame]);
if (texture == null)
continue;
drawableTextureAnimation.AddFrame(texture, Animation.FrameDelay);
}
}
} }
} }

View File

@ -2,11 +2,11 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using System.IO;
using osuTK; using osuTK;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using osu.Framework.Utils; using osu.Framework.Utils;
@ -15,17 +15,10 @@ using osu.Game.Skinning;
namespace osu.Game.Storyboards.Drawables namespace osu.Game.Storyboards.Drawables
{ {
public class DrawableStoryboardSprite : SkinReloadableDrawable, IFlippable, IVectorScalable public class DrawableStoryboardSprite : CompositeDrawable, IFlippable, IVectorScalable
{ {
public StoryboardSprite Sprite { get; } public StoryboardSprite Sprite { get; }
private Sprite drawableSprite;
[Resolved]
private TextureStore storyboardTextureStore { get; set; }
private string texturePath;
private bool flipH; private bool flipH;
public bool FlipH public bool FlipH
@ -123,29 +116,19 @@ namespace osu.Game.Storyboards.Drawables
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(IBindable<WorkingBeatmap> beatmap) private void load(IBindable<WorkingBeatmap> beatmap, TextureStore textureStore)
{ {
InternalChild = drawableSprite = new Sprite var storyboardPath = beatmap.Value.BeatmapSetInfo?.Files?.Find(f => f.Filename.Equals(Sprite.Path, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath;
var sprite = storyboardPath != null
? (Drawable)new Sprite
{ {
Anchor = Anchor.Centre, Texture = textureStore.Get(storyboardPath)
Origin = Anchor.Centre }
}; : new SkinnableSprite(Sprite.Path); // fall back to skin textures if not found in storyboard files.
texturePath = beatmap.Value.BeatmapSetInfo?.Files?.Find(f => f.Filename.Equals(Sprite.Path, StringComparison.OrdinalIgnoreCase))?.FileInfo.StoragePath; InternalChild = sprite.With(s => s.Anchor = s.Origin = Anchor.Centre);
Sprite.ApplyTransforms(this); Sprite.ApplyTransforms(this);
} }
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
{
base.SkinChanged(skin, allowFallback);
var newTexture = skin?.GetTexture(Path.GetFileNameWithoutExtension(Sprite.Path)) ?? storyboardTextureStore?.Get(texturePath);
if (drawableSprite.Texture == newTexture) return;
drawableSprite.Size = Vector2.Zero; // Sprite size needs to be recalculated (e.g. aspect ratio of combo number textures may differ between skins)
drawableSprite.Texture = newTexture;
}
} }
} }