291 lines
9.9 KiB
C#
291 lines
9.9 KiB
C#
// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
using Animancer.TransitionLibraries;
|
|
using System;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace Animancer.Editor.TransitionLibraries
|
|
{
|
|
/// <summary>[Editor-Only]
|
|
/// A dummy object for tracking the selection within the <see cref="TransitionLibraryWindow"/>
|
|
/// and showing its details in the Inspector.
|
|
/// </summary>
|
|
/// https://kybernetik.com.au/animancer/api/Animancer.Editor.TransitionLibraries/TransitionLibrarySelection
|
|
[AnimancerHelpUrl(typeof(TransitionLibrarySelection))]
|
|
public class TransitionLibrarySelection : ScriptableObject
|
|
{
|
|
/************************************************************************************************************************/
|
|
|
|
/// <summary>[Editor-Only] Types of objects can be selected.</summary>
|
|
public enum SelectionType
|
|
{
|
|
/// <summary>Nothing selected.</summary>
|
|
None,
|
|
|
|
/// <summary>The main library.</summary>
|
|
Library,
|
|
|
|
/// <summary>A from-transition.</summary>
|
|
FromTransition,
|
|
|
|
/// <summary>A to-transition.</summary>
|
|
ToTransition,
|
|
|
|
/// <summary>A fade duration modifier.</summary>
|
|
Modifier,
|
|
}
|
|
|
|
/************************************************************************************************************************/
|
|
|
|
[SerializeField] private TransitionLibraryWindow _Window;
|
|
[SerializeField] private SelectionType _Type;
|
|
[SerializeField] private int _FromIndex = -1;
|
|
[SerializeField] private int _ToIndex = -1;
|
|
[SerializeField] private int _Version;
|
|
|
|
/// <summary>The window this selection is associated with.</summary>
|
|
public TransitionLibraryWindow Window
|
|
=> _Window;
|
|
|
|
/// <summary>The type of selected object.</summary>
|
|
public SelectionType Type
|
|
=> _Type;
|
|
|
|
/// <summary>The index of the <see cref="FromTransition"/>.</summary>
|
|
public int FromIndex
|
|
=> _FromIndex;
|
|
|
|
/// <summary>The index of the <see cref="ToTransition"/>.</summary>
|
|
public int ToIndex
|
|
=> _ToIndex;
|
|
|
|
/// <summary>The number of times this selection has been changed.</summary>
|
|
public int Version
|
|
=> _Version;
|
|
|
|
/************************************************************************************************************************/
|
|
|
|
/// <summary>The transition the current selection is coming from.</summary>
|
|
public TransitionAssetBase FromTransition { get; private set; }
|
|
|
|
/// <summary>The transition the current selection is going to.</summary>
|
|
public TransitionAssetBase ToTransition { get; private set; }
|
|
|
|
/// <summary>The <see cref="ITransition.FadeDuration"/> of the current selection.</summary>
|
|
public float FadeDuration { get; private set; }
|
|
|
|
/// <summary>Does the current selection have a modified <see cref="FadeDuration"/>?</summary>
|
|
public bool HasModifier { get; private set; }
|
|
|
|
/************************************************************************************************************************/
|
|
|
|
[NonSerialized] private object _Selected;
|
|
|
|
/// <summary>The currently selected object.</summary>
|
|
public object Selected
|
|
{
|
|
get
|
|
{
|
|
Validate();
|
|
return _Selected;
|
|
}
|
|
}
|
|
|
|
/************************************************************************************************************************/
|
|
|
|
/// <summary>Deselects the current object if it isn't valid.</summary>
|
|
public bool Validate()
|
|
{
|
|
if (IsValid())
|
|
return true;
|
|
|
|
Deselect();
|
|
return false;
|
|
}
|
|
|
|
/// <summary>Is the current selection valid?</summary>
|
|
public bool IsValid()
|
|
{
|
|
if (this == null ||
|
|
_Window == null ||
|
|
Selection.activeObject != this)
|
|
return false;
|
|
|
|
var library = _Window.SourceObject;
|
|
if (library == null)
|
|
return false;
|
|
|
|
FromTransition = null;
|
|
ToTransition = null;
|
|
FadeDuration = float.NaN;
|
|
HasModifier = false;
|
|
|
|
switch (_Type)
|
|
{
|
|
case SelectionType.Library:
|
|
name = "Transition Library";
|
|
_Selected = library;
|
|
return library != null;
|
|
|
|
case SelectionType.FromTransition:
|
|
name = "From Transition";
|
|
if (!_Window.Data.Transitions.TryGet(_FromIndex, out var transition))
|
|
return false;
|
|
|
|
FromTransition = transition;
|
|
FadeDuration = transition.TryGetFadeDuration();
|
|
_Selected = transition;
|
|
return true;
|
|
|
|
case SelectionType.ToTransition:
|
|
name = "To Transition";
|
|
if (!_Window.Data.Transitions.TryGet(_ToIndex, out transition))
|
|
return false;
|
|
|
|
ToTransition = transition;
|
|
FadeDuration = transition.TryGetFadeDuration();
|
|
_Selected = transition;
|
|
return true;
|
|
|
|
case SelectionType.Modifier:
|
|
name = "Transition Modifier";
|
|
|
|
var hasTransitions = _Window.Data.TryGetTransition(_FromIndex, out transition);
|
|
FromTransition = transition;
|
|
|
|
hasTransitions |= _Window.Data.TryGetTransition(_ToIndex, out transition);
|
|
ToTransition = transition;
|
|
|
|
if (_Window.Data.TryGetModifier(_FromIndex, _ToIndex, out var modifier))
|
|
{
|
|
HasModifier = true;
|
|
}
|
|
else if (hasTransitions)
|
|
{
|
|
modifier = modifier.WithFadeDuration(transition.TryGetFadeDuration());
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
|
|
FadeDuration = modifier.FadeDuration;
|
|
_Selected = modifier;
|
|
return true;
|
|
|
|
default:
|
|
return false;
|
|
};
|
|
}
|
|
|
|
/************************************************************************************************************************/
|
|
|
|
/// <summary>Sets the <see cref="Selected"/> object.</summary>
|
|
/// <remarks>
|
|
/// We can't simply set the <see cref="Selection.activeObject"/>
|
|
/// because it might not be a <see cref="UnityEngine.Object"/>
|
|
/// and if it is then we don't want the Project window to move to it.
|
|
/// <para></para>
|
|
/// So instead, we select this dummy object and <see cref="TransitionLibrarySelectionEditor"/>
|
|
/// draws a custom Inspector for the target object.
|
|
/// </remarks>
|
|
public void Select(
|
|
TransitionLibraryWindow window,
|
|
object select,
|
|
int index,
|
|
SelectionType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case SelectionType.Library:
|
|
_FromIndex = -1;
|
|
_ToIndex = -1;
|
|
break;
|
|
|
|
case SelectionType.FromTransition:
|
|
_FromIndex = index;
|
|
_ToIndex = -1;
|
|
break;
|
|
|
|
case SelectionType.ToTransition:
|
|
_FromIndex = -1;
|
|
_ToIndex = index;
|
|
break;
|
|
|
|
case SelectionType.Modifier:
|
|
if (select is TransitionModifierDefinition modifier)
|
|
{
|
|
_FromIndex = modifier.FromIndex;
|
|
_ToIndex = modifier.ToIndex;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
Deselect();
|
|
return;
|
|
}
|
|
|
|
default:
|
|
Deselect();
|
|
throw new ArgumentException($"Unhandled {nameof(SelectionType)}", nameof(type));
|
|
}
|
|
|
|
_Window = window;
|
|
_Type = type;
|
|
_Selected = select;
|
|
_Version++;
|
|
|
|
Selection.activeObject = this;
|
|
|
|
Validate();
|
|
}
|
|
|
|
/************************************************************************************************************************/
|
|
|
|
/// <summary>Clears the <see cref="Selected"/> object.</summary>
|
|
public void Deselect()
|
|
{
|
|
_Window = null;
|
|
_Type = default;
|
|
_FromIndex = -1;
|
|
_ToIndex = -1;
|
|
_Selected = null;
|
|
_Version++;
|
|
|
|
if (Selection.activeObject == this)
|
|
Selection.activeObject = null;
|
|
}
|
|
|
|
/************************************************************************************************************************/
|
|
|
|
/// <summary>Handles selection changes.</summary>
|
|
public void OnSelectionChange()
|
|
{
|
|
if (Selection.activeObject == this)
|
|
return;
|
|
|
|
Deselect();
|
|
|
|
if (_Window != null)
|
|
_Window.Repaint();
|
|
}
|
|
|
|
/************************************************************************************************************************/
|
|
|
|
/// <summary>Selects this object if it contains a valid selection.</summary>
|
|
protected virtual void OnEnable()
|
|
{
|
|
if (Selected != null)
|
|
Selection.activeObject = this;
|
|
}
|
|
|
|
/************************************************************************************************************************/
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|