Artifact e754271834a9e6177657b1494a71e1e2c107ff787b47392b31339f859d6408b1:
- File
src/menus.mm
— part of check-in
[489124a92f]
at
2025-03-16 10:11:39
on branch trunk
— Use one autorelease pool per frame
This way, nowhere else autorelease pools need to be managed. (user: js, size: 3087) [annotate] [blame] [check-ins using]
// menus.cpp: ingame menu system (also used for scores and serverlist) #include "cube.h" #import "Menu.h" #import "MenuItem.h" static OFMutableArray<OFNumber *> *menuStack; static OFMutableArray<Menu *> *menus; static int vmenu = -1; void menuset(int menu) { if ((vmenu = menu) >= 1) resetmovement(player1); if (vmenu == 1) menus[1].menusel = 0; } void showmenu(OFString *name) { int i = 0; for (Menu *menu in menus) { if (i > 1 && [menu.name isEqual:name]) { menuset(i); return; } i++; } } COMMAND(showmenu, ARG_1STR) 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; loopi(mdisp) { 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); } loopj(mdisp) { 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 alloc] initWithName:name]]; } COMMAND(newmenu, ARG_1STR) void menumanual(int m, int n, OFString *text) { if (n == 0) [menus[m].items removeAllObjects]; MenuItem *item = [[MenuItem alloc] initWithText:text action:@""]; [menus[m].items addObject:item]; } void menuitem(OFString *text, OFString *action) { Menu *menu = menus.lastObject; MenuItem *item = [[MenuItem alloc] initWithText:text action:(action.length > 0 ? action : text)]; [menu.items addObject:item]; } COMMAND(menuitem, ARG_2STR) 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; }