Files
2026-05-08 11:04:00 +08:00

176 lines
7.1 KiB
C#

// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2026 Kybernetik //
#if UNITY_EDITOR
using Animancer.TransitionLibraries;
using System;
using UnityEngine;
using static Animancer.Editor.TransitionLibraries.TransitionLibrarySelection;
namespace Animancer.Editor.TransitionLibraries
{
/// <summary>[Editor-Only]
/// Operations for modifying the order of items in a <see cref="TransitionLibraryAsset"/>.
/// </summary>
/// https://kybernetik.com.au/animancer/api/Animancer.Editor.TransitionLibraries/TransitionLibraryOrdering
public static class TransitionLibraryOrdering
{
/************************************************************************************************************************/
/// <summary>Handles a drag and drop operation.</summary>
public static void OnDropItem(
this TransitionLibraryWindow window,
object item,
ListTargetCalculation target,
SelectionType selectionType)
{
window.RecordUndo();
window.EditorData.TransitionSortMode = TransitionSortMode.Custom;
if (item is TransitionAssetBase transition)
OnDropTransition(window, transition, target, selectionType);
else if (item is TransitionGroup group)
OnDropGroup(window, group, target);
else
Debug.LogWarning($"Unhandled item type: {item}");
}
/************************************************************************************************************************/
/// <summary>Handles a drag and drop operation for a `transition`.</summary>
private static void OnDropTransition(
TransitionLibraryWindow window,
TransitionAssetBase transition,
ListTargetCalculation target,
SelectionType selectionType)
{
var transitions = window.Data.Transitions;
var fromTransitionIndex = Array.IndexOf(transitions, transition);
var fromItemIndex = window.Items.IndexOf(transition);
var fromGroup = window.Items.GetGroup(fromItemIndex);
var fromIndexWithinGroup = int.MaxValue;
if (fromGroup != null)
{
fromIndexWithinGroup = fromGroup.TransitionIndices.IndexOf(fromTransitionIndex);
if (fromIndexWithinGroup >= 0)
fromGroup.TransitionIndices.RemoveAt(fromIndexWithinGroup);
}
var toGroup = window.Items.TryGet(target.Index, out var targetItem)
? window.Items.GetGroup(target.Index)
: null;
// If dropping onto the top half of a group, drop outside that group.
if (target.LocalOffset < 0.5f && ReferenceEquals(toGroup, targetItem))
{
toGroup = null;
if (fromItemIndex < target.Index)
target.Index--;
}
// Drop onto group or a transition in a group.
if (toGroup != null)
{
var groupIndex = window.Items.IndexOf(toGroup);
var indexWithinGroup = target.Index - groupIndex;
// If dropping into the top half of an item, insert above that item instead of below.
if (target.LocalOffset < 0.5f)
indexWithinGroup--;
// If this item was just removed from earlier in the same list, adjust the new index.
if (fromGroup == toGroup && fromIndexWithinGroup < indexWithinGroup)
indexWithinGroup--;
indexWithinGroup = Mathf.Clamp(indexWithinGroup, 0, toGroup.TransitionIndices.Count);
toGroup.TransitionIndices.Insert(indexWithinGroup, fromTransitionIndex);
}
else// Drop onto a transition with no group.
{
var toTransitionIndex = Array.IndexOf(transitions, targetItem);
if (toTransitionIndex >= 0)
{
// If dropping into the top half of an item, insert above that item instead of below.
if (target.LocalOffset >= 0.5f)
toTransitionIndex++;
// If this item was just removed from earlier in the transition list, adjust the new index.
if (fromTransitionIndex < toTransitionIndex)
toTransitionIndex--;
}
else if (target.Index < 0)// Above everything.
{
toTransitionIndex = 0;
}
else// Below everything.
{
toTransitionIndex = transitions.Length;
}
AdjustGroupIndices(window, fromItemIndex, target.Index);
TransitionLibrarySort.MoveTransition(window, fromTransitionIndex, toTransitionIndex);
}
window.Selection.Select(window, targetItem, fromTransitionIndex, selectionType);
}
/************************************************************************************************************************/
/// <summary>Handles a drag and drop operation for a `group`.</summary>
private static void OnDropGroup(
TransitionLibraryWindow window,
TransitionGroup group,
ListTargetCalculation target)
{
var fromItemIndex = window.Items.IndexOf(group);
if (target.LocalOffset > 0.5f)
target.Index++;
var previousIndex = group.Index;
AdjustGroupIndices(window, fromItemIndex, target.Index);
if (target.Index > fromItemIndex)
target.Index += group.Index - previousIndex;
group.Index = window.Items.ItemToGroupIndex(target.Index);
TransitionGroupCache.SortGroups(window.EditorData.TransitionGroups);
window.Selection.Select(window, group, target.Index, SelectionType.Group);
}
/************************************************************************************************************************/
/// <summary>Adjusts the <see cref="TransitionGroup.Index"/> for any groups an item is moved over.</summary>
private static void AdjustGroupIndices(
TransitionLibraryWindow window,
int movedFromItemIndex,
int movedToItemIndex)
{
var direction = Math.Sign(movedToItemIndex - movedFromItemIndex);
movedFromItemIndex = Mathf.Clamp(movedFromItemIndex, 0, window.Items.Count - 1);
movedToItemIndex = Mathf.Clamp(movedToItemIndex, 0, window.Items.Count - 1);
while (true)
{
if (window.Items.GetItem(movedFromItemIndex) is TransitionGroup group)
group.Index -= direction;
if (movedFromItemIndex == movedToItemIndex)
break;
movedFromItemIndex += direction;
}
}
/************************************************************************************************************************/
}
}
#endif