-#include <msp/core/algorithm.h>
-#include "animatedobject.h"
-#include "animationplayer.h"
-#include "armature.h"
-#include "programdata.h"
-
-using namespace std;
-
-namespace Msp {
-namespace GL {
-
-AnimationPlayer::Target &AnimationPlayer::get_slot(Placeable &obj)
-{
- ObjectMap::iterator i = objects.find(&obj);
- if(i!=objects.end())
- return i->second;
-
- return objects.insert(ObjectMap::value_type(&obj, Target(obj))).first->second;
-}
-
-AnimationPlayer::Target &AnimationPlayer::play_(Placeable &obj, const Animation &anim, bool stacked)
-{
- Target &target = get_slot(obj);
- 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 = 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
-{
- ObjectMap::const_iterator i = objects.find(&obj);
- 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);
-}
-
-void AnimationPlayer::stop(AnimatedObject &obj, const Animation &anim)
-{
- ObjectMap::iterator i = objects.find(&obj);
- if(i==objects.end())
- return;
-
- for(vector<PlayingAnimation>::iterator j=i->second.animations.begin(); j!=i->second.animations.end(); ++j)
- if(j->animation==&anim)
- {
- i->second.animations.erase(j);
- break;
- }
-
- if(i->second.animations.empty())
- objects.erase(i);
-}
-
-void AnimationPlayer::tick(const Time::TimeDelta &dt)
-{
- for(ObjectMap::iterator i=objects.begin(); i!=objects.end(); )
- {
- if(i->second.stacked)
- tick_stacked(i->second, dt);
- else if(!i->second.animations.empty())
- tick_single(i->second, dt);
-
- if(i->second.animations.empty() && i->second.event_observers.empty())
- objects.erase(i++);
- else
- ++i;
- }
-}
-
-void AnimationPlayer::tick_single(Target &target, const Time::TimeDelta &dt)
-{
- PlayingAnimation &anim = target.animations.front();
- anim.iterator += dt;
- target.placeable.set_matrix(anim.iterator.get_matrix());
-
- if(target.object)
- {
- 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);
-
- if(anim.iterator.is_end())
- target.animations.clear();
-}
-
-void AnimationPlayer::tick_stacked(Target &target, const Time::TimeDelta &dt)
-{
- Matrix matrix = target.base_matrix;
- for(vector<PlayingAnimation>::iterator i=target.animations.begin(); i!=target.animations.end(); ++i)
- {
- i->iterator += dt;
- matrix *= i->iterator.get_matrix();
-
- 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.placeable.set_matrix(matrix);
-
- if(target.object && target.armature)
- {
- unsigned max_index = target.armature->get_max_link_index();
- for(unsigned i=0; i<=max_index; ++i)
- {
- matrix = Matrix();
- /* XXX This is in all likelihood incorrect. The stacking should be
- performed on local matrices. */
- 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);
- }
- }
-
- 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
- ++i;
- }
-
- if(target.animations.empty())
- target.stacked = false;
-}
-
-void AnimationPlayer::set_object_uniform(AnimatedObject &obj, const string &name, const KeyFrame::AnimatedUniform &uni)
-{
- ProgramData &shdata = obj.get_shader_data();
-
- if(uni.size==1)
- shdata.uniform(name, uni.values[0]);
- else if(uni.size==2)
- shdata.uniform2(name, uni.values);
- else if(uni.size==2)
- shdata.uniform3(name, uni.values);
- else if(uni.size==4)
- shdata.uniform4(name, uni.values);
-}
-
-
-AnimationPlayer::PlayingAnimation::PlayingAnimation(const Animation &a):
- animation(&a),
- iterator(*animation)
-{ }
-
-
-AnimationPlayer::Target::Target(Placeable &p):
- placeable(p),
- object(0),
- armature(0),
- stacked(false)
-{ }
-
-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(&placeable, name, value);
-}
-
-} // namespace GL
-} // namespace Msp