/************************************************************************************************************************/

        /// <summary>
        /// Gathers all animations linked to the target <see cref="IAnimancerComponent"/> by objects under the same
        /// <see cref="Transform.root"/> as it.
        /// </summary>
        public static void GatherAnimationClips <TSource>(IAnimancerComponent animancer, List <AnimationClip> clips,
                                                          TSource[] sources, Func <int, IAnimancerComponent> sourceIndexToAnimancer)
        {
            if (AlreadyGathering.Contains(animancer))
            {
                return;
            }

            AlreadyGathering.Add(animancer);

            int i = 0;

GatherClips:
            try
            {
                for (; i < sources.Length; i++)
                {
                    if (sourceIndexToAnimancer(i) == animancer)
                    {
                        GatherAnimationClips(sources[i], clips, typeof(TSource));
                    }
                }
            }
            catch (NullReferenceException)
            {
                // If something throws a null exception, just ignore it and go to the next object.
                i++;
                goto GatherClips;
            }

            AlreadyGathering.Remove(animancer);
        }
Ejemplo n.º 2
0
        private static bool ShouldEditModePlay(IAnimancerComponent animancer, AnimationClip clip)
        {
            return
                (ShouldEditModeSample(clip, animancer?.Animator) &&
                 (!(animancer is Object obj) || obj != null));
#endif
        }
Ejemplo n.º 3
0
        /************************************************************************************************************************/

        private void DoStatesGUI(IAnimancerComponent owner)
        {
            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 (Target.Index == 0 &&
                Target.Weight != 0 &&
                !Target.IsAdditive &&
                !Mathf.Approximately(Target.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 (AnimancerGUI.TryUseClickEventInLastRect())
                {
                    EditorUtility.OpenWithDefaultApp(Strings.DocsURLs.Fading);
                }
            }
        }
Ejemplo n.º 4
0
        /// <summary>Initialises a single property.</summary>
        public AnimatedProperty(IAnimancerComponent animancer, string propertyName)
            : this(animancer, 1, NativeArrayOptions.UninitializedMemory)
        {
            var animator = animancer.Animator;

            _Properties[0] = animator.BindStreamProperty(animator.transform, typeof(Animator), propertyName);
        }
Ejemplo n.º 5
0
        /************************************************************************************************************************/

        /// <summary>
        /// If <see cref="AnimationClip"/>s or <see cref="IAnimationClipSource"/>s are dropped inside the 'dropArea',
        /// this method creates a new state in the 'target' for each animation.
        /// </summary>
        public static void HandleDragAndDropAnimations(Rect dropArea, IAnimancerComponent target, int layerIndex)
        {
            AnimancerEditorUtilities.HandleDragAndDropAnimations(dropArea, (clip) =>
            {
                target.GetOrCreateState(clip, layerIndex);
            });
        }
        public static void EditModePlay(IAnimancerComponent animancer, AnimationClip clip, bool pauseImmediately = true)
        {
#if UNITY_EDITOR
            if (UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode ||
                animancer == null || clip == null)
            {
                return;
            }

            // Delay for a frame in case this was called at a bad time (such as during OnValidate).
            UnityEditor.EditorApplication.delayCall += () =>
            {
                if (UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode ||
                    animancer == null || clip == null)
                {
                    return;
                }

                animancer.Playable.Play(clip);

                if (pauseImmediately)
                {
                    animancer.Playable.Evaluate();
                    animancer.Playable.PauseGraph();
                }
            };
#endif
        }
Ejemplo n.º 7
0
 /// <summary>
 /// If <see cref="AnimationClip"/>s or <see cref="IAnimationClipSource"/>s are dropped inside the `dropArea`,
 /// this method creates a new state in the `target` for each animation.
 /// </summary>
 public static void HandleDragAndDropAnimations(Rect dropArea, IAnimancerComponent target, int layerIndex)
 {
     AnimancerGUI.HandleDragAndDropAnimations(dropArea, (clip) =>
     {
         target.Playable.Layers[layerIndex].GetOrCreateState(clip);
     });
 }
Ejemplo n.º 8
0
        /************************************************************************************************************************/

        /// <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--;
        }
Ejemplo n.º 9
0
        /************************************************************************************************************************/
        #region Initialisation
        /************************************************************************************************************************/

        /// <summary>
        /// Allocates room for a specified number of properties to be filled by
        /// <see cref="InitialiseProperty(int, Transform, Type, string)"/>.
        /// </summary>
        public AnimatedProperty(IAnimancerComponent animancer, int propertyCount,
                                NativeArrayOptions options = NativeArrayOptions.ClearMemory)
        {
            _Properties = new NativeArray <PropertyStreamHandle>(propertyCount, Allocator.Persistent, options);
            _Values     = new NativeArray <TValue>(propertyCount, Allocator.Persistent);
            CreateJob();

            var playable = animancer.Playable;

            CreatePlayable(playable);
            playable.Disposables.Add(this);
        }
