/************************************************************************************************************************/ /// <summary> /// Asks if the user wants to delete the root Animancer folder and does so if they confirm. /// </summary> private void CheckDeleteAnimancer() { if (!AnimancerEditorUtilities.TryUseClickInLastRect()) { return; } if (!AssetDatabase.IsValidFolder(AnimancerDirectory)) { Debug.Log(AnimancerDirectory + " doesn't exist." + " You must have moved Animancer somewhere else so you will need to delete it manually."); return; } if (!EditorUtility.DisplayDialog("Delete Animancer?", "Would you like to delete " + AnimancerDirectory + "?" + "\n\nYou will then need to reimport Animancer manually.", "Delete", "Cancel")) { return; } AssetDatabase.DeleteAsset(AnimancerDirectory); Close(); File.Delete(LockFile); }
/************************************************************************************************************************/ private void DoLayerWeightWarningGUI() { for (int i = 0; i < _LayerCount; i++) { var layer = LayerInfos[i].Layer; 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 (AnimancerEditorUtilities.TryUseClickInLastRect()) { EditorUtility.OpenWithDefaultApp( AnimancerPlayable.APIDocumentationURL + "/docs/manual/smooth-transitions"); } }
/************************************************************************************************************************/ private void DoAnimatorGUI() { var hasAnimator = AnimatorProperty.objectReferenceValue != null; var color = GUI.color; if (!hasAnimator) { GUI.color = AnimancerEditorUtilities.WarningFieldColor; } EditorGUILayout.PropertyField(AnimatorProperty); if (!hasAnimator) { GUI.color = color; EditorGUILayout.HelpBox("An Animator is required in order to play animations." + " Click here to search for one nearby.", MessageType.Warning); if (AnimancerEditorUtilities.TryUseClickInLastRect()) { AnimancerEditorUtilities.ForEachTarget(AnimatorProperty, (property) => { var target = (IAnimancerComponent)property.serializedObject.targetObject; // Can't use AnimancerEditorUtilities.GetComponentInHierarchy // because Animancer Lite leaves it outside the DLL. var animator = target.gameObject.GetComponentInParent <Animator>(); if (animator == null) { animator = target.gameObject.GetComponentInChildren <Animator>(); if (animator == null) { Debug.Log("No Animator found on '" + target + "' or any of its parents or children." + " You must assign one manually.", target.gameObject); return; } } property.objectReferenceValue = animator; }); } } }
/************************************************************************************************************************/ /// <summary>Draws all states in the given layer.</summary> public void DoInspectorGUI(IAnimancerComponent owner) { AnimancerEditorUtilities.BeginVerticalBox(GUI.skin.box); DoHeaderGUI(); if (HideInactiveStates) { DoStatesGUI("Active States", ActiveStates, owner); } else if (SeparateActiveFromInactiveStates) { DoStatesGUI("Active States", ActiveStates, owner); DoStatesGUI("Inactive States", InactiveStates, owner); } else { DoStatesGUI("States", ActiveStates, owner); } if (Layer.PortIndex == 0 && Layer.Weight != 0 && !Layer.IsAdditive && !Mathf.Approximately(Layer.GetTotalWeight(), 1)) { EditorGUILayout.HelpBox( "The total Weight of all states in this layer does not equal 1, which will likely give undesirable results." + " Click here for more information.", MessageType.Warning); if (AnimancerEditorUtilities.TryUseClickInLastRect()) { EditorUtility.OpenWithDefaultApp( AnimancerPlayable.APIDocumentationURL + "/docs/manual/smooth-transitions"); } } AnimancerEditorUtilities.EndVerticalBox(GUI.skin.box); var totalArea = GUILayoutUtility.GetLastRect(); HandleDragAndDropAnimations(totalArea, owner, Layer.PortIndex); CheckContextMenu(totalArea); }
/************************************************************************************************************************/ /// <summary> /// Draws the <see cref="Animator.updateMode"/> field with any appropriate warnings. /// </summary> private void DoUpdateModeGUI(bool showWithoutWarning) { if (_UpdateMode == null) { return; } var label = AnimancerEditorUtilities.TempContent("Update Mode", "Controls when and how often the animations are updated"); var initialUpdateMode = Targets[0].InitialUpdateMode; var updateMode = (AnimatorUpdateMode)_UpdateMode.intValue; EditorGUI.BeginChangeCheck(); if (!EditorApplication.isPlaying || !AnimancerPlayable.HasChangedToOrFromAnimatePhysics(initialUpdateMode, updateMode)) { if (showWithoutWarning) { EditorGUILayout.PropertyField(_UpdateMode, label); } } else { GUILayout.BeginHorizontal(); var color = GUI.color; GUI.color = AnimancerEditorUtilities.WarningFieldColor; EditorGUILayout.PropertyField(_UpdateMode, label); GUI.color = color; label = AnimancerEditorUtilities.TempContent("Revert", "Revert to initial mode"); if (GUILayout.Button(label, EditorStyles.miniButton, AnimancerEditorUtilities.DontExpandWidth)) { _UpdateMode.intValue = (int)initialUpdateMode.Value; } GUILayout.EndHorizontal(); EditorGUILayout.HelpBox( "Changing to or from AnimatePhysics mode at runtime has no effect when using the" + " Playables API. It will continue using the original mode it had on startup.", MessageType.Warning); if (AnimancerEditorUtilities.TryUseClickInLastRect()) { EditorUtility.OpenWithDefaultApp(AnimancerPlayable.APIDocumentationURL + "/docs/unity-bugs/update-modes"); } } if (EditorGUI.EndChangeCheck()) { _OnEndGUI += () => { for (int i = 0; i < _Animators.Length; i++) { var animator = _Animators[i]; if (animator != null) { AnimancerEditorUtilities.Invoke(animator, "OnUpdateModeChanged"); } } }; } }
/************************************************************************************************************************/ /// <summary> /// Draws the <see cref="Animator.runtimeAnimatorController"/> field with a warning if a controller is /// assigned. /// </summary> private void DoControllerGUI() { if (_Controller == null) { return; } var controller = _Animators[0].runtimeAnimatorController; var showMixedValue = EditorGUI.showMixedValue; for (int i = 1; i < _Animators.Length; i++) { if (_Animators[i].runtimeAnimatorController != controller) { EditorGUI.showMixedValue = true; break; } } if (controller == null && !EditorGUI.showMixedValue) { return; } var label = AnimancerEditorUtilities.TempContent("Controller"); EditorGUI.BeginChangeCheck(); var area = EditorGUILayout.BeginHorizontal(); label = EditorGUI.BeginProperty(area, label, _Controller); var color = GUI.color; GUI.color = AnimancerEditorUtilities.WarningFieldColor; controller = (RuntimeAnimatorController)EditorGUILayout.ObjectField(label, controller, typeof(RuntimeAnimatorController), false); GUI.color = color; if (GUILayout.Button("Remove", EditorStyles.miniButton, AnimancerEditorUtilities.DontExpandWidth)) { controller = null; } GUILayout.EndHorizontal(); if (EditorGUI.EndChangeCheck()) { Undo.RecordObjects(_Animators, "Changed AnimatorController"); for (int i = 0; i < _Animators.Length; i++) { _Animators[i].runtimeAnimatorController = controller; } OnControllerChanged(); } EditorGUI.showMixedValue = showMixedValue; EditorGUILayout.HelpBox( "The AnimatorController will not affect the model while Animancer is active," + " however Unity will still execute it's state machine in the background," + " which may be a waste of processing time if you aren't using it intentionally." + " Click here for more information.", MessageType.Warning); if (AnimancerEditorUtilities.TryUseClickInLastRect()) { EditorUtility.OpenWithDefaultApp(AnimancerPlayable.APIDocumentationURL + "/docs/manual/animator-controller-states"); } }