X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fanimationplayer.cpp;h=7c693ad2c3eef32ce7ec2a8aa74f4e754d130258;hp=9bcb5e5720872d006b28ac6f8a9c1dec7421c26b;hb=bf1f59c4dca6b651e39c126c63a0780b65a34927;hpb=164d77011ab4ebe76c9bf2b7ed8d8dd8ebc20e61 diff --git a/source/animationplayer.cpp b/source/animationplayer.cpp index 9bcb5e57..7c693ad2 100644 --- a/source/animationplayer.cpp +++ b/source/animationplayer.cpp @@ -1,43 +1,214 @@ +#include #include "animatedobject.h" #include "animationplayer.h" #include "armature.h" +#include "programdata.h" using namespace std; namespace Msp { namespace GL { +AnimationPlayer::Target &AnimationPlayer::get_slot(AnimatedObject &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; +} + void AnimationPlayer::play(AnimatedObject &obj, const Animation &anim) { - slots.push_back(Slot(obj, anim)); + Target &target = get_slot(obj); + target.animations.clear(); + target.base_matrix = Matrix(); + target.stacked = false; + target.armature = anim.get_armature(); + target.animations.push_back(PlayingAnimation(anim)); +} + +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)); +} + +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::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::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::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(list::iterator i=slots.begin(); i!=slots.end(); ) + 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.object.set_matrix(anim.iterator.get_matrix()); + + unsigned n_uniforms = anim.animation->get_n_uniforms(); + for(unsigned i=0; iget_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::iterator i=target.animations.begin(); i!=target.animations.end(); ++i) { i->iterator += dt; - i->object.set_matrix(i->iterator.get_matrix()); - if(const Armature *armature = i->animation.get_armature()) + matrix *= i->iterator.get_matrix(); + + unsigned n_uniforms = i->animation->get_n_uniforms(); + for(unsigned j=0; janimation->get_uniform_name(j), i->iterator.get_uniform(j)); + } + target.object.set_matrix(matrix); + + if(target.armature) + { + unsigned max_index = target.armature->get_max_link_index(); + for(unsigned i=0; i<=max_index; ++i) { - unsigned max_index = armature->get_max_link_index(); - for(unsigned j=0; j<=max_index; ++j) - i->object.set_pose_matrix(j, i->iterator.get_pose_matrix(j)); + matrix = Matrix(); + /* XXX This is in all likelihood incorrect. The stacking should be + performed on local matrices. */ + for(vector::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::iterator i=target.animations.begin(); i!=target.animations.end(); ) + { + i->iterator.dispatch_events(target); if(i->iterator.is_end()) - slots.erase(i++); + 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::Slot::Slot(AnimatedObject &o, const Animation &a): +AnimationPlayer::PlayingAnimation::PlayingAnimation(const Animation &a): + animation(&a), + iterator(*animation) +{ } + + +AnimationPlayer::Target::Target(AnimatedObject &o): object(o), - animation(a), - iterator(animation) + armature(0), + stacked(false) { } +void AnimationPlayer::Target::animation_event(AnimatedObject *, const string &name, const Variant &value) +{ + for(vector::const_iterator i=event_observers.begin(); i!=event_observers.end(); ++i) + (*i)->animation_event(&object, name, value); +} + } // namespace GL } // namespace Msp