Animation.hh 9.65 KB
Newer Older
1
2
3
4
5
/***********************************************************************
 * Copyright 2011-2012 Computer Graphics Group RWTH Aachen University. *
 * All rights reserved.                                                *
 * Distributed under the terms of the MIT License (see LICENSE.TXT).   *
 **********************************************************************/
6

Ole Untzelmann's avatar
Ole Untzelmann committed
7
8
#ifndef ACGL_ANIMATIONS_ANIMATION_HH
#define ACGL_ANIMATIONS_ANIMATION_HH
9

10
#include <ACGL/ACGL.hh>
11
#include <ACGL/Types.hh>
Ole Untzelmann's avatar
Ole Untzelmann committed
12
13
14
#include <ACGL/Base/Macros.hh>
#include <ACGL/Animations/EaseFunctions.hh>
#include <ACGL/Animations/Interpolator.hh>
15

Ole Untzelmann's avatar
Ole Untzelmann committed
16
17
#include <list>
#include <queue>
18
19
20
21
22
23
24
25

namespace ACGL{
namespace Animations{

// Animation *************************************************************************************
class Animation
{
public:
Ole Untzelmann's avatar
Ole Untzelmann committed
26
    enum RepeatMode {Endless = -1, EndlessNoRepeat = -2};
27

Ole Untzelmann's avatar
Ole Untzelmann committed
28
29
    Animation() :
        mInited(false),
30
31
        mStopped(false) {}
    virtual ~Animation() {}
32

Ole Untzelmann's avatar
Ole Untzelmann committed
33
    virtual void init() = 0;
34
    virtual long update(uint_t msec) = 0;
Ole Untzelmann's avatar
Ole Untzelmann committed
35
    virtual bool finished() = 0;
36

Ole Untzelmann's avatar
Ole Untzelmann committed
37
38
    inline const bool& isInited() const;
    inline const bool& isStopped() const;
39

Ole Untzelmann's avatar
Ole Untzelmann committed
40
41
    inline void restart();
    inline void stop();
42
43
44
protected:

    bool mInited;
Ole Untzelmann's avatar
Ole Untzelmann committed
45
    bool mStopped;
46
47
48
49
private:

};

Robert Menzel's avatar
Robert Menzel committed
50
ACGL_SMARTPOINTER_TYPEDEFS(Animation)
51

Ole Untzelmann's avatar
Ole Untzelmann committed
52
typedef std::list<SharedAnimation> AnimationList;
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
typedef std::queue<SharedAnimation> AnimationQueue;

class AnimationManager
{
public:
    static void push(const SharedAnimation&  _animation);
    static void update(uint_t _msec);

    static void cleanUp();
protected:
private:
    static AnimationList mAnimations;

};

Ole Untzelmann's avatar
Ole Untzelmann committed
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
class AnimationEventCallbackFunction
{
public:
    typedef void (*Function)(uint_t);

    AnimationEventCallbackFunction(Function _pFunction,uint_t _id) :
        mpFunction(_pFunction),
        mId(_id) {  }

    inline void call()
    {
        mpFunction(mId);
    }

private:

    Function mpFunction;
    uint_t mId;
};

template <class T>
class AnimationEventCallbackMemberFunction
{
public:
    typedef void (T::*Function)(uint_t);

    AnimationEventCallbackMemberFunction(const T* _pTarget, Function _pFunction,uint_t _id) :
        mpTarget(_pTarget),
        mpFunction(_pFunction),
        mId(_id) { }

    inline void call()
    {
        mpTarget->mpFunction(mId);
    }

private:
    const T* mpTarget;
    Function mpFunction;
    uint_t mId;
};

110
111
// AnimationEvent *************************************************************************************

Ole Untzelmann's avatar
Ole Untzelmann committed
112
template <class Callback>
113
114
115
class AnimationEvent : public Animation
{
public:
Ole Untzelmann's avatar
Ole Untzelmann committed
116
117
118
119
    AnimationEvent(const Callback& _callback) :
        Animation(),
        mCallback(_callback),
        mEventCalled(false) {  }
120

Ole Untzelmann's avatar
Ole Untzelmann committed
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
    virtual void init()
    {
        mEventCalled = false;

        mInited = true;
    }

    virtual long update(uint_t _msec)
    {
        mCallback.call();
        mEventCalled = true;

        return _msec;
    }

    virtual bool finished()
    {
        return mEventCalled;
    }