Ejemplo n.º 10
0
        /************************************************************************************************************************/

        /// <summary> Draws the details of the target state in the GUI.</summary>
        protected override void DoDetailsGUI(IAnimancerComponent owner)
        {
            if (!IsExpanded)
            {
                return;
            }

            EditorGUI.indentLevel++;
            DoTimeSliderGUI();
            DoNodeDetailsGUI();
            DoOnEndGUI();
            EditorGUI.indentLevel--;
        }
Ejemplo n.º 11
0
        /// <summary>Draws the Inspector for the given `state`.</summary>
        private void DoStateGUI(AnimancerState state, IAnimancerComponent owner)
        {
            IAnimancerNodeDrawer Inspector;

            if (!StateInspectors.TryGetValue(state, out Inspector))
            {
                Inspector = state.GetDrawer();
                StateInspectors.Add(state, Inspector);
            }

            Inspector.DoGUI(owner);
            DoChildStatesGUI(state, owner);
        }
Ejemplo n.º 12
0
        /// <summary>Initialises a group of properties.</summary>
        public AnimatedProperty(IAnimancerComponent animancer, params string[] propertyNames)
            : this(animancer, propertyNames.Length, NativeArrayOptions.UninitializedMemory)
        {
            var count = propertyNames.Length;

            var animator  = animancer.Animator;
            var transform = animator.transform;

            for (int i = 0; i < count; i++)
            {
                InitialiseProperty(animator, i, transform, typeof(Animator), propertyNames[i]);
            }
        }
Ejemplo n.º 13
0
        /************************************************************************************************************************/

        /// <summary>
        /// Draws the details and controls for the target <see cref="AnimancerNodeDrawer{T}.Target"/> in the Inspector.
        /// </summary>
        public override void DoGUI(IAnimancerComponent owner)
        {
            if (!Target.IsValid)
            {
                return;
            }

            base.DoGUI(owner);

            var area = GUILayoutUtility.GetLastRect();

            HandleDragAndDropAnimations(area, owner, Target.Index);
        }
Ejemplo n.º 14
0
        /************************************************************************************************************************/

        private void DoLayerWeightWarningGUI(IAnimancerComponent target)
        {
            if (_LayerCount == 0)
            {
                EditorGUILayout.HelpBox(
                    "No layers have been created, which likely means no animations have been played yet.",
                    MessageType.Warning);
                return;
            }

            if (!target.gameObject.activeInHierarchy ||
                !target.enabled ||
                (target.Animator != null && target.Animator.runtimeAnimatorController != null))
            {
                return;
            }

            if (_LayerCount == 1)
            {
                var layer = LayerInfos[0].Target;
                if (layer.Weight == 0)
                {
                    EditorGUILayout.HelpBox(
                        layer + " is at 0 weight, which likely means no animations have been played yet.",
                        MessageType.Warning);
                }
                return;
            }

            for (int i = 0; i < _LayerCount; i++)
            {
                var layer = LayerInfos[i].Target;
                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 (AnimancerGUI.TryUseClickEventInLastRect())
            {
                EditorUtility.OpenWithDefaultApp(Strings.DocsURLs.Layers + "#blending");
            }
        }
Ejemplo n.º 15
0
            /// <summary>
            /// Validates the <see cref="Clip"/> type compared to the owner's <see cref="Animator"/> type.
            /// </summary>
            private void DoAnimationTypeWarningGUI(IAnimancerComponent owner)
            {
                // Validate the clip type compared to the owner.
                if (owner.Animator == null)
                {
                    _AnimationTypeWarning = null;
                    return;
                }

                if (_AnimationTypeWarningOwner != owner.Animator)
                {
                    _AnimationTypeWarning      = null;
                    _AnimationTypeWarningOwner = owner.Animator;
                }

                if (_AnimationTypeWarning == null)
                {
                    var ownerAnimationType = Editor.AnimancerEditorUtilities.GetAnimationType(_AnimationTypeWarningOwner);
                    var clipAnimationType  = Editor.AnimancerEditorUtilities.GetAnimationType(Target._Clip);

                    if (ownerAnimationType == clipAnimationType)
                    {
                        _AnimationTypeWarning = "";
                    }
                    else
                    {
                        var text = new StringBuilder()
                                   .Append("Possible animation type mismatch:\n - Animator type is ")
                                   .Append(ownerAnimationType)
                                   .Append("\n - AnimationClip type is ")
                                   .Append(clipAnimationType)
                                   .Append("\nThis means that the clip may not work correctly," +
                                           " however this check is not totally accurate. Click here for more info.");

                        _AnimationTypeWarning = text.ToString();
                    }
                }

                if (_AnimationTypeWarning != "")
                {
                    UnityEditor.EditorGUILayout.HelpBox(_AnimationTypeWarning, UnityEditor.MessageType.Warning);

                    if (Editor.AnimancerGUI.TryUseClickEventInLastRect())
                    {
                        UnityEditor.EditorUtility.OpenWithDefaultApp(
                            Strings.DocsURLs.AnimationTypes);
                    }
                }
            }
Ejemplo n.º 16
0
        /************************************************************************************************************************/

        /// <summary>Draws the details and controls for the target <see cref="Target"/> in the Inspector.</summary>
        public virtual void DoGUI(IAnimancerComponent owner)
        {
            if (!Target.IsValid)
            {
                return;
            }

            AnimancerGUI.BeginVerticalBox(RegionStyle);
            {
                DoHeaderGUI();
                DoDetailsGUI(owner);
            }
            AnimancerGUI.EndVerticalBox(RegionStyle);

            CheckContextMenu(GUILayoutUtility.GetLastRect());
        }
Ejemplo n.º 17
0
        /************************************************************************************************************************/

        /// <summary>Draws all child states of the `state`.</summary>
        private void DoChildStatesGUI(AnimancerState state, IAnimancerComponent owner)
        {
            EditorGUI.indentLevel++;

            foreach (var child in state)
            {
                if (child == null)
                {
                    continue;
                }

                DoStateGUI(child, owner);
            }

            EditorGUI.indentLevel--;
        }
Ejemplo n.º 18
0
        /************************************************************************************************************************/

        /// <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();
            }
        }
