| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523 | 
							- // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
 
- #if UNITY_EDITOR && UNITY_IMGUI
 
- using Animancer.Editor.Previews;
 
- using Animancer.TransitionLibraries;
 
- using System;
 
- using UnityEditor;
 
- using UnityEngine;
 
- using static Animancer.Editor.AnimancerGUI;
 
- using Object = UnityEngine.Object;
 
- namespace Animancer.Editor.TransitionLibraries
 
- {
 
-     /// <summary>[Editor-Only] Custom preview for <see cref="TransitionLibrarySelection"/>.</summary>
 
-     /// <remarks>Parts of this class are based on Unity's <see cref="MeshPreview"/>.</remarks>
 
-     /// https://kybernetik.com.au/animancer/api/Animancer.Editor.TransitionLibraries/TransitionLibrarySelectionPreview
 
-     [CustomPreview(typeof(TransitionLibrarySelection))]
 
-     public class TransitionLibrarySelectionPreview : ObjectPreview
 
-     {
 
-         /************************************************************************************************************************/
 
-         [SerializeField] private AnimancerPreviewRenderer _PreviewRenderer;
 
-         [SerializeField] private TransitionPreviewPlayer _PreviewPlayer;
 
-         [NonSerialized] private TransitionLibrarySelection _Target;
 
-         [NonSerialized] private int _TargetVersion = -1;
 
-         [NonSerialized] private readonly TransitionLibrarySelectionPreviewSpeed Speed = new();
 
-         /************************************************************************************************************************/
 
-         /// <inheritdoc/>
 
-         public override void Initialize(Object[] targets)
 
-         {
 
-             _PreviewRenderer ??= new();
 
-             _PreviewPlayer ??= new();
 
-             if (targets.Length == 1)
 
-             {
 
-                 _Target = targets[0] as TransitionLibrarySelection;
 
-                 if (_Target != null)
 
-                 {
 
-                     _TargetVersion = _Target.Version - 1;
 
-                     if (_Target.Window != null)
 
-                         _PreviewRenderer.PreviewObject.TrySelectBestModel(_Target.Window.Data);
 
-                     CheckTarget();
 
-                 }
 
-             }
 
-             base.Initialize(targets);
 
-         }
 
-         /************************************************************************************************************************/
 
-         /// <inheritdoc/>
 
-         public override void Cleanup()
 
-         {
 
-             base.Cleanup();
 
-             _PreviewPlayer?.Dispose();
 
-             _PreviewPlayer = null;
 
-             _PreviewRenderer?.Dispose();
 
-             _PreviewRenderer = null;
 
-         }
 
-         /************************************************************************************************************************/
 
-         /// <summary>Handles changes to the target object.</summary>
 
-         private void CheckTarget()
 
-         {
 
-             if (_TargetVersion == _Target.Version)
 
-                 return;
 
-             _TargetVersion = _Target.Version;
 
-             _PreviewPlayer.IsPlaying = false;
 
-             switch (_Target.Type)
 
-             {
 
-                 case TransitionLibrarySelection.SelectionType.FromTransition:
 
-                     _PreviewPlayer.FromTransition = _Target.FromTransition;
 
-                     _PreviewPlayer.ToTransition = null;
 
-                     break;
 
-                 case TransitionLibrarySelection.SelectionType.ToTransition:
 
-                     _PreviewPlayer.FromTransition = null;
 
-                     _PreviewPlayer.ToTransition = _Target.ToTransition;
 
-                     break;
 
-                 case TransitionLibrarySelection.SelectionType.Modifier:
 
-                     _PreviewPlayer.FromTransition = _Target.FromTransition;
 
-                     _PreviewPlayer.ToTransition = _Target.ToTransition;
 
-                     break;
 
-             }
 
-         }
 
-         /************************************************************************************************************************/
 
-         /// <summary>Updates the settings of the <see cref="TransitionPreviewPlayer"/>.</summary>
 
-         private void UpdatePlayerSettings()
 
-         {
 
-             _PreviewPlayer.Graph = _PreviewRenderer.PreviewObject.Graph;
 
-             _PreviewPlayer.FadeDuration = _Target.FadeDuration;
 
-             _PreviewPlayer.Speed = Speed.Speed;
 
-             _PreviewPlayer.RecalculateTimeBounds();
 
-         }
 
-         /************************************************************************************************************************/
 
-         private static readonly GUIContent
 
-             Title = new("Preview");
 
-         /// <inheritdoc/>
 
-         public override GUIContent GetPreviewTitle()
 
-             => Title;
 
-         /************************************************************************************************************************/
 
-         /// <inheritdoc/>
 
-         public override bool HasPreviewGUI()
 
-             => _Target != null
 
-             && _Target.Type switch
 
-             {
 
-                 TransitionLibrarySelection.SelectionType.FromTransition or
 
-                 TransitionLibrarySelection.SelectionType.ToTransition or
 
-                 TransitionLibrarySelection.SelectionType.Modifier
 
-                 => true,
 
-                 _ => false,
 
-             };
 
-         /************************************************************************************************************************/
 
-         #region Header Settings
 
-         /************************************************************************************************************************/
 
-         private static GUIStyle _ToolbarButtonStyle;
 
-         /// <inheritdoc/>
 
-         public override void OnPreviewSettings()
 
-         {
 
-             CheckTarget();
 
-             _ToolbarButtonStyle ??= new(EditorStyles.toolbarButton)
 
-             {
 
-                 padding = new(),
 
-             };
 
-             var area = GUILayoutUtility.GetRect(LineHeight * 1.5f, LineHeight);
 
-             DoPlayPauseToggle(area, _ToolbarButtonStyle);
 
-             area = GUILayoutUtility.GetRect(LineHeight * 2f, LineHeight);
 
-             Speed.DoToggleGUI(area, _ToolbarButtonStyle);
 
-         }
 
-         /************************************************************************************************************************/
 
-         /// <summary>Draws a toggle to play and pause the preview.</summary>
 
-         private void DoPlayPauseToggle(Rect area, GUIStyle style)
 
-         {
 
-             if (TryUseClickEvent(area, 1) || TryUseClickEvent(area, 2))
 
-                 _PreviewPlayer.CurrentTime = _PreviewPlayer.MinTime;
 
-             _PreviewPlayer.IsPlaying = AnimancerGUI.DoPlayPauseToggle(
 
-                 area,
 
-                 _PreviewPlayer.IsPlaying,
 
-                 style,
 
-                 "Left Click = Play/Pause\nRight Click = Reset Time");
 
-         }
 
-         /************************************************************************************************************************/
 
-         #endregion
 
-         /************************************************************************************************************************/
 
-         /// <inheritdoc/>
 
-         public override void OnInteractivePreviewGUI(Rect area, GUIStyle background)
 
-         {
 
-             if (_Target == null)
 
-                 return;
 
-             CheckTarget();
 
-             UpdatePlayerSettings();
 
-             DoSettingsGUI(ref area);
 
-             DoTimelineGUI(ref area);
 
-             _PreviewRenderer.DoGUI(area, background);
 
-             AnimancerPreviewObjectGUI.HandleDragAndDrop(area, _PreviewRenderer.PreviewObject);
 
-         }
 
-         /************************************************************************************************************************/
 
-         /// <summary>Draws settings for modifying the preview.</summary>
 
-         private void DoSettingsGUI(ref Rect area)
 
-         {
 
-             if (!Speed.IsOn)
 
-                 return;
 
-             area.yMin += StandardSpacing;
 
-             Speed.DoSpeedSlider(ref area, EditorStyles.toolbar);
 
-             var preview = _PreviewRenderer.PreviewObject;
 
-             var height = AnimancerPreviewObjectGUI.CalculateHeight(preview);
 
-             var settingsArea = StealFromTop(ref area, height, StandardSpacing);
 
-             settingsArea = settingsArea.Expand(-StandardSpacing, 0);
 
-             GUI.Label(settingsArea, GUIContent.none, EditorStyles.toolbar);
 
-             AnimancerPreviewObjectGUI.DoModelGUI(settingsArea, preview);
 
-         }
 
-         /************************************************************************************************************************/
 
-         #region Timeline
 
-         /************************************************************************************************************************/
 
-         /// <summary>Draws the preview timeline.</summary>
 
-         private void DoTimelineGUI(ref Rect area)
 
-         {
 
-             var timelineArea = StealFromTop(ref area, EditorStyles.toolbar.fixedHeight, StandardSpacing);
 
-             EditorGUI.DrawRect(timelineArea, Grey(0.25f, 0.3f));
 
-             EditorGUI.DrawRect(new(timelineArea.x, timelineArea.yMax - 1, timelineArea.width, 1), Grey(0, 0.5f));
 
-             DoFadeDurationSliderGUI(timelineArea);
 
-             DoTimeSliderGUI(timelineArea);
 
-         }
 
-         /************************************************************************************************************************/
 
-         private static readonly int SliderHash = "Slider".GetHashCode();
 
-         /************************************************************************************************************************/
 
-         /// <summary>Draws the fade duration slider.</summary>
 
-         private void DoFadeDurationSliderGUI(Rect area)
 
-         {
 
-             if (!CalculateFadeBounds(area, out var startFadeX, out var endFadeX))
 
-                 return;
 
-             switch (_Target.Type)
 
-             {
 
-                 default:
 
-                     return;
 
-                 case TransitionLibrarySelection.SelectionType.FromTransition:
 
-                 case TransitionLibrarySelection.SelectionType.ToTransition:
 
-                 case TransitionLibrarySelection.SelectionType.Modifier:
 
-                     break;
 
-             }
 
-             var sliderArea = area;
 
-             sliderArea.width = LineHeight * 0.5f;
 
-             sliderArea.x = endFadeX - sliderArea.width * 0.5f;
 
-             var control = new GUIControl(sliderArea, SliderHash);
 
-             switch (control.EventType)
 
-             {
 
-                 case EventType.MouseDown:
 
-                     if (control.TryUseMouseDown())
 
-                         _PreviewPlayer.IsPlaying = false;
 
-                     break;
 
-                 case EventType.MouseUp:
 
-                     control.TryUseMouseUp();
 
-                     break;
 
-                 case EventType.MouseDrag:
 
-                     if (control.TryUseHotControl())
 
-                     {
 
-                         var x = Math.Max(startFadeX, control.Event.mousePosition.x);
 
-                         var normalizedTime = area.InverseLerpUnclampedX(x);
 
-                         var normalizedStartFade = area.InverseLerpUnclampedX(startFadeX);
 
-                         _PreviewPlayer.NormalizedTime = normalizedTime;
 
-                         var fadeDuration =
 
-                             _PreviewPlayer.LerpTimeUnclamped(normalizedTime) -
 
-                             _PreviewPlayer.LerpTimeUnclamped(normalizedStartFade);
 
-                         var selected = _Target.Selected;
 
-                         if (selected is TransitionModifierDefinition modifier)
 
-                         {
 
-                             _Target.Window.RecordUndo()
 
-                                 .SetModifier(modifier.WithFadeDuration(fadeDuration));
 
-                         }
 
-                         else if (selected is TransitionAssetBase transitionAsset)
 
-                         {
 
-                             if (fadeDuration < 0)
 
-                                 fadeDuration = 0;
 
-                             using var serializedObject = new SerializedObject(transitionAsset);
 
-                             var property = serializedObject.FindProperty(TransitionAssetBase.TransitionField);
 
-                             property = property.FindPropertyRelative("_" + nameof(ITransition.FadeDuration));
 
-                             property.floatValue = fadeDuration;
 
-                             serializedObject.ApplyModifiedProperties();
 
-                         }
 
-                         _Target.Window.Repaint();
 
-                     }
 
-                     break;
 
-                 case EventType.Repaint:
 
-                     var color = AnimancerStateDrawerColors.FadeLineColor;
 
-                     var showCursor = GUIUtility.hotControl == 0 || GUIUtility.hotControl == control.ID;
 
-                     if (showCursor)
 
-                         EditorGUIUtility.AddCursorRect(sliderArea, MouseCursor.ResizeHorizontal);
 
-                     if (!showCursor || !sliderArea.Contains(control.Event.mousePosition))
 
-                         color.a *= 0.5f;
 
-                     EditorGUI.DrawRect(
 
-                         new(endFadeX, sliderArea.y, 1, sliderArea.height - 1),
 
-                         color);
 
-                     break;
 
-             }
 
-         }
 
-         /************************************************************************************************************************/
 
-         /// <summary>Draws the preview time slider.</summary>
 
-         private void DoTimeSliderGUI(Rect area)
 
-         {
 
-             var control = new GUIControl(area, SliderHash);
 
-             switch (control.EventType)
 
-             {
 
-                 case EventType.MouseDown:
 
-                     if (control.TryUseMouseDown())
 
-                     {
 
-                         _ForceClampTime = true;
 
-                         _DidWrapTime = false;
 
-                         HandleDragTime(area, control.Event);
 
-                         _ForceClampTime = control.Event.control;
 
-                         if (!_ForceClampTime)
 
-                             EditorGUIUtility.SetWantsMouseJumping(1);
 
-                         _PreviewPlayer.IsPlaying = control.Event.clickCount > 1;
 
-                     }
 
-                     break;
 
-                 case EventType.MouseUp:
 
-                     if (control.TryUseMouseUp())
 
-                         EditorGUIUtility.SetWantsMouseJumping(0);
 
-                     break;
 
-                 case EventType.MouseDrag:
 
-                     if (control.TryUseHotControl())
 
-                         HandleDragTime(area, control.Event);
 
-                     break;
 
-                 case EventType.Repaint:
 
-                     BeginTriangles(AnimancerStateDrawerColors.FadeLineColor);
 
-                     if (CalculateFadeBounds(area, out var startFadeX, out var endFadeX))
 
-                     {
 
-                         // Fade.
 
-                         DrawLineBatched(
 
-                             new(startFadeX, area.yMin + 1),
 
-                             new(endFadeX, area.yMax - 1),
 
-                             1);
 
-                         // To.
 
-                         if (endFadeX < area.xMax)
 
-                             DrawLineBatched(
 
-                             new(endFadeX, area.yMax - 1),
 
-                             new(area.xMax, area.yMax - 1),
 
-                             1);
 
-                     }
 
-                     // From.
 
-                     if (area.xMin < startFadeX)
 
-                         DrawLineBatched(
 
-                             new(area.xMin, area.yMin + 1),
 
-                             new(startFadeX, area.yMin + 1),
 
-                             1);
 
-                     var color = _PreviewPlayer.IsPlaying
 
-                         ? AnimancerStateDrawerColors.PlayingBarColor
 
-                         : AnimancerStateDrawerColors.PausedBarColor;
 
-                     color.a = 1;
 
-                     var timeX = area.LerpUnclampedX(_PreviewPlayer.NormalizedTime);
 
-                     GL.Color(color);
 
-                     DrawLineBatched(new(timeX, area.yMin), new(timeX, area.yMax), 2);
 
-                     EndTriangles();
 
-                     DoTransitionLabels(area);
 
-                     break;
 
-             }
 
-         }
 
-         /************************************************************************************************************************/
 
-         private bool _ForceClampTime;
 
-         private bool _DidWrapTime;
 
-         /// <summary>Draws handles drag events to control the preview time.</summary>
 
-         private void HandleDragTime(Rect area, Event currentEvent)
 
-         {
 
-             if (_ForceClampTime)
 
-             {
 
-                 _PreviewPlayer.NormalizedTime = area.InverseLerpUnclampedX(currentEvent.mousePosition.x);
 
-                 return;
 
-             }
 
-             var delta = currentEvent.delta.x;
 
-             var normalizedTime = _PreviewPlayer.NormalizedTime;
 
-             if (normalizedTime == 0 && !_DidWrapTime && delta > 0)
 
-             {
 
-                 var x = currentEvent.mousePosition.x;
 
-                 if (area.xMin > x || area.xMax < x)
 
-                     return;
 
-             }
 
-             normalizedTime += delta / area.width;
 
-             if (normalizedTime >= 0 || _DidWrapTime)
 
-             {
 
-                 if (normalizedTime > 1)
 
-                     _DidWrapTime = true;
 
-                 normalizedTime = AnimancerUtilities.Wrap01(normalizedTime);
 
-             }
 
-             else
 
-             {
 
-                 normalizedTime = 0;
 
-             }
 
-             _PreviewPlayer.NormalizedTime = normalizedTime;
 
-         }
 
-         /************************************************************************************************************************/
 
-         /// <summary>Calculates the start and end pixels of the fade.</summary>
 
-         private bool CalculateFadeBounds(
 
-             Rect area,
 
-             out float startFadeX,
 
-             out float endFadeX)
 
-         {
 
-             var fadeDuration = _Target.FadeDuration;
 
-             if (!float.IsNaN(fadeDuration))
 
-             {
 
-                 startFadeX = area.LerpUnclampedX(_PreviewPlayer.InverseLerpTimeUnclamped(0));
 
-                 endFadeX = area.LerpUnclampedX(_PreviewPlayer.InverseLerpTimeUnclamped(fadeDuration));
 
-                 if (_Target.FromTransition.IsValid())
 
-                 {
 
-                     if (!_Target.ToTransition.IsValid())
 
-                     {
 
-                         endFadeX -= startFadeX;
 
-                         startFadeX = area.xMin;
 
-                     }
 
-                     return true;
 
-                 }
 
-                 else
 
-                 {
 
-                     if (_Target.ToTransition.IsValid())
 
-                     {
 
-                         return true;
 
-                     }
 
-                 }
 
-             }
 
-             startFadeX = area.LerpUnclampedX(_PreviewPlayer.InverseLerpTimeUnclamped(0));
 
-             endFadeX = startFadeX;
 
-             return false;
 
-         }
 
-         /************************************************************************************************************************/
 
-         /// <summary>Draws labels for the selected transitions.</summary>
 
-         private void DoTransitionLabels(Rect area)
 
-         {
 
-             area.xMin += 1;
 
-             area.xMax -= 2;
 
-             var mid = area.width * 0.5f;
 
-             var leftArea = area;
 
-             var rightArea = area;
 
-             var fromTransition = _Target.FromTransition;
 
-             var toTransition = _Target.ToTransition;
 
-             var hasFrom = fromTransition.IsValid();
 
-             var hasTo = toTransition.IsValid();
 
-             if (hasFrom && hasTo)
 
-             {
 
-                 leftArea.width = mid - StandardSpacing * 0.5f;
 
-                 rightArea.x = area.xMax - leftArea.width;
 
-                 rightArea.width = leftArea.width;
 
-             }
 
-             if (hasFrom)
 
-                 GUI.Label(leftArea, _Target.FromTransition.GetCachedName());
 
-             if (hasTo)
 
-                 GUI.Label(rightArea, _Target.ToTransition.GetCachedName(), RightLabelStyle);
 
-         }
 
-         /************************************************************************************************************************/
 
-         #endregion
 
-         /************************************************************************************************************************/
 
-     }
 
- }
 
- #endif
 
 
  |