c++ animation manager

This is the C++ version of the Lua Animation manager that comes with the Leadwerks Engine

Thanks to Crazy Carpet and Reepblue for making this. Original topic: http://www.leadwerks.com/werkspace/topic/14863-a-c-version-of-animationmanger/

.H

#ifndef ANIMATIONMGR_H
#define ANIMATIONMGR_H
#pragma once

#include <string>
#include <vector>

namespace Leadwerks {
    class Entity;

    typedef void(*func_ptr)(Entity* entity, const std::string&);
    class Animation {
    public:
        Animation() {};
        ~Animation() {};

        long blendstart;
        long blendfinish;
        int blendtime;
        std::string sequence;
        int length;
        float speed;
        bool mode;
        bool endOfSequenceReached = false;
        func_ptr endHook;
    };

    class AnimationManager {
    public:
        AnimationManager(Entity* pEntity);
        virtual ~AnimationManager();
        virtual void SetAnimationSequence(const std::string& pSequence, const float pSpeed = 1.0f, const int pBlendTime = 500, const bool pMode = false, func_ptr pEndHook = nullptr);
        virtual void Update();
        void ClearAnimations();
    private:
        Entity* entity;
        short frameoffset;
        std::vector<Animation*> animations;
    };
}
#endif

.cpp

#include "AnimationManager.h"
#include "Leadwerks.h"

namespace Leadwerks {
    AnimationManager::AnimationManager(Entity* pEntity) {
        if (pEntity == NULL) {
            Debug::Error("[AnimationManager] 'pEntity' is NULL in constructor.");
        }
        entity = pEntity;
        frameoffset = Math::Random(0, 1000);
    }

    AnimationManager::~AnimationManager() {
        for (auto it = animations.begin(); it != animations.end(); ++it) {
            delete *it;
        }
        ClearAnimations();
    }

    void AnimationManager::SetAnimationSequence(const std::string& pSequence, const float pSpeed, const int pBlendTime, const bool pMode, func_ptr pEndHook) {
        if (pMode == false) {
            if (animations.size() > 0) {
                if (animations.back()->sequence == pSequence) {
                    if (animations.back()->speed == pSpeed) {
                        animations.back()->blendtime = pBlendTime;
                        return;
                    }
                }
            }
        }

        Animation* animation = new Animation();
        animation->blendstart = Time::GetCurrent();
        animation->blendfinish = animation->blendstart + pBlendTime;
        animation->sequence = pSequence;
        animation->length = entity->GetAnimationLength(animation->sequence, true);
        animation->speed = pSpeed;
        animation->mode = pMode;
        animation->endHook = pEndHook;
        animation->endOfSequenceReached = false;

        animations.push_back(animation);
    }

    void AnimationManager::ClearAnimations() {
        animations.clear();
    }

    void AnimationManager::Update() {
        float blend, frame; 
        bool doanimation = false;
        long currenttime = Time::GetCurrent();
        int maxanim = -1;
        for (int i = 0; i < animations.size(); ++i) {
            Animation* animation = animations[i];

            if (doanimation == false) {
                doanimation = true;
                entity->LockMatrix();
            }

            //Division can result in a float, so cast numerator and denominator to float.
            blend = float(currenttime - animation->blendstart) / float(animation->blendfinish - animation->blendstart);
            blend = Math::Min(1.0, blend);

            if (animation->mode == false) {
                frame = currenttime * animation->speed + frameoffset;
            }
            else {
                frame = (currenttime - animation->blendstart) * animation->speed;

                if (frame >= (animation->length - 1)) {
                    frame = animation->length - 1;
                    maxanim = i + 1;
                    if (animation->endOfSequenceReached == false) {
                        if (animation->endHook != nullptr) {
                            animation->endHook(entity, animation->sequence);
                            animation->endHook = nullptr;
                        }
                        animation->endOfSequenceReached = true;
                    }
                }
            }

            entity->SetAnimationFrame(frame, blend, animation->sequence, true);

            if (blend >= 1.0) {
                maxanim = Math::Max(maxanim, i);
            }
        }

        if (doanimation == true) {
            entity->UnlockMatrix();
        }

        if (maxanim > -1)  {
            for (int n = 0; n < animations.size(); ++n) {
                Animation* completedanimation = animations[n];

                if (n < maxanim) {
                    if (completedanimation->mode == false || completedanimation->endOfSequenceReached == true) {
                        animations.erase(animations.begin() + n);
                    }
                }
                else {
                    break;
                }
            }
        }
    }
}
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License