123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
- #if UNITY_EDITOR && UNITY_IMGUI
- using System;
- using UnityEditor;
- using UnityEngine;
- using static Animancer.Editor.AnimancerGUI;
- using Object = UnityEngine.Object;
- namespace Animancer.Editor.Previews
- {
- /// <summary>[Editor-Only]
- /// An interactive preview which displays the internal details of an <see cref="AnimancerComponent"/>.
- /// </summary>
- /// https://kybernetik.com.au/animancer/api/Animancer.Editor.Previews/AnimancerComponentPreview
- [CustomPreview(typeof(AnimancerComponent))]
- public class AnimancerComponentPreview : ObjectPreview
- {
- /************************************************************************************************************************/
- private static readonly GUIContent
- Title = new(nameof(Animancer));
- /// <inheritdoc/>
- public override GUIContent GetPreviewTitle()
- => Title;
- /************************************************************************************************************************/
- [NonSerialized] private IAnimancerComponent _Animancer;
- [NonSerialized] private UnityEditor.Editor _Editor;
- /// <summary>The drawer for the <see cref="IAnimancerComponent.Graph"/>.</summary>
- private readonly AnimancerGraphDrawer
- GraphDrawer = new();
- /************************************************************************************************************************/
- /// <inheritdoc/>
- public override void Initialize(Object[] targets)
- {
- _Animancer = targets.Length == 1
- ? targets[0] as IAnimancerComponent
- : null;
- _Editor = UnityEditor.Editor.CreateEditor(targets);
- base.Initialize(targets);
- EditorApplication.update += Update;
- }
- /************************************************************************************************************************/
- /// <inheritdoc/>
- public override void Cleanup()
- {
- EditorApplication.update -= Update;
- Object.DestroyImmediate(_Editor);
- base.Cleanup();
- }
- /************************************************************************************************************************/
- /// <inheritdoc/>
- public override bool HasPreviewGUI()
- => !_Animancer.IsNullOrDestroyed()
- && _Animancer.IsGraphInitialized;
- /************************************************************************************************************************/
- private static GUIStyle _ToolbarButtonStyle;
- /// <inheritdoc/>
- public override void OnPreviewSettings()
- {
- base.OnPreviewSettings();
- _ToolbarButtonStyle ??= new(EditorStyles.toolbarButton)
- {
- padding = new(),
- };
- var graph = _Animancer.Graph;
- if (!graph.IsGraphPlaying)
- {
- var stepArea = GUILayoutUtility.GetRect(LineHeight * 1.5f, LineHeight);
- AnimancerGraphControls.DoFrameStepButton(stepArea, graph, _ToolbarButtonStyle);
- }
- var area = GUILayoutUtility.GetRect(LineHeight * 1.5f, LineHeight);
- AnimancerGraphControls.DoPlayPauseToggle(area, graph, _ToolbarButtonStyle);
- area = GUILayoutUtility.GetRect(LineHeight * 2f, LineHeight);
- AnimancerGraphSpeedSlider.Instance.Graph = graph;
- AnimancerGraphSpeedSlider.Instance.DoToggleGUI(area, _ToolbarButtonStyle);
- }
- /************************************************************************************************************************/
- [NonSerialized]
- private static GUIStyle _PaddingStyle;
- [NonSerialized]
- private Rect _Area;
- [SerializeField]
- private Vector2 _ScrollPosition;
- /// <inheritdoc/>
- public override void OnInteractivePreviewGUI(Rect area, GUIStyle background)
- {
- _PaddingStyle ??= new()
- {
- padding = new((int)StandardSpacing, (int)StandardSpacing, (int)StandardSpacing, (int)StandardSpacing),
- };
- // The area isn't properly set during Layout events so remember it after each Repaint.
- if (area.y == 0)
- area.y = EditorStyles.toolbar.fixedHeight + 1;
- if (Event.current.type == EventType.Repaint)
- _Area = area;
- // Draw the graph.
- var labelWidth = EditorGUIUtility.labelWidth;
- EditorGUIUtility.labelWidth += IndentSize;
- GUILayout.BeginArea(_Area);
- _ScrollPosition = GUILayout.BeginScrollView(_ScrollPosition, _PaddingStyle);
- GraphDrawer.DoGUI(_Animancer);
- GUILayout.EndScrollView();
- GUILayout.EndArea();
- EditorGUIUtility.labelWidth = labelWidth;
- _LastRepaintTime = EditorApplication.timeSinceStartup;
- }
- /************************************************************************************************************************/
- [NonSerialized]
- private double _LastRepaintTime = double.NegativeInfinity;
- /// <summary>Repaints the preview if necessary.</summary>
- private void Update()
- {
- if (!HasPreviewGUI() ||
- !UnityEditorInternal.InternalEditorUtility.isApplicationActive)
- return;
- var targetDeltaTime = 1f / AnimancerComponentPreviewSettings.RepaintRate;
- var nextRepaintTime = _LastRepaintTime + targetDeltaTime;
- if (EditorApplication.timeSinceStartup > nextRepaintTime)
- _Editor.Repaint();
- // This seems to be the least hacky way to repaint only the Inspector window.
- // Ideally an interactive preview would have a way to repaint itself.
- }
- /************************************************************************************************************************/
- }
- /************************************************************************************************************************/
- #region Settings
- /************************************************************************************************************************/
- /// <summary>[Editor-Only] Settings for <see cref="AnimancerComponentPreview"/>.</summary>
- /// https://kybernetik.com.au/animancer/api/Animancer.Editor.Previews/AnimancerComponentPreviewSettings
- [Serializable, InternalSerializableType]
- public class AnimancerComponentPreviewSettings : AnimancerSettingsGroup
- {
- /************************************************************************************************************************/
- /// <inheritdoc/>
- public override string DisplayName
- => "Live Inspector";
- /// <inheritdoc/>
- public override int Index
- => 1;
- /************************************************************************************************************************/
- [SerializeField, Range(1, 100)]
- [Tooltip("The target frame rate of repaint commands (FPS)")]
- private float _RepaintRate = 30;
- /// <summary>The target frame rate of repaint commands (FPS).</summary>
- public static float RepaintRate
- => AnimancerSettingsGroup<AnimancerComponentPreviewSettings>.Instance._RepaintRate;
- /************************************************************************************************************************/
- }
- /************************************************************************************************************************/
- #endregion
- /************************************************************************************************************************/
- }
- #endif
|