Support animations on Placeables
authorMikko Rasa <tdb@tdb.fi>
Sun, 1 Jul 2018 20:58:02 +0000 (23:58 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sun, 1 Jul 2018 20:58:02 +0000 (23:58 +0300)
Only matrix animations work for obvious reasons.

source/animationeventobserver.h
source/animationplayer.cpp
source/animationplayer.h

index 167b966cd2cf3ee4ff49461f075ad23d3e5c2748..1eafc4d206c89c32b20245300043c154fcee10ee 100644 (file)
@@ -7,7 +7,7 @@
 namespace Msp {
 namespace GL {
 
-class AnimatedObject;
+class Placeable;
 
 class AnimationEventObserver
 {
@@ -16,7 +16,7 @@ protected:
 public:
        virtual ~AnimationEventObserver() { }
 
-       virtual void animation_event(AnimatedObject *, const std::string &, const Variant &) { }
+       virtual void animation_event(Placeable *, const std::string &, const Variant &) { }
 };
 
 } // namespace GL
index 7c693ad2c3eef32ce7ec2a8aa74f4e754d130258..13bd7af034a70aa59b4c9b445cb8161640ba969a 100644 (file)
@@ -9,7 +9,7 @@ using namespace std;
 namespace Msp {
 namespace GL {
 
-AnimationPlayer::Target &AnimationPlayer::get_slot(AnimatedObject &obj)
+AnimationPlayer::Target &AnimationPlayer::get_slot(Placeable &obj)
 {
        ObjectMap::iterator i = objects.find(&obj);
        if(i!=objects.end())
@@ -18,25 +18,43 @@ AnimationPlayer::Target &AnimationPlayer::get_slot(AnimatedObject &obj)
        return objects.insert(ObjectMap::value_type(&obj, Target(obj))).first->second;
 }
 
-void AnimationPlayer::play(AnimatedObject &obj, const Animation &anim)
+AnimationPlayer::Target &AnimationPlayer::play_(Placeable &obj, const Animation &anim, bool stacked)
 {
        Target &target = get_slot(obj);
-       target.animations.clear();
-       target.base_matrix = Matrix();
-       target.stacked = false;
+       if(!stacked)
+       {
+               target.animations.clear();
+               target.base_matrix = Matrix();
+       }
+       else if(target.animations.empty())
+               target.base_matrix = *obj.get_matrix();
+       target.stacked = stacked;
+       // TODO check for incompatible armature
        target.armature = anim.get_armature();
        target.animations.push_back(PlayingAnimation(anim));
+       return target;
+}
+
+void AnimationPlayer::play(AnimatedObject &obj, const Animation &anim)
+{
+       Target &target = play_(obj, anim, false);
+       target.object = &obj;
+}
+
+void AnimationPlayer::play(Placeable &obj, const Animation &anim)
+{
+       play_(obj, anim, false);
 }
 
 void AnimationPlayer::play_stacked(AnimatedObject &obj, const Animation &anim)
 {
-       Target &target = get_slot(obj);
-       if(target.animations.empty())
-               target.base_matrix = *obj.get_matrix();
-       // TODO check for incompatible armature
-       target.stacked = true;
-       target.armature = anim.get_armature();
-       target.animations.push_back(PlayingAnimation(anim));
+       Target &target = play_(obj, anim, true);
+       target.object = &obj;
+}
+
+void AnimationPlayer::play_stacked(Placeable &obj, const Animation &anim)
+{
+       play_(obj, anim, true);
 }
 
 unsigned AnimationPlayer::get_n_active_animations(const AnimatedObject &obj) const
@@ -115,17 +133,20 @@ void AnimationPlayer::tick_single(Target &target, const Time::TimeDelta &dt)
 {
        PlayingAnimation &anim = target.animations.front();
        anim.iterator += dt;
-       target.object.set_matrix(anim.iterator.get_matrix());
-
-       unsigned n_uniforms = anim.animation->get_n_uniforms();
-       for(unsigned i=0; i<n_uniforms; ++i)
-               set_object_uniform(target.object, anim.animation->get_uniform_name(i), anim.iterator.get_uniform(i));
+       target.placeable.set_matrix(anim.iterator.get_matrix());
 
-       if(target.armature)
+       if(target.object)
        {
-               unsigned max_index = target.armature->get_max_link_index();
-               for(unsigned i=0; i<=max_index; ++i)
-                       target.object.set_pose_matrix(i, anim.iterator.get_pose_matrix(i));
+               unsigned n_uniforms = anim.animation->get_n_uniforms();
+               for(unsigned i=0; i<n_uniforms; ++i)
+                       set_object_uniform(*target.object, anim.animation->get_uniform_name(i), anim.iterator.get_uniform(i));
+
+               if(target.armature)
+               {
+                       unsigned max_index = target.armature->get_max_link_index();
+                       for(unsigned i=0; i<=max_index; ++i)
+                               target.object->set_pose_matrix(i, anim.iterator.get_pose_matrix(i));
+               }
        }
 
        anim.iterator.dispatch_events(target);
@@ -142,13 +163,16 @@ void AnimationPlayer::tick_stacked(Target &target, const Time::TimeDelta &dt)
                i->iterator += dt;
                matrix *= i->iterator.get_matrix();
 
-               unsigned n_uniforms = i->animation->get_n_uniforms();
-               for(unsigned j=0; j<n_uniforms; ++j)
-                       set_object_uniform(target.object, i->animation->get_uniform_name(j), i->iterator.get_uniform(j));
+               if(target.object)
+               {
+                       unsigned n_uniforms = i->animation->get_n_uniforms();
+                       for(unsigned j=0; j<n_uniforms; ++j)
+                               set_object_uniform(*target.object, i->animation->get_uniform_name(j), i->iterator.get_uniform(j));
+               }
        }
-       target.object.set_matrix(matrix);
+       target.placeable.set_matrix(matrix);
 
-       if(target.armature)
+       if(target.object && target.armature)
        {
                unsigned max_index = target.armature->get_max_link_index();
                for(unsigned i=0; i<=max_index; ++i)
@@ -159,7 +183,7 @@ void AnimationPlayer::tick_stacked(Target &target, const Time::TimeDelta &dt)
                        for(vector<PlayingAnimation>::iterator j=target.animations.begin(); j!=target.animations.end(); ++j)
                                if(j->animation->get_armature())
                                        matrix *= j->iterator.get_pose_matrix(i);
-                       target.object.set_pose_matrix(i, matrix);
+                       target.object->set_pose_matrix(i, matrix);
                }
        }
 
@@ -198,16 +222,17 @@ AnimationPlayer::PlayingAnimation::PlayingAnimation(const Animation &a):
 { }
 
 
-AnimationPlayer::Target::Target(AnimatedObject &o):
-       object(o),
+AnimationPlayer::Target::Target(Placeable &p):
+       placeable(p),
+       object(0),
        armature(0),
        stacked(false)
 { }
 
-void AnimationPlayer::Target::animation_event(AnimatedObject *, const string &name, const Variant &value)
+void AnimationPlayer::Target::animation_event(Placeable *, 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);
+               (*i)->animation_event(&placeable, name, value);
 }
 
 } // namespace GL
index 4c6e9ceca50bbc2fc0c7beeb5f256658a81c7150..4158627dbaa66fc26cceee5bb9d4dfb93600decf 100644 (file)
@@ -28,33 +28,39 @@ private:
 
        struct Target: AnimationEventObserver
        {
-               AnimatedObject &object;
+               Placeable &placeable;
+               AnimatedObject *object;
                Matrix base_matrix;
                const Armature *armature;
                std::vector<PlayingAnimation> animations;
                bool stacked;
                std::vector<AnimationEventObserver *> event_observers;
 
-               Target(AnimatedObject &);
+               Target(Placeable &);
 
-               virtual void animation_event(AnimatedObject *, const std::string &, const Variant &);
+               virtual void animation_event(Placeable *, const std::string &, const Variant &);
        };
 
-       typedef std::map<const AnimatedObject *, Target> ObjectMap;
+       typedef std::map<const Placeable *, Target> ObjectMap;
 
        ObjectMap objects;
 
 private:
-       Target &get_slot(AnimatedObject &);
+       Target &get_slot(Placeable &);
 
+       Target &play_(Placeable &, const Animation &, bool);
 public:
        /// Plays an animation on an object.  Any previous animations are replaced.
        void play(AnimatedObject &, const Animation &);
 
+       void play(Placeable &, const Animation &);
+
        /** Plays an animation, stacked with other animations.  If no animations are
        playing yet, the object's current matrix is used as the base. */
        void play_stacked(AnimatedObject &, const Animation &);
 
+       void play_stacked(Placeable &, const Animation &);
+
        /// Returns the number of animations currently affecting an object.
        unsigned get_n_active_animations(const AnimatedObject &) const;