]> git.tdb.fi Git - libs/gl.git/blob - source/animationplayer.cpp
Add a function to stop a single animation
[libs/gl.git] / source / animationplayer.cpp
1 #include "animatedobject.h"
2 #include "animationplayer.h"
3 #include "armature.h"
4
5 using namespace std;
6
7 namespace Msp {
8 namespace GL {
9
10 AnimationPlayer::ObjectSlot &AnimationPlayer::get_slot(AnimatedObject &obj)
11 {
12         ObjectMap::iterator i = objects.find(&obj);
13         if(i!=objects.end())
14                 return i->second;
15
16         return objects.insert(ObjectMap::value_type(&obj, ObjectSlot(obj))).first->second;
17 }
18
19 void AnimationPlayer::play(AnimatedObject &obj, const Animation &anim)
20 {
21         ObjectSlot &obj_slot = get_slot(obj);
22         obj_slot.animations.clear();
23         obj_slot.base_matrix = Matrix();
24         obj_slot.stacked = false;
25         obj_slot.armature = anim.get_armature();
26         obj_slot.animations.push_back(AnimationSlot(anim));
27 }
28
29 void AnimationPlayer::play_stacked(AnimatedObject &obj, const Animation &anim)
30 {
31         ObjectSlot &obj_slot = get_slot(obj);
32         if(obj_slot.animations.empty())
33                 obj_slot.base_matrix = *obj.get_matrix();
34         // TODO check for incompatible armature
35         obj_slot.stacked = true;
36         obj_slot.armature = anim.get_armature();
37         obj_slot.animations.push_back(AnimationSlot(anim));
38 }
39
40 unsigned AnimationPlayer::get_n_active_animations(const AnimatedObject &obj) const
41 {
42         ObjectMap::const_iterator i = objects.find(&obj);
43         return (i!=objects.end() ? i->second.animations.size() : 0);
44 }
45
46 void AnimationPlayer::stop(AnimatedObject &obj)
47 {
48         objects.erase(&obj);
49 }
50
51 void AnimationPlayer::stop(AnimatedObject &obj, const Animation &anim)
52 {
53         ObjectMap::iterator i = objects.find(&obj);
54         if(i==objects.end())
55                 return;
56
57         for(AnimationList::iterator j=i->second.animations.begin(); j!=i->second.animations.end(); ++j)
58                 if(&j->animation==&anim)
59                 {
60                         i->second.animations.erase(j);
61                         break;
62                 }
63
64         if(i->second.animations.empty())
65                 objects.erase(i);
66 }
67
68 void AnimationPlayer::tick(const Time::TimeDelta &dt)
69 {
70         for(ObjectMap::iterator i=objects.begin(); i!=objects.end(); )
71         {
72                 bool keep = false;
73                 if(i->second.stacked)
74                         keep = tick_stacked(i->second, dt);
75                 else
76                         keep = tick_single(i->second, dt);
77
78                 if(!keep)
79                         objects.erase(i++);
80                 else
81                         ++i;
82         }
83 }
84
85 bool AnimationPlayer::tick_single(ObjectSlot &slot, const Time::TimeDelta &dt)
86 {
87         AnimatedObject &obj = slot.object;
88         AnimationSlot &anim = slot.animations.front();
89         anim.iterator += dt;
90         obj.set_matrix(anim.iterator.get_matrix());
91
92         unsigned n_uniforms = anim.animation.get_n_uniforms();
93         for(unsigned i=0; i<n_uniforms; ++i)
94                 obj.set_uniform(anim.animation.get_uniform_name(i), anim.iterator.get_uniform(i));
95
96         if(slot.armature)
97         {
98                 unsigned max_index = slot.armature->get_max_link_index();
99                 for(unsigned i=0; i<=max_index; ++i)
100                         obj.set_pose_matrix(i, anim.iterator.get_pose_matrix(i));
101         }
102
103         return !anim.iterator.is_end();
104 }
105
106 bool AnimationPlayer::tick_stacked(ObjectSlot &slot, const Time::TimeDelta &dt)
107 {
108         Matrix matrix = slot.base_matrix;
109         for(AnimationList::iterator i=slot.animations.begin(); i!=slot.animations.end(); ++i)
110         {
111                 i->iterator += dt;
112                 matrix *= i->iterator.get_matrix();
113
114                 unsigned n_uniforms = i->animation.get_n_uniforms();
115                 for(unsigned j=0; j<n_uniforms; ++j)
116                         slot.object.set_uniform(i->animation.get_uniform_name(j), i->iterator.get_uniform(j));
117         }
118         slot.object.set_matrix(matrix);
119
120         if(slot.armature)
121         {
122                 unsigned max_index = slot.armature->get_max_link_index();
123                 for(unsigned i=0; i<=max_index; ++i)
124                 {
125                         matrix = Matrix();
126                         /* XXX This is in all likelihood incorrect.  The stacking should be
127                         performed on local matrices. */
128                         for(AnimationList::iterator j=slot.animations.begin(); j!=slot.animations.end(); ++j)
129                                 if(j->animation.get_armature())
130                                         matrix *= j->iterator.get_pose_matrix(i);
131                         slot.object.set_pose_matrix(i, matrix);
132                 }
133         }
134
135         for(AnimationList::iterator i=slot.animations.begin(); i!=slot.animations.end(); )
136         {
137                 if(i->iterator.is_end())
138                         slot.animations.erase(i++);
139                 else
140                         ++i;
141         }
142
143         return !slot.animations.empty();
144 }
145
146
147 AnimationPlayer::ObjectSlot::ObjectSlot(AnimatedObject &o):
148         object(o),
149         armature(0),
150         stacked(false)
151 { }
152
153
154 AnimationPlayer::AnimationSlot::AnimationSlot(const Animation &a):
155         animation(a),
156         iterator(animation)
157 { }
158
159 } // namespace GL
160 } // namespace Msp