    Callback& getCallback()
    {
        return mCallback;
    }
145
146

private:
Ole Untzelmann's avatar
Ole Untzelmann committed
147
    Callback mCallback;
Ole Untzelmann's avatar
Ole Untzelmann committed
148
149

    bool mEventCalled;
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
};


// AnimationWait *************************************************************************************

class AnimationWait : public Animation
{
public:
    AnimationWait(const uint_t _duration);

    virtual void init();
    virtual long update(uint_t _msec);
    virtual bool finished();

private:
    long mTimeLeft;
    long mDuration;
};

Robert Menzel's avatar
Robert Menzel committed
169
ACGL_SMARTPOINTER_TYPEDEFS(AnimationWait)
170
171
172
173
174
175

// AnimationSequential *************************************************************************************

class AnimationSequential : public Animation
{
public:
Ole Untzelmann's avatar
Ole Untzelmann committed
176
    AnimationSequential(const int_t _loops = 0);
177
178
179
180
181
182
183
184
185
    virtual ~AnimationSequential();

    virtual void init();
    virtual long update(uint_t _msec);
    virtual bool finished();

    void push_animation(const SharedAnimation& _animation);

private:
Ole Untzelmann's avatar
Ole Untzelmann committed
186
    int_t mLoops;
187

Ole Untzelmann's avatar
Ole Untzelmann committed
188
    AnimationList::iterator mCurrentPosition;
189
190
191
    AnimationList mAnimations;
};

Robert Menzel's avatar
Robert Menzel committed
192
ACGL_SMARTPOINTER_TYPEDEFS(AnimationSequential)
193
194
195
196
197
198

// AnimationParallel *************************************************************************************

class AnimationParallel : public Animation
{
public:
Ole Untzelmann's avatar
Ole Untzelmann committed
199
    AnimationParallel(const int_t _loops = 0);
200
201
202
203
204
205
206
207
208
    virtual ~AnimationParallel();

    virtual void init();
    virtual long update(uint_t _msec);
    virtual bool finished();

    void push_animation(const SharedAnimation& animation);

private:
Ole Untzelmann's avatar
Ole Untzelmann committed
209
    int_t mLoops;
210
211

    AnimationList mAnimations;
Ole Untzelmann's avatar
Ole Untzelmann committed
212
    uint_t mRunningAnimations;
213
214
};

Robert Menzel's avatar
Robert Menzel committed
215
ACGL_SMARTPOINTER_TYPEDEFS(AnimationParallel)
216
217
218
219
220
221
222
223
224
225
226
227


// AnimationVariable *************************************************************************************
template <class T, class Interpolator>
class AnimationVariable : public Animation
{
public:

    AnimationVariable(T& _data, uint_t _duration, const SharedEaseFunction& _ease_function, const Interpolator& _interpolator = Interpolator()) :
        mpEaseFunction(_ease_function),
        mInterpolator(_interpolator),
        mCurrentTime(0),
228
        mDuration(_duration),
229
230
231
232
233
234
235
236
237
238
239
        mpData(_data) { }

    virtual ~AnimationVariable()
    {
         mBlendInterpolators.clear();
    }

    virtual void init()
    {
        mCurrentTime = 0;
        mInterpolator.init(mpData);
Ole Untzelmann's avatar
Ole Untzelmann committed
240
241

        mInited = true;
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
    }

    virtual long update(uint_t _msec)
    {
        long time_span;
        if(mDuration-mCurrentTime >= _msec) time_span = _msec;
        else time_span = mDuration-mCurrentTime;

        mCurrentTime += time_span;
        float progress = (float)mCurrentTime/(float)mDuration;

        mpData = mInterpolator.interpolate( mpEaseFunction->value(progress) );

        float sub_progress;

        for(unsigned int i = 0;i < mBlendInterpolators.size();i++)
        {
            sub_progress = (progress - mBlendInterpolators[i].start)/(mBlendInterpolators[i].end - mBlendInterpolators[i].start);
            if(0.0f <= sub_progress && sub_progress <= 1.0f)
            {
                mBlendInterpolators[i].mpInterpolator->blend(&mpData, mBlendInterpolators[i].mpEaseFunction->value(sub_progress) );
            }
        }

        return _msec-time_span;
    }

    virtual bool finished()
    {
        if(mCurrentTime >= mDuration)
            mpData = mInterpolator.finish();

        return mCurrentTime >= mDuration;
    }

