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:
parent
93bdca5211
commit
cbc4e5319d
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user