/************************************************************************************************************************/ /// <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> /// Draws a toggle inverted from the <see cref="Animator.keepAnimatorControllerStateOnDisable"/> field. /// </summary> private void DoStopOnDisableGUI() { #if UNITY_2018_1_OR_NEWER var area = AnimancerGUI.LayoutSingleLineRect(); var label = AnimancerGUI.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) { _KeepStateOnDisable.serializedObject.Update(); label = UnityEditor.EditorGUI.BeginProperty(area, label, _KeepStateOnDisable); _KeepStateOnDisable.boolValue = !UnityEditor.EditorGUI.Toggle(area, label, !_KeepStateOnDisable.boolValue); UnityEditor.EditorGUI.EndProperty(); _KeepStateOnDisable.serializedObject.ApplyModifiedProperties(); } else { var enabled = GUI.enabled; GUI.enabled = false; UnityEditor.EditorGUI.Toggle(area, label, false); GUI.enabled = enabled; } #endif }
/************************************************************************************************************************/ private static bool DoDropdownObjectField <T>(GUIContent label, bool showDropdown, ref T obj, AnimancerGUI.SpacingMode spacingMode = AnimancerGUI.SpacingMode.None) where T : Object { var area = AnimancerGUI.LayoutSingleLineRect(spacingMode); var labelWidth = EditorGUIUtility.labelWidth; #if UNITY_2019_3_OR_NEWER labelWidth += 2; area.xMin -= 1; #else area.xMin += 1; area.xMax -= 1; #endif var spacing = AnimancerGUI.StandardSpacing; var labelArea = AnimancerGUI.StealFromLeft(ref area, labelWidth - spacing, spacing); obj = (T)EditorGUI.ObjectField(area, obj, typeof(T), true); if (showDropdown) { return(EditorGUI.DropdownButton(labelArea, label, FocusType.Passive)); } else { GUI.Label(labelArea, label); return(false); } }
/************************************************************************************************************************/ /// <summary> /// 从 <see cref="Animator.keepAnimatorControllerStateOnDisable"/> 字段中反向绘制一个切换. /// </summary> private void DoStopOnDisableGUI() { #if UNITY_2018_1_OR_NEWER var area = AnimancerGUI.LayoutSingleLineRect(); var label = AnimancerGUI.TempContent("Stop On Disable", " 如果为真,禁用此对象将停止并回滚所有动画." + " 否则,它们将被暂停,并在重新启用时从当前状态继续."); if (_KeepStateOnDisable != null) { _KeepStateOnDisable.serializedObject.Update(); label = UnityEditor.EditorGUI.BeginProperty(area, label, _KeepStateOnDisable); _KeepStateOnDisable.boolValue = !UnityEditor.EditorGUI.Toggle(area, label, !_KeepStateOnDisable.boolValue); UnityEditor.EditorGUI.EndProperty(); _KeepStateOnDisable.serializedObject.ApplyModifiedProperties(); } else { var enabled = GUI.enabled; GUI.enabled = false; UnityEditor.EditorGUI.Toggle(area, label, false); GUI.enabled = enabled; } #endif }
/************************************************************************************************************************/ private bool DoHeadingLink(string heading, string description, string url, string displayURL = null) { if (DoLinkLabel(heading, description)) { Application.OpenURL(url); } bool clicked; if (displayURL == null) { displayURL = url; } var content = AnimancerGUI.TempContent(displayURL, "Click to copy this link to the clipboard", false); var area = AnimancerGUI.LayoutSingleLineRect(); if (GUI.Button(area, content, GUIStyles.URL)) { GUIUtility.systemCopyBuffer = displayURL; Debug.Log("Copied '" + displayURL + "' to the clipboard."); clicked = true; } else { clicked = false; } EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), MouseCursor.Text); return(clicked); }
/************************************************************************************************************************/ /// <summary> /// Draws the name and other details of the <see cref="Target"/> in the GUI. /// </summary> protected virtual void DoHeaderGUI() { var area = AnimancerGUI.LayoutSingleLineRect(AnimancerGUI.SpacingMode.Before); DoLabelGUI(area); DoFoldoutGUI(area); }
/************************************************************************************************************************/ /// <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; }
/************************************************************************************************************************/ /// <summary>Draws a slider for controlling the current <see cref="AnimancerState.Time"/>.</summary> private void DoTimeSliderGUI() { if (Target.Length <= 0) { return; } float length; var time = GetWrappedTime(out length); if (length == 0) { return; } var area = AnimancerGUI.LayoutSingleLineRect(AnimancerGUI.SpacingMode.Before); 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 = AnimancerGUI.BeginTightLabel(label); time = EditorGUI.Slider(area, label, time, 0, max); AnimancerGUI.EndTightLabel(); if (AnimancerGUI.TryUseClickEvent(area, 2)) { time = 0; } if (EditorGUI.EndChangeCheck()) { if (normalized) { Target.NormalizedTime = time; } else { Target.Time = time; } } }
/************************************************************************************************************************/ private void DoOnEndGUI() { if (Target.Events.OnEnd == null) { return; } var area = AnimancerGUI.LayoutSingleLineRect(AnimancerGUI.SpacingMode.Before); EditorGUI.LabelField(area, "OnEnd: " + Target.Events.OnEnd.Method); }
/************************************************************************************************************************/ /// <summary>Draws all `states` in the given list.</summary> private void DoStatesGUI(string label, List <AnimancerState> states, IAnimancerComponent owner) { var area = AnimancerGUI.LayoutSingleLineRect(); var width = AnimancerGUI.CalculateLabelWidth("Weight"); GUI.Label(AnimancerGUI.StealFromRight(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--; }
/************************************************************************************************************************/ private bool DoHeadingLink(string heading, string description, string url, string displayURL = null) { if (DoLinkLabel(heading, description)) { Application.OpenURL(url); } bool clicked; if (displayURL == null) { displayURL = url; } var area = AnimancerGUI.LayoutSingleLineRect(); var content = AnimancerGUI.TempContent(displayURL, "Click to copy this link to the clipboard", false); var style = ObjectPool.GetCachedResult(() => { var newStyle = new GUIStyle(GUI.skin.label); newStyle.fontSize = Mathf.CeilToInt(newStyle.fontSize * 0.8f); newStyle.normal.textColor = Color.Lerp(newStyle.normal.textColor, Color.grey, 0.75f); return(newStyle); }); if (GUI.Button(area, content, style)) { GUIUtility.systemCopyBuffer = displayURL; Debug.Log($"Copied '{displayURL}' to the clipboard.", this); clicked = true; } else { clicked = false; } EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), MouseCursor.Text); return(clicked); }
/************************************************************************************************************************/ private void DoAnimatorSelectorGUI() { var instanceAnimators = _Instance._Scene.InstanceAnimators; if (instanceAnimators == null || instanceAnimators.Length <= 1) { return; } var area = AnimancerGUI.LayoutSingleLineRect(AnimancerGUI.SpacingMode.After); var labelArea = AnimancerGUI.StealFromLeft(ref area, EditorGUIUtility.labelWidth, AnimancerGUI.StandardSpacing); GUI.Label(labelArea, nameof(Animator)); var selectedAnimator = _Instance._Scene.SelectedInstanceAnimator; using (ObjectPool.Disposable.AcquireContent(out var label, selectedAnimator != null ? selectedAnimator.name : "None")) { var clicked = EditorGUI.DropdownButton(area, label, FocusType.Passive); if (!clicked) { return; } var menu = new GenericMenu(); for (int i = 0; i < instanceAnimators.Length; i++) { var animator = instanceAnimators[i]; var index = i; menu.AddItem(new GUIContent(animator.name), animator == selectedAnimator, () => { _Instance._Scene.SetSelectedAnimator(index); NormalizedTime = 0; }); } menu.ShowAsContext(); } }
/************************************************************************************************************************/ /// <summary> /// Draws the Header GUI for this panel which is displayed regardless of whether it is expanded or not. /// </summary> public virtual void DoHeaderGUI() { var area = AnimancerGUI.LayoutSingleLineRect(AnimancerGUI.SpacingMode.BeforeAndAfter); var click = GUI.Button(area, Name, EditorStyles.boldLabel); area.xMin = area.xMax - area.height; GUI.DrawTexture(area, HelpIcon); if (click) { if (area.Contains(Event.current.mousePosition)) { Application.OpenURL(HelpURL); return; } else { IsExpanded = !IsExpanded; } } }
/************************************************************************************************************************/ private void DoRootGUI(AnimancerPlayable playable) { var labelWidth = EditorGUIUtility.labelWidth; AnimancerGUI.BeginVerticalBox(GUI.skin.box); using (ObjectPool.Disposable.AcquireContent(out var label, "Is Graph Playing")) { const string SpeedLabel = "Speed"; var isPlayingWidth = AnimancerGUI.CalculateLabelWidth(label.text); var speedWidth = AnimancerGUI.CalculateLabelWidth(SpeedLabel); var area = AnimancerGUI.LayoutSingleLineRect(); var isPlayingArea = area; var speedArea = area; isPlayingArea.width = isPlayingWidth + AnimancerGUI.ToggleWidth; speedArea.xMin = isPlayingArea.xMax; EditorGUIUtility.labelWidth = isPlayingWidth; playable.IsGraphPlaying = EditorGUI.Toggle(isPlayingArea, label, playable.IsGraphPlaying); EditorGUIUtility.labelWidth = speedWidth; EditorGUI.BeginChangeCheck(); var speed = EditorGUI.FloatField(speedArea, SpeedLabel, playable.Speed); if (EditorGUI.EndChangeCheck()) { playable.Speed = speed; } if (AnimancerGUI.TryUseClickEvent(speedArea, 2)) { playable.Speed = playable.Speed != 1 ? 1 : 0; } } AnimancerGUI.EndVerticalBox(GUI.skin.box); EditorGUIUtility.labelWidth = labelWidth; CheckContextMenu(GUILayoutUtility.GetLastRect(), playable); }
private static void DoHierarchyGUI(Transform root) { var area = AnimancerGUI.LayoutSingleLineRect(); if (_HierarchyButtonStyle == null) _HierarchyButtonStyle = new GUIStyle(EditorStyles.miniButton) { alignment = TextAnchor.MiddleLeft, }; if (GUI.Button(EditorGUI.IndentedRect(area), root.name, _HierarchyButtonStyle)) { Selection.activeTransform = root; GUIUtility.ExitGUI(); } var childCount = root.childCount; if (childCount == 0) return; var expandedHierarchy = _Instance._Scene.ExpandedHierarchy; var index = expandedHierarchy != null ? expandedHierarchy.IndexOf(root) : -1; var isExpanded = EditorGUI.Foldout(area, index >= 0, GUIContent.none); if (isExpanded) { if (index < 0) expandedHierarchy.Add(root); EditorGUI.indentLevel++; for (int i = 0; i < childCount; i++) DoHierarchyGUI(root.GetChild(i)); EditorGUI.indentLevel--; } else if (index >= 0) { expandedHierarchy.RemoveAt(index); } }
/************************************************************************************************************************/ private void DoShowOnStartup() { var area = AnimancerGUI.LayoutSingleLineRect(); area.xMin += AnimancerGUI.LineHeight * 0.2f; using (ObjectPool.Disposable.AcquireContent(out var content, _DontShowOnStartupProperty, false)) { var label = EditorGUI.BeginProperty(area, content, _DontShowOnStartupProperty); EditorGUI.BeginChangeCheck(); var value = _DontShowOnStartupProperty.boolValue; value = GUI.Toggle(area, value, label); if (EditorGUI.EndChangeCheck()) { _DontShowOnStartupProperty.boolValue = value; if (value) { PlayerPrefs.SetInt(_Target.ReleaseNumberPrefKey, _Target.ReleaseNumber); } } EditorGUI.EndProperty(); } }
/************************************************************************************************************************/ private void DoDefaultAnimationField(SerializedProperty playAutomatically) { var area = AnimancerGUI.LayoutSingleLineRect(); var playAutomaticallyWidth = EditorGUIUtility.labelWidth + AnimancerGUI.ToggleWidth; var playAutomaticallyArea = AnimancerGUI.StealFromLeft(ref area, playAutomaticallyWidth); var label = AnimancerGUI.TempContent(playAutomatically); EditorGUI.PropertyField(playAutomaticallyArea, playAutomatically, label); SerializedProperty firstElement; AnimationClip clip; var animations = serializedObject.FindProperty("_Animations"); if (animations.arraySize > 0) { firstElement = animations.GetArrayElementAtIndex(0); clip = (AnimationClip)firstElement.objectReferenceValue; EditorGUI.BeginProperty(area, null, firstElement); } else { firstElement = null; clip = null; EditorGUI.BeginProperty(area, null, animations); } EditorGUI.BeginChangeCheck(); var indentLevel = EditorGUI.indentLevel; EditorGUI.indentLevel = 0; clip = (AnimationClip)EditorGUI.ObjectField(area, GUIContent.none, clip, typeof(AnimationClip), true); EditorGUI.indentLevel = indentLevel; if (EditorGUI.EndChangeCheck()) { if (clip != null) { if (firstElement == null) { animations.arraySize = 1; firstElement = animations.GetArrayElementAtIndex(0); } firstElement.objectReferenceValue = clip; } else { if (firstElement == null || animations.arraySize == 1) { animations.arraySize = 0; } else { firstElement.objectReferenceValue = clip; } } } EditorGUI.EndProperty(); }
/************************************************************************************************************************/ /// <summary> /// Draws controls for <see cref="AnimancerState.IsPlaying"/>, <see cref="AnimancerNode.Speed"/>, and /// <see cref="AnimancerNode.Weight"/>. /// </summary> protected void DoNodeDetailsGUI() { var area = AnimancerGUI.LayoutSingleLineRect(AnimancerGUI.SpacingMode.Before); area.xMin += EditorGUI.indentLevel * AnimancerGUI.IndentSize; var xMin = area.xMin; var xMax = area.xMax; var labelWidth = EditorGUIUtility.labelWidth; var indentLevel = EditorGUI.indentLevel; EditorGUI.indentLevel = 0; // Is Playing. var state = Target as AnimancerState; if (state != null) { var label = AnimancerGUI.BeginTightLabel("Is Playing"); area.width = EditorGUIUtility.labelWidth + 16; state.IsPlaying = EditorGUI.Toggle(area, label, state.IsPlaying); AnimancerGUI.EndTightLabel(); area.x += area.width; area.xMax = xMax; } AnimancerGUI.SplitHorizontally(area, "Speed", "Weight", out var speedWidth, out var weightWidth, out var speedRect, out var weightRect); // Speed. EditorGUIUtility.labelWidth = speedWidth; EditorGUI.BeginChangeCheck(); var speed = EditorGUI.FloatField(speedRect, "Speed", Target.Speed); if (EditorGUI.EndChangeCheck()) { Target.Speed = speed; } if (AnimancerGUI.TryUseClickEvent(speedRect, 2)) { Target.Speed = Target.Speed != 1 ? 1 : 0; } // Weight. EditorGUIUtility.labelWidth = weightWidth; EditorGUI.BeginChangeCheck(); var weight = EditorGUI.FloatField(weightRect, "Weight", Target.Weight); if (EditorGUI.EndChangeCheck()) { SetWeight(Mathf.Max(weight, 0)); } if (AnimancerGUI.TryUseClickEvent(weightRect, 2)) { SetWeight(Target.Weight != 1 ? 1 : 0); } // Not really sure why this is necessary. // It allows the dummy ID added when the Real Speed is hidden to work properly. GUIUtility.GetControlID(FocusType.Passive); // Real Speed (Mixer Synchronization changes the internal Playable Speed without setting the State Speed). speed = (float)Target._Playable.GetSpeed(); if (Target.Speed != speed) { using (new EditorGUI.DisabledScope(true)) { area = AnimancerGUI.LayoutSingleLineRect(AnimancerGUI.SpacingMode.Before); area.xMin = xMin; var label = AnimancerGUI.BeginTightLabel("Real Speed"); EditorGUIUtility.labelWidth = AnimancerGUI.CalculateLabelWidth(label); EditorGUI.FloatField(area, label, speed); AnimancerGUI.EndTightLabel(); } } else// Add a dummy ID so that subsequent IDs don't change when the Real Speed appears or disappears. { GUIUtility.GetControlID(FocusType.Passive); } EditorGUI.indentLevel = indentLevel; EditorGUIUtility.labelWidth = labelWidth; DoFadeDetailsGUI(); }
/************************************************************************************************************************/ /// <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); }
/************************************************************************************************************************/ /// <inheritdoc/> protected override void DoDetailsGUI() { base.DoDetailsGUI(); if (!IsExpanded) { return; } var count = ParameterCount; if (count <= 0) { return; } var labelWidth = EditorGUIUtility.labelWidth; EditorGUIUtility.labelWidth -= AnimancerGUI.IndentSize; 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(); var area = AnimancerGUI.LayoutSingleLineRect(AnimancerGUI.SpacingMode.Before); 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, "Unsupported Type: " + type); break; } if (EditorGUI.EndChangeCheck()) { SetParameterValue(i, value); } } EditorGUIUtility.labelWidth = labelWidth; }
/************************************************************************************************************************/ /// <inheritdoc/> public override void DoBodyGUI() { var area = AnimancerGUI.LayoutSingleLineRect(); area.xMin += 4; using (ObjectPool.Disposable.AcquireContent(out var label, "Offset Rects", null, false)) area = EditorGUI.PrefixLabel(area, label); BeginChangeCheck(); var selected = (OffsetRectMode)GUI.Toolbar(area, (int)_RectMode, OffsetRectModes); EndChangeCheck(ref _RectMode, selected); using (var property = _SerializedProperty.Copy()) { property.serializedObject.Update(); var depth = property.depth; while (property.Next(false) && property.depth >= depth) { EditorGUILayout.PropertyField(property, true); } property.serializedObject.ApplyModifiedProperties(); } GUI.enabled = false; for (int i = 0; i < Sprites.Count; i++) { if (_ShowDetails) { GUILayout.BeginVertical(GUI.skin.box); } var sprite = Sprites[i] = (Sprite)EditorGUILayout.ObjectField(Sprites[i], typeof(Sprite), false); if (_ShowDetails) { if (_RectMode != OffsetRectMode.None) { EditorGUILayout.RectField("Rect", sprite.rect); } if (_SetPivot) { EditorGUILayout.Vector2Field("Pivot", sprite.pivot); } if (_SetBorder) { EditorGUILayout.Vector4Field("Border", sprite.border); } GUILayout.EndVertical(); } } GUILayout.BeginHorizontal(); { GUILayout.FlexibleSpace(); GUI.enabled = Sprites.Count > 0 && IsValidModification(); if (GUILayout.Button("Apply")) { AnimancerGUI.Deselect(); AskAndApply(); } } GUILayout.EndHorizontal(); }
/************************************************************************************************************************/ /// <summary> /// Draws controls for <see cref="AnimancerState.IsPlaying"/>, <see cref="AnimancerNode.Speed"/>, and /// <see cref="AnimancerNode.Weight"/>. /// </summary> protected void DoNodeDetailsGUI() { var labelWidth = EditorGUIUtility.labelWidth; var area = AnimancerGUI.LayoutSingleLineRect(AnimancerGUI.SpacingMode.Before); area.xMin += EditorGUI.indentLevel * AnimancerGUI.IndentSize; var indentLevel = EditorGUI.indentLevel; EditorGUI.indentLevel = 0; var right = area.xMax; // Is Playing. var state = Target as AnimancerState; if (state != null) { var label = AnimancerGUI.BeginTightLabel("Is Playing"); area.width = EditorGUIUtility.labelWidth + 16; state.IsPlaying = EditorGUI.Toggle(area, label, state.IsPlaying); AnimancerGUI.EndTightLabel(); area.x += area.width; area.xMax = right; } AnimancerGUI.SplitHorizontally(area, "Speed", "Weight", out var speedWidth, out var weightWidth, out var speedRect, out var weightRect); // Speed. EditorGUIUtility.labelWidth = speedWidth; EditorGUI.BeginChangeCheck(); var speed = EditorGUI.FloatField(speedRect, "Speed", Target.Speed); if (EditorGUI.EndChangeCheck()) { Target.Speed = speed; } if (AnimancerGUI.TryUseClickEvent(speedRect, 2)) { Target.Speed = Target.Speed != 1 ? 1 : 0; } // Weight. EditorGUIUtility.labelWidth = weightWidth; EditorGUI.BeginChangeCheck(); var weight = EditorGUI.FloatField(weightRect, "Weight", Target.Weight); if (EditorGUI.EndChangeCheck()) { Target.Weight = Mathf.Max(weight, 0); } if (AnimancerGUI.TryUseClickEvent(weightRect, 2)) { Target.Weight = Target.Weight != 1 ? 1 : 0; } EditorGUI.indentLevel = indentLevel; EditorGUIUtility.labelWidth = labelWidth; DoFadeDetailsGUI(); }