1 #if ! defined(PROG_DISABLE_GUI) && ! defined(PROG_DISABLE_BOB)
2
3 #include "declarations.h"
4 #include "widget_shr.h"
5 #include "bob.h"
6
7
8
9 /**
10 * @brief Get bob current altitude in pixels.
11 *
12 * @param[in] d Bob container id returned by bob_create_container()
13 * @param[in] e Bob id returned by bob_create()
14 *
15 * @retval Bob altitude in pixels
16 *
17 */
18
bob_get_altitude(unsigned int d,unsigned int e)19 unsigned int bob_get_altitude(unsigned int d, unsigned int e) {
20 struct b_bob *b;
21
22 if((b = bob_get_bob_by_id(d, e)) == NULL) return(0);
23
24 return(b->a);
25 }
26
27 /**
28 * @brief Set bob altitude in pixels.
29 *
30 * @param[in] d Bob container id returned by bob_create_container()
31 * @param[in] e Bob id returned by bob_create()
32 * @param[in] a Bob altitude in pixels
33 *
34 */
35
bob_set_altitude(unsigned int d,unsigned int e,unsigned int a)36 void bob_set_altitude(unsigned int d, unsigned int e, unsigned int a) {
37 struct b_bob *b;
38
39 if((b = bob_get_bob_by_id(d, e)) == NULL) return;
40
41 b->a = a;
42 }
43
44 /**
45 * @brief Add offset to bob altitude.
46 *
47 * @param[in] d Bob container id returned by bob_create_container()
48 * @param[in] e Bob id returned by bob_create()
49 * @param[in] a Pixels to add to current altitude
50 *
51 */
52
bob_add_altitude(unsigned int d,unsigned int e,int a)53 void bob_add_altitude(unsigned int d, unsigned int e, int a) {
54 struct b_bob *b;
55
56 if((b = bob_get_bob_by_id(d, e)) == NULL) return;
57
58 b->a += a;
59 }
60
61 /**
62 * @brief Subtract offset from bob altitude.
63 *
64 * @param[in] d Bob container id returned by bob_create_container()
65 * @param[in] e Bob id returned by bob_create()
66 * @param[in] a Pixels to subtract from current altitude
67 *
68 */
69
bob_sub_altitude(unsigned int d,unsigned int e,int a)70 void bob_sub_altitude(unsigned int d, unsigned int e, int a) {
71 struct b_bob *b;
72
73 if((b = bob_get_bob_by_id(d, e)) == NULL) return;
74
75 b->a -= a;
76 }
77
78 /**
79 * @brief Get bob current x position in pixels.
80 *
81 * @param[in] d Bob container id returned by bob_create_container()
82 * @param[in] e Bob id returned by bob_create()
83 *
84 * @retval Bob position in x axis
85 *
86 */
87
bob_get_x_position(unsigned int d,unsigned int e)88 int bob_get_x_position(unsigned int d, unsigned int e) {
89 struct b_bob *b;
90
91 if((b = bob_get_bob_by_id(d, e)) == NULL) return(0);
92
93 return(b->x);
94 }
95
96 /**
97 * @brief Get bob current y position in pixels.
98 *
99 * @param[in] d Bob container id returned by bob_create_container()
100 * @param[in] e Bob id returned by bob_create()
101 *
102 * @retval Bob position in y axis
103 *
104 */
105
bob_get_y_position(unsigned int d,unsigned int e)106 int bob_get_y_position(unsigned int d, unsigned int e) {
107 struct b_bob *b;
108
109 if((b = bob_get_bob_by_id(d, e)) == NULL) return(0);
110
111 return(b->y);
112 }
113
114 /**
115 * @brief Set bob position in pixels.
116 *
117 * @param[in] d Bob container id returned by bob_create_container()
118 * @param[in] e Bob id returned by bob_create()
119 * @param[in] x Bob position in x axis
120 * @param[in] y Bob position in y axis
121 *
122 */
123
bob_set_position(unsigned int d,unsigned int e,int x,int y)124 void bob_set_position(unsigned int d, unsigned int e, int x, int y) {
125 struct b_bob *b;
126
127 if((b = bob_get_bob_by_id(d, e)) == NULL) return;
128
129 b->x = x;
130 b->y = y;
131 }
132
133 /**
134 * @brief Set bob x position in pixels.
135 *
136 * @param[in] d Bob container id returned by bob_create_container()
137 * @param[in] e Bob id returned by bob_create()
138 * @param[in] x Bob position in x axis
139 *
140 */
141
bob_set_x_position(unsigned int d,unsigned int e,int x)142 void bob_set_x_position(unsigned int d, unsigned int e, int x) {
143 struct b_bob *b;
144
145 if((b = bob_get_bob_by_id(d, e)) == NULL) return;
146
147 b->x = x;
148 }
149
150 /**
151 * @brief Set bob y position in pixels.
152 *
153 * @param[in] d Bob container id returned by bob_create_container()
154 * @param[in] e Bob id returned by bob_create()
155 * @param[in] y Bob position in y axis
156 *
157 */
158
bob_set_y_position(unsigned int d,unsigned int e,int y)159 void bob_set_y_position(unsigned int d, unsigned int e, int y) {
160 struct b_bob *b;
161
162 if((b = bob_get_bob_by_id(d, e)) == NULL) return;
163
164 b->y = y;
165 }
166
167 /**
168 * @brief Add offset to bob x position.
169 *
170 * @param[in] d Bob container id returned by bob_create_container()
171 * @param[in] e Bob id returned by bob_create()
172 * @param[in] x Pixels to add to current x position
173 *
174 */
175
bob_add_x_position(unsigned int d,unsigned int e,int x)176 void bob_add_x_position(unsigned int d, unsigned int e, int x) {
177 struct b_bob *b;
178
179 if((b = bob_get_bob_by_id(d, e)) == NULL) return;
180
181 b->x += x;
182 }
183
184 /**
185 * @brief Add offset to bob y position.
186 *
187 * @param[in] d Bob container id returned by bob_create_container()
188 * @param[in] e Bob id returned by bob_create()
189 * @param[in] y Pixels to add to current y position
190 *
191 */
192
bob_add_y_position(unsigned int d,unsigned int e,int y)193 void bob_add_y_position(unsigned int d, unsigned int e, int y) {
194 struct b_bob *b;
195
196 if((b = bob_get_bob_by_id(d, e)) == NULL) return;
197
198 b->y += y;
199 }
200
201 /**
202 * @brief Subtract offset from bob x position.
203 *
204 * @param[in] d Bob container id returned by bob_create_container()
205 * @param[in] e Bob id returned by bob_create()
206 * @param[in] x Pixels to subtract from current x position
207 *
208 */
209
bob_sub_x_position(unsigned int d,unsigned int e,int x)210 void bob_sub_x_position(unsigned int d, unsigned int e, int x) {
211 struct b_bob *b;
212
213 if((b = bob_get_bob_by_id(d, e)) == NULL) return;
214
215 b->x -= x;
216 }
217
218 /**
219 * @brief Subtract offset from bob y position.
220 *
221 * @param[in] d Bob container id returned by bob_create_container()
222 * @param[in] e Bob id returned by bob_create()
223 * @param[in] y Pixels to subtract from current y position
224 *
225 */
226
bob_sub_y_position(unsigned int d,unsigned int e,int y)227 void bob_sub_y_position(unsigned int d, unsigned int e, int y) {
228 struct b_bob *b;
229
230 if((b = bob_get_bob_by_id(d, e)) == NULL) return;
231
232 b->y -= y;
233 }
234
235 /**
236 * @brief Get bob position angle.
237 *
238 * @param[in] d Bob container id returned by bob_create_container()
239 * @param[in] e Bob id returned by bob_create()
240 *
241 * @retval Bob position angle in degrees
242 *
243 */
244
bob_get_angle(unsigned int d,unsigned int e)245 double bob_get_angle(unsigned int d, unsigned int e) {
246 struct b_bob *b;
247
248 struct position a;
249
250 if((b = bob_get_bob_by_id(d, e)) == NULL) return(0.0);
251
252 a.x = b->x;
253 a.y = b->y;
254 a.z = 0.0;
255
256 return(coords_position_to_angle(&a));
257 }
258
259 /**
260 * @brief Set bob position in pixels by given angle and distance.
261 *
262 * @param[in] d Bob container id returned by bob_create_container()
263 * @param[in] e Bob id returned by bob_create()
264 * @param[in] a Angle in degrees
265 * @param[in] n Distance in pixels
266 *
267 */
268
bob_set_angle_position(unsigned int d,unsigned int e,double a,double n)269 void bob_set_angle_position(unsigned int d, unsigned int e, double a, double n) {
270 struct b_bob *b;
271
272 struct position p;
273
274 if((b = bob_get_bob_by_id(d, e)) == NULL) return;
275
276 (void) coords_angle_distance_to_position(a, n, &p);
277
278 b->x = (int) round(p.x);
279 b->y = (int) round(p.y);
280 }
281
282 /**
283 * @brief Get bob current depth in its container, aka drawing order.
284 *
285 * @param[in] d Bob container id returned by bob_create_container()
286 * @param[in] e Bob id returned by bob_create()
287 *
288 * @retval Bob drawing order in its container
289 *
290 */
291
bob_get_depth(unsigned int d,unsigned int e)292 int bob_get_depth(unsigned int d, unsigned int e) {
293 struct b_bob *b;
294
295 if((b = bob_get_bob_by_id(d, e)) == NULL) return(0);
296
297 return(b->z);
298 }
299
300 /**
301 * @brief Set bob depth in its container, aka drawing order.
302 *
303 * Bobs are drawn by starting from the lowest number to highest, ie. highest depth is the topmost.
304 *
305 * @param[in] d Bob container id returned by bob_create_container()
306 * @param[in] e Bob id returned by bob_create()
307 * @param[in] z Bob drawing order in its container
308 *
309 */
310
bob_set_depth(unsigned int d,unsigned int e,int z)311 void bob_set_depth(unsigned int d, unsigned int e, int z) {
312 struct b_bob *b;
313 struct b_bob_c *c;
314
315 if((b = bob_get_bob_by_id(d, e)) == NULL) return;
316 if((c = bob_get_container_by_id(d)) == NULL) return;
317
318 if(b->z == z) return;
319
320 /* Hold on a while if bobs are currently being processed */
321 while(b_lck == IS_YES) {
322 (void) timer_wait(0, TIMER_RESOLUTION_VERYFAST);
323 }
324
325 b_lck = IS_MAYBE;
326
327 b->z = z;
328
329 /* Sort bob array */
330 if(c->c > 1) {
331 (void) qsort((void *) c->b, (size_t) c->c, sizeof(struct b_bob *), bob_create_cmp);
332 }
333
334 b_lck = IS_NO;
335 }
336
337 /**
338 * @brief Get distance in pixels between two bobs.
339 *
340 * @param[in] d First bob container id returned by bob_create_container()
341 * @param[in] e First bob id returned by bob_create()
342 * @param[in] o Second bob container id returned by bob_create_container()
343 * @param[in] p Second bob id returned by bob_create()
344 *
345 * @retval Distance in pixels
346 *
347 */
348
bob_get_distance(unsigned int d,unsigned int e,unsigned int o,unsigned int p)349 unsigned int bob_get_distance(unsigned int d, unsigned int e, unsigned int o, unsigned int p) {
350 struct b_bob *b, *c;
351
352 struct position x, y;
353
354 if((b = bob_get_bob_by_id(d, e)) == NULL) return(0);
355 if((c = bob_get_bob_by_id(o, p)) == NULL) return(0);
356
357 x.x = (double) b->x;
358 x.y = (double) b->y;
359 x.z = 0.0;
360
361 y.x = (double) c->x;
362 y.y = (double) c->y;
363 y.z = 0.0;
364
365 return((unsigned int) round(coords_difference_2d(&x, &y)));
366 }
367
368 /**
369 * @brief Get distance in pixels between bob and given point.
370 *
371 * @param[in] d Bob container id returned by bob_create_container()
372 * @param[in] e Bob id returned by bob_create()
373 * @param[in] x Point x position in pixels
374 * @param[in] y Point y position in pixels
375 *
376 * @retval Distance in pixels
377 *
378 */
379
bob_get_measure(unsigned int d,unsigned int e,int x,int y)380 unsigned int bob_get_measure(unsigned int d, unsigned int e, int x, int y) {
381 struct b_bob *b;
382
383 struct position o, p;
384
385 if((b = bob_get_bob_by_id(d, e)) == NULL) return(0);
386
387 o.x = (double) x;
388 o.y = (double) y;
389 o.z = 0.0;
390
391 p.x = (double) b->x;
392 p.y = (double) b->y;
393 p.z = 0.0;
394
395 return((unsigned int) round(coords_difference_2d(&o, &p)));
396 }
397
398 /**
399 * @brief Get bob current mapping, aka visibility, state.
400 *
401 * @param[in] d Bob container id returned by bob_create_container()
402 * @param[in] e Bob id returned by bob_create()
403 *
404 * @retval Bob mapping state (IS_YES or IS_NO)
405 *
406 */
407
bob_get_map(unsigned int d,unsigned int e)408 unsigned int bob_get_map(unsigned int d, unsigned int e) {
409 struct b_bob *b;
410
411 if((b = bob_get_bob_by_id(d, e)) == NULL) return(0);
412
413 return(b->m);
414 }
415
416 /**
417 * @brief Set bob mapping, aka visibility, state.
418 *
419 * @param[in] d Bob container id returned by bob_create_container()
420 * @param[in] e Bob id returned by bob_create()
421 * @param[in] m Bob mapping state (IS_YES or IS_NO)
422 *
423 */
424
bob_set_map(unsigned int d,unsigned int e,unsigned int m)425 void bob_set_map(unsigned int d, unsigned int e, unsigned int m) {
426 struct b_bob *b;
427
428 if((b = bob_get_bob_by_id(d, e)) == NULL) return;
429
430 b->play.u = clock_get_ticks();
431
432 b->m = m;
433 }
434
435 /**
436 * @brief Get bob current play direction.
437 *
438 * @param[in] d Bob container id returned by bob_create_container()
439 * @param[in] e Bob id returned by bob_create()
440 *
441 * @retval Bob play direction (BOB_PLAY_DIRECTION_*)
442 *
443 */
444
bob_get_playdirection(unsigned int d,unsigned int e)445 unsigned int bob_get_playdirection(unsigned int d, unsigned int e) {
446 struct b_bob *b;
447
448 if((b = bob_get_bob_by_id(d, e)) == NULL) return(0);
449
450 return(b->play.n);
451 }
452
453 /**
454 * @brief Set bob play direction.
455 *
456 * @param[in] d Bob container id returned by bob_create_container()
457 * @param[in] e Bob id returned by bob_create()
458 * @param[in] n Bob play direction (BOB_PLAY_DIRECTION_*)
459 *
460 */
461
bob_set_playdirection(unsigned int d,unsigned int e,unsigned int n)462 void bob_set_playdirection(unsigned int d, unsigned int e, unsigned int n) {
463 struct b_bob *b;
464
465 if((b = bob_get_bob_by_id(d, e)) == NULL) return;
466
467 b->play.n = n;
468 }
469
470 /**
471 * @brief Get bob current play mode.
472 *
473 * @param[in] d Bob container id returned by bob_create_container()
474 * @param[in] e Bob id returned by bob_create()
475 *
476 * @retval Bob play mode (BOB_PLAY_MODE_*)
477 *
478 */
479
bob_get_playmode(unsigned int d,unsigned int e)480 unsigned int bob_get_playmode(unsigned int d, unsigned int e) {
481 struct b_bob *b;
482
483 if((b = bob_get_bob_by_id(d, e)) == NULL) return(0);
484
485 return(b->play.m);
486 }
487
488 /**
489 * @brief Set bob play mode.
490 *
491 * @param[in] d Bob container id returned by bob_create_container()
492 * @param[in] e Bob id returned by bob_create()
493 * @param[in] m Bob play mode (BOB_PLAY_MODE_*)
494 *
495 */
496
bob_set_playmode(unsigned int d,unsigned int e,unsigned int m)497 void bob_set_playmode(unsigned int d, unsigned int e, unsigned int m) {
498 struct b_bob *b;
499
500 if((b = bob_get_bob_by_id(d, e)) == NULL) return;
501
502 b->play.m = m;
503 }
504
505 /**
506 * @brief Get bob current frame skip in frames.
507 *
508 * @param[in] d Bob container id returned by bob_create_container()
509 * @param[in] e Bob id returned by bob_create()
510 *
511 * @retval Bob frame skip in frames
512 *
513 */
514
bob_get_playskip(unsigned int d,unsigned int e)515 unsigned int bob_get_playskip(unsigned int d, unsigned int e) {
516 struct b_bob *b;
517
518 if((b = bob_get_bob_by_id(d, e)) == NULL) return(0);
519
520 return(b->play.s);
521 }
522
523 /**
524 * @brief Set bob frame skip in frames.
525 *
526 * @param[in] d Bob container id returned by bob_create_container()
527 * @param[in] e Bob id returned by bob_create()
528 * @param[in] s Bob frame skip in frames
529 *
530 */
531
bob_set_playskip(unsigned int d,unsigned int e,unsigned int s)532 void bob_set_playskip(unsigned int d, unsigned int e, unsigned int s) {
533 struct b_bob *b;
534
535 if((b = bob_get_bob_by_id(d, e)) == NULL) return;
536
537 b->play.s = s;
538 }
539
540 /**
541 * @brief Get bob current play speed.
542 *
543 * @param[in] d Bob container id returned by bob_create_container()
544 * @param[in] e Bob id returned by bob_create()
545 *
546 * @retval Bob play speed as multiplier to one second
547 *
548 */
549
bob_get_playspeed(unsigned int d,unsigned int e)550 double bob_get_playspeed(unsigned int d, unsigned int e) {
551 struct b_bob *b;
552
553 if((b = bob_get_bob_by_id(d, e)) == NULL) return(0.0);
554
555 return(b->play.r);
556 }
557
558 /**
559 * @brief Set bob play speed.
560 *
561 * @param[in] d Bob container id returned by bob_create_container()
562 * @param[in] e Bob id returned by bob_create()
563 * @param[in] r Bob play speed as multiplier to one second
564 *
565 */
566
bob_set_playspeed(unsigned int d,unsigned int e,double r)567 void bob_set_playspeed(unsigned int d, unsigned int e, double r) {
568 struct b_bob *b;
569
570 if((b = bob_get_bob_by_id(d, e)) == NULL) return;
571
572 b->play.r = r;
573 }
574
575 /**
576 * @brief Set bob current frame to display.
577 *
578 * @param[in] d Bob container id returned by bob_create_container()
579 * @param[in] e Bob id returned by bob_create()
580 * @param[in] c Bob frame number to display
581 *
582 */
583
bob_set_frame(unsigned int d,unsigned int e,unsigned int c)584 void bob_set_frame(unsigned int d, unsigned int e, unsigned int c) {
585 struct b_bob *b;
586
587 if((b = bob_get_bob_by_id(d, e)) == NULL) return;
588
589 b->c = c;
590
591 (void) bob_set_frame_op(b);
592 }
593
594 /**
595 * @brief Add offset to bob frame to display.
596 *
597 * @param[in] d Bob container id returned by bob_create_container()
598 * @param[in] e Bob id returned by bob_create()
599 * @param[in] c Frames to add to current frame
600 *
601 */
602
bob_add_frame(unsigned int d,unsigned int e,int c)603 void bob_add_frame(unsigned int d, unsigned int e, int c) {
604 struct b_bob *b;
605
606 if((b = bob_get_bob_by_id(d, e)) == NULL) return;
607
608 b->c += c;
609
610 (void) bob_set_frame_op(b);
611 }
612
613 /**
614 * @brief Subtract offset from bob frame to display.
615 *
616 * @param[in] d Bob container id returned by bob_create_container()
617 * @param[in] e Bob id returned by bob_create()
618 * @param[in] c Frames to subtract from current frame
619 *
620 */
621
bob_sub_frame(unsigned int d,unsigned int e,int c)622 void bob_sub_frame(unsigned int d, unsigned int e, int c) {
623 struct b_bob *b;
624
625 if((b = bob_get_bob_by_id(d, e)) == NULL) return;
626
627 b->c -= c;
628
629 (void) bob_set_frame_op(b);
630 }
631
bob_set_frame_op(struct b_bob * b)632 static void bob_set_frame_op(struct b_bob *b) {
633 switch(b->play.m) {
634 case BOB_PLAY_MODE_MANUAL:
635 b->play.u = clock_get_ticks();
636
637 /* Handle possible frame overflow */
638 if(b->c >= b->data->c) b->c %= b->data->c;
639
640 break;
641 default:
642 break;
643 }
644 }
645
646 /**
647 * @brief Get bob container depth, aka drawing order.
648 *
649 * @param[in] d Bob container id returned by bob_create_container()
650 *
651 * @retval Bob container drawing order
652 *
653 */
654
bob_get_container_depth(unsigned int d)655 int bob_get_container_depth(unsigned int d) {
656 struct b_bob_c *c;
657
658 if((c = bob_get_container_by_id(d)) == NULL) return(0);
659
660 return(c->z);
661 }
662
663 /**
664 * @brief Set bob container depth, aka drawing order.
665 *
666 * Bob containers are drawn by starting from the lowest number to highest, ie. highest depth is the topmost.
667 *
668 * @param[in] d Bob container id returned by bob_create_container()
669 * @param[in] z Bob container drawing order
670 *
671 */
672
bob_set_container_depth(unsigned int d,int z)673 void bob_set_container_depth(unsigned int d, int z) {
674 struct b_bob_c *c;
675
676 if((c = bob_get_container_by_id(d)) == NULL) return;
677
678 if(c->z == z) return;
679
680 /* Hold on a while if bobs are currently being processed */
681 while(b_lck == IS_YES) {
682 (void) timer_wait(0, TIMER_RESOLUTION_VERYFAST);
683 }
684
685 b_lck = IS_MAYBE;
686
687 c->z = z;
688
689 /* Sort bob container array */
690 if(c_bob > 1) {
691 (void) qsort((void *) a_bob, (size_t) c_bob, sizeof(struct b_bob_c *), bob_create_container_cmp);
692 }
693
694 b_lck = IS_NO;
695 }
696
697 /**
698 * @brief Create new bob in given container.
699 *
700 * Initial visibility, aka mapping, for new bob is hidden. Use bob_set_map() to change visibility.
701 * Use positive value for drawing order to get bob on top of background.
702 *
703 * @param[in] f Bob file id returned by bob_init_[file|image]()
704 * @param[in] n Bob container id returned by bob_create_container()
705 * @param[in] a Bob initial altitude in pixels
706 * @param[in] x Bob initial position in x axis
707 * @param[in] y Bob initial position in y axis
708 * @param[in] z Bob initial depth in its container, aka drawing order
709 *
710 * @retval Bob id on success
711 * @retval Zero on failure
712 *
713 */
714
bob_create(unsigned int f,unsigned int n,unsigned int a,int x,int y,int z)715 unsigned int bob_create(unsigned int f, unsigned int n, unsigned int a, int x, int y, int z) {
716 struct b_bob_c *c;
717 struct b_bob **t;
718
719 if((c = bob_get_container_by_id(n)) == NULL) return(0);
720
721 APP_REALLOC_RET_VALUE(t, c->b, sizeof(struct b_bob *) * (c->c + 1), 0);
722 APP_MALLOC_RET_VALUE(c->b[c->c], sizeof(struct b_bob), 0);
723
724 (void) memset((void *) c->b[c->c], 0, sizeof(struct b_bob));
725
726 /* Hold on a while if bobs are currently being processed */
727 while(b_lck == IS_YES) {
728 (void) timer_wait(0, TIMER_RESOLUTION_VERYFAST);
729 }
730
731 b_lck = IS_MAYBE;
732
733 if(bob_create_op(f, c->b[c->c]) != 0) {
734 (void) free(c->b[c->c]);
735
736 c->b[c->c] = NULL;
737
738 b_lck = IS_NO;
739
740 return(0);
741 }
742
743 c->b[c->c]->d = ++c->p;
744
745 c->b[c->c]->m = IS_NO;
746
747 c->b[c->c]->o = 0;
748
749 c->b[c->c]->c = 0;
750
751 c->b[c->c]->a = a;
752 c->b[c->c]->x = x;
753 c->b[c->c]->y = y;
754 c->b[c->c]->z = z;
755
756 c->b[c->c]->play.n = BOB_PLAY_DIRECTION_NONE;
757 c->b[c->c]->play.m = BOB_PLAY_MODE_MANUAL;
758 c->b[c->c]->play.s = 0;
759
760 c->b[c->c]->play.r = BOB_UPDATE_RATE_DEFAULT;
761 c->b[c->c]->play.u = 0.0;
762
763 /* Sort bob array */
764 if(++c->c > 1) {
765 (void) qsort((void *) c->b, (size_t) c->c, sizeof(struct b_bob *), bob_create_cmp);
766 }
767
768 b_lck = IS_NO;
769
770 return(c->p);
771 }
772
bob_create_cmp(const void * a,const void * b)773 static int bob_create_cmp(const void *a, const void *b) {
774 const struct b_bob *c, *d;
775
776 c = *(const struct b_bob **) a;
777 d = *(const struct b_bob **) b;
778
779 return(c->z - d->z);
780 }
781
bob_create_op(unsigned int d,struct b_bob * b)782 static int bob_create_op(unsigned int d, struct b_bob *b) {
783 struct a_bob *a;
784
785 if((a = bob_get_file_by_id(d)) == NULL) return(-1);
786
787 b->data = a;
788
789 return(0);
790 }
791
792 /**
793 * @brief Create new background in given container.
794 *
795 * Initial visibility, aka mapping, for new background is hidden. Use bob_set_map() to change visibility.
796 * Use negative value for drawing order to get bobs on top of background.
797 *
798 * @param[in] f Bob file id returned by bob_init_[file|image]()
799 * @param[in] n Bob container id returned by bob_create_container()
800 * @param[in] o Background mode, non-zero for opaque or zero for translucent where alpha channel takes effect
801 * @param[in] z Background initial depth in its container, aka drawing order
802 *
803 * @retval Bob id on success
804 * @retval Zero on failure
805 *
806 */
807
bob_create_background(unsigned int f,unsigned int n,unsigned int o,int z)808 unsigned int bob_create_background(unsigned int f, unsigned int n, unsigned int o, int z) {
809 unsigned int d, w, h;
810
811 struct a_bob *a, *b;
812 struct b_bob_c *c;
813 struct b_bob **t;
814
815 if((c = bob_get_container_by_id(n)) == NULL) return(0);
816
817 if((w = window_get_active_width(c->h)) == 0 || (h = window_get_active_height(c->h)) == 0) {
818 return(0);
819 }
820
821 if((a = bob_get_file_by_id(f)) == NULL) return(0);
822
823 APP_REALLOC_RET_VALUE(t, c->b, sizeof(struct b_bob *) * (c->c + 1), 0);
824 APP_MALLOC_RET_VALUE(c->b[c->c], sizeof(struct b_bob), 0);
825
826 (void) memset((void *) c->b[c->c], 0, sizeof(struct b_bob));
827
828 /* Hold on a while if bobs are currently being processed */
829 while(b_lck == IS_YES) {
830 (void) timer_wait(0, TIMER_RESOLUTION_VERYFAST);
831 }
832
833 b_lck = IS_MAYBE;
834
835 if((d = bob_init_image(w, h)) == 0) return(0);
836
837 if((b = bob_create_background_at(c->b[c->c], d)) == NULL) {
838 (void) bob_free_image(d);
839 (void) free(c->b[c->c]);
840
841 c->b[c->c] = NULL;
842
843 b_lck = IS_NO;
844
845 return(0);
846 }
847
848 /* Fill background source image */
849 (void) bob_create_background_op(b->t_a.p, a->t_a.p,
850 h / a->t_a.h, w / a->t_a.w, h % a->t_a.h, w % a->t_a.w,
851 (unsigned int) a->t_a.w, (unsigned int) a->t_a.h, w);
852
853 c->b[c->c]->d = ++c->p;
854
855 c->b[c->c]->m = IS_NO;
856
857 c->b[c->c]->o = o;
858
859 c->b[c->c]->c = 0;
860
861 c->b[c->c]->a = 0;
862 c->b[c->c]->x = 0;
863 c->b[c->c]->y = 0;
864 c->b[c->c]->z = z;
865
866 c->b[c->c]->play.n = BOB_PLAY_DIRECTION_NONE;
867 c->b[c->c]->play.m = BOB_PLAY_MODE_MANUAL;
868 c->b[c->c]->play.s = 0;
869
870 c->b[c->c]->play.r = 0.0;
871 c->b[c->c]->play.u = 0.0;
872
873 /* Sort bob array */
874 if(++c->c > 1) {
875 (void) qsort((void *) c->b, (size_t) c->c, sizeof(struct b_bob *), bob_create_cmp);
876 }
877
878 b_lck = IS_NO;
879
880 return(c->p);
881 }
882
bob_create_background_at(struct b_bob * b,unsigned int d)883 static struct a_bob *bob_create_background_at(struct b_bob *b, unsigned int d) {
884 struct a_bob *a;
885
886 if((a = bob_get_file_by_id(d)) == NULL) return(NULL);
887
888 b->data = a;
889 b->data->i = d;
890
891 return(a);
892 }
893
bob_create_background_op(struct pixel_rgba_8 * p,struct pixel_rgba_8 * r,unsigned int a,unsigned int b,unsigned int e,unsigned int f,unsigned int w,unsigned int h,unsigned int q)894 static void bob_create_background_op(struct pixel_rgba_8 *p, struct pixel_rgba_8 *r, unsigned int a, unsigned int b, unsigned int e, unsigned int f, unsigned int w, unsigned int h, unsigned int q) {
895 unsigned int i, j;
896
897 for(i = 0; i < a; i++) {
898 /* Copy row of bobs to background if needed */
899 for(j = 0; j < b; j++) {
900 (void) bob_create_background_op_full(p, r, j, i, w, h, q);
901 }
902
903 /* Copy also partial bob at the end of the row if needed */
904 if(f != 0) (void) bob_create_background_op_part(p, r, j, i, f, h, w, h, q);
905 }
906
907 if(e != 0) {
908 /* Copy last partial line of bobs if needed */
909 for(j = 0; j < b; j++) {
910 (void) bob_create_background_op_part(p, r, j, a, w, e, w, h, q);
911 }
912
913 /* Copy also partial bob at the end of the last row if needed */
914 if(f != 0) (void) bob_create_background_op_part(p, r, j, a, f, e, w, h, q);
915 }
916 }
917
bob_create_background_op_full(struct pixel_rgba_8 * a,struct pixel_rgba_8 * r,unsigned int x,unsigned int y,unsigned int e,unsigned int f,unsigned int q)918 static void bob_create_background_op_full(struct pixel_rgba_8 *a, struct pixel_rgba_8 *r, unsigned int x, unsigned int y, unsigned int e, unsigned int f, unsigned int q) {
919 unsigned int i, j, k;
920
921 struct pixel_rgba_8 *b;
922
923 /* Adjust destination coordinate for tiling */
924 a += (y * f) * q;
925 a += (x * e);
926
927 for(i = 0; i < f; i++) {
928 b = a + (i * q);
929 k = i * e;
930
931 for(j = 0; j < e; j++) b[j].pixel.p = r[k + j].pixel.p;
932 }
933 }
934
bob_create_background_op_part(struct pixel_rgba_8 * a,struct pixel_rgba_8 * r,unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int e,unsigned int f,unsigned int q)935 static void bob_create_background_op_part(struct pixel_rgba_8 *a, struct pixel_rgba_8 *r, unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned int e, unsigned int f, unsigned int q) {
936 unsigned int i, j, k;
937
938 struct pixel_rgba_8 *b;
939
940 /* Adjust destination coordinate for tiling */
941 a += (y * f) * q;
942 a += (x * e);
943
944 for(i = 0; i < h; i++) {
945 b = a + (i * q);
946 k = i * e;
947
948 for(j = 0; j < w; j++) b[j].pixel.p = r[k + j].pixel.p;
949 }
950 }
951
952 /**
953 * @brief Create new bob container to host bobs.
954 *
955 * @param[in] h Window handle where to draw bobs created in this container
956 * @param[in] z Container initial depth, aka drawing order
957 *
958 * @retval Bob container id on success
959 * @retval Zero on failure
960 *
961 */
962
bob_create_container(unsigned int h,int z)963 unsigned int bob_create_container(unsigned int h, int z) {
964 if(c_bob >= BOB_CONTAINERS_MAX) {
965 (void) flush_error();
966
967 LOGWARN(
968 ERROR_SLIGHT, SUBSYSTEM,
969 _("Failed to create new container, pool has reached its maximum limit of %u entries"),
970 (unsigned int) BOB_CONTAINERS_MAX
971 );
972
973 return(0);
974 }
975
976 APP_MALLOC_RET_VALUE(a_bob[c_bob], sizeof(struct b_bob_c), 0);
977
978 (void) memset((void *) a_bob[c_bob], 0, sizeof(struct b_bob_c));
979
980 /* Hold on a while if bobs are currently being processed */
981 while(b_lck == IS_YES) {
982 (void) timer_wait(0, TIMER_RESOLUTION_VERYFAST);
983 }
984
985 b_lck = IS_MAYBE;
986
987 a_bob[c_bob]->d = ++d_bob;
988 a_bob[c_bob]->c = 0;
989 a_bob[c_bob]->p = 0;
990
991 a_bob[c_bob]->h = h;
992 a_bob[c_bob]->z = z;
993
994 a_bob[c_bob]->b = NULL;
995
996 /* Sort bob container array */
997 if(++c_bob > 1) {
998 (void) qsort((void *) a_bob, (size_t) c_bob, sizeof(struct b_bob_c *), bob_create_container_cmp);
999 }
1000
1001 b_lck = IS_NO;
1002
1003 /* Request drawing if this is first container */
1004 if(c_bob == 1) (void) bob_create_container_op();
1005
1006 return(d_bob);
1007 }
1008
bob_create_container_cmp(const void * a,const void * b)1009 static int bob_create_container_cmp(const void *a, const void *b) {
1010 const struct b_bob_c *c, *d;
1011
1012 c = *(const struct b_bob_c **) a;
1013 d = *(const struct b_bob_c **) b;
1014
1015 return(c->z - d->z);
1016 }
1017
bob_create_container_op(void)1018 static void bob_create_container_op(void) {
1019 struct w_cmd c;
1020
1021 c.c = WINDOW_COMMAND_BOBS;
1022 c.e = IS_YES;
1023 c.h = 0;
1024 c.p = (void *) a_bob;
1025 c.t = sizeof(c.p);
1026
1027 (void) window_cmd_push(&c);
1028 }
1029
1030 /**
1031 * @brief Delete bob from its container.
1032 *
1033 * When bob_delete() is called, bob is gone for good and cannot be used anymore.
1034 *
1035 * @param[in] d Bob container id returned by bob_create_container()
1036 * @param[in] e Bob id returned by bob_create()
1037 *
1038 */
1039
bob_delete(unsigned int d,unsigned int e)1040 void bob_delete(unsigned int d, unsigned int e) {
1041 unsigned int i;
1042
1043 size_t t;
1044
1045 struct b_bob *b;
1046 struct b_bob_c *c;
1047
1048 if((c = bob_get_container_by_id(d)) == NULL) return;
1049
1050 for(i = 0; i < c->c; i++) {
1051 if(c->b[i] == NULL || c->b[i]->d != e) continue;
1052
1053 /* Hold on a while if bobs are currently being processed */
1054 while(b_lck == IS_YES) {
1055 (void) timer_wait(0, TIMER_RESOLUTION_VERYFAST);
1056 }
1057
1058 b_lck = IS_MAYBE;
1059
1060 if((b = bob_get_bob_by_id(d, e)) != NULL) {
1061 /* Free also allocated image frame if this bob has one */
1062 if(b->data->i != 0) (void) bob_free_image(b->data->i);
1063
1064 (void) free(b);
1065 }
1066
1067 /* Compress bob array to get rid of deleted slot */
1068 if((t = (c->c - (i + 1)) * sizeof(struct b_bob *)) != 0) {
1069 (void) memmove(c->b + i, c->b + (i + 1), t);
1070 }
1071
1072 --c->c;
1073
1074 b_lck = IS_NO;
1075
1076 return;
1077 }
1078 }
1079
1080 /**
1081 * @brief Delete bob container and all bobs in it.
1082 *
1083 * When bob_delete_container() is called, container and all bobs in it are gone for good and cannot be used anymore.
1084 *
1085 * @param[in] d Bob container id returned by bob_create_container()
1086 *
1087 */
1088
bob_delete_container(unsigned int d)1089 void bob_delete_container(unsigned int d) {
1090 unsigned int i, j;
1091
1092 size_t t;
1093
1094 struct b_bob_c *c;
1095
1096 for(i = 0; i < c_bob; i++) {
1097 if(a_bob[i] == NULL || a_bob[i]->d != d) continue;
1098
1099 /* Hold on a while if bobs are currently being processed */
1100 while(b_lck == IS_YES) {
1101 (void) timer_wait(0, TIMER_RESOLUTION_VERYFAST);
1102 }
1103
1104 b_lck = IS_MAYBE;
1105
1106 c = a_bob[i];
1107
1108 if(c->b != NULL) {
1109 /* Free bobs in this container */
1110 for(j = 0; j < c->c; j++) {
1111 if(c->b[j] != NULL) (void) free(c->b[j]);
1112 }
1113
1114 (void) free(c->b);
1115 }
1116
1117 (void) free(c);
1118
1119 /* Compress bob container array to get rid of deleted slot */
1120 if(c_bob > 1) {
1121 if((t = (c_bob - (i + 1)) * sizeof(struct b_bob_c *)) != 0) {
1122 (void) memmove(a_bob + i, a_bob + (i + 1), t);
1123 }
1124 }
1125
1126 /* Remove permanent command from command pool if last container was deleted */
1127 if(--c_bob == 0) {
1128 (void) window_cmd_cancel_permanent(WINDOW_COMMAND_BOBS);
1129
1130 d_bob = 0;
1131 }
1132
1133 b_lck = IS_NO;
1134
1135 return;
1136 }
1137 }
1138
1139 /**
1140 * @brief Initialize bob image data from file.
1141 *
1142 * @param[in] a Bob image data file name
1143 *
1144 * @retval Bob file id on success
1145 * @retval Zero on failure
1146 *
1147 */
1148
bob_init_file(char * a)1149 unsigned int bob_init_file(char *a) {
1150 unsigned int i, d;
1151
1152 struct a_bob **t;
1153
1154 if(a == NULL) return(0);
1155
1156 /* Check if some slot can be reused */
1157 d = 0;
1158
1159 for(i = 0; i < c_fle; i++) {
1160 if(a_fle[i] == NULL) {
1161 d = i + 1;
1162
1163 break;
1164 }
1165 }
1166
1167 if(d == 0) {
1168 /* No free slot found, allocate one */
1169 APP_REALLOC_RET_VALUE(t, a_fle, sizeof(struct a_bob *) * (c_fle + 1), 0);
1170 APP_MALLOC_RET_VALUE(a_fle[c_fle], sizeof(struct a_bob), 0);
1171
1172 (void) memset((void *) a_fle[c_fle], 0, sizeof(struct a_bob));
1173
1174 d = ++c_fle;
1175 }
1176 else {
1177 /* Reuse existing slot */
1178 APP_MALLOC_RET_VALUE(a_fle[d - 1], sizeof(struct a_bob), 0);
1179
1180 (void) memset((void *) a_fle[d - 1], 0, sizeof(struct a_bob));
1181 }
1182
1183 a_fle[d - 1]->d = d;
1184 a_fle[d - 1]->i = 0;
1185
1186 /* Try to read and initialize the file */
1187 if((a_fle[d - 1]->f = bob_init_file_op(a, a_fle[d - 1], &a_fle[d - 1]->t_a, &a_fle[d - 1]->t_b)) == 0) {
1188 (void) free(a_fle[d - 1]);
1189
1190 a_fle[d - 1] = NULL;
1191
1192 return(0);
1193 }
1194
1195 return(d);
1196 }
1197
bob_init_file_op(char * a,struct a_bob * b,struct t_img * t_a,struct t_img * t_b)1198 static unsigned int bob_init_file_op(char *a, struct a_bob *b, struct t_img *t_a, struct t_img *t_b) {
1199 unsigned int i, f;
1200
1201 char *s;
1202
1203 size_t t;
1204
1205 struct widget_header *h;
1206
1207 t = CONFIG_PATH_LENGTH;
1208
1209 APP_MALLOC_RET_VALUE(s, t + sizeof(char), 0);
1210
1211 for(i = 0; ; i++) {
1212 if(c_d_t[i] == NULL) {
1213 (void) flush_error();
1214
1215 LOGWARN(
1216 ERROR_SLIGHT, SUBSYSTEM,
1217 _("Failed to find %s from any of the bob directories, please check the installation"),
1218 a
1219 );
1220
1221 (void) free(s);
1222
1223 return(0);
1224 }
1225
1226 if(conf_read_try(c_d_t[i], a, s, t) != 0) continue;
1227
1228 if((f = files_open(s, FILE_FLAG_SILENT, FILE_MODE_READ)) != 0) {
1229 if((t = files_get_file_size(f)) == 0) {
1230 (void) bob_init_file_op_c(s, f);
1231
1232 return(0);
1233 }
1234
1235 if(files_read(f, t) != 0) {
1236 (void) bob_init_file_op_c(s, f);
1237
1238 return(0);
1239 }
1240
1241 break;
1242 }
1243 }
1244
1245 /* Check and initialize bob image data */
1246 if((t_a->c = files_get_content(f)) == NULL) {
1247 (void) bob_init_file_op_c(s, f);
1248
1249 return(0);
1250 }
1251
1252 t_a->t = files_get_content_size(f);
1253
1254 h = (struct widget_header *) t_a->c;
1255
1256 for(i = 0; i < WIDGET_FILE_TAG_SIZE; i++) {
1257 if(t_a->t < sizeof(struct widget_header) || h->id[i] != endian_le_uint32(widget_header_tag[i])) {
1258 (void) flush_error();
1259
1260 LOGWARN(
1261 ERROR_SLIGHT, SUBSYSTEM,
1262 _("Failed to identify bob file %s, please check the installation"),
1263 s
1264 );
1265
1266 (void) bob_init_file_op_c(s, f);
1267
1268 return(0);
1269 }
1270 }
1271
1272 (void) free(s);
1273
1274 (void) bob_init_file_at(b, h, t_a, t_b);
1275
1276 return(f);
1277 }
1278
bob_init_file_op_c(char * s,unsigned int f)1279 static void bob_init_file_op_c(char *s, unsigned int f) {
1280 (void) files_close(f);
1281 (void) free(s);
1282 }
1283
bob_init_file_at(struct a_bob * b,struct widget_header * h,struct t_img * t_a,struct t_img * t_b)1284 static void bob_init_file_at(struct a_bob *b, struct widget_header *h, struct t_img *t_a, struct t_img *t_b) {
1285 char *p;
1286
1287 /* Initialize bob image frames */
1288 b->c = (unsigned int) endian_be_uint32(h->frames);
1289
1290 b->ox = (int) endian_be_int32(h->offset_x);
1291 b->oy = (int) endian_be_int32(h->offset_y);
1292
1293 t_a->w = (int32_t) endian_be_uint32(h->widget_width);
1294 t_a->h = (int32_t) endian_be_uint32(h->widget_height);
1295
1296 t_a->b = sizeof(struct pixel_rgba_8) * 8;
1297
1298 p = (char *) t_a->c;
1299 p += sizeof(struct widget_header) + endian_be_uint32(h->widget_data);
1300
1301 t_a->p = (struct pixel_rgba_8 *) p;
1302
1303 /* Correct endianess in image data if needed */
1304 (void) bob_init_file_en(t_a->p, b->c, (unsigned int) t_a->w, (unsigned int) t_a->h);
1305
1306 /* Initialize bob shadow frames */
1307 t_b->c = t_a->c;
1308 t_b->t = t_a->t;
1309
1310 t_b->w = (int32_t) endian_be_uint32(h->shadow_width);
1311 t_b->h = (int32_t) endian_be_uint32(h->shadow_height);
1312
1313 if(t_b->w == 0 || t_b->h == 0) {
1314 t_b->b = 0;
1315
1316 t_b->p = NULL;
1317 }
1318 else {
1319 t_b->b = sizeof(struct pixel_rgba_8) * 8;
1320
1321 p = (char *) t_b->c;
1322 p += sizeof(struct widget_header) + endian_be_uint32(h->shadow_data);
1323
1324 t_b->p = (struct pixel_rgba_8 *) p;
1325
1326 /* Correct endianess in shadow data if needed */
1327 (void) bob_init_file_en(t_b->p, b->c, (unsigned int) t_b->w, (unsigned int) t_b->h);
1328 }
1329 }
1330
bob_init_file_en(struct pixel_rgba_8 * p,unsigned int e,unsigned int w,unsigned int h)1331 static void bob_init_file_en(struct pixel_rgba_8 *p, unsigned int e, unsigned int w, unsigned int h) {
1332 #if defined(IS_BIGENDIAN)
1333 unsigned int i, j, k, l, n;
1334
1335 /* Big-endian machine needs bytes reversed */
1336 for(l = 0; l < e; l++) {
1337 n = w * h * l;
1338
1339 for(i = 0; i < h; i++) {
1340 k = n + (i * w);
1341
1342 for(j = 0; j < w; j++) {
1343 p[k + j].pixel.p = endian_le_uint32(p[k + j].pixel.p);
1344 }
1345 }
1346 }
1347 #else
1348 (void) p;
1349 (void) e;
1350 (void) w;
1351 (void) h;
1352 #endif
1353 }
1354
1355 /**
1356 * @brief Initialize one-frame bob with empty image buffer.
1357 *
1358 * @param[in] w Bob image data width in pixels
1359 * @param[in] h Bob image data height in pixels
1360 *
1361 * @retval Bob image id on success
1362 * @retval Zero on failure
1363 *
1364 */
1365
bob_init_image(unsigned int w,unsigned int h)1366 unsigned int bob_init_image(unsigned int w, unsigned int h) {
1367 unsigned int i, d;
1368
1369 struct a_bob **t;
1370
1371 if(w == 0 || h == 0) return(0);
1372
1373 /* Check if some slot can be reused */
1374 d = 0;
1375
1376 for(i = 0; i < c_fle; i++) {
1377 if(a_fle[i] == NULL) {
1378 d = i + 1;
1379
1380 break;
1381 }
1382 }
1383
1384 if(d == 0) {
1385 /* No free slot found, allocate one */
1386 APP_REALLOC_RET_VALUE(t, a_fle, sizeof(struct a_bob *) * (c_fle + 1), 0);
1387 APP_MALLOC_RET_VALUE(a_fle[c_fle], sizeof(struct a_bob), 0);
1388
1389 (void) memset((void *) a_fle[c_fle], 0, sizeof(struct a_bob));
1390
1391 d = ++c_fle;
1392 }
1393 else {
1394 /* Reuse existing slot */
1395 APP_MALLOC_RET_VALUE(a_fle[d - 1], sizeof(struct a_bob), 0);
1396
1397 (void) memset((void *) a_fle[d - 1], 0, sizeof(struct a_bob));
1398 }
1399
1400 a_fle[d - 1]->d = d;
1401 a_fle[d - 1]->f = 0;
1402 a_fle[d - 1]->i = 0;
1403
1404 a_fle[d - 1]->c = 1;
1405
1406 a_fle[d - 1]->ox = 0;
1407 a_fle[d - 1]->oy = 0;
1408
1409 /* Try to initialize empty image buffer */
1410 if(bob_init_image_op(w, h, &a_fle[d - 1]->t_a, &a_fle[d - 1]->t_b) != 0) {
1411 (void) free(a_fle[d - 1]);
1412
1413 a_fle[d - 1] = NULL;
1414
1415 return(0);
1416 }
1417
1418 return(d);
1419 }
1420
bob_init_image_op(unsigned int w,unsigned int h,struct t_img * t_a,struct t_img * t_b)1421 static int bob_init_image_op(unsigned int w, unsigned int h, struct t_img *t_a, struct t_img *t_b) {
1422 char *p;
1423
1424 size_t t;
1425
1426 t = (w * h) * sizeof(struct pixel_rgba_8);
1427
1428 APP_MALLOC_RET_VALUE(p, t, -1);
1429
1430 /* Initialize bob image frame */
1431 t_a->w = (int32_t) w;
1432 t_a->h = (int32_t) h;
1433
1434 t_a->b = sizeof(struct pixel_rgba_8) * 8;
1435
1436 t_a->c = (void *) p;
1437 t_a->p = (struct pixel_rgba_8 *) t_a->c;
1438 t_a->t = t;
1439
1440 (void) memset((void *) t_a->c, 0, t);
1441
1442 /* Initialize empty shadow frame */
1443 t_b->w = 0;
1444 t_b->h = 0;
1445
1446 t_b->b = 0;
1447
1448 t_b->c = NULL;
1449 t_b->p = (struct pixel_rgba_8 *) t_b->c;
1450 t_b->t = 0;
1451
1452 return(0);
1453 }
1454
1455 /**
1456 * @brief Free bob file.
1457 *
1458 * When bob_free_file() is called, file is freed for good and cannot be accessed anymore.
1459 * All bobs using this file must be deleted before calling this function.
1460 *
1461 * @param[in] d Bob file id returned by bob_init_file()
1462 *
1463 */
1464
bob_free_file(unsigned int d)1465 void bob_free_file(unsigned int d) {
1466 unsigned int i;
1467
1468 for(i = 0; i < c_fle; i++) {
1469 if(a_fle[i] != NULL && a_fle[i]->d == d) {
1470 (void) files_close(a_fle[i]->f);
1471 (void) free(a_fle[i]);
1472
1473 a_fle[i] = NULL;
1474
1475 break;
1476 }
1477 }
1478 }
1479
1480 /**
1481 * @brief Free bob image.
1482 *
1483 * When bob_free_image() is called, image is freed for good and cannot be accessed anymore.
1484 * All bobs using this image must be deleted before calling this function.
1485 *
1486 * @param[in] d Bob image id returned by bob_init_image()
1487 *
1488 */
1489
bob_free_image(unsigned int d)1490 void bob_free_image(unsigned int d) {
1491 unsigned int i;
1492
1493 for(i = 0; i < c_fle; i++) {
1494 if(a_fle[i] != NULL && a_fle[i]->d == d) {
1495 (void) free(a_fle[i]->t_a.c);
1496 (void) free(a_fle[i]);
1497
1498 a_fle[i] = NULL;
1499
1500 break;
1501 }
1502 }
1503 }
1504
bob_get_frame(unsigned int d,unsigned int e,struct w_bob * b,struct w_bob * s)1505 int bob_get_frame(unsigned int d, unsigned int e, struct w_bob *b, struct w_bob *s) {
1506 struct b_bob *c;
1507 struct pixel_rgba_8 *p;
1508
1509 c = a_bob[d]->b[e];
1510
1511 /* Return error to caller if bob is not mapped */
1512 if(c->m != IS_YES) return(-1);
1513
1514 /* Pass bob image frame to the caller */
1515 b->x = c->x;
1516 b->y = c->y - c->a;
1517
1518 b->width = c->data->t_a.w;
1519 b->height = c->data->t_a.h;
1520 b->opaque = c->o;
1521
1522 p = c->data->t_a.p;
1523 p += (c->data->t_a.w * c->data->t_a.h) * c->c;
1524
1525 b->frame = p;
1526
1527 /* Pass bob shadow frame to the caller */
1528 s->x = c->x + c->data->ox;
1529 s->y = c->y + c->data->oy;
1530
1531 s->width = c->data->t_b.w;
1532 s->height = c->data->t_b.h;
1533 s->opaque = c->o;
1534
1535 if(c->data->t_b.p != NULL) {
1536 p = c->data->t_b.p;
1537 p += (c->data->t_b.w * c->data->t_b.h) * c->c;
1538
1539 s->frame = p;
1540 }
1541 else s->frame = NULL;
1542
1543 /* Pass container's window handle to the caller */
1544 b->hnd = a_bob[d]->h;
1545
1546 /* Prepare new frame for next iteration */
1547 (void) bob_get_frame_op(c);
1548
1549 return(0);
1550 }
1551
bob_get_frame_op(struct b_bob * c)1552 static void bob_get_frame_op(struct b_bob *c) {
1553 if(c->data->c < 2 || c->play.m == BOB_PLAY_MODE_MANUAL) return;
1554
1555 /* If this frame's visible timeslice exceeded, update frame */
1556 if(clock_get_ticks() - c->play.u >= c->play.r) {
1557 switch(c->play.n) {
1558 case BOB_PLAY_DIRECTION_FORWARD:
1559 c->c = c->c + (1 + c->play.s);
1560
1561 break;
1562 case BOB_PLAY_DIRECTION_BACKWARDS:
1563 c->c = c->c - (1 + c->play.s);
1564
1565 break;
1566 default:
1567 break;
1568 }
1569
1570 /* Bob play mode says what happens if new frame is off limits */
1571 if(c->c >= c->data->c) {
1572 switch(c->play.m) {
1573 case BOB_PLAY_MODE_ONCE:
1574 c->c = 0;
1575 c->m = IS_NO;
1576
1577 break;
1578 default:
1579 c->c %= c->data->c;
1580
1581 break;
1582 }
1583 }
1584
1585 c->play.u += c->play.r;
1586 }
1587 }
1588
bob_count(unsigned int d)1589 unsigned int bob_count(unsigned int d) {
1590 return(a_bob[d]->c);
1591 }
1592
bob_begin(void)1593 unsigned int bob_begin(void) {
1594 b_lck = IS_YES;
1595
1596 return(c_bob);
1597 }
1598
bob_end(void)1599 void bob_end(void) {
1600 b_lck = IS_NO;
1601 }
1602
bob_locked(void)1603 void bob_locked(void) {
1604 while(b_lck == IS_MAYBE) {
1605 (void) timer_wait(0, TIMER_RESOLUTION_VERYFAST);
1606 }
1607 }
1608
bob_get_file_by_id(unsigned int d)1609 static struct a_bob *bob_get_file_by_id(unsigned int d) {
1610 unsigned int i;
1611
1612 for(i = 0; i < c_fle; i++) {
1613 if(a_fle[i] != NULL && a_fle[i]->d == d) return(a_fle[i]);
1614 }
1615
1616 return(NULL);
1617 }
1618
bob_get_bob_by_id(unsigned int d,unsigned int b)1619 static struct b_bob *bob_get_bob_by_id(unsigned int d, unsigned int b) {
1620 unsigned int i;
1621
1622 struct b_bob_c *c;
1623
1624 if((c = bob_get_container_by_id(d)) == NULL) return(NULL);
1625
1626 for(i = 0; i < c->c; i++) {
1627 if(c->b[i] != NULL && c->b[i]->d == b) return(c->b[i]);
1628 }
1629
1630 return(NULL);
1631 }
1632
bob_get_container_by_id(unsigned int d)1633 static struct b_bob_c *bob_get_container_by_id(unsigned int d) {
1634 unsigned int i;
1635
1636 for(i = 0; i < c_bob; i++) {
1637 if(a_bob[i] != NULL && a_bob[i]->d == d) return(a_bob[i]);
1638 }
1639
1640 return(NULL);
1641 }
1642
bob_get_default_bob_path(unsigned int i)1643 const char *bob_get_default_bob_path(unsigned int i) {
1644 return(c_d_t[i]);
1645 }
1646 #endif
1647