Mercurial > MadButterfly
comparison src/animate.c @ 48:bdf711cbf0fb
Use absolute time to dispatch animation actions.
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Sat, 09 Aug 2008 18:26:20 +0800 |
parents | f3818d996f4f |
children | c986e45c1e91 |
comparison
equal
deleted
inserted
replaced
47:f3818d996f4f | 48:bdf711cbf0fb |
---|---|
28 /*! \brief A word is a set of concurrent actions in a program. | 28 /*! \brief A word is a set of concurrent actions in a program. |
29 */ | 29 */ |
30 struct _mb_word { | 30 struct _mb_word { |
31 mb_timeval_t start_time; /*!< time to start the word */ | 31 mb_timeval_t start_time; /*!< time to start the word */ |
32 mb_timeval_t playing_time; /*!< time duration of playing */ | 32 mb_timeval_t playing_time; /*!< time duration of playing */ |
33 mb_timeval_t abs_start, abs_stop; | |
33 STAILQ(mb_action_t) actions; | 34 STAILQ(mb_action_t) actions; |
34 }; | 35 }; |
35 | 36 |
36 /*! \brief A program describe a series of actions to animate shapes. | 37 /*! \brief A program describe a series of actions to animate shapes. |
37 */ | 38 */ |
163 */ | 164 */ |
164 static void mb_progm_step(const mb_timeval_t *tmo, | 165 static void mb_progm_step(const mb_timeval_t *tmo, |
165 const mb_timeval_t *now, | 166 const mb_timeval_t *now, |
166 void *arg) { | 167 void *arg) { |
167 mb_progm_t *progm = (mb_progm_t *)arg; | 168 mb_progm_t *progm = (mb_progm_t *)arg; |
168 mb_timeval_t next_tmo, word_stop; | 169 mb_timeval_t next_tmo; |
169 mb_timeval_t tmo_diff, next_diff; | |
170 mb_word_t *word; | 170 mb_word_t *word; |
171 mb_timer_t *timer; | 171 mb_timer_t *timer; |
172 int i; | 172 int i; |
173 | 173 |
174 MB_TIMEVAL_CP(&tmo_diff, tmo); | 174 MB_TIMEVAL_SET(&next_tmo, 0, STEP_INTERVAL); |
175 MB_TIMEVAL_DIFF(&tmo_diff, &progm->start_time); | 175 MB_TIMEVAL_ADD(&next_tmo, tmo); |
176 | 176 |
177 MB_TIMEVAL_SET(&next_diff, 0, STEP_INTERVAL); | 177 /* _step() or _stop() words that in playing. */ |
178 MB_TIMEVAL_ADD(&next_diff, &tmo_diff); | |
179 | |
180 i = progm->first_playing; | 178 i = progm->first_playing; |
181 for(word = progm->words + i; | 179 for(word = progm->words + i; |
182 i < progm->n_words && | 180 i < progm->n_words && MB_TIMEVAL_LATER(tmo, &word->abs_start); |
183 MB_TIMEVAL_LATER(&tmo_diff, &word->start_time); | |
184 word = progm->words + ++i) { | 181 word = progm->words + ++i) { |
185 MB_TIMEVAL_CP(&word_stop, &word->start_time); | 182 if(MB_TIMEVAL_LATER(tmo, &word->abs_stop)) |
186 MB_TIMEVAL_ADD(&word_stop, &word->playing_time); | 183 continue; |
187 if(MB_TIMEVAL_LATER(&next_diff, &word_stop)) | 184 if(MB_TIMEVAL_LATER(&next_tmo, &word->abs_stop)) |
188 mb_word_stop(word, tmo, now, progm->rdman); | 185 mb_word_stop(word, tmo, now, progm->rdman); |
189 else | 186 else |
190 mb_word_step(word, tmo, now, progm->rdman); | 187 mb_word_step(word, tmo, now, progm->rdman); |
191 } | 188 } |
192 | 189 |
190 /* Start words that their abs_start is in duration | |
191 * from now to timeout for next update. | |
192 */ | |
193 for(word = progm->words + i; | 193 for(word = progm->words + i; |
194 i < progm->n_words && | 194 i < progm->n_words && MB_TIMEVAL_LATER(&next_tmo, &word->abs_start); |
195 MB_TIMEVAL_LATER(&next_diff, &word->start_time); | |
196 word = progm->words + ++i) { | 195 word = progm->words + ++i) { |
197 mb_word_start(word, tmo, now, progm->rdman); | 196 mb_word_start(word, tmo, now, progm->rdman); |
198 MB_TIMEVAL_CP(&word_stop, &word->start_time); | 197 if(MB_TIMEVAL_LATER(&next_tmo, &word->abs_stop)) |
199 MB_TIMEVAL_ADD(&word_stop, &word->playing_time); | |
200 if(MB_TIMEVAL_LATER(&next_diff, &word_stop)) | |
201 mb_word_stop(word, tmo, now, progm->rdman); | 198 mb_word_stop(word, tmo, now, progm->rdman); |
202 } | 199 } |
203 | 200 |
201 /* Find a new first_playing if any consequence words, following current | |
202 * first_playing word, are stoped. | |
203 */ | |
204 i = progm->first_playing; | 204 i = progm->first_playing; |
205 for(word = progm->words + i; | 205 for(word = progm->words + i; |
206 i < progm->n_words && | 206 i < progm->n_words && MB_TIMEVAL_LATER(&next_tmo, &word->abs_stop); |
207 MB_TIMEVAL_LATER(&next_diff, &word->start_time); | |
208 word = progm->words + ++i) { | 207 word = progm->words + ++i) { |
209 MB_TIMEVAL_CP(&word_stop, &word->start_time); | |
210 MB_TIMEVAL_ADD(&word_stop, &word->playing_time); | |
211 if(!MB_TIMEVAL_LATER(&next_diff, &word_stop)) | |
212 break; | |
213 progm->first_playing++; | 208 progm->first_playing++; |
214 } | 209 } |
215 | 210 |
211 /* Setup timeout for next update. */ | |
216 if(progm->first_playing < progm->n_words) { | 212 if(progm->first_playing < progm->n_words) { |
217 word = progm->words + progm->first_playing; | 213 word = progm->words + progm->first_playing; |
218 if(MB_TIMEVAL_LATER(&word->start_time, &next_diff)) { | 214 if(MB_TIMEVAL_LATER(&word->abs_start, &next_tmo)) |
219 MB_TIMEVAL_CP(&next_tmo, &word->start_time); | 215 MB_TIMEVAL_CP(&next_tmo, &word->abs_start); |
220 MB_TIMEVAL_ADD(&next_tmo, &progm->start_time); | |
221 } else { | |
222 MB_TIMEVAL_CP(&next_tmo, &next_diff); | |
223 MB_TIMEVAL_ADD(&next_tmo, &progm->start_time); | |
224 } | |
225 timer = mb_tman_timeout(progm->tman, &next_tmo, | 216 timer = mb_tman_timeout(progm->tman, &next_tmo, |
226 mb_progm_step, progm); | 217 mb_progm_step, progm); |
227 } | 218 } |
228 } | 219 } |
229 | 220 |
230 void mb_progm_start(mb_progm_t *progm, mb_tman_t *tman, | 221 void mb_progm_start(mb_progm_t *progm, mb_tman_t *tman, |
231 mb_timeval_t *now) { | 222 mb_timeval_t *now) { |
232 mb_timeval_t next_time; | |
233 mb_timer_t *timer; | 223 mb_timer_t *timer; |
224 mb_word_t *word; | |
225 int i; | |
234 | 226 |
235 if(progm->n_words == 0) | 227 if(progm->n_words == 0) |
236 return; | 228 return; |
237 | 229 |
238 progm->tman = tman; | 230 progm->tman = tman; |
239 MB_TIMEVAL_CP(&progm->start_time, now); | 231 MB_TIMEVAL_CP(&progm->start_time, now); |
240 progm->first_playing = 0; | 232 progm->first_playing = 0; |
241 | 233 |
242 MB_TIMEVAL_CP(&next_time, &progm->words[0].start_time); | 234 for(i = 0; i < progm->n_words; i++) { |
243 MB_TIMEVAL_ADD(&next_time, now); | 235 word = progm->words + i; |
244 if(!MB_TIMEVAL_LATER(&next_time, now)) { | 236 MB_TIMEVAL_CP(&word->abs_start, &word->start_time); |
245 mb_progm_step(&next_time, now, progm); | 237 MB_TIMEVAL_ADD(&word->abs_start, now); |
238 MB_TIMEVAL_CP(&word->abs_stop, &word->abs_start); | |
239 MB_TIMEVAL_ADD(&word->abs_stop, &word->playing_time); | |
240 } | |
241 | |
242 if(MB_TIMEVAL_EQ(&progm->words[0].abs_start, now)) { | |
243 mb_progm_step(now, now, progm); | |
246 return; | 244 return; |
247 } | 245 } |
248 | 246 |
249 timer = mb_tman_timeout(tman, &next_time, mb_progm_step, progm); | 247 timer = mb_tman_timeout(tman, &progm->words[0].abs_start, |
248 mb_progm_step, progm); | |
250 ASSERT(timer != NULL); | 249 ASSERT(timer != NULL); |
251 } | 250 } |
252 | 251 |
253 void mb_progm_abort(mb_progm_t *progm, mb_tman_t *tman) { | 252 void mb_progm_abort(mb_progm_t *progm, mb_tman_t *tman) { |
254 } | 253 } |