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

Generated on Sun Dec 3 18:06:49 2006 for AllegroGL by  doxygen 1.5.1