// menus.cpp: ingame menu system (also used for scores and serverlist) #include "cube.h" #import "Menu.h" #import "Command.h" #import "MenuItem.h" #import "Player.h" static OFMutableArray *menuStack; static OFMutableArray *menus; static int vmenu = -1; void menuset(int menu) { if ((vmenu = menu) >= 1) [Player.player1 resetMovement]; if (vmenu == 1) menus[1].menusel = 0; } COMMAND(showmenu, ARG_1STR, ^ (OFString *name) { int i = 0; for (Menu *menu in menus) { if (i > 1 && [menu.name isEqual: name]) { menuset(i); return; } i++; } }) void sortmenu() { [menus[0].items sort]; } void refreshservers(); bool rendermenu() { if (vmenu < 0) { [menuStack removeAllObjects]; return false; } if (vmenu == 1) refreshservers(); Menu *m = menus[vmenu]; OFString *title; if (vmenu > 1) title = [OFString stringWithFormat: @"[ %@ menu ]", m.name]; else title = m.name; int mdisp = m.items.count; int w = 0; for (int i = 0; i < mdisp; i++) { int x = text_width(m.items[i].text); if (x > w) w = x; } int tw = text_width(title); if (tw > w) w = tw; int step = FONTH / 4 * 5; int h = (mdisp + 2) * step; int y = (VIRTH - h) / 2; int x = (VIRTW - w) / 2; blendbox(x - FONTH / 2 * 3, y - FONTH, x + w + FONTH / 2 * 3, y + h + FONTH, true); draw_text(title, x, y, 2); y += FONTH * 2; if (vmenu) { int bh = y + m.menusel * step; blendbox( x - FONTH, bh - 10, x + w + FONTH, bh + FONTH + 10, false); } for (int j = 0; j < mdisp; j++) { draw_text(m.items[j].text, x, y, 2); y += step; } return true; } void newmenu(OFString *name) { if (menus == nil) menus = [[OFMutableArray alloc] init]; [menus addObject: [Menu menuWithName: name]]; } COMMAND(newmenu, ARG_1STR, ^ (OFString *name) { newmenu(name); }) void menumanual(int m, int n, OFString *text) { if (n == 0) [menus[m].items removeAllObjects]; MenuItem *item = [MenuItem itemWithText: text action: @""]; [menus[m].items addObject: item]; } COMMAND(menuitem, ARG_2STR, ^ (OFString *text, OFString *action) { Menu *menu = menus.lastObject; MenuItem *item = [MenuItem itemWithText: text action: (action.length > 0 ? action : text)]; [menu.items addObject: item]; }) bool menukey(int code, bool isdown) { if (vmenu <= 0) return false; int menusel = menus[vmenu].menusel; if (isdown) { if (code == SDLK_ESCAPE) { menuset(-1); if (menuStack.count > 0) { menuset(menuStack.lastObject.intValue); [menuStack removeLastObject]; } return true; } else if (code == SDLK_UP || code == -4) menusel--; else if (code == SDLK_DOWN || code == -5) menusel++; int n = menus[vmenu].items.count; if (menusel < 0) menusel = n - 1; else if (menusel >= n) menusel = 0; menus[vmenu].menusel = menusel; } else { if (code == SDLK_RETURN || code == -2) { OFString *action = menus[vmenu].items[menusel].action; if (vmenu == 1) connects(getservername(menusel)); if (menuStack == nil) menuStack = [[OFMutableArray alloc] init]; [menuStack addObject: @(vmenu)]; menuset(-1); execute(action, true); } } return true; }