Esempio n. 1
0
            private bool ApplyAnimation(Skeleton skeleton, AnimatorClipInfo info, AnimatorStateInfo stateInfo,
                                        int layerIndex, float layerWeight, MixBlend layerBlendMode, bool useClipWeight1 = false)
            {
                float weight = info.weight * layerWeight;

                if (weight == 0)
                {
                    return(false);
                }

                var clip = GetAnimation(info.clip);

                if (clip == null)
                {
                    return(false);
                }

                var time = AnimationTime(stateInfo.normalizedTime, info.clip.length,
                                         info.clip.isLooping, stateInfo.speed < 0);

                weight = useClipWeight1 ? layerWeight : weight;
                clip.Apply(skeleton, 0, time, info.clip.isLooping, null,
                           weight, layerBlendMode, MixDirection.In);
                if (_OnClipApplied != null)
                {
                    OnClipAppliedCallback(clip, stateInfo, layerIndex, time, info.clip.isLooping, weight);
                }
                return(true);
            }
Esempio n. 2
0
 private MixMode GetMixMode(int layer, MixBlend layerBlendMode)
 {
     if (useCustomMixMode)
     {
         MixMode mode = layerMixModes[layer];
         // Note: at additive blending it makes no sense to use constant weight 1 at a fadeout anim add1 as
         // with override layers, so we use AlwaysMix instead to use the proper weights.
         // AlwaysMix leads to the expected result = lower_layer + lerp(add1, add2, transition_weight).
         if (layerBlendMode == MixBlend.Add && mode == MixMode.MixNext)
         {
             mode = MixMode.AlwaysMix;
             layerMixModes[layer] = mode;
         }
         return(mode);
     }
     else
     {
         return(layerBlendMode == MixBlend.Add ? MixMode.AlwaysMix : MixMode.MixNext);
     }
 }