Ejemplo n.º 19
0
        /************************************************************************************************************************/

        /// <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--;
        }
Ejemplo n.º 20
0
        /************************************************************************************************************************/

        /// <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--;
        }
Ejemplo n.º 21
0
        /************************************************************************************************************************/

        /// <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);
        }
Ejemplo n.º 22
0
        /************************************************************************************************************************/

        /// <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());
        }
Ejemplo n.º 23
0
        /************************************************************************************************************************/

        /// <summary> Draws the details of the target state in the GUI.</summary>
        protected override void DoDetailsGUI(IAnimancerComponent owner)
        {
            if (IsExpanded)
            {
                EditorGUI.indentLevel++;
                GUILayout.BeginHorizontal();
                GUILayout.Space(FoldoutIndent);
                GUILayout.BeginVertical();

                DoLayerDetailsGUI();
                DoNodeDetailsGUI();

                GUILayout.EndVertical();
                GUILayout.EndHorizontal();
                EditorGUI.indentLevel--;
            }

            DoStatesGUI(owner);
        }
Ejemplo n.º 24
0
        /************************************************************************************************************************/

        /// <summary>Draws the GUI of the <see cref="IAnimancerComponent.Playable"/>.</summary>
        public void DoGUI(IAnimancerComponent target)
        {
            DoNativeAnimatorControllerGUI(target);

            if (!target.IsPlayableInitialized)
            {
                DoPlayableNotInitializedGUI(target);
                return;
            }

            EditorGUI.BeginChangeCheck();

            var playable = target.Playable;

            // 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(playable, LayerInfos, out _LayerCount);
            }

            DoRootGUI(playable);

            for (int i = 0; i < _LayerCount; i++)
            {
                LayerInfos[i].DoGUI();
            }

            DoLayerWeightWarningGUI(target);

            if (ShowInternalDetails)
            {
                DoInternalDetailsGUI(playable);
            }

            if (EditorGUI.EndChangeCheck() && !playable.IsGraphPlaying)
            {
                playable.Evaluate();
            }
        }
Ejemplo n.º 25
0
        /************************************************************************************************************************/

        private void DoPlayableNotInitializedGUI(IAnimancerComponent target)
        {
            if (!EditorApplication.isPlaying ||
                target.Animator == null ||
                EditorUtility.IsPersistent(target.Animator))
            {
                return;
            }

            EditorGUILayout.HelpBox("Playable is not initialized." +
                                    " It will be initialized automatically when something needs it, such as playing an animation.",
                                    MessageType.Info);

            if (AnimancerGUI.TryUseClickEventInLastRect(1))
            {
                var menu = new GenericMenu();

                menu.AddItem(new GUIContent("Initialize"), false, () => target.Playable.Evaluate());

                AnimancerEditorUtilities.AddDocumentationLink(menu, "Layer Documentation", Strings.DocsURLs.Layers);

                menu.ShowAsContext();
            }
        }
Ejemplo n.º 26
0
 /// <summary>Initializes a group of properties.</summary>
 public AnimatedBool(IAnimancerComponent animancer, params string[] propertyNames)
     : base(animancer, propertyNames)
 {
 }
Ejemplo n.º 27
0
 /// <summary>Initializes a single property.</summary>
 public AnimatedBool(IAnimancerComponent animancer, string propertyName)
     : base(animancer, propertyName)
 {
 }
Ejemplo n.º 28
0
        /************************************************************************************************************************/

        /// <summary>
        /// Allocates room for a specified number of properties to be filled by
        /// <see cref="InitializeProperty(int, Transform, Type, string)"/>.
        /// </summary>
        public AnimatedBool(IAnimancerComponent animancer, int propertyCount,
                            NativeArrayOptions options = NativeArrayOptions.ClearMemory)
            : base(animancer, propertyCount, options)
        {
        }
Ejemplo n.º 29
0
        /************************************************************************************************************************/

        /// <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);
        }
Ejemplo n.º 30
0
            /************************************************************************************************************************/

            /// <summary> Draws the details of the target state in the GUI.</summary>
            protected override void DoDetailsGUI(IAnimancerComponent owner)
            {
                base.DoDetailsGUI(owner);
                DoAnimationTypeWarningGUI(owner);
                DoEndEventWarningGUI();
            }