/************************************************************************************************************************/ /// <summary> /// Draws controls for <see cref="AnimancerLayer.IsAdditive"/> and <see cref="AnimancerLayer._Mask"/>. /// </summary> private void DoLayerDetailsGUI() { var area = AnimancerGUI.LayoutSingleLineRect(AnimancerGUI.SpacingMode.Before); area = EditorGUI.IndentedRect(area); var labelWidth = EditorGUIUtility.labelWidth; var indentLevel = EditorGUI.indentLevel; EditorGUI.indentLevel = 0; var additiveLabel = AnimancerGUI.GetNarrowText("Is Additive"); var additiveWidth = GUI.skin.toggle.CalculateWidth(additiveLabel); var maskRect = AnimancerGUI.StealFromRight(ref area, area.width - additiveWidth); // Additive. EditorGUIUtility.labelWidth = AnimancerGUI.CalculateLabelWidth(additiveLabel); Target.IsAdditive = EditorGUI.Toggle(area, additiveLabel, Target.IsAdditive); // Mask. using (ObjectPool.Disposable.AcquireContent(out var label, "Mask")) { EditorGUIUtility.labelWidth = AnimancerGUI.CalculateLabelWidth(label.text); EditorGUI.BeginChangeCheck(); Target._Mask = (AvatarMask)EditorGUI.ObjectField(maskRect, label, Target._Mask, typeof(AvatarMask), false); if (EditorGUI.EndChangeCheck()) { Target.SetMask(Target._Mask); } } EditorGUI.indentLevel = indentLevel; EditorGUIUtility.labelWidth = labelWidth; }
/// <summary> /// If the `property` is a "Start Time" field, this method draws it as well as the "End Time" below it and /// returns true. /// </summary> public static bool TryDoStartTimeField(ref Rect area, SerializedProperty rootProperty, SerializedProperty property, GUIContent label) { if (!property.propertyPath.EndsWith("." + NormalizedStartTimeFieldName)) { return(false); } // Start Time. label.text = AnimancerGUI.GetNarrowText("Start Time"); var length = Context.MaximumDuration; var defaultStartTime = AnimancerEvent.Sequence.GetDefaultNormalizedStartTime(Context.Transition.Speed); AnimancerGUI.DoOptionalTimeField(ref area, label, property, true, length, defaultStartTime); AnimancerGUI.NextVerticalArea(ref area); // End Time. var events = rootProperty.FindPropertyRelative("_Events"); using (var context = EventSequenceDrawer.Context.Get(events)) { var areaCopy = area; var index = Mathf.Max(0, context.TimeCount - 1); string callbackLabel; EventSequenceDrawer.DoEventTimeGUI(ref areaCopy, context, index, true, out callbackLabel); } return(true); }
/// <summary> /// If the `property` is a "Start Time" field, this method draws it as well as the "End Time" below it and /// returns true. /// </summary> public static bool TryDoStartTimeField(ref Rect area, SerializedProperty rootProperty, SerializedProperty property, GUIContent label) { if (!property.propertyPath.EndsWith("." + NormalizedStartTimeFieldName)) { return(false); } // Start Time. label.text = AnimancerGUI.GetNarrowText("Start Time"); AnimationTimeAttribute.nextDefaultValue = AnimancerEvent.Sequence.GetDefaultNormalizedStartTime(Context.Transition.Speed); EditorGUI.PropertyField(area, property, label, false); AnimancerGUI.NextVerticalArea(ref area); // End Time. var events = rootProperty.FindPropertyRelative("_Events"); using (var context = SerializableEventSequenceDrawer.Context.Get(events)) { var areaCopy = area; var index = Mathf.Max(0, context.Times.Count - 1); SerializableEventSequenceDrawer.DoTimeGUI(ref areaCopy, context, index, true); } return(true); }
private void DoRootMotionGUI() { if (_RootMotion == null) { return; } var text = AnimancerGUI.GetNarrowText("Apply Root Motion"); var animator = _Animators[0]; if (_Animators.Length == 1 && (bool)AnimancerEditorUtilities.Invoke(animator, "get_supportsOnAnimatorMove")) { EditorGUILayout.LabelField(text, "Handled by Script"); } else { EditorGUILayout.PropertyField(_RootMotion, AnimancerGUI.TempContent(text, "If enabled, the Animator will automatically move the object using the root motion from the animations")); if (Event.current.type == EventType.Layout) { _IsRootPositionOrRotationControlledByCurves = (bool)AnimancerEditorUtilities.Invoke(animator, "get_isRootPositionOrRotationControlledByCurves"); } if (_IsRootPositionOrRotationControlledByCurves && !_RootMotion.boolValue) { EditorGUILayout.HelpBox("Root position or rotation are controlled by curves", MessageType.Info, true); } } }
/************************************************************************************************************************/ /// <summary>Draws the rest of the Inspector fields after the Animator field.</summary> protected void DoOtherFieldsGUI() { var property = serializedObject.GetIterator(); if (!property.NextVisible(true)) { return; } do { using (ObjectPool.Disposable.Acquire <GUIContent>(out var label)) { var path = property.propertyPath; if (path == "m_Script") { continue; } label.text = AnimancerGUI.GetNarrowText(property.displayName); label.tooltip = property.tooltip; // Let the target try to override. if (DoOverridePropertyGUI(property.propertyPath, property, label)) { continue; } // Otherwise draw the property normally. EditorGUILayout.PropertyField(property, label, true); } }while (property.NextVisible(false)); }
/************************************************************************************************************************/ /// <summary> /// Draws controls for <see cref="AnimancerNode.FadeSpeed"/> and <see cref="AnimancerNode.TargetWeight"/>. /// </summary> private void DoFadeDetailsGUI() { var area = AnimancerGUI.LayoutSingleLineRect(AnimancerGUI.SpacingMode.Before); area = EditorGUI.IndentedRect(area); var speedLabel = AnimancerGUI.GetNarrowText("Fade Speed"); var targetLabel = AnimancerGUI.GetNarrowText("Target Weight"); float speedWidth, weightWidth; Rect speedRect, weightRect; AnimancerGUI.SplitHorizontally(area, speedLabel, targetLabel, out speedWidth, out weightWidth, out speedRect, out weightRect); var labelWidth = EditorGUIUtility.labelWidth; var indentLevel = EditorGUI.indentLevel; EditorGUI.indentLevel = 0; EditorGUI.BeginChangeCheck(); // Fade Speed. EditorGUIUtility.labelWidth = speedWidth; Target.FadeSpeed = EditorGUI.DelayedFloatField(speedRect, speedLabel, Target.FadeSpeed); if (AnimancerGUI.TryUseClickEvent(speedRect, 2)) { Target.FadeSpeed = Target.FadeSpeed != 0 ? 0 : Math.Abs(Target.Weight - Target.TargetWeight) / AnimancerPlayable.DefaultFadeDuration; } // Target Weight. EditorGUIUtility.labelWidth = weightWidth; Target.TargetWeight = EditorGUI.FloatField(weightRect, targetLabel, Target.TargetWeight); if (AnimancerGUI.TryUseClickEvent(weightRect, 2)) { if (Target.TargetWeight != Target.Weight) { Target.TargetWeight = Target.Weight; } else if (Target.TargetWeight != 1) { Target.TargetWeight = 1; } else { Target.TargetWeight = 0; } } if (EditorGUI.EndChangeCheck() && Target.FadeSpeed != 0) { Target.StartFade(Target.TargetWeight, 1 / Target.FadeSpeed); } EditorGUI.indentLevel = indentLevel; EditorGUIUtility.labelWidth = labelWidth; }
/************************************************************************************************************************/ private void DoHeaderGUI(Rect area, SerializedProperty property, GUIContent label, bool isPreviewing, out float height) { area.height = AnimancerGUI.LineHeight; DoPreviewButtonGUI(ref area, property, isPreviewing); label.text = AnimancerGUI.GetNarrowText(label.text); var mainProperty = GetMainProperty(property); if (mainProperty != null) { var mainPropertyReferenceIsMissing = mainProperty.propertyType == SerializedPropertyType.ObjectReference && mainProperty.objectReferenceValue == null; DoPropertyGUI(ref area, property, mainProperty, label); // If the main Object reference was just assigned and all fields were at their type default, // reset the value to run its default constructor and field initialisers then reassign the reference. var reference = mainProperty.objectReferenceValue; if (mainPropertyReferenceIsMissing && reference != null) { mainProperty.objectReferenceValue = null; if (Serialization.IsDefaultValueByType(property)) { Serialization.ResetValue(property); } mainProperty.objectReferenceValue = reference; } if (_Mode != Mode.AlwaysExpanded) { var hierarchyMode = EditorGUIUtility.hierarchyMode; EditorGUIUtility.hierarchyMode = true; property.isExpanded = EditorGUI.Foldout(area, property.isExpanded, GUIContent.none, true); EditorGUIUtility.hierarchyMode = hierarchyMode; } } else { area.height = EditorGUI.GetPropertyHeight(property, label, false); if (_Mode != Mode.AlwaysExpanded) { EditorGUI.PropertyField(area, property, label, false); } else { label = EditorGUI.BeginProperty(area, label, property); EditorGUI.LabelField(area, label); EditorGUI.EndProperty(); } } height = area.height; }
/************************************************************************************************************************/ private void DoHeaderGUI(ref Rect area, GUIContent label, Context context) { area.height = AnimancerGUI.LineHeight; var headerArea = area; AnimancerGUI.NextVerticalArea(ref area); label = EditorGUI.BeginProperty(headerArea, label, context.Property); if (!context.Property.hasMultipleDifferentValues) { var addEventArea = AnimancerGUI.StealFromRight(ref headerArea, headerArea.height, AnimancerGUI.StandardSpacing); DoAddRemoveEventButtonGUI(addEventArea, context); } if (context.TransitionContext != null && context.TransitionContext.Transition != null) { EditorGUI.EndProperty(); TimelineGUI.DoGUI(headerArea, context, out var addEventNormalizedTime); if (!float.IsNaN(addEventNormalizedTime)) { AddEvent(context, addEventNormalizedTime); } } else { label.text = AnimancerGUI.GetNarrowText(label.text); string summary; if (context.Times.Count == 0) { summary = "[0] End Time 1"; } else { var index = context.Times.Count - 1; var endTime = context.Times.GetElement(index).floatValue; summary = $"[{index}] End Time {endTime:G3}"; } using (ObjectPool.Disposable.AcquireContent(out var content, summary)) EditorGUI.LabelField(headerArea, label, content); EditorGUI.EndProperty(); } EditorGUI.BeginChangeCheck(); context.Property.isExpanded = EditorGUI.Foldout(headerArea, context.Property.isExpanded, GUIContent.none, true); if (EditorGUI.EndChangeCheck()) { context.SelectedEvent = -1; } }
private void DoHeaderGUI(ref Rect area, GUIContent label, Context context) { area.height = AnimancerGUI.LineHeight; var headerArea = area; AnimancerGUI.NextVerticalArea(ref area); label = EditorGUI.BeginProperty(headerArea, label, context.Property); var addEventArea = AnimancerGUI.StealFromRight(ref headerArea, headerArea.height, AnimancerGUI.StandardSpacing); DoAddEventButtonGUI(addEventArea, context); if (context.TransitionContext != null && context.TransitionContext.Transition != null) { EditorGUI.EndProperty(); float addEventNormalizedTime; TimeRuler.DoGUI(headerArea, context, out addEventNormalizedTime); if (!float.IsNaN(addEventNormalizedTime)) { AddEvent(context, addEventNormalizedTime); } } else { label.text = AnimancerGUI.GetNarrowText(label.text); var summary = AnimancerGUI.TempContent(); if (context.TimeCount == 0) { summary.text = "[0] End Time 1"; } else { var index = context.TimeCount - 1;; var endTime = context.GetTime(index).floatValue; summary.text = string.Concat("[", index.ToString(), "] End Time ", endTime.ToString("G3")); } EditorGUI.LabelField(headerArea, label, summary); EditorGUI.EndProperty(); } EditorGUI.BeginChangeCheck(); context.Property.isExpanded = EditorGUI.Foldout(headerArea, context.Property.isExpanded, GUIContent.none, true); if (EditorGUI.EndChangeCheck()) { context.SelectedEvent = -1; } }
/// <summary> /// Draws the rest of the Inspector fields after the Animator field. /// </summary> protected void DoOtherFieldsGUI() { var property = _AnimatorEditor.AnimatorProperty.Copy(); while (property.NextVisible(false)) { Label.text = AnimancerGUI.GetNarrowText(property.displayName); Label.tooltip = property.tooltip; // Let the target try to override. if (DoOverridePropertyGUI(property.propertyPath, property, Label)) { continue; } // Otherwise draw the property normally. EditorGUILayout.PropertyField(property, Label, true); } }
/************************************************************************************************************************/ private void DoHeaderGUI(Rect area, SerializedProperty property, GUIContent label, bool isPreviewing, out float height) { area.height = AnimancerGUI.LineHeight; DoPreviewButtonGUI(ref area, property, isPreviewing); label.text = AnimancerGUI.GetNarrowText(label.text); var mainProperty = GetMainProperty(property); if (mainProperty != null) { DoPropertyGUI(ref area, property, mainProperty, label); if (_Mode != Mode.AlwaysExpanded) { var hierarchyMode = EditorGUIUtility.hierarchyMode; EditorGUIUtility.hierarchyMode = true; property.isExpanded = EditorGUI.Foldout(area, property.isExpanded, GUIContent.none, true); EditorGUIUtility.hierarchyMode = hierarchyMode; } } else { area.height = EditorGUI.GetPropertyHeight(property, label, false); if (_Mode != Mode.AlwaysExpanded) { EditorGUI.PropertyField(area, property, label, false); } else { label = EditorGUI.BeginProperty(area, label, property); EditorGUI.LabelField(area, label); EditorGUI.EndProperty(); } } height = area.height; }
/************************************************************************************************************************/ /// <summary>Draws a GUI for the <see cref="Animator.runtimeAnimatorController"/> if there is one.</summary> private void DoNativeAnimatorControllerGUI(IAnimancerComponent target) { if (!EditorApplication.isPlaying && !target.IsPlayableInitialized) { return; } var animator = target.Animator; if (animator == null) { return; } var controller = (AnimatorController)animator.runtimeAnimatorController; if (controller == null) { return; } AnimancerGUI.BeginVerticalBox(GUI.skin.box); var label = AnimancerGUI.GetNarrowText("Native Animator Controller"); EditorGUI.BeginChangeCheck(); controller = (AnimatorController)EditorGUILayout.ObjectField(label, controller, typeof(AnimatorController), true); if (EditorGUI.EndChangeCheck()) { animator.runtimeAnimatorController = controller; } var layers = controller.layers; for (int i = 0; i < layers.Length; i++) { var layer = layers[i]; var runtimeState = animator.IsInTransition(i) ? animator.GetNextAnimatorStateInfo(i) : animator.GetCurrentAnimatorStateInfo(i); var states = layer.stateMachine.states; var editorState = GetState(states, runtimeState.shortNameHash); var area = AnimancerGUI.LayoutSingleLineRect(AnimancerGUI.SpacingMode.Before); var weight = i == 0 ? 1 : animator.GetLayerWeight(i); string stateName; if (editorState != null) { stateName = editorState.name; var isLooping = editorState.motion != null && editorState.motion.isLooping; AnimancerStateDrawer <ClipState> .DoTimeHighlightBarGUI( area, true, weight, runtimeState.normalizedTime *runtimeState.length, runtimeState.length, isLooping); } else { stateName = "State Not Found"; } AnimancerGUI.DoWeightLabel(ref area, weight); stateName = AnimancerGUI.GetNarrowText(stateName); EditorGUI.LabelField(area, layer.name, stateName); } AnimancerGUI.EndVerticalBox(GUI.skin.box); }