00001
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef _ALLEGRO5_
00014 #define _ALLEGRO5_
00015 #include <allegro5/allegro5.h>
00016 #endif // _ALLEGRO5_
00017
00018 #ifndef _ALLEGRO5FONT_
00019 #define _ALLEGRO5FONT_
00020 #include <allegro5/allegro_font.h>
00021 #endif // _ALLEGRO5FONT_
00022
00023 #ifndef _ALLEGRO5IMAGE_
00024 #define _ALLEGRO5IMAGE_
00025 #include <allegro5/allegro_image.h>
00026 #endif // _ALLEGRO5IMAGE_
00027
00028 #ifndef _IMAGESCALE_
00029 #define _IMAGESCALE_
00030 #include "../include/imagescale.h"
00031 #endif // _IMAGESCALE_
00032
00033 #ifndef _BUTTONS_
00034 #define _BUTTONS_
00035 #include "../include/buttons.h"
00036 #endif // _BUTTONS_
00037
00038
00039
00040 static BUTTONPTR bfirstptr = NULL;
00041
00042
00043
00044 static BIMAGESPTR bitoptr = NULL;
00045
00046
00047
00048 static BUTTON_CALLBACK bcallback_func;
00049
00050
00051
00052 static SBANIMATIONS sb = SBNONE;
00053
00054
00055
00056 BUTTONPTR get_first_element_from_button_list(void)
00057 {
00058 return bfirstptr;
00059 }
00060
00061
00062
00063 BIMAGESPTR get_first_element_from_button_image_list(void)
00064 {
00065 return bitoptr;
00066 }
00067
00068
00069
00070 BUTTONPTR set_first_element_in_button_list(BUTTONPTR *newfirst)
00071 {
00072 bfirstptr = *newfirst;
00073 return bfirstptr;
00074 }
00075
00076
00077
00078 BUTTON_CALLBACK get_button_callback(void)
00079 {
00080 return bcallback_func;
00081 }
00082
00083
00084
00085 BUTTON_CALLBACK set_button_callback(BUTTON_CALLBACK bcallb_func)
00086 {
00087 bcallback_func = bcallb_func;
00088 return bcallback_func;
00089 }
00090
00091
00092
00093 void buttoncheck(BUTTON_CALLBACK bcallb_func, void *data)
00094 {
00095 BUTTONPTR currentptr = bfirstptr;
00096 do
00097 {
00098 if((currentptr->bdata.bflags & BVISIBLE))
00099 {
00100 if(currentptr->bdata.aflags == BNONE)
00101 check_for_button_events(currentptr);
00102 if((currentptr->bdata.bflags & BMOUSEOVER) && (currentptr->bdata.bflags & BLRELEASED))
00103 bcallb_func(currentptr, data, BPRESSED_CALL);
00104 standard_button_animations(currentptr);
00105 custom_button_animations(currentptr, currentptr->bdata.aflags, currentptr->bdata.limit, bcallb_func, data);
00106 }
00107 } while((currentptr = currentptr->nextbutton) != bfirstptr);
00108 }
00109
00110
00111
00112 void render_buttons(void)
00113 {
00114 BUTTONPTR currentptr = bfirstptr;
00115 do
00116 {
00117 if((currentptr->bdata.bflags & BVISIBLE))
00118 {
00119 draw_button(currentptr);
00120 if((currentptr->bdata.bflags & BLPRESSED) && !(currentptr->bdata.bflags & BLRELEASED))
00121 remove_bflags_on_button(currentptr, BLRELEASED | BRPRESSED | BRRELEASED | BMRELEASED | BMPRESSED |
00122 BDRAW | BMOUSEOVER);
00123 else
00124 remove_bflags_on_button(currentptr, BLPRESSED | BLRELEASED | BMRELEASED | BMPRESSED | BRPRESSED |
00125 BRRELEASED | BDRAW | BMOUSEOVER);
00126 }
00127 } while((currentptr = currentptr->nextbutton) != bfirstptr);
00128 }
00129
00130
00131
00132 void draw_button(BUTTONPTR currentptr)
00133 {
00134 const int c = 2, d = 2, x = 0, y = 0;
00135 nscale();
00136 static ALLEGRO_BITMAP *newbitm = NULL;
00137 if(newbitm == NULL)
00138 newbitm = al_create_bitmap(currentptr->bimage->width, currentptr->bimage->height);
00139 al_set_target_bitmap(newbitm);
00140 al_clear_to_color(al_map_rgba(0, 0, 0, 0));
00141 if((currentptr->bdata.bflags & BDRAW) && !(currentptr->bdata.bflags & BLPRESSED))
00142 {
00143 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, currentptr->bdata.b_color);
00144 al_draw_bitmap(currentptr->bimage->button_image, x, y, 0);
00145 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, currentptr->btext.text_c);
00146 al_draw_text(currentptr->btext.text_f,
00147 currentptr->bimage->width/d,
00148 currentptr->bimage->height/d-al_get_font_line_height(currentptr->btext.text_f)/d,
00149 ALLEGRO_ALIGN_CENTRE,
00150 currentptr->btext.text
00151 );
00152 }
00153 else if((currentptr->bdata.bflags & BDRAW) && (currentptr->bdata.bflags & BLPRESSED))
00154 {
00155 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, currentptr->bdata.b_color);
00156 al_draw_bitmap(currentptr->bimage->button_image, x, y, ALLEGRO_FLIP_VERTICAL);
00157 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, currentptr->btext.text_c);
00158 al_draw_text(currentptr->btext.text_f,
00159 currentptr->bimage->width/d+c,
00160 currentptr->bimage->height/d-al_get_font_line_height(currentptr->btext.text_f)/d+c,
00161 ALLEGRO_ALIGN_CENTRE,
00162 currentptr->btext.text
00163 );
00164 }
00165 else
00166 {
00167 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, currentptr->bdata.b_color);
00168 al_draw_bitmap(currentptr->bimage->button_image, x, y, 0);
00169 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, currentptr->btext.text_c);
00170 al_draw_text(currentptr->btext.text_f,
00171 currentptr->bimage->width/d,
00172 currentptr->bimage->height/d-al_get_font_line_height(currentptr->btext.text_f)/d,
00173 ALLEGRO_ALIGN_CENTRE,
00174 currentptr->btext.text
00175 );
00176 }
00177 al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, BDEFAULT);
00178 scale(800.0, 600.0);
00179 al_set_target_bitmap(al_get_backbuffer());
00180 al_draw_bitmap(newbitm, currentptr->bdata.x, currentptr->bdata.y, 0);
00181 }
00182
00183
00184
00185 void check_for_button_events(BUTTONPTR currentptr)
00186 {
00187 const int MOUSEL = 1;
00188 static int mx, my;
00189 static _Bool mdown = false;
00190 ALLEGRO_MOUSE_STATE mouse;
00191 al_get_mouse_state(&mouse);
00192
00193 set_bflags_on_button(currentptr, BDRAW);
00194 if(al_mouse_button_down(&mouse, MOUSEL) && !mdown)
00195 {
00196 mx = mouse.x;
00197 my = mouse.y;
00198 mdown = true;
00199 }
00200 if(!al_mouse_button_down(&mouse, MOUSEL))
00201 {
00202 mdown = false;
00203 }
00204 if(is_point_over_button(mx, my, currentptr))
00205 {
00206 if(is_mouse_over_button(&mouse, currentptr))
00207 {
00208 set_bflags_on_button(currentptr, BMOUSEOVER);
00209 }
00210 if(al_mouse_button_down(&mouse, MOUSEL) && (currentptr->bdata.bflags & BMOUSEOVER))
00211 {
00212 set_bflags_on_button(currentptr, BLPRESSED);
00213 }
00214 if(!al_mouse_button_down(&mouse, MOUSEL) && (currentptr->bdata.bflags & BLPRESSED))
00215 {
00216 set_bflags_on_button(currentptr, BLRELEASED);
00217 }
00218 }
00219 else
00220 {
00221 if(is_mouse_over_button(&mouse, currentptr))
00222 {
00223 set_bflags_on_button(currentptr, BMOUSEOVER);
00224 }
00225 }
00226 }
00227
00228
00229
00230 BUTTONPTR search_button_list_for_element(BUTTONPTR *firstptr, char *label)
00231 {
00232 BUTTONPTR currentptr = *firstptr;
00233 if(currentptr == NULL) return NULL;
00234 do
00235 {
00236 if(strcmp(currentptr->blabel, label) == 0) break;
00237 currentptr = currentptr->nextbutton;
00238 } while(currentptr != *firstptr);
00239
00240 if(strcmp(currentptr->blabel, label) != 0) return NULL;
00241 return currentptr;
00242 }
00243
00244
00245
00246 BUTTONPTR create_new_button(char *label, char *bimage_label,
00247 char *text, ALLEGRO_FONT *font,
00248 ALLEGRO_COLOR text_color, ALLEGRO_COLOR button_color,
00249 float x, float y, float limit,
00250 CBANIMATIONS aflags, BPROPERTIES bflags,
00251 _Bool add_to_list)
00252 {
00253 BUTTONPTR newptr;
00254 BIMAGESPTR bcurrentptr = search_button_image_list_for_element(bitoptr, bimage_label);
00255 unsigned char r, g, b, a;
00256 if((newptr = (BUTTONPTR)malloc(sizeof(BUTTON))) == NULL) return NULL;
00257
00258 newptr->blabel = label;
00259 newptr->bimage = bcurrentptr;
00260 newptr->btext.text = text;
00261 newptr->btext.text_f = font;
00262 newptr->btext.text_c = text_color;
00263 newptr->bdata.x = x;
00264 newptr->bdata.y = y;
00265 newptr->bdata.ox = x;
00266 newptr->bdata.oy = y;
00267 newptr->bdata.limit = limit;
00268 newptr->bdata.b_color = button_color;
00269 newptr->bdata.sflags = 0;
00270 newptr->bdata.aflags = aflags;
00271 newptr->bdata.bflags = bflags;
00272
00273 al_unmap_rgba(newptr->bdata.b_color, &r, &g, &b, &a);
00274
00275 newptr->bdata.alpha = a;
00276
00277 if(add_to_list)
00278 add_element_to_button_list(&newptr);
00279
00280 return newptr;
00281 }
00282
00283
00284
00285 BUTTONPTR add_element_to_button_list(BUTTONPTR *button)
00286 {
00287 BUTTONPTR currentptr;
00288 if(bfirstptr != NULL)
00289 {
00290 currentptr = bfirstptr->prevbutton;
00291 currentptr->nextbutton = *button;
00292 (*button)->prevbutton = currentptr;
00293 bfirstptr->prevbutton = *button;
00294 (*button)->nextbutton = bfirstptr;
00295 }
00296 else
00297 {
00298 bfirstptr = *button;
00299 (*button)->nextbutton = *button;
00300 (*button)->prevbutton = *button;
00301 }
00302 return *button;
00303 }
00304
00305
00306
00307 BUTTONPTR remove_element_from_button_list(BUTTONPTR *currentptr)
00308 {
00309 if(bfirstptr == NULL) return NULL;
00310 if(*currentptr == NULL) return NULL;
00311 if(*currentptr == bfirstptr && (*currentptr)->nextbutton == *currentptr && (*currentptr)->prevbutton == *currentptr)
00312 {
00313 free(*currentptr);
00314 bfirstptr = NULL;
00315 }
00316 else
00317 {
00318 (*currentptr)->nextbutton->prevbutton = (*currentptr)->prevbutton;
00319 (*currentptr)->prevbutton->nextbutton = (*currentptr)->nextbutton;
00320 if(*currentptr == bfirstptr)
00321 bfirstptr = (*currentptr)->nextbutton;
00322 free(*currentptr);
00323 }
00324 return bfirstptr;
00325 }
00326
00327
00328
00329 _Bool empty_button_list(BUTTONPTR firstptr)
00330 {
00331 BUTTONPTR currentptr = firstptr;
00332 if(firstptr == NULL) return false;
00333 if(firstptr->nextbutton == firstptr && firstptr->prevbutton == firstptr)
00334 {
00335 free(firstptr);
00336 firstptr = NULL;
00337 }
00338 else if(firstptr->nextbutton == firstptr->prevbutton)
00339 {
00340 currentptr = currentptr->nextbutton;
00341 free(firstptr);
00342 free(currentptr);
00343 firstptr = NULL;
00344 }
00345 else
00346 {
00347 currentptr = currentptr->nextbutton;
00348 firstptr->prevbutton->nextbutton = NULL;
00349 currentptr->prevbutton = NULL;
00350 free(firstptr);
00351 firstptr = currentptr;
00352
00353 while(currentptr != NULL)
00354 {
00355 currentptr = currentptr->nextbutton;
00356 free(firstptr);
00357 firstptr = currentptr;
00358 }
00359 firstptr = NULL;
00360 }
00361 return true;
00362 }
00363
00364
00365
00366 _Bool empty_button_image_list(BIMAGESPTR firstptr)
00367 {
00368 BIMAGESPTR currentptr = firstptr;
00369 if(firstptr == NULL) return false;
00370 if(firstptr->nextbimage == firstptr && firstptr->prevbimage == firstptr)
00371 {
00372 free(firstptr);
00373 firstptr = NULL;
00374 }
00375 else if(firstptr->nextbimage == firstptr->prevbimage)
00376 {
00377 currentptr = currentptr->nextbimage;
00378 free(firstptr);
00379 free(currentptr);
00380 firstptr = NULL;
00381 }
00382 else
00383 {
00384 currentptr = currentptr->nextbimage;
00385 firstptr->prevbimage->nextbimage = NULL;
00386 currentptr->prevbimage = NULL;
00387 free(firstptr);
00388 firstptr = currentptr;
00389
00390 while(currentptr != NULL)
00391 {
00392 currentptr = currentptr->nextbimage;
00393 free(firstptr);
00394 firstptr = currentptr;
00395 }
00396 firstptr = NULL;
00397 }
00398 return true;
00399 }
00400
00401
00402
00403 BUTTONPTR set_bflags_on_button(BUTTONPTR button, BPROPERTIES bflags)
00404 {
00405 if((bflags & BVISIBLE))
00406 button->bdata.bflags |= BVISIBLE;
00407 if((bflags & BLPRESSED))
00408 button->bdata.bflags |= BLPRESSED;
00409 if((bflags & BLRELEASED))
00410 button->bdata.bflags |= BLRELEASED;
00411 if((bflags & BRPRESSED))
00412 button->bdata.bflags |= BRPRESSED;
00413 if((bflags & BRRELEASED))
00414 button->bdata.bflags |= BRRELEASED;
00415 if((bflags & BMPRESSED))
00416 button->bdata.bflags |= BMPRESSED;
00417 if((bflags & BMRELEASED))
00418 button->bdata.bflags |= BMRELEASED;
00419 if((bflags & BMOUSEOVER))
00420 button->bdata.bflags |= BMOUSEOVER;
00421 if((bflags & BDRAW))
00422 button->bdata.bflags |= BDRAW;
00423
00424 return button;
00425 }
00426
00427
00428
00429 BUTTONPTR remove_bflags_on_button(BUTTONPTR button, BPROPERTIES bflags)
00430 {
00431 if((bflags & BVISIBLE))
00432 button->bdata.bflags &= ~BVISIBLE;
00433 if((bflags & BLPRESSED))
00434 button->bdata.bflags &= ~BLPRESSED;
00435 if((bflags & BLRELEASED))
00436 button->bdata.bflags &= ~BLRELEASED;
00437 if((bflags & BRPRESSED))
00438 button->bdata.bflags &= ~BRPRESSED;
00439 if((bflags & BRRELEASED))
00440 button->bdata.bflags &= ~BRRELEASED;
00441 if((bflags & BMPRESSED))
00442 button->bdata.bflags &= ~BMPRESSED;
00443 if((bflags & BMRELEASED))
00444 button->bdata.bflags &= ~BMRELEASED;
00445 if((bflags & BMOUSEOVER))
00446 button->bdata.bflags &= ~BMOUSEOVER;
00447 if((bflags & BDRAW))
00448 button->bdata.bflags &= ~BDRAW;
00449
00450 return button;
00451 }
00452
00453
00454
00455 BUTTONPTR standard_button_animations(BUTTONPTR button)
00456 {
00457 const int dx = 1, dy = 1, limit = 20;
00458 unsigned char r, g, b, a;
00459 al_unmap_rgba(button->bdata.b_color, &r, &g, &b, &a);
00460 if((button->bdata.bflags & BMOUSEOVER))
00461 {
00462 button->bdata.b_color = BCOLOR(r, g, b, 255);
00463 switch(sb)
00464 {
00465 default:
00466 case SBLEFT:
00467 case SBRIGHT:
00468 case SBUP:
00469 case SBDOWN:
00470 case SBNONE:
00471 break;
00472 case BBOUNCEHORZ:
00473 {
00474 if(button->bdata.sflags == SBRIGHT)
00475 button->bdata.x += dx;
00476 else if(button->bdata.sflags == SBLEFT)
00477 button->bdata.x -= dx;
00478 if(button->bdata.x >= button->bdata.ox+limit)
00479 button->bdata.sflags = SBLEFT;
00480 if(button->bdata.x <= button->bdata.ox-limit)
00481 button->bdata.sflags = SBRIGHT;
00482 if(button->bdata.sflags == 0)
00483 button->bdata.sflags = SBRIGHT;
00484 }
00485 break;
00486 case BSHIFTRIGHT:
00487 {
00488 if(button->bdata.x < button->bdata.ox+limit)
00489 button->bdata.x += 1;
00490 }
00491 break;
00492 case BSHIFTLEFT:
00493 {
00494 if(button->bdata.x > button->bdata.ox-limit)
00495 button->bdata.x -= 1;
00496 }
00497 break;
00498 case BBOUNCEVERT:
00499 {
00500 if(button->bdata.sflags == SBDOWN)
00501 button->bdata.y += dy;
00502 else if(button->bdata.sflags == SBUP)
00503 button->bdata.y -= dy;
00504 if(button->bdata.y >= button->bdata.oy+limit)
00505 button->bdata.sflags = SBUP;
00506 if(button->bdata.y <= button->bdata.oy-limit)
00507 button->bdata.sflags = SBDOWN;
00508 if(button->bdata.sflags == 0)
00509 button->bdata.sflags = SBDOWN;
00510 }
00511 }
00512 }
00513 else
00514 {
00515 button->bdata.b_color = BCOLOR(r, g, b, button->bdata.alpha);
00516 button->bdata.sflags = 0;
00517 if(button->bdata.x > button->bdata.ox)
00518 button->bdata.x -= 1;
00519 if(button->bdata.x < button->bdata.ox)
00520 button->bdata.x += 1;
00521 if(button->bdata.y > button->bdata.oy)
00522 button->bdata.y -= 1;
00523 if(button->bdata.y < button->bdata.oy)
00524 button->bdata.y += 1;
00525 }
00526 return button;
00527 }
00528
00529
00530
00531 BUTTONPTR custom_button_animations(BUTTONPTR button, CBANIMATIONS cb, float limit, BUTTON_CALLBACK bcall,
00532 void *data)
00533 {
00534 const int dx = 10, dy = 10;
00535 switch(cb)
00536 {
00537 case BNONE:
00538 break;
00539 case BRIGHT:
00540 {
00541 if(button->bdata.x < limit)
00542 button->bdata.x += dx;
00543 else
00544 {
00545 button->bdata.x = limit;
00546 button->bdata.ox = limit;
00547 bcall(button, data, CBANIMATION_CALL);
00548 button->bdata.aflags = BNONE;
00549 }
00550 }
00551 break;
00552 case BLEFT:
00553 {
00554 if(button->bdata.x > limit)
00555 button->bdata.x -= dx;
00556 else
00557 {
00558 button->bdata.x = limit;
00559 button->bdata.ox = limit;
00560 bcall(button, data, CBANIMATION_CALL);
00561 button->bdata.aflags = BNONE;
00562 }
00563 }
00564 break;
00565 case BUP:
00566 {
00567 if(button->bdata.y > limit)
00568 button->bdata.y -= dy;
00569 else
00570 {
00571 button->bdata.y = limit;
00572 button->bdata.oy = limit;
00573 bcall(button, data, CBANIMATION_CALL);
00574 button->bdata.aflags = BNONE;
00575 }
00576 }
00577 break;
00578 case BDOWN:
00579 {
00580 if(button->bdata.y < limit)
00581 button->bdata.y += dy;
00582 else
00583 {
00584 button->bdata.y = limit;
00585 button->bdata.oy = limit;
00586 bcall(button, data, CBANIMATION_CALL);
00587 button->bdata.aflags = BNONE;
00588 }
00589 }
00590 break;
00591 default:
00592 break;
00593 }
00594 return button;
00595 }
00596
00597
00598
00599 SBANIMATIONS set_standard_button_animation(SBANIMATIONS sb_new)
00600 {
00601 sb = sb_new;
00602 return sb;
00603 }
00604
00605
00606
00607 SBANIMATIONS get_standard_button_animation(void)
00608 {
00609 return sb;
00610 }
00611
00612
00613
00614 _Bool is_mouse_over_button(ALLEGRO_MOUSE_STATE *mouse, BUTTONPTR currentptr)
00615 {
00616 if((mouse->x >= currentptr->bdata.x && mouse->x <= (currentptr->bdata.x+currentptr->bimage->width)) &&
00617 (mouse->y >= currentptr->bdata.y && mouse->y <= (currentptr->bdata.y+currentptr->bimage->height)))
00618 return true;
00619 else
00620 return false;
00621 }
00622
00623
00624
00625 _Bool is_point_over_button(int x, int y, BUTTONPTR currentptr)
00626 {
00627 if((x >= currentptr->bdata.x && x <= (currentptr->bdata.x+currentptr->bimage->width)) &&
00628 (y >= currentptr->bdata.y && y <= (currentptr->bdata.y+currentptr->bimage->height)))
00629 return true;
00630 else
00631 return false;
00632 }
00633
00634
00635
00636 BIMAGESPTR create_new_button_image_list(char *labels[], char *images[], int num_elements)
00637 {
00638 BIMAGESPTR newptr;
00639 int i;
00640
00641 for(i = 0; i < num_elements; i++)
00642 {
00643 if((newptr = (BIMAGESPTR)malloc(sizeof(BIMAGES))) == NULL) return NULL;
00644 newptr->label = labels[i];
00645 newptr->button_image = al_load_png(images[i]);
00646 newptr->width = al_get_bitmap_width(newptr->button_image);
00647 newptr->height = al_get_bitmap_height(newptr->button_image);
00648 add_element_to_button_image_list(&bitoptr, &newptr);
00649 }
00650 return bitoptr;
00651 }
00652
00653
00654
00655 BIMAGESPTR add_element_to_button_image_list(BIMAGESPTR *firstptr, BIMAGESPTR *newptr)
00656 {
00657 BIMAGESPTR currentptr;
00658 if(*firstptr != NULL)
00659 {
00660 currentptr = (*firstptr)->prevbimage;
00661 currentptr->nextbimage = *newptr;
00662 (*newptr)->prevbimage = currentptr;
00663 (*firstptr)->prevbimage = *newptr;
00664 (*newptr)->nextbimage = *firstptr;
00665 }
00666 else
00667 {
00668 *firstptr = *newptr;
00669 (*newptr)->nextbimage = *newptr;
00670 (*newptr)->prevbimage = *newptr;
00671 }
00672 return *newptr;
00673 }
00674
00675
00676
00677 BIMAGESPTR search_button_image_list_for_element(BIMAGESPTR firstptr, char *label)
00678 {
00679 BIMAGESPTR currentptr = firstptr;
00680 if(currentptr == NULL) return NULL;
00681 do
00682 {
00683 if(strcmp(currentptr->label, label) == 0) break;
00684 currentptr = currentptr->nextbimage;
00685 } while(currentptr != firstptr);
00686
00687 if(strcmp(currentptr->label, label) != 0) return NULL;
00688 return currentptr;
00689 }
00690
00691
00692
00693
00694
00695