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.
521 lines
14 KiB
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 ();
|
|
};
|