Theme Editor: Factored out code to skip over enum/arg lists while scanning for childr...
[kugel-rb.git] / apps / plugins / cube.c
blob2b1e00d6901893ce0304e68526641274f4a9b0b4
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Damien Teney
11 * modified to use int instead of float math by Andreas Zwirtes
12 * heavily extended by Jens Arnold
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ***************************************************************************/
23 #include "plugin.h"
24 #include "lib/playergfx.h"
25 #if LCD_DEPTH > 1
26 #include "lib/mylcd.h" /* MYLCD_CFG_RB_XLCD or MYLCD_CFG_PGFX */
27 #include "lib/grey.h"
28 #else
29 #include "lib/grey.h"
30 #include "lib/mylcd.h" /* MYLCD_CFG_GREYLIB or MYLCD_CFG_PGFX */
31 #endif
32 #include "lib/xlcd.h"
33 #include "lib/fixedpoint.h"
35 PLUGIN_HEADER
37 /* Loops that the values are displayed */
38 #define DISP_TIME 30
40 /* variable button definitions */
41 #if CONFIG_KEYPAD == RECORDER_PAD
42 #define CUBE_QUIT BUTTON_OFF
43 #define CUBE_NEXT BUTTON_RIGHT
44 #define CUBE_PREV BUTTON_LEFT
45 #define CUBE_INC BUTTON_UP
46 #define CUBE_DEC BUTTON_DOWN
47 #define CUBE_MODE BUTTON_F1
48 #define CUBE_PAUSE BUTTON_PLAY
49 #define CUBE_HIGHSPEED BUTTON_ON
51 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
52 #define CUBE_QUIT BUTTON_OFF
53 #define CUBE_NEXT BUTTON_RIGHT
54 #define CUBE_PREV BUTTON_LEFT
55 #define CUBE_INC BUTTON_UP
56 #define CUBE_DEC BUTTON_DOWN
57 #define CUBE_MODE BUTTON_F1
58 #define CUBE_PAUSE BUTTON_SELECT
59 #define CUBE_HIGHSPEED BUTTON_ON
61 #elif CONFIG_KEYPAD == PLAYER_PAD
62 #define CUBE_QUIT BUTTON_STOP
63 #define CUBE_INC BUTTON_RIGHT
64 #define CUBE_DEC BUTTON_LEFT
65 #define CUBE_NEXT (BUTTON_ON | BUTTON_RIGHT)
66 #define CUBE_PREV (BUTTON_ON | BUTTON_LEFT)
67 #define CUBE_MODE BUTTON_MENU
68 #define CUBE_PAUSE BUTTON_PLAY
69 #define CUBE_HIGHSPEED_PRE BUTTON_ON
70 #define CUBE_HIGHSPEED (BUTTON_ON | BUTTON_REL)
72 #elif CONFIG_KEYPAD == ONDIO_PAD
73 #define CUBE_QUIT BUTTON_OFF
74 #define CUBE_NEXT BUTTON_RIGHT
75 #define CUBE_PREV BUTTON_LEFT
76 #define CUBE_INC BUTTON_UP
77 #define CUBE_DEC BUTTON_DOWN
78 #define CUBE_MODE_PRE BUTTON_MENU
79 #define CUBE_MODE (BUTTON_MENU | BUTTON_REL)
80 #define CUBE_PAUSE (BUTTON_MENU | BUTTON_LEFT)
81 #define CUBE_HIGHSPEED (BUTTON_MENU | BUTTON_RIGHT)
83 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
84 (CONFIG_KEYPAD == IRIVER_H300_PAD)
85 #define CUBE_QUIT BUTTON_OFF
86 #define CUBE_NEXT BUTTON_RIGHT
87 #define CUBE_PREV BUTTON_LEFT
88 #define CUBE_INC BUTTON_UP
89 #define CUBE_DEC BUTTON_DOWN
90 #define CUBE_MODE BUTTON_MODE
91 #define CUBE_PAUSE BUTTON_ON
92 #define CUBE_HIGHSPEED BUTTON_SELECT
94 #define CUBE_RC_QUIT BUTTON_RC_STOP
96 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
97 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
98 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
99 #define CUBE_QUIT (BUTTON_SELECT | BUTTON_MENU)
100 #define CUBE_NEXT BUTTON_RIGHT
101 #define CUBE_PREV BUTTON_LEFT
102 #define CUBE_INC BUTTON_SCROLL_FWD
103 #define CUBE_DEC BUTTON_SCROLL_BACK
104 #define CUBE_MODE BUTTON_MENU
105 #define CUBE_PAUSE BUTTON_PLAY
106 #define CUBE_HIGHSPEED_PRE BUTTON_SELECT
107 #define CUBE_HIGHSPEED (BUTTON_SELECT | BUTTON_REL)
109 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
110 #define CUBE_QUIT BUTTON_PLAY
111 #define CUBE_NEXT BUTTON_RIGHT
112 #define CUBE_PREV BUTTON_LEFT
113 #define CUBE_INC BUTTON_UP
114 #define CUBE_DEC BUTTON_DOWN
115 #define CUBE_MODE BUTTON_MODE
116 #define CUBE_PAUSE BUTTON_SELECT
117 #define CUBE_HIGHSPEED BUTTON_EQ
119 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
120 #define CUBE_QUIT BUTTON_POWER
121 #define CUBE_NEXT BUTTON_RIGHT
122 #define CUBE_PREV BUTTON_LEFT
123 #define CUBE_INC BUTTON_UP
124 #define CUBE_DEC BUTTON_DOWN
125 #define CUBE_MODE BUTTON_REC
126 #define CUBE_PAUSE BUTTON_PLAY
127 #define CUBE_HIGHSPEED BUTTON_SELECT
129 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
130 #define CUBE_QUIT BUTTON_POWER
131 #define CUBE_NEXT BUTTON_RIGHT
132 #define CUBE_PREV BUTTON_LEFT
133 #define CUBE_INC BUTTON_UP
134 #define CUBE_DEC BUTTON_DOWN
135 #define CUBE_MODE BUTTON_MENU
136 #define CUBE_PAUSE BUTTON_SELECT
137 #define CUBE_HIGHSPEED BUTTON_A
139 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
140 #define CUBE_QUIT BUTTON_POWER
141 #define CUBE_NEXT BUTTON_RIGHT
142 #define CUBE_PREV BUTTON_LEFT
143 #define CUBE_INC BUTTON_SCROLL_FWD
144 #define CUBE_DEC BUTTON_SCROLL_BACK
145 #define CUBE_MODE BUTTON_DOWN
146 #define CUBE_PAUSE BUTTON_UP
147 #define CUBE_HIGHSPEED BUTTON_SELECT
149 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
150 #define CUBE_QUIT (BUTTON_HOME|BUTTON_REPEAT)
151 #define CUBE_NEXT BUTTON_RIGHT
152 #define CUBE_PREV BUTTON_LEFT
153 #define CUBE_INC BUTTON_SCROLL_FWD
154 #define CUBE_DEC BUTTON_SCROLL_BACK
155 #define CUBE_MODE BUTTON_DOWN
156 #define CUBE_PAUSE BUTTON_UP
157 #define CUBE_HIGHSPEED BUTTON_SELECT
159 #elif (CONFIG_KEYPAD == SANSA_C200_PAD) || \
160 (CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
161 (CONFIG_KEYPAD == SANSA_M200_PAD)
162 #define CUBE_QUIT BUTTON_POWER
163 #define CUBE_NEXT BUTTON_RIGHT
164 #define CUBE_PREV BUTTON_LEFT
165 #define CUBE_INC BUTTON_VOL_UP
166 #define CUBE_DEC BUTTON_VOL_DOWN
167 #define CUBE_MODE BUTTON_DOWN
168 #define CUBE_PAUSE BUTTON_UP
169 #define CUBE_HIGHSPEED BUTTON_SELECT
172 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
173 #define CUBE_QUIT BUTTON_POWER
174 #define CUBE_NEXT BUTTON_RIGHT
175 #define CUBE_PREV BUTTON_LEFT
176 #define CUBE_INC BUTTON_SCROLL_UP
177 #define CUBE_DEC BUTTON_SCROLL_DOWN
178 #define CUBE_MODE BUTTON_REW
179 #define CUBE_PAUSE BUTTON_PLAY
180 #define CUBE_HIGHSPEED BUTTON_FF
182 #elif CONFIG_KEYPAD == MROBE500_PAD
183 #define CUBE_QUIT BUTTON_POWER
185 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
186 #define CUBE_QUIT BUTTON_BACK
187 #define CUBE_NEXT BUTTON_RIGHT
188 #define CUBE_PREV BUTTON_LEFT
189 #define CUBE_INC BUTTON_UP
190 #define CUBE_DEC BUTTON_DOWN
191 #define CUBE_MODE BUTTON_MENU
192 #define CUBE_PAUSE BUTTON_PLAY
193 #define CUBE_HIGHSPEED BUTTON_SELECT
195 #elif (CONFIG_KEYPAD == MROBE100_PAD)
196 #define CUBE_QUIT BUTTON_POWER
197 #define CUBE_NEXT BUTTON_RIGHT
198 #define CUBE_PREV BUTTON_LEFT
199 #define CUBE_INC BUTTON_UP
200 #define CUBE_DEC BUTTON_DOWN
201 #define CUBE_MODE BUTTON_MENU
202 #define CUBE_PAUSE BUTTON_PLAY
203 #define CUBE_HIGHSPEED BUTTON_SELECT
205 #elif (CONFIG_KEYPAD == IAUDIO_M3_PAD)
206 #define CUBE_QUIT BUTTON_RC_REC
207 #define CUBE_NEXT BUTTON_RC_FF
208 #define CUBE_PREV BUTTON_RC_REW
209 #define CUBE_INC BUTTON_RC_VOL_UP
210 #define CUBE_DEC BUTTON_RC_VOL_DOWN
211 #define CUBE_MODE BUTTON_RC_MODE
212 #define CUBE_PAUSE BUTTON_RC_PLAY
213 #define CUBE_HIGHSPEED BUTTON_RC_MENU
215 #elif CONFIG_KEYPAD == COWON_D2_PAD
216 #define CUBE_QUIT BUTTON_POWER
218 #elif (CONFIG_KEYPAD == IAUDIO67_PAD)
219 #define CUBE_QUIT BUTTON_POWER
220 #define CUBE_NEXT BUTTON_RIGHT
221 #define CUBE_PREV BUTTON_LEFT
222 #define CUBE_INC BUTTON_VOLUP
223 #define CUBE_DEC BUTTON_VOLDOWN
224 #define CUBE_MODE BUTTON_MENU
225 #define CUBE_PAUSE BUTTON_PLAY
226 #define CUBE_HIGHSPEED BUTTON_STOP
228 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
229 #define CUBE_QUIT BUTTON_BACK
230 #define CUBE_NEXT BUTTON_RIGHT
231 #define CUBE_PREV BUTTON_LEFT
232 #define CUBE_INC BUTTON_UP
233 #define CUBE_DEC BUTTON_DOWN
234 #define CUBE_MODE BUTTON_MENU
235 #define CUBE_PAUSE BUTTON_PLAY
236 #define CUBE_HIGHSPEED BUTTON_SELECT
238 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
239 #define CUBE_QUIT BUTTON_POWER
240 #define CUBE_NEXT BUTTON_RIGHT
241 #define CUBE_PREV BUTTON_LEFT
242 #define CUBE_INC BUTTON_UP
243 #define CUBE_DEC BUTTON_DOWN
244 #define CUBE_MODE BUTTON_MENU
245 #define CUBE_PAUSE BUTTON_SELECT
246 #define CUBE_HIGHSPEED BUTTON_VIEW
248 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
249 #define CUBE_QUIT BUTTON_POWER
250 #define CUBE_NEXT BUTTON_NEXT
251 #define CUBE_PREV BUTTON_PREV
252 #define CUBE_INC BUTTON_UP
253 #define CUBE_DEC BUTTON_DOWN
254 #define CUBE_MODE BUTTON_MENU
255 #define CUBE_PAUSE BUTTON_PLAY
256 #define CUBE_HIGHSPEED BUTTON_RIGHT
258 #elif CONFIG_KEYPAD == ONDAVX747_PAD
259 #define CUBE_QUIT BUTTON_POWER
260 #elif CONFIG_KEYPAD == ONDAVX777_PAD
261 #define CUBE_QUIT BUTTON_POWER
263 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
264 #define CUBE_QUIT BUTTON_REC
265 #define CUBE_NEXT BUTTON_RIGHT
266 #define CUBE_PREV BUTTON_LEFT
267 #define CUBE_INC BUTTON_UP
268 #define CUBE_DEC BUTTON_DOWN
269 #define CUBE_MODE BUTTON_REW
270 #define CUBE_PAUSE BUTTON_PLAY
271 #define CUBE_HIGHSPEED BUTTON_FFWD
273 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
274 #define CUBE_QUIT BUTTON_REC
275 #define CUBE_NEXT BUTTON_NEXT
276 #define CUBE_PREV BUTTON_PREV
277 #define CUBE_INC BUTTON_UP
278 #define CUBE_DEC BUTTON_DOWN
279 #define CUBE_MODE BUTTON_MENU
280 #define CUBE_PAUSE BUTTON_PLAY
281 #define CUBE_HIGHSPEED BUTTON_OK
283 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
284 #define CUBE_QUIT (BUTTON_REC | BUTTON_PLAY)
285 #define CUBE_NEXT BUTTON_NEXT
286 #define CUBE_PREV BUTTON_PREV
287 #define CUBE_INC BUTTON_VOL_UP
288 #define CUBE_DEC BUTTON_VOL_DOWN
289 #define CUBE_MODE BUTTON_REC
290 #define CUBE_PAUSE BUTTON_PLAY
291 #define CUBE_HIGHSPEED BUTTON_SELECT
293 #else
294 #error No keymap defined!
295 #endif
297 #ifdef HAVE_TOUCHSCREEN
298 #ifndef CUBE_QUIT
299 #define CUBE_QUIT BUTTON_TOPLEFT
300 #endif
301 #ifndef CUBE_NEXT
302 #define CUBE_NEXT BUTTON_MIDRIGHT
303 #endif
304 #ifndef CUBE_PREV
305 #define CUBE_PREV BUTTON_MIDLEFT
306 #endif
307 #ifndef CUBE_INC
308 #define CUBE_INC BUTTON_TOPMIDDLE
309 #endif
310 #ifndef CUBE_DEC
311 #define CUBE_DEC BUTTON_BOTTOMMIDDLE
312 #endif
313 #ifndef CUBE_MODE
314 #define CUBE_MODE BUTTON_TOPRIGHT
315 #endif
316 #ifndef CUBE_PAUSE
317 #define CUBE_PAUSE BUTTON_CENTER
318 #endif
319 #ifndef CUBE_HIGHSPEED
320 #define CUBE_HIGHSPEED BUTTON_BOTTOMRIGHT
321 #endif
322 #endif
325 #ifdef HAVE_LCD_BITMAP
327 #define DIST (10 * MIN(LCD_HEIGHT, LCD_WIDTH) / 16)
328 static int x_off = LCD_WIDTH/2;
329 static int y_off = LCD_HEIGHT/2;
331 #if LCD_DEPTH == 1
332 #define USEGSLIB
333 GREY_INFO_STRUCT
334 struct my_lcd {
335 void (*update)(void);
336 void (*clear_display)(void);
337 void (*drawline)(int x1, int y1, int x2, int y2);
338 void (*putsxy)(int x, int y, const unsigned char *string);
341 static struct my_lcd greyfuncs = {
342 grey_update, grey_clear_display, grey_drawline, grey_putsxy
344 static struct my_lcd lcdfuncs; /* initialised at runtime */
345 static struct my_lcd *mylcd = &greyfuncs;
347 #define MYLCD(fn) mylcd->fn
349 #else
350 #define MYLCD(fn) rb->lcd_ ## fn
351 #endif
353 #if CONFIG_LCD == LCD_SSD1815
354 #define ASPECT 320 /* = 1.25 (fixed point 24.8) */
355 #else
356 #define ASPECT 256 /* = 1.00 */
357 #endif
359 #else /* !LCD_BITMAP */
361 #define MYLCD(fn) pgfx_ ## fn
362 #define DIST 9
363 static int x_off = 10;
364 static int y_off = 7;
365 #define ASPECT 300 /* = 1.175 */
367 #endif /* !LCD_BITMAP */
369 struct point_3D {
370 long x, y, z;
373 struct point_2D {
374 long x, y;
377 struct line {
378 int start, end;
381 struct face {
382 int corner[4];
383 int line[4];
386 /* initial, unrotated cube corners */
387 static const struct point_3D sommet[8] =
389 {-DIST, -DIST, -DIST},
390 { DIST, -DIST, -DIST},
391 { DIST, DIST, -DIST},
392 {-DIST, DIST, -DIST},
393 {-DIST, -DIST, DIST},
394 { DIST, -DIST, DIST},
395 { DIST, DIST, DIST},
396 {-DIST, DIST, DIST}
399 /* The 12 lines forming the edges */
400 static const struct line lines[12] =
402 {0, 1}, {1, 2}, {2, 3}, {3, 0},
403 {4, 7}, {7, 6}, {6, 5}, {5, 4},
404 {0, 4}, {1, 5}, {2, 6}, {3, 7}
407 static bool lines_drawn[12];
409 /* The 6 faces of the cube; points are in clockwise order when viewed
410 from the outside */
411 static const struct face faces[6] =
413 {{0, 1, 2, 3}, {0, 1, 2, 3}},
414 {{4, 7, 6, 5}, {4, 5, 6, 7}},
415 {{0, 4, 5, 1}, {8, 7, 9, 0}},
416 {{2, 6, 7, 3}, {10, 5, 11, 2}},
417 {{0, 3, 7, 4}, {3, 11, 4, 8}},
418 {{1, 5, 6, 2}, {9, 6, 10, 1}}
421 #if LCD_DEPTH > 1 || defined(USEGSLIB)
422 static const unsigned face_colors[6] =
424 #ifdef HAVE_LCD_COLOR
425 LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(0, 255, 0),
426 LCD_RGBPACK(0, 255, 0), LCD_RGBPACK(0, 0, 255), LCD_RGBPACK(0, 0, 255)
427 #elif defined(USEGSLIB)
428 #ifdef MROBE_100
429 GREY_LIGHTGRAY, GREY_LIGHTGRAY, GREY_DARKGRAY,
430 GREY_DARKGRAY, GREY_WHITE, GREY_WHITE
431 #else
432 GREY_LIGHTGRAY, GREY_LIGHTGRAY, GREY_DARKGRAY,
433 GREY_DARKGRAY, GREY_BLACK, GREY_BLACK
434 #endif
435 #else
436 LCD_LIGHTGRAY, LCD_LIGHTGRAY, LCD_DARKGRAY,
437 LCD_DARKGRAY, LCD_BLACK, LCD_BLACK
438 #endif
440 #endif
442 enum {
443 #if LCD_DEPTH > 1 || defined(USEGSLIB)
444 SOLID,
445 #endif
446 HIDDEN_LINES,
447 WIREFRAME,
448 NUM_MODES
451 static int mode = 0;
453 struct counter {
454 const char *label;
455 short speed;
456 short angle;
459 static struct counter axes[] = {
460 {"x-axis", 1, 0},
461 {"y-axis", 3, 0},
462 {"z-axis", 2, 0}
465 static struct point_3D point3D[8];
466 static struct point_2D point2D[8];
467 static long matrice[3][3];
469 static const int nb_points = 8;
470 static long z_off = 600;
472 static void cube_rotate(int xa, int ya, int za)
474 int i;
475 /* Just to prevent unnecessary lookups */
476 long sxa, cxa, sya, cya, sza, cza;
478 sxa = fp14_sin(xa);
479 cxa = fp14_cos(xa);
480 sya = fp14_sin(ya);
481 cya = fp14_cos(ya);
482 sza = fp14_sin(za);
483 cza = fp14_cos(za);
485 /* calculate overall translation matrix */
486 matrice[0][0] = (cza * cya) >> 14;
487 matrice[1][0] = (sza * cya) >> 14;
488 matrice[2][0] = -sya;
490 matrice[0][1] = (((cza * sya) >> 14) * sxa - sza * cxa) >> 14;
491 matrice[1][1] = (((sza * sya) >> 14) * sxa + cxa * cza) >> 14;
492 matrice[2][1] = (sxa * cya) >> 14;
494 matrice[0][2] = (((cza * sya) >> 14) * cxa + sza * sxa) >> 14;
495 matrice[1][2] = (((sza * sya) >> 14) * cxa - cza * sxa) >> 14;
496 matrice[2][2] = (cxa * cya) >> 14;
498 /* apply translation matrix to all points */
499 for (i = 0; i < nb_points; i++)
501 point3D[i].x = matrice[0][0] * sommet[i].x + matrice[1][0] * sommet[i].y
502 + matrice[2][0] * sommet[i].z;
504 point3D[i].y = matrice[0][1] * sommet[i].x + matrice[1][1] * sommet[i].y
505 + matrice[2][1] * sommet[i].z;
507 point3D[i].z = matrice[0][2] * sommet[i].x + matrice[1][2] * sommet[i].y
508 + matrice[2][2] * sommet[i].z;
512 static void cube_viewport(void)
514 int i;
516 /* Do viewport transformation for all points */
517 for (i = 0; i < nb_points; i++)
519 #if ASPECT != 256
520 point2D[i].x = (point3D[i].x * ASPECT) / (point3D[i].z + (z_off << 14))
521 + x_off;
522 #else
523 point2D[i].x = (point3D[i].x << 8) / (point3D[i].z + (z_off << 14))
524 + x_off;
525 #endif
526 point2D[i].y = (point3D[i].y << 8) / (point3D[i].z + (z_off << 14))
527 + y_off;
531 static void cube_draw(void)
533 int i, j, line;
534 #if LCD_DEPTH > 1 || defined(USEGSLIB)
535 unsigned old_foreground;
536 #endif
538 switch (mode)
540 #if LCD_DEPTH > 1 || defined(USEGSLIB)
541 case SOLID:
543 old_foreground = mylcd_get_foreground();
544 for (i = 0; i < 6; i++)
546 /* backface culling; if the shape winds counter-clockwise, we are
547 * looking at the backface, and the (simplified) cross product
548 * is < 0. Do not draw it. */
549 if (0 >= (point2D[faces[i].corner[1]].x - point2D[faces[i].corner[0]].x)
550 * (point2D[faces[i].corner[2]].y - point2D[faces[i].corner[1]].y)
551 - (point2D[faces[i].corner[1]].y - point2D[faces[i].corner[0]].y)
552 * (point2D[faces[i].corner[2]].x - point2D[faces[i].corner[1]].x))
553 continue;
555 mylcd_set_foreground(face_colors[i]);
556 mylcd_filltriangle(point2D[faces[i].corner[0]].x,
557 point2D[faces[i].corner[0]].y,
558 point2D[faces[i].corner[1]].x,
559 point2D[faces[i].corner[1]].y,
560 point2D[faces[i].corner[2]].x,
561 point2D[faces[i].corner[2]].y);
562 mylcd_filltriangle(point2D[faces[i].corner[0]].x,
563 point2D[faces[i].corner[0]].y,
564 point2D[faces[i].corner[2]].x,
565 point2D[faces[i].corner[2]].y,
566 point2D[faces[i].corner[3]].x,
567 point2D[faces[i].corner[3]].y);
570 mylcd_set_foreground(old_foreground);
571 break;
572 #endif /* (LCD_DEPTH > 1) || GSLIB */
574 case HIDDEN_LINES:
576 rb->memset(lines_drawn, 0, sizeof(lines_drawn));
577 for (i = 0; i < 6; i++)
579 /* backface culling; if the shape winds counter-clockwise, we are
580 * looking at the backface, and the (simplified) cross product
581 * is < 0. Do not draw it. */
582 if (0 >= (point2D[faces[i].corner[1]].x - point2D[faces[i].corner[0]].x)
583 * (point2D[faces[i].corner[2]].y - point2D[faces[i].corner[1]].y)
584 - (point2D[faces[i].corner[1]].y - point2D[faces[i].corner[0]].y)
585 * (point2D[faces[i].corner[2]].x - point2D[faces[i].corner[1]].x))
586 continue;
588 for (j = 0; j < 4; j++)
590 line = faces[i].line[j];
591 if (!lines_drawn[line])
593 lines_drawn[line] = true;
594 MYLCD(drawline)(point2D[lines[line].start].x,
595 point2D[lines[line].start].y,
596 point2D[lines[line].end].x,
597 point2D[lines[line].end].y);
601 break;
603 case WIREFRAME:
605 for (i = 0; i < 12; i++)
606 MYLCD(drawline)(point2D[lines[i].start].x,
607 point2D[lines[i].start].y,
608 point2D[lines[i].end].x,
609 point2D[lines[i].end].y);
610 break;
614 void cleanup(void *parameter)
616 (void)parameter;
618 #ifdef USEGSLIB
619 grey_release();
620 #elif defined HAVE_LCD_CHARCELLS
621 pgfx_release();
622 #endif
625 enum plugin_status plugin_start(const void* parameter)
627 char buffer[30];
628 int t_disp = 0;
629 #ifdef USEGSLIB
630 unsigned char *gbuf;
631 size_t gbuf_size = 0;
632 bool mode_switch = true;
633 #endif
635 int button;
636 int lastbutton = BUTTON_NONE;
637 int curr = 0;
638 bool highspeed = false;
639 bool paused = false;
640 bool redraw = true;
641 bool exit = false;
643 (void)(parameter);
645 #ifdef HAVE_LCD_BITMAP
646 #if defined(USEGSLIB)
647 gbuf = (unsigned char *)rb->plugin_get_buffer(&gbuf_size);
648 if (!grey_init(gbuf, gbuf_size, GREY_BUFFERED,
649 LCD_WIDTH, LCD_HEIGHT, NULL))
651 rb->splash(HZ, "Couldn't init greyscale display");
652 return PLUGIN_ERROR;
654 /* init lcd_ function pointers */
655 lcdfuncs.update = rb->lcd_update;
656 lcdfuncs.clear_display = rb->lcd_clear_display;
657 lcdfuncs.drawline = rb->lcd_drawline;
658 lcdfuncs.putsxy = rb->lcd_putsxy;
660 #ifdef MROBE_100
661 grey_set_background(GREY_BLACK);
662 #endif
664 grey_setfont(FONT_SYSFIXED);
665 #endif
666 rb->lcd_setfont(FONT_SYSFIXED);
667 #else /* LCD_CHARCELLS */
668 if (!pgfx_init(4, 2))
670 rb->splash(HZ*2, "Old LCD :(");
671 return PLUGIN_OK;
673 pgfx_display(0, 0);
674 #endif
676 while(!exit)
678 if (redraw)
680 MYLCD(clear_display)();
681 cube_rotate(axes[0].angle, axes[1].angle, axes[2].angle);
682 cube_viewport();
683 cube_draw();
684 redraw = false;
687 #ifdef HAVE_LCD_BITMAP
688 if (t_disp > 0)
690 t_disp--;
691 rb->snprintf(buffer, sizeof(buffer), "%s: %d %s",
692 axes[curr].label,
693 paused ? axes[curr].angle : axes[curr].speed,
694 highspeed ? "(hs)" : "");
695 MYLCD(putsxy)(0, LCD_HEIGHT-8, buffer);
696 if (t_disp == 0)
697 redraw = true;
699 #else
700 if (t_disp > 0)
702 if (t_disp == DISP_TIME)
704 rb->lcd_puts(5, 0, axes[curr].label);
705 rb->snprintf(buffer, sizeof(buffer), "%d %c",
706 paused ? axes[curr].angle : axes[curr].speed,
707 highspeed ? 'H' : ' ');
708 rb->lcd_puts(5, 1, buffer);
710 t_disp--;
711 if (t_disp == 0)
713 rb->lcd_clear_display();
714 pgfx_display(0, 0);
717 #endif
718 #ifdef USEGSLIB
719 if (mode_switch)
721 grey_show(mode == SOLID);
722 mode_switch = false;
724 #endif
725 MYLCD(update)();
727 if (!paused)
729 int i;
731 for (i = 0; i < 3; i++)
733 axes[i].angle += axes[i].speed;
734 if (axes[i].angle > 359)
735 axes[i].angle -= 360;
736 else if (axes[i].angle < 0)
737 axes[i].angle += 360;
739 redraw = true;
741 if (highspeed)
742 rb->yield();
743 else
744 rb->sleep(HZ/25);
745 button = rb->button_get(false);
747 else
749 button = rb->button_get_w_tmo(HZ/25);
752 switch (button)
754 case CUBE_INC:
755 case CUBE_INC|BUTTON_REPEAT:
756 if (!paused)
758 if (axes[curr].speed < 10)
759 axes[curr].speed++;
761 else
763 if (++axes[curr].angle > 359)
764 axes[curr].angle -= 360;
766 t_disp = DISP_TIME;
767 redraw = true;
768 break;
770 case CUBE_DEC:
771 case CUBE_DEC|BUTTON_REPEAT:
772 if (!paused)
774 if (axes[curr].speed > -10)
775 axes[curr].speed--;
777 else
779 if (--axes[curr].angle < 0)
780 axes[curr].angle += 360;
782 t_disp = DISP_TIME;
783 redraw = true;
784 break;
786 case CUBE_NEXT:
787 if (++curr > 2)
788 curr = 0;
789 t_disp = DISP_TIME;
790 break;
792 case CUBE_PREV:
793 if (--curr < 0)
794 curr = 2;
795 t_disp = DISP_TIME;
796 break;
798 case CUBE_MODE:
799 #ifdef CUBE_MODE_PRE
800 if (lastbutton != CUBE_MODE_PRE)
801 break;
802 #endif
803 if (++mode >= NUM_MODES)
804 mode = 0;
805 #ifdef USEGSLIB
806 mylcd = (mode == SOLID) ? &greyfuncs : &lcdfuncs;
807 mode_switch = true;
808 #endif
809 redraw = true;
810 break;
812 case CUBE_PAUSE:
813 #ifdef CUBE_PAUSE_PRE
814 if (lastbutton != CUBE_PAUSE_PRE)
815 break;
816 #endif
817 paused = !paused;
818 break;
820 case CUBE_HIGHSPEED:
821 #ifdef CUBE_HIGHSPEED_PRE
822 if (lastbutton != CUBE_HIGHSPEED_PRE)
823 break;
824 #endif
825 highspeed = !highspeed;
826 t_disp = DISP_TIME;
827 break;
829 #ifdef CUBE_RC_QUIT
830 case CUBE_RC_QUIT:
831 #endif
832 case CUBE_QUIT:
833 exit = true;
834 break;
836 default:
837 if (rb->default_event_handler_ex(button, cleanup, NULL)
838 == SYS_USB_CONNECTED)
839 return PLUGIN_USB_CONNECTED;
840 break;
842 if (button != BUTTON_NONE)
843 lastbutton = button;
846 #ifdef USEGSLIB
847 grey_release();
848 #elif defined(HAVE_LCD_CHARCELLS)
849 pgfx_release();
850 #endif
851 return PLUGIN_OK;