Cube  menus.m at [51fb59fc93]

File src/menus.m artifact 9134766c32 part of check-in 51fb59fc93


// menus.cpp: ingame menu system (also used for scores and serverlist)

#include "cube.h"

#import "Menu.h"

#import "DynamicEntity.h"
#import "MenuItem.h"

static OFMutableArray<OFNumber *> *menuStack;
static OFMutableArray<Menu *> *menus;
static int vmenu = -1;

void
menuset(int menu)
{
	if ((vmenu = menu) >= 1)
		[player1 resetMovement];
	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;
	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)

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];
}

void
menuitem(OFString *text, OFString *action)
{
	Menu *menu = menus.lastObject;

	MenuItem *item =
	    [MenuItem itemWithText: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;
}