]> git.tdb.fi Git - libs/gl.git/blob - source/animationplayer.cpp
Additional overloads for creating pipelines
[libs/gl.git] / source / animationplayer.cpp
1 #include <msp/core/algorithm.h>
2 #include "animatedobject.h"
3 #include "animationplayer.h"
4 #include "armature.h"
5 #include "programdata.h"
6
7 using namespace std;
8
9 namespace Msp {
10 namespace GL {
11
12 AnimationPlayer::Target &AnimationPlayer::get_slot(AnimatedObject &obj)
13 {
14         ObjectMap::iterator i = objects.find(&obj);
15         if(i!=objects.end())
16                 return i->second;
17
18         return objects.insert(ObjectMap::value_type(&obj, Target(obj))).first->second;
19 }
20
21 void AnimationPlayer::play(AnimatedObject &obj, const Animation &anim)
22 {
23         Target &target = get_slot(obj);
24         target.animations.clear();
25         target.base_matrix = Matrix();
26         target.stacked = false;
27         target.armature = anim.get_armature();
28         target.animations.push_back(PlayingAnimation(anim));
29 }
30
31 void AnimationPlayer::play_stacked(AnimatedObject &obj, const Animation &anim)
32 {
33         Target &target = get_slot(obj);
34         if(target.animations.empty())
35                 target.base_matrix = *obj.get_matrix();
36         // TODO check for incompatible armature
37         target.stacked = true;
38         target.armature = anim.get_armature();
39         target.animations.push_back(PlayingAnimation(anim));
40 }
41
42 unsigned AnimationPlayer::get_n_active_animations(const AnimatedObject &obj) const
43 {
44         ObjectMap::const_iterator i = objects.find(&obj);
45         return (i!=objects.end() ? i->second.animations.size() : 0);
46 }
47
48 void AnimationPlayer::observe_events(AnimatedObject &obj, AnimationEventObserver &observer)
49 {
50         Target &target = get_slot(obj);
51         if(find(target.event_observers, &observer)==target.event_observers.end())
52                 target.event_observers.push_back(&observer);
53 }
54
55 void AnimationPlayer::unobserve_events(AnimatedObject &obj, AnimationEventObserver &observer)
56 {
57         ObjectMap::iterator i = objects.find(&obj);
58         if(i==objects.end())
59                 return;
60
61         vector<AnimationEventObserver *>::iterator j = find(i->second.event_observers, &observer);
62         if(j!=i->second.event_observers.end())
63                 i->second.event_observers.erase(j);
64 }
65
66 void AnimationPlayer::unobserve_events(AnimationEventObserver &observer)
67 {
68         for(ObjectMap::iterator i=objects.begin(); i!=objects.end(); ++i)
69         {
70                 vector<AnimationEventObserver *>::iterator j = find(i->second.event_observers, &observer);
71                 if(j!=i->second.event_observers.end())
72                         i->second.event_observers.erase(j);
73         }
74 }
75
76 void AnimationPlayer::stop(AnimatedObject &obj)
77 {
78         objects.erase(&obj);
79 }
80
81 void AnimationPlayer::stop(AnimatedObject &obj, const Animation &anim)
82 {
83         ObjectMap::iterator i = objects.find(&obj);
84         if(i==objects.end())
85                 return;
86
87         for(vector<PlayingAnimation>::iterator j=i->second.animations.begin(); j!=i->second.animations.end(); ++j)
88                 if(j->animation==&anim)
89                 {
90                         i->second.animations.erase(j);
91                         break;
92                 }
93
94         if(i->second.animations.empty())
95                 objects.erase(i);
96 }
97
98 void AnimationPlayer::tick(const Time::TimeDelta &dt)
99 {
100         for(ObjectMap::iterator i=objects.begin(); i!=objects.end(); )
101         {
102                 if(i->second.stacked)
103                         tick_stacked(i->second, dt);
104                 else if(!i->second.animations.empty())
105                         tick_single(i->second, dt);
106
107                 if(i->second.animations.empty() && i->second.event_observers.empty())
108                         objects.erase(i++);
109                 else
110                         ++i;
111         }
112 }
113
114 void AnimationPlayer::tick_single(Target &target, const Time::TimeDelta &dt)
115 {
116         PlayingAnimation &anim = target.animations.front();
117         anim.iterator += dt;
118         target.object.set_matrix(anim.iterator.get_matrix());
119
120         unsigned n_uniforms = anim.animation->get_n_uniforms();
121         for(unsigned i=0; i<n_uniforms; ++i)
122                 set_object_uniform(target.object, anim.animation->get_uniform_name(i), anim.iterator.get_uniform(i));
123
124         if(target.armature)
125         {
126                 unsigned max_index = target.armature->get_max_link_index();
127                 for(unsigned i=0; i<=max_index; ++i)
128                         target.object.set_pose_matrix(i, anim.iterator.get_pose_matrix(i));
129         }
130
131         anim.iterator.dispatch_events(target);
132
133         if(anim.iterator.is_end())
134                 target.animations.clear();
135 }
136
137 void AnimationPlayer::tick_stacked(Target &target, const Time::TimeDelta &dt)
138 {
139         Matrix matrix = target.base_matrix;
140         for(vector<PlayingAnimation>::iterator i=target.animations.begin(); i!=target.animations.end(); ++i)
141         {
142                 i->iterator += dt;
143                 matrix *= i->iterator.get_matrix();
144
145                 unsigned n_uniforms = i->animation->get_n_uniforms();
146                 for(unsigned j=0; j<n_uniforms; ++j)
147                         set_object_uniform(target.object, i->animation->get_uniform_name(j), i->iterator.get_uniform(j));
148         }
149         target.object.set_matrix(matrix);
150
151         if(target.armature)
152         {
153                 unsigned max_index = target.armature->get_max_link_index();
154                 for(unsigned i=0; i<=max_index; ++i)
155                 {
156                         matrix = Matrix();
157                         /* XXX This is in all likelihood incorrect.  The stacking should be
158                         performed on local matrices. */
159                         for(vector<PlayingAnimation>::iterator j=target.animations.begin(); j!=target.animations.end(); ++j)
160                                 if(j->animation->get_armature())
161                                         matrix *= j->iterator.get_pose_matrix(i);
162                         target.object.set_pose_matrix(i, matrix);
163                 }
164         }
165
166         for(vector<PlayingAnimation>::iterator i=target.animations.begin(); i!=target.animations.end(); )
167         {
168                 i->iterator.dispatch_events(target);
169
170                 if(i->iterator.is_end())
171                         i = target.animations.erase(i);
172                 else
173                         ++i;
174         }
175
176         if(target.animations.empty())
177                 target.stacked = false;
178 }
179
180 void AnimationPlayer::set_object_uniform(AnimatedObject &obj, const string &name, const KeyFrame::AnimatedUniform &uni)
181 {
182         ProgramData &shdata = obj.get_shader_data();
183
184         if(uni.size==1)
185                 shdata.uniform(name, uni.values[0]);
186         else if(uni.size==2)
187                 shdata.uniform2(name, uni.values);
188         else if(uni.size==2)
189                 shdata.uniform3(name, uni.values);
190         else if(uni.size==4)
191                 shdata.uniform4(name, uni.values);
192 }
193
194
195 AnimationPlayer::PlayingAnimation::PlayingAnimation(const Animation &a):
196         animation(&a),
197         iterator(*animation)
198 { }
199
200
201 AnimationPlayer::Target::Target(AnimatedObject &o):
202         object(o),
203         armature(0),
204         stacked(false)
205 { }
206
207 void AnimationPlayer::Target::animation_event(AnimatedObject *, const string &name, const Variant &value)
208 {
209         for(vector<AnimationEventObserver *>::const_iterator i=event_observers.begin(); i!=event_observers.end(); ++i)
210                 (*i)->animation_event(&object, name, value);
211 }
212
213 } // namespace GL
214 } // namespace Msp