Example #1
0
 private AnimationOperation CreatePushOperation(PlayingAnimation playingAnimation)
 {
     return(AnimationOperation.NewPush(playingAnimation.Evaluator, playingAnimation.CurrentTime));
 }
Example #2
0
        public override void Draw(RenderContext context)
        {
            var time = context.Time;

            //foreach (var entity in ComponentDatas.Values)
            Dispatcher.ForEach(ComponentDatas, () => animationOperationPool.Acquire(), (entity, animationOperations) =>
            {
                var associatedData = entity.Value;

                var animationUpdater   = associatedData.AnimationUpdater;
                var animationComponent = associatedData.AnimationComponent;

                if (animationComponent.BlendTreeBuilder != null)
                {
                    animationComponent.BlendTreeBuilder.BuildBlendTree(animationOperations);
                }
                else
                {
                    // Advance time for all playing animations with AutoPlay set to on
                    foreach (var playingAnimation in animationComponent.PlayingAnimations)
                    {
                        if (!playingAnimation.Enabled || playingAnimation.Clip == null)
                        {
                            continue;
                        }

                        switch (playingAnimation.RepeatMode)
                        {
                        case AnimationRepeatMode.PlayOnceHold:
                        case AnimationRepeatMode.PlayOnce:
                            playingAnimation.CurrentTime = TimeSpan.FromTicks(playingAnimation.CurrentTime.Ticks + (long)(time.Elapsed.Ticks * (double)playingAnimation.TimeFactor));
                            if (playingAnimation.CurrentTime > playingAnimation.Clip.Duration)
                            {
                                playingAnimation.CurrentTime = playingAnimation.Clip.Duration;
                            }
                            else if (playingAnimation.CurrentTime < TimeSpan.Zero)
                            {
                                playingAnimation.CurrentTime = TimeSpan.Zero;
                            }
                            break;

                        case AnimationRepeatMode.LoopInfinite:
                            playingAnimation.CurrentTime = playingAnimation.Clip.Duration == TimeSpan.Zero
                                    ? TimeSpan.Zero
                                    : TimeSpan.FromTicks((playingAnimation.CurrentTime.Ticks + playingAnimation.Clip.Duration.Ticks
                                                          + (long)(time.Elapsed.Ticks * (double)playingAnimation.TimeFactor)) % playingAnimation.Clip.Duration.Ticks);
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }
                    }

                    // Regenerate animation operations
                    float totalWeight = 0.0f;

                    for (int index = 0; index < animationComponent.PlayingAnimations.Count; index++)
                    {
                        var playingAnimation = animationComponent.PlayingAnimations[index];
                        var animationWeight  = playingAnimation.Weight;

                        // Skip animation with 0.0f weight
                        if (animationWeight == 0.0f || playingAnimation.Clip == null)
                        {
                            continue;
                        }

                        // Default behavior for linea blending (it will properly accumulate multiple blending with their cumulative weight)
                        totalWeight       += animationWeight;
                        float currentBlend = animationWeight / totalWeight;

                        if (playingAnimation.BlendOperation == AnimationBlendOperation.Add)
                        {
                            // Additive or substractive blending will use the weight as is (and reset total weight with it)
                            currentBlend = animationWeight;
                            totalWeight  = animationWeight;
                        }

                        // Create evaluator
                        var evaluator = playingAnimation.Evaluator;
                        if (evaluator == null)
                        {
                            evaluator = animationComponent.Blender.CreateEvaluator(playingAnimation.Clip);
                            playingAnimation.Evaluator = evaluator;
                        }

                        animationOperations.Add(CreatePushOperation(playingAnimation));

                        if (animationOperations.Count >= 2)
                        {
                            animationOperations.Add(AnimationOperation.NewBlend((CoreAnimationOperation)playingAnimation.BlendOperation, currentBlend));
                        }
                    }
                }

                if (animationOperations.Count > 0)
                {
                    // Animation blending
                    animationComponent.Blender.Compute(animationOperations, ref associatedData.AnimationClipResult);

                    // Update animation data if we have a model component
                    animationUpdater.Update(animationComponent.Entity, associatedData.AnimationClipResult);
                }

                if (animationComponent.BlendTreeBuilder == null)
                {
                    // Update weight animation
                    for (int index = 0; index < animationComponent.PlayingAnimations.Count; index++)
                    {
                        var playingAnimation = animationComponent.PlayingAnimations[index];
                        bool removeAnimation = false;
                        if (playingAnimation.CrossfadeRemainingTime > TimeSpan.Zero)
                        {
                            playingAnimation.Weight += (playingAnimation.WeightTarget - playingAnimation.Weight) *
                                                       ((float)time.Elapsed.Ticks / playingAnimation.CrossfadeRemainingTime.Ticks);
                            playingAnimation.CrossfadeRemainingTime -= time.Elapsed;
                            if (playingAnimation.CrossfadeRemainingTime <= TimeSpan.Zero)
                            {
                                playingAnimation.Weight = playingAnimation.WeightTarget;

                                // If weight target was 0, removes the animation
                                if (playingAnimation.Weight <= 0.0f)
                                {
                                    removeAnimation = true;
                                }
                            }
                        }

                        if (playingAnimation.RepeatMode == AnimationRepeatMode.PlayOnce)
                        {
                            if ((playingAnimation.TimeFactor > 0 && playingAnimation.CurrentTime == playingAnimation.Clip.Duration) ||
                                (playingAnimation.TimeFactor < 0 && playingAnimation.CurrentTime == TimeSpan.Zero))
                            {
                                removeAnimation = true;
                            }
                        }

                        if (removeAnimation)
                        {
                            animationComponent.PlayingAnimations.RemoveAt(index--); // Will also release its evaluator
                        }
                    }
                }

                animationOperations.Clear();
            }, animationOperations => animationOperationPool.Release(animationOperations));
        }
 private void ApplyAnimationOperation(ref AnimationOperation animationOperation)
 {
     switch (animationOperation.Type)
     {
         case AnimationOperationType.Blend:
             {
                 // Blend stack[last - 1] and stack[last] into stack[last - 1], then pop stack[last]
                 var op2 = animationStack.Pop();
                 var op1 = animationStack.Peek();
                 Blend(animationOperation.CoreBlendOperation, animationOperation.BlendFactor, op1, op2, op1);
                 FreeIntermediateResult(op2);
             }
             break;
         case AnimationOperationType.Push:
             {
                 var op = AllocateIntermediateResult();
                 animationOperation.Evaluator.Compute((CompressedTimeSpan)animationOperation.Time, op);
                 animationStack.Push(op);
             }
             break;
         case AnimationOperationType.Pop:
             {
                 var op = animationStack.Pop();
                 animationOperation.Evaluator.AddCurveValues((CompressedTimeSpan)animationOperation.Time, op);
             }
             break;
     }
 }