+ 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, float speed)
+{
+ 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, speed));
+ return target;
+}
+
+void AnimationPlayer::play(AnimatedObject &obj, const Animation &anim, float speed)
+{
+ Target &target = play_(obj, anim, false, speed);
+ target.object = &obj;
+}
+
+void AnimationPlayer::play(Placeable &obj, const Animation &anim, float speed)
+{
+ play_(obj, anim, false, speed);
+}
+
+void AnimationPlayer::play_stacked(AnimatedObject &obj, const Animation &anim, float speed)
+{
+ Target &target = play_(obj, anim, true, speed);
+ target.object = &obj;
+}
+
+void AnimationPlayer::play_stacked(Placeable &obj, const Animation &anim, float speed)
+{
+ play_(obj, anim, true, speed);
+}
+
+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(Placeable &obj)
+{
+ objects.erase(&obj);
+}
+
+void AnimationPlayer::stop(Placeable &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);