    void add_blend_interpolator(const SharedBlendInterpolator& _interpolator, const SharedEaseFunction& _ease_function, float _start = 0.0f, float _end = 1.0f)
    {
        mBlendInterpolators.push_back((blend_interpolator_t){_interpolator, _ease_function, _start, _end, false});
    }

    inline const SharedEaseFunction& get_ease_function(){ return mpEaseFunction;}
    inline void set_ease_function(const SharedEaseFunction& _ease_function){ mpEaseFunction.reset(); mpEaseFunction = _ease_function;}

    inline Interpolator& get_interpolator(){ return mInterpolator; }
    //void set_interpolator(Interpolator* interpolator){ this->interpolator = interpolator; }

protected:
private:
    SharedEaseFunction mpEaseFunction;
    Interpolator mInterpolator;

    uint_t mCurrentTime;
    uint_t mDuration;

    T& mpData;

    struct blend_interpolator_t{
        SharedBlendInterpolator mpInterpolator;
        SharedEaseFunction mpEaseFunction;
        float start, end;
        bool active;
    };
    typedef std::vector<blend_interpolator_t> BlendInterpolators;

    BlendInterpolators mBlendInterpolators;
307

308
309
310
};

typedef AnimationVariable<float, LinearInterpolatorFloat > AnimationFloatLinear;
Robert Menzel's avatar
Robert Menzel committed
311
ACGL_SMARTPOINTER_TYPEDEFS(AnimationFloatLinear)
312

313
typedef AnimationVariable<glm::vec2, LinearInterpolatorVec2 > AnimationVec2Linear;
Robert Menzel's avatar
Robert Menzel committed
314
ACGL_SMARTPOINTER_TYPEDEFS(AnimationVec2Linear)
315

316
typedef AnimationVariable<glm::vec3, LinearInterpolatorVec3 > AnimationVec3Linear;
Robert Menzel's avatar
Robert Menzel committed
317
ACGL_SMARTPOINTER_TYPEDEFS(AnimationVec3Linear)
318

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
template <class T, class SpeedInterpolator>
class AnimationSpeed : public Animation{
public:
    AnimationSpeed(T& _data, float _targetSpeed, float _acceleration = 1.0f, float _decceleration = 1.0f, float _startSpeed = 0.0f, const SpeedInterpolator& _interpolator = SpeedInterpolator()) :
        mCurrentSpeed(_startSpeed),
        mTargetSpeed(_targetSpeed),
        mAcceleration(_acceleration),
        mDecceleration(_decceleration),
        mpData(_data),
        mInterpolator(_interpolator){ }

    virtual void init()
    {
        mInterpolator.init(mpData);
        mInited = true;
    }

    virtual long update(uint_t _msec)
    {
        //Calculate the distance
        float distance = mCurrentSpeed*((float)_msec)/1000.0f;

        //Move on that distance
        float realDistance = mInterpolator.interpolate(mpData, distance);
        long msecLeft = (uint_t)((distance-realDistance)*1000.0f/mCurrentSpeed);

        //Adjust the speed
        if(mCurrentSpeed > mTargetSpeed)
            mCurrentSpeed -= fmin(mCurrentSpeed-mTargetSpeed, mDecceleration*((float)_msec)/1000.0f);
        else
            mCurrentSpeed += fmin(mTargetSpeed-mCurrentSpeed, mAcceleration*((float)_msec)/1000.0f);

351
        return msecLeft;
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
    }

    virtual bool finished()
    {
        if(mInterpolator.finished())
            mInited = false;
        return mInterpolator.finished();
    }

    SpeedInterpolator& getSpeedInterpolator(){return mInterpolator;}

    void setTargetSpeed(float _value)
    {
        mTargetSpeed = _value;
    }

    void setSpeed(float _value)
    {
        mCurrentSpeed = _value;
    }

    void setAcceleration(float _value)
    {
        mAcceleration = _value;
    }

    void setDecceleration(float _value)
    {
        mDecceleration = _value;
    }

private:
    float mCurrentSpeed;
    float mTargetSpeed;
    float mAcceleration;
    float mDecceleration;

    T& mpData;

    SpeedInterpolator mInterpolator;
};

394
395
396
397
398
}
}



Ole Untzelmann's avatar
Ole Untzelmann committed
399
#endif // ACGL_ANIMATIONS_ANIMATION_HH