/************************************************************************************************************************/ /// <summary> /// Draws the name and other details of the <see cref="Layer"/> in the GUI. /// </summary> private void DoHeaderGUI() { if (Layer.Root.LayerCount <= 1 && Layer.Weight == 1 && Layer._Mask == null) { return; } var area = AnimancerEditorUtilities.GetRect(); const float FoldoutIndent = 12; area.xMin += FoldoutIndent; Layer._IsInspectorExpanded = EditorGUI.Foldout(area, Layer._IsInspectorExpanded, GUIContent.none, true); AnimancerEditorUtilities.DoWeightLabelGUI(ref area, Layer.Weight); var label = Layer.IsAdditive ? "Additive" : "Override"; if (Layer._Mask != null) { label = string.Concat(label, " (", Layer._Mask.name, ")"); } EditorGUIUtility.labelWidth -= FoldoutIndent; EditorGUI.LabelField(area, Layer.Name, label); EditorGUIUtility.labelWidth += FoldoutIndent; if (Layer._IsInspectorExpanded) { GUILayout.BeginHorizontal(); GUILayout.Space(FoldoutIndent); GUILayout.BeginVertical(); EditorGUI.indentLevel++; Layer.IsAdditive = EditorGUILayout.Toggle("Is Additive", Layer.IsAdditive); EditorGUI.BeginChangeCheck(); Layer._Mask = (AvatarMask)EditorGUILayout.ObjectField("Mask", Layer._Mask, typeof(AvatarMask), false); if (EditorGUI.EndChangeCheck()) { Layer.SetMask(Layer._Mask); } EditorGUI.BeginChangeCheck(); var weight = EditorGUILayout.FloatField("Weight", Layer.Weight); if (EditorGUI.EndChangeCheck()) { Layer.Weight = weight; } area = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight); Layer.DoFadeDetailsGUI(area); EditorGUI.indentLevel--; GUILayout.EndVertical(); GUILayout.EndHorizontal(); } }
/************************************************************************************************************************/ /// <summary> Draws the details of the target state in the GUI.</summary> protected virtual void DoDetailsGUI(IAnimancerComponent owner) { EditorGUI.indentLevel++; DoTimeSliderGUI(); DoPlayingDetailsGUI(); State.DoFadeDetailsGUI(AnimancerEditorUtilities.GetRect(true)); DoOnEndGUI(); EditorGUI.indentLevel--; }
/************************************************************************************************************************/ private void DoDefaultAnimationField(SerializedProperty property) { var area = AnimancerEditorUtilities.GetRect(); var label = AnimancerEditorUtilities.TempContent("Default Animation", "If 'Play Automatically' is enabled, this animation will be played by OnEnable"); SerializedProperty firstElement; AnimationClip clip; if (property.arraySize > 0) { firstElement = property.GetArrayElementAtIndex(0); clip = (AnimationClip)firstElement.objectReferenceValue; label = EditorGUI.BeginProperty(area, label, firstElement); } else { firstElement = null; clip = null; label = EditorGUI.BeginProperty(area, label, property); } EditorGUI.BeginChangeCheck(); clip = (AnimationClip)EditorGUI.ObjectField(area, label, clip, typeof(AnimationClip), true); if (EditorGUI.EndChangeCheck()) { if (clip != null) { if (firstElement == null) { property.arraySize = 1; firstElement = property.GetArrayElementAtIndex(0); } firstElement.objectReferenceValue = clip; } else { if (firstElement == null || property.arraySize == 1) { property.arraySize = 0; } else { firstElement.objectReferenceValue = clip; } } } EditorGUI.EndProperty(); }
/************************************************************************************************************************/ private void DoOnEndGUI() { if (State.OnEnd == null) { return; } var area = AnimancerEditorUtilities.GetRect(true); EditorGUI.LabelField(area, "OnEnd: " + State.OnEnd.Method); }
/************************************************************************************************************************/ /// <summary>Draws a slider for controlling the current <see cref="AnimancerState.Time"/>.</summary> private void DoTimeSliderGUI() { if (!State.HasLength) { return; } float length; var time = GetWrappedTime(out length); if (length == 0) { return; } var area = AnimancerEditorUtilities.GetRect(true); var normalized = DoNormalizedTimeToggle(ref area); string label; float max; if (normalized) { label = "Normalized Time"; time /= length; max = 1; } else { label = "Time"; max = length; } DoLoopCounterGUI(ref area, length); EditorGUI.BeginChangeCheck(); label = AnimancerEditorUtilities.BeginTightLabel(label); time = EditorGUI.Slider(area, label, time, 0, max); AnimancerEditorUtilities.EndTightLabel(); if (EditorGUI.EndChangeCheck()) { if (normalized) { State.NormalizedTime = time; } else { State.Time = time; } State.Root.Evaluate(); } }
/************************************************************************************************************************/ /// <summary> /// Draws controls for <see cref="AnimancerState.IsPlaying"/>, <see cref="AnimancerState.Speed"/>, and /// <see cref="AnimancerState.Weight"/>. /// </summary> protected void DoPlayingDetailsGUI() { var labelWidth = EditorGUIUtility.labelWidth; var area = AnimancerEditorUtilities.GetRect(true); var right = area.xMax; // Is Playing. var label = AnimancerEditorUtilities.BeginTightLabel("Is Playing"); area.width = EditorGUIUtility.labelWidth + 16; State.IsPlaying = EditorGUI.Toggle(area, label, State.IsPlaying); AnimancerEditorUtilities.EndTightLabel(); area.x += area.width; area.xMax = right; float speedWidth, weightWidth; Rect speedRect, weightRect; AnimancerEditorUtilities.SplitHorizontally(area, "Speed", "Weight", out speedWidth, out weightWidth, out speedRect, out weightRect); var indentLevel = EditorGUI.indentLevel; EditorGUI.indentLevel = 0; // Speed. EditorGUIUtility.labelWidth = speedWidth; EditorGUI.BeginChangeCheck(); var speed = EditorGUI.FloatField(speedRect, "Speed", State.Speed); if (EditorGUI.EndChangeCheck()) { State.Speed = speed; } // Weight. EditorGUIUtility.labelWidth = weightWidth; EditorGUI.BeginChangeCheck(); var weight = EditorGUI.FloatField(weightRect, "Weight", State.Weight); if (EditorGUI.EndChangeCheck()) { State.Weight = weight; } EditorGUI.indentLevel = indentLevel; EditorGUIUtility.labelWidth = labelWidth; }
/************************************************************************************************************************/ /// <summary>Draws all 'states' in the given list.</summary> private void DoStatesGUI(string label, List <AnimancerState> states, IAnimancerComponent owner) { var area = AnimancerEditorUtilities.GetRect(); var width = GUI.skin.label.CalculateWidth("Weight"); GUI.Label(AnimancerEditorUtilities.StealWidth(ref area, width), "Weight"); EditorGUI.LabelField(area, label, states.Count.ToString()); EditorGUI.indentLevel++; for (int i = 0; i < states.Count; i++) { DoStateGUI(states[i], owner); } EditorGUI.indentLevel--; }
/************************************************************************************************************************/ /// <summary>Draws the details and controls for the target <see cref="State"/> in the inspector.</summary> public virtual void DoGUI(IAnimancerComponent owner) { GUILayout.BeginVertical(); { var position = AnimancerEditorUtilities.GetRect(true); string label; DoFoldoutGUI(position, out label); DoLabelGUI(ref position, label); if (_IsExpanded) { DoDetailsGUI(owner); } } GUILayout.EndVertical(); CheckContextMenu(GUILayoutUtility.GetLastRect()); }
/************************************************************************************************************************/ /// <summary> /// Draws the <see cref="Animator.keepAnimatorControllerStateOnDisable"/> field. /// </summary> public static void DoStopOnDisableGUI(SerializedProperty keepStateOnDisable, bool updateAndApply) { #if UNITY_2018_1_OR_NEWER var area = AnimancerEditorUtilities.GetRect(); var label = AnimancerEditorUtilities.TempContent("Stop On Disable", "If true, disabling this object will stop and rewind all animations." + " Otherwise they will simply be paused and will resume from their current states when it is re-enabled."); if (keepStateOnDisable != null) { if (updateAndApply) { keepStateOnDisable.serializedObject.Update(); } label = EditorGUI.BeginProperty(area, label, keepStateOnDisable); keepStateOnDisable.boolValue = !EditorGUI.Toggle(area, label, !keepStateOnDisable.boolValue); EditorGUI.EndProperty(); if (updateAndApply) { keepStateOnDisable.serializedObject.ApplyModifiedProperties(); } } else { var enabled = GUI.enabled; GUI.enabled = false; EditorGUI.Toggle(area, label, false); GUI.enabled = enabled; } #endif }
/************************************************************************************************************************/ /// <summary> Draws the details of the target state in the GUI.</summary> protected override void DoDetailsGUI(IAnimancerComponent owner) { base.DoDetailsGUI(owner); var animator = owner.Animator; if (animator == null) { return; } var count = ParameterCount; if (count <= 0) { return; } var labelWidth = EditorGUIUtility.labelWidth; EditorGUIUtility.labelWidth -= AnimancerEditorUtilities.IndentSize; var area = AnimancerEditorUtilities.GetRect(true); area = EditorGUI.IndentedRect(area); EditorGUI.LabelField(area, "Parameters", count.ToString()); for (int i = 0; i < count; i++) { var type = GetParameterType(i); if (type == 0) { continue; } var name = GetParameterName(i); var value = GetParameterValue(i); EditorGUI.BeginChangeCheck(); area = AnimancerEditorUtilities.GetRect(true); area = EditorGUI.IndentedRect(area); switch (type) { case AnimatorControllerParameterType.Float: value = EditorGUI.FloatField(area, name, (float)value); break; case AnimatorControllerParameterType.Int: value = EditorGUI.IntField(area, name, (int)value); break; case AnimatorControllerParameterType.Bool: value = EditorGUI.Toggle(area, name, (bool)value); break; case AnimatorControllerParameterType.Trigger: value = EditorGUI.Toggle(area, name, (bool)value, EditorStyles.radioButton); break; default: EditorGUI.LabelField(area, name, "Unhandled Type: " + type); break; } if (EditorGUI.EndChangeCheck()) { SetParameterValue(i, value); } } EditorGUIUtility.labelWidth = labelWidth; }