Esempio n. 3
0
            public void Apply(Skeleton skeleton)
            {
                        #if UNITY_EDITOR
                if (!Application.isPlaying)
                {
                    GetLayerBlendModes();
                }
                        #endif

                if (layerMixModes.Length < animator.layerCount)
                {
                    int oldSize = layerMixModes.Length;
                    System.Array.Resize <MixMode>(ref layerMixModes, animator.layerCount);
                    for (int layer = oldSize; layer < animator.layerCount; ++layer)
                    {
                        bool isAdditiveLayer = false;
                        if (layer < layerBlendModes.Length)
                        {
                            isAdditiveLayer = layerBlendModes[layer] == MixBlend.Add;
                        }
                        layerMixModes[layer] = isAdditiveLayer ? MixMode.AlwaysMix : MixMode.MixNext;
                    }
                }

                InitClipInfosForLayers();
                for (int layer = 0, n = animator.layerCount; layer < n; layer++)
                {
                    GetStateUpdatesFromAnimator(layer);
                }

                // Clear Previous
                if (autoReset)
                {
                    var previousAnimations = this.previousAnimations;
                    for (int i = 0, n = previousAnimations.Count; i < n; i++)
                    {
                        previousAnimations[i].SetKeyedItemsToSetupPose(skeleton);
                    }

                    previousAnimations.Clear();
                    for (int layer = 0, n = animator.layerCount; layer < n; layer++)
                    {
                        float layerWeight = (layer == 0) ? 1 : animator.GetLayerWeight(layer);                         // Animator.GetLayerWeight always returns 0 on the first layer. Should be interpreted as 1.
                        if (layerWeight <= 0)
                        {
                            continue;
                        }

                        AnimatorStateInfo nextStateInfo = animator.GetNextAnimatorStateInfo(layer);

                        bool hasNext = nextStateInfo.fullPathHash != 0;

                        int clipInfoCount, nextClipInfoCount, interruptingClipInfoCount;
                        IList <AnimatorClipInfo> clipInfo, nextClipInfo, interruptingClipInfo;
                        bool isInterruptionActive, shallInterpolateWeightTo1;
                        GetAnimatorClipInfos(layer, out isInterruptionActive, out clipInfoCount, out nextClipInfoCount, out interruptingClipInfoCount,
                                             out clipInfo, out nextClipInfo, out interruptingClipInfo, out shallInterpolateWeightTo1);

                        for (int c = 0; c < clipInfoCount; c++)
                        {
                            var   info   = clipInfo[c];
                            float weight = info.weight * layerWeight; if (weight == 0)
                            {
                                continue;
                            }
                            var clip = GetAnimation(info.clip);
                            if (clip != null)
                            {
                                previousAnimations.Add(clip);
                            }
                        }

                        if (hasNext)
                        {
                            for (int c = 0; c < nextClipInfoCount; c++)
                            {
                                var   info   = nextClipInfo[c];
                                float weight = info.weight * layerWeight; if (weight == 0)
                                {
                                    continue;
                                }
                                var clip = GetAnimation(info.clip);
                                if (clip != null)
                                {
                                    previousAnimations.Add(clip);
                                }
                            }
                        }

                        if (isInterruptionActive)
                        {
                            for (int c = 0; c < interruptingClipInfoCount; c++)
                            {
                                var   info       = interruptingClipInfo[c];
                                float clipWeight = shallInterpolateWeightTo1 ? (info.weight + 1.0f) * 0.5f : info.weight;
                                float weight     = clipWeight * layerWeight; if (weight == 0)
                                {
                                    continue;
                                }
                                var clip = GetAnimation(info.clip);
                                if (clip != null)
                                {
                                    previousAnimations.Add(clip);
                                }
                            }
                        }
                    }
                }

                // Apply
                for (int layer = 0, n = animator.layerCount; layer < n; layer++)
                {
                    float layerWeight = (layer == 0) ? 1 : animator.GetLayerWeight(layer);                     // Animator.GetLayerWeight always returns 0 on the first layer. Should be interpreted as 1.

                    bool isInterruptionActive;
                    AnimatorStateInfo stateInfo;
                    AnimatorStateInfo nextStateInfo;
                    AnimatorStateInfo interruptingStateInfo;
                    float             interruptingClipTimeAddition;
                    GetAnimatorStateInfos(layer, out isInterruptionActive, out stateInfo, out nextStateInfo, out interruptingStateInfo, out interruptingClipTimeAddition);

                    bool hasNext = nextStateInfo.fullPathHash != 0;

                    int clipInfoCount, nextClipInfoCount, interruptingClipInfoCount;
                    IList <AnimatorClipInfo> clipInfo, nextClipInfo, interruptingClipInfo;
                    bool interpolateWeightTo1;
                    GetAnimatorClipInfos(layer, out isInterruptionActive, out clipInfoCount, out nextClipInfoCount, out interruptingClipInfoCount,
                                         out clipInfo, out nextClipInfo, out interruptingClipInfo, out interpolateWeightTo1);

                    MixBlend layerBlendMode = (layer < layerBlendModes.Length) ? layerBlendModes[layer] : MixBlend.Replace;
                    MixMode  mode           = GetMixMode(layer, layerBlendMode);
                    if (mode == MixMode.AlwaysMix)
                    {
                        // Always use Mix instead of Applying the first non-zero weighted clip.
                        for (int c = 0; c < clipInfoCount; c++)
                        {
                            ApplyAnimation(skeleton, clipInfo[c], stateInfo, layer, layerWeight, layerBlendMode);
                        }
                        if (hasNext)
                        {
                            for (int c = 0; c < nextClipInfoCount; c++)
                            {
                                ApplyAnimation(skeleton, nextClipInfo[c], nextStateInfo, layer, layerWeight, layerBlendMode);
                            }
                        }
                        if (isInterruptionActive)
                        {
                            for (int c = 0; c < interruptingClipInfoCount; c++)
                            {
                                ApplyInterruptionAnimation(skeleton, interpolateWeightTo1,
                                                           interruptingClipInfo[c], interruptingStateInfo,
                                                           layer, layerWeight, layerBlendMode, interruptingClipTimeAddition);
                            }
                        }
                    }
                    else                         // case MixNext || Hard
                                                 // Apply first non-zero weighted clip
                    {
                        int c = 0;
                        for (; c < clipInfoCount; c++)
                        {
                            if (!ApplyAnimation(skeleton, clipInfo[c], stateInfo, layer, layerWeight, layerBlendMode, useClipWeight1:true))
                            {
                                continue;
                            }
                            ++c; break;
                        }
                        // Mix the rest
                        for (; c < clipInfoCount; c++)
                        {
                            ApplyAnimation(skeleton, clipInfo[c], stateInfo, layer, layerWeight, layerBlendMode);
                        }

                        c = 0;
                        if (hasNext)
                        {
                            // Apply next clip directly instead of mixing (ie: no crossfade, ignores mecanim transition weights)
                            if (mode == MixMode.Hard)
                            {
                                for (; c < nextClipInfoCount; c++)
                                {
                                    if (!ApplyAnimation(skeleton, nextClipInfo[c], nextStateInfo, layer, layerWeight, layerBlendMode, useClipWeight1:true))
                                    {
                                        continue;
                                    }
                                    ++c; break;
                                }
                            }
                            // Mix the rest
                            for (; c < nextClipInfoCount; c++)
                            {
                                if (!ApplyAnimation(skeleton, nextClipInfo[c], nextStateInfo, layer, layerWeight, layerBlendMode))
                                {
                                    continue;
                                }
                            }
                        }

                        c = 0;
                        if (isInterruptionActive)
                        {
                            // Apply next clip directly instead of mixing (ie: no crossfade, ignores mecanim transition weights)
                            if (mode == MixMode.Hard)
                            {
                                for (; c < interruptingClipInfoCount; c++)
                                {
                                    if (ApplyInterruptionAnimation(skeleton, interpolateWeightTo1,
                                                                   interruptingClipInfo[c], interruptingStateInfo,
                                                                   layer, layerWeight, layerBlendMode, interruptingClipTimeAddition, useClipWeight1:true))
                                    {
                                        ++c; break;
                                    }
                                }
                            }
                            // Mix the rest
                            for (; c < interruptingClipInfoCount; c++)
                            {
                                ApplyInterruptionAnimation(skeleton, interpolateWeightTo1,
                                                           interruptingClipInfo[c], interruptingStateInfo,
                                                           layer, layerWeight, layerBlendMode, interruptingClipTimeAddition);
                            }
                        }
                    }
                }
            }
