/************************************************************************************************************************/ private void DoPlayableNotInitialisedGUI() { if (!EditorApplication.isPlaying) { return; } var target = _Targets[0]; if (EditorUtility.IsPersistent(target.gameObject)) { return; } EditorGUILayout.HelpBox("Playable is not initialised." + " It will be initialised automatically when something needs it, such as playing an animation.", MessageType.Info); var area = GUILayoutUtility.GetLastRect(); AnimancerLayerDrawer.HandleDragAndDropAnimations(area, target, 0); if (!AnimancerEditorUtilities.TryUseContextClick(area)) { return; } var menu = new GenericMenu(); menu.AddItem(new GUIContent("Initialise"), false, () => target.Playable.GetLayer(0)); AnimancerEditorUtilities.AddDocumentationLink(menu, "Layer Documentation", "/docs/manual/animation-layers"); menu.ShowAsContext(); }
/// <summary> /// Draws the state of each animation that is playing or has been played. /// </summary> protected void DoStatesGUI() { // If only multiple objects are selected and or the playable isn't initialised, don't draw anything. if (targets.Length != 1) { return; } var target = _Targets[0]; if (!target.IsPlayableInitialised) { DoPlayableNotInitialisedGUI(); return; } // 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) { AnimancerEditorUtilities.BeginVerticalBox(GUI.skin.box); _IsGraphPlaying = EditorGUILayout.Toggle("Is Graph Playing", _IsGraphPlaying); AnimancerEditorUtilities.EndVerticalBox(GUI.skin.box); if (_IsGraphPlaying) { target.Playable.UnpauseGraph(); } } for (int i = 0; i < _LayerCount; i++) { LayerInfos[i].DoInspectorGUI(target); } DoLayerWeightWarningGUI(); if (AnimancerLayerDrawer.ShowUpdatingNodes) { target.Playable.DoUpdateListGUI(); } }
/************************************************************************************************************************/ /// <summary>Draws the GUI of the <see cref="IAnimancerComponent.Playable"/>.</summary> 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(); } }
/************************************************************************************************************************/ #region Gathering /************************************************************************************************************************/ /// <summary> /// Initializes an editor in the list for each layer in the `animancer`. /// <para></para> /// The `count` indicates the number of elements actually being used. Spare elements are kept in the list in /// case they need to be used again later. /// </summary> internal static void GatherLayerEditors(AnimancerPlayable animancer, List <AnimancerLayerDrawer> editors, out int count) { count = animancer.Layers.Count; for (int i = 0; i < count; i++) { AnimancerLayerDrawer editor; if (editors.Count <= i) { editor = new AnimancerLayerDrawer(); editors.Add(editor); } else { editor = editors[i]; } editor.GatherStates(animancer.Layers._Layers[i]); } }
/************************************************************************************************************************/ /// <summary> /// Called by the Unity editor to draw the custom Inspector GUI elements. /// </summary> public override void OnInspectorGUI() { // Normally the targets wouldn't change after OnEnable, but the trick AnimancerComponent.Reset uses to // swap the type of an existing component when a new one is added causes the old target to be destroyed. GatherTargets(); serializedObject.Update(); var area = GUILayoutUtility.GetRect(0, 0); _AnimatorEditor.DoInspectorGUI(); DoOtherFieldsGUI(); PlayableDrawer.DoGUI(_Targets); area.yMax = GUILayoutUtility.GetLastRect().yMax; AnimancerLayerDrawer.HandleDragAndDropAnimations(area, _Targets[0], 0); serializedObject.ApplyModifiedProperties(); }
/************************************************************************************************************************/ /// <summary>Draws the GUI of the <see cref="IAnimancerComponent.Playable"/>.</summary> public void DoGUI(IAnimancerComponent target) { DoNativeAnimatorControllerGUI(target); if (!target.IsPlayableInitialized) { DoPlayableNotInitializedGUI(target); return; } EditorGUI.BeginChangeCheck(); var playable = target.Playable; // 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(playable, LayerInfos, out _LayerCount); } DoRootGUI(playable); for (int i = 0; i < _LayerCount; i++) { LayerInfos[i].DoGUI(); } DoLayerWeightWarningGUI(target); if (ShowInternalDetails) { DoInternalDetailsGUI(playable); } if (EditorGUI.EndChangeCheck() && !playable.IsGraphPlaying) { playable.Evaluate(); } }