/************************************************************************************************************************/ /// <summary> 绘制目标的运行时详细信息. </summary> private void DoRuntimeDetailsGUI() { if (!UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode || targets.Length != 1) { return; } AnimancerGUI.BeginVerticalBox(GUI.skin.box); var target = (SoloAnimation)this.target; if (!target.IsInitialised) { GUILayout.Label("Not Initialised"); } else { UnityEditor.EditorGUI.BeginChangeCheck(); var isPlaying = UnityEditor.EditorGUILayout.Toggle("Is Playing", target.IsPlaying); if (UnityEditor.EditorGUI.EndChangeCheck()) { target.IsPlaying = isPlaying; } UnityEditor.EditorGUI.BeginChangeCheck(); var time = UnityEditor.EditorGUILayout.FloatField("Time", target.Time); if (UnityEditor.EditorGUI.EndChangeCheck()) { target.Time = time; } time = target.NormalizedTime.Wrap01(); if (time == 0 && target.Time != 0) { time = 1; } UnityEditor.EditorGUI.BeginChangeCheck(); time = UnityEditor.EditorGUILayout.Slider("Normalized Time", time, 0, 1); if (UnityEditor.EditorGUI.EndChangeCheck()) { target.NormalizedTime = time; } } AnimancerGUI.EndVerticalBox(GUI.skin.box); Repaint(); }
/************************************************************************************************************************/ /// <summary>Draws the details and controls for the target <see cref="Target"/> in the Inspector.</summary> public virtual void DoGUI() { if (!Target.IsValid) { return; } AnimancerGUI.BeginVerticalBox(RegionStyle); { DoHeaderGUI(); DoDetailsGUI(); } AnimancerGUI.EndVerticalBox(RegionStyle); CheckContextMenu(GUILayoutUtility.GetLastRect()); }
/************************************************************************************************************************/ /// <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(); } }
/************************************************************************************************************************/ 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); }
/// <summary> /// Draws the animator reference field followed by its fields that are relevant to Animancer. /// </summary> public void DoInspectorGUI() { _OnEndGUI = null; DoAnimatorGUI(); GatherAnimatorProperties(); if (_SerializedAnimator == null) { return; } _SerializedAnimator.Update(); AnimancerGUI.BeginVerticalBox(EditorStyles.helpBox); { if (!_IsAnimatorOnSameObject) { EditorGUILayout.HelpBox("It is recommended that you keep this component on the same GameObject" + " as its target Animator so that they get enabled and disabled at the same time.", MessageType.Info); } DoControllerGUI(); EditorGUILayout.PropertyField(_Avatar, AnimancerGUI.TempContent("Avatar", "The Avatar used by the Animator")); DoRootMotionGUI(); DoUpdateModeGUI(true); DoCullingModeGUI(); } AnimancerGUI.EndVerticalBox(EditorStyles.helpBox); _SerializedAnimator.ApplyModifiedProperties(); if (_OnEndGUI != null) { _OnEndGUI(); _OnEndGUI = null; } }
/************************************************************************************************************************/ /// <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); }