]> git.tdb.fi Git - libs/gl.git/blobdiff - source/animationplayer.cpp
Implement an event system for animations
[libs/gl.git] / source / animationplayer.cpp
index cd71679800fffea672ebea6c4ef84ed796622104..6b5a481f6a74f8da98b138067d803d8aacfbe785 100644 (file)
@@ -1,3 +1,4 @@
+#include <msp/core/algorithm.h>
 #include "animatedobject.h"
 #include "animationplayer.h"
 #include "armature.h"
@@ -44,6 +45,34 @@ unsigned AnimationPlayer::get_n_active_animations(const AnimatedObject &obj) con
        return (i!=objects.end() ? i->second.animations.size() : 0);
 }
 
+void AnimationPlayer::observe_events(AnimatedObject &obj, AnimationEventObserver &observer)
+{
+       Target &target = get_slot(obj);
+       if(find(target.event_observers, &observer)==target.event_observers.end())
+               target.event_observers.push_back(&observer);
+}
+
+void AnimationPlayer::unobserve_events(AnimatedObject &obj, AnimationEventObserver &observer)
+{
+       ObjectMap::iterator i = objects.find(&obj);
+       if(i==objects.end())
+               return;
+
+       vector<AnimationEventObserver *>::iterator j = find(i->second.event_observers, &observer);
+       if(j!=i->second.event_observers.end())
+               i->second.event_observers.erase(j);
+}
+
+void AnimationPlayer::unobserve_events(AnimationEventObserver &observer)
+{
+       for(ObjectMap::iterator i=objects.begin(); i!=objects.end(); ++i)
+       {
+               vector<AnimationEventObserver *>::iterator j = find(i->second.event_observers, &observer);
+               if(j!=i->second.event_observers.end())
+                       i->second.event_observers.erase(j);
+       }
+}
+
 void AnimationPlayer::stop(AnimatedObject &obj)
 {
        objects.erase(&obj);
@@ -72,10 +101,10 @@ void AnimationPlayer::tick(const Time::TimeDelta &dt)
        {
                if(i->second.stacked)
                        tick_stacked(i->second, dt);
-               else
+               else if(!i->second.animations.empty())
                        tick_single(i->second, dt);
 
-               if(i->second.animations.empty())
+               if(i->second.animations.empty() && i->second.event_observers.empty())
                        objects.erase(i++);
                else
                        ++i;
@@ -99,6 +128,8 @@ void AnimationPlayer::tick_single(Target &target, const Time::TimeDelta &dt)
                        target.object.set_pose_matrix(i, anim.iterator.get_pose_matrix(i));
        }
 
+       anim.iterator.dispatch_events(target);
+
        if(!anim.iterator.is_end())
                target.animations.clear();
 }
@@ -134,6 +165,8 @@ void AnimationPlayer::tick_stacked(Target &target, const Time::TimeDelta &dt)
 
        for(vector<PlayingAnimation>::iterator i=target.animations.begin(); i!=target.animations.end(); )
        {
+               i->iterator.dispatch_events(target);
+
                if(i->iterator.is_end())
                        i = target.animations.erase(i);
                else
@@ -165,6 +198,12 @@ AnimationPlayer::Target::Target(AnimatedObject &o):
        stacked(false)
 { }
 
+void AnimationPlayer::Target::animation_event(AnimatedObject *, const string &name, const Variant &value)
+{
+       for(vector<AnimationEventObserver *>::const_iterator i=event_observers.begin(); i!=event_observers.end(); ++i)
+               (*i)->animation_event(&object, name, value);
+}
+
 
 AnimationPlayer::PlayingAnimation::PlayingAnimation(const Animation &a):
        animation(&a),