feat: 动画系统第五阶段(未验收)
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AibisDream.FrameAnimation.Editor
|
||||
{
|
||||
public static class FrameAnimationPreviewSampleBuilder
|
||||
{
|
||||
private const string Folder = "Assets/GameContent/Test/FrameAnimation/Preview";
|
||||
private const string GraphPath = Folder + "/PreviewSampleGraph.asset";
|
||||
private const string TexturePath = "Assets/GameContent/Test/AnimatorRaw/手接树叶特写.png";
|
||||
|
||||
[MenuItem("Tools/Frame Animation/Create Phase 5 Preview Sample")]
|
||||
public static void BuildFromCommandLine()
|
||||
{
|
||||
if (AssetDatabase.LoadAssetAtPath<FrameAnimationGraph>(GraphPath) != null)
|
||||
{
|
||||
Debug.Log($"Frame Animation preview sample already exists; preserved without overwrite: {GraphPath}");
|
||||
return;
|
||||
}
|
||||
EnsureFolder(Folder);
|
||||
var sprites = AssetDatabase.LoadAllAssetsAtPath(TexturePath).OfType<Sprite>()
|
||||
.OrderBy(sprite => sprite.name, StringComparer.Ordinal).ToArray();
|
||||
if (sprites.Length < 6)
|
||||
{
|
||||
throw new InvalidOperationException("第五阶段预览样例需要至少 6 个已切分 Sprite。");
|
||||
}
|
||||
|
||||
var graph = ScriptableObject.CreateInstance<FrameAnimationGraph>();
|
||||
graph.name = "PreviewSampleGraph";
|
||||
AssetDatabase.CreateAsset(graph, GraphPath);
|
||||
var action = CreateClip(graph, "PreviewAction", "Preview Action", FrameClipEndBehavior.HoldLastFrame,
|
||||
new[]
|
||||
{
|
||||
new FrameAnimationFrame(sprites[0], 100, sprites[0].name, 0),
|
||||
new FrameAnimationFrame(sprites[1], 160, sprites[1].name, 1),
|
||||
new FrameAnimationFrame(sprites[2], 220, sprites[2].name, 2)
|
||||
});
|
||||
var withEmpty = CreateClip(graph, "PreviewEmpty", "Preview Empty Frame", FrameClipEndBehavior.HoldLastFrame,
|
||||
new[]
|
||||
{
|
||||
new FrameAnimationFrame(sprites[3], 120, sprites[3].name, 3),
|
||||
new FrameAnimationFrame(null, 300, "empty", -1),
|
||||
new FrameAnimationFrame(sprites[4], 120, sprites[4].name, 4)
|
||||
});
|
||||
var idle = CreateClip(graph, "PreviewIdle", "Preview Idle Loop", FrameClipEndBehavior.Loop,
|
||||
new[]
|
||||
{
|
||||
new FrameAnimationFrame(sprites[4], 140, sprites[4].name, 4),
|
||||
new FrameAnimationFrame(sprites[5], 140, sprites[5].name, 5)
|
||||
});
|
||||
|
||||
var finiteA = new AnimationNode(action.Id, "Finite Action", speedOverride: 2f,
|
||||
internalId: "51000000000000000000000000000001");
|
||||
var finiteB = new AnimationNode(withEmpty.Id, "Finite Empty",
|
||||
endBehaviorOverride: FrameClipEndBehavior.HoldLastFrame,
|
||||
internalId: "51000000000000000000000000000002");
|
||||
var loopA = new AnimationNode(action.Id, "Loop Intro", internalId: "51000000000000000000000000000003");
|
||||
var loopB = new AnimationNode(idle.Id, "Loop Terminal",
|
||||
endBehaviorOverride: FrameClipEndBehavior.Loop,
|
||||
internalId: "51000000000000000000000000000004");
|
||||
var blocked = new AnimationNode(withEmpty.Id, "Zero Speed Block", speedOverride: 0f,
|
||||
internalId: "51000000000000000000000000000005");
|
||||
var clear = new AnimationNode(action.Id, "Clear Terminal",
|
||||
endBehaviorOverride: FrameClipEndBehavior.Clear,
|
||||
internalId: "51000000000000000000000000000006");
|
||||
var hidden = new AnimationNode(idle.Id, "Hide Terminal",
|
||||
endBehaviorOverride: FrameClipEndBehavior.HideTarget,
|
||||
internalId: "51000000000000000000000000000007");
|
||||
var finiteFlow = new AnimationFlow("PreviewFiniteFlow", "Finite Flow", finiteA.InternalId);
|
||||
var loopFlow = new AnimationFlow("PreviewLoopFlow", "Loop Flow", loopA.InternalId);
|
||||
var blockedFlow = new AnimationFlow("PreviewBlockedFlow", "Zero Speed Flow", blocked.InternalId);
|
||||
var clearFlow = new AnimationFlow("PreviewClearFlow", "Clear Flow", clear.InternalId);
|
||||
var hideFlow = new AnimationFlow("PreviewHideFlow", "Hide Flow", hidden.InternalId);
|
||||
graph.Configure(
|
||||
"PreviewSampleGraph",
|
||||
"Phase 5 Preview Sample",
|
||||
new[] { action, withEmpty, idle },
|
||||
new[] { finiteA, finiteB, loopA, loopB, blocked, clear, hidden },
|
||||
new[]
|
||||
{
|
||||
new AnimationEdge(finiteA.InternalId, finiteB.InternalId, "52000000000000000000000000000001"),
|
||||
new AnimationEdge(loopA.InternalId, loopB.InternalId, "52000000000000000000000000000002")
|
||||
},
|
||||
new[] { finiteFlow, loopFlow, blockedFlow, clearFlow, hideFlow },
|
||||
finiteFlow.Id);
|
||||
|
||||
var positions = new[]
|
||||
{
|
||||
(finiteA, new Vector2(80f, 80f)), (finiteB, new Vector2(420f, 80f)),
|
||||
(loopA, new Vector2(80f, 320f)), (loopB, new Vector2(420f, 320f)),
|
||||
(blocked, new Vector2(80f, 560f)), (clear, new Vector2(420f, 560f)),
|
||||
(hidden, new Vector2(760f, 560f))
|
||||
};
|
||||
foreach (var item in positions)
|
||||
{
|
||||
graph.EditorData.GetOrCreateNodeData(item.Item1.InternalId, item.Item2);
|
||||
}
|
||||
var colors = new[]
|
||||
{
|
||||
new Color(0.25f, 0.65f, 0.95f), new Color(0.55f, 0.4f, 0.9f),
|
||||
new Color(0.9f, 0.55f, 0.2f), new Color(0.3f, 0.75f, 0.5f), new Color(0.85f, 0.35f, 0.45f)
|
||||
};
|
||||
var flows = graph.Flows.ToArray();
|
||||
for (var index = 0; index < flows.Length; index++)
|
||||
{
|
||||
graph.EditorData.GetOrCreateFlowData(flows[index].Id, colors[index]);
|
||||
}
|
||||
EditorUtility.SetDirty(graph);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
Debug.Log($"Frame Animation phase 5 preview sample created: {GraphPath}");
|
||||
}
|
||||
|
||||
private static FrameClip CreateClip(
|
||||
FrameAnimationGraph graph,
|
||||
string id,
|
||||
string displayName,
|
||||
FrameClipEndBehavior endBehavior,
|
||||
FrameAnimationFrame[] frames)
|
||||
{
|
||||
var clip = ScriptableObject.CreateInstance<FrameClip>();
|
||||
clip.name = id;
|
||||
clip.Configure(id, displayName, frames, 1f, endBehavior);
|
||||
AssetDatabase.AddObjectToAsset(clip, graph);
|
||||
return clip;
|
||||
}
|
||||
|
||||
private static void EnsureFolder(string path)
|
||||
{
|
||||
var segments = path.Split('/');
|
||||
var current = segments[0];
|
||||
for (var index = 1; index < segments.Length; index++)
|
||||
{
|
||||
var next = current + "/" + segments[index];
|
||||
if (!AssetDatabase.IsValidFolder(next)) AssetDatabase.CreateFolder(current, segments[index]);
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user