public void BuildBlendTree(FastList <AnimationOperation> blendStack) { // Note! The tree has to be flattened and given as a stack! blendStack.Add(AnimationOperation.NewPush(anim1Evaluator, TimeSpan.FromTicks((long)(currentTime * Animation1.Duration.Ticks)))); blendStack.Add(AnimationOperation.NewPush(anim2Evaluator, TimeSpan.FromTicks((long)(currentTime * Animation2.Duration.Ticks)))); blendStack.Add(AnimationOperation.NewBlend(CoreAnimationOperation.Blend, BlendLerp)); }
/// <summary> /// BuildBlendTree is called every frame from the animation system when the <see cref="AnimationComponent"/> needs to be evaluated /// It overrides the default behavior of the <see cref="AnimationComponent"/> by setting a custom blend tree /// </summary> /// <param name="blendStack">The stack of animation operations to be blended</param> public void BuildBlendTree(FastList <AnimationOperation> blendStack) { switch (state) { case AnimationState.Walking: { // Note! The tree is laid out as a stack and has to be flattened before returning it to the animation system! blendStack.Add(AnimationOperation.NewPush(animEvaluatorWalkLerp1, TimeSpan.FromTicks((long)(currentTime * animationClipWalkLerp1.Duration.Ticks)))); blendStack.Add(AnimationOperation.NewPush(animEvaluatorWalkLerp2, TimeSpan.FromTicks((long)(currentTime * animationClipWalkLerp2.Duration.Ticks)))); blendStack.Add(AnimationOperation.NewBlend(CoreAnimationOperation.Blend, walkLerpFactor)); } break; case AnimationState.Jumping: { blendStack.Add(AnimationOperation.NewPush(animEvaluatorJumpStart, TimeSpan.FromTicks((long)(currentTime * AnimationJumpStart.Duration.Ticks)))); } break; case AnimationState.Airborne: { blendStack.Add(AnimationOperation.NewPush(animEvaluatorJumpMid, TimeSpan.FromTicks((long)(currentTime * AnimationJumpMid.Duration.Ticks)))); } break; case AnimationState.Landing: { blendStack.Add(AnimationOperation.NewPush(animEvaluatorJumpEnd, TimeSpan.FromTicks((long)(currentTime * AnimationJumpEnd.Duration.Ticks)))); } break; case AnimationState.Punching: { blendStack.Add(AnimationOperation.NewPush(animEvaluatorPunch, TimeSpan.FromTicks((long)(currentTime * AnimationPunch.Duration.Ticks)))); } break; } }
private AnimationClip SubtractAnimations(AnimationClip baseAnimation, AnimationClip sourceAnimation) { if (baseAnimation == null) { throw new ArgumentNullException("baseAnimation"); } if (sourceAnimation == null) { throw new ArgumentNullException("sourceAnimation"); } var animationBlender = new AnimationBlender(); var baseEvaluator = animationBlender.CreateEvaluator(baseAnimation); var sourceEvaluator = animationBlender.CreateEvaluator(sourceAnimation); // Create a result animation with same channels var resultAnimation = new AnimationClip(); foreach (var channel in sourceAnimation.Channels) { // Create new instance of curve var newCurve = (AnimationCurve)Activator.CreateInstance(typeof(AnimationCurve <>).MakeGenericType(channel.Value.ElementType)); // Quaternion curve are linear, others are cubic if (newCurve.ElementType != typeof(Quaternion)) { newCurve.InterpolationType = AnimationCurveInterpolationType.Cubic; } resultAnimation.AddCurve(channel.Key, newCurve); } var resultEvaluator = animationBlender.CreateEvaluator(resultAnimation); var animationOperations = new FastList <AnimationOperation>(); // Perform animation blending for each frame and upload results in a new animation // Note that it does a simple per-frame sampling, so animation discontinuities will be lost. // TODO: Framerate is hardcoded at 30 FPS. var frameTime = TimeSpan.FromSeconds(1.0f / 30.0f); for (var time = TimeSpan.Zero; time < sourceAnimation.Duration + frameTime; time += frameTime) { // Last frame, round it to end of animation if (time > sourceAnimation.Duration) { time = sourceAnimation.Duration; } TimeSpan baseTime; switch (Parameters.Mode) { case AdditiveAnimationBaseMode.FirstFrame: baseTime = TimeSpan.Zero; break; case AdditiveAnimationBaseMode.Animation: baseTime = TimeSpan.FromTicks(time.Ticks % baseAnimation.Duration.Ticks); break; default: throw new ArgumentOutOfRangeException(); } // Generates result = source - base animationOperations.Clear(); animationOperations.Add(AnimationOperation.NewPush(sourceEvaluator, time)); animationOperations.Add(AnimationOperation.NewPush(baseEvaluator, baseTime)); animationOperations.Add(AnimationOperation.NewBlend(CoreAnimationOperation.Subtract, 1.0f)); animationOperations.Add(AnimationOperation.NewPop(resultEvaluator, time)); // Compute AnimationClipResult animationClipResult = null; animationBlender.Compute(animationOperations, ref animationClipResult); } resultAnimation.Duration = sourceAnimation.Duration; resultAnimation.RepeatMode = sourceAnimation.RepeatMode; return(resultAnimation); }