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 */
4 /** \file gui.c
5 * \brief AllegroGL GUI wrappers
6 *
7 * These are replacements for Allegro's do_dialog routine and
8 * standard dialogs (to use our version of the routine).
9 */
10
11
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
28 /**
29 * \ingroup gui
30 * \brief AllegroGL-friendly version of do_dialog
31 *
32 * This behaves exactly like do_dialog but forces a screen clear,
33 * rerender, and flip, after each iteration of update_dialog.
34 *
35 * User gui components can do OpenGL or Allegro rendering to draw
36 * themselves. They should take care not to alter any OpenGL state
37 * (or be aware that this will affect other components). For the
38 * main render, they will be called in order, but this is not
39 * guarranteed at other times -- they may be called out of order;
40 * however the results will never be visible, so just don't crash.
41 *
42 * Before drawing the final (in-order) pass, the color and depth buffers will
43 * be cleared -- set your clear color to black or green or whatever you like.
44 * You can overdraw it with an object of course.
45 *
46 * Further notes: This routine uses allegro_gl_set_allegro_mode(), so
47 * your GUI components can use allegro_gl_unset_allegro_mode() to restore
48 * the old state while they draw themselves, provided that they use
49 * allegro_gl_set_allegro_mode() again afterwards.
50 *
51 * \param dialog an array of dialog objects terminated by one with a NULL
52 * dialog procedure.
53 * \param focus_obj index of the object on which the focus is set (-1 if you
54 * don't want anything to have the focus
55 *
56 * \sa algl_draw_mouse
57 */
algl_do_dialog(DIALOG * dialog,int focus_obj)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
85 /**
86 * \ingroup gui
87 * \brief AllegroGL-friendly version of popup_dialog
88 *
89 * This routine is likely to be very slow. It has to take a copy of the
90 * screen on entry, then where algl_do_dialog() would just clear the screen,
91 * this routine has to blit that copy back again after clearing. This is
92 * the only way to do overlays without knowing what type of flipping is
93 * going on.
94 *
95 * Also, note that we don't save the depth buffer or anything like that so
96 * don't go around thinking that algl_popup_dialog won't affect anything
97 * when it's gone.
98 *
99 * So, unless you need overlays, it's recommended that you just use
100 * algl_do_dialog(), and if you do need overlays, it's recommended that you
101 * just use algl_do_dialog() and redraw the thing you're overlaying yourself.
102 * If you're lazy or that's impossible, use this routine...
103 *
104 * \param dialog an array of dialog objects terminated by one with a NULL
105 * dialog procedure.
106 * \param focus_obj index of the object on which the focus is set (-1 if you
107 * don't want anything to have the focus
108 *
109 * \sa algl_do_dialog, algl_draw_mouse
110 */
algl_popup_dialog(DIALOG * dialog,int focus_obj)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
167 /**
168 * \ingroup gui
169 * \brief Draws a mouse pointer on the screen
170 *
171 * This function draws a mouse pointer on the screen. By default, it displays
172 * Allegro's standard black arrow cursor. However the settings of the cursor
173 * can be altered by Allegro's functions for mouse cursor management like
174 * show_mouse, set_mouse_sprite, scare_mouse, and so on... As a consequence,
175 * it should be stressed that if show_mouse(NULL) is called then
176 * algl_draw_mouse() won't draw anything.
177 *
178 * Unlike Allegro, AllegroGL does not manage the mouse cursor with an
179 * interrupt routine, hence algl_draw_mouse() must be regularly called
180 * in order to display the mouse cursor (ideally it should be the last function
181 * called before allegro_gl_flip()). However if you use algl_do_dialog()
182 * then you do not need to make explicit calls to algl_draw_mouse() since
183 * algl_do_dialog() takes care of that for you.
184 *
185 * \sa algl_set_mouse_drawer
186 */
algl_draw_mouse(void)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
268 /**
269 * \ingroup gui
270 * \brief Sets (or clears) a user mouse drawing callback
271 *
272 * This function allows to use a user-defined routine to display the mouse
273 * cursor. This allows nice effects like a spinning cube or any fancy thing
274 * you can think of to be used as a mouse cursor.
275 *
276 * When a user mouse drawing callback is enabled, set_mouse_sprite has no effect.
277 * However show_mouse and scare_mouse are still enabled.
278 *
279 * \param user_draw_mouse user routine that displays the mouse cursor (NULL if
280 * you want to get back to the standard behaviour)
281 *
282 * \sa algl_draw_mouse
283 */
algl_set_mouse_drawer(void (* user_draw_mouse)(void))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
319 /**
320 * \ingroup gui
321 * \brief AllegroGL-friendly version of Allegro's alert3.
322 *
323 * Displays a simple alert box, containing three lines of text (s1-s3),
324 * and with either one, two, or three buttons. The text for these buttons
325 * is passed in b1, b2, and b3 (NULL for buttons which are not used), and
326 * the keyboard shortcuts in c1 and c2. Returns 1, 2, or 3 depending on
327 * which button was selected.
328 */
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)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
440 /**
441 * \ingroup gui
442 * \brief AllegroGL-friendly version of Allegro's alert.
443 *
444 * Displays a simple alert box, containing three lines of text (s1-s3),
445 * and with either one or two buttons. The text for these buttons is passed
446 * in b1 and b2 (b2 may be null), and the keyboard shortcuts in c1 and c2.
447 * Returns 1 or 2 depending on which button was selected.
448 */
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)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
465 /**
466 * \ingroup gui
467 * \brief Creates a viewport object where OpenGL commands can be performed.
468 *
469 * The viewport and the scissor are updated so that this GUI object behaves
470 * somewhat like a window. The dp field of the DIALOG object points to a
471 * callback function : int (*callback)(BITMAP* viewport, int msg, int c) where:
472 * viewport is a sub-bitmap of the screen limited to the area of the
473 * DIALOG object. msg and c are the values that come from the GUI manager.
474 * The callback function must return a sensible value to the GUI manager
475 * like D_O_K if everything went right or D_EXIT to close the dialog.
476 */
d_algl_viewport_proc(int msg,DIALOG * d,int c)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
allegro_gl_set_mouse_sprite(BITMAP * sprite,int xfocus,int yfocus)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
allegro_gl_show_mouse(BITMAP * bmp,int x,int y)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
allegro_gl_hide_mouse(void)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
allegro_gl_move_mouse(int x,int y)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
620