AllegroGL 0.4.4
|
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