Esempio n. 4
0
            public void Apply(Skeleton skeleton)
            {
                if (layerMixModes.Length < animator.layerCount)
                {
                    System.Array.Resize <MixMode>(ref layerMixModes, animator.layerCount);
                    layerMixModes[animator.layerCount - 1] = MixMode.MixNext;
                }

                        #if UNITY_EDITOR
                if (!Application.isPlaying)
                {
                    GetLayerBlendModes();
                }
                        #endif
                InitClipInfosForLayers();
                for (int layer = 0, n = animator.layerCount; layer < n; layer++)
                {
                    GetStateUpdatesFromAnimator(layer);
                }

                //skeleton.Update(Time.deltaTime); // Doesn't actually do anything, currently. (Spine 3.6).

                // Clear Previous
                if (autoReset)
                {
                    var previousAnimations = this.previousAnimations;
                    for (int i = 0, n = previousAnimations.Count; i < n; i++)
                    {
                        previousAnimations[i].SetKeyedItemsToSetupPose(skeleton);
                    }

                    previousAnimations.Clear();
                    for (int layer = 0, n = animator.layerCount; layer < n; layer++)
                    {
                        float layerWeight = (layer == 0) ? 1 : animator.GetLayerWeight(layer);                         // Animator.GetLayerWeight always returns 0 on the first layer. Should be interpreted as 1.
                        if (layerWeight <= 0)
                        {
                            continue;
                        }

                        AnimatorStateInfo nextStateInfo = animator.GetNextAnimatorStateInfo(layer);

                        bool hasNext = nextStateInfo.fullPathHash != 0;

                        int clipInfoCount, nextClipInfoCount, interruptingClipInfoCount;
                        IList <AnimatorClipInfo> clipInfo, nextClipInfo, interruptingClipInfo;
                        bool isInterruptionActive, shallInterpolateWeightTo1;
                        GetAnimatorClipInfos(layer, out isInterruptionActive, out clipInfoCount, out nextClipInfoCount, out interruptingClipInfoCount,
                                             out clipInfo, out nextClipInfo, out interruptingClipInfo, out shallInterpolateWeightTo1);

                        for (int c = 0; c < clipInfoCount; c++)
                        {
                            var   info   = clipInfo[c];
                            float weight = info.weight * layerWeight; if (weight == 0)
                            {
                                continue;
                            }
                            previousAnimations.Add(GetAnimation(info.clip));
                        }

                        if (hasNext)
                        {
                            for (int c = 0; c < nextClipInfoCount; c++)
                            {
                                var   info   = nextClipInfo[c];
                                float weight = info.weight * layerWeight; if (weight == 0)
                                {
                                    continue;
                                }
                                previousAnimations.Add(GetAnimation(info.clip));
                            }
                        }

                        if (isInterruptionActive)
                        {
                            for (int c = 0; c < interruptingClipInfoCount; c++)
                            {
                                var   info       = interruptingClipInfo[c];
                                float clipWeight = shallInterpolateWeightTo1 ? (info.weight + 1.0f) * 0.5f : info.weight;
                                float weight     = clipWeight * layerWeight; if (weight == 0)
                                {
                                    continue;
                                }
                                previousAnimations.Add(GetAnimation(info.clip));
                            }
                        }
                    }
                }

                // Apply
                for (int layer = 0, n = animator.layerCount; layer < n; layer++)
                {
                    float layerWeight = (layer == 0) ? 1 : animator.GetLayerWeight(layer);                     // Animator.GetLayerWeight always returns 0 on the first layer. Should be interpreted as 1.

                    bool isInterruptionActive;
                    AnimatorStateInfo stateInfo;
                    AnimatorStateInfo nextStateInfo;
                    AnimatorStateInfo interruptingStateInfo;
                    float             interruptingClipTimeAddition;
                    GetAnimatorStateInfos(layer, out isInterruptionActive, out stateInfo, out nextStateInfo, out interruptingStateInfo, out interruptingClipTimeAddition);

                    bool hasNext = nextStateInfo.fullPathHash != 0;

                    int clipInfoCount, nextClipInfoCount, interruptingClipInfoCount;
                    IList <AnimatorClipInfo> clipInfo, nextClipInfo, interruptingClipInfo;
                    bool shallInterpolateWeightTo1;
                    GetAnimatorClipInfos(layer, out isInterruptionActive, out clipInfoCount, out nextClipInfoCount, out interruptingClipInfoCount,
                                         out clipInfo, out nextClipInfo, out interruptingClipInfo, out shallInterpolateWeightTo1);

                    MixMode  mode           = layerMixModes[layer];
                    MixBlend layerBlendMode = (layer < layerBlendModes.Length) ? layerBlendModes[layer] : MixBlend.Replace;
                    if (mode == MixMode.AlwaysMix)
                    {
                        // Always use Mix instead of Applying the first non-zero weighted clip.
                        for (int c = 0; c < clipInfoCount; c++)
                        {
                            var info = clipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0)
                            {
                                continue;
                            }
                            GetAnimation(info.clip).Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed < 0), stateInfo.loop, null, weight, layerBlendMode, MixDirection.In);
                        }
                        if (hasNext)
                        {
                            for (int c = 0; c < nextClipInfoCount; c++)
                            {
                                var info = nextClipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0)
                                {
                                    continue;
                                }
                                GetAnimation(info.clip).Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime, info.clip.length, nextStateInfo.speed < 0), nextStateInfo.loop, null, weight, layerBlendMode, MixDirection.In);
                            }
                        }
                        if (isInterruptionActive)
                        {
                            for (int c = 0; c < interruptingClipInfoCount; c++)
                            {
                                var   info       = interruptingClipInfo[c];
                                float clipWeight = shallInterpolateWeightTo1 ? (info.weight + 1.0f) * 0.5f : info.weight;
                                float weight     = clipWeight * layerWeight; if (weight == 0)
                                {
                                    continue;
                                }
                                GetAnimation(info.clip).Apply(skeleton, 0, AnimationTime(interruptingStateInfo.normalizedTime + interruptingClipTimeAddition, info.clip.length, interruptingStateInfo.speed < 0),
                                                              interruptingStateInfo.loop, null, weight, layerBlendMode, MixDirection.In);
                            }
                        }
                    }
                    else                         // case MixNext || Hard
                                                 // Apply first non-zero weighted clip
                    {
                        int c = 0;
                        for (; c < clipInfoCount; c++)
                        {
                            var info = clipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0)
                            {
                                continue;
                            }
                            GetAnimation(info.clip).Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed < 0), stateInfo.loop, null, 1f, layerBlendMode, MixDirection.In);
                            break;
                        }
                        // Mix the rest
                        for (; c < clipInfoCount; c++)
                        {
                            var info = clipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0)
                            {
                                continue;
                            }
                            GetAnimation(info.clip).Apply(skeleton, 0, AnimationTime(stateInfo.normalizedTime, info.clip.length, stateInfo.loop, stateInfo.speed < 0), stateInfo.loop, null, weight, layerBlendMode, MixDirection.In);
                        }

                        c = 0;
                        if (hasNext)
                        {
                            // Apply next clip directly instead of mixing (ie: no crossfade, ignores mecanim transition weights)
                            if (mode == MixMode.Hard)
                            {
                                for (; c < nextClipInfoCount; c++)
                                {
                                    var info = nextClipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0)
                                    {
                                        continue;
                                    }
                                    GetAnimation(info.clip).Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime, info.clip.length, nextStateInfo.speed < 0), nextStateInfo.loop, null, 1f, layerBlendMode, MixDirection.In);
                                    break;
                                }
                            }
                            // Mix the rest
                            for (; c < nextClipInfoCount; c++)
                            {
                                var info = nextClipInfo[c]; float weight = info.weight * layerWeight; if (weight == 0)
                                {
                                    continue;
                                }
                                GetAnimation(info.clip).Apply(skeleton, 0, AnimationTime(nextStateInfo.normalizedTime, info.clip.length, nextStateInfo.speed < 0), nextStateInfo.loop, null, weight, layerBlendMode, MixDirection.In);
                            }
                        }

                        c = 0;
                        if (isInterruptionActive)
                        {
                            // Apply next clip directly instead of mixing (ie: no crossfade, ignores mecanim transition weights)
                            if (mode == MixMode.Hard)
                            {
                                for (; c < interruptingClipInfoCount; c++)
                                {
                                    var   info       = interruptingClipInfo[c];
                                    float clipWeight = shallInterpolateWeightTo1 ? (info.weight + 1.0f) * 0.5f : info.weight;
                                    float weight     = clipWeight * layerWeight; if (weight == 0)
                                    {
                                        continue;
                                    }
                                    GetAnimation(info.clip).Apply(skeleton, 0, AnimationTime(interruptingStateInfo.normalizedTime + interruptingClipTimeAddition, info.clip.length, interruptingStateInfo.speed < 0), interruptingStateInfo.loop, null, 1f, layerBlendMode, MixDirection.In);
                                    break;
                                }
                            }
                            // Mix the rest
                            for (; c < interruptingClipInfoCount; c++)
                            {
                                var   info       = interruptingClipInfo[c];
                                float clipWeight = shallInterpolateWeightTo1 ? (info.weight + 1.0f) * 0.5f : info.weight;
                                float weight     = clipWeight * layerWeight; if (weight == 0)
                                {
                                    continue;
                                }
                                GetAnimation(info.clip).Apply(skeleton, 0, AnimationTime(interruptingStateInfo.normalizedTime + interruptingClipTimeAddition, info.clip.length, interruptingStateInfo.speed < 0), interruptingStateInfo.loop, null, weight, layerBlendMode, MixDirection.In);
                            }
                        }
                    }
                }
            }
Esempio n. 5
0
            private bool ApplyInterruptionAnimation(Skeleton skeleton,
                                                    bool interpolateWeightTo1, AnimatorClipInfo info, AnimatorStateInfo stateInfo,
                                                    int layerIndex, float layerWeight, MixBlend layerBlendMode, float interruptingClipTimeAddition,
                                                    bool useClipWeight1 = false)
            {
                float clipWeight = interpolateWeightTo1 ? (info.weight + 1.0f) * 0.5f : info.weight;
                float weight     = clipWeight * layerWeight;

                if (weight < WeightEpsilon)
                {
                    return(false);
                }

                var clip = GetAnimation(info.clip);

                if (clip == null)
                {
                    return(false);
                }

                var time = AnimationTime(stateInfo.normalizedTime + interruptingClipTimeAddition,
                                         info.clip.length, stateInfo.speed < 0);

                weight = useClipWeight1 ? layerWeight : weight;
                clip.Apply(skeleton, 0, time, info.clip.isLooping, null,
                           weight, layerBlendMode, MixDirection.In);
                if (_OnClipApplied != null)
                {
                    OnClipAppliedCallback(clip, stateInfo, layerIndex, time, info.clip.isLooping, weight);
                }
                return(true);
            }