AllegroGL: gui.c Source File

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

# 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     if (msg == MSG_DRAW) {
    00487         /* Draws the background */
    00488         clear_to_color(viewport, d->bg);
    00489     }
    00490
    00491     /* First we get back into a 3D mode */
    00492     allegro_gl_unset_allegro_mode();
    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