AllegroGL: gui.c Source File

AllegroGL 0.4.4

- Main Page
- Related Pages
- Modules
- Files

- File List
- Globals

gui.c
Go to the documentation of this file.
1 /* This code is (C) AllegroGL contributors, and double licensed under
2 * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
3 */
12 #include "alleggl.h"
13 #include "allglint.h"
14
15 #include <allegro/internal/aintern.h>
16
17
18 static struct {
19 GLuint texture;
20 int hidden;
21 int xfocus;
22 int yfocus;
23 int width;
24 int height;
25 } allegro_gl_mouse = { 0, TRUE, 0, 0, 0, 0};
26
27
58 int algl_do_dialog (DIALOG *dialog, int focus_obj)
59 {
60 DIALOG_PLAYER *player;
61
62 AGL_LOG(2, "allegro_gl_do_dialog\n");
63
64 /* Allegro GUI routines generally use the 2D gfx functions therefore
65 we set default behaviour to allegro_gl_set_allegro_mode so that we
66 can use the GUI functions "as is" */
67 allegro_gl_set_allegro_mode();
68
69 player = init_dialog (dialog, focus_obj);
70 show_mouse(screen);
71
72 /* Nothing to do here.
73 * Redrawing is done from d_algl_viewport_proc() callback. */
74 while (update_dialog (player)) {}
75
76 show_mouse(NULL);
77 /* restore previous projection matrices */
78 allegro_gl_unset_allegro_mode();
79
80 return shutdown_dialog (player);
81 }
82
83
84
111 int algl_popup_dialog (DIALOG *dialog, int focus_obj)
112 {
113 void *backdrop;
114 DIALOG_PLAYER *player;
115 GLint read_buffer;
116
117 AGL_LOG(2, "allegro_gl_popup_dialog\n");
118
119 /* Allegro GUI routines generally use the 2D gfx functions therefore
120 we set default behaviour to allegro_gl_set_allegro_mode so that we
121 can use the GUI functions "as is" */
122 allegro_gl_set_allegro_mode();
123
124 glGetIntegerv(GL_READ_BUFFER, &read_buffer);
125 glReadBuffer (GL_FRONT); /* TODO: don't clobber */
126 glDisable(GL_DEPTH_TEST);
127 backdrop = malloc (SCREEN_W * SCREEN_H * 3 * 4);
128 glReadPixels (0, 0, SCREEN_W, SCREEN_H, GL_RGB, GL_UNSIGNED_BYTE, backdrop);
129 glReadBuffer(read_buffer);
130
131 player = init_dialog (dialog, focus_obj);
132 show_mouse(screen);
133
134 while (update_dialog (player)) {
135
136 /* Redraw the GUI every frame */
137 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
138 glRasterPos2f (0., SCREEN_H-.5); /* TODO: don't clobber */
139 glDrawPixels (SCREEN_W, SCREEN_H, GL_RGB, GL_UNSIGNED_BYTE, backdrop);
140 broadcast_dialog_message (MSG_DRAW, 0);
141
142 /* Draw the mouse cursor */
143 algl_draw_mouse();
144
145 /* Flip buffers */
146 allegro_gl_flip();
147 }
148
149 glRasterPos2f (0., SCREEN_H-.5); /* TODO: don't clobber */
150 glDrawPixels (SCREEN_W, SCREEN_H, GL_RGB, GL_UNSIGNED_BYTE, backdrop);
151 glEnable(GL_DEPTH_TEST);
152 free (backdrop);
153
154 show_mouse(NULL);
155 /* restore previous projection matrices */
156 allegro_gl_unset_allegro_mode();
157
158 return shutdown_dialog (player);
159 }
160
161
162
163 /* User mouse drawing callback */
164 static void (*__algl_user_draw_mouse)(void) = NULL;
165
166
187 void algl_draw_mouse (void)
188 {
189 AGL_LOG(2, "allegro_gl_draw_mouse\n");
190
191 /* don't draw the mouse if it's not in our window */
192 if (!_mouse_on || allegro_gl_mouse.hidden) return;
193
194 if (__algl_user_draw_mouse) {
195
196 __algl_user_draw_mouse();
197
198 } else {
199
200 #if 0
201 float x = mouse_x;
202 float y = mouse_y;
203
204 int depth_enabled = glIsEnabled (GL_DEPTH_TEST);
205 int cull_enabled = glIsEnabled (GL_CULL_FACE);
206 if (depth_enabled) glDisable (GL_DEPTH_TEST);
207 if (cull_enabled) glDisable (GL_CULL_FACE);
208
209 glBegin (GL_TRIANGLES);
210
211 #define draw(dx,dy) \
212 glVertex2f (x + dx, y + dy); \
213 glVertex2f (x + dx, y + dy + 10); \
214 glVertex2f (x + dx + 7, y + dy + 7); \
215 glVertex2f (x + dx + 1.5, y + dy + 6); \
216 glVertex2f (x + dx + 5.5, y + dy + 14); \
217 glVertex2f (x + dx + 7.5, y + dy + 14); \
218 glVertex2f (x + dx + 3.5, y + dy + 6); \
219 glVertex2f (x + dx + 1.5, y + dy + 6); \
220 glVertex2f (x + dx + 7.5, y + dy + 14);
221
222 glColor3f (0, 0, 0);
223 draw(-1,0)
224 draw(1,0)
225 draw(0,-1)
226 draw(0,1)
227
228 glColor3f (1, 1, 1);
229 draw(0,0)
230
231 #undef draw
232
233 glEnd();
234
235 if (depth_enabled) glEnable (GL_DEPTH_TEST);
236 if (cull_enabled) glEnable (GL_CULL_FACE);
237 #endif
238
239 int x = mouse_x - allegro_gl_mouse.xfocus;
240 int y = mouse_y - allegro_gl_mouse.yfocus;
241
242 glPushAttrib(GL_COLOR_BUFFER_BIT);
243 glAlphaFunc(GL_GREATER, 0.5);
244 glEnable(GL_TEXTURE_2D);
245 glEnable(GL_ALPHA_TEST);
246
247 glBindTexture(GL_TEXTURE_2D, allegro_gl_mouse.texture);
248 glColor4f(1., 1., 1., 1.);
249 glTranslatef(-0.375, -0.375, 0);
250 glBegin(GL_QUADS);
251 glTexCoord2f(0., 1.);
252 glVertex2f(x, y);
253 glTexCoord2f(0., 0.);
254 glVertex2f(x, y + allegro_gl_mouse.height);
255 glTexCoord2f(1., 0.);
256 glVertex2f(x + allegro_gl_mouse.width, y + allegro_gl_mouse.height);
257 glTexCoord2f(1., 1.);
258 glVertex2f(x + allegro_gl_mouse.width, y);
259 glEnd();
260 glTranslatef(0.375, 0.375, 0);
261 glPopAttrib();
262 glBindTexture(GL_TEXTURE_2D, 0);
263 glDisable(GL_TEXTURE_2D);
264 }
265 }
266
267
284 void algl_set_mouse_drawer (void (*user_draw_mouse)(void))
285 {
286 AGL_LOG(2, "allegro_gl_set_mouse_drawer\n");
287
288 __algl_user_draw_mouse = user_draw_mouse;
289 }
290
291
292
293
294
295 static DIALOG alert_dialog[] =
296 {
297 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */
298 { _gui_shadow_box_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
299 { _gui_ctext_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
300 { _gui_ctext_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
301 { _gui_ctext_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
302 { _gui_button_proc, 0, 0, 0, 0, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL },
303 { _gui_button_proc, 0, 0, 0, 0, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL },
304 { _gui_button_proc, 0, 0, 0, 0, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL },
305 { d_yield_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
306 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
307 };
308
309
310 #define A_S1 1
311 #define A_S2 2
312 #define A_S3 3
313 #define A_B1 4
314 #define A_B2 5
315 #define A_B3 6
316
317
318
329 int algl_alert3(AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, AL_CONST char *b3, int c1, int c2, int c3)
330 {
331 char tmp[16];
332 int avg_w, avg_h;
333 int len1, len2, len3;
334 int maxlen = 0;
335 int buttons = 0;
336 int b[3];
337 int c;
338
339 AGL_LOG(2, "allegro_gl_alert3\n");
340
341 #define SORT_OUT_BUTTON(x) { \
342 if (b##x) { \
343 alert_dialog[A_B##x].flags &= ~D_HIDDEN; \
344 alert_dialog[A_B##x].key = c##x; \
345 alert_dialog[A_B##x].dp = (char *)b##x; \
346 len##x = gui_strlen(b##x); \
347 b[buttons++] = A_B##x; \
348 } \
349 else { \
350 alert_dialog[A_B##x].flags |= D_HIDDEN; \
351 len##x = 0; \
352 } \
353 }
354
355 usetc(tmp+usetc(tmp, ' '), 0);
356
357 avg_w = text_length(font, tmp);
358 avg_h = text_height(font);
359
360 alert_dialog[A_S1].dp = alert_dialog[A_S2].dp = alert_dialog[A_S3].dp =
361 alert_dialog[A_B1].dp = alert_dialog[A_B2].dp = empty_string;
362
363 if (s1) {
364 alert_dialog[A_S1].dp = (char *)s1;
365 maxlen = text_length(font, s1);
366 }
367
368 if (s2) {
369 alert_dialog[A_S2].dp = (char *)s2;
370 len1 = text_length(font, s2);
371 if (len1 > maxlen)
372 maxlen = len1;
373 }
374
375 if (s3) {
376 alert_dialog[A_S3].dp = (char *)s3;
377 len1 = text_length(font, s3);
378 if (len1 > maxlen)
379 maxlen = len1;
380 }
381
382 SORT_OUT_BUTTON(1);
383 SORT_OUT_BUTTON(2);
384 SORT_OUT_BUTTON(3);
385
386 len1 = MAX(len1, MAX(len2, len3)) + avg_w*3;
387 if (len1*buttons > maxlen)
388 maxlen = len1*buttons;
389
390 maxlen += avg_w*4;
391 alert_dialog[0].w = maxlen;
392 alert_dialog[A_S1].x = alert_dialog[A_S2].x = alert_dialog[A_S3].x =
393 alert_dialog[0].x + maxlen/2;
394
395 alert_dialog[A_B1].w = alert_dialog[A_B2].w = alert_dialog[A_B3].w = len1;
396
397 alert_dialog[A_B1].x = alert_dialog[A_B2].x = alert_dialog[A_B3].x =
398 alert_dialog[0].x + maxlen/2 - len1/2;
399
400 if (buttons == 3) {
401 alert_dialog[b[0]].x = alert_dialog[0].x + maxlen/2 - len1*3/2 - avg_w;
402 alert_dialog[b[2]].x = alert_dialog[0].x + maxlen/2 + len1/2 + avg_w;
403 }
404 else if (buttons == 2) {
405 alert_dialog[b[0]].x = alert_dialog[0].x + maxlen/2 - len1 - avg_w;
406 alert_dialog[b[1]].x = alert_dialog[0].x + maxlen/2 + avg_w;
407 }
408
409 alert_dialog[0].h = avg_h*8;
410 alert_dialog[A_S1].y = alert_dialog[0].y + avg_h;
411 alert_dialog[A_S2].y = alert_dialog[0].y + avg_h*2;
412 alert_dialog[A_S3].y = alert_dialog[0].y + avg_h*3;
413 alert_dialog[A_S1].h = alert_dialog[A_S2].h = alert_dialog[A_S3].h = avg_h;
414 alert_dialog[A_B1].y = alert_dialog[A_B2].y = alert_dialog[A_B3].y = alert_dialog[0].y + avg_h*5;
415 alert_dialog[A_B1].h = alert_dialog[A_B2].h = alert_dialog[A_B3].h = avg_h*2;
416
417 centre_dialog(alert_dialog);
418 set_dialog_color(alert_dialog, gui_fg_color, gui_bg_color);
419 for (c = 0; alert_dialog[c].proc; c++)
420 if (alert_dialog[c].proc == _gui_ctext_proc)
421 alert_dialog[c].bg = -1;
422
423 clear_keybuf();
424
425 do {
426 } while (gui_mouse_b());
427
428 c = algl_popup_dialog(alert_dialog, A_B1);
429
430 if (c == A_B1)
431 return 1;
432 else if (c == A_B2)
433 return 2;
434 else
435 return 3;
436 }
437
438
439
449 int algl_alert(AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, int c1, int c2)
450 {
451 int ret;
452
453 AGL_LOG(2, "allegro_gl_alert\n");
454
455 ret = algl_alert3(s1, s2, s3, b1, b2, NULL, c1, c2, 0);
456
457 if (ret > 2)
458 ret = 2;
459
460 return ret;
461 }
462
463
464
477 int d_algl_viewport_proc(int msg, DIALOG *d, int c)
478 {
479 int ret = D_O_K;
480 typedef int (*_callback)(BITMAP*, int, int);
481 _callback callback = (_callback) d->dp;
482 BITMAP *viewport = create_sub_bitmap(screen, d->x, d->y, d->w, d->h);
483
484 AGL_LOG(3, "d_algl_viewport_proc\n");
485
486 if (msg == MSG_DRAW) {
487 /* Draws the background */
488 clear_to_color(viewport, d->bg);
489 }
490
491 /* First we get back into a 3D mode */
492 allegro_gl_unset_allegro_mode();
493
494 /* Save the Viewport and Scissor states */
495 glPushAttrib(GL_SCISSOR_BIT | GL_VIEWPORT_BIT);
496
497 /* Adapt the viewport to the object size */
498 glViewport(d->x, SCREEN_H - d->y - d->h, d->w, d->h);
499 glScissor(d->x, SCREEN_H - d->y - d->h, d->w, d->h);
500 glEnable(GL_SCISSOR_TEST);
501
502 /* Clear the depth buffer for this scissor region */
503 if (msg == MSG_DRAW) {
504 glClear(GL_DEPTH_BUFFER_BIT);
505 }
506
507 /* Call the callback function */
508 if (callback)
509 ret = callback(viewport, msg, c);
510
511 /* Restore the previous state */
512 glPopAttrib();
513 allegro_gl_set_allegro_mode();
514 destroy_bitmap(viewport);
515
516 /* Redraw the GUI every frame */
517 if (msg == MSG_IDLE) {
518 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
519 broadcast_dialog_message (MSG_DRAW, 0);
520
521 /* Draw the mouse cursor */
522 algl_draw_mouse();
523
524 /* Flip buffers */
525 allegro_gl_flip();
526 }
527
528
529 return ret;
530 }
531
532
533
534 /*****************/
535 /* Mouse manager */
536 /*****************/
537
538 int allegro_gl_set_mouse_sprite(BITMAP *sprite, int xfocus, int yfocus)
539 {
540 BITMAP *bmp = NULL;
541 GLint old_texture;
542
543 AGL_LOG(2, "allegro_gl_set_mouse_sprite\n");
544
545 glGetIntegerv(GL_TEXTURE_2D_BINDING, &old_texture);
546
547 bmp = create_bitmap_ex(bitmap_color_depth(sprite),
548 __allegro_gl_make_power_of_2(sprite->w),
549 __allegro_gl_make_power_of_2(sprite->h));
550
551 if (allegro_gl_mouse.texture) {
552 glDeleteTextures(1, &allegro_gl_mouse.texture);
553 allegro_gl_mouse.texture = 0;
554 }
555
556 clear_to_color(bmp, bitmap_mask_color(sprite));
557 blit(sprite, bmp, 0, 0, 0, 0, sprite->w, sprite->h);
558 #ifdef DEBUGMODE
559 save_bmp("mcursor.bmp",bmp,NULL);
560 #endif
561
562 allegro_gl_mouse.texture = allegro_gl_make_texture_ex(AGL_TEXTURE_RESCALE
563 | AGL_TEXTURE_MASKED | AGL_TEXTURE_FLIP, bmp, -1);
564 if (!allegro_gl_mouse.texture) {
565 destroy_bitmap(bmp);
566 return -1;
567 }
568
569 glBindTexture(GL_TEXTURE_2D, allegro_gl_mouse.texture);
570 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
571 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
572
573 if (allegro_gl_extensions_GL.SGIS_texture_edge_clamp) {
574 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
575 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
576 }
577 else {
578 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
579 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
580 }
581
582 glBindTexture(GL_TEXTURE_2D, old_texture);
583
584 allegro_gl_mouse.width = bmp->w;
585 allegro_gl_mouse.height = bmp->h;
586 allegro_gl_mouse.xfocus = xfocus;
587 allegro_gl_mouse.yfocus = yfocus;
588
589 destroy_bitmap(bmp);
590 return 0;
591 }
592
593
594
595 int allegro_gl_show_mouse(BITMAP* bmp, int x, int y)
596 {
597 AGL_LOG(3, "allegro_gl_show_mouse\n");
598 allegro_gl_mouse.hidden = FALSE;
599 return 0;
600 }
601
602
603
604 void allegro_gl_hide_mouse(void)
605 {
606 AGL_LOG(3, "allegro_gl_hide_mouse\n");
607 allegro_gl_mouse.hidden = TRUE;
608 }
609
610
611
612 void allegro_gl_move_mouse(int x, int y)
613 {
614 AGL_LOG(3, "allegro_gl_move_mouse\n");
615 /* This function is not called from the main thread, so
616 * we must not call any OpenGL command there !!!
617 */
618 }
619
AGL_TEXTURE_MASKED
#define AGL_TEXTURE_MASKED
Generate an alpha channel for this texture, based on the Allegro mask color.
Definition: alleggl.h:537
allegro_gl_make_texture_ex
GLuint allegro_gl_make_texture_ex(int flags, BITMAP *bmp, GLint internal_format)
Uploads an Allegro BITMAP to the GL driver as a texture.
Definition: texture.c:1165
d_algl_viewport_proc
int d_algl_viewport_proc(int msg, DIALOG *d, int c)
Creates a viewport object where OpenGL commands can be performed.
Definition: gui.c:477
allegro_gl_unset_allegro_mode
void allegro_gl_unset_allegro_mode(void)
Restores previous OpenGL settings.
Definition: glvtable.c:2491
algl_draw_mouse
void algl_draw_mouse(void)
Draws a mouse pointer on the screen.
Definition: gui.c:187
algl_set_mouse_drawer
void algl_set_mouse_drawer(void(*user_draw_mouse)(void))
Sets (or clears) a user mouse drawing callback.
Definition: gui.c:284
allegro_gl_flip
void allegro_gl_flip(void)
Flips the front and back framebuffers.
Definition: alleggl.c:951
allegro_gl_extensions_GL
struct AGL_EXTENSION_LIST_GL allegro_gl_extensions_GL
List of OpenGL extensions supported by AllegroGL.
Definition: glext.c:55
algl_alert
int algl_alert(AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, int c1, int c2)
AllegroGL-friendly version of Allegro&#39;s alert.
Definition: gui.c:449
algl_popup_dialog
int algl_popup_dialog(DIALOG *dialog, int focus_obj)
AllegroGL-friendly version of popup_dialog.
Definition: gui.c:111
alleggl.h
Main header file for AllegroGL.
allegro_gl_set_allegro_mode
void allegro_gl_set_allegro_mode(void)
Prepares for Allegro drawing to the screen.
Definition: glvtable.c:2422
AGL_TEXTURE_FLIP
#define AGL_TEXTURE_FLIP
Flip the texture on the x-axis.
Definition: alleggl.h:532
AGL_TEXTURE_RESCALE
#define AGL_TEXTURE_RESCALE
Tell AllegroGL to allow rescaling of the bitmap.
Definition: alleggl.h:543
algl_do_dialog
int algl_do_dialog(DIALOG *dialog, int focus_obj)
AllegroGL-friendly version of do_dialog.
Definition: gui.c:58
algl_alert3
int algl_alert3(AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, AL_CONST char *b3, int c1, int c2, int c3)
AllegroGL-friendly version of Allegro&#39;s alert3.
Definition: gui.c:329