init
This commit is contained in:
+231
@@ -0,0 +1,231 @@
|
||||
// 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
|
||||
{
|
||||
/// <summary>[Editor-Only]
|
||||
/// A <see cref="TransitionLibraryWindowPage"/> for editing transition aliases.
|
||||
/// </summary>
|
||||
/// https://kybernetik.com.au/animancer/api/Animancer.Editor.TransitionLibraries/TransitionLibraryAliasesPage
|
||||
[Serializable]
|
||||
public class TransitionLibraryAliasesPage : TransitionLibraryWindowPage
|
||||
{
|
||||
/************************************************************************************************************************/
|
||||
|
||||
[SerializeField]
|
||||
private Vector2 _ScrollPosition;
|
||||
|
||||
[NonSerialized]
|
||||
private bool _HasSorted;
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string DisplayName
|
||||
=> "Transition Aliases";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string HelpTooltip
|
||||
=> "Aliases are custom names which can be used to refer to transitions instead of direct references.";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int Index
|
||||
=> 1;
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
private static readonly List<Rect>
|
||||
TransitionAreas = new();
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <inheritdoc/>
|
||||
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();
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Draws <see cref="TransitionLibraryDefinition.AliasAllTransitions"/>.</summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Draws a `transition`.</summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Calculates the transition index for a drag and drop operation.</summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Draws an `alias`.</summary>
|
||||
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
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d5be687cb9b8da4e9c61bfb49ab861d
|
||||
timeCreated: 1516751545
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Animancer.Editor.TransitionLibraries
|
||||
{
|
||||
/// <summary>[Editor-Only]
|
||||
/// A <see cref="TransitionLibraryWindowPage"/> for editing transition modifiers.
|
||||
/// </summary>
|
||||
/// https://kybernetik.com.au/animancer/api/Animancer.Editor.TransitionLibraries/TransitionLibraryModifiersPage
|
||||
[Serializable]
|
||||
public class TransitionLibraryModifiersPage : TransitionLibraryWindowPage
|
||||
{
|
||||
/************************************************************************************************************************/
|
||||
|
||||
[SerializeField]
|
||||
private TransitionModifierTableGUI _TableGUI;
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string DisplayName
|
||||
=> "Transition Modifiers";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string HelpTooltip
|
||||
=> "Modifiers allow you to replace the usual fade duration for specific combinations of transitions.";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int Index
|
||||
=> 0;
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void OnGUI(Rect area)
|
||||
{
|
||||
_TableGUI ??= new();
|
||||
|
||||
if (Window.Data.Transitions.Length == 0)
|
||||
{
|
||||
area = new Rect(
|
||||
area.x + AnimancerGUI.StandardSpacing,
|
||||
area.y + AnimancerGUI.StandardSpacing,
|
||||
area.width - AnimancerGUI.StandardSpacing * 2,
|
||||
AnimancerGUI.LineHeight);
|
||||
|
||||
GUI.Label(area, "Library contains no Transitions");
|
||||
|
||||
AnimancerGUI.NextVerticalArea(ref area);
|
||||
|
||||
if (GUI.Button(area, "Create Transition"))
|
||||
TransitionLibraryOperations.CreateTransition(Window);
|
||||
}
|
||||
else
|
||||
{
|
||||
_TableGUI.DoGUI(area, Window);
|
||||
}
|
||||
|
||||
TransitionLibraryOperations.HandleBackgroundInput(area, Window);
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de81cf7262eb1514894f722e6050eead
|
||||
timeCreated: 1516751545
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Animancer.Editor.TransitionLibraries
|
||||
{
|
||||
/// <summary>[Editor-Only]
|
||||
/// Manages the selection of pages in the <see cref="TransitionLibraryWindow"/>.
|
||||
/// </summary>
|
||||
/// https://kybernetik.com.au/animancer/api/Animancer.Editor.TransitionLibraries/TransitionLibraryWindowPage
|
||||
[Serializable]
|
||||
public abstract class TransitionLibraryWindowPage : IComparable<TransitionLibraryWindowPage>
|
||||
{
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>The window containing this page.</summary>
|
||||
public TransitionLibraryWindow Window { get; set; }
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>The name of this page.</summary>
|
||||
public abstract string DisplayName { get; }
|
||||
|
||||
/// <summary>The text to use for the tooltip on the help button while this page is visible.</summary>
|
||||
public abstract string HelpTooltip { get; }
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>The sorting index of this page.</summary>
|
||||
public abstract int Index { get; }
|
||||
|
||||
/// <summary>Compares the <see cref="Index"/>.</summary>
|
||||
public int CompareTo(TransitionLibraryWindowPage other)
|
||||
=> Index.CompareTo(other.Index);
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Draws the GUI of this page.</summary>
|
||||
public abstract void OnGUI(Rect area);
|
||||
|
||||
/************************************************************************************************************************/
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61210733873388e4e815c6628988b306
|
||||
timeCreated: 1516751545
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+428
@@ -0,0 +1,428 @@
|
||||
// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using static Animancer.Editor.AnimancerGUI;
|
||||
using static Animancer.Editor.TransitionLibraries.TransitionLibrarySelection;
|
||||
|
||||
namespace Animancer.Editor.TransitionLibraries
|
||||
{
|
||||
/// <summary>[Editor-Only]
|
||||
/// A <see cref="TableGUI"/> for editing
|
||||
/// <see cref="Animancer.TransitionLibraries.TransitionLibraryDefinition.Modifiers"/>.
|
||||
/// </summary>
|
||||
/// https://kybernetik.com.au/animancer/api/Animancer.Editor.TransitionLibraries/TransitionModifierTableGUI
|
||||
[Serializable]
|
||||
public class TransitionModifierTableGUI : TableGUI
|
||||
{
|
||||
/************************************************************************************************************************/
|
||||
|
||||
[NonSerialized] private TransitionLibraryWindow _Window;
|
||||
[NonSerialized] private Vector2Int _SelectedCell;
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Creates a new <see cref="TransitionModifierTableGUI"/>.</summary>
|
||||
public TransitionModifierTableGUI()
|
||||
{
|
||||
base.DoCellGUI = DoCellGUI;
|
||||
CalculateWidestLabel = CalculateWidestTransitionLabel;
|
||||
MinCellSize = new(LineHeight * 2, LineHeight);
|
||||
MaxCellSize = new(LineHeight * 4, LineHeight);
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Draws the table GUI.</summary>
|
||||
public void DoGUI(
|
||||
Rect area,
|
||||
TransitionLibraryWindow window)
|
||||
{
|
||||
_Window = window;
|
||||
_SelectedCell = RecalculateSelectedCell(window.Selection);
|
||||
|
||||
var transitions = window.Data.Transitions;
|
||||
DoTableGUI(area, transitions.Length, transitions.Length);
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Calculates the table coordinates of the `selection`.</summary>
|
||||
private Vector2Int RecalculateSelectedCell(TransitionLibrarySelection selection)
|
||||
{
|
||||
if (selection.Validate())
|
||||
{
|
||||
switch (selection.Type)
|
||||
{
|
||||
case SelectionType.FromTransition:
|
||||
case SelectionType.ToTransition:
|
||||
case SelectionType.Modifier:
|
||||
var cell = new Vector2Int(selection.ToIndex, selection.FromIndex);
|
||||
|
||||
if (cell.x < 0)
|
||||
cell.x = int.MinValue;
|
||||
|
||||
if (cell.y < 0)
|
||||
cell.y = int.MinValue;
|
||||
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
|
||||
return new(int.MinValue, int.MinValue);
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Draws a table cell.</summary>
|
||||
private new void DoCellGUI(Rect area, int column, int row)
|
||||
{
|
||||
var invertHover = false;
|
||||
|
||||
if (column < 0)
|
||||
{
|
||||
if (row < 0)
|
||||
DoCornerGUI(area);
|
||||
else
|
||||
DoLabelGUI(
|
||||
area,
|
||||
row,
|
||||
RightLabelStyle,
|
||||
SelectionType.FromTransition);
|
||||
}
|
||||
else if (row < 0)
|
||||
{
|
||||
DoLabelGUI(
|
||||
area,
|
||||
column,
|
||||
EditorStyles.label,
|
||||
SelectionType.ToTransition);
|
||||
|
||||
invertHover = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
DoFadeDurationGUI(area, _Window, row, column, "");
|
||||
|
||||
}
|
||||
|
||||
DrawHighlightGUI(area, column, row, invertHover);
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Draws the header corner.</summary>
|
||||
private void DoCornerGUI(Rect area)
|
||||
{
|
||||
area.xMin += StandardSpacing;
|
||||
|
||||
var fromArea = area;
|
||||
fromArea.y += area.height - LineHeight;
|
||||
fromArea.height = LineHeight;
|
||||
|
||||
var toArea = fromArea;
|
||||
toArea.y -= toArea.height - Padding;
|
||||
|
||||
var removeArea = toArea;
|
||||
removeArea.y -= removeArea.height - Padding;
|
||||
|
||||
var createArea = removeArea;
|
||||
createArea.y -= createArea.height - Padding;
|
||||
|
||||
fromArea.width -= VerticalScrollBar.fixedWidth + Padding;
|
||||
|
||||
var style = RightLabelStyle;
|
||||
var fontStyle = style.fontStyle;
|
||||
style.fontStyle = FontStyle.Bold;
|
||||
|
||||
GUI.Label(fromArea, "From", style);
|
||||
GUI.Label(toArea, "To", style);
|
||||
|
||||
style.fontStyle = fontStyle;
|
||||
|
||||
DoCreateButtonGUI(createArea);
|
||||
DoDeleteButtonGUI(removeArea);
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Draws a button to create a new transition.</summary>
|
||||
private void DoCreateButtonGUI(Rect area)
|
||||
{
|
||||
if (GUI.Button(area, "Create Transition"))
|
||||
TransitionLibraryOperations.CreateTransition(_Window);
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Draws a button to remove the selected transition.</summary>
|
||||
private void DoDeleteButtonGUI(Rect area)
|
||||
{
|
||||
TransitionAssetBase transition = null;
|
||||
int index = -1;
|
||||
|
||||
var selection = _Window.Selection;
|
||||
switch (selection.Type)
|
||||
{
|
||||
case SelectionType.FromTransition:
|
||||
transition = selection.FromTransition;
|
||||
index = selection.FromIndex;
|
||||
break;
|
||||
|
||||
case SelectionType.ToTransition:
|
||||
transition = selection.ToTransition;
|
||||
index = selection.ToIndex;
|
||||
break;
|
||||
}
|
||||
|
||||
using (new EditorGUI.DisabledScope(index < 0 || index >= _Window.Data.Transitions.Length))
|
||||
if (GUI.Button(area, "Remove Transition"))
|
||||
TransitionLibraryOperations.AskHowToDeleteTransition(transition, index, _Window);
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Draws a row or column label.</summary>
|
||||
private void DoLabelGUI(
|
||||
Rect area,
|
||||
int index,
|
||||
GUIStyle style,
|
||||
SelectionType selectionType)
|
||||
{
|
||||
if (!_Window.Data.Transitions.TryGet(index, out var transition))
|
||||
return;
|
||||
|
||||
HandleTransitionLabelInput(
|
||||
ref area,
|
||||
_Window,
|
||||
transition,
|
||||
index,
|
||||
selectionType,
|
||||
CalculateTargetTransitionIndex);
|
||||
|
||||
GUI.Label(area, GetTransitionName(transition), style);
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Returns the name of the `transition` with a special message for <c>null</c>.</summary>
|
||||
public static string GetTransitionName(TransitionAssetBase transition)
|
||||
=> transition != null
|
||||
? transition.GetCachedName()
|
||||
: "<Missing Transition>";
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
private static readonly int LabelHint = "Label".GetHashCode();
|
||||
|
||||
[NonSerialized] private static bool _IsLabelDrag;
|
||||
|
||||
/// <summary>Handles input events on transition labels.</summary>
|
||||
public static void HandleTransitionLabelInput(
|
||||
ref Rect area,
|
||||
TransitionLibraryWindow window,
|
||||
TransitionAssetBase transition,
|
||||
int index,
|
||||
SelectionType selectionType,
|
||||
Func<Rect, int, Event, int> calculateTargetTransitionIndex)
|
||||
{
|
||||
var control = new GUIControl(area, LabelHint);
|
||||
|
||||
switch (control.EventType)
|
||||
{
|
||||
case EventType.MouseDown:
|
||||
if (control.Event.button == 0 &&
|
||||
control.TryUseMouseDown())
|
||||
{
|
||||
if (control.Event.clickCount == 2)
|
||||
EditorGUIUtility.PingObject(transition);
|
||||
else
|
||||
window.Selection.Select(window, transition, index, selectionType);
|
||||
|
||||
_IsLabelDrag = false;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EventType.MouseUp:
|
||||
if (control.TryUseMouseUp() && _IsLabelDrag)
|
||||
{
|
||||
var target = calculateTargetTransitionIndex(area, index, control.Event);
|
||||
TransitionLibrarySort.MoveTransition(window, index, target);
|
||||
window.Selection.Select(window, transition, index, selectionType);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EventType.MouseDrag:
|
||||
if (control.TryUseHotControl())
|
||||
_IsLabelDrag = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (GUIUtility.hotControl == control.ID && _IsLabelDrag)
|
||||
{
|
||||
RepaintEverything();
|
||||
area.y = control.Event.mousePosition.y - area.height * 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Calculates the transition index for a drag and drop operation.</summary>
|
||||
private static int CalculateTargetTransitionIndex(
|
||||
Rect area,
|
||||
int index,
|
||||
Event currentEvent)
|
||||
{
|
||||
var distance = currentEvent.mousePosition.y - area.y;
|
||||
var offset = Mathf.FloorToInt(distance / area.height);
|
||||
return index + offset;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
private static GUIStyle _FadeDurationStyle;
|
||||
|
||||
/// <summary>Draws the fade duration for a particular transition combination.</summary>
|
||||
public static void DoFadeDurationGUI(
|
||||
Rect area,
|
||||
TransitionLibraryWindow window,
|
||||
int from,
|
||||
int to,
|
||||
string label)
|
||||
{
|
||||
_FadeDurationStyle ??= new(EditorStyles.numberField)
|
||||
{
|
||||
alignment = TextAnchor.MiddleLeft,
|
||||
};
|
||||
|
||||
var previousHotControl = GUIUtility.hotControl;
|
||||
|
||||
var hasModifier = window.Data.TryGetModifier(from, to, out var modifier);
|
||||
|
||||
var labelStyle = EditorStyles.label.fontStyle;
|
||||
try
|
||||
{
|
||||
if (hasModifier)
|
||||
{
|
||||
EditorStyles.label.fontStyle = FontStyle.Bold;
|
||||
_FadeDurationStyle.fontStyle = FontStyle.Bold;
|
||||
_FadeDurationStyle.fontSize = EditorStyles.numberField.fontSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
_FadeDurationStyle.fontStyle = FontStyle.Normal;
|
||||
_FadeDurationStyle.fontSize = EditorStyles.numberField.fontSize * 4 / 5;
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
// This is basically a float field,
|
||||
// but anything that fails to parse will clear the field instead of setting it to 0.
|
||||
|
||||
var text = modifier.FadeDuration.ToStringCached();
|
||||
text = EditorGUI.TextField(area, label, text, _FadeDurationStyle);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if (!float.TryParse(text, out var fadeDuration))
|
||||
fadeDuration = float.NaN;
|
||||
|
||||
window.RecordUndo()
|
||||
.SetModifier(modifier.WithFadeDuration(fadeDuration));
|
||||
|
||||
hasModifier = true;
|
||||
|
||||
RepaintEverything();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
EditorStyles.label.fontStyle = labelStyle;
|
||||
}
|
||||
|
||||
if (previousHotControl != GUIUtility.hotControl)
|
||||
{
|
||||
window.Selection.Select(
|
||||
window,
|
||||
modifier,
|
||||
modifier.FromIndex,
|
||||
SelectionType.Modifier);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Draws the selection and hover highlights for a particular cell.</summary>
|
||||
private void DrawHighlightGUI(Rect area, int column, int row, bool invertHover)
|
||||
{
|
||||
if (_Window.Highlighter.EventType != EventType.Repaint)
|
||||
return;
|
||||
|
||||
var selected =
|
||||
_SelectedCell.x == column ||
|
||||
_SelectedCell.y == row;
|
||||
|
||||
var hover = false;
|
||||
|
||||
if (_Window.Highlighter.IsMouseOver)
|
||||
{
|
||||
if (invertHover)
|
||||
(row, column) = (column, row);
|
||||
|
||||
var mousePosition = Event.current.mousePosition;
|
||||
if ((column >= 0 && IsInlineWithX(area, mousePosition.x)) ||
|
||||
(row >= 0 && IsInlineWithY(area, mousePosition.y)))
|
||||
{
|
||||
hover = true;
|
||||
}
|
||||
}
|
||||
|
||||
_Window.Highlighter.DrawHighlightGUI(area, selected, hover);
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Is `x` inside the `area`.</summary>
|
||||
private static bool IsInlineWithX(Rect area, float x)
|
||||
=> area.xMin <= x
|
||||
&& area.xMax > x;
|
||||
|
||||
/// <summary>Is `y` inside the `area`.</summary>
|
||||
private static bool IsInlineWithY(Rect area, float y)
|
||||
=> area.yMin <= y
|
||||
&& area.yMax > y;
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Calculates the largest width of all transition labels.</summary>
|
||||
private float CalculateWidestTransitionLabel()
|
||||
{
|
||||
var widest = LineHeight * 2;
|
||||
|
||||
var transitions = _Window.Data.Transitions;
|
||||
for (int i = 0; i < transitions.Length; i++)
|
||||
{
|
||||
var transition = transitions[i];
|
||||
if (transition == null)
|
||||
continue;
|
||||
|
||||
var label = transition.GetCachedName();
|
||||
var width = CalculateLabelWidth(label);
|
||||
if (widest < width)
|
||||
widest = width;
|
||||
}
|
||||
|
||||
return widest;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 78f4b212f3ad9cd4285498110975c389
|
||||
timeCreated: 1516751545
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user