Have a good day.
Usage:
Code: Select all
//animation id's
enum AnimationID
{
ANIM_IDLE,
ANIM_RUN
};
//pseudo code
class MyEntity : public Animations
{
public:
/**
* Get entity reference
* @return Entity reference.
*/
Ogre::Entity& getEntity() const {
return *mEntity;
}
private:
Ogre::Entity* mEntity;
};
void test()
{
MyEntity entity;
entity.registerAnimation(entity.getEntity(), 1.0f, 7.5, 4.5, true, ANIM_IDLE, "Idle");
entity.registerAnimation(entity.getEntity(), 1.0f, 7.5, 4.5, true, ANIM_RUN, "Run");
//set idle as default
entity.setAnimation( ANIM_IDLE, Animations::eInstant );
//switch using blending
entity.setAnimation( ANIM_RUN );
//update each frame
entity.updateAnimations( timestep );
}
Code: Select all
#include <animations.h>
#include <ogre/OgreEntity.h>
#include <ogre/OgreAnimationState.h>
//constructor
Animations::Animations() : mActiveStatePtr( nullptr )
{
}
//registerAnimation
void Animations::registerAnimation(Ogre::Entity& entity, float speed, float blend_in, float blend_out, bool looping, AnimationID animationId, std::string const& name)
{
if( entity.hasAnimationState(name) )
{
auto* statePtr = entity.getAnimationState(name);
if( statePtr )
{
statePtr->setLoop(looping);
statePtr->setEnabled(0);
statePtr->setWeight(0);
statePtr->setTimePosition(0);
mAnimationSet[animationId] = AnimationData(statePtr, speed, blend_in, blend_out);
}
}
}
//setAnimation
void Animations::setAnimation(AnimationID animationId, SwitchStates state)
{
auto it = mAnimationSet.find(animationId);
if( it != std::end(mAnimationSet) ) {
setAnimation(it->second, state);
}
}
//setAnimation
void Animations::setAnimation(AnimationData& animation, SwitchStates state)
{
switch( state )
{
case eInstant:
{
if( mActiveStatePtr ) {
mActiveStatePtr->mStatePtr->setWeight(0);
mActiveStatePtr->mStatePtr->setEnabled(0);
}
mActiveStatePtr = &animation;
mActiveStatePtr->mStatePtr->setEnabled(1);
mActiveStatePtr->mStatePtr->setTimePosition(0);
mActiveStatePtr->mStatePtr->setWeight(1);
break;
}
case eBlending:
{
//blending.
if( mActiveStatePtr && mActiveStatePtr != &animation ) {
mDeadList.push_back( mActiveStatePtr );
}
//activate new animation state.
mActiveStatePtr = &animation;
mActiveStatePtr->mStatePtr->setEnabled(1);
break;
}
}
}
// Update the animation states.
void Animations::updateAnimations(float timestep)
{
//blend in the new active animation.
if( mActiveStatePtr )
{
Ogre::Real weight = mActiveStatePtr->mStatePtr->getWeight();
if( weight < 1 ) {
weight = std::min<float>( weight + (timestep * mActiveStatePtr->mBlendIn), 1.0f );
mActiveStatePtr->mStatePtr->setWeight(weight);
}
mActiveStatePtr->mStatePtr->addTime(timestep * mActiveStatePtr->mSpeed);
}
//blend out / remove the "dead" animations.
std::for_each( std::begin(mDeadList), std::end(mDeadList), [&]( AnimationData* dataPtr ) {
dataPtr->mStatePtr->setWeight( std::max<float>( dataPtr->mStatePtr->getWeight() - (timestep * dataPtr->mBlendOut), 0.0f ) );
});
mDeadList.remove_if( [&]( AnimationData* dataPtr ) { return (dataPtr->mStatePtr->getWeight() == 0.0f || dataPtr == mActiveStatePtr); } );
}
//setAnimationSpeed
void Animations::setAnimationSpeed(AnimationID animationId, float speed)
{
auto it = mAnimationSet.find( animationId );
if( it != std::end(mAnimationSet) ) {
it->second.mSpeed = speed;
}
}
//clearAnimations
void Animations::clearAnimations()
{
mAnimationSet.clear();
mActiveStatePtr = nullptr;
}
Code: Select all
#include <list>
#include <map>
//forward declaration.
namespace Ogre {
class Entity;
class AnimationState;
}
class Animations
{
public:
/**
* Constructor
*/
Animations();
//typedefs
typedef std::list<AnimationData*> DeadList;
typedef std::map<AnimationID, AnimationData> MAnimationSet;
//animation switch states
enum SwitchStates
{
eBlending,
eInstant
};
/**
* Register new animation state.
* @param entity Entity reference.
* @param speed Animation speed.
* @param blend_in Animation blend in speed.
* @param blend_out Animation blend in speed.
* @param looping Animation loop state.
* @param animationId Animation id.
* @param name Skeleton animation name.
*/
void registerAnimation(Ogre::Entity& entity, float speed, float blend_in, float blend_out, bool looping, AnimationID animationId, std::string const& name);
/**
* Set new animation state.
* @param Animation id.
* @param Current animation state.
*/
void setAnimation(AnimationID animationId, SwitchStates state = eBlending);
/**
* Set new animation state.
* @param AnimationData reference.
* @param Current animation state.
*/
void setAnimation(AnimationData& animation, SwitchStates state = eBlending);
/**
* Set new animation speed.
* @param animationId Animation id.
* @param speed New animation speed.
*/
void setAnimationSpeed(AnimationID animationId, float speed);
/**
* Update the animation states.
* @param timestep Current timestep.
*/
void updateAnimations(float timestep);
/**
* clear animations.
*/
void clearAnimations();
/**
* Get current active animation.
* @return Current active animation state.
*/
inline AnimationData* getActiveState() {
return mActiveStatePtr;
}
private:
// animation states.
MAnimationSet mAnimationSet;
// storage of dead states.
DeadList mDeadList;
// current active animation state.
AnimationData* mActiveStatePtr;
};