public override void Start()
        {
            base.Start();

            if (AnimationComponent == null)
                throw new InvalidOperationException("The animation component is not set");

            if (AnimationIdle == null)
                throw new InvalidOperationException("Idle animation is not set");

            if (AnimationWalk == null)
                throw new InvalidOperationException("Walking animation is not set");

            if (AnimationRun == null)
                throw new InvalidOperationException("Running animation is not set");

            if (AnimationPunch == null)
                throw new InvalidOperationException("Punching animation is not set");

            // By setting a custom blend tree builder we can override the default behavior of the animation system
            //  Instead, BuildBlendTree(FastList<AnimationOperation> blendStack) will be called each frame
            AnimationComponent.BlendTreeBuilder = this;

            animEvaluatorIdle = AnimationComponent.Blender.CreateEvaluator(AnimationIdle);
            animEvaluatorWalk = AnimationComponent.Blender.CreateEvaluator(AnimationWalk);
            animEvaluatorRun = AnimationComponent.Blender.CreateEvaluator(AnimationRun);
            animEvaluatorPunch = AnimationComponent.Blender.CreateEvaluator(AnimationPunch);

            // Initial walk lerp
            walkLerpFactor = 0;
            animEvaluatorWalkLerp1 = animEvaluatorIdle;
            animEvaluatorWalkLerp2 = animEvaluatorWalk;
            animationClipWalkLerp1 = AnimationIdle;
            animationClipWalkLerp2 = AnimationWalk;
        }
        public override void Start()
        {
            base.Start();

            if (AnimationComponent == null)
                throw new InvalidOperationException("The animation component is not set");

            if (AnimationIdle == null)
                throw new InvalidOperationException("Idle animation is not set");

            if (AnimationWalk == null)
                throw new InvalidOperationException("Walking animation is not set");

            if (AnimationShoot == null)
                throw new InvalidOperationException("Shooting animation is not set");

            if (AnimationReload == null)
                throw new InvalidOperationException("Reloading animation is not set");

            // By setting a custom blend tree builder we can override the default behavior of the animation system
            //  Instead, BuildBlendTree(FastList<AnimationOperation> blendStack) will be called each frame
            AnimationComponent.BlendTreeBuilder = this;

            animEvaluatorIdle   = AnimationComponent.Blender.CreateEvaluator(AnimationIdle);
            animEvaluatorWalk   = AnimationComponent.Blender.CreateEvaluator(AnimationWalk);
            animEvaluatorShoot  = AnimationComponent.Blender.CreateEvaluator(AnimationShoot);
            animEvaluatorReload = AnimationComponent.Blender.CreateEvaluator(AnimationReload);

            currentEvaluator    = animEvaluatorIdle;
            currentClip         = AnimationIdle;
        }
        private void UpdateWalking()
        {
            if (runSpeed < WalkThreshold)
            {
                walkLerpFactor = runSpeed / WalkThreshold;
                walkLerpFactor = (float)Math.Sqrt(walkLerpFactor);  // Idle-Walk blend looks really werid, so skew the factor towards walking
                animEvaluatorWalkLerp1 = animEvaluatorIdle;
                animEvaluatorWalkLerp2 = animEvaluatorWalk;
                animationClipWalkLerp1 = AnimationIdle;
                animationClipWalkLerp2 = AnimationWalk;
            }
            else
            {
                walkLerpFactor = (runSpeed - WalkThreshold) / (1.0f - WalkThreshold);
                animEvaluatorWalkLerp1 = animEvaluatorWalk;
                animEvaluatorWalkLerp2 = animEvaluatorRun;
                animationClipWalkLerp1 = AnimationWalk;
                animationClipWalkLerp2 = AnimationRun;
            }

            // Use DrawTime rather than UpdateTime
            var time = Game.DrawTime;
            // This update function will account for animation with different durations, keeping a current time relative to the blended maximum duration
            long blendedMaxDuration = 0;
            blendedMaxDuration =
                (long)MathUtil.Lerp(animationClipWalkLerp1.Duration.Ticks, animationClipWalkLerp2.Duration.Ticks, walkLerpFactor);

            var currentTicks = TimeSpan.FromTicks((long)(currentTime * blendedMaxDuration));

            currentTicks = blendedMaxDuration == 0
                ? TimeSpan.Zero
                : TimeSpan.FromTicks((currentTicks.Ticks + (long)(time.Elapsed.Ticks * TimeFactor)) %
                                     blendedMaxDuration);

            currentTime = ((double)currentTicks.Ticks / (double)blendedMaxDuration);
        }
 /// <summary>
 /// Creates a new animation pop operation.
 /// </summary>
 /// <param name="evaluator">The evaluator.</param>
 /// <param name="time">The time.</param>
 /// <returns></returns>
 public static AnimationOperation NewPop(AnimationClipEvaluator evaluator, TimeSpan time)
 {
     return new AnimationOperation { Type = AnimationOperationType.Pop, Evaluator = evaluator, Time = time };
 }
 /// <summary>
 /// Creates a new animation push operation.
 /// </summary>
 /// <param name="evaluator">The evaluator.</param>
 /// <returns></returns>
 public static AnimationOperation NewPush(AnimationClipEvaluator evaluator)
 {
     return new AnimationOperation { Type = AnimationOperationType.Push, Evaluator = evaluator, Time = TimeSpan.Zero };
 }
