gui.c

Go to the documentation of this file.
00001 /* This code is (C) AllegroGL contributors, and double licensed under
00002  * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
00003  */
00012 #include "alleggl.h"
00013 #include "allglint.h"
00014 
00015 #include <allegro/internal/aintern.h>
00016 
00017 
00018 static struct {
00019     GLuint texture;
00020     int hidden;
00021     int xfocus;
00022     int yfocus;
00023     int width;
00024     int height;
00025 } allegro_gl_mouse = { 0, TRUE, 0, 0, 0, 0};
00026 
00027 
00058 int algl_do_dialog (DIALOG *dialog, int focus_obj)
00059 {
00060     DIALOG_PLAYER *player;
00061 
00062     AGL_LOG(2, "allegro_gl_do_dialog\n");
00063 
00064     /* Allegro GUI routines generally use the 2D gfx functions therefore
00065        we set default behaviour to allegro_gl_set_allegro_mode so that we
00066        can use the GUI functions "as is" */
00067     allegro_gl_set_allegro_mode();
00068 
00069     player = init_dialog (dialog, focus_obj);
00070     show_mouse(screen);
00071 
00072     /* Nothing to do here.
00073      * Redrawing is done from d_algl_viewport_proc() callback. */
00074     while (update_dialog (player)) {}
00075 
00076     show_mouse(NULL);
00077     /* restore previous projection matrices */
00078     allegro_gl_unset_allegro_mode();
00079 
00080     return shutdown_dialog (player);
00081 }
00082 
00083 
00084 
00111 int algl_popup_dialog (DIALOG *dialog, int focus_obj)
00112 {
00113     void *backdrop;
00114     DIALOG_PLAYER *player;
00115     GLint read_buffer;
00116 
00117     AGL_LOG(2, "allegro_gl_popup_dialog\n");
00118 
00119     /* Allegro GUI routines generally use the 2D gfx functions therefore
00120        we set default behaviour to allegro_gl_set_allegro_mode so that we
00121        can use the GUI functions "as is" */
00122     allegro_gl_set_allegro_mode();
00123 
00124     glGetIntegerv(GL_READ_BUFFER, &read_buffer);
00125     glReadBuffer (GL_FRONT); /* TODO: don't clobber */
00126     glDisable(GL_DEPTH_TEST);
00127     backdrop = malloc (SCREEN_W * SCREEN_H * 3 * 4);
00128     glReadPixels (0, 0, SCREEN_W, SCREEN_H, GL_RGB, GL_UNSIGNED_BYTE, backdrop);
00129     glReadBuffer(read_buffer);
00130 
00131     player = init_dialog (dialog, focus_obj);
00132     show_mouse(screen);
00133 
00134     while (update_dialog (player)) {
00135 
00136         /* Redraw the GUI every frame */
00137         glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00138         glRasterPos2f (0., SCREEN_H-.5); /* TODO: don't clobber */
00139         glDrawPixels (SCREEN_W, SCREEN_H, GL_RGB, GL_UNSIGNED_BYTE, backdrop);
00140         broadcast_dialog_message (MSG_DRAW, 0);
00141 
00142         /* Draw the mouse cursor */
00143         algl_draw_mouse();
00144 
00145         /* Flip buffers */
00146         allegro_gl_flip();
00147     }
00148 
00149     glRasterPos2f (0., SCREEN_H-.5); /* TODO: don't clobber */
00150     glDrawPixels (SCREEN_W, SCREEN_H, GL_RGB, GL_UNSIGNED_BYTE, backdrop);
00151     glEnable(GL_DEPTH_TEST);
00152     free (backdrop);
00153 
00154     show_mouse(NULL);
00155     /* restore previous projection matrices */
00156     allegro_gl_unset_allegro_mode();
00157 
00158     return shutdown_dialog (player);
00159 }
00160 
00161 
00162 
00163 /* User mouse drawing callback */
00164 static void (*__algl_user_draw_mouse)(void) = NULL;
00165 
00166 
00187 void algl_draw_mouse (void)
00188 {
00189     AGL_LOG(2, "allegro_gl_draw_mouse\n");
00190 
00191     /* don't draw the mouse if it's not in our window */
00192     if (!_mouse_on || allegro_gl_mouse.hidden) return;
00193 
00194     if (__algl_user_draw_mouse) {
00195 
00196         __algl_user_draw_mouse();
00197 
00198     } else {
00199 
00200 #if 0
00201         float x = mouse_x;
00202         float y = mouse_y;
00203 
00204         int depth_enabled = glIsEnabled (GL_DEPTH_TEST);
00205         int cull_enabled = glIsEnabled (GL_CULL_FACE);
00206         if (depth_enabled) glDisable (GL_DEPTH_TEST);
00207         if (cull_enabled) glDisable (GL_CULL_FACE);
00208 
00209         glBegin (GL_TRIANGLES);
00210 
00211             #define draw(dx,dy) \
00212                 glVertex2f (x + dx, y + dy); \
00213                 glVertex2f (x + dx, y + dy + 10); \
00214                 glVertex2f (x + dx + 7, y + dy + 7); \
00215                 glVertex2f (x + dx + 1.5, y + dy + 6); \
00216                 glVertex2f (x + dx + 5.5, y + dy + 14); \
00217                 glVertex2f (x + dx + 7.5, y + dy + 14); \
00218                 glVertex2f (x + dx + 3.5, y + dy + 6); \
00219                 glVertex2f (x + dx + 1.5, y + dy + 6); \
00220                 glVertex2f (x + dx + 7.5, y + dy + 14);
00221 
00222             glColor3f (0, 0, 0);
00223             draw(-1,0)
00224             draw(1,0)
00225             draw(0,-1)
00226             draw(0,1)
00227 
00228             glColor3f (1, 1, 1);
00229             draw(0,0)
00230 
00231             #undef draw
00232 
00233         glEnd();
00234 
00235         if (depth_enabled) glEnable (GL_DEPTH_TEST);
00236         if (cull_enabled) glEnable (GL_CULL_FACE);
00237 #endif
00238 
00239         int x = mouse_x - allegro_gl_mouse.xfocus;
00240         int y = mouse_y - allegro_gl_mouse.yfocus;
00241     
00242         glPushAttrib(GL_COLOR_BUFFER_BIT);
00243         glAlphaFunc(GL_GREATER, 0.5);
00244         glEnable(GL_TEXTURE_2D);
00245         glEnable(GL_ALPHA_TEST);
00246 
00247         glBindTexture(GL_TEXTURE_2D, allegro_gl_mouse.texture);
00248         glColor4f(1., 1., 1., 1.);
00249         glTranslatef(-0.375, -0.375, 0);
00250         glBegin(GL_QUADS);
00251             glTexCoord2f(0., 1.);
00252             glVertex2f(x, y);
00253             glTexCoord2f(0., 0.);
00254             glVertex2f(x, y + allegro_gl_mouse.height);
00255             glTexCoord2f(1., 0.);
00256             glVertex2f(x + allegro_gl_mouse.width, y + allegro_gl_mouse.height);
00257             glTexCoord2f(1., 1.);
00258             glVertex2f(x + allegro_gl_mouse.width, y);
00259         glEnd();
00260         glTranslatef(0.375, 0.375, 0);
00261         glPopAttrib();
00262         glBindTexture(GL_TEXTURE_2D, 0);
00263         glDisable(GL_TEXTURE_2D);
00264     }
00265 }
00266 
00267 
00284 void algl_set_mouse_drawer (void (*user_draw_mouse)(void))
00285 {
00286     AGL_LOG(2, "allegro_gl_set_mouse_drawer\n");
00287 
00288     __algl_user_draw_mouse = user_draw_mouse;
00289 }
00290 
00291 
00292 
00293 
00294 
00295 static DIALOG alert_dialog[] =
00296 {
00297    /* (dialog proc)        (x)   (y)   (w)   (h)   (fg)  (bg)  (key) (flags)  (d1)  (d2)  (dp)  (dp2) (dp3) */
00298    { _gui_shadow_box_proc, 0,    0,    0,    0,    0,    0,    0,    0,       0,    0,    NULL, NULL, NULL  },
00299    { _gui_ctext_proc,      0,    0,    0,    0,    0,    0,    0,    0,       0,    0,    NULL, NULL, NULL  },
00300    { _gui_ctext_proc,      0,    0,    0,    0,    0,    0,    0,    0,       0,    0,    NULL, NULL, NULL  },
00301    { _gui_ctext_proc,      0,    0,    0,    0,    0,    0,    0,    0,       0,    0,    NULL, NULL, NULL  },
00302    { _gui_button_proc,     0,    0,    0,    0,    0,    0,    0,    D_EXIT,  0,    0,    NULL, NULL, NULL  },
00303    { _gui_button_proc,     0,    0,    0,    0,    0,    0,    0,    D_EXIT,  0,    0,    NULL, NULL, NULL  },
00304    { _gui_button_proc,     0,    0,    0,    0,    0,    0,    0,    D_EXIT,  0,    0,    NULL, NULL, NULL  },
00305    { d_yield_proc,         0,    0,    0,    0,    0,    0,    0,    0,       0,    0,    NULL, NULL, NULL  },
00306    { NULL,                 0,    0,    0,    0,    0,    0,    0,    0,       0,    0,    NULL, NULL, NULL  }
00307 };
00308 
00309 
00310 #define A_S1  1
00311 #define A_S2  2
00312 #define A_S3  3
00313 #define A_B1  4
00314 #define A_B2  5
00315 #define A_B3  6
00316 
00317 
00318 
00329 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)
00330 {
00331    char tmp[16];
00332    int avg_w, avg_h;
00333    int len1, len2, len3;
00334    int maxlen = 0;
00335    int buttons = 0;
00336    int b[3];
00337    int c;
00338 
00339    AGL_LOG(2, "allegro_gl_alert3\n");
00340 
00341    #define SORT_OUT_BUTTON(x) {                                            \
00342       if (b##x) {                                                          \
00343      alert_dialog[A_B##x].flags &= ~D_HIDDEN;                          \
00344      alert_dialog[A_B##x].key = c##x;                                  \
00345      alert_dialog[A_B##x].dp = (char *)b##x;                           \
00346      len##x = gui_strlen(b##x);                                        \
00347      b[buttons++] = A_B##x;                                            \
00348       }                                                                    \
00349       else {                                                               \
00350      alert_dialog[A_B##x].flags |= D_HIDDEN;                           \
00351      len##x = 0;                                                       \
00352       }                                                                    \
00353    }
00354 
00355    usetc(tmp+usetc(tmp, ' '), 0);
00356 
00357    avg_w = text_length(font, tmp);
00358    avg_h = text_height(font);
00359 
00360    alert_dialog[A_S1].dp = alert_dialog[A_S2].dp = alert_dialog[A_S3].dp = 
00361    alert_dialog[A_B1].dp = alert_dialog[A_B2].dp = empty_string;
00362 
00363    if (s1) {
00364       alert_dialog[A_S1].dp = (char *)s1;
00365       maxlen = text_length(font, s1);
00366    }
00367 
00368    if (s2) {
00369       alert_dialog[A_S2].dp = (char *)s2;
00370       len1 = text_length(font, s2);
00371       if (len1 > maxlen)
00372      maxlen = len1;
00373    }
00374 
00375    if (s3) {
00376       alert_dialog[A_S3].dp = (char *)s3;
00377       len1 = text_length(font, s3);
00378       if (len1 > maxlen)
00379      maxlen = len1;
00380    }
00381 
00382    SORT_OUT_BUTTON(1);
00383    SORT_OUT_BUTTON(2);
00384    SORT_OUT_BUTTON(3);
00385 
00386    len1 = MAX(len1, MAX(len2, len3)) + avg_w*3;
00387    if (len1*buttons > maxlen)
00388       maxlen = len1*buttons;
00389 
00390    maxlen += avg_w*4;
00391    alert_dialog[0].w = maxlen;
00392    alert_dialog[A_S1].x = alert_dialog[A_S2].x = alert_dialog[A_S3].x = 
00393                         alert_dialog[0].x + maxlen/2;
00394 
00395    alert_dialog[A_B1].w = alert_dialog[A_B2].w = alert_dialog[A_B3].w = len1;
00396 
00397    alert_dialog[A_B1].x = alert_dialog[A_B2].x = alert_dialog[A_B3].x = 
00398                        alert_dialog[0].x + maxlen/2 - len1/2;
00399 
00400    if (buttons == 3) {
00401       alert_dialog[b[0]].x = alert_dialog[0].x + maxlen/2 - len1*3/2 - avg_w;
00402       alert_dialog[b[2]].x = alert_dialog[0].x + maxlen/2 + len1/2 + avg_w;
00403    }
00404    else if (buttons == 2) {
00405       alert_dialog[b[0]].x = alert_dialog[0].x + maxlen/2 - len1 - avg_w;
00406       alert_dialog[b[1]].x = alert_dialog[0].x + maxlen/2 + avg_w;
00407    }
00408 
00409    alert_dialog[0].h = avg_h*8;
00410    alert_dialog[A_S1].y = alert_dialog[0].y + avg_h;
00411    alert_dialog[A_S2].y = alert_dialog[0].y + avg_h*2;
00412    alert_dialog[A_S3].y = alert_dialog[0].y + avg_h*3;
00413    alert_dialog[A_S1].h = alert_dialog[A_S2].h = alert_dialog[A_S3].h = avg_h;
00414    alert_dialog[A_B1].y = alert_dialog[A_B2].y = alert_dialog[A_B3].y = alert_dialog[0].y + avg_h*5;
00415    alert_dialog[A_B1].h = alert_dialog[A_B2].h = alert_dialog[A_B3].h = avg_h*2;
00416 
00417    centre_dialog(alert_dialog);
00418    set_dialog_color(alert_dialog, gui_fg_color, gui_bg_color);
00419    for (c = 0; alert_dialog[c].proc; c++)
00420       if (alert_dialog[c].proc == _gui_ctext_proc)
00421      alert_dialog[c].bg = -1;
00422 
00423    clear_keybuf();
00424 
00425    do {
00426    } while (gui_mouse_b());
00427 
00428    c = algl_popup_dialog(alert_dialog, A_B1);
00429 
00430    if (c == A_B1)
00431       return 1;
00432    else if (c == A_B2)
00433       return 2;
00434    else
00435       return 3;
00436 }
00437 
00438 
00439 
00449 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)
00450 {
00451    int ret;
00452 
00453    AGL_LOG(2, "allegro_gl_alert\n");
00454 
00455    ret = algl_alert3(s1, s2, s3, b1, b2, NULL, c1, c2, 0);
00456 
00457    if (ret > 2)
00458       ret = 2;
00459 
00460    return ret;
00461 }
00462 
00463 
00464 
00477 int d_algl_viewport_proc(int msg, DIALOG *d, int c)
00478 {
00479     int ret = D_O_K;
00480     typedef int (*_callback)(BITMAP*, int, int);
00481     _callback callback = (_callback) d->dp;
00482     BITMAP *viewport = create_sub_bitmap(screen, d->x, d->y, d->w, d->h);
00483 
00484     AGL_LOG(3, "d_algl_viewport_proc\n");
00485 
00486     /* First we get back into a 3D mode */
00487     allegro_gl_unset_allegro_mode();
00488 
00489     if (msg == MSG_DRAW) {
00490         /* Draws the background */
00491         clear_to_color(viewport, d->bg);
00492     }
00493 
00494     /* Save the Viewport and Scissor states */
00495     glPushAttrib(GL_SCISSOR_BIT | GL_VIEWPORT_BIT);
00496 
00497     /* Adapt the viewport to the object size */
00498     glViewport(d->x, SCREEN_H - d->y - d->h, d->w, d->h);
00499     glScissor(d->x, SCREEN_H - d->y - d->h, d->w, d->h);
00500     glEnable(GL_SCISSOR_TEST);
00501     
00502     /* Clear the depth buffer for this scissor region */
00503     if (msg == MSG_DRAW) {
00504         glClear(GL_DEPTH_BUFFER_BIT);
00505     }
00506 
00507     /* Call the callback function */
00508     if (callback)
00509         ret = callback(viewport, msg, c);
00510 
00511     /* Restore the previous state */
00512     glPopAttrib();
00513     allegro_gl_set_allegro_mode();
00514     destroy_bitmap(viewport);
00515 
00516     /* Redraw the GUI every frame */
00517     if (msg == MSG_IDLE) {
00518         glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00519         broadcast_dialog_message (MSG_DRAW, 0);
00520 
00521         /* Draw the mouse cursor */
00522         algl_draw_mouse();
00523 
00524         /* Flip buffers */
00525         allegro_gl_flip();
00526     }
00527 
00528 
00529     return ret;
00530 }
00531 
00532 
00533 
00534 /*****************/
00535 /* Mouse manager */
00536 /*****************/
00537 
00538 int allegro_gl_set_mouse_sprite(BITMAP *sprite, int xfocus, int yfocus)
00539 {
00540     BITMAP *bmp = NULL;
00541     GLint old_texture;
00542     
00543     AGL_LOG(2, "allegro_gl_set_mouse_sprite\n");
00544 
00545     glGetIntegerv(GL_TEXTURE_2D_BINDING, &old_texture);
00546 
00547     bmp = create_bitmap_ex(bitmap_color_depth(sprite),
00548              __allegro_gl_make_power_of_2(sprite->w),
00549              __allegro_gl_make_power_of_2(sprite->h));
00550 
00551     if (allegro_gl_mouse.texture) {
00552         glDeleteTextures(1, &allegro_gl_mouse.texture);
00553         allegro_gl_mouse.texture = 0;
00554     }
00555     
00556     clear_to_color(bmp, bitmap_mask_color(sprite));
00557     blit(sprite, bmp, 0, 0, 0, 0, sprite->w, sprite->h);
00558 #ifdef DEBUGMODE
00559     save_bmp("mcursor.bmp",bmp,NULL);
00560 #endif
00561 
00562     allegro_gl_mouse.texture = allegro_gl_make_texture_ex(AGL_TEXTURE_RESCALE
00563                             | AGL_TEXTURE_MASKED | AGL_TEXTURE_FLIP, bmp, -1);
00564     if (!allegro_gl_mouse.texture) {
00565         destroy_bitmap(bmp);
00566         return -1;
00567     }
00568 
00569     glBindTexture(GL_TEXTURE_2D, allegro_gl_mouse.texture);
00570     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00571     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00572     
00573     if (allegro_gl_extensions_GL.SGIS_texture_edge_clamp) {
00574         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00575         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00576     }
00577     else {
00578         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00579         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00580     }
00581 
00582     glBindTexture(GL_TEXTURE_2D, old_texture);
00583 
00584     allegro_gl_mouse.width  = bmp->w;
00585     allegro_gl_mouse.height = bmp->h;
00586     allegro_gl_mouse.xfocus = xfocus;
00587     allegro_gl_mouse.yfocus = yfocus;
00588 
00589     destroy_bitmap(bmp);
00590     return 0;
00591 }
00592 
00593 
00594 
00595 int allegro_gl_show_mouse(BITMAP* bmp, int x, int y)
00596 {
00597     AGL_LOG(3, "allegro_gl_show_mouse\n");
00598     allegro_gl_mouse.hidden = FALSE;
00599     return 0;
00600 }
00601 
00602 
00603 
00604 void allegro_gl_hide_mouse(void)
00605 {
00606     AGL_LOG(3, "allegro_gl_hide_mouse\n");
00607     allegro_gl_mouse.hidden = TRUE;
00608 }
00609 
00610 
00611 
00612 void allegro_gl_move_mouse(int x, int y)
00613 {
00614     AGL_LOG(3, "allegro_gl_move_mouse\n");
00615     /* This function is not called from the main thread, so
00616      * we must not call any OpenGL command there !!!
00617      */
00618 }
00619 

Generated on Sun Nov 11 15:52:55 2007 for AllegroGL by  doxygen 1.5.2