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

521 lines
14 KiB

/* $Id: menu.c,v 1.39 2004/02/05 22:59:04 stpohle Exp $
* Menuhandling */
#include "basic.h"
#include "bomberclone.h"
#include "menu.h"
#include "menugui.h"
#include "network.h"
#include "ogcache-client.h"
_menuitem menuitems[MENU_MAXENTRYS];
_menu menu;
int menu_looprunning = 0;
/* delete all informations and create a totally new menuscreen */
void menu_new (char *title, int x, int y) {
int i;
if (menu.oldscreen != NULL)
menu_delete();
strncpy (menu.title, title, MENU_TITLELEN);
menu.items = NULL;
menu.focus = NULL;
for (i = 0; i < MENU_MAXENTRYS; i++) {
menuitems[i].id = -1;
menuitems[i].type = -1;
menuitems[i].next = NULL;
}
/* save the old background screen */
x = (1 + (int)(x / menu.images[1]->w)) * menu.images[1]->w;
y = (1 + (int)(y / menu.images[3]->h)) * menu.images[3]->h;
menu.oldscreenpos.x = ((gfx.res.x - (x + 2*menu.images[0]->w)) / 2);
menu.oldscreenpos.y = ((gfx.res.y - (y + 2*menu.images[0]->h)) / 2);
menu.oldscreenpos.w = x + 2*menu.images[0]->w;
menu.oldscreenpos.h = y + 2*menu.images[0]->h;
menu.oldscreen = gfx_copyscreen (&menu.oldscreenpos);
menu.focus = NULL;
menu_looprunning = 0;
};
/* restore the screen and reset all needed informations, free the old screen */
void menu_delete () {
gfx_restorescreen (menu.oldscreen, &menu.oldscreenpos);
gfx_blitdraw ();
SDL_FreeSurface (menu.oldscreen);
menu.oldscreen = NULL;
menuitems[0].next = NULL;
menu.items = NULL;
menu_looprunning = 0;
if (GS_RUNNING)
draw_field ();
};
/* draw only a part of the Screen */
void menu_draw_background (SDL_Rect *updaterect) {
int x,y, dx, dy;
SDL_Rect dest, cdest, src, csrc, window;
y = 0; // start at the updaterect. start pos
for (; y <= (menu.oldscreenpos.h - 2*menu.images[0]->h - 1)/menu.images[4]->h; y++) {
x = 0; // start at the updaterect. start pos
for (; x <= (menu.oldscreenpos.w - 2*menu.images[0]->w - 1)/menu.images[4]->w; x++) {
dest.x = x * menu.images[4]->w; // start pos
dest.y = y * menu.images[4]->h;
dx = (1+x) * menu.images[4]->w; // end pos
if (dx >= (menu.oldscreenpos.w - 2*menu.images[0]->w))
dest.w = menu.images[4]->w - (dx - (menu.oldscreenpos.w - 2*menu.images[0]->w));
else
dest.w = menu.images[4]->w;
dy = (1+y) * menu.images[4]->h;
if (dy >= (menu.oldscreenpos.h - 2*menu.images[0]->h))
dest.h = menu.images[4]->h - (dy - (menu.oldscreenpos.h - 2*menu.images[0]->h));
else
dest.h = menu.images[4]->h;
if (dest.w > 0 || dest.h > 0) {
dest.x += MENUOFFSET_X;
dest.y += MENUOFFSET_Y;
src.x = 0; src.y = 0; src.h = dest.h; src.w = dest.w;
if (updaterect == NULL)
gfx_blit (menu.images[4], &src, gfx.screen, &dest, 10000);
else {
window = *updaterect;
window.x += MENUOFFSET_X;
window.y += MENUOFFSET_Y;
rect_clipping (&src, &dest, &window, &csrc, &cdest);
if (csrc.w < UINT16_HALF && csrc.h < UINT16_HALF && cdest.w < UINT16_HALF && cdest.h < UINT16_HALF)
gfx_blit (menu.images[4], &csrc, gfx.screen, &cdest, 10000);
}
}
}
}
};
/* draws the menuborders, this function does not save the background */
void menu_draw_border () {
SDL_Rect dest;
int i, dx;
// draw top left
dest.x = menu.oldscreenpos.x;
dest.y = menu.oldscreenpos.y;
dest.w = menu.images[0]->w;
dest.h = menu.images[0]->h;
gfx_blit (menu.images[0], NULL, gfx.screen, &dest, 10000);
// draw top and below
for (i = 0; i < ((menu.oldscreenpos.w - (2*menu.images[0]->w)) / menu.images[1]->w); i++) {
dest.x = menu.oldscreenpos.x + menu.images[0]->w + (i * menu.images[1]->w);
dest.y = menu.oldscreenpos.y;
dest.w = menu.images[1]->w;
dest.h = menu.images[1]->h;
gfx_blit (menu.images[1], NULL, gfx.screen, &dest, 10000);
dest.y = menu.oldscreenpos.y + menu.oldscreenpos.h - menu.images[7]->h;
gfx_blit (menu.images[7], NULL, gfx.screen, &dest, 10000);
}
// draw top right
dest.x = menu.oldscreenpos.x + menu.oldscreenpos.w - menu.images[2]->w;
dest.y = menu.oldscreenpos.y;
dest.w = menu.images[2]->w;
dest.h = menu.images[2]->h;
gfx_blit (menu.images[2], NULL, gfx.screen, &dest, 10000);
// draw left and right
for (i = 0; i < ((menu.oldscreenpos.h - (2*menu.images[0]->h)) / menu.images[3]->h); i++) {
dest.x = menu.oldscreenpos.x;
dest.y = menu.oldscreenpos.y + menu.images[0]->h + menu.images[3]->h * i;
dest.w = menu.images[1]->w;
dest.h = menu.images[1]->h;
gfx_blit (menu.images[3], NULL, gfx.screen, &dest, 10000);
dest.x = menu.oldscreenpos.x + menu.oldscreenpos.w - menu.images[5]->w;
gfx_blit (menu.images[5], NULL, gfx.screen, &dest, 10000);
}
// draw below left
dest.x = menu.oldscreenpos.x;
dest.y = menu.oldscreenpos.y + menu.oldscreenpos.h - menu.images[7]->h;
dest.w = menu.images[6]->w;
dest.h = menu.images[6]->h;
gfx_blit (menu.images[6], NULL, gfx.screen, &dest, 10000);
// draw below right
dest.x = menu.oldscreenpos.x + menu.oldscreenpos.w - menu.images[8]->w;
dest.y = menu.oldscreenpos.y + menu.oldscreenpos.h - menu.images[8]->h;
dest.w = menu.images[8]->w;
dest.h = menu.images[8]->h;
gfx_blit (menu.images[8], NULL, gfx.screen, &dest, 10000);
menu_draw_background (NULL);
// draw title
dx = menu.oldscreenpos.x + (menu.oldscreenpos.w - font[2].size.x*strlen (menu.title)) / 2;
font_gfxdrawbold (dx, menu.oldscreenpos.y + menu.images[0]->h + 8, menu.title, 2, COLOR_brown, 2, 10000);
font_gfxdraw (dx, menu.oldscreenpos.y + menu.images[0]->h + 8, menu.title, 2, COLOR_yellow, 10000);
};
/* draw the menu, even it is only put into the gfx_blitlist. gfx_blitdraw needs
* to be called before the menu is drawed on the screen */
void menu_draw () {
_menuitem *m;
if (!menu_looprunning) return;
menu_draw_border ();
for (m = menu.items; m != NULL; m = m->next)
menu_draw_menuitem (m);
};
/* draw an item on the screen */
inline void menu_draw_menuitem (_menuitem *m) {
if (!menu_looprunning) return;
switch (m->type) {
case (MENU_label):
menu_draw_label (m);
break;
case (MENU_button):
menu_draw_button (m);
break;
case (MENU_bool):
menu_draw_bool (m);
break;
case (MENU_entrytext):
case (MENU_entryint16):
case (MENU_entryint32):
case (MENU_entryfloat):
menu_draw_entry (m);
break;
case (MENU_list):
menu_draw_list (m);
break;
}
};
/* reload all variables into all menuelements */
void menu_reload () {
_menuitem *m;
for (m = menu.items; m != NULL; m = m->next)
menu_reload_menuitem (m);
};
/* reload variable into menuelement */
inline void menu_reload_menuitem (_menuitem *m) {
switch (m->type) {
case (MENU_entrytext):
case (MENU_entryint16):
case (MENU_entryint32):
case (MENU_entryfloat):
menu_entry_restore (m);
break;
default:
break;
}
};
/* find the last menuitem in the list. */
int menu_getlastitem (_menuitem *first) {
int i = 0;
_menuitem *result = first;
if (first == NULL) // no first item there
return -1;
for (;result->next != NULL; result = result->next)
i++;
return i;
}
/* get the last and the first id number */
_menuitem *menu_get_firstid () {
_menuitem *result = NULL, *mi = menu.items;
for (mi = menu.items; mi != NULL; mi = mi->next)
if ((result == NULL || mi->id < result->id) && mi->id != -1)
result = mi;
return result;
};
_menuitem *menu_get_lastid () {
_menuitem *result = NULL, *mi = menu.items;
for (mi = menu.items; mi != NULL; mi = mi->next)
if ((result == NULL || mi->id > result->id) && mi->id != -1)
result = mi;
return result;
};
/* change the focus to the givin element */
void menu_change_focus (_menuitem *newfocus) {
_menuitem *oldmi;
if (newfocus == menu.focus) // no focus change
return;
/* lose focus */
if (menu.focus != NULL) {
switch (menu.focus->type) {
case (MENU_entryfloat):
case (MENU_entryint16):
case (MENU_entryint32):
case (MENU_entrytext):
menu_entry_lose_focus (menu.focus);
break;
}
}
/* draw the old and the new element */
oldmi = menu.focus;
menu.focus = newfocus;
if (oldmi != NULL)
menu_draw_menuitem (oldmi);
menu_draw_menuitem (menu.focus);
/* get focus ... no function yet */
d_printf ("menu_change_focus: ID:%d Name:%s\n", menu.focus->id, menu.focus->label);
};
/* focus next element, order by ID */
void menu_focus_next () {
_menuitem *newmi = menu.focus, *mi, *oldmi = menu.focus;
for (mi = menu.items; mi != NULL; mi = mi->next)
if (mi->id != oldmi->id && mi->id > menu.focus->id && (mi->id < newmi->id || newmi == oldmi))
newmi = mi;
if (newmi == oldmi)
menu_change_focus (menu_get_firstid());
else
menu_change_focus (newmi);
};
/* focus previous element, order by ID */
void menu_focus_prev () {
_menuitem *newmi = menu.focus, *mi, *oldmi = menu.focus;
for (mi = menu.items; mi != NULL; mi = mi->next)
if (mi->id != -1 && mi->id != oldmi->id && mi->id < oldmi->id && (mi->id > newmi->id || newmi == oldmi))
newmi = mi;
if (newmi == oldmi)
menu_change_focus (menu_get_lastid());
else
menu_change_focus (newmi);
};
/* focus element with id ID */
void menu_focus_id (int id) {
_menuitem *mi, *oldmi = menu.focus;
for (mi = menu.items; mi != NULL; mi = mi->next)
if (mi->id == id)
menu_change_focus (mi);
menu_draw_menuitem (oldmi);
if (menu.focus != oldmi)
menu_draw_menuitem (menu.focus);
};
/* menu loop, programm will stay in here as long as no ESCAPE is pressed
* and as long as no Button is clicked. Return of -2 means something needs to reordered */
int menu_loop () {
SDL_Event event;
Uint8 *keys;
int keypressed = 0, done = 0, eventstate = 0, reorder = 0;
menu_looprunning = 1;
/* check if the focus is set to something, if not
* set the focus to the first item */
if (menu.focus == NULL) {
menu.focus = menu.items;
menu_focus_id (0);
}
if (menu.focus == NULL) {
d_fatal ("menu_loop: focus == NULL, something went wrong\n");
menu_looprunning = 0;
return -1;
}
keys = SDL_GetKeyState (NULL);
if (keys[SDLK_RETURN] || keys[SDLK_ESCAPE])
keypressed = 1;
timestamp = SDL_GetTicks (); // needed for time sync.
menu_draw();
while (!reorder && !done && bman.state != GS_quit) {
gfx_blitdraw ();
/* do the network loop if we have to */
if (bman.sock > 0) {
network_loop ();
if (bman.notifygamemaster)
reorder = ogc_loop ();
else
reorder = 0;
}
eventstate = SDL_PollEvent (&event);
if (eventstate >= 1) {
switch (event.type) {
case (SDL_QUIT):
bman.state = GS_quit;
done = 1;
return -1;
break;
case (SDL_KEYDOWN): /* focus next element */
if (event.key.keysym.sym == SDLK_TAB) {
keys = SDL_GetKeyState (NULL);
if (keys[SDLK_LSHIFT] || keys[SDLK_RSHIFT])
menu_focus_prev ();
else
menu_focus_next ();
break;
}
else if (event.key.keysym.sym == SDLK_ESCAPE) {
return -1;
break;
}
default: /* push events to the menu items */
switch (menu.focus->type) {
case (MENU_button):
done = menu_event_button (menu.focus, &event);
break;
case (MENU_bool):
done = menu_event_bool (menu.focus, &event);
break;
case (MENU_entrytext):
case (MENU_entryfloat):
case (MENU_entryint16):
case (MENU_entryint32):
done = menu_event_entry (menu.focus, &event);
break;
case (MENU_label):
break;
case (MENU_list):
done = menu_event_list (menu.focus, &event);
break;
}
}
}
menu.focusto -= timediff;
if (menu.focusto <= 0.0f) {
menu.focusto = MENU_FOCUSVIS_BLINKTO;
menu.focusvis = !menu.focusvis;
menu_draw_menuitem (menu.focus);
}
s_calctimesync ();
}
menu_looprunning = 0;
if (reorder) {
menu.focus->changed=1;
return -2;
}
return menu.focus->id;
};
/* create a list with all directory entrys,
* except we can't put everything in the list because the list is too smal.
* Return: number of entrys, Pointers will be set*/
int menu_create_dirlist (char *path, signed char dirflags, _charlist *cl, int maxentry) {
int cnt;
_direntry *destart, *de;
destart = s_getdir (path);
destart = s_dirfilter (destart, dirflags);
for (cnt = 0, de = destart; (de != NULL && cnt < maxentry); de = de->next) {
strncpy (cl[cnt].text, de->name, 255);
if (de->next != NULL)
cl[cnt].next = &cl[cnt+1];
else
cl[cnt].next = NULL;
cnt++;
}
return cnt;
};
/* displays a file selectionmenu and
* returns the name of the file */
static char menu_dir_name[LEN_PATHFILENAME];
char *
menu_dir_select (char *title, char *path, signed char dirflags) {
_charlist flist[MAX_DIRENTRYS];
int flcnt, menuselect;
_charlist *selfile = NULL;
flcnt = menu_create_dirlist (path, dirflags, flist, MAX_DIRENTRYS);
menu_new (title, 300, 300);
menu_create_list ("Dir", -1, 50, 200, 200, flist, &selfile, 1);
menu_create_button ("OK", -1, 270, 150, 0);
menuselect = menu_loop ();
menu_delete ();
if (menuselect < 0 || selfile-&flist[0] < 0 || selfile-&flist[0] >= flcnt)
return NULL;
strncpy (menu_dir_name, selfile->text, LEN_PATHFILENAME);
return menu_dir_name;
};
/* display a message on the screen and wait untill ESC is pressed */
void menu_displaymessage (char *title, char *line1, char *line2, char *line3, char *line4) {
menu_new (title, 500, 150);
if (line1 != NULL) menu_create_label (line1, -1, 55, 0);
if (line2 != NULL) menu_create_label (line2, -1, 75, 0);
if (line3 != NULL) menu_create_label (line3, -1, 95, 0);
if (line4 != NULL) menu_create_label (line4, -1, 115, 0);
menu_loop ();
menu_delete ();
};
/* display a text on the screen and return */
void menu_displaytext (char *title, char *line1, char *line2, char *line3, char *line4) {
menu_new (title, 500, 150);
if (line1 != NULL) menu_create_label (line1, -1, 55, 0);
if (line2 != NULL) menu_create_label (line2, -1, 75, 0);
if (line3 != NULL) menu_create_label (line3, -1, 95, 0);
if (line4 != NULL) menu_create_label (line4, -1, 115, 0);
menu_looprunning = 1;
menu_draw ();
gfx_blitdraw ();
SDL_FreeSurface (menu.oldscreen);
menu.oldscreen = NULL;
menuitems[0].next = NULL;
menu.items = NULL;
menu_looprunning = 0;
gfx_blitdraw ();
};