Mercurial > MadButterfly
annotate src/animate.c @ 1160:1a699dc00fa3
Fix the issue of not removing node in old scene when switching scenes.
- When a timeline is playing and crossing two scenes (tween block),
nodes, for the old scene, in duplicate group must be removed. But,
it is not.
- It is fixed by checking if nodes, in the duplicate group, are also
in the key frame next to the new scene. All nodes that is not in
next key frame are remove.
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Tue, 28 Dec 2010 13:35:34 +0800 |
parents | 572277fcec0d |
children |
rev | line source |
---|---|
822
586e50f82c1f
Unify coding style tag for emacs and vim.
Shih-Yuan Lee (FourDollars) <fourdollars@gmail.com>
parents:
332
diff
changeset
|
1 // -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- |
586e50f82c1f
Unify coding style tag for emacs and vim.
Shih-Yuan Lee (FourDollars) <fourdollars@gmail.com>
parents:
332
diff
changeset
|
2 // vim: sw=4:ts=8:sts=4 |
111 | 3 /*! \file |
4 * \brief Animation tools. | |
5 * | |
117 | 6 * \sa \ref ani |
111 | 7 */ |
8 /*! \page ani What is Animation? | |
41 | 9 * |
117 | 10 * Animation is a program to move, resize, rotate, ..., changing |
11 * graphics on the output screen. | |
12 * | |
13 * \image html program.png | |
14 * | |
41 | 15 * XXX: Program is a sequence of actions duration a perior. |
16 * Actions are grouped into words. A program defines | |
17 * the order and time of playing of words. A word | |
18 * defines how long to perform a set of actions. Actions | |
19 * in a word are performed concurrently. | |
45 | 20 * |
21 * Animation shapes are updated periodically. Every action | |
22 * are working with start, step, and stop 3 calls. start is | |
23 * called when start time the word, contain it, due. step is | |
24 * called periodically in duration of playing time start at | |
25 * 'start time'. When the clock run out the playing time of | |
26 * a word, it call stop of actions in the word. | |
111 | 27 * |
28 * A program is driven by a timer. Once a program is started, it registers | |
1017
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
29 * with timer for periodic running. \ref mb_timer_man_t is timer of |
111 | 30 * MadButterfly. The update frequence is 10fps by default, now. |
31 * | |
117 | 32 * \section use_progm How to Use Animation Program? |
33 * Following code block creates a program with 2 words. First word is | |
34 * started immediately after the program been started. It is consisted | |
35 * for 1 second. Second word is started 1 second after the program been | |
36 * started. It is consisted for 2 seconds. There are 2 action in | |
37 * first word, they shift graphics managed by coord1 & coord2 by (50,50) and | |
38 * (-50,50) pixels, respectly. The shifting is performed incrementally | |
39 * in 1 second. Second word shifts coord1 and coord2, too. And, graphics | |
40 * managed by coord3 are hidden at end of the word. At end of code in the | |
41 * block, mb_progm_start() starts the program. 3rd argument of | |
42 * mb_progm_start() must be current wall time. | |
43 * | |
44 * \code | |
45 * progm = mb_progm_new(10, &rdman); | |
822
586e50f82c1f
Unify coding style tag for emacs and vim.
Shih-Yuan Lee (FourDollars) <fourdollars@gmail.com>
parents:
332
diff
changeset
|
46 * |
117 | 47 * MB_TIMEVAL_SET(&start, 0, 0); |
48 * MB_TIMEVAL_SET(&playing, 1, 0); | |
49 * word = mb_progm_next_word(progm, &start, &playing); | |
50 * | |
51 * act = mb_shift_new(50, 50, coord1, word); | |
52 * act = mb_shift_new(-50, 50, coord2, word); | |
53 * | |
54 * MB_TIMEVAL_SET(&start, 1, 0); | |
55 * MB_TIMEVAL_SET(&playing, 2, 0); | |
56 * word = mb_progm_next_word(progm, &start, &playing); | |
57 * | |
58 * act = mb_shift_new(0, 20, coord1, word); | |
59 * act = mb_shift_new(0, -20, coord2, word); | |
60 * act = mb_visibility_new(VIS_HIDDEN, coord3, word); | |
61 * | |
62 * gettimeofday(&tv, NULL); | |
63 * MB_TIMEVAL_SET(&mbtv, tv.tv_sec, tv.tv_usec); | |
1017
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
64 * mb_progm_start(progm, timer_man, &mbtv); |
117 | 65 * \endcode |
66 * | |
67 * | |
68 * \sa \ref animate.c | |
41 | 69 */ |
70 #include <stdio.h> | |
71 #include <stdlib.h> | |
72 #include <string.h> | |
186
530bb7728546
Move header files to $(top_srcdir)/include/ and prefixed with 'mb_'.
Thinker K.F. Li <thinker@branda.to>
parents:
185
diff
changeset
|
73 #include "mb_types.h" |
530bb7728546
Move header files to $(top_srcdir)/include/ and prefixed with 'mb_'.
Thinker K.F. Li <thinker@branda.to>
parents:
185
diff
changeset
|
74 #include "mb_redraw_man.h" |
530bb7728546
Move header files to $(top_srcdir)/include/ and prefixed with 'mb_'.
Thinker K.F. Li <thinker@branda.to>
parents:
185
diff
changeset
|
75 #include "mb_timer.h" |
530bb7728546
Move header files to $(top_srcdir)/include/ and prefixed with 'mb_'.
Thinker K.F. Li <thinker@branda.to>
parents:
185
diff
changeset
|
76 #include "mb_animate.h" |
41 | 77 |
78 | |
122
17e97e92b76e
Encapsulate X_MB_runtime_t and support X keyboard events.
Thinker K.F. Li <thinker@branda.to>
parents:
120
diff
changeset
|
79 #define STEP_INTERVAL 90000 |
41 | 80 #define ASSERT(x) |
81 | |
82 /*! \brief A word is a set of concurrent actions in a program. | |
83 */ | |
84 struct _mb_word { | |
85 mb_timeval_t start_time; /*!< time to start the word */ | |
86 mb_timeval_t playing_time; /*!< time duration of playing */ | |
48
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
87 mb_timeval_t abs_start, abs_stop; |
41 | 88 STAILQ(mb_action_t) actions; |
89 }; | |
90 | |
91 /*! \brief A program describe a series of actions to animate shapes. | |
51 | 92 * |
93 * first_playing is an index to one of words. It always points to | |
94 * the first of words that is playing or waiting for playing. | |
41 | 95 */ |
96 struct _mb_progm { | |
97 redraw_man_t *rdman; | |
98 | |
46 | 99 mb_timeval_t start_time; |
41 | 100 int first_playing; /*!< first playing word. */ |
1017
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
101 mb_timer_man_t *timer_man; |
123
9e2316dc6ecb
Program completion events
Thinker K.F. Li <thinker@branda.to>
parents:
122
diff
changeset
|
102 subject_t *complete; /*!< notify when a program is completed. */ |
1017
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
103 int cur_timer; |
41 | 104 |
105 int n_words; | |
106 int max_words; | |
107 mb_word_t words[1]; | |
108 }; | |
109 | |
119 | 110 /*! \brief Create a program object. |
111 * | |
112 * \param max_words is maximum number of words the program can hold. | |
113 * \param rdman is a rdman that show graphics manipulated by it. | |
114 */ | |
41 | 115 mb_progm_t *mb_progm_new(int max_words, redraw_man_t *rdman) { |
116 mb_progm_t *progm; | |
128
07dc9ec71221
Fix the problem that animate.c can not pass testcases
Thinker K.F. Li <thinker@branda.to>
parents:
124
diff
changeset
|
117 #ifndef UNITTEST |
1060
e415c55b4a0d
Stop using ob as acronym observer
Thinker K.F. Li <thinker@codemud.net>
parents:
1024
diff
changeset
|
118 observer_factory_t *factory; |
128
07dc9ec71221
Fix the problem that animate.c can not pass testcases
Thinker K.F. Li <thinker@branda.to>
parents:
124
diff
changeset
|
119 #endif /* UNITTEST */ |
41 | 120 int i; |
121 | |
122 progm = (mb_progm_t *)malloc(sizeof(mb_progm_t) + | |
123 (sizeof(mb_word_t) * (max_words - 1))); | |
124 if(progm == NULL) | |
125 return NULL; | |
126 | |
127 progm->rdman = rdman; | |
123
9e2316dc6ecb
Program completion events
Thinker K.F. Li <thinker@branda.to>
parents:
122
diff
changeset
|
128 |
128
07dc9ec71221
Fix the problem that animate.c can not pass testcases
Thinker K.F. Li <thinker@branda.to>
parents:
124
diff
changeset
|
129 #ifndef UNITTEST |
1060
e415c55b4a0d
Stop using ob as acronym observer
Thinker K.F. Li <thinker@codemud.net>
parents:
1024
diff
changeset
|
130 factory = rdman_get_observer_factory(rdman); |
123
9e2316dc6ecb
Program completion events
Thinker K.F. Li <thinker@branda.to>
parents:
122
diff
changeset
|
131 progm->complete = subject_new(factory, progm, OBJT_PROGM); |
194
45d9a1e2764d
Add mb_subtree_free animate action and fix bugs.
Thinker K.F. Li <thinker@branda.to>
parents:
192
diff
changeset
|
132 if(progm->complete == NULL) { |
45d9a1e2764d
Add mb_subtree_free animate action and fix bugs.
Thinker K.F. Li <thinker@branda.to>
parents:
192
diff
changeset
|
133 free(progm); |
45d9a1e2764d
Add mb_subtree_free animate action and fix bugs.
Thinker K.F. Li <thinker@branda.to>
parents:
192
diff
changeset
|
134 return NULL; |
45d9a1e2764d
Add mb_subtree_free animate action and fix bugs.
Thinker K.F. Li <thinker@branda.to>
parents:
192
diff
changeset
|
135 } |
128
07dc9ec71221
Fix the problem that animate.c can not pass testcases
Thinker K.F. Li <thinker@branda.to>
parents:
124
diff
changeset
|
136 #endif /* UNITTEST */ |
123
9e2316dc6ecb
Program completion events
Thinker K.F. Li <thinker@branda.to>
parents:
122
diff
changeset
|
137 |
41 | 138 progm->n_words = 0; |
139 progm->max_words = max_words; | |
140 for(i = 0; i < max_words; i++) | |
141 STAILQ_INIT(progm->words[i].actions); | |
1017
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
142 progm->cur_timer = -1; |
41 | 143 return progm; |
144 } | |
145 | |
146 void mb_progm_free(mb_progm_t *progm) { | |
147 int n_words; | |
148 mb_word_t *word; | |
149 mb_action_t *cur_act; | |
150 int i; | |
151 | |
152 n_words = progm->n_words; | |
153 for(i = 0; i < n_words; i++) { | |
154 word = progm->words + i; | |
155 for(cur_act = STAILQ_HEAD(word->actions); | |
156 cur_act != NULL; | |
157 cur_act = STAILQ_HEAD(word->actions)) { | |
158 STAILQ_REMOVE(word->actions, mb_action_t, next, cur_act); | |
159 cur_act->free(cur_act); | |
160 } | |
161 } | |
124
ad5ab8e61c2b
Free subject of complete when a program is freed
Thinker K.F. Li <thinker@branda.to>
parents:
123
diff
changeset
|
162 |
128
07dc9ec71221
Fix the problem that animate.c can not pass testcases
Thinker K.F. Li <thinker@branda.to>
parents:
124
diff
changeset
|
163 #ifndef UNITTEST |
192
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
164 subject_free(progm->complete); |
128
07dc9ec71221
Fix the problem that animate.c can not pass testcases
Thinker K.F. Li <thinker@branda.to>
parents:
124
diff
changeset
|
165 #endif /* UNITTEST */ |
124
ad5ab8e61c2b
Free subject of complete when a program is freed
Thinker K.F. Li <thinker@branda.to>
parents:
123
diff
changeset
|
166 |
41 | 167 free(progm); |
168 } | |
169 | |
170 /*! \brief Add a new word into a program. | |
171 * | |
172 * The start time of new word should bigger or equal to last one. | |
173 * The time should be specified in incremental order. | |
174 */ | |
175 mb_word_t *mb_progm_next_word(mb_progm_t *progm, | |
176 const mb_timeval_t *start, | |
177 const mb_timeval_t *playing) { | |
178 mb_word_t *word; | |
179 if(progm->n_words >= progm->max_words) | |
180 return NULL; | |
181 if(progm->n_words && | |
182 MB_TIMEVAL_LATER(&progm->words[progm->n_words - 1].start_time, start)) | |
183 return NULL; | |
184 word = progm->words + progm->n_words++; | |
43
6270230b9248
Use MB_TIMEVAL_CP() instead of memcpy
Thinker K.F. Li <thinker@branda.to>
parents:
42
diff
changeset
|
185 MB_TIMEVAL_CP(&word->start_time, start); |
6270230b9248
Use MB_TIMEVAL_CP() instead of memcpy
Thinker K.F. Li <thinker@branda.to>
parents:
42
diff
changeset
|
186 MB_TIMEVAL_CP(&word->playing_time, playing); |
41 | 187 return word; |
188 } | |
189 | |
116
1d74eb3861b7
move animation actions from animate.c to files.
Thinker K.F. Li <thinker@branda.to>
parents:
111
diff
changeset
|
190 void mb_word_add_action(mb_word_t *word, mb_action_t *act) { |
41 | 191 STAILQ_INS_TAIL(word->actions, mb_action_t, next, act); |
192 } | |
193 | |
194 static void mb_word_start(mb_word_t *word, const mb_timeval_t *tmo, | |
195 const mb_timeval_t *now, redraw_man_t *rdman) { | |
42 | 196 mb_action_t *act; |
197 | |
198 for(act = STAILQ_HEAD(word->actions); | |
199 act != NULL; | |
200 act = STAILQ_NEXT(mb_action_t, next, act)) { | |
201 act->start(act, tmo, &word->playing_time, rdman); | |
202 } | |
41 | 203 } |
204 | |
205 static void mb_word_step(mb_word_t *word, const mb_timeval_t *tmo, | |
206 const mb_timeval_t *now, redraw_man_t *rdman) { | |
42 | 207 mb_action_t *act; |
208 | |
209 for(act = STAILQ_HEAD(word->actions); | |
210 act != NULL; | |
211 act = STAILQ_NEXT(mb_action_t, next, act)) { | |
212 act->step(act, tmo, rdman); | |
213 } | |
41 | 214 } |
215 | |
216 static void mb_word_stop(mb_word_t *word, const mb_timeval_t *tmo, | |
217 const mb_timeval_t *now, redraw_man_t *rdman) { | |
42 | 218 mb_action_t *act; |
219 | |
220 for(act = STAILQ_HEAD(word->actions); | |
221 act != NULL; | |
222 act = STAILQ_NEXT(mb_action_t, next, act)) { | |
223 act->stop(act, tmo, rdman); | |
224 } | |
41 | 225 } |
226 | |
122
17e97e92b76e
Encapsulate X_MB_runtime_t and support X keyboard events.
Thinker K.F. Li <thinker@branda.to>
parents:
120
diff
changeset
|
227 /*! \brief Time stepping for a program. |
17e97e92b76e
Encapsulate X_MB_runtime_t and support X keyboard events.
Thinker K.F. Li <thinker@branda.to>
parents:
120
diff
changeset
|
228 * |
46 | 229 * Any two actions in concurrent words never change the same attribute. |
230 * Start time of words in a program are specified in incremental order. | |
122
17e97e92b76e
Encapsulate X_MB_runtime_t and support X keyboard events.
Thinker K.F. Li <thinker@branda.to>
parents:
120
diff
changeset
|
231 * |
17e97e92b76e
Encapsulate X_MB_runtime_t and support X keyboard events.
Thinker K.F. Li <thinker@branda.to>
parents:
120
diff
changeset
|
232 * \note Program will take a big step at last monent. It is because |
17e97e92b76e
Encapsulate X_MB_runtime_t and support X keyboard events.
Thinker K.F. Li <thinker@branda.to>
parents:
120
diff
changeset
|
233 * mb_progm_step() running mb_word_stop() if the word being stop |
17e97e92b76e
Encapsulate X_MB_runtime_t and support X keyboard events.
Thinker K.F. Li <thinker@branda.to>
parents:
120
diff
changeset
|
234 * between now and next_tmo. It is not obviously if time stepping |
17e97e92b76e
Encapsulate X_MB_runtime_t and support X keyboard events.
Thinker K.F. Li <thinker@branda.to>
parents:
120
diff
changeset
|
235 * small. |
46 | 236 */ |
1017
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
237 static void mb_progm_step(int timer_hdl, |
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
238 const mb_timeval_t *tmo, |
120 | 239 const mb_timeval_t *now, |
240 void *arg) { | |
41 | 241 mb_progm_t *progm = (mb_progm_t *)arg; |
128
07dc9ec71221
Fix the problem that animate.c can not pass testcases
Thinker K.F. Li <thinker@branda.to>
parents:
124
diff
changeset
|
242 #ifndef UNITTEST |
129
ba581d8a4b9b
Now, tank1 can be controlled by user with keyboard
Thinker K.F. Li <thinker@branda.to>
parents:
128
diff
changeset
|
243 /*! \todo Leverage aspective programming to prevent problem of unittest. |
ba581d8a4b9b
Now, tank1 can be controlled by user with keyboard
Thinker K.F. Li <thinker@branda.to>
parents:
128
diff
changeset
|
244 */ |
123
9e2316dc6ecb
Program completion events
Thinker K.F. Li <thinker@branda.to>
parents:
122
diff
changeset
|
245 mb_progm_complete_t comp_evt; |
128
07dc9ec71221
Fix the problem that animate.c can not pass testcases
Thinker K.F. Li <thinker@branda.to>
parents:
124
diff
changeset
|
246 #endif /* UNITTEST */ |
48
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
247 mb_timeval_t next_tmo; |
41 | 248 mb_word_t *word; |
1113
572277fcec0d
Fix waring of gcc for an typo on type name of variable
Thinker K.F. Li <thinker@codemud.net>
parents:
1060
diff
changeset
|
249 int timer; |
41 | 250 int i; |
251 | |
48
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
252 MB_TIMEVAL_SET(&next_tmo, 0, STEP_INTERVAL); |
120 | 253 MB_TIMEVAL_ADD(&next_tmo, now); |
41 | 254 |
48
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
255 /* _step() or _stop() words that in playing. */ |
41 | 256 i = progm->first_playing; |
257 for(word = progm->words + i; | |
48
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
258 i < progm->n_words && MB_TIMEVAL_LATER(tmo, &word->abs_start); |
41 | 259 word = progm->words + ++i) { |
48
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
260 if(MB_TIMEVAL_LATER(tmo, &word->abs_stop)) |
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
261 continue; |
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
262 if(MB_TIMEVAL_LATER(&next_tmo, &word->abs_stop)) |
46 | 263 mb_word_stop(word, tmo, now, progm->rdman); |
264 else | |
41 | 265 mb_word_step(word, tmo, now, progm->rdman); |
266 } | |
267 | |
48
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
268 /* Start words that their abs_start is in duration |
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
269 * from now to timeout for next update. |
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
270 */ |
41 | 271 for(word = progm->words + i; |
48
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
272 i < progm->n_words && MB_TIMEVAL_LATER(&next_tmo, &word->abs_start); |
41 | 273 word = progm->words + ++i) { |
274 mb_word_start(word, tmo, now, progm->rdman); | |
48
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
275 if(MB_TIMEVAL_LATER(&next_tmo, &word->abs_stop)) |
46 | 276 mb_word_stop(word, tmo, now, progm->rdman); |
41 | 277 } |
278 | |
48
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
279 /* Find a new first_playing if any consequence words, following current |
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
280 * first_playing word, are stoped. |
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
281 */ |
46 | 282 i = progm->first_playing; |
283 for(word = progm->words + i; | |
48
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
284 i < progm->n_words && MB_TIMEVAL_LATER(&next_tmo, &word->abs_stop); |
46 | 285 word = progm->words + ++i) { |
286 progm->first_playing++; | |
287 } | |
288 | |
48
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
289 /* Setup timeout for next update. */ |
41 | 290 if(progm->first_playing < progm->n_words) { |
42 | 291 word = progm->words + progm->first_playing; |
48
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
292 if(MB_TIMEVAL_LATER(&word->abs_start, &next_tmo)) |
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
293 MB_TIMEVAL_CP(&next_tmo, &word->abs_start); |
1017
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
294 timer = mb_timer_man_timeout(progm->timer_man, &next_tmo, |
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
295 mb_progm_step, progm); |
155
6749f6639924
Fix bug for STAILQ that fail to remove a node.
Thinker K.F. Li <thinker@branda.to>
parents:
153
diff
changeset
|
296 progm->cur_timer = timer; |
123
9e2316dc6ecb
Program completion events
Thinker K.F. Li <thinker@branda.to>
parents:
122
diff
changeset
|
297 } else { |
153
9870b049b7f6
Make mb_progm_abort() work.
Thinker K.F. Li <thinker@branda.to>
parents:
131
diff
changeset
|
298 /* Make program to complete. */ |
128
07dc9ec71221
Fix the problem that animate.c can not pass testcases
Thinker K.F. Li <thinker@branda.to>
parents:
124
diff
changeset
|
299 #ifndef UNITTEST |
123
9e2316dc6ecb
Program completion events
Thinker K.F. Li <thinker@branda.to>
parents:
122
diff
changeset
|
300 comp_evt.event.type = EVT_PROGM_COMPLETE; |
9e2316dc6ecb
Program completion events
Thinker K.F. Li <thinker@branda.to>
parents:
122
diff
changeset
|
301 comp_evt.event.tgt = comp_evt.event.cur_tgt = progm->complete; |
9e2316dc6ecb
Program completion events
Thinker K.F. Li <thinker@branda.to>
parents:
122
diff
changeset
|
302 comp_evt.progm = progm; |
192
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
303 subject_notify(progm->complete, &comp_evt.event); |
128
07dc9ec71221
Fix the problem that animate.c can not pass testcases
Thinker K.F. Li <thinker@branda.to>
parents:
124
diff
changeset
|
304 #endif /* UNITTEST */ |
1017
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
305 progm->cur_timer = -1; |
41 | 306 } |
307 } | |
308 | |
1017
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
309 void mb_progm_start(mb_progm_t *progm, mb_timer_man_t *timer_man, |
41 | 310 mb_timeval_t *now) { |
1017
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
311 int timer; |
48
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
312 mb_word_t *word; |
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
313 int i; |
41 | 314 |
315 if(progm->n_words == 0) | |
316 return; | |
317 | |
1017
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
318 progm->timer_man = timer_man; |
43
6270230b9248
Use MB_TIMEVAL_CP() instead of memcpy
Thinker K.F. Li <thinker@branda.to>
parents:
42
diff
changeset
|
319 MB_TIMEVAL_CP(&progm->start_time, now); |
41 | 320 progm->first_playing = 0; |
321 | |
48
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
322 for(i = 0; i < progm->n_words; i++) { |
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
323 word = progm->words + i; |
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
324 MB_TIMEVAL_CP(&word->abs_start, &word->start_time); |
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
325 MB_TIMEVAL_ADD(&word->abs_start, now); |
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
326 MB_TIMEVAL_CP(&word->abs_stop, &word->abs_start); |
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
327 MB_TIMEVAL_ADD(&word->abs_stop, &word->playing_time); |
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
328 } |
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
329 |
bdf711cbf0fb
Use absolute time to dispatch animation actions.
Thinker K.F. Li <thinker@branda.to>
parents:
47
diff
changeset
|
330 if(MB_TIMEVAL_EQ(&progm->words[0].abs_start, now)) { |
1017
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
331 mb_progm_step(-1, now, now, progm); |
41 | 332 return; |
333 } | |
822
586e50f82c1f
Unify coding style tag for emacs and vim.
Shih-Yuan Lee (FourDollars) <fourdollars@gmail.com>
parents:
332
diff
changeset
|
334 |
1017
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
335 timer = mb_timer_man_timeout(timer_man, &progm->words[0].abs_start, |
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
336 mb_progm_step, progm); |
1024
63f2f1daf5d3
X_main.c works with new backend definition
Thinker K.F. Li <thinker@codemud.net>
parents:
1020
diff
changeset
|
337 ASSERT(timer != -1); |
153
9870b049b7f6
Make mb_progm_abort() work.
Thinker K.F. Li <thinker@branda.to>
parents:
131
diff
changeset
|
338 |
9870b049b7f6
Make mb_progm_abort() work.
Thinker K.F. Li <thinker@branda.to>
parents:
131
diff
changeset
|
339 /* We need timer to abort it. */ |
9870b049b7f6
Make mb_progm_abort() work.
Thinker K.F. Li <thinker@branda.to>
parents:
131
diff
changeset
|
340 progm->cur_timer = timer; |
41 | 341 } |
342 | |
332
f90c60967a9c
Add mb_progm_finish to terminate the current animation and put all objects in the final position.
wycc
parents:
194
diff
changeset
|
343 void mb_progm_finish(mb_progm_t *progm) { |
f90c60967a9c
Add mb_progm_finish to terminate the current animation and put all objects in the final position.
wycc
parents:
194
diff
changeset
|
344 mb_timeval_t infi; |
f90c60967a9c
Add mb_progm_finish to terminate the current animation and put all objects in the final position.
wycc
parents:
194
diff
changeset
|
345 |
f90c60967a9c
Add mb_progm_finish to terminate the current animation and put all objects in the final position.
wycc
parents:
194
diff
changeset
|
346 mb_progm_abort(progm); |
f90c60967a9c
Add mb_progm_finish to terminate the current animation and put all objects in the final position.
wycc
parents:
194
diff
changeset
|
347 MB_TIMEVAL_SET(&infi, 0x7fffffff,0); |
1017
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
348 mb_progm_step(-1, &progm->start_time, &infi,progm); |
332
f90c60967a9c
Add mb_progm_finish to terminate the current animation and put all objects in the final position.
wycc
parents:
194
diff
changeset
|
349 } |
153
9870b049b7f6
Make mb_progm_abort() work.
Thinker K.F. Li <thinker@branda.to>
parents:
131
diff
changeset
|
350 void mb_progm_abort(mb_progm_t *progm) { |
131
6a8588df68af
Tank can change direction and navigate on the mud area
Thinker K.F. Li <thinker@branda.to>
parents:
129
diff
changeset
|
351 /*! \todo Make sure abort release resources. */ |
1017
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
352 if(progm->cur_timer != -1) { |
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
353 mb_timer_man_remove(progm->timer_man, progm->cur_timer); |
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
354 progm->cur_timer = -1; |
153
9870b049b7f6
Make mb_progm_abort() work.
Thinker K.F. Li <thinker@branda.to>
parents:
131
diff
changeset
|
355 } |
42 | 356 } |
357 | |
123
9e2316dc6ecb
Program completion events
Thinker K.F. Li <thinker@branda.to>
parents:
122
diff
changeset
|
358 /*! \brief Return event subject for completion of a program. |
9e2316dc6ecb
Program completion events
Thinker K.F. Li <thinker@branda.to>
parents:
122
diff
changeset
|
359 */ |
9e2316dc6ecb
Program completion events
Thinker K.F. Li <thinker@branda.to>
parents:
122
diff
changeset
|
360 subject_t *mb_progm_get_complete(mb_progm_t *progm) { |
9e2316dc6ecb
Program completion events
Thinker K.F. Li <thinker@branda.to>
parents:
122
diff
changeset
|
361 return progm->complete; |
9e2316dc6ecb
Program completion events
Thinker K.F. Li <thinker@branda.to>
parents:
122
diff
changeset
|
362 } |
9e2316dc6ecb
Program completion events
Thinker K.F. Li <thinker@branda.to>
parents:
122
diff
changeset
|
363 |
192
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
364 static void _free_completed_hdlr(event_t *event, void *arg) { |
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
365 mb_progm_t *progm = (mb_progm_t *)arg; |
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
366 |
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
367 mb_progm_free(progm); |
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
368 } |
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
369 |
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
370 /*! \brief The program should be freed after completed. */ |
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
371 void mb_progm_free_completed(mb_progm_t *progm) { |
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
372 subject_t *complete; |
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
373 |
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
374 complete = mb_progm_get_complete(progm); |
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
375 subject_add_observer(complete, _free_completed_hdlr, progm); |
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
376 } |
54fdc2a65242
Remove factory from observer APIs.
Thinker K.F. Li <thinker@branda.to>
parents:
186
diff
changeset
|
377 |
50 | 378 #ifdef UNITTEST |
379 | |
1019
1a3cc22ee1bd
Fix testcase of animate.c for mb_timer_man_t
Thinker K.F. Li <thinker@codemud.net>
parents:
1017
diff
changeset
|
380 #include "mb_backend_utils.h" |
50 | 381 #include <CUnit/Basic.h> |
382 | |
383 typedef struct _mb_dummy mb_dummy_t; | |
384 | |
385 struct _mb_dummy { | |
386 mb_action_t action; | |
387 int id; | |
388 int *logidx; | |
389 int *logs; | |
390 }; | |
391 | |
392 | |
393 static void mb_dummy_start(mb_action_t *act, | |
394 const mb_timeval_t *now, | |
395 const mb_timeval_t *playing_time, | |
396 redraw_man_t *rdman) { | |
397 mb_dummy_t *dummy = (mb_dummy_t *)act; | |
398 | |
399 dummy->logs[(*dummy->logidx)++] = dummy->id; | |
400 } | |
401 | |
402 static void mb_dummy_step(mb_action_t *act, | |
403 const mb_timeval_t *now, | |
404 redraw_man_t *rdman) { | |
405 mb_dummy_t *dummy = (mb_dummy_t *)act; | |
406 | |
407 dummy->logs[(*dummy->logidx)++] = dummy->id; | |
408 } | |
409 | |
410 static void mb_dummy_stop(mb_action_t *act, | |
411 const mb_timeval_t *now, | |
412 redraw_man_t *rdman) { | |
413 mb_dummy_t *dummy = (mb_dummy_t *)act; | |
414 | |
415 dummy->logs[(*dummy->logidx)++] = dummy->id; | |
416 } | |
417 | |
418 static void mb_dummy_free(mb_action_t *act) { | |
419 free(act); | |
420 } | |
421 | |
422 mb_action_t *mb_dummy_new(int id, int *logidx, int *logs, mb_word_t *word) { | |
423 mb_dummy_t *dummy; | |
424 | |
425 dummy = (mb_dummy_t *)malloc(sizeof(mb_dummy_t)); | |
426 if(dummy == NULL) | |
427 return NULL; | |
428 | |
429 dummy->id = id; | |
430 dummy->logidx = logidx; | |
431 dummy->logs = logs; | |
432 | |
433 dummy->action.start = mb_dummy_start; | |
434 dummy->action.step = mb_dummy_step; | |
435 dummy->action.stop = mb_dummy_stop; | |
436 dummy->action.free = mb_dummy_free; | |
437 | |
438 mb_word_add_action(word, (mb_action_t *)dummy); | |
439 | |
440 return (mb_action_t *)dummy; | |
441 } | |
442 | |
443 void test_animate_words(void) { | |
444 mb_progm_t *progm; | |
445 mb_word_t *word; | |
446 mb_action_t *acts[4]; | |
1017
9b5d4839c5bb
Use mb_timer_man_t instead of mb_tman_t.
Thinker K.F. Li <thinker@codemud.net>
parents:
822
diff
changeset
|
447 mb_timer_man_t *timer_man; |
1019
1a3cc22ee1bd
Fix testcase of animate.c for mb_timer_man_t
Thinker K.F. Li <thinker@codemud.net>
parents:
1017
diff
changeset
|
448 mb_tman_t *tman; |
50 | 449 mb_timeval_t tv1, tv2, now, tmo_after; |
450 int logcnt = 0; | |
451 int logs[256]; | |
452 int r; | |
453 | |
1019
1a3cc22ee1bd
Fix testcase of animate.c for mb_timer_man_t
Thinker K.F. Li <thinker@codemud.net>
parents:
1017
diff
changeset
|
454 timer_man = mb_timer_man_new(&tman_timer_factory); |
1020
f25b8ad338b4
Fix error on error checking for mb_timer_man_new()
Thinker K.F. Li <thinker@codemud.net>
parents:
1019
diff
changeset
|
455 CU_ASSERT(timer_man != -1); |
1019
1a3cc22ee1bd
Fix testcase of animate.c for mb_timer_man_t
Thinker K.F. Li <thinker@codemud.net>
parents:
1017
diff
changeset
|
456 |
1a3cc22ee1bd
Fix testcase of animate.c for mb_timer_man_t
Thinker K.F. Li <thinker@codemud.net>
parents:
1017
diff
changeset
|
457 tman = tman_timer_man_get_tman(timer_man); |
50 | 458 |
459 progm = mb_progm_new(3, NULL); | |
460 CU_ASSERT(progm != NULL); | |
461 | |
462 MB_TIMEVAL_SET(&tv1, 1, 0); | |
463 MB_TIMEVAL_SET(&tv2, 0, STEP_INTERVAL * 3); | |
464 word = mb_progm_next_word(progm, &tv1, &tv2); | |
465 CU_ASSERT(word != NULL); | |
466 acts[0] = mb_dummy_new(0, &logcnt, logs, word); | |
467 CU_ASSERT(acts[0] != NULL); | |
468 | |
469 MB_TIMEVAL_SET(&tv1, 1, STEP_INTERVAL * 4 / 3); | |
470 MB_TIMEVAL_SET(&tv2, 0, STEP_INTERVAL / 3); | |
471 word = mb_progm_next_word(progm, &tv1, &tv2); | |
472 CU_ASSERT(word != NULL); | |
473 acts[1] = mb_dummy_new(1, &logcnt, logs, word); | |
474 CU_ASSERT(acts[1] != NULL); | |
475 | |
476 MB_TIMEVAL_SET(&tv1, 1, STEP_INTERVAL * 2); | |
477 MB_TIMEVAL_SET(&tv2, 0, STEP_INTERVAL * 3); | |
478 word = mb_progm_next_word(progm, &tv1, &tv2); | |
479 CU_ASSERT(word != NULL); | |
480 acts[2] = mb_dummy_new(2, &logcnt, logs, word); | |
481 CU_ASSERT(acts[2] != NULL); | |
482 | |
483 MB_TIMEVAL_SET(&now, 0, 0); | |
1019
1a3cc22ee1bd
Fix testcase of animate.c for mb_timer_man_t
Thinker K.F. Li <thinker@codemud.net>
parents:
1017
diff
changeset
|
484 mb_progm_start(progm, timer_man, &now); |
50 | 485 |
486 r = mb_tman_next_timeout(tman, &now, &tmo_after); | |
487 CU_ASSERT(r == 0); | |
488 CU_ASSERT(MB_TIMEVAL_SEC(&tmo_after) == 1 && | |
489 MB_TIMEVAL_USEC(&tmo_after) == 0); | |
490 | |
491 /* 1.0s */ | |
492 MB_TIMEVAL_ADD(&now, &tmo_after); | |
493 mb_tman_handle_timeout(tman, &now); | |
494 CU_ASSERT(logcnt == 1); | |
495 | |
496 r = mb_tman_next_timeout(tman, &now, &tmo_after); | |
497 CU_ASSERT(r == 0); | |
498 CU_ASSERT(MB_TIMEVAL_SEC(&tmo_after) == 0 && | |
499 MB_TIMEVAL_USEC(&tmo_after) == STEP_INTERVAL); | |
822
586e50f82c1f
Unify coding style tag for emacs and vim.
Shih-Yuan Lee (FourDollars) <fourdollars@gmail.com>
parents:
332
diff
changeset
|
500 |
50 | 501 /* 1.1s */ |
502 MB_TIMEVAL_ADD(&now, &tmo_after); | |
503 mb_tman_handle_timeout(tman, &now); | |
504 CU_ASSERT(logcnt == 4); | |
505 | |
506 r = mb_tman_next_timeout(tman, &now, &tmo_after); | |
507 CU_ASSERT(r == 0); | |
508 CU_ASSERT(MB_TIMEVAL_SEC(&tmo_after) == 0 && | |
509 MB_TIMEVAL_USEC(&tmo_after) == STEP_INTERVAL); | |
822
586e50f82c1f
Unify coding style tag for emacs and vim.
Shih-Yuan Lee (FourDollars) <fourdollars@gmail.com>
parents:
332
diff
changeset
|
510 |
50 | 511 /* 1.2s */ |
512 MB_TIMEVAL_ADD(&now, &tmo_after); | |
513 mb_tman_handle_timeout(tman, &now); | |
514 CU_ASSERT(logcnt == 6); | |
515 | |
516 r = mb_tman_next_timeout(tman, &now, &tmo_after); | |
517 CU_ASSERT(r == 0); | |
518 CU_ASSERT(MB_TIMEVAL_SEC(&tmo_after) == 0 && | |
519 MB_TIMEVAL_USEC(&tmo_after) == STEP_INTERVAL); | |
822
586e50f82c1f
Unify coding style tag for emacs and vim.
Shih-Yuan Lee (FourDollars) <fourdollars@gmail.com>
parents:
332
diff
changeset
|
520 |
50 | 521 /* 1.3s */ |
522 MB_TIMEVAL_ADD(&now, &tmo_after); | |
523 mb_tman_handle_timeout(tman, &now); | |
524 CU_ASSERT(logcnt == 8); | |
525 | |
526 r = mb_tman_next_timeout(tman, &now, &tmo_after); | |
527 CU_ASSERT(r == 0); | |
528 CU_ASSERT(MB_TIMEVAL_SEC(&tmo_after) == 0 && | |
529 MB_TIMEVAL_USEC(&tmo_after) == STEP_INTERVAL); | |
822
586e50f82c1f
Unify coding style tag for emacs and vim.
Shih-Yuan Lee (FourDollars) <fourdollars@gmail.com>
parents:
332
diff
changeset
|
530 |
50 | 531 /* 1.4s */ |
532 MB_TIMEVAL_ADD(&now, &tmo_after); | |
533 mb_tman_handle_timeout(tman, &now); | |
534 CU_ASSERT(logcnt == 9); | |
535 | |
536 r = mb_tman_next_timeout(tman, &now, &tmo_after); | |
537 CU_ASSERT(r == 0); | |
538 CU_ASSERT(MB_TIMEVAL_SEC(&tmo_after) == 0 && | |
539 MB_TIMEVAL_USEC(&tmo_after) == STEP_INTERVAL); | |
822
586e50f82c1f
Unify coding style tag for emacs and vim.
Shih-Yuan Lee (FourDollars) <fourdollars@gmail.com>
parents:
332
diff
changeset
|
540 |
50 | 541 /* 1.5s */ |
542 MB_TIMEVAL_ADD(&now, &tmo_after); | |
543 mb_tman_handle_timeout(tman, &now); | |
544 CU_ASSERT(logcnt == 10); | |
545 | |
546 r = mb_tman_next_timeout(tman, &now, &tmo_after); | |
547 CU_ASSERT(r == -1); | |
548 | |
549 mb_progm_free(progm); | |
1019
1a3cc22ee1bd
Fix testcase of animate.c for mb_timer_man_t
Thinker K.F. Li <thinker@codemud.net>
parents:
1017
diff
changeset
|
550 mb_timer_man_free(&tman_timer_factory, timer_man); |
50 | 551 } |
552 | |
553 CU_pSuite get_animate_suite(void) { | |
554 CU_pSuite suite; | |
555 | |
556 suite = CU_add_suite("Suite_animate", NULL, NULL); | |
557 if(suite == NULL) | |
558 return NULL; | |
559 | |
560 CU_ADD_TEST(suite, test_animate_words); | |
822
586e50f82c1f
Unify coding style tag for emacs and vim.
Shih-Yuan Lee (FourDollars) <fourdollars@gmail.com>
parents:
332
diff
changeset
|
561 |
50 | 562 return suite; |
563 } | |
564 | |
565 #endif /* UNITTEST */ |