Exemple #6
0
        public AnimationClipEvaluator CreateEvaluator(AnimationClip clip)
        {
            // Check if this clip has already been used
            if (clips.Add(clip))
            {
                // If new clip, let's scan its channel to add new ones.
                foreach (var curve in clip.Channels)
                {
                    Channel channel;
                    if (channelsByName.TryGetValue(curve.Key, out channel))
                    {
                        // TODO: Check if channel matches
                    }
                    else
                    {
                        // New channel, add it to every evaluator

                        // Find blend type
                        BlendType blendType;
                        var       elementType = curve.Value.ElementType;

                        if (elementType == typeof(Quaternion))
                        {
                            blendType = BlendType.Quaternion;
                        }
                        else if (elementType == typeof(float))
                        {
                            blendType = BlendType.Float1;
                        }
                        else if (elementType == typeof(Vector2))
                        {
                            blendType = BlendType.Float2;
                        }
                        else if (elementType == typeof(Vector3))
                        {
                            blendType = BlendType.Float3;
                        }
                        else if (elementType == typeof(Vector4))
                        {
                            blendType = BlendType.Float4;
                        }
                        else
                        {
                            blendType = BlittableHelper.IsBlittable(elementType) ? BlendType.Blit : BlendType.Object;
                        }

                        // Create channel structure
                        channel.BlendType    = blendType;
                        channel.Offset       = blendType == BlendType.Object ? objectsSize : structureSize;
                        channel.PropertyName = curve.Key;
                        channel.Size         = curve.Value.ElementSize;

                        // Add channel
                        channelsByName.Add(channel.PropertyName, channel);
                        channels.Add(channel);

                        if (blendType == BlendType.Object)
                        {
                            objectsSize++;
                        }
                        else
                        {
                            // Update new structure size
                            // We also reserve space for a float that will specify channel existence and factor in case of subtree blending
                            structureSize += sizeof(float) + channel.Size;
                        }

                        // Add new channel update info to every evaluator
                        // TODO: Maybe it's better lazily done? (avoid need to store list of all evaluators)
                        foreach (var currentEvaluator in evaluators)
                        {
                            currentEvaluator.AddChannel(ref channel);
                        }
                    }
                }
            }

            // Update results to fit the new data size
            lock (availableResultsPool)
            {
                foreach (var result in availableResultsPool)
                {
                    if (result.DataSize < structureSize)
                    {
                        result.DataSize = structureSize;
                        result.Data     = new byte[structureSize];
                    }
                }
            }

            // Create evaluator and store it in list of instantiated evaluators
            AnimationClipEvaluator evaluator;

            lock (evaluatorPool)
            {
                if (evaluatorPool.Count > 0)
                {
                    evaluator = evaluatorPool.Pop();
                }
                else
                {
                    evaluator = new AnimationClipEvaluator();
                }
            }

            evaluator.Initialize(clip, channels);
            evaluators.Add(evaluator);

            return(evaluator);
        }
        public AnimationClipEvaluator CreateEvaluator(AnimationClip clip)
        {
            // Check if this clip has already been used
            if (clips.Add(clip))
            {
                // If new clip, let's scan its channel to add new ones.
                foreach (var curve in clip.Channels)
                {
                    Channel channel;
                    if (channelsByName.TryGetValue(curve.Key, out channel))
                    {
                        // TODO: Check if channel matches
                    }
                    else
                    {
                        // New channel, add it to every evaluator

                        // Find blend type
                        BlendType blendType;
                        var elementType = curve.Value.ElementType;

                        if (elementType == typeof(Quaternion))
                        {
                            blendType = BlendType.Quaternion;
                        }
                        else if (elementType == typeof(float))
                        {
                            blendType = BlendType.Float1;
                        }
                        else if (elementType == typeof(Vector2))
                        {
                            blendType = BlendType.Float2;
                        }
                        else if (elementType == typeof(Vector3))
                        {
                            blendType = BlendType.Float3;
                        }
                        else if (elementType == typeof(Vector4))
                        {
                            blendType = BlendType.Float4;
                        }
                        else
                        {
                            blendType = BlittableHelper.IsBlittable(elementType) ? BlendType.Blit : BlendType.Object;
                        }

                        // Create channel structure
                        channel.BlendType = blendType;
                        channel.Offset = blendType == BlendType.Object ? objectsSize : structureSize;
                        channel.PropertyName = curve.Key;
                        channel.Size = curve.Value.ElementSize;

                        // Add channel
                        channelsByName.Add(channel.PropertyName, channel);
                        channels.Add(channel);

                        if (blendType == BlendType.Object)
                        {
                            objectsSize++;
                        }
                        else
                        {
                            // Update new structure size
                            // We also reserve space for a float that will specify channel existence and factor in case of subtree blending
                            structureSize += sizeof(float) + channel.Size;
                        }

                        // Add new channel update info to every evaluator
                        // TODO: Maybe it's better lazily done? (avoid need to store list of all evaluators)
                        foreach (var currentEvaluator in evaluators)
                        {
                            currentEvaluator.AddChannel(ref channel);
                        }
                    }
                }
            }

            // Update results to fit the new data size
            lock (availableResultsPool)
            {
                foreach (var result in availableResultsPool)
                {
                    if (result.DataSize < structureSize)
                    {
                        result.DataSize = structureSize;
                        result.Data = new byte[structureSize];
                    }
                }
            }

            // Create evaluator and store it in list of instantiated evaluators
            AnimationClipEvaluator evaluator;
            lock (evaluatorPool)
            {
                if (evaluatorPool.Count > 0)
                {
                    evaluator = evaluatorPool.Pop();
                }
                else
                {
                    evaluator = new AnimationClipEvaluator();
                }
            }
            
            evaluator.Initialize(clip, channels);
            evaluators.Add(evaluator);

            return evaluator;
        }
 public void ReleaseEvaluator(AnimationClipEvaluator evaluator)
 {
     lock (evaluatorPool)
     {
         evaluators.Remove(evaluator);
         evaluator.Cleanup();
         evaluatorPool.Push(evaluator);
     }
 }
