// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
#if UNITY_EDITOR
using Animancer.TransitionLibraries;
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using static Animancer.Editor.AnimancerGUI;
using static Animancer.Editor.TransitionLibraries.TransitionLibrarySelection;
namespace Animancer.Editor.TransitionLibraries
{
/// [Editor-Only]
/// A for editing transition aliases.
///
/// https://kybernetik.com.au/animancer/api/Animancer.Editor.TransitionLibraries/TransitionLibraryAliasesPage
[Serializable]
public class TransitionLibraryAliasesPage : TransitionLibraryWindowPage
{
/************************************************************************************************************************/
[SerializeField]
private Vector2 _ScrollPosition;
[NonSerialized]
private bool _HasSorted;
/************************************************************************************************************************/
///
public override string DisplayName
=> "Transition Aliases";
///
public override string HelpTooltip
=> "Aliases are custom names which can be used to refer to transitions instead of direct references.";
///
public override int Index
=> 1;
/************************************************************************************************************************/
private static readonly List
TransitionAreas = new();
/************************************************************************************************************************/
///
public override void OnGUI(Rect area)
{
var definition = Window.Data;
if (!_HasSorted)
{
_HasSorted = true;
definition.SortAliases();
}
var currentEvent = Event.current;
var isRepaint = currentEvent.type == EventType.Repaint;
if (isRepaint)
TransitionAreas.Clear();
area.yMin += StandardSpacing;
area.xMin += StandardSpacing;
area.xMax -= StandardSpacing;
var transitions = definition.Transitions;
var aliases = definition.Aliases;
var viewArea = new Rect(
0,
0,
area.width,
CalculateHeight(1 + transitions.Length + aliases.Length) + StandardSpacing);
if (viewArea.height > area.height)
viewArea.width -= GUI.skin.verticalScrollbar.fixedWidth;
_ScrollPosition = GUI.BeginScrollView(area, _ScrollPosition, viewArea);
viewArea.height = LineHeight;
DoAliasAllGUI(viewArea);
NextVerticalArea(ref viewArea);
var aliasIndex = 0;
for (int i = 0; i < transitions.Length; i++)
{
var totalTransitionArea = viewArea;
if (isRepaint)
TransitionAreas.Add(viewArea);
DoTransitionGUI(viewArea, transitions[i], i);
NextVerticalArea(ref viewArea);
while (aliasIndex < aliases.Length)
{
var alias = aliases[aliasIndex];
if (alias.Index != i)
{
if (alias.Index < i && currentEvent.type != EventType.Used)
{
Debug.LogError("Aliases aren't properly sorted.");
definition.SortAliases();
GUIUtility.ExitGUI();
}
break;
}
DoAliasGUI(viewArea, alias, aliasIndex++);
NextVerticalArea(ref viewArea);
}
// Highlights.
totalTransitionArea.yMax = viewArea.yMin - StandardSpacing;
var selected = Window.Selection.FromIndex == i || Window.Selection.ToIndex == i;
var hover = totalTransitionArea.Contains(currentEvent.mousePosition);
Window.Highlighter.DrawHighlightGUI(totalTransitionArea, selected, hover);
}
GUI.EndScrollView();
}
/************************************************************************************************************************/
/// Draws .
private void DoAliasAllGUI(Rect area)
{
var definition = Window.Data;
using (var label = PooledGUIContent.Acquire(
"Alias All Transitions",
TransitionLibraryDefinition.AliasAllTransitionsTooltip))
definition.AliasAllTransitions = EditorGUI.Toggle(area, label, definition.AliasAllTransitions);
if (TryUseClickEvent(area, 0))
definition.AliasAllTransitions = !definition.AliasAllTransitions;
}
/************************************************************************************************************************/
/// Draws a `transition`.
private void DoTransitionGUI(Rect area, TransitionAssetBase transition, int index)
{
var addArea = StealFromLeft(ref area, LineHeight * 5, StandardSpacing);
TransitionModifierTableGUI.HandleTransitionLabelInput(
ref area,
Window,
transition,
index,
SelectionType.ToTransition,
CalculateTargetTransitionIndex);
var typeArea = StealFromRight(ref area, area.width * 0.5f, StandardSpacing);
var label = transition.GetCachedName();
GUI.Label(area, label);
var wrappedTransition = transition.GetTransition();
var type = wrappedTransition != null
? wrappedTransition.GetType().GetNameCS(false)
: "Null";
GUI.Label(typeArea, type);
if (GUI.Button(addArea, "Add"))
{
var alias = new NamedIndex(null, index);
Window.RecordUndo().AddAlias(alias);
}
}
/************************************************************************************************************************/
/// Calculates the transition index for a drag and drop operation.
private static int CalculateTargetTransitionIndex(
Rect area,
int index,
Event currentEvent)
{
var y = currentEvent.mousePosition.y;
for (int i = 0; i < TransitionAreas.Count; i++)
if (y <= TransitionAreas[i].yMax)
return i;
return TransitionAreas.Count;
}
/************************************************************************************************************************/
/// Draws an `alias`.
private void DoAliasGUI(Rect area, NamedIndex alias, int index)
{
var removeArea = StealFromLeft(ref area, LineHeight * 5, StandardSpacing);
EditorGUI.BeginChangeCheck();
var name = StringAssetDrawer.DrawGUI(area, GUIContent.none, alias.Name, Window.SourceObject, out _);
if (EditorGUI.EndChangeCheck())
{
Window.RecordUndo().Aliases[index] = alias.With(name as StringAsset);
}
if (GUI.Button(removeArea, "Remove"))
{
Window.RecordUndo().RemoveAlias(index);
}
}
/************************************************************************************************************************/
}
}
#endif