219 lines
7.9 KiB
C#
219 lines
7.9 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using NUnit.Framework;
|
|
using UnityEngine;
|
|
using UnityEngine.TestTools;
|
|
|
|
namespace AibisDream.FrameAnimation.Tests.PlayMode
|
|
{
|
|
/// <summary>
|
|
/// 帧动画组件的最小运行时集成测试。
|
|
/// 时间推进细节由 EditMode 的 PlaybackSession 契约覆盖。
|
|
/// </summary>
|
|
public sealed class FrameAnimationPlayerTests
|
|
{
|
|
private readonly List<UnityEngine.Object> createdObjects =
|
|
new List<UnityEngine.Object>();
|
|
|
|
[TearDown]
|
|
public void TearDown()
|
|
{
|
|
for (var index = createdObjects.Count - 1; index >= 0; index--)
|
|
{
|
|
if (createdObjects[index] != null)
|
|
UnityEngine.Object.DestroyImmediate(createdObjects[index]);
|
|
}
|
|
|
|
createdObjects.Clear();
|
|
}
|
|
|
|
[Test]
|
|
public void GraphPlayer_RendersAndAppliesTerminalBehavior()
|
|
{
|
|
var first = CreateSprite(Color.red);
|
|
var second = CreateSprite(Color.blue);
|
|
var clip = CreateClip(
|
|
"Clip",
|
|
FrameClipEndBehavior.Clear,
|
|
first,
|
|
second);
|
|
var graph = CreateGraph(clip);
|
|
var gameObject = Track(new GameObject("Graph Player"));
|
|
var renderer = gameObject.AddComponent<SpriteRenderer>();
|
|
var player = gameObject.AddComponent<FrameAnimationPlayer>();
|
|
player.ConfigureForAuthoring(graph, false, 1f);
|
|
|
|
var handle = player.Play(clip.Id);
|
|
Assert.That(renderer.sprite, Is.SameAs(first));
|
|
|
|
player.EvaluateForTests(0.2d);
|
|
|
|
Assert.That(handle.Result.Reason,
|
|
Is.EqualTo(FrameAnimationCompletionReason.Completed));
|
|
Assert.That(renderer.sprite, Is.Null);
|
|
Assert.That(renderer.enabled, Is.True);
|
|
}
|
|
|
|
[Test]
|
|
public void StandalonePlayer_PlaysConfiguredClipWithoutGraph()
|
|
{
|
|
var first = CreateSprite(Color.magenta);
|
|
var second = CreateSprite(Color.cyan);
|
|
var clip = CreateClip(
|
|
"Standalone",
|
|
FrameClipEndBehavior.HoldLastFrame,
|
|
first,
|
|
second);
|
|
var gameObject = Track(new GameObject("Standalone Player"));
|
|
var renderer = gameObject.AddComponent<SpriteRenderer>();
|
|
var player = gameObject.AddComponent<FrameClipPlayer>();
|
|
player.ConfigureForAuthoring(clip, false, 1f);
|
|
|
|
var handle = player.Play();
|
|
Assert.That(player.CurrentClip, Is.SameAs(clip));
|
|
player.EvaluateForTests(0.2d);
|
|
|
|
Assert.That(handle.Result.Reason,
|
|
Is.EqualTo(FrameAnimationCompletionReason.Completed));
|
|
Assert.That(renderer.sprite, Is.SameAs(second));
|
|
}
|
|
|
|
[Test]
|
|
public void PlayRequest_FailureKeepsActiveAndSuccessReplacesIt()
|
|
{
|
|
var first = CreateClip(
|
|
"First",
|
|
FrameClipEndBehavior.Loop,
|
|
CreateSprite(Color.white));
|
|
var second = CreateClip(
|
|
"Second",
|
|
FrameClipEndBehavior.Loop,
|
|
CreateSprite(Color.black));
|
|
var graph = CreateGraph(first, second);
|
|
var gameObject = Track(new GameObject("Request Arbitration"));
|
|
gameObject.AddComponent<SpriteRenderer>();
|
|
var player = gameObject.AddComponent<FrameAnimationPlayer>();
|
|
player.ConfigureForAuthoring(graph, false, 1f);
|
|
|
|
var active = player.Play(first.Id);
|
|
var failed = player.Play("Missing");
|
|
|
|
Assert.That(failed.Result.Error.Code,
|
|
Is.EqualTo(FrameAnimationPlaybackErrorCode.PlayableNotFound));
|
|
Assert.That(active.IsCompleted, Is.False);
|
|
Assert.That(player.CurrentPlayableId, Is.EqualTo(first.Id));
|
|
|
|
var replacement = player.Play(second.Id);
|
|
|
|
Assert.That(active.Result.Reason,
|
|
Is.EqualTo(FrameAnimationCompletionReason.Replaced));
|
|
Assert.That(replacement.IsCompleted, Is.False);
|
|
Assert.That(player.CurrentPlayableId, Is.EqualTo(second.Id));
|
|
}
|
|
|
|
[Test]
|
|
public void RestoreTerminalState_RebuildsSavedVisualState()
|
|
{
|
|
var terminalSprite = CreateSprite(Color.green);
|
|
var hold = CreateClip(
|
|
"Hold",
|
|
FrameClipEndBehavior.HoldLastFrame,
|
|
CreateSprite(Color.red),
|
|
terminalSprite);
|
|
var hidden = CreateClip(
|
|
"Hidden",
|
|
FrameClipEndBehavior.HideTarget,
|
|
CreateSprite(Color.blue));
|
|
var graph = CreateGraph(hold, hidden);
|
|
var gameObject = Track(new GameObject("Restore Terminal State"));
|
|
var renderer = gameObject.AddComponent<SpriteRenderer>();
|
|
var player = gameObject.AddComponent<FrameAnimationPlayer>();
|
|
player.ConfigureForAuthoring(graph, false, 1f);
|
|
|
|
var holdResult = player.RestoreTerminalState(hold.Id);
|
|
|
|
Assert.That(holdResult.Result.Reason,
|
|
Is.EqualTo(FrameAnimationCompletionReason.Completed));
|
|
Assert.That(renderer.sprite, Is.SameAs(terminalSprite));
|
|
Assert.That(renderer.enabled, Is.True);
|
|
|
|
player.RestoreTerminalState(hidden.Id);
|
|
|
|
Assert.That(renderer.enabled, Is.False);
|
|
}
|
|
|
|
[UnityTest]
|
|
public IEnumerator Disable_SettlesActiveRequestAsStopped()
|
|
{
|
|
var clip = CreateClip(
|
|
"Loop",
|
|
FrameClipEndBehavior.Loop,
|
|
CreateSprite(Color.white));
|
|
var gameObject = Track(new GameObject("Disable Player"));
|
|
gameObject.AddComponent<SpriteRenderer>();
|
|
var player = gameObject.AddComponent<FrameAnimationPlayer>();
|
|
player.ConfigureForAuthoring(CreateGraph(clip), false, 1f);
|
|
var handle = player.Play(clip.Id);
|
|
|
|
player.enabled = false;
|
|
yield return null;
|
|
|
|
Assert.That(handle.Result.Reason,
|
|
Is.EqualTo(FrameAnimationCompletionReason.Stopped));
|
|
Assert.That(player.State, Is.EqualTo(FrameAnimationPlaybackState.Stopped));
|
|
}
|
|
|
|
private FrameClip CreateClip(
|
|
string id,
|
|
FrameClipEndBehavior endBehavior,
|
|
params Sprite[] sprites)
|
|
{
|
|
var clip = Track(ScriptableObject.CreateInstance<FrameClip>());
|
|
var frames = new List<FrameAnimationFrame>();
|
|
for (var index = 0; index < sprites.Length; index++)
|
|
{
|
|
frames.Add(new FrameAnimationFrame(
|
|
sprites[index],
|
|
100,
|
|
$"frame_{index}",
|
|
index));
|
|
}
|
|
|
|
clip.Configure(id, id, frames, 1f, endBehavior);
|
|
return clip;
|
|
}
|
|
|
|
private FrameAnimationGraph CreateGraph(params FrameClip[] clips)
|
|
{
|
|
var graph = Track(ScriptableObject.CreateInstance<FrameAnimationGraph>());
|
|
graph.Configure(
|
|
"Graph",
|
|
"Graph",
|
|
clips,
|
|
Array.Empty<AnimationNode>(),
|
|
Array.Empty<AnimationEdge>(),
|
|
Array.Empty<AnimationFlow>(),
|
|
clips[0].Id);
|
|
return graph;
|
|
}
|
|
|
|
private Sprite CreateSprite(Color color)
|
|
{
|
|
var texture = Track(new Texture2D(2, 2));
|
|
texture.SetPixels(new[] { color, color, color, color });
|
|
texture.Apply();
|
|
return Track(Sprite.Create(
|
|
texture,
|
|
new Rect(0, 0, 2, 2),
|
|
new Vector2(0.5f, 0.5f)));
|
|
}
|
|
|
|
private T Track<T>(T value) where T : UnityEngine.Object
|
|
{
|
|
createdObjects.Add(value);
|
|
return value;
|
|
}
|
|
}
|
|
}
|