258 lines
9.4 KiB
C#
258 lines
9.4 KiB
C#
// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
using Animancer.TransitionLibraries;
|
|
using System;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using static Animancer.Editor.AnimancerGUI;
|
|
using static Animancer.Editor.TransitionLibraries.TransitionLibrarySelection;
|
|
|
|
namespace Animancer.Editor.TransitionLibraries
|
|
{
|
|
/// <summary>[Editor-Only]
|
|
/// Operations for modifying a <see cref="TransitionLibraryAsset"/>.
|
|
/// </summary>
|
|
/// https://kybernetik.com.au/animancer/api/Animancer.Editor.TransitionLibraries/TransitionLibraryOperations
|
|
public static class TransitionLibraryOperations
|
|
{
|
|
/************************************************************************************************************************/
|
|
|
|
/// <summary>Handles input events for the background of the `window`.</summary>
|
|
public static void HandleBackgroundInput(
|
|
Rect area,
|
|
TransitionLibraryWindow window)
|
|
{
|
|
// Click to select the library.
|
|
if (TryUseClickEvent(area, 0))
|
|
window.Selection.Select(window, window.SourceObject, -1, SelectionType.Library);
|
|
|
|
var currentEvent = Event.current;
|
|
switch (currentEvent.type)
|
|
{
|
|
// Drag and drop to add transition.
|
|
case EventType.DragUpdated:
|
|
case EventType.DragPerform:
|
|
HandleDragAndDrop(currentEvent, window);
|
|
break;
|
|
|
|
case EventType.ValidateCommand:
|
|
case EventType.ExecuteCommand:
|
|
switch (currentEvent.commandName)
|
|
{
|
|
// Delete to remove the selection.
|
|
case Commands.Delete:
|
|
case Commands.SoftDelete:
|
|
HandleDelete(currentEvent, window);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/************************************************************************************************************************/
|
|
|
|
/// <summary>Handles drag and drop events to add transitions to the `window`.</summary>
|
|
private static void HandleDragAndDrop(
|
|
Event currentEvent,
|
|
TransitionLibraryWindow window)
|
|
{
|
|
var dragging = DragAndDrop.objectReferences;
|
|
|
|
TransitionAssetBase dropped = null;
|
|
int index = -1;
|
|
|
|
for (int i = dragging.Length - 1; i >= 0; i--)
|
|
{
|
|
var transition = TryCreateTransitionAttribute.TryCreateTransitionAsset(dragging[i]);
|
|
if (transition != null &&
|
|
Array.IndexOf(window.Data.Transitions, transition) >= 0)
|
|
continue;
|
|
|
|
switch (currentEvent.type)
|
|
{
|
|
case EventType.DragUpdated:
|
|
DragAndDrop.visualMode = DragAndDropVisualMode.Link;
|
|
currentEvent.Use();
|
|
return;
|
|
|
|
case EventType.DragPerform:
|
|
dropped = transition;
|
|
index = window.Data.Transitions.Length;
|
|
window.RecordUndo().AddTransition(transition);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (dropped != null)
|
|
{
|
|
window.Selection.Select(
|
|
window,
|
|
dropped,
|
|
index,
|
|
SelectionType.ToTransition);
|
|
DragAndDrop.AcceptDrag();
|
|
currentEvent.Use();
|
|
}
|
|
}
|
|
|
|
/************************************************************************************************************************/
|
|
|
|
/// <summary>Creates a new transition as a sub-asset of the `window`'s library.</summary>
|
|
public static TransitionAssetBase CreateTransition(
|
|
TransitionLibraryWindow window)
|
|
{
|
|
var createInstance = TransitionAssetBase.CreateInstance;
|
|
if (createInstance == null)
|
|
{
|
|
Debug.LogError(
|
|
$"{nameof(CreateTransition)} failed because " +
|
|
$"{nameof(TransitionAssetBase)}.{nameof(TransitionAssetBase.CreateInstance)}" +
|
|
$" hasn't been assigned." +
|
|
$" It should be automatically initialized by TransitionAsset.");
|
|
return null;
|
|
}
|
|
|
|
var definition = window.RecordUndo();
|
|
|
|
var transition = createInstance(null);
|
|
transition.name = "Transition " + (definition.Transitions.Length + 1);
|
|
AnimancerReflection.TryInvoke(transition, "Reset");
|
|
|
|
definition.AddTransition(transition);
|
|
|
|
var index = definition.Transitions.Length;
|
|
window.Selection.Select(window, transition, index, SelectionType.ToTransition);
|
|
|
|
return transition;
|
|
}
|
|
|
|
/************************************************************************************************************************/
|
|
|
|
/// <summary>Handles a delete event.</summary>
|
|
private static void HandleDelete(
|
|
Event currentEvent,
|
|
TransitionLibraryWindow window)
|
|
{
|
|
if (!window.Selection.Validate())
|
|
return;
|
|
|
|
switch (window.Selection.Type)
|
|
{
|
|
case SelectionType.FromTransition:
|
|
if (currentEvent.type == EventType.ExecuteCommand &&
|
|
window.Selection.Selected is TransitionAssetBase fromTransition)
|
|
AskHowToDeleteTransition(
|
|
fromTransition,
|
|
window.Selection.FromIndex,
|
|
window);
|
|
break;
|
|
|
|
case SelectionType.ToTransition:
|
|
if (currentEvent.type == EventType.ExecuteCommand &&
|
|
window.Selection.Selected is TransitionAssetBase toTransition)
|
|
AskHowToDeleteTransition(
|
|
toTransition,
|
|
window.Selection.ToIndex,
|
|
window);
|
|
break;
|
|
|
|
case SelectionType.Modifier:
|
|
if (currentEvent.type == EventType.ExecuteCommand &&
|
|
window.Selection.Selected is TransitionModifierDefinition modifier)
|
|
window.RecordUndo().RemoveModifier(modifier);
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
|
|
currentEvent.Use();
|
|
}
|
|
|
|
/************************************************************************************************************************/
|
|
|
|
/// <summary>Asks if the user wants to delete a transition asset or just remove it from the library.</summary>
|
|
public static void AskHowToDeleteTransition(
|
|
TransitionAssetBase transition,
|
|
int index,
|
|
TransitionLibraryWindow window)
|
|
{
|
|
var assetPath = AssetDatabase.GetAssetPath(transition);
|
|
if (string.IsNullOrEmpty(assetPath))
|
|
{
|
|
if (transition != null)
|
|
Undo.DestroyObjectImmediate(transition);
|
|
|
|
window.RecordUndo().RemoveTransition(index);
|
|
return;
|
|
}
|
|
|
|
var isMainAsset = AssetDatabase.IsMainAsset(transition);
|
|
var assetType = isMainAsset ? "Asset" : "Sub-Asset";
|
|
var isSubAssetOfLibrary =
|
|
!isMainAsset &&
|
|
assetPath == AssetDatabase.GetAssetPath(window.SourceObject);
|
|
|
|
var message = assetPath;
|
|
if (!isSubAssetOfLibrary)
|
|
message += "\n\nRemove Transition: removes it from this Transition Library.";
|
|
|
|
message += $"\n\nDelete {assetType}: deletes the Transition {assetType} from your project (cannot be undone).";
|
|
|
|
int choice;
|
|
if (isSubAssetOfLibrary)
|
|
{
|
|
if (EditorUtility.DisplayDialog(
|
|
"Delete transition?",
|
|
message,
|
|
"Delete " + assetType,
|
|
"Cancel"))
|
|
choice = 2;
|
|
else
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
choice = EditorUtility.DisplayDialogComplex(
|
|
"Remove or Delete transition?",
|
|
message,
|
|
"Remove Transition",
|
|
"Cancel",
|
|
"Delete " + assetType);
|
|
}
|
|
|
|
switch (choice)
|
|
{
|
|
case 0:// Remove.
|
|
window.RecordUndo().RemoveTransition(index);
|
|
break;
|
|
|
|
case 2:// Delete.
|
|
if (isMainAsset)
|
|
{
|
|
AssetDatabase.DeleteAsset(assetPath);
|
|
}
|
|
else
|
|
{
|
|
AnimancerEditorUtilities.DeleteSubAsset(transition);
|
|
}
|
|
|
|
window.Data.RemoveTransition(index);
|
|
Undo.ClearUndo(window);
|
|
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
/************************************************************************************************************************/
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|