1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 03:15:36 +08:00

Fix DrawableStoryboardAnimation to handle skin fallback frame count similar to stable

Reasoning is explained in the inline comment (basically, stable doesn't
care what the user specifies as the frame count when falling back to
skin resources).

This change also removes on to two layers of drawables, which should be
a win in heavy storyboards.
This commit is contained in:
Dean Herbert 2022-04-07 17:26:31 +09:00
parent 93bdca5211
commit cbc4e5319d
3 changed files with 66 additions and 28 deletions

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.IO;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Animations;
@ -98,17 +99,55 @@ namespace osu.Game.Storyboards.Drawables
return new Vector2(texture?.DisplayWidth ?? 0, texture?.DisplayHeight ?? 0);
}
[Resolved]
private ISkinSource skin { get; set; }
[BackgroundDependencyLoader]
private void load(TextureStore textureStore, Storyboard storyboard)
{
for (int frameIndex = 0; frameIndex < Animation.FrameCount; frameIndex++)
int frameIndex = 0;
Texture frameTexture = storyboard.GetTextureFromPath(getFramePath(frameIndex), textureStore);
if (frameTexture != null)
{
string framePath = Animation.Path.Replace(".", frameIndex + ".");
Drawable frame = storyboard.CreateSpriteFromResourcePath(framePath, textureStore) ?? Empty();
AddFrame(frame, Animation.FrameDelay);
// sourcing from storyboard.
for (frameIndex = 0; frameIndex < Animation.FrameCount; frameIndex++)
{
frameTexture = storyboard.GetTextureFromPath(getFramePath(frameIndex), textureStore);
AddFrame(new Sprite { Texture = frameTexture }, Animation.FrameDelay);
}
}
else if (storyboard.UseSkinSprites)
{
// fallback to skin if required.
skin.SourceChanged += skinSourceChanged;
skinSourceChanged();
}
Animation.ApplyTransforms(this);
}
private void skinSourceChanged()
{
ClearFrames();
// ClearFrames doesn't clear the last displayed frame.
// Clear manually for now, in case the skin doesn't provide any frames.
DisplayFrame(Empty());
// When reading from a skin, we match stables weird behaviour where `FrameCount` is ignored
// and resources are retrieved until the end of the animation.
foreach (var texture in skin.GetTextures(Path.GetFileNameWithoutExtension(Animation.Path), default, default, true, string.Empty, out _))
AddFrame(new Sprite { Texture = texture }, Animation.FrameDelay);
}
private string getFramePath(int i) => Animation.Path.Replace(".", $"{i}.");
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
skin.SourceChanged -= skinSourceChanged;
}
}
}

View File

@ -4,14 +4,15 @@
using System;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Framework.Utils;
using osu.Game.Skinning;
using osuTK;
namespace osu.Game.Storyboards.Drawables
{
public class DrawableStoryboardSprite : CompositeDrawable, IFlippable, IVectorScalable
public class DrawableStoryboardSprite : Sprite, IFlippable, IVectorScalable
{
public StoryboardSprite Sprite { get; }
@ -85,19 +86,31 @@ namespace osu.Game.Storyboards.Drawables
LifetimeStart = sprite.StartTime;
LifetimeEnd = sprite.EndTime;
AutoSizeAxes = Axes.Both;
}
[Resolved]
private ISkinSource skin { get; set; }
[BackgroundDependencyLoader]
private void load(TextureStore textureStore, Storyboard storyboard)
{
var drawable = storyboard.CreateSpriteFromResourcePath(Sprite.Path, textureStore);
Texture = storyboard.GetTextureFromPath(Sprite.Path, textureStore);
if (drawable != null)
InternalChild = drawable;
if (Texture == null && storyboard.UseSkinSprites)
{
skin.SourceChanged += skinSourceChanged;
skinSourceChanged();
}
Sprite.ApplyTransforms(this);
}
private void skinSourceChanged() => Texture = skin.GetTexture(Sprite.Path);
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
skin.SourceChanged -= skinSourceChanged;
}
}
}

View File

@ -4,13 +4,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Game.Beatmaps;
using osu.Game.Extensions;
using osu.Game.Rulesets.Mods;
using osu.Game.Skinning;
using osu.Game.Storyboards.Drawables;
namespace osu.Game.Storyboards
@ -94,25 +91,14 @@ namespace osu.Game.Storyboards
public DrawableStoryboard CreateDrawable(IReadOnlyList<Mod> mods = null) =>
new DrawableStoryboard(this, mods);
public Drawable CreateSpriteFromResourcePath(string path, TextureStore textureStore)
public Texture GetTextureFromPath(string path, TextureStore textureStore)
{
Drawable drawable = null;
string storyboardPath = BeatmapInfo.BeatmapSet?.Files.FirstOrDefault(f => f.Filename.Equals(path, StringComparison.OrdinalIgnoreCase))?.File.GetStoragePath();
if (!string.IsNullOrEmpty(storyboardPath))
drawable = new Sprite { Texture = textureStore.Get(storyboardPath) };
// if the texture isn't available locally in the beatmap, some storyboards choose to source from the underlying skin lookup hierarchy.
else if (UseSkinSprites)
{
drawable = new SkinnableSprite(path)
{
RelativeSizeAxes = Axes.None,
AutoSizeAxes = Axes.Both,
};
}
return textureStore.Get(storyboardPath);
return drawable;
return null;
}
}
}