/* $Id: menu.c,v 1.29 2003/07/25 12:28:50 stpohle Exp $ */ /* menu's for the game */ #include #include "bomberclone.h" #include "gfx.h" /* draws a box size (x,y) */ void draw_menubox (int x, int y) { int x1, x2, y1, y2, i; SDL_Rect src, dest; x1 = gfx.res.x / 2 - x / 2; x2 = gfx.res.x / 2 + x / 2; y1 = gfx.res.y / 2 - y / 2; y2 = gfx.res.y / 2 + y / 2; if (gfx_locksurface (gfx.screen)) return; for (i = 0; i < 2; i++) { src.x = x1 + i; src.w = x2 + i; src.y = y1 + i; src.h = y2 + i; draw_shadefield (gfx.screen, &src, MENU_BG_SHADE_BRIGHT); } gfx_unlocksurface (gfx.screen); dest.w = src.w = x - 2; dest.h = src.h = y - 2; dest.x = src.x = x1 + 2; dest.y = src.y = y1 + 2; redraw_logo_shaded (x1 + 2, y1 + 2, x - 2, y - 2, MENU_BG_SHADE_DARK); } void draw_menu (char *text, _menu menu[], int *x, int *y) { int last, maxlen, y1, i; char vers[20]; // count the number of entrys for (last = 0, maxlen = 0; menu[last].index != -1; last++) if (((3+strlen (menu[last].text))*font[0].size.x) > maxlen) { *x = gfx.res.x / 2 - (3+strlen (menu[last].text))*font[0].size.x / 2; maxlen = (3+strlen (menu[last].text))*font[0].size.x; } if ((1+strlen (text))*font[2].size.x > maxlen) maxlen = (1 + strlen (text))*font[2].size.x; y1 = 2 * font[2].size.y + (last) * font[0].size.y; draw_menubox (maxlen + 8, y1); y1 = gfx.res.y / 2 - y1 / 2; font_setcolor (128,128,0, 2); font_draw ((gfx.res.x / 2) - ((font[2].size.x * strlen (text))/2) - 2, y1 - 2, text, 2); font_setcolor (255,255,0, 2); font_draw ((gfx.res.x / 2) - ((font[2].size.x * strlen (text))/2), y1, text, 2); *y = y1 = y1 + (font[2].size.y * 2); font_setcolor (255,255,255,0); for (i = 0; i < last; i++) { font_draw ((gfx.res.x / 2) - ((font[0].size.x * strlen (menu[i].text))/2) , y1, menu[i].text, 0); y1 = y1 + font[0].size.y; } font_setcolor (255,255,255,0); sprintf (vers, "v%s", VERSION); font_draw (gfx.res.x - font[0].size.x * strlen (vers), gfx.res.y - font[0].size.y, vers, 0); }; void draw_select (int select, _menu menu[], int x, int y) { SDL_Rect dest, src; int last; for (last = 0; menu[last].index != -1; last++) redraw_logo_shaded (x, y + last * font[0].size.y, gfx.menuselect.image->w, gfx.menuselect.image->h, MENU_BG_SHADE_DARK); dest.x = x; dest.y = y + select * font[0].size.y; src.x = 0; src.y = 0; src.w = font[0].size.y; src.h = font[0].size.y; SDL_BlitSurface (gfx.menuselect.image, &src, gfx.screen, &dest); }; int menu_loop (char *menutitle, _menu menu[], int lastselect) { int menuselect = lastselect, done = 0, ds = 0, lastentry, eventstate; SDL_Event event; Uint8 *keys; int keypressed = 0, bx, by; draw_logo (); draw_menu (menutitle, menu, &bx, &by); for (lastentry = 0; menu[lastentry].index != -1; lastentry++); draw_select (menuselect, menu, bx, by); SDL_Flip (gfx.screen); keys = SDL_GetKeyState (NULL); if (keys[SDLK_RETURN] || keys[SDLK_ESCAPE]) keypressed = 1; while (menuselect != -1 && done == 0) { /* do the network loop if we have to */ if (bman.gametype == GT_multi && bman.sock != -1) { network_loop (); eventstate = SDL_PollEvent (&event); } else eventstate = SDL_WaitEvent (&event); if ( eventstate != 0) switch (event.type) { case (SDL_QUIT): menuselect = -1; bman.state = GS_quit; done = 1; break; } /* keyboard handling */ keys = SDL_GetKeyState (NULL); if (keys[SDLK_ESCAPE] && (!keypressed)) { /* we want to quit */ keypressed = 1; menuselect = -1; } if (keys[SDLK_DOWN] && (!keypressed)) { menuselect++; while (menu[menuselect].index == 0) menuselect++; if (menu[menuselect].index == -1) { menuselect = 0; while (menu[menuselect].index == 0) menuselect++; } keypressed = 1; ds = 1; } if (keys[SDLK_UP] && (!keypressed)) { menuselect--; while (menu[menuselect].index == 0 && menuselect >= 0) menuselect--; if (menuselect == -1) menuselect = lastentry - 1; keypressed = 1; ds = 1; } if ((keys[SDLK_LCTRL] || keys[SDLK_RCTRL] || keys[SDLK_RETURN]) && (!keypressed) && (event.type = SDL_KEYDOWN)) { done = 1; keypressed = 1; // d_printf("return pressed - done=1\n"); } if (event.type == SDL_KEYUP) { // d_printf("keyup\n"); keypressed = 0; } else if (event.type == SDL_KEYDOWN) { // d_printf("keydown\n"); keypressed = 1; } if (ds) { draw_select (menuselect, menu, bx, by); ds = 0; SDL_Flip (gfx.screen); } s_delay (25); }; return menuselect; }; void menu_get_text (char *title, char *text, int len) { char t[255]; int done = 0, keypressed = 0, curpos, x, y, i, len_, eventstate, maxwidth; SDL_Event event; Uint8 *keys; text[len] = 0; curpos = strlen (text); if (curpos >= len) curpos = len - 1; strcpy (t, text); maxwidth = len * font[0].size.x; if (maxwidth < font[1].size.x * strlen (title)) maxwidth = font[1].size.x * strlen (title); draw_menubox (maxwidth + 8, font[1].size.y + font[0].size.y + 8); x = gfx.res.x / 2 - maxwidth / 2; y = gfx.res.y / 2 - (font[1].size.y + font[0].size.y) / 2; font_setcolor (128,64,0,1); font_draw (x - 2, y - 2, title, 1); font_setcolor (192,128,0,1); font_draw (x, y, title, 1); font_setcolor (192,192,192,0); y = y + font[1].size.y; if ((len - 1) * (font[0].size.x) > gfx.res.x) len_ = 40; else len_ = len; while (!done || keypressed == 1) { redraw_logo_shaded (x, y, font[0].size.x * len_, font[0].size.y, MENU_BG_SHADE_DARK); font_draw (x, y, t, 0); font_draw (x + font[0].size.x * curpos, y, "_", 0); SDL_Flip (gfx.screen); /* do the network loop if we have to */ if (bman.gametype == GT_multi && bman.sock != -1) { network_loop (); eventstate = SDL_PollEvent (&event); } else eventstate = SDL_WaitEvent (&event); if ( eventstate != 0) switch (event.type) { case (SDL_QUIT): bman.state = GS_quit; done = 1; } keys = SDL_GetKeyState (NULL); if (!keypressed && keys[SDLK_LEFT] && event.type == SDL_KEYDOWN) { if (curpos > 0) curpos--; keypressed = 1; } if (!keypressed && keys[SDLK_RIGHT] && event.type == SDL_KEYDOWN) { if (curpos < strlen (text) && curpos < len - 1) curpos++; keypressed = 1; } if (!keypressed && keys[SDLK_ESCAPE] && event.type == SDL_KEYDOWN) { done = 1; keypressed = 1; } if (!keypressed && keys[SDLK_RETURN] && event.type == SDL_KEYDOWN) { done = 1; keypressed = 1; strcpy (text, t); } if (!keypressed && keys[8] && event.type == SDL_KEYDOWN) if (curpos > 0) { curpos--; t[curpos] = t[curpos + 1]; t[curpos + 1] = t[curpos + 2]; keypressed = 1; } for (i = ' '; i <= 255; i++) if (i != 127 && !keypressed && keys[i] && event.type == SDL_KEYDOWN) { if (t[curpos] == 0) t[curpos + 1] = 0; t[curpos] = event.key.keysym.unicode; if (curpos < strlen (t) && curpos < len - 1) curpos++; keypressed = 1; } if (event.type == SDL_KEYUP) keypressed = 0; s_delay (25); } }; void menu_displaytext (char *title, char *text, Uint8 r, Uint8 g, Uint8 b) { int x, x1, y, y1, len, maxwidth; SDL_Rect dest; len = strlen (title); if (len < strlen (text)) len = strlen (text); maxwidth = strlen(title) * font[1].size.x; if (maxwidth < font[0].size.x * strlen (text)) maxwidth = font[0].size.x * strlen (text); y = (gfx.res.y - (font[1].size.y + font[1].size.y)) / 2; x = (gfx.res.x - maxwidth) / 2; y1 = font[0].size.y + font[1].size.y; x1 = maxwidth + 8; dest.x = x - 4; dest.y = y - 4; dest.h = y1 + 8; dest.w = x1 + 8; SDL_FillRect (gfx.screen, &dest, SDL_MapRGB (gfx.screen->format, r, g, b)); font_setcolor (128,128,128, 1); font_draw ((gfx.res.x - font[1].size.x * strlen (title)) / 2 - 2, y - 2, title, 1); font_setcolor (255,255,255, 1); font_draw ((gfx.res.x - font[1].size.x * strlen (title)) / 2, y, title, 1); font_setcolor (255,255,0, 1); font_draw ((gfx.res.x - font[0].size.x * strlen (text)) / 2, y + font[1].size.y + 2, text, 0); SDL_Flip (gfx.screen); }; void menu_displaymessage (char *title, char *text) { SDL_Event event; Uint8 *keys; int done = 0, keypressed = 0, eventstate; menu_displaytext (title, text, 64, 0, 0); while (done == 0 || (done == 1 && keypressed == 1)) { /* do the network loop if we have to */ if (bman.gametype == GT_multi && bman.sock != -1) { network_loop (); eventstate = SDL_PollEvent (&event); } else eventstate = SDL_WaitEvent (&event); if ( eventstate != 0) switch (event.type) { case (SDL_QUIT): done = 1; bman.state = GS_quit; } keys = SDL_GetKeyState (NULL); if (!keypressed && keys[SDLK_ESCAPE] && event.type == SDL_KEYDOWN) { done = 1; keypressed = 1; } if (!keypressed && keys[SDLK_RETURN] && event.type == SDL_KEYDOWN) { done = 1; keypressed = 1; } if (event.type == SDL_KEYUP) keypressed = 0; s_delay (100); } }; void menu_clearkeybuff () { SDL_Event event; Uint8 *keys; int i; SDL_PollEvent (&event); keys = SDL_GetKeyState (NULL); if (!(keys[SDLK_RETURN])) return; for (i = 0; i < 20; i++) { s_delay (25); SDL_PollEvent (&event); keys = SDL_GetKeyState (NULL); if (!(keys[SDLK_RETURN])) return; } menu_displaytext ("", " Press Return ", 64, 0, 0); while (keys[SDLK_RETURN]) { s_delay (25); SDL_PollEvent (&event); keys = SDL_GetKeyState (NULL); } } /*** *** Menu Selection of a file ior a directory ***/ #define DIRSCRMAX 10 /* draws the selection on the screen.. dirstart - first entry do display flags - flags what should be shown directorys or files selected - Selected file in the list */ int menu_dir_draw (char *title, _direntry * dirstart, int start, int selected) { _direntry *de = dirstart; int maxlen = 0, maxchar = 0, pos = 0; SDL_Rect wnd; /* look for the longest name */ maxlen = font[1].size.x * strlen (title); for (; de != NULL; de = de->next) if (maxlen < font[0].size.x * strlen (de->name)) maxlen = font[0].size.x * strlen (de->name); if (maxlen > gfx.res.x - 32) maxchar = (gfx.res.x - 40) / font[0].size.x; else maxchar = maxlen / font[0].size.x; wnd.h = DIRSCRMAX * font[0].size.y * 2; wnd.w = maxlen; wnd.x = (gfx.res.x - wnd.w) / 2; wnd.y = (gfx.res.y - wnd.h) / 2; draw_menubox (wnd.w + 8, wnd.h + 8); font_setcolor (128,64,0,1); font_draw ((gfx.res.x - font[1].size.x * strlen (title)) / 2 - 2, wnd.y - 2, title, 1); font_setcolor (192,128,0,1); font_draw ((gfx.res.x - font[1].size.x * strlen (title)) / 2, wnd.y, title, 1); for (de = dirstart, pos = 0; de != NULL && pos < start + DIRSCRMAX - 1; de = de->next, pos++) { if (pos >= start && pos < (start + DIRSCRMAX - 1)) { if (pos == selected) font_setcolor (255,255,255, 0); else font_setcolor (128,128,128, 0); font_draw (wnd.x + gfx.menuselect.image->w + 2, 8 + wnd.y + (1 + pos - start) * font[0].size.y * 2, de->name, 0); } } return (de == NULL); } char * menu_dir_select (char *title, char *path, signed char dirflags) { _direntry *destart, *de; SDL_Event event; Uint8 *keys; int max = 0, sel = 0, keypressed = 0, done = 0, listend = 0, liststart = 0, oldsel = -1, eventstate; /* get the directory list and count the numbers */ destart = s_getdir (path); destart = s_dirfilter (destart, dirflags); for (max = 0, de = destart; de != NULL; de = de->next) max++; if (max <= 0) return NULL; while (done == 0 || (done == 1 && keypressed == 1)) { if (sel != oldsel) { listend = menu_dir_draw (title, destart, liststart, sel); SDL_Flip (gfx.screen); oldsel = sel; } /* do the network loop if we have to */ if (bman.gametype == GT_multi && bman.sock != -1) { network_loop (); eventstate = SDL_PollEvent (&event); } else eventstate = SDL_WaitEvent (&event); if ( eventstate != 0) switch (event.type) { case (SDL_QUIT): sel = -1; bman.state = GS_quit; done = 1; } /* keyboard handling */ keys = SDL_GetKeyState (NULL); if (keys[SDLK_DOWN] && event.type == SDL_KEYDOWN && keypressed == 0) { keypressed = 1; sel++; if (!(listend)) /* if we can move this list down */ liststart++; if (sel >= max) { liststart = 0; sel = 0; } } if (keys[SDLK_UP] && event.type == SDL_KEYDOWN && keypressed == 0) { keypressed = 1; sel--; if (liststart > 0) liststart--; if (sel < 0) { sel = max - 1; if (sel > (DIRSCRMAX / 2)) liststart = sel - (DIRSCRMAX / 2); } } if (keys[SDLK_ESCAPE] && event.type == SDL_KEYDOWN) { keypressed = 1; return NULL; } if (!keys[SDLK_ESCAPE] && event.type == SDL_KEYUP) keypressed = 0; if (keys[SDLK_RETURN] && event.type == SDL_KEYDOWN) { done = 1; keypressed = 1; } if (!keys[SDLK_RETURN] && event.type == SDL_KEYUP) keypressed = 0; s_delay (25); } for (max = 0, de = destart; max != sel && de != NULL; de = de->next) max++; if (de == NULL) return NULL; return de->name; }; #undef DIRSCRMAX