author | kergoth <kergoth> | 2002-01-25 22:14:26 (UTC) |
---|---|---|
committer | kergoth <kergoth> | 2002-01-25 22:14:26 (UTC) |
commit | 15318cad33835e4e2dc620d033e43cd930676cdd (patch) (unidiff) | |
tree | c2fa0399a2c47fda8e2cd0092c73a809d17f68eb /core/multimedia/opieplayer/libflash/program.cc | |
download | opie-15318cad33835e4e2dc620d033e43cd930676cdd.zip opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.gz opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.bz2 |
Initial revision
Diffstat (limited to 'core/multimedia/opieplayer/libflash/program.cc') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/multimedia/opieplayer/libflash/program.cc | 921 |
1 files changed, 921 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/libflash/program.cc b/core/multimedia/opieplayer/libflash/program.cc new file mode 100644 index 0000000..c6e8c0f --- a/dev/null +++ b/core/multimedia/opieplayer/libflash/program.cc | |||
@@ -0,0 +1,921 @@ | |||
1 | ///////////////////////////////////////////////////////////// | ||
2 | // Flash Plugin and Player | ||
3 | // Copyright (C) 1998,1999 Olivier Debon | ||
4 | // | ||
5 | // This program is free software; you can redistribute it and/or | ||
6 | // modify it under the terms of the GNU General Public License | ||
7 | // as published by the Free Software Foundation; either version 2 | ||
8 | // of the License, or (at your option) any later version. | ||
9 | // | ||
10 | // This program is distributed in the hope that it will be useful, | ||
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | // GNU General Public License for more details. | ||
14 | // | ||
15 | // You should have received a copy of the GNU General Public License | ||
16 | // along with this program; if not, write to the Free Software | ||
17 | // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | // | ||
19 | /////////////////////////////////////////////////////////////// | ||
20 | // Author : Olivier Debon <odebon@club-internet.fr> | ||
21 | // | ||
22 | |||
23 | #include "swf.h" | ||
24 | |||
25 | #define NOTHING 0x0 | ||
26 | #define WAKEUP 0x1 | ||
27 | #define GOTO 0x2 | ||
28 | #define REFRESH 0x4 | ||
29 | |||
30 | #ifdef RCSID | ||
31 | static char *rcsid = "$Id$"; | ||
32 | #endif | ||
33 | |||
34 | #define PRINT 0 | ||
35 | |||
36 | int debug = 0; | ||
37 | |||
38 | Program::Program(FlashMovie *movie, long n) | ||
39 | { | ||
40 | long f; | ||
41 | |||
42 | this->movie = movie; | ||
43 | |||
44 | totalFrames = 0; | ||
45 | |||
46 | dl = new DisplayList(movie); | ||
47 | if (dl == NULL) return; | ||
48 | frames = new Frame[n]; | ||
49 | if (frames == NULL) { | ||
50 | delete dl; | ||
51 | return; | ||
52 | } | ||
53 | |||
54 | nbFrames = 0; | ||
55 | totalFrames = n; | ||
56 | currentFrame = 0; | ||
57 | loadingFrame = 0; | ||
58 | movieWait = 1; | ||
59 | nextFrame = currentFrame; | ||
60 | for(f = 0; f < n; f++) | ||
61 | { | ||
62 | frames[f].controls = 0; | ||
63 | frames[f].label = NULL; | ||
64 | } | ||
65 | |||
66 | movieStatus = MoviePlay; | ||
67 | settings = 0; | ||
68 | } | ||
69 | |||
70 | Program::~Program() | ||
71 | { | ||
72 | int i; | ||
73 | Control *ctrl, *ctrl1; | ||
74 | |||
75 | delete dl; | ||
76 | |||
77 | if (frames != NULL) { | ||
78 | for(i=0;i<nbFrames;i++) { | ||
79 | ctrl = frames[i].controls; | ||
80 | if (frames[i].label) free(frames[i].label); | ||
81 | while (ctrl != NULL) { | ||
82 | ctrl1 = ctrl->next; | ||
83 | ctrl->next = NULL; | ||
84 | delete ctrl; | ||
85 | ctrl = ctrl1; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | delete[] frames; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | void | ||
94 | Program::validateLoadingFrame() | ||
95 | { | ||
96 | nbFrames = loadingFrame; | ||
97 | loadingFrame++; | ||
98 | movieWait = 0; | ||
99 | } | ||
100 | |||
101 | Frame* | ||
102 | Program::getFrames() | ||
103 | { | ||
104 | return frames; | ||
105 | } | ||
106 | |||
107 | long | ||
108 | Program::getNbFrames() | ||
109 | { | ||
110 | return nbFrames; | ||
111 | } | ||
112 | |||
113 | DisplayList * | ||
114 | Program::getDisplayList() | ||
115 | { | ||
116 | return dl; | ||
117 | } | ||
118 | |||
119 | long | ||
120 | Program::getCurrentFrame() | ||
121 | { | ||
122 | return currentFrame; | ||
123 | } | ||
124 | |||
125 | void | ||
126 | Program::setCurrentFrame(long n) | ||
127 | { | ||
128 | currentFrame = n; | ||
129 | nextFrame = n; | ||
130 | //refresh = 1; | ||
131 | } | ||
132 | |||
133 | void | ||
134 | Program::gotoFrame(GraphicDevice *gd, long frame) | ||
135 | { | ||
136 | long f; | ||
137 | |||
138 | //printf("GotoFrame %d (Current = %d)\n", frame, currentFrame); | ||
139 | dl->clearList(); | ||
140 | |||
141 | for(f=0; f <= frame; f++) { | ||
142 | runFrame(gd, 0, f, 0); | ||
143 | } | ||
144 | } | ||
145 | |||
146 | long | ||
147 | Program::runFrame(GraphicDevice *gd, SoundMixer *sm, long f, long action) | ||
148 | { | ||
149 | Control *ctrl; | ||
150 | Character*character; | ||
151 | Matrix *matrix; | ||
152 | Cxform *cxform; | ||
153 | long status = NOTHING; | ||
154 | long update = 0; | ||
155 | char *name; | ||
156 | |||
157 | #if PRINT&1 | ||
158 | if (action) printf("Prog %x (dl=%x): Frame N° %d/%d\n", this, this->dl, f, nbFrames-1); | ||
159 | #endif | ||
160 | movie->buttons_updated = 0; | ||
161 | |||
162 | for(ctrl = frames[f].controls; ctrl; ctrl = ctrl->next) | ||
163 | { | ||
164 | switch (ctrl->type) | ||
165 | { | ||
166 | case ctrlPlaceObject: | ||
167 | case ctrlPlaceObject2: | ||
168 | character = 0; | ||
169 | matrix = 0; | ||
170 | cxform = 0; | ||
171 | name = ""; | ||
172 | if (ctrl->flags & placeHasCharacter) { | ||
173 | character = ctrl->character; | ||
174 | } | ||
175 | if (ctrl->flags & placeHasMatrix) { | ||
176 | matrix = &ctrl->matrix; | ||
177 | } | ||
178 | if (ctrl->flags & placeHasColorXform) { | ||
179 | cxform = &ctrl->cxform; | ||
180 | } | ||
181 | if (ctrl->flags & placeHasName) { | ||
182 | name = ctrl->name; | ||
183 | } | ||
184 | if (!ctrl->clipDepth) {// Ignore | ||
185 | dl->placeObject(gd,character, ctrl->depth, matrix, cxform, name); | ||
186 | update = 1; | ||
187 | } | ||
188 | break; | ||
189 | case ctrlRemoveObject: | ||
190 | character = ctrl->character; | ||
191 | |||
192 | if (!character) break;// Should not happen | ||
193 | |||
194 | dl->removeObject(gd, character, ctrl->depth); | ||
195 | if (action) { | ||
196 | character->reset(); | ||
197 | update = 1; | ||
198 | } | ||
199 | break; | ||
200 | case ctrlRemoveObject2: | ||
201 | character = dl->removeObject(gd,NULL, ctrl->depth); | ||
202 | if (character && action) { | ||
203 | character->reset(); | ||
204 | update = 1; | ||
205 | } | ||
206 | break; | ||
207 | // Actions | ||
208 | case ctrlDoAction: | ||
209 | if (action) { | ||
210 | status = doAction(gd, ctrl->actionRecords, sm); | ||
211 | } | ||
212 | break; | ||
213 | case ctrlStartSound: | ||
214 | if (action && sm) { | ||
215 | sm->startSound( (Sound *)ctrl->character ); | ||
216 | } | ||
217 | break; | ||
218 | case ctrlStopSound: | ||
219 | if (action && sm) { | ||
220 | sm->stopSounds(); | ||
221 | } | ||
222 | break; | ||
223 | case ctrlBackgroundColor: | ||
224 | if (action) { | ||
225 | if (gd->setBackgroundColor(ctrl->color)) { | ||
226 | dl->bbox.xmin = -32768; | ||
227 | dl->bbox.ymin = -32768; | ||
228 | dl->bbox.xmax = 32768; | ||
229 | dl->bbox.ymax = 32768; | ||
230 | } | ||
231 | } | ||
232 | break; | ||
233 | } | ||
234 | } | ||
235 | if (movie->buttons_updated) { | ||
236 | dl->updateButtons(movie); | ||
237 | } | ||
238 | |||
239 | if (status & GOTO) { | ||
240 | if (nextFrame < nbFrames) { | ||
241 | gotoFrame(gd,nextFrame); | ||
242 | if (nextFrame != f) | ||
243 | if (movieStatus == MoviePaused) runFrame(gd,sm,nextFrame); | ||
244 | update = 1; | ||
245 | } | ||
246 | } | ||
247 | |||
248 | #if PRINT&1 | ||
249 | if (action) printf("Frame N° %d ready\n", f); | ||
250 | #endif | ||
251 | return update; | ||
252 | } | ||
253 | |||
254 | long | ||
255 | Program::nestedMovie(GraphicDevice *gd, SoundMixer *sm, Matrix *mat, Cxform *cxform) | ||
256 | { | ||
257 | if (movieStatus == MoviePlay) { | ||
258 | // Movie Beeing Played | ||
259 | advanceFrame(); | ||
260 | if (currentFrame == 0) { | ||
261 | dl->clearList(); | ||
262 | } | ||
263 | runFrame(gd, sm, currentFrame); | ||
264 | if (nbFrames == 1) { | ||
265 | pauseMovie(); | ||
266 | } | ||
267 | } | ||
268 | |||
269 | return (movieStatus == MoviePlay); | ||
270 | } | ||
271 | |||
272 | long | ||
273 | Program::processMovie(GraphicDevice *gd, SoundMixer *sm) | ||
274 | { | ||
275 | int wakeUp = 0; | ||
276 | |||
277 | #if PRINT&1 | ||
278 | printf("Prog %x (dl=%x): Current = %d Next = %d Wait = %d Status = %d\n", this, this->dl, currentFrame, nextFrame, movieWait, movieStatus); | ||
279 | #endif | ||
280 | |||
281 | if (movieStatus == MoviePlay && movieWait == 0) { | ||
282 | // Movie Beeing Played | ||
283 | advanceFrame(); | ||
284 | if (currentFrame == 0) { | ||
285 | dl->clearList(); | ||
286 | } | ||
287 | wakeUp |= runFrame(gd, sm, currentFrame); | ||
288 | wakeUp |= dl->updateSprites(); | ||
289 | if (nextFrame == nbFrames) { | ||
290 | if (nbFrames != totalFrames) { | ||
291 | movieWait = 1; | ||
292 | } else if ((settings & PLAYER_LOOP) == 0) { | ||
293 | pauseMovie(); | ||
294 | } | ||
295 | } | ||
296 | } else { | ||
297 | wakeUp |= dl->updateSprites(); | ||
298 | } | ||
299 | |||
300 | if (wakeUp) { | ||
301 | render = 1; | ||
302 | } | ||
303 | |||
304 | return (wakeUp || movieStatus == MoviePlay); | ||
305 | } | ||
306 | |||
307 | /* timer (ms) -1 = delete timer */ | ||
308 | void setFlashTimer(struct timeval *tv, int time_ms) | ||
309 | { | ||
310 | if (time_ms == -1) { | ||
311 | tv->tv_sec = -1; | ||
312 | } else { | ||
313 | gettimeofday(tv,0); | ||
314 | |||
315 | tv->tv_usec += time_ms*1000; | ||
316 | while (tv->tv_usec > 1000000) { | ||
317 | tv->tv_usec -= 1000000; | ||
318 | tv->tv_sec++; | ||
319 | } | ||
320 | } | ||
321 | } | ||
322 | |||
323 | int checkFlashTimer(struct timeval *tv) | ||
324 | { | ||
325 | struct timeval now; | ||
326 | |||
327 | if (tv->tv_sec == -1) return 0; | ||
328 | |||
329 | gettimeofday(&now,0); | ||
330 | return (now.tv_sec > tv->tv_sec || | ||
331 | (now.tv_sec == tv->tv_sec && now.tv_usec >= tv->tv_usec)); | ||
332 | } | ||
333 | |||
334 | /* bbox */ | ||
335 | typedef struct { | ||
336 | long x1,y1,x2,y2; | ||
337 | } ButtonBoundingBox; | ||
338 | |||
339 | |||
340 | static void button_bbox_func(void *id, long y, long start, long end) | ||
341 | { | ||
342 | ButtonBoundingBox *h = (ButtonBoundingBox *) id; | ||
343 | |||
344 | if (y < h->y1) h->y1 = y; | ||
345 | if (y > h->y2) h->y2 = y; | ||
346 | if (start < h->x1) h->x1 = start; | ||
347 | if (end > h->x2) h->x2 = end; | ||
348 | } | ||
349 | |||
350 | void computeBBox(FlashMovie *movie, Rect *rect, DisplayListEntry *e) | ||
351 | { | ||
352 | ButtonBoundingBox bb; | ||
353 | |||
354 | bb.x1 = LONG_MAX; | ||
355 | bb.y1 = LONG_MAX; | ||
356 | bb.x2 = LONG_MIN; | ||
357 | bb.y2 = LONG_MIN; | ||
358 | |||
359 | e->character->getRegion(movie->gd,&e->renderMatrix,&bb,button_bbox_func); | ||
360 | |||
361 | rect->xmin = bb.x1 / FRAC; | ||
362 | rect->xmax = bb.x2 / FRAC; | ||
363 | rect->ymin = bb.y1; | ||
364 | rect->ymax = bb.y2; | ||
365 | } | ||
366 | |||
367 | void transform_coords(long *x_ptr,long *y_ptr, long cx, long cy, long dx, long dy) | ||
368 | { | ||
369 | long x,y,x1,y1; | ||
370 | x = *x_ptr; | ||
371 | y = *y_ptr; | ||
372 | |||
373 | x -= cx; | ||
374 | y -= cy; | ||
375 | |||
376 | if (dx < 0) { | ||
377 | /* left */ | ||
378 | x1 = - x; | ||
379 | y1 = y; | ||
380 | } else if (dy < 0) { | ||
381 | /* up */ | ||
382 | y1 = x; | ||
383 | x1 = -y; | ||
384 | } else if (dy > 0) { | ||
385 | /* down */ | ||
386 | y1 = x; | ||
387 | x1 = y; | ||
388 | } else { | ||
389 | /* right */ | ||
390 | x1 = x; | ||
391 | y1 = y; | ||
392 | } | ||
393 | |||
394 | *x_ptr = x1; | ||
395 | *y_ptr = y1; | ||
396 | } | ||
397 | |||
398 | typedef struct { | ||
399 | FlashMovie *movie; | ||
400 | DisplayListEntry *emin,*cur_focus; | ||
401 | long dmin; | ||
402 | long w,cx,cy,dx,dy; | ||
403 | } ButtonFocus; | ||
404 | |||
405 | static int button_focus(void *opaque, Program *prg, DisplayListEntry *e) | ||
406 | { | ||
407 | ButtonFocus *h=(ButtonFocus *)opaque; | ||
408 | Rect rect; | ||
409 | long d,x,y; | ||
410 | |||
411 | if (e != h->cur_focus) { | ||
412 | computeBBox(h->movie,&rect,e); | ||
413 | x = (rect.xmin + rect.xmax) / 2; | ||
414 | y = (rect.ymin + rect.ymax) / 2; | ||
415 | |||
416 | /* transform the coords so that the angular sector is directed to the right */ | ||
417 | transform_coords(&x,&y,h->cx,h->cy,h->dx,h->dy); | ||
418 | |||
419 | /* inside it ? */ | ||
420 | if ( x >= 0 && | ||
421 | (y - x - h->w) <= 0 && | ||
422 | (y + x + h->w) >= 0) { | ||
423 | d = x*x + y*y; | ||
424 | |||
425 | if (d < h->dmin) { | ||
426 | h->dmin = d; | ||
427 | h->emin = e; | ||
428 | } | ||
429 | } | ||
430 | } | ||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | DisplayListEntry *moveFocus(FlashMovie *movie, long dx, long dy, | ||
435 | DisplayListEntry *cur_focus) | ||
436 | { | ||
437 | Rect cur_rect; | ||
438 | ButtonFocus h; | ||
439 | |||
440 | h.movie = movie; | ||
441 | h.dx = dx; | ||
442 | h.dy = dy; | ||
443 | |||
444 | computeBBox(movie,&cur_rect,cur_focus); | ||
445 | /* center */ | ||
446 | h.cx = (cur_rect.xmin + cur_rect.xmax) / 2; | ||
447 | h.cy = (cur_rect.ymin + cur_rect.ymax) / 2; | ||
448 | |||
449 | /* width/2 of the 45 degrees angular sector */ | ||
450 | if (dy != 0) { | ||
451 | /* for vertical displacement, we have a larger width */ | ||
452 | h.w = (cur_rect.xmax - cur_rect.xmin) / 2; | ||
453 | } else { | ||
454 | /* zero width for horizontal displacement */ | ||
455 | h.w = 0; | ||
456 | } | ||
457 | |||
458 | /* now we select the nearest button in the angular sector */ | ||
459 | h.dmin = LONG_MAX; | ||
460 | h.emin = NULL; | ||
461 | h.cur_focus = cur_focus; | ||
462 | |||
463 | exploreButtons(movie, &h, button_focus); | ||
464 | |||
465 | return h.emin; | ||
466 | } | ||
467 | |||
468 | static int button_newfocus(void *opaque, Program *prg, DisplayListEntry *e) | ||
469 | { | ||
470 | * (DisplayListEntry **)opaque = e; | ||
471 | return 2; | ||
472 | } | ||
473 | |||
474 | static int button_nextfocus(void *opaque, Program *prg, DisplayListEntry *e) | ||
475 | { | ||
476 | static int found = 0; | ||
477 | DisplayListEntry **focus; | ||
478 | |||
479 | focus = (DisplayListEntry **)opaque; | ||
480 | if (found) { | ||
481 | *focus = e; | ||
482 | found = 0; | ||
483 | return 2; | ||
484 | } | ||
485 | if (e == *focus) { | ||
486 | found = 1; | ||
487 | } | ||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | |||
492 | /* XXX: should not be here (one level upper) */ | ||
493 | long | ||
494 | Program::handleEvent(GraphicDevice *gd, SoundMixer *sm, FlashEvent *fe) | ||
495 | { | ||
496 | ActionRecord*action; | ||
497 | Program *prog; | ||
498 | long status = 0; | ||
499 | DisplayListEntry *cur_focus, *new_focus; | ||
500 | long dx,dy; | ||
501 | int refresh; | ||
502 | |||
503 | refresh = 0; | ||
504 | |||
505 | switch(fe->type) { | ||
506 | |||
507 | case FeKeyRelease: | ||
508 | if (movie->mouse_active == 0) { | ||
509 | |||
510 | if (movie->cur_focus) { | ||
511 | movie->cur_focus->owner->updateBoundingBox(movie->cur_focus); | ||
512 | movie->cur_focus->renderState = stateOver; | ||
513 | movie->cur_focus->owner->updateBoundingBox(movie->cur_focus); | ||
514 | } | ||
515 | } | ||
516 | break; | ||
517 | |||
518 | case FeKeyPress: | ||
519 | |||
520 | movie->mouse_active = 0; | ||
521 | |||
522 | /* find the button which has the focus */ | ||
523 | cur_focus = movie->cur_focus; | ||
524 | |||
525 | if (fe->key == FeKeyEnter) { | ||
526 | /* selection */ | ||
527 | if (cur_focus) { | ||
528 | /* select the button */ | ||
529 | cur_focus->owner->updateBoundingBox(cur_focus); | ||
530 | cur_focus->renderState = stateDown; | ||
531 | ((Button *)cur_focus->character)->updateButtonState(cur_focus); | ||
532 | cur_focus->owner->updateBoundingBox(cur_focus); | ||
533 | |||
534 | movie->scheduledEvent.type = FeKeyRelease; | ||
535 | movie->scheduledEvent.key = FeKeyEnter; | ||
536 | |||
537 | setFlashTimer(&movie->scheduledTime, 250); /* 250 ms down */ | ||
538 | } | ||
539 | } else { | ||
540 | /* displacement */ | ||
541 | |||
542 | if (cur_focus == NULL) { | ||
543 | /* no current focus : set one */ | ||
544 | exploreButtons(movie, &cur_focus, button_newfocus); | ||
545 | if (cur_focus) { | ||
546 | cur_focus->renderState = stateOver; | ||
547 | ((Button *)cur_focus->character)->updateButtonState(cur_focus); | ||
548 | cur_focus->owner->updateBoundingBox(cur_focus); | ||
549 | } | ||
550 | movie->cur_focus = cur_focus; | ||
551 | } else { | ||
552 | /* move the focus (test) */ | ||
553 | switch(fe->key) { | ||
554 | case FeKeyNext: | ||
555 | /* Next available */ | ||
556 | cur_focus->owner->updateBoundingBox(cur_focus); | ||
557 | cur_focus->renderState = stateUp; | ||
558 | ((Button *)cur_focus->character)->updateButtonState(cur_focus); | ||
559 | cur_focus->owner->updateBoundingBox(cur_focus); | ||
560 | exploreButtons(movie, &cur_focus, button_nextfocus); | ||
561 | if (cur_focus) { | ||
562 | cur_focus->renderState = stateOver; | ||
563 | ((Button *)cur_focus->character)->updateButtonState(cur_focus); | ||
564 | cur_focus->owner->updateBoundingBox(cur_focus); | ||
565 | } | ||
566 | movie->cur_focus = cur_focus; | ||
567 | dx = 0; | ||
568 | dy = 0; | ||
569 | break; | ||
570 | case FeKeyUp: | ||
571 | dx = 0; | ||
572 | dy = -1; | ||
573 | break; | ||
574 | case FeKeyDown: | ||
575 | dx = 0; | ||
576 | dy = 1; | ||
577 | break; | ||
578 | case FeKeyLeft: | ||
579 | dx = -1; | ||
580 | dy = 0; | ||
581 | break; | ||
582 | case FeKeyRight: | ||
583 | dx = 1; | ||
584 | dy = 0; | ||
585 | break; | ||
586 | default: | ||
587 | /* should not happen */ | ||
588 | dx = 0; | ||
589 | dy = 0; | ||
590 | break; | ||
591 | } | ||
592 | |||
593 | if (dx != 0 || dy != 0) { | ||
594 | |||
595 | new_focus = moveFocus(movie, dx, dy, cur_focus); | ||
596 | if (new_focus) { | ||
597 | cur_focus->owner->updateBoundingBox(cur_focus); | ||
598 | cur_focus->renderState = stateUp; | ||
599 | ((Button *)cur_focus->character)->updateButtonState(cur_focus); | ||
600 | cur_focus->owner->updateBoundingBox(cur_focus); | ||
601 | |||
602 | if (computeActions(movie, &prog, &action)) { | ||
603 | status |= prog->doAction(gd, action, sm); | ||
604 | } | ||
605 | |||
606 | new_focus->renderState = stateOver; | ||
607 | ((Button *)new_focus->character)->updateButtonState(new_focus); | ||
608 | movie->cur_focus = new_focus; | ||
609 | new_focus->owner->updateBoundingBox(new_focus); | ||
610 | } else { | ||
611 | return 0; | ||
612 | } | ||
613 | } | ||
614 | } | ||
615 | if (movie->cur_focus == NULL) return 0; | ||
616 | } | ||
617 | break; | ||
618 | |||
619 | case FeMouseMove: | ||
620 | movie->mouse_active = 1; | ||
621 | movie->mouse_x = fe->x * FRAC; | ||
622 | movie->mouse_y = fe->y * FRAC; | ||
623 | dl->updateButtons(movie); | ||
624 | break; | ||
625 | |||
626 | case FeButtonPress: | ||
627 | movie->mouse_active = 1; | ||
628 | movie->button_pressed = 1; | ||
629 | dl->updateButtons(movie); | ||
630 | break; | ||
631 | |||
632 | case FeButtonRelease: | ||
633 | movie->mouse_active = 1; | ||
634 | movie->button_pressed = 0; | ||
635 | dl->updateButtons(movie); | ||
636 | break; | ||
637 | |||
638 | default: | ||
639 | return 0; | ||
640 | } | ||
641 | |||
642 | if (computeActions(movie, &prog, &action)) { | ||
643 | status |= prog->doAction(gd, action, sm); | ||
644 | } | ||
645 | |||
646 | if (status & REFRESH) { | ||
647 | status |= WAKEUP; | ||
648 | refresh = 1; | ||
649 | } | ||
650 | if (status & GOTO) { | ||
651 | if (nextFrame < nbFrames) { | ||
652 | gotoFrame(gd, nextFrame); | ||
653 | if (movieStatus == MoviePaused) runFrame(gd,sm,nextFrame); | ||
654 | refresh = 1; | ||
655 | } | ||
656 | } | ||
657 | |||
658 | if (refresh) { | ||
659 | dl->updateSprites(); | ||
660 | render = 1; | ||
661 | } | ||
662 | return (refresh || movieStatus == MoviePlay); | ||
663 | } | ||
664 | |||
665 | long | ||
666 | Program::doAction(GraphicDevice *gd, ActionRecord *action, SoundMixer *sm) | ||
667 | { | ||
668 | long status = NOTHING; | ||
669 | long f; | ||
670 | char *target = ""; | ||
671 | long skip = 0; | ||
672 | |||
673 | while(action) | ||
674 | { | ||
675 | if (skip) skip--; | ||
676 | else | ||
677 | switch (action->action) | ||
678 | { | ||
679 | case ActionPlaySound: | ||
680 | #if PRINT&2 | ||
681 | printf("Prog %x : PlaySound\n", this); | ||
682 | #endif | ||
683 | if (sm) { | ||
684 | sm->startSound(action->sound); | ||
685 | } | ||
686 | status |= WAKEUP; | ||
687 | break; | ||
688 | case ActionRefresh: | ||
689 | #if PRINT&2 | ||
690 | printf("Prog %x : Refresh\n", this); | ||
691 | #endif | ||
692 | status |= REFRESH; | ||
693 | break; | ||
694 | case ActionGotoFrame: | ||
695 | #if PRINT&2 | ||
696 | printf("Prog %x : GotoFrame %d\n", this, action->frameIndex); | ||
697 | #endif | ||
698 | if (target[0] == 0) { | ||
699 | if (action->frameIndex < nbFrames) { | ||
700 | currentFrame = action->frameIndex; | ||
701 | pauseMovie(); | ||
702 | status |= WAKEUP|GOTO; | ||
703 | } | ||
704 | } | ||
705 | break; | ||
706 | case ActionGetURL: | ||
707 | #if PRINT&2 | ||
708 | printf("Prog %x : GetURL %s target = %s\n", this, action->url, action->target); | ||
709 | #endif | ||
710 | { | ||
711 | int len,level; | ||
712 | len = strlen(action->target); | ||
713 | |||
714 | if (len > 6 && memcmp(action->target,"_level", 6) == 0) { | ||
715 | level = atoi(action->target + 6); | ||
716 | loadNewSwf(movie, action->url, level); | ||
717 | } else { | ||
718 | if (movie->getUrl) { | ||
719 | movie->getUrl(action->url, action->target, movie->getUrlClientData); | ||
720 | } | ||
721 | } | ||
722 | } | ||
723 | break; | ||
724 | case ActionNextFrame: | ||
725 | nextFrame = currentFrame+1; | ||
726 | movieStatus = MoviePlay; | ||
727 | status |= WAKEUP; | ||
728 | break; | ||
729 | case ActionPrevFrame: | ||
730 | nextFrame = currentFrame-1; | ||
731 | status |= WAKEUP|GOTO; | ||
732 | break; | ||
733 | case ActionPlay: | ||
734 | #if PRINT&2 | ||
735 | printf("Prog %x : Play\n", this); | ||
736 | #endif | ||
737 | if (target[0] == 0) { | ||
738 | movieStatus = MoviePlay; | ||
739 | if ((status & GOTO) == 0) { | ||
740 | if (currentFrame == nextFrame) advanceFrame(); | ||
741 | } | ||
742 | status |= WAKEUP; | ||
743 | } | ||
744 | break; | ||
745 | case ActionStop: | ||
746 | #if PRINT&2 | ||
747 | printf("Prog %x : Stop\n", this); | ||
748 | #endif | ||
749 | if (target[0] == 0) { | ||
750 | movieStatus = MoviePaused; | ||
751 | nextFrame = currentFrame; | ||
752 | } | ||
753 | break; | ||
754 | case ActionToggleQuality: | ||
755 | break; | ||
756 | case ActionStopSounds: | ||
757 | if (sm) { | ||
758 | sm->stopSounds(); | ||
759 | } | ||
760 | break; | ||
761 | case ActionWaitForFrame: | ||
762 | if (action->frameIndex >= nbFrames) { | ||
763 | skip = action->skipCount; | ||
764 | } | ||
765 | break; | ||
766 | case ActionSetTarget: | ||
767 | #if PRINT&2 | ||
768 | printf("Prog %x : SetTarget '%s'\n", this, action->target); | ||
769 | #endif | ||
770 | target = action->target; | ||
771 | break; | ||
772 | case ActionGoToLabel: | ||
773 | #if PRINT&2 | ||
774 | printf("Prog %x : GotoFrame '%s'\n", this, action->frameLabel); | ||
775 | #endif | ||
776 | f = searchFrame(gd, action->frameLabel, target); | ||
777 | if (f >= 0) { | ||
778 | currentFrame = f; | ||
779 | pauseMovie(); | ||
780 | status |= WAKEUP|GOTO; | ||
781 | } else { | ||
782 | status |= REFRESH; | ||
783 | } | ||
784 | break; | ||
785 | } | ||
786 | action = action->next; | ||
787 | } | ||
788 | return status; | ||
789 | } | ||
790 | |||
791 | void | ||
792 | Program::setCurrentFrameLabel(char *label) | ||
793 | { | ||
794 | frames[loadingFrame].label = label; | ||
795 | } | ||
796 | |||
797 | void | ||
798 | Program::rewindMovie() | ||
799 | { | ||
800 | currentFrame = 0; | ||
801 | nextFrame = 0; | ||
802 | } | ||
803 | |||
804 | void | ||
805 | Program::pauseMovie() | ||
806 | { | ||
807 | movieStatus = MoviePaused; | ||
808 | nextFrame = currentFrame; | ||
809 | } | ||
810 | |||
811 | void | ||
812 | Program::continueMovie() | ||
813 | { | ||
814 | movieStatus = MoviePlay; | ||
815 | } | ||
816 | |||
817 | void | ||
818 | Program::nextStepMovie() | ||
819 | { | ||
820 | if (movieStatus == MoviePaused) { | ||
821 | advanceFrame(); | ||
822 | } | ||
823 | } | ||
824 | |||
825 | void | ||
826 | Program::advanceFrame() | ||
827 | { | ||
828 | currentFrame = nextFrame; | ||
829 | nextFrame = currentFrame+1; | ||
830 | if (currentFrame == nbFrames) { | ||
831 | currentFrame = 0; | ||
832 | nextFrame = 0; | ||
833 | movieStatus = MoviePlay; | ||
834 | } | ||
835 | } | ||
836 | |||
837 | void | ||
838 | Program::addControlInCurrentFrame(Control *ctrl) | ||
839 | { | ||
840 | Control *c; | ||
841 | |||
842 | ctrl->next = 0; | ||
843 | if (frames[loadingFrame].controls == 0) { | ||
844 | frames[loadingFrame].controls = ctrl; | ||
845 | } else { | ||
846 | for(c = frames[loadingFrame].controls; c->next; c = c->next); | ||
847 | c->next = ctrl; | ||
848 | } | ||
849 | } | ||
850 | |||
851 | void | ||
852 | Program::modifySettings(long flags) | ||
853 | { | ||
854 | settings = flags; | ||
855 | } | ||
856 | |||
857 | long | ||
858 | Program::searchFrame(GraphicDevice *gd, char *label, char *target) | ||
859 | { | ||
860 | long f; | ||
861 | DisplayListEntry *e; | ||
862 | Program *prg; | ||
863 | |||
864 | // Current movie | ||
865 | if (target[0] == 0) { | ||
866 | for(f=0; f < nbFrames; f++) | ||
867 | { | ||
868 | if (frames[f].label && !strcmp(label,frames[f].label)) { | ||
869 | return f; | ||
870 | } | ||
871 | } | ||
872 | } | ||
873 | |||
874 | // Kludge !!! | ||
875 | for (e = dl->list; e; e = e->next) { | ||
876 | if (e->character->isSprite()) { | ||
877 | prg = ((Sprite *)e->character)->program; | ||
878 | f = prg->searchFrame(gd,label,""); | ||
879 | if (f >= 0 && f < prg->nbFrames) { | ||
880 | prg->dl->updateBoundingBox(e); | ||
881 | prg->gotoFrame(gd, f); | ||
882 | prg->nextFrame = f; | ||
883 | prg->dl->updateBoundingBox(e); | ||
884 | return -1; | ||
885 | } | ||
886 | } | ||
887 | } | ||
888 | |||
889 | return -1; | ||
890 | } | ||
891 | |||
892 | void loadNewSwf(FlashMovie *movie, char *url, int level) | ||
893 | { | ||
894 | CInputScript *s,*prev,**l; | ||
895 | |||
896 | if (movie->getSwf == NULL) return; | ||
897 | |||
898 | for(s = movie->main, prev = 0; s != NULL; prev = s, s = s->next) { | ||
899 | if (s->level == level) { | ||
900 | // Mark movie to be deleted | ||
901 | s->level = -1; | ||
902 | break; | ||
903 | } | ||
904 | } | ||
905 | |||
906 | //printf("Unload movie @ %d\n", level); | ||
907 | |||
908 | if (*url == 0) return;// Just UnloadMovie | ||
909 | |||
910 | s = new CInputScript(level); | ||
911 | if (s == NULL) return; | ||
912 | |||
913 | /* insert it in the right order */ | ||
914 | l = &movie->main; | ||
915 | while (*l != NULL && (*l)->level < level) l = &(*l)->next; | ||
916 | s->next = *l; | ||
917 | *l = s; | ||
918 | |||
919 | // Notify the external loader of a new movie to load | ||
920 | movie->getSwf(url, level, movie->getSwfClientData); | ||
921 | } | ||