using System; using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEditor.Experimental.GraphView; using UnityEngine; using UnityEngine.UIElements; namespace AibisDream.FrameAnimation.Editor { internal sealed class FrameAnimationClipNodeView : Node { private readonly Label subtitle; private readonly Label behavior; private readonly Label issueBadge; private readonly Label entryBadge; private readonly VisualElement badgeContainer; private readonly FrameAnimationPreviewElement preview; private readonly Action selectedCallback; private FrameAnimationFlowColorPalette? entryPalette; public AnimationNode Data { get; } public Port InputPort { get; } public Port OutputPort { get; } internal FrameAnimationClipNodeView( AnimationNode data, Action selectedCallback) { Data = data; this.selectedCallback = selectedCallback; viewDataKey = data.InternalId; AddToClassList("fa-node"); InputPort = Port.Create(Orientation.Horizontal, Direction.Input, Port.Capacity.Multi, typeof(AnimationNode)); InputPort.portName = string.Empty; inputContainer.Add(InputPort); OutputPort = Port.Create(Orientation.Horizontal, Direction.Output, Port.Capacity.Single, typeof(AnimationNode)); OutputPort.portName = string.Empty; outputContainer.Add(OutputPort); subtitle = new Label(); subtitle.AddToClassList("fa-node__clip-id"); behavior = new Label(); behavior.AddToClassList("fa-node__behavior"); var meta = new VisualElement(); meta.AddToClassList("fa-node__meta"); meta.Add(subtitle); meta.Add(behavior); extensionContainer.Add(meta); preview = new FrameAnimationPreviewElement(); preview.AddToClassList("fa-node__preview"); extensionContainer.Add(preview); badgeContainer = new VisualElement(); badgeContainer.AddToClassList("fa-node__badges"); entryBadge = new Label("E") { tooltip = "Flow Entry" }; entryBadge.AddToClassList("fa-node__entry"); badgeContainer.Add(entryBadge); issueBadge = new Label(); issueBadge.AddToClassList("fa-badge"); issueBadge.style.unityFontStyleAndWeight = FontStyle.Bold; badgeContainer.Add(issueBadge); extensionContainer.Add(badgeContainer); RefreshExpandedState(); } public override void OnSelected() { base.OnSelected(); selectedCallback?.Invoke(this); } internal void Refresh( FrameAnimationGraph graph, IReadOnlyList issues, IReadOnlyList flows) { var clip = graph.Clips.FirstOrDefault(item => item != null && item.Id == Data.ClipId); title = string.IsNullOrWhiteSpace(Data.DisplayName) ? Data.ClipId : Data.DisplayName; subtitle.text = clip != null ? Data.ClipId : $"Missing: {Data.ClipId}"; var speed = Data.SpeedOverride.HasValue ? $"Speed {Data.SpeedOverride.Value:0.###} (Node)" : clip != null ? $"Speed {clip.Speed:0.###} (Clip)" : "Speed ?"; var end = Data.EndBehaviorOverride?.ToString() ?? "Continue / terminal fallback"; behavior.text = $"{speed} · {end}"; var used = flows.Where(flow => flow != null).ToArray(); var entryFlows = used.Where(flow => flow.EntryNodeId == Data.InternalId).ToArray(); entryPalette = entryFlows.Length > 0 ? FrameAnimationFlowColorUtility.CreatePalette( FrameAnimationFlowColorUtility.ResolveRaw(graph, entryFlows[0])) : (FrameAnimationFlowColorPalette?)null; entryBadge.style.display = entryPalette.HasValue ? DisplayStyle.Flex : DisplayStyle.None; if (entryPalette.HasValue) { entryBadge.style.backgroundColor = entryPalette.Value.Stroke; entryBadge.style.color = entryPalette.Value.Text; entryBadge.tooltip = "Flow Entry: " + string.Join(", ", entryFlows.Select(flow => flow.Id)); } foreach (var label in badgeContainer.Query