Exemple #9
0
 /// <summary>
 /// Creates a new animation pop operation.
 /// </summary>
 /// <param name="evaluator">The evaluator.</param>
 /// <param name="time">The time.</param>
 /// <returns></returns>
 public static AnimationOperation NewPop(AnimationClipEvaluator evaluator, TimeSpan time)
 {
     return(new AnimationOperation {
         Type = AnimationOperationType.Pop, Evaluator = evaluator, Time = time
     });
 }
Exemple #10
0
 /// <summary>
 /// Creates a new animation push operation.
 /// </summary>
 /// <param name="evaluator">The evaluator.</param>
 /// <returns></returns>
 public static AnimationOperation NewPush(AnimationClipEvaluator evaluator)
 {
     return(new AnimationOperation {
         Type = AnimationOperationType.Push, Evaluator = evaluator, Time = TimeSpan.Zero
     });
 }
        private void SwitchToDefaultState()
        {
            currentTime = (state == defaultState) ? currentTime : 0;
            state = defaultState;

            if (state == AnimationState.Idle)
            {
                currentClip = AnimationIdle;
                currentEvaluator = animEvaluatorIdle;
            }
            else
            {
                currentClip = AnimationWalk;
                currentEvaluator = animEvaluatorWalk;
            }
        }
        public override void Update()
        {
            runSpeedEvent.TryReceive(out runSpeed);
            defaultState = (runSpeed > 0.15f) ? AnimationState.Walking : AnimationState.Idle;

            WeaponFiredResult weaponResult;
            var didFire = weaponFiredEvent.TryReceive(out weaponResult);

            bool isReloading;
            var didReload = isReloadingEvent.TryReceive(out isReloading);
            isReloading |= didReload;

            // Update current animation
            var currentTicks = TimeSpan.FromTicks((long)(currentTime * currentClip.Duration.Ticks));
            var updatedTicks = currentTicks.Ticks + (long)(Game.DrawTime.Elapsed.Ticks * TimeFactor);

            var currentClipFinished = (updatedTicks >= currentClip.Duration.Ticks);

            currentTicks = TimeSpan.FromTicks(updatedTicks % currentClip.Duration.Ticks);
            currentTime = ((double)currentTicks.Ticks / (double)currentClip.Duration.Ticks);

            // State change if necessary
            if (isReloading)
            {
                if (state != AnimationState.Reloading)
                {
                    currentTime = 0;
                    state = AnimationState.Reloading;
                    currentClip = AnimationReload;
                    currentEvaluator = animEvaluatorReload;
                }
            }
            else
            if (didFire)
            {
                if (state != AnimationState.Shooting)
                {
                    currentTime = 0;
                    state = AnimationState.Shooting;
                    currentClip = AnimationShoot;
                    currentEvaluator = animEvaluatorShoot;
                }
            }
            else
            if (currentClipFinished)
            {
                SwitchToDefaultState();
            }
            else
            if ((state == AnimationState.Idle || state == AnimationState.Walking) && state != defaultState)
            {
                SwitchToDefaultState();
            }
        }