// Animancer // Copyright 2020 Kybernetik //
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Animancer.Editor
{
/// [Editor-Only] Draws the Inspector GUI for an .
public sealed class AnimancerPlayableDrawer
{
/************************************************************************************************************************/
/// Only get during .
private bool _IsGraphPlaying;
/// A lazy list of information about the layers currently being displayed.
private readonly List
LayerInfos = new List();
/// The number of elements in that are currently being used.
private int _LayerCount;
/************************************************************************************************************************/
/// Draws the GUI of the if there is only one target.
public void DoGUI(IAnimancerComponent[] targets)
{
if (targets.Length != 1)
return;
DoGUI(targets[0]);
}
/************************************************************************************************************************/
/// Draws the GUI of the .
public void DoGUI(IAnimancerComponent target)
{
if (!target.IsPlayableInitialised)
{
DoPlayableNotInitialisedGUI(target);
return;
}
EditorGUI.BeginChangeCheck();
// Gather the during the layout event and use the same ones during subsequent events to avoid GUI errors
// in case they change (they shouldn't, but this is also more efficient).
if (Event.current.type == EventType.Layout)
{
AnimancerLayerDrawer.GatherLayerEditors(target.Playable, LayerInfos, out _LayerCount);
_IsGraphPlaying = target.Playable.IsGraphPlaying;
}
if (!_IsGraphPlaying)
{
AnimancerGUI.BeginVerticalBox(GUI.skin.box);
_IsGraphPlaying = EditorGUILayout.Toggle("Is Graph Playing", _IsGraphPlaying);
AnimancerGUI.EndVerticalBox(GUI.skin.box);
if (_IsGraphPlaying)
target.Playable.UnpauseGraph();
}
for (int i = 0; i < _LayerCount; i++)
{
LayerInfos[i].DoGUI(target);
}
DoLayerWeightWarningGUI();
if (AnimancerLayerDrawer.ShowUpdatingNodes)
target.Playable.DoUpdateListGUI();
if (EditorGUI.EndChangeCheck() && !_IsGraphPlaying)
target.Playable.Evaluate();
}
/************************************************************************************************************************/
private void DoPlayableNotInitialisedGUI(IAnimancerComponent target)
{
if (!EditorApplication.isPlaying ||
target.Animator == null ||
EditorUtility.IsPersistent(target.Animator))
return;
EditorGUILayout.HelpBox("Playable is not initialised." +
" It will be initialised automatically when something needs it, such as playing an animation.",
MessageType.Info);
if (AnimancerGUI.TryUseClickEventInLastRect(1))
{
var menu = new GenericMenu();
menu.AddItem(new GUIContent("Initialise"), false, () => target.Playable.Evaluate());
AnimancerEditorUtilities.AddDocumentationLink(menu, "Layer Documentation", "/docs/manual/blending/layers");
menu.ShowAsContext();
}
}
/************************************************************************************************************************/
private void DoLayerWeightWarningGUI()
{
for (int i = 0; i < _LayerCount; i++)
{
var layer = LayerInfos[i].Target;
if (layer.Weight == 1 &&
!layer.IsAdditive &&
layer._Mask == null &&
Mathf.Approximately(layer.GetTotalWeight(), 1))
return;
}
EditorGUILayout.HelpBox(
"There are no Override layers at weight 1, which will likely give undesirable results." +
" Click here for more information.",
MessageType.Warning);
if (AnimancerGUI.TryUseClickEventInLastRect())
EditorUtility.OpenWithDefaultApp(Strings.DocsURLs.Fading);
}
/************************************************************************************************************************/
}
}
#endif