You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bomberclone/src/menu.c

474 lines
12 KiB

/* $Id: menu.c,v 1.11 2003/05/07 14:33:24 stpohle Exp $ */
/* menu's for the game */
#include <SDL.h>
#include "bomberclone.h"
#include "gfx.h"
#define MENU_BG_SHADE_DARK -64
#define MENU_BG_SHADE_BRIGHT 64
/* 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,
x1,
y1,
i;
char vers[20];
// count the number of entrys
for (last = 0, maxlen = 0; menu[last].index != -1; last++)
if (strlen (menu[last].text) > maxlen)
maxlen = strlen (menu[last].text);
if (strlen (text) > maxlen)
maxlen = strlen (text);
*x = x1 = gfx.res.x / 2 - ((gfx.font.size.x + (maxlen * (gfx.font.size.x - 2))) / 2);
y1 = gfx.res.y / 2 - ((last + 2) * gfx.font.size.y / 2);
x1 = x1 + gfx.font.size.x;
draw_menubox (maxlen * gfx.font.size.x, (last + 3) * gfx.font.size.y);
draw_text (x1, y1, text, 1);
*y = y1 = y1 + (gfx.font.size.y * 2);
for (i = 0; i < last; i++) {
draw_text (x1, y1, menu[i].text, 1);
y1 = y1 + gfx.font.size.y;
}
sprintf (vers, "v%s", VERSION);
draw_text (gfx.res.x - gfx.font.size.x * strlen (vers), gfx.res.y - gfx.font.size.y, vers, 1);
};
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 * gfx.font.size.y, gfx.menuselect.image->w, gfx.menuselect.image->h , MENU_BG_SHADE_DARK);
dest.x = x;
dest.y = y + select * gfx.font.size.y;
src.x = 0;
src.y = 0;
src.w = gfx.font.size.x;
src.h = gfx.font.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,
lastentry;
SDL_Event event;
Uint8 *keys;
int keypressed = 0;
int bx,
by;
draw_logo ();
draw_menu (menutitle, menu, &bx, &by);
SDL_Flip (gfx.screen);
for (lastentry = 0; menu[lastentry].index != -1; lastentry++);
while ((!done || keypressed == 1) && bman.state != GS_quit) {
draw_select (menuselect, menu, bx, by);
SDL_Flip (gfx.screen);
/* do the network loop if we have to */
if (bman.gametype == GT_multi && bman.sock != -1)
network_loop ();
if (SDL_PollEvent (&event) != 0)
switch (event.type) {
case (SDL_QUIT):
menuselect = -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;
menuselect++;
if (menuselect >= lastentry)
menuselect = 0;
}
if (keys[SDLK_UP] && event.type == SDL_KEYDOWN && keypressed == 0) {
keypressed = 1;
menuselect--;
if (menuselect < 0)
menuselect = lastentry - 1;
}
if (keys[SDLK_ESCAPE] && event.type == SDL_KEYDOWN) {
keypressed = 1;
return -1;
}
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 (100);
};
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_;
SDL_Event event;
Uint8 *keys;
text[len]=0;
curpos = strlen (text);
if(curpos>=len) curpos=len-1;
strcpy (t, text);
if (len > strlen (title)) {
len_ = len;
}
else {
len_ = strlen (title);
}
draw_logo ();
y = (gfx.res.y - 2 * gfx.font.size.y) / 2;
x = (gfx.res.x - (gfx.font.size.x - 4) * len_) / 2;
draw_menubox ((gfx.font.size.x - 1) * len_, 4 * gfx.font.size.y);
draw_text (x, y, title, 1);
y = y + gfx.font.size.y;
x = (gfx.res.x - (gfx.font.size.x - 4) * len) / 2;
if ((len - 1) * (gfx.font.size.x - 4) > gfx.res.x)
len_ = 40;
else
len_ = len;
while (!done || keypressed == 1) {
redraw_logo_shaded (x, y, (gfx.font.size.x - 4) * len_, gfx.font.size.y, MENU_BG_SHADE_DARK);
draw_text (x, y, t, 1);
draw_text (x + (gfx.font.size.x - 4) * curpos, y, "_", 1);
SDL_Flip (gfx.screen);
/* do the network loop if we have to */
if (bman.gametype == GT_multi && bman.sock != -1)
network_loop ();
if (SDL_PollEvent (&event) != 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 (100);
}
};
void
menu_displaytext (char *title, char *text, Uint8 r, Uint8 g, Uint8 b)
{
int x,
x1,
y,
y1,
len;
SDL_Rect dest;
len = strlen (title);
if (len < strlen (text))
len = strlen (text);
y = (gfx.res.y - 2 * gfx.block.y) / 2;
x = (gfx.res.x - (gfx.font.size.x - 4) * len) / 2;
y1 = gfx.font.size.y * 3;
x1 = ((gfx.font.size.x - 4) * len);
dest.x = x;
dest.y = y - 4;
dest.h = y1;
dest.w = x1;
SDL_FillRect (gfx.screen, &dest, SDL_MapRGB (gfx.screen->format, r, g, b));
y = (gfx.res.y - 2 * gfx.block.y) / 2;
draw_text ((gfx.res.x - (gfx.font.size.x - 4) * strlen (title)) / 2, y, title, 1);
draw_text ((gfx.res.x - (gfx.font.size.x - 4) * strlen (text)) / 2, y + gfx.font.size.y, text,
0);
SDL_Flip (gfx.screen);
};
void
menu_displaymessage (char *title, char *text)
{
SDL_Event event;
Uint8 *keys;
int done = 0,
keypressed = 0;
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 ();
if (SDL_PollEvent (&event) != 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);
}
};
/***
*** 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, pos = 0;
SDL_Rect wnd;
/* look for the longest name */
for (; de != NULL; de = de->next)
if (maxlen < strlen (de->name))
maxlen = strlen (de->name);
maxlen = strlen (title);
if (maxlen * gfx.font.size.x > gfx.res.x - 32)
maxlen = (gfx.res.x - 40) /gfx.font.size.x;
wnd.h = DIRSCRMAX * gfx.font.size.y * 2;
wnd.w = maxlen * gfx.font.size.x;
wnd.x = (gfx.res.x - wnd.w) / 2;
wnd.y = (gfx.res.y - wnd.h) / 2;
draw_menubox (wnd.w, wnd.h);
draw_text ((gfx.res.x - (gfx.font.size.x/1.17) * strlen (title)) / 2, wnd.y + 4, title, 1);
for (de = dirstart, pos = 0; de != NULL && pos < start + DIRSCRMAX - 1; de=de->next, pos++) {
if (pos >= start && pos < (start + DIRSCRMAX - 1))
draw_text (wnd.x + gfx.menuselect.image->w + 2, 8 + wnd.y + (1+pos-start) * gfx.font.size.y * 2, de->name, (pos == selected));
}
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;
/* 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)) {
/* do the network loop if we have to */
listend = menu_dir_draw (title, destart, liststart, sel);
SDL_Flip (gfx.screen);
if (bman.gametype == GT_multi && bman.sock != -1)
network_loop ();
if (SDL_PollEvent (&event) != 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 (100);
}
for (max = 0, de = destart; max != sel && de != NULL; de = de->next)
max++;
if (de == NULL)
return NULL;
return de->name;
};
#undef DIRSCRMAX