441 lines
16 KiB
C#
441 lines
16 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace AibisDream.FrameAnimation
|
|
{
|
|
[Serializable]
|
|
public sealed class FrameAnimationFrame
|
|
{
|
|
[SerializeField] private Sprite sprite;
|
|
[SerializeField] private int durationMs = 100;
|
|
[SerializeField] private string frameName = string.Empty;
|
|
[SerializeField] private int sourceIndex = -1;
|
|
|
|
public Sprite Sprite => sprite;
|
|
public int DurationMs => durationMs;
|
|
public string FrameName => frameName;
|
|
public int SourceIndex => sourceIndex;
|
|
|
|
public FrameAnimationFrame()
|
|
{
|
|
}
|
|
|
|
internal FrameAnimationFrame(Sprite sprite, int durationMs, string frameName, int sourceIndex)
|
|
{
|
|
this.sprite = sprite;
|
|
this.durationMs = durationMs;
|
|
this.frameName = frameName ?? string.Empty;
|
|
this.sourceIndex = sourceIndex;
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public sealed class FrameClipImportInfo
|
|
{
|
|
[SerializeField] private string importSourceId = string.Empty;
|
|
[SerializeField] private string sourceTagName = string.Empty;
|
|
[SerializeField] private bool isMissingFromSource;
|
|
|
|
public string ImportSourceId => importSourceId;
|
|
public string SourceTagName => sourceTagName;
|
|
public bool IsMissingFromSource => isMissingFromSource;
|
|
|
|
internal FrameClipImportInfo(string importSourceId, string sourceTagName, bool isMissingFromSource)
|
|
{
|
|
this.importSourceId = importSourceId ?? string.Empty;
|
|
this.sourceTagName = sourceTagName ?? string.Empty;
|
|
this.isMissingFromSource = isMissingFromSource;
|
|
}
|
|
|
|
internal void Update(string sourceId, string tagName, bool missingFromSource)
|
|
{
|
|
importSourceId = sourceId ?? string.Empty;
|
|
sourceTagName = tagName ?? string.Empty;
|
|
isMissingFromSource = missingFromSource;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Editor-time source settings owned by an external FrameClip asset.
|
|
/// This is intentionally separate from graph-owned FrameClipImportInfo.
|
|
/// </summary>
|
|
[Serializable]
|
|
public sealed class FrameClipImportSource
|
|
{
|
|
[SerializeField] private Texture2D texture;
|
|
[SerializeField] private TextAsset asepriteJson;
|
|
[SerializeField] private Vector2 pivot = new Vector2(0.5f, 0.5f);
|
|
[SerializeField] private bool manageSpriteSlicing;
|
|
[SerializeField] private string lastSourceHash = string.Empty;
|
|
[SerializeField] private string lastImportedTagName = string.Empty;
|
|
|
|
public Texture2D Texture => texture;
|
|
public TextAsset AsepriteJson => asepriteJson;
|
|
public Vector2 Pivot => pivot;
|
|
public bool ManageSpriteSlicing => manageSpriteSlicing;
|
|
public string LastSourceHash => lastSourceHash;
|
|
public string LastImportedTagName => lastImportedTagName;
|
|
|
|
internal void SetLastImport(string sourceHash, string tagName)
|
|
{
|
|
lastSourceHash = sourceHash ?? string.Empty;
|
|
lastImportedTagName = tagName ?? string.Empty;
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public sealed class AnimationFlow
|
|
{
|
|
[SerializeField] private string id = string.Empty;
|
|
[SerializeField] private string displayName = string.Empty;
|
|
[SerializeField] private string entryNodeId = string.Empty;
|
|
[SerializeField] private AnimationFlowAsyncCompletionMode asyncCompletionMode =
|
|
AnimationFlowAsyncCompletionMode.CompleteOnTerminalLoopStart;
|
|
[SerializeField] private bool hasEndBehaviorOverride;
|
|
[SerializeField] private FrameClipEndBehavior endBehaviorOverride;
|
|
|
|
public string Id => id;
|
|
public string DisplayName => displayName;
|
|
public string EntryNodeId => entryNodeId;
|
|
public AnimationFlowAsyncCompletionMode AsyncCompletionMode => asyncCompletionMode;
|
|
public FrameClipEndBehavior? EndBehaviorOverride =>
|
|
hasEndBehaviorOverride ? endBehaviorOverride : (FrameClipEndBehavior?)null;
|
|
|
|
public AnimationFlow()
|
|
{
|
|
}
|
|
|
|
internal AnimationFlow(
|
|
string id,
|
|
string displayName,
|
|
string entryNodeId,
|
|
FrameClipEndBehavior? endBehaviorOverride = null,
|
|
AnimationFlowAsyncCompletionMode asyncCompletionMode =
|
|
AnimationFlowAsyncCompletionMode.CompleteOnTerminalLoopStart)
|
|
{
|
|
this.id = id ?? string.Empty;
|
|
this.displayName = displayName ?? this.id;
|
|
this.entryNodeId = entryNodeId ?? string.Empty;
|
|
this.asyncCompletionMode = asyncCompletionMode;
|
|
SetEndBehaviorOverride(endBehaviorOverride);
|
|
}
|
|
|
|
internal void SetEndBehaviorOverride(FrameClipEndBehavior? value)
|
|
{
|
|
hasEndBehaviorOverride = value.HasValue;
|
|
endBehaviorOverride = value.GetValueOrDefault();
|
|
}
|
|
|
|
internal void SetId(string value)
|
|
{
|
|
id = value ?? string.Empty;
|
|
}
|
|
|
|
internal void SetDisplayName(string value)
|
|
{
|
|
displayName = value ?? string.Empty;
|
|
}
|
|
|
|
internal void SetEntryNodeId(string value)
|
|
{
|
|
entryNodeId = value ?? string.Empty;
|
|
}
|
|
|
|
internal void SetAsyncCompletionMode(AnimationFlowAsyncCompletionMode value)
|
|
{
|
|
asyncCompletionMode = value;
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public sealed class AnimationNode
|
|
{
|
|
[SerializeField] private string internalId = string.Empty;
|
|
[SerializeField] private string displayName = string.Empty;
|
|
[SerializeField] private AnimationNodeType type = AnimationNodeType.Clip;
|
|
[SerializeField] private string clipId = string.Empty;
|
|
[SerializeField] private bool hasEndBehaviorOverride;
|
|
[SerializeField] private FrameClipEndBehavior endBehaviorOverride;
|
|
[SerializeField] private bool hasSpeedOverride;
|
|
[SerializeField] private float speedOverride = 1f;
|
|
|
|
public string InternalId => internalId;
|
|
public string DisplayName => displayName;
|
|
public AnimationNodeType Type => type;
|
|
public string ClipId => clipId;
|
|
public FrameClipEndBehavior? EndBehaviorOverride =>
|
|
hasEndBehaviorOverride ? endBehaviorOverride : (FrameClipEndBehavior?)null;
|
|
public float? SpeedOverride => hasSpeedOverride ? speedOverride : (float?)null;
|
|
|
|
public AnimationNode()
|
|
{
|
|
}
|
|
|
|
internal AnimationNode(
|
|
string clipId,
|
|
string displayName = null,
|
|
FrameClipEndBehavior? endBehaviorOverride = null,
|
|
float? speedOverride = null,
|
|
string internalId = null)
|
|
{
|
|
this.internalId = string.IsNullOrEmpty(internalId)
|
|
? FrameAnimationValueUtility.NewInternalId()
|
|
: internalId;
|
|
this.displayName = displayName ?? clipId ?? string.Empty;
|
|
type = AnimationNodeType.Clip;
|
|
this.clipId = clipId ?? string.Empty;
|
|
SetEndBehaviorOverride(endBehaviorOverride);
|
|
SetSpeedOverride(speedOverride);
|
|
}
|
|
|
|
internal void EnsureInternalId()
|
|
{
|
|
if (string.IsNullOrWhiteSpace(internalId))
|
|
{
|
|
internalId = FrameAnimationValueUtility.NewInternalId();
|
|
}
|
|
}
|
|
|
|
internal void SetEndBehaviorOverride(FrameClipEndBehavior? value)
|
|
{
|
|
hasEndBehaviorOverride = value.HasValue;
|
|
endBehaviorOverride = value.GetValueOrDefault();
|
|
}
|
|
|
|
internal void SetSpeedOverride(float? value)
|
|
{
|
|
hasSpeedOverride = value.HasValue;
|
|
speedOverride = value.GetValueOrDefault(1f);
|
|
}
|
|
|
|
internal void SetClipId(string value)
|
|
{
|
|
clipId = value ?? string.Empty;
|
|
}
|
|
|
|
internal void SetDisplayName(string value)
|
|
{
|
|
displayName = value ?? string.Empty;
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public sealed class AnimationEdge
|
|
{
|
|
[SerializeField] private string internalId = string.Empty;
|
|
[SerializeField] private string fromNodeId = string.Empty;
|
|
[SerializeField] private string toNodeId = string.Empty;
|
|
[SerializeField] private string exitName = "default";
|
|
[SerializeField] private AnimationEdgeCondition condition = AnimationEdgeCondition.Always;
|
|
|
|
public string InternalId => internalId;
|
|
public string FromNodeId => fromNodeId;
|
|
public string ToNodeId => toNodeId;
|
|
public string ExitName => exitName;
|
|
public AnimationEdgeCondition Condition => condition;
|
|
|
|
public AnimationEdge()
|
|
{
|
|
}
|
|
|
|
internal AnimationEdge(string fromNodeId, string toNodeId, string internalId = null)
|
|
{
|
|
this.internalId = string.IsNullOrEmpty(internalId)
|
|
? FrameAnimationValueUtility.NewInternalId()
|
|
: internalId;
|
|
this.fromNodeId = fromNodeId ?? string.Empty;
|
|
this.toNodeId = toNodeId ?? string.Empty;
|
|
exitName = "default";
|
|
condition = AnimationEdgeCondition.Always;
|
|
}
|
|
|
|
internal void EnsureInternalId()
|
|
{
|
|
if (string.IsNullOrWhiteSpace(internalId))
|
|
{
|
|
internalId = FrameAnimationValueUtility.NewInternalId();
|
|
}
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public sealed class FrameAnimationImportSource
|
|
{
|
|
[SerializeField] private string internalId = string.Empty;
|
|
[SerializeField] private string displayName = string.Empty;
|
|
[SerializeField] private bool isEnabled = true;
|
|
[SerializeField] private Texture2D texture;
|
|
[SerializeField] private TextAsset asepriteJson;
|
|
[SerializeField] private Vector2 pivot = new Vector2(0.5f, 0.5f);
|
|
[SerializeField] private bool manageSpriteSlicing;
|
|
[SerializeField] private FrameClipEndBehavior defaultNewClipEndBehavior =
|
|
FrameClipEndBehavior.HoldLastFrame;
|
|
[SerializeField] private string lastSourceHash = string.Empty;
|
|
|
|
public string InternalId => internalId;
|
|
public string DisplayName => displayName;
|
|
public bool IsEnabled => isEnabled;
|
|
public Texture2D Texture => texture;
|
|
public TextAsset AsepriteJson => asepriteJson;
|
|
public Vector2 Pivot => pivot;
|
|
public bool ManageSpriteSlicing => manageSpriteSlicing;
|
|
public FrameClipEndBehavior DefaultNewClipEndBehavior => defaultNewClipEndBehavior;
|
|
public string LastSourceHash => lastSourceHash;
|
|
|
|
public FrameAnimationImportSource()
|
|
{
|
|
}
|
|
|
|
internal FrameAnimationImportSource(
|
|
string sourceDisplayName,
|
|
Texture2D sourceTexture,
|
|
TextAsset sourceJson,
|
|
Vector2 sourcePivot,
|
|
bool ownsSpriteSlicing,
|
|
FrameClipEndBehavior newClipEndBehavior = FrameClipEndBehavior.HoldLastFrame,
|
|
string sourceInternalId = null)
|
|
{
|
|
internalId = string.IsNullOrWhiteSpace(sourceInternalId)
|
|
? FrameAnimationValueUtility.NewInternalId()
|
|
: sourceInternalId;
|
|
displayName = sourceDisplayName ?? string.Empty;
|
|
isEnabled = true;
|
|
texture = sourceTexture;
|
|
asepriteJson = sourceJson;
|
|
pivot = sourcePivot;
|
|
manageSpriteSlicing = ownsSpriteSlicing;
|
|
defaultNewClipEndBehavior = newClipEndBehavior;
|
|
}
|
|
|
|
internal void EnsureInternalId()
|
|
{
|
|
if (string.IsNullOrWhiteSpace(internalId))
|
|
{
|
|
internalId = FrameAnimationValueUtility.NewInternalId();
|
|
}
|
|
}
|
|
|
|
internal void SetLastSourceHash(string value)
|
|
{
|
|
lastSourceHash = value ?? string.Empty;
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public sealed class FrameAnimationGraphSettings
|
|
{
|
|
[SerializeField] private string defaultPlayableId = string.Empty;
|
|
[SerializeField] private FrameClipEndBehavior newManualClipDefaultEndBehavior =
|
|
FrameClipEndBehavior.HoldLastFrame;
|
|
|
|
public string DefaultPlayableId => defaultPlayableId;
|
|
public FrameClipEndBehavior NewManualClipDefaultEndBehavior => newManualClipDefaultEndBehavior;
|
|
|
|
internal void SetDefaultPlayableId(string value)
|
|
{
|
|
defaultPlayableId = value ?? string.Empty;
|
|
}
|
|
|
|
internal void SetNewManualClipDefaultEndBehavior(FrameClipEndBehavior value)
|
|
{
|
|
newManualClipDefaultEndBehavior = value;
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public sealed class AnimationNodeEditorData
|
|
{
|
|
[SerializeField] private string nodeId = string.Empty;
|
|
[SerializeField] private Vector2 position;
|
|
|
|
public string NodeId => nodeId;
|
|
public Vector2 Position => position;
|
|
|
|
internal AnimationNodeEditorData(string nodeId, Vector2 position)
|
|
{
|
|
this.nodeId = nodeId ?? string.Empty;
|
|
this.position = position;
|
|
}
|
|
|
|
internal void SetPosition(Vector2 value)
|
|
{
|
|
position = value;
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public sealed class AnimationFlowEditorData
|
|
{
|
|
[SerializeField] private string flowId = string.Empty;
|
|
[SerializeField] private Color color = Color.white;
|
|
|
|
public string FlowId => flowId;
|
|
public Color Color => color;
|
|
|
|
internal AnimationFlowEditorData(string flowId, Color color)
|
|
{
|
|
this.flowId = flowId ?? string.Empty;
|
|
this.color = color;
|
|
}
|
|
|
|
internal void SetFlowId(string value)
|
|
{
|
|
flowId = value ?? string.Empty;
|
|
}
|
|
|
|
internal void SetColor(Color value)
|
|
{
|
|
color = value;
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public sealed class FrameAnimationGraphEditorData
|
|
{
|
|
[SerializeField] private List<AnimationNodeEditorData> nodeEditorData = new List<AnimationNodeEditorData>();
|
|
[SerializeField] private List<AnimationFlowEditorData> flowEditorData = new List<AnimationFlowEditorData>();
|
|
|
|
public IReadOnlyList<AnimationNodeEditorData> NodeEditorData => nodeEditorData;
|
|
public IReadOnlyList<AnimationFlowEditorData> FlowEditorData => flowEditorData;
|
|
|
|
internal AnimationNodeEditorData GetOrCreateNodeData(string nodeId, Vector2 position)
|
|
{
|
|
nodeEditorData ??= new List<AnimationNodeEditorData>();
|
|
var existing = nodeEditorData.Find(data => data != null && data.NodeId == nodeId);
|
|
if (existing != null)
|
|
{
|
|
return existing;
|
|
}
|
|
var created = new AnimationNodeEditorData(nodeId, position);
|
|
nodeEditorData.Add(created);
|
|
return created;
|
|
}
|
|
|
|
internal bool RemoveNodeData(string nodeId)
|
|
{
|
|
nodeEditorData ??= new List<AnimationNodeEditorData>();
|
|
return nodeEditorData.RemoveAll(data => data != null && data.NodeId == nodeId) > 0;
|
|
}
|
|
|
|
internal AnimationFlowEditorData GetOrCreateFlowData(string flowId, Color color)
|
|
{
|
|
flowEditorData ??= new List<AnimationFlowEditorData>();
|
|
var existing = flowEditorData.Find(data => data != null && data.FlowId == flowId);
|
|
if (existing != null)
|
|
{
|
|
return existing;
|
|
}
|
|
var created = new AnimationFlowEditorData(flowId, color);
|
|
flowEditorData.Add(created);
|
|
return created;
|
|
}
|
|
|
|
internal bool RemoveFlowData(string flowId)
|
|
{
|
|
flowEditorData ??= new List<AnimationFlowEditorData>();
|
|
return flowEditorData.RemoveAll(data => data != null && data.FlowId == flowId) > 0;
|
|
}
|
|
}
|
|
}
|