This is a port of the C++ AnimationBlender class to Mogre and C# by Ernesto Gutiérrez (smernesto). It was tested with Mogre 0.2.0 (Ogre 1.4.0)
To blend is to fade between two states. In the animation process it allows to create a transition between two animations.
If you have some questions, want to add something or you have some bug fixes please post at this Forum topic
//Porting notes: //* Ported by Ernesto Gutierrez (smernesto) - 02-july-2007 //* Added properties for the public variables //* Changed the code to the C# coding style //* Tested with Mogre 0.2.0 (Ogre 1.4.0) using System; using Mogre; namespace Mogre { public class AnimationBlender { public enum BlendingTransition { BlendSwitch, // stop source and start dest BlendWhileAnimating, // cross fade, blend source animation out while blending destination animation in BlendThenAnimate // blend source to first frame of dest, when done, start dest anim } private Entity mEntity; private AnimationState mSource; private AnimationState mTarget; private BlendingTransition mTransition; private bool loop; private float mTimeleft, mDuration; private bool complete; public void Blend(string animation, BlendingTransition transition, float duration, bool l) { loop = l; if (transition == BlendingTransition.BlendSwitch) { if (mSource != null) mSource.Enabled = false; mSource = mEntity.GetAnimationState(animation); mSource.Enabled = true; mSource.Weight = 1; mSource.TimePosition = 0; mTimeleft = 0; } else { AnimationState newTarget = mEntity.GetAnimationState(animation); if (mTimeleft > 0) { // oops, weren't finished yet if (newTarget == mTarget) { // nothing to do! (ignoring duration here) } else if (newTarget == mSource) { // going back to the source state, so let's switch mSource = mTarget; mTarget = newTarget; mTimeleft = mDuration - mTimeleft; // i'm ignoring the new duration here } else { // ok, newTarget is really new, so either we simply replace the target with this one, or // we make the target the new source if (mTimeleft < mDuration * 0.5) { // simply replace the target with this one mTarget.Enabled = false; mTarget.Weight = 0; } else { // old target becomes new source mSource.Enabled = false; mSource.Weight = 0; mSource = mTarget; } mTarget = newTarget; mTarget.Enabled = true; mTarget.Weight = 1.0f - mTimeleft / mDuration; mTarget.TimePosition = 0; } } else { // assert( target == 0, "target should be 0 when not blending" ) // mSource->setEnabled(true); // mSource->setWeight(1); mTransition = transition; mTimeleft = mDuration = duration; mTarget = newTarget; mTarget.Enabled = true; mTarget.Weight = 0; mTarget.TimePosition = 0; } } } public void AddTime(float time) { if (mSource != null) { if (mTimeleft > 0) { mTimeleft -= time; if (mTimeleft < 0) { // finish blending mSource.Enabled = false; mSource.Weight = 0; mSource = mTarget; mSource.Enabled = true; mSource.Weight = 1; mTarget = null; } else { // still blending, advance weights mSource.Weight = mTimeleft / mDuration; mTarget.Weight = 1.0f - mTimeleft / mDuration; if (mTransition == BlendingTransition.BlendWhileAnimating) mTarget.AddTime(time); } } if (mSource.TimePosition >= mSource.Length) { complete = true; } else { complete = false; } mSource.AddTime(time); mSource.Loop = loop; } } public AnimationBlender(Entity entity) { mEntity = entity; } public void Init(string animation) { AnimationStateSet set = mEntity.AllAnimationStates; foreach (AnimationState anim in set.GetAnimationStateIterator()) { anim.Enabled = false; anim.Weight = 0; anim.TimePosition = 0; } mSource = mEntity.GetAnimationState(animation); mSource.Enabled = true; mSource.Weight = 1; mTimeleft = 0; mDuration = 1; mTarget = null; complete = false; } //Properties public float Progress { get { return mTimeleft / mDuration; } } public AnimationState Source { get { return mSource; } } public AnimationState Target { get { return mTarget; } } public bool Complete { get { return complete; } } public float TimeLeft { get { return mTimeleft; } } public float Duration { get { return mDuration; } } } }