2004-08-23 00:15:46 +00:00
|
|
|
#include "quakedef.h"
|
|
|
|
|
|
|
|
int omousex;
|
|
|
|
int omousey;
|
|
|
|
qboolean mousemoved;
|
2004-09-07 18:19:22 +00:00
|
|
|
qboolean bindingactive;
|
2004-08-23 00:15:46 +00:00
|
|
|
|
|
|
|
void Draw_TextBox (int x, int y, int width, int lines)
|
|
|
|
{
|
2004-12-24 08:45:56 +00:00
|
|
|
mpic_t *p;
|
2004-08-23 00:15:46 +00:00
|
|
|
int cx, cy;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
// draw left side
|
|
|
|
cx = x;
|
|
|
|
cy = y;
|
|
|
|
p = Draw_SafeCachePic ("gfx/box_tl.lmp");
|
|
|
|
|
|
|
|
if (!p) //assume none exist
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (p)
|
|
|
|
Draw_TransPic (cx, cy, p);
|
|
|
|
p = Draw_SafeCachePic ("gfx/box_ml.lmp");
|
|
|
|
for (n = 0; n < lines; n++)
|
|
|
|
{
|
|
|
|
cy += 8;
|
|
|
|
if (p)
|
|
|
|
Draw_TransPic (cx, cy, p);
|
|
|
|
}
|
|
|
|
p = Draw_SafeCachePic ("gfx/box_bl.lmp");
|
|
|
|
if (p)
|
|
|
|
Draw_TransPic (cx, cy+8, p);
|
|
|
|
|
|
|
|
// draw middle
|
|
|
|
cx += 8;
|
|
|
|
while (width > 0)
|
|
|
|
{
|
|
|
|
cy = y;
|
|
|
|
p = Draw_SafeCachePic ("gfx/box_tm.lmp");
|
|
|
|
if (p)
|
|
|
|
Draw_TransPic (cx, cy, p);
|
|
|
|
p = Draw_SafeCachePic ("gfx/box_mm.lmp");
|
|
|
|
for (n = 0; n < lines; n++)
|
|
|
|
{
|
|
|
|
cy += 8;
|
|
|
|
if (n == 1)
|
|
|
|
p = Draw_SafeCachePic ("gfx/box_mm2.lmp");
|
|
|
|
if (p)
|
|
|
|
Draw_TransPic (cx, cy, p);
|
|
|
|
}
|
|
|
|
p = Draw_SafeCachePic ("gfx/box_bm.lmp");
|
|
|
|
if (p)
|
|
|
|
Draw_TransPic (cx, cy+8, p);
|
|
|
|
width -= 2;
|
|
|
|
cx += 16;
|
|
|
|
}
|
|
|
|
|
|
|
|
// draw right side
|
|
|
|
cy = y;
|
|
|
|
p = Draw_SafeCachePic ("gfx/box_tr.lmp");
|
|
|
|
if (p)
|
|
|
|
Draw_TransPic (cx, cy, p);
|
|
|
|
p = Draw_SafeCachePic ("gfx/box_mr.lmp");
|
|
|
|
for (n = 0; n < lines; n++)
|
|
|
|
{
|
|
|
|
cy += 8;
|
|
|
|
if (p)
|
|
|
|
Draw_TransPic (cx, cy, p);
|
|
|
|
}
|
|
|
|
p = Draw_SafeCachePic ("gfx/box_br.lmp");
|
|
|
|
if (p)
|
|
|
|
Draw_TransPic (cx, cy+8, p);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Draw_BigFontString(int x, int y, const char *text)
|
|
|
|
{
|
|
|
|
int sx, sy;
|
2004-12-24 08:45:56 +00:00
|
|
|
mpic_t *p;
|
2004-08-23 00:15:46 +00:00
|
|
|
p = Draw_SafeCachePic ("gfx/menu/bigfont.lmp");
|
|
|
|
|
|
|
|
while(*text)
|
|
|
|
{
|
|
|
|
if (*text >= 'a' && *text <= 'z')
|
|
|
|
{
|
|
|
|
sx = ((*text-'a')%8)*20;
|
|
|
|
sy = ((*text-'a')/8)*20;
|
|
|
|
}
|
|
|
|
else if (*text >= 'A' && *text <= 'Z')
|
|
|
|
{
|
|
|
|
sx = ((*text-'A')%8)*20;
|
|
|
|
sy = ((*text-'A')/8)*20;
|
|
|
|
}
|
|
|
|
else// if (*text <= ' ')
|
|
|
|
{
|
|
|
|
sx=-1;
|
|
|
|
sy=-1;
|
|
|
|
}
|
|
|
|
if(sx>=0)
|
|
|
|
Draw_SubPic(x, y, p, sx, sy, 20, 20);
|
|
|
|
x+=20;
|
|
|
|
text++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
char *menudotstyle;
|
|
|
|
int maxdots;
|
|
|
|
int mindot;
|
|
|
|
int dotofs;
|
|
|
|
|
|
|
|
void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu)
|
|
|
|
{
|
|
|
|
int i;
|
2004-12-24 08:45:56 +00:00
|
|
|
mpic_t *p;
|
2004-08-23 00:15:46 +00:00
|
|
|
while (option)
|
|
|
|
{
|
2004-09-07 18:19:22 +00:00
|
|
|
if (mousemoved && !bindingactive)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
|
|
|
if (omousex > xpos+option->common.posx && omousex < xpos+option->common.posx+option->common.width)
|
|
|
|
if (omousey > ypos+option->common.posy && omousey < ypos+option->common.posy+option->common.height)
|
|
|
|
{
|
2004-09-07 18:19:22 +00:00
|
|
|
if (menu->selecteditem != option)
|
|
|
|
{
|
|
|
|
S_LocalSound ("misc/menu1.wav");
|
|
|
|
menu->selecteditem = option;
|
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
if (menu->cursoritem)
|
|
|
|
menu->cursoritem->common.posy = menu->selecteditem->common.posy;
|
|
|
|
}
|
|
|
|
}
|
2005-01-26 18:56:49 +00:00
|
|
|
if (!option->common.ishidden)
|
2004-08-23 00:15:46 +00:00
|
|
|
switch(option->common.type)
|
|
|
|
{
|
|
|
|
case mt_text:
|
|
|
|
if (!option->text.text)
|
|
|
|
Draw_Character (xpos+option->common.posx, ypos+option->common.posy, 12+((int)(realtime*4)&1));
|
|
|
|
else if (option->text.isred)
|
|
|
|
Draw_Alt_String(xpos+option->common.posx, ypos+option->common.posy, option->text.text);
|
|
|
|
else
|
|
|
|
Draw_String(xpos+option->common.posx, ypos+option->common.posy, option->text.text);
|
|
|
|
break;
|
|
|
|
case mt_button:
|
|
|
|
if (!menu->cursoritem && menu->selecteditem == option)
|
|
|
|
Draw_Alt_String(xpos+option->common.posx, ypos+option->common.posy, option->button.text);
|
|
|
|
else
|
|
|
|
Draw_String(xpos+option->common.posx, ypos+option->common.posy, option->button.text);
|
|
|
|
break;
|
|
|
|
case mt_buttonbigfont:
|
|
|
|
Draw_BigFontString(xpos+option->common.posx, ypos+option->common.posy, option->button.text);
|
|
|
|
break;
|
|
|
|
case mt_menudot:
|
|
|
|
i = (int)(realtime * 10)%maxdots;
|
|
|
|
p = Draw_SafeCachePic(va(menudotstyle, i+mindot ));
|
|
|
|
Draw_TransPic(xpos+option->common.posx, ypos+option->common.posy+dotofs, p);
|
|
|
|
break;
|
|
|
|
case mt_picture:
|
|
|
|
p = NULL;
|
|
|
|
if (menu->selecteditem && menu->selecteditem->common.posx == option->common.posx && menu->selecteditem->common.posy == option->common.posy)
|
|
|
|
p = Draw_SafeCachePic(va("%s_sel", option->picture.picturename));
|
|
|
|
|
|
|
|
if (!p)
|
|
|
|
p = Draw_SafeCachePic(option->picture.picturename);
|
|
|
|
|
|
|
|
Draw_TransPic (xpos+option->common.posx, ypos+option->common.posy, p);
|
|
|
|
break;
|
|
|
|
case mt_childwindow:
|
|
|
|
MenuDrawItems(xpos+option->common.posx, ypos+option->common.posy, ((menu_t *)option->custom.data)->options, (menu_t *)option->custom.data);
|
|
|
|
break;
|
|
|
|
case mt_box:
|
|
|
|
Draw_TextBox(xpos+option->common.posx, ypos+option->common.posy, option->box.width, option->box.height);
|
|
|
|
break;
|
|
|
|
case mt_slider:
|
|
|
|
if (option->slider.var)
|
|
|
|
{
|
|
|
|
#define SLIDER_RANGE 10
|
2004-09-07 23:15:19 +00:00
|
|
|
float range;
|
2004-08-23 00:15:46 +00:00
|
|
|
int i;
|
|
|
|
int x = xpos+option->common.posx;
|
|
|
|
int y = ypos+option->common.posy;
|
|
|
|
|
2004-09-07 23:15:19 +00:00
|
|
|
range = (option->slider.current - option->slider.min)/(option->slider.max-option->slider.min);
|
|
|
|
|
2004-08-23 00:15:46 +00:00
|
|
|
if (option->slider.text)
|
|
|
|
{
|
|
|
|
if (!menu->cursoritem && menu->selecteditem == option)
|
|
|
|
Draw_Alt_String(x, y, option->slider.text);
|
|
|
|
else
|
|
|
|
Draw_String(x, y, option->slider.text);
|
|
|
|
x += strlen(option->slider.text)*8+28;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (range < 0)
|
|
|
|
range = 0;
|
|
|
|
if (range > 1)
|
|
|
|
range = 1;
|
|
|
|
Draw_Character (x-8, y, 128);
|
|
|
|
for (i=0 ; i<SLIDER_RANGE ; i++)
|
|
|
|
Draw_Character (x + i*8, y, 129);
|
|
|
|
Draw_Character (x+i*8, y, 130);
|
|
|
|
Draw_Character (x + (SLIDER_RANGE-1)*8 * range, y, 131);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case mt_checkbox:
|
|
|
|
{
|
|
|
|
int x = xpos+option->common.posx;
|
|
|
|
int y = ypos+option->common.posy;
|
|
|
|
qboolean on;
|
|
|
|
if (option->check.func)
|
|
|
|
on = option->check.func(option, CHK_CHECKED);
|
|
|
|
else if (!option->check.var)
|
2004-09-13 03:10:10 +00:00
|
|
|
on = option->check.value;
|
|
|
|
else if (option->check.bits) //bits is a bitmask for use with cvars (users can be clumsy, so bittage of 0 uses non-zero as true, but sets only bit 1)
|
|
|
|
{
|
|
|
|
if (option->check.var->latched_string)
|
|
|
|
on = atoi(option->check.var->latched_string)&option->check.bits;
|
|
|
|
else
|
|
|
|
on = (int)(option->check.var->value)&option->check.bits;
|
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
else
|
2004-09-13 03:10:10 +00:00
|
|
|
{
|
|
|
|
if (option->check.var->latched_string)
|
|
|
|
on = !!atof(option->check.var->latched_string);
|
|
|
|
else
|
|
|
|
on = !!option->check.var->value;
|
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
|
|
|
|
if (option->check.text)
|
|
|
|
{
|
|
|
|
if (!menu->cursoritem && menu->selecteditem == option)
|
|
|
|
Draw_Alt_String(x, y, option->check.text);
|
|
|
|
else
|
|
|
|
Draw_String(x, y, option->check.text);
|
|
|
|
x += strlen(option->check.text)*8+28;
|
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
if (on)
|
|
|
|
Draw_Character (x, y, 131);
|
|
|
|
else
|
|
|
|
Draw_Character (x, y, 129);
|
|
|
|
#endif
|
|
|
|
if (on)
|
|
|
|
Draw_String (x, y, "on");
|
|
|
|
else
|
|
|
|
Draw_String (x, y, "off");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case mt_edit:
|
|
|
|
{
|
|
|
|
int x = xpos+option->common.posx;
|
|
|
|
int y = ypos+option->common.posy;
|
|
|
|
|
|
|
|
if (!menu->cursoritem && menu->selecteditem == option)
|
|
|
|
Draw_Alt_String(x, y, option->edit.caption);
|
|
|
|
else
|
|
|
|
Draw_String(x, y, option->edit.caption);
|
|
|
|
x+=strlen(option->edit.caption)*8+8;
|
|
|
|
Draw_TextBox(x-8, y-8, 16, 1);
|
|
|
|
Draw_String(x, y, option->edit.text);
|
|
|
|
|
|
|
|
if (menu->selecteditem == option && (int)(realtime*4) & 1)
|
|
|
|
{
|
|
|
|
x += strlen(option->edit.text)*8;
|
|
|
|
Draw_Character(x, y, 11);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2004-09-07 18:19:22 +00:00
|
|
|
case mt_bind:
|
|
|
|
{
|
|
|
|
int x = xpos+option->common.posx;
|
|
|
|
int y = ypos+option->common.posy;
|
|
|
|
int l;
|
|
|
|
int keys[2];
|
|
|
|
char *keyname;
|
|
|
|
|
|
|
|
if (!menu->cursoritem && menu->selecteditem == option)
|
|
|
|
Draw_Alt_String(x, y, option->bind.caption);
|
|
|
|
else
|
|
|
|
Draw_String(x, y, option->bind.caption);
|
|
|
|
x += strlen(option->bind.caption)*8+28;
|
|
|
|
{
|
|
|
|
l = strlen (option->bind.command);
|
|
|
|
|
|
|
|
M_FindKeysForCommand (option->bind.command, keys);
|
|
|
|
|
|
|
|
if (bindingactive && menu->selecteditem == option)
|
|
|
|
{
|
|
|
|
Draw_String (x, y, "Press key");
|
|
|
|
}
|
|
|
|
else if (keys[0] == -1)
|
|
|
|
{
|
|
|
|
Draw_String (x, y, "???");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
keyname = Key_KeynumToString (keys[0]);
|
|
|
|
Draw_String (x, y, keyname);
|
|
|
|
x += strlen(keyname) * 8;
|
|
|
|
if (keys[1] != -1)
|
|
|
|
{
|
|
|
|
Draw_String (x + 8, y, "or");
|
|
|
|
Draw_String (x + 32, y, Key_KeynumToString (keys[1]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2004-08-23 00:15:46 +00:00
|
|
|
case mt_combo:
|
|
|
|
{
|
|
|
|
int x = xpos+option->common.posx;
|
|
|
|
int y = ypos+option->common.posy;
|
|
|
|
|
|
|
|
Draw_String(x, y, option->combo.caption);
|
|
|
|
x += strlen(option->combo.caption)*8+24;
|
|
|
|
Draw_String(x, y, option->combo.options[option->combo.selectedoption]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case mt_custom:
|
|
|
|
option->custom.draw(xpos+option->common.posx, ypos+option->common.posy, &option->custom, menu);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Sys_Error("Bad item type\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
option = option->common.next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MenuDraw(menu_t *menu)
|
|
|
|
{
|
|
|
|
if (menu->event)
|
|
|
|
menu->event(menu);
|
|
|
|
menu->xpos = ((vid.width - 320)>>1);
|
|
|
|
MenuDrawItems(menu->xpos, menu->ypos, menu->options, menu);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
menutext_t *MC_AddWhiteText(menu_t *menu, int x, int y, const char *text, qboolean rightalign)
|
|
|
|
{
|
|
|
|
menutext_t *n = Z_Malloc(sizeof(menutext_t));
|
|
|
|
n->common.type = mt_text;
|
|
|
|
n->common.iszone = true;
|
|
|
|
n->common.posx = x;
|
|
|
|
n->common.posy = y;
|
|
|
|
n->text = text;
|
|
|
|
|
|
|
|
if (rightalign && text)
|
|
|
|
n->common.posx -= strlen(text)*8;
|
|
|
|
|
|
|
|
n->common.next = menu->options;
|
|
|
|
menu->options = (menuoption_t *)n;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
menutext_t *MC_AddBufferedText(menu_t *menu, int x, int y, const char *text, qboolean rightalign, qboolean red)
|
|
|
|
{
|
|
|
|
menutext_t *n = Z_Malloc(sizeof(menutext_t) + strlen(text)+1);
|
|
|
|
n->common.type = mt_text;
|
|
|
|
n->common.iszone = true;
|
|
|
|
n->common.posx = x;
|
|
|
|
n->common.posy = y;
|
|
|
|
n->text = (char *)(n+1);
|
|
|
|
strcpy((char *)(n+1), text);
|
|
|
|
n->isred = red;
|
|
|
|
|
|
|
|
if (rightalign && text)
|
|
|
|
n->common.posx -= strlen(text)*8;
|
|
|
|
|
|
|
|
n->common.next = menu->options;
|
|
|
|
menu->options = (menuoption_t *)n;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
menutext_t *MC_AddRedText(menu_t *menu, int x, int y, const char *text, qboolean rightalign)
|
|
|
|
{
|
|
|
|
menutext_t *n;
|
|
|
|
n = MC_AddWhiteText(menu, x, y, text, false);
|
|
|
|
n->isred = true;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
2004-09-07 18:19:22 +00:00
|
|
|
menubind_t *MC_AddBind(menu_t *menu, int x, int y, const char *caption, char *command)
|
|
|
|
{
|
|
|
|
menubind_t *n = Z_Malloc(sizeof(menutext_t) + strlen(caption)+1 + strlen(command)+1);
|
|
|
|
n->common.type = mt_bind;
|
|
|
|
n->common.iszone = true;
|
|
|
|
n->common.posx = x;
|
|
|
|
n->common.posy = y;
|
|
|
|
n->caption = (char *)(n+1);
|
|
|
|
strcpy(n->caption, caption);
|
|
|
|
n->command = n->caption+strlen(n->caption)+1;
|
|
|
|
strcpy(n->command, command);
|
|
|
|
|
|
|
|
n->common.next = menu->options;
|
|
|
|
menu->options = (menuoption_t *)n;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
2004-08-23 00:15:46 +00:00
|
|
|
menupicture_t *MC_AddPicture(menu_t *menu, int x, int y, char *picname)
|
|
|
|
{
|
|
|
|
menupicture_t *n;
|
|
|
|
if (!qrenderer)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
Draw_SafeCachePic(picname);
|
|
|
|
|
|
|
|
n = Z_Malloc(sizeof(menupicture_t) + strlen(picname)+1);
|
|
|
|
n->common.type = mt_picture;
|
|
|
|
n->common.iszone = true;
|
|
|
|
n->common.posx = x;
|
|
|
|
n->common.posy = y;
|
|
|
|
n->picturename = (char *)(n+1);
|
|
|
|
strcpy(n->picturename, picname);
|
|
|
|
|
|
|
|
n->common.next = menu->options;
|
|
|
|
menu->options = (menuoption_t *)n;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
menupicture_t *MC_AddCenterPicture(menu_t *menu, int y, char *picname)
|
|
|
|
{
|
|
|
|
int x;
|
2004-12-24 08:45:56 +00:00
|
|
|
mpic_t *p;
|
2004-08-23 00:15:46 +00:00
|
|
|
|
|
|
|
if (!qrenderer)
|
|
|
|
return NULL;
|
|
|
|
p = Draw_SafeCachePic(picname);
|
|
|
|
if (!p)
|
|
|
|
x = 320/2;
|
|
|
|
else
|
|
|
|
x = (320-p->width)/2;
|
|
|
|
|
|
|
|
return MC_AddPicture(menu, x, y, picname);
|
|
|
|
}
|
|
|
|
|
|
|
|
menupicture_t *MC_AddCursor(menu_t *menu, int x, int y)
|
|
|
|
{
|
|
|
|
int q1, h2, q2;
|
|
|
|
menupicture_t *n = Z_Malloc(sizeof(menupicture_t));
|
|
|
|
n->common.type = mt_menudot;
|
|
|
|
n->common.iszone = true;
|
|
|
|
n->common.posx = x;
|
|
|
|
n->common.posy = y;
|
|
|
|
|
|
|
|
n->common.next = menu->options;
|
|
|
|
menu->options = (menuoption_t *)n;
|
|
|
|
|
|
|
|
|
|
|
|
q1 = COM_FDepthFile("gfx/menudot1.lmp", true);
|
|
|
|
h2 = COM_FDepthFile("gfx/menu/menudot1.lmp", true);
|
|
|
|
q2 = COM_FDepthFile("pics/m_cursor1.pcx", true);
|
|
|
|
if (q2 < h2 && q2 < q1)
|
|
|
|
{ //AND QUAKE 2 WINS!!!
|
|
|
|
menudotstyle = "m_cursor%i";
|
|
|
|
mindot = 0;
|
|
|
|
maxdots = 15;
|
|
|
|
dotofs=0;
|
|
|
|
}
|
|
|
|
else if (h2 < q1)
|
|
|
|
{ //AND THE WINNER IS HEXEN 2!!!
|
|
|
|
menudotstyle = "gfx/menu/menudot%i.lmp";
|
|
|
|
mindot = 1;
|
|
|
|
maxdots = 8;
|
|
|
|
dotofs=-5;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ //QUAKE 1 WINS BY DEFAULT!
|
|
|
|
menudotstyle = "gfx/menudot%i.lmp";
|
|
|
|
mindot = 1;
|
|
|
|
maxdots = 6;
|
|
|
|
dotofs=0;
|
|
|
|
}
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
menuedit_t *MC_AddEdit(menu_t *menu, int x, int y, char *text, char *def)
|
|
|
|
{
|
|
|
|
menuedit_t *n = Z_Malloc(sizeof(menuedit_t));
|
|
|
|
n->common.type = mt_edit;
|
|
|
|
n->common.iszone = true;
|
|
|
|
n->common.posx = x;
|
|
|
|
n->common.posy = y;
|
|
|
|
n->caption = text;
|
|
|
|
Q_strncpyz(n->text, def, sizeof(n->text));
|
|
|
|
|
|
|
|
n->common.next = menu->options;
|
|
|
|
menu->options = (menuoption_t *)n;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
menuedit_t *MC_AddEditCvar(menu_t *menu, int x, int y, char *text, char *name)
|
|
|
|
{
|
|
|
|
menuedit_t *n = Z_Malloc(sizeof(menuedit_t)+strlen(text)+1);
|
|
|
|
cvar_t *cvar;
|
|
|
|
cvar = Cvar_Get(name, "", CVAR_USERCREATED|CVAR_ARCHIVE, NULL); //well, this is a menu/
|
|
|
|
n->common.type = mt_edit;
|
|
|
|
n->common.iszone = true;
|
|
|
|
n->common.posx = x;
|
|
|
|
n->common.posy = y;
|
|
|
|
n->common.width = (strlen(text)+17)*8;
|
|
|
|
n->common.height = 8;
|
|
|
|
n->caption = (char *)(n+1);
|
|
|
|
strcpy((char *)(n+1), text);
|
|
|
|
n->cvar = cvar;
|
|
|
|
Q_strncpyz(n->text, cvar->string, sizeof(n->text));
|
|
|
|
|
|
|
|
n->common.next = menu->options;
|
|
|
|
menu->options = (menuoption_t *)n;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
menubox_t *MC_AddBox(menu_t *menu, int x, int y, int width, int height)
|
|
|
|
{
|
|
|
|
menubox_t *n = Z_Malloc(sizeof(menupicture_t));
|
|
|
|
n->common.type = mt_box;
|
|
|
|
n->common.iszone = true;
|
|
|
|
n->common.posx = x;
|
|
|
|
n->common.posy = y;
|
|
|
|
n->width = width;
|
|
|
|
n->height = height;
|
|
|
|
|
|
|
|
n->common.next = menu->options;
|
|
|
|
menu->options = (menuoption_t *)n;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
menucustom_t *MC_AddCustom(menu_t *menu, int x, int y, const char *data)
|
|
|
|
{
|
|
|
|
menucustom_t *n = Z_Malloc(sizeof(menucustom_t));
|
|
|
|
n->common.type = mt_custom;
|
|
|
|
n->common.iszone = true;
|
|
|
|
n->common.posx = x;
|
|
|
|
n->common.posy = y;
|
|
|
|
n->data = NULL;
|
|
|
|
|
|
|
|
n->common.next = menu->options;
|
|
|
|
menu->options = (menuoption_t *)n;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
2004-09-13 03:10:10 +00:00
|
|
|
menucheck_t *MC_AddCheckBox(menu_t *menu, int x, int y, const char *text, cvar_t *var, int bits)
|
2004-08-23 00:15:46 +00:00
|
|
|
{
|
|
|
|
menucheck_t *n = Z_Malloc(sizeof(menucheck_t)+strlen(text)+1);
|
|
|
|
n->common.type = mt_checkbox;
|
|
|
|
n->common.iszone = true;
|
|
|
|
n->common.posx = x;
|
|
|
|
n->common.posy = y;
|
|
|
|
n->common.height = 8;
|
|
|
|
n->common.width = (strlen(text)+7)*8;
|
|
|
|
n->text = (char *)(n+1);
|
|
|
|
strcpy((char *)(n+1), text);
|
|
|
|
n->var = var;
|
2004-09-13 03:10:10 +00:00
|
|
|
n->bits = bits;
|
2004-08-23 00:15:46 +00:00
|
|
|
|
|
|
|
n->common.next = menu->options;
|
|
|
|
menu->options = (menuoption_t *)n;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
menuslider_t *MC_AddSlider(menu_t *menu, int x, int y, const char *text, cvar_t *var, float min, float max)
|
|
|
|
{
|
|
|
|
menuslider_t *n = Z_Malloc(sizeof(menuslider_t)+strlen(text)+1);
|
|
|
|
n->common.type = mt_slider;
|
|
|
|
n->common.iszone = true;
|
|
|
|
n->common.posx = x;
|
|
|
|
n->common.posy = y;
|
|
|
|
n->common.height = 8;
|
|
|
|
n->common.width = (strlen(text)+SLIDER_RANGE+5)*8;
|
|
|
|
n->var = var;
|
|
|
|
n->text = (char *)(n+1);
|
|
|
|
strcpy((char *)(n+1), text);
|
|
|
|
|
|
|
|
if (var)
|
|
|
|
n->current = var->value;
|
|
|
|
|
|
|
|
n->min = min;
|
|
|
|
n->max = max;
|
|
|
|
|
|
|
|
n->common.next = menu->options;
|
|
|
|
menu->options = (menuoption_t *)n;
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
menucombo_t *MC_AddCombo(menu_t *menu, int x, int y, const char *caption, const char **ops, int initialvalue)
|
|
|
|
{
|
|
|
|
menucombo_t *n = Z_Malloc(sizeof(menucombo_t));
|
|
|
|
n->common.type = mt_combo;
|
|
|
|
n->common.iszone = true;
|
|
|
|
n->common.posx = x;
|
|
|
|
n->common.posy = y;
|
|
|
|
n->common.height = 8;
|
|
|
|
n->common.width = strlen(caption)*8;
|
|
|
|
n->caption = caption;
|
|
|
|
n->options = ops;
|
|
|
|
|
|
|
|
n->common.next = menu->options;
|
|
|
|
menu->options = (menuoption_t *)n;
|
|
|
|
|
|
|
|
n->numoptions = 0;
|
|
|
|
while(ops[n->numoptions])
|
|
|
|
{
|
|
|
|
n->common.width = strlen(caption)*8+strlen(ops[n->numoptions])*8;
|
|
|
|
n->numoptions++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (initialvalue >= n->numoptions)
|
|
|
|
{
|
|
|
|
Con_Printf("WARNING: Fixed initialvalue for %s\n", caption);
|
|
|
|
initialvalue = n->numoptions-1;
|
|
|
|
}
|
|
|
|
n->selectedoption = initialvalue;
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
menucombo_t *MC_AddCvarCombo(menu_t *menu, int x, int y, const char *caption, cvar_t *cvar, const char **ops, const char **values)
|
|
|
|
{
|
|
|
|
menucombo_t *n = Z_Malloc(sizeof(menucombo_t));
|
|
|
|
n->common.type = mt_combo;
|
|
|
|
n->common.iszone = true;
|
|
|
|
n->common.posx = x;
|
|
|
|
n->common.posy = y;
|
|
|
|
n->common.height = 8;
|
|
|
|
n->common.width = strlen(caption)*8;
|
|
|
|
n->caption = caption;
|
|
|
|
n->options = ops;
|
|
|
|
n->values = values;
|
|
|
|
n->cvar = cvar;
|
|
|
|
|
|
|
|
n->selectedoption = 0;
|
|
|
|
|
|
|
|
n->common.next = menu->options;
|
|
|
|
menu->options = (menuoption_t *)n;
|
|
|
|
|
|
|
|
n->numoptions = 0;
|
|
|
|
while(ops[n->numoptions])
|
|
|
|
{
|
|
|
|
if (!strcmp(values[n->numoptions], cvar->string))
|
|
|
|
n->selectedoption = n->numoptions;
|
|
|
|
n->common.width = strlen(caption)*8+strlen(ops[n->numoptions])*8;
|
|
|
|
n->numoptions++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
menubutton_t *MC_AddConsoleCommand(menu_t *menu, int x, int y, const char *text, const char *command)
|
|
|
|
{
|
|
|
|
menubutton_t *n = Z_Malloc(sizeof(menubutton_t)+strlen(text)+1+strlen(command)+1);
|
|
|
|
n->common.type = mt_button;
|
|
|
|
n->common.iszone = true;
|
|
|
|
n->common.posx = x;
|
|
|
|
n->common.posy = y;
|
|
|
|
n->common.height = 8;
|
|
|
|
n->common.width = strlen(text)*8;
|
|
|
|
n->text = (char *)(n+1);
|
|
|
|
strcpy((char *)(n+1), text);
|
|
|
|
n->command = n->text + strlen(n->text)+1;
|
|
|
|
strcpy((char *)n->command, command);
|
|
|
|
|
|
|
|
n->common.next = menu->options;
|
|
|
|
menu->options = (menuoption_t *)n;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
menubutton_t *MC_AddConsoleCommandBigFont(menu_t *menu, int x, int y, const char *text, const char *command)
|
|
|
|
{
|
|
|
|
menubutton_t *n = Z_Malloc(sizeof(menubutton_t)+strlen(text)+1+strlen(command)+1);
|
|
|
|
n->common.type = mt_buttonbigfont;
|
|
|
|
n->common.iszone = true;
|
|
|
|
n->common.posx = x;
|
|
|
|
n->common.posy = y;
|
|
|
|
n->common.height = 8;
|
|
|
|
n->common.width = strlen(text)*8;
|
|
|
|
n->text = (char *)(n+1);
|
|
|
|
strcpy((char *)(n+1), text);
|
|
|
|
n->command = n->text + strlen(n->text)+1;
|
|
|
|
strcpy((char *)n->command, command);
|
|
|
|
|
|
|
|
n->common.next = menu->options;
|
|
|
|
menu->options = (menuoption_t *)n;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
menubutton_t *MC_AddCommand(menu_t *menu, int x, int y, char *text, qboolean (*command) (union menuoption_s *,struct menu_s *,int))
|
|
|
|
{
|
|
|
|
menubutton_t *n = Z_Malloc(sizeof(menubutton_t));
|
|
|
|
n->common.type = mt_button;
|
|
|
|
n->common.iszone = true;
|
|
|
|
n->common.posx = x;
|
|
|
|
n->common.posy = y;
|
|
|
|
n->text = text;
|
|
|
|
n->command = NULL;
|
|
|
|
n->key = command;
|
|
|
|
|
|
|
|
n->common.next = menu->options;
|
|
|
|
menu->options = (menuoption_t *)n;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
menubutton_t *VARGS MC_AddConsoleCommandf(menu_t *menu, int x, int y, const char *text, char *command, ...)
|
|
|
|
{
|
|
|
|
va_list argptr;
|
|
|
|
static char string[1024];
|
|
|
|
menubutton_t *n;
|
|
|
|
|
|
|
|
va_start (argptr, command);
|
|
|
|
_vsnprintf (string,sizeof(string)-1, command,argptr);
|
|
|
|
va_end (argptr);
|
|
|
|
|
|
|
|
n = Z_Malloc(sizeof(menubutton_t) + strlen(string)+1);
|
|
|
|
n->common.type = mt_button;
|
|
|
|
n->common.iszone = true;
|
|
|
|
n->common.posx = x;
|
|
|
|
n->common.posy = y;
|
|
|
|
n->text = text;
|
|
|
|
n->command = (char *)(n+1);
|
|
|
|
strcpy((char *)(n+1), string);
|
|
|
|
|
|
|
|
n->common.next = menu->options;
|
|
|
|
menu->options = (menuoption_t *)n;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MC_Slider_Key(menuslider_t *option, int key)
|
|
|
|
{
|
|
|
|
float range = (option->current - option->min)/(option->max-option->min);
|
|
|
|
|
|
|
|
if (key == K_LEFTARROW)
|
|
|
|
{
|
|
|
|
range -= 0.1;
|
|
|
|
if (range < 0)
|
|
|
|
range = 0;
|
|
|
|
option->current = range = (range * (option->max-option->min)) + option->min;
|
|
|
|
if (option->var)
|
2004-09-07 23:15:19 +00:00
|
|
|
Cvar_SetValue(option->var, range);
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
else if (key == K_RIGHTARROW)
|
|
|
|
{
|
|
|
|
range += 0.1;
|
|
|
|
if (range > 1)
|
|
|
|
range = 1;
|
|
|
|
option->current = range = (range * (option->max-option->min)) + option->min;
|
|
|
|
if (option->var)
|
2004-09-07 23:15:19 +00:00
|
|
|
Cvar_SetValue(option->var, range);
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
else if (key == K_ENTER || key == K_MOUSE1)
|
|
|
|
{
|
|
|
|
range += 0.1;
|
|
|
|
|
|
|
|
if (range >= 1.05)
|
|
|
|
range = 0;
|
|
|
|
if (range > 1)
|
|
|
|
range = 1;
|
|
|
|
option->current = range = (range * (option->max-option->min)) + option->min;
|
|
|
|
if (option->var)
|
|
|
|
Cvar_SetValue(option->var, range);
|
|
|
|
}
|
2004-09-07 18:19:22 +00:00
|
|
|
else
|
|
|
|
return;
|
2004-08-23 00:15:46 +00:00
|
|
|
|
2004-09-07 18:19:22 +00:00
|
|
|
S_LocalSound ("misc/menu2.wav");
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MC_CheckBox_Key(menucheck_t *option, int key)
|
|
|
|
{
|
|
|
|
if (key != K_ENTER && key != K_LEFTARROW && key != K_RIGHTARROW && key != K_MOUSE1)
|
|
|
|
return;
|
|
|
|
if (option->func)
|
|
|
|
option->func((union menuoption_s *)option, CHK_TOGGLE);
|
|
|
|
else if (!option->var)
|
|
|
|
option->value = !option->value;
|
|
|
|
else
|
2004-09-07 18:19:22 +00:00
|
|
|
{
|
2004-09-13 03:10:10 +00:00
|
|
|
if (option->bits)
|
|
|
|
{
|
|
|
|
int old;
|
|
|
|
if (option->var->latched_string)
|
|
|
|
old = atoi(option->var->latched_string);
|
|
|
|
else
|
|
|
|
old = option->var->value;
|
|
|
|
|
|
|
|
if (old & option->bits)
|
|
|
|
Cvar_SetValue(option->var, old&~option->bits);
|
|
|
|
else
|
|
|
|
Cvar_SetValue(option->var, old|option->bits);
|
|
|
|
}
|
2004-09-07 23:15:19 +00:00
|
|
|
else
|
2004-09-13 03:10:10 +00:00
|
|
|
{
|
|
|
|
if (option->var->latched_string)
|
|
|
|
Cvar_SetValue(option->var, !atof(option->var->latched_string));
|
|
|
|
else
|
|
|
|
Cvar_SetValue(option->var, !option->var->value);
|
|
|
|
}
|
2004-09-07 18:19:22 +00:00
|
|
|
S_LocalSound ("misc/menu2.wav");
|
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MC_EditBox_Key(menuedit_t *edit, int key)
|
|
|
|
{
|
|
|
|
int len = strlen(edit->text);
|
|
|
|
if (key == K_DEL || key == K_BACKSPACE)
|
|
|
|
{
|
|
|
|
if (!len)
|
|
|
|
return;
|
|
|
|
edit->text[len-1] = '\0';
|
|
|
|
}
|
|
|
|
else if (key < 32 || key > 127)
|
|
|
|
return;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
edit->text[len] = key;
|
|
|
|
edit->text[len+1] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (edit->cvar)
|
2004-09-07 18:19:22 +00:00
|
|
|
{
|
2004-08-23 00:15:46 +00:00
|
|
|
Cvar_Set(edit->cvar, edit->text);
|
2004-09-07 18:19:22 +00:00
|
|
|
S_LocalSound ("misc/menu2.wav");
|
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MC_Combo_Key(menucombo_t *combo, int key)
|
|
|
|
{
|
|
|
|
if (key == K_ENTER || key == K_RIGHTARROW || key == K_MOUSE1)
|
|
|
|
{
|
|
|
|
combo->selectedoption++;
|
|
|
|
if (combo->selectedoption >= combo->numoptions)
|
|
|
|
combo->selectedoption = 0;
|
|
|
|
|
|
|
|
changed:
|
|
|
|
if (combo->cvar)
|
|
|
|
Cvar_Set(combo->cvar, (char *)combo->values[combo->selectedoption]);
|
|
|
|
}
|
|
|
|
else if (key == K_LEFTARROW)
|
|
|
|
{
|
|
|
|
combo->selectedoption--;
|
|
|
|
if (combo->selectedoption < 0)
|
|
|
|
combo->selectedoption = combo->numoptions-1;
|
|
|
|
goto changed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
menu_t *currentmenu;
|
|
|
|
menu_t *firstmenu;
|
|
|
|
|
|
|
|
void M_AddMenuFront (menu_t *menu)
|
|
|
|
{
|
|
|
|
menu_t *pmenu;
|
|
|
|
m_state = m_complex;
|
|
|
|
if (!firstmenu)
|
|
|
|
{
|
|
|
|
M_AddMenu(menu);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
pmenu = firstmenu;
|
|
|
|
while(pmenu->parent)
|
|
|
|
pmenu = pmenu->parent;
|
|
|
|
pmenu->parent = menu;
|
|
|
|
menu->child = pmenu;
|
|
|
|
menu->parent = NULL;
|
|
|
|
|
|
|
|
menu->exclusive = true;
|
|
|
|
|
|
|
|
menu->xpos = ((vid.width - 320)>>1);
|
|
|
|
|
|
|
|
currentmenu = menu;
|
|
|
|
}
|
|
|
|
|
|
|
|
void M_AddMenu (menu_t *menu)
|
|
|
|
{
|
|
|
|
m_state = m_complex;
|
|
|
|
menu->parent = firstmenu;
|
|
|
|
if (firstmenu)
|
|
|
|
firstmenu->child = menu;
|
|
|
|
menu->child = NULL;
|
|
|
|
firstmenu = menu;
|
|
|
|
|
|
|
|
menu->exclusive = true;
|
|
|
|
|
|
|
|
currentmenu = menu;
|
|
|
|
}
|
|
|
|
menu_t *M_CreateMenu (int extrasize)
|
|
|
|
{
|
|
|
|
menu_t *menu;
|
|
|
|
menu = Z_Malloc(sizeof(menu_t)+extrasize);
|
|
|
|
menu->iszone=true;
|
|
|
|
menu->data = menu+1;
|
|
|
|
|
|
|
|
M_AddMenu(menu);
|
|
|
|
|
|
|
|
return menu;
|
|
|
|
}
|
|
|
|
void M_HideMenu (menu_t *menu)
|
|
|
|
{
|
|
|
|
if (menu == firstmenu)
|
|
|
|
firstmenu = menu->parent;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
menu_t *prev;
|
|
|
|
prev = menu->child;
|
|
|
|
if (prev)
|
|
|
|
prev->parent = menu->parent;
|
|
|
|
if (menu->parent)
|
|
|
|
menu->parent->child = menu;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void M_RemoveMenu (menu_t *menu)
|
|
|
|
{
|
|
|
|
menuoption_t *op, *oop;
|
|
|
|
if (menu->remove)
|
|
|
|
menu->remove(menu);
|
|
|
|
if (menu == firstmenu)
|
|
|
|
firstmenu = menu->parent;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
menu_t *prev;
|
|
|
|
prev = menu->child;
|
|
|
|
if (prev)
|
|
|
|
prev->parent = menu->parent;
|
|
|
|
if (menu->parent)
|
|
|
|
menu->parent->child = menu;
|
|
|
|
}
|
|
|
|
|
|
|
|
op = menu->options;
|
|
|
|
while(op)
|
|
|
|
{
|
|
|
|
oop = op;
|
|
|
|
op = op->common.next;
|
|
|
|
if (oop->common.iszone)
|
|
|
|
Z_Free(oop);
|
|
|
|
}
|
|
|
|
menu->options=NULL;
|
|
|
|
|
|
|
|
if (menu->iszone)
|
|
|
|
{
|
|
|
|
menu->iszone=false;
|
|
|
|
Z_Free(menu);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (menu == currentmenu)
|
|
|
|
currentmenu = firstmenu;
|
|
|
|
}
|
|
|
|
|
|
|
|
void M_RemoveAllMenus (void)
|
|
|
|
{
|
|
|
|
if (!firstmenu)
|
|
|
|
return;
|
|
|
|
|
|
|
|
while(firstmenu)
|
|
|
|
M_RemoveMenu(firstmenu);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void M_Complex_Draw(void)
|
|
|
|
{
|
|
|
|
extern int mousecursor_x, mousecursor_y;
|
|
|
|
menu_t *menu, *cmenu;
|
|
|
|
qboolean foundexclusive = false;
|
|
|
|
|
|
|
|
if (omousex != mousecursor_x || omousey != mousecursor_y)
|
|
|
|
mousemoved = true;
|
|
|
|
else
|
|
|
|
mousemoved = false;
|
|
|
|
omousex = mousecursor_x;
|
|
|
|
omousey = mousecursor_y;
|
|
|
|
|
|
|
|
if (!firstmenu)
|
|
|
|
{
|
|
|
|
key_dest = key_game;
|
|
|
|
m_state = m_none;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (menu = firstmenu; menu; )
|
|
|
|
{
|
|
|
|
cmenu = menu;
|
|
|
|
menu = menu->parent; //this way we can remove the currently drawn menu easily (if needed)
|
|
|
|
|
|
|
|
if (cmenu->exclusive)
|
|
|
|
{
|
|
|
|
if (foundexclusive)
|
|
|
|
continue;
|
|
|
|
foundexclusive=true;
|
|
|
|
}
|
|
|
|
MenuDraw(cmenu);
|
|
|
|
}
|
|
|
|
Draw_Character(mousecursor_x-4, mousecursor_y-4, '+');
|
|
|
|
}
|
|
|
|
|
|
|
|
menuoption_t *M_NextItem(menu_t *m, menuoption_t *old)
|
|
|
|
{
|
|
|
|
menuoption_t *op = m->options;
|
|
|
|
while(op->common.next)
|
|
|
|
{
|
|
|
|
if (op->common.next == old)
|
|
|
|
return op;
|
|
|
|
|
|
|
|
op = op->common.next;
|
|
|
|
}
|
|
|
|
return op;
|
|
|
|
}
|
|
|
|
menuoption_t *M_NextSelectableItem(menu_t *m, menuoption_t *old)
|
|
|
|
{
|
|
|
|
menuoption_t *op;
|
|
|
|
|
|
|
|
if (!old)
|
|
|
|
old = M_NextItem(m, old);
|
|
|
|
|
|
|
|
op = old;
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
if (!op)
|
|
|
|
op = currentmenu->options;
|
|
|
|
|
|
|
|
op = M_NextItem(m, op);
|
|
|
|
if (!op)
|
|
|
|
op = currentmenu->options;
|
|
|
|
|
|
|
|
if (op == old)
|
|
|
|
{
|
2004-09-07 18:19:22 +00:00
|
|
|
if (op->common.type == mt_slider || op->common.type == mt_checkbox || op->common.type == mt_button || op->common.type == mt_buttonbigfont || op->common.type == mt_edit || op->common.type == mt_combo || op->common.type == mt_bind)
|
2004-08-23 00:15:46 +00:00
|
|
|
return op;
|
|
|
|
return NULL; //whoops.
|
|
|
|
}
|
|
|
|
|
2004-09-07 18:19:22 +00:00
|
|
|
if (op->common.type == mt_slider || op->common.type == mt_checkbox || op->common.type == mt_button || op->common.type == mt_buttonbigfont || op->common.type == mt_edit || op->common.type == mt_combo || op->common.type == mt_bind)
|
2005-01-26 18:56:49 +00:00
|
|
|
if (!op->common.ishidden)
|
|
|
|
return op;
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
menuoption_t *M_PrevSelectableItem(menu_t *m, menuoption_t *old)
|
|
|
|
{
|
|
|
|
menuoption_t *op;
|
|
|
|
|
|
|
|
if (!old)
|
|
|
|
old = currentmenu->options;
|
|
|
|
|
|
|
|
op = old;
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
if (!op)
|
|
|
|
op = currentmenu->options;
|
|
|
|
|
|
|
|
op = op->common.next;
|
|
|
|
if (!op)
|
|
|
|
op = currentmenu->options;
|
|
|
|
|
|
|
|
if (op == old)
|
|
|
|
return old; //whoops.
|
|
|
|
|
2004-09-07 18:19:22 +00:00
|
|
|
if (op->common.type == mt_slider || op->common.type == mt_checkbox || op->common.type == mt_button || op->common.type == mt_buttonbigfont || op->common.type == mt_edit || op->common.type == mt_combo || op->common.type == mt_bind)
|
2005-01-26 18:56:49 +00:00
|
|
|
if (!op->common.ishidden)
|
|
|
|
return op;
|
2004-08-23 00:15:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void M_Complex_Key(int key)
|
|
|
|
{
|
|
|
|
if (!currentmenu)
|
|
|
|
return; //erm...
|
|
|
|
|
|
|
|
if (currentmenu->key)
|
|
|
|
if (currentmenu->key(key, currentmenu))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (currentmenu->selecteditem && currentmenu->selecteditem->common.type == mt_custom && (key == K_DOWNARROW || key == K_UPARROW || key == K_TAB))
|
|
|
|
if (currentmenu->selecteditem->custom.key(¤tmenu->selecteditem->custom, currentmenu, key))
|
|
|
|
return;
|
2004-09-07 18:19:22 +00:00
|
|
|
|
|
|
|
if (currentmenu->selecteditem && currentmenu->selecteditem->common.type == mt_bind)
|
|
|
|
{
|
|
|
|
if (bindingactive)
|
|
|
|
{
|
|
|
|
S_LocalSound ("misc/menu1.wav");
|
|
|
|
|
|
|
|
if (key != K_ESCAPE && key != '`')
|
|
|
|
{
|
|
|
|
Cbuf_InsertText (va("bind %s \"%s\"\n", Key_KeynumToString (key), currentmenu->selecteditem->bind.command), RESTRICT_LOCAL);
|
|
|
|
}
|
|
|
|
bindingactive = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
|
|
|
|
switch(key)
|
|
|
|
{
|
|
|
|
case K_ESCAPE:
|
|
|
|
//remove
|
|
|
|
M_RemoveMenu(currentmenu);
|
2004-09-07 18:19:22 +00:00
|
|
|
S_LocalSound ("misc/menu3.wav");
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
case K_TAB:
|
|
|
|
case K_DOWNARROW:
|
|
|
|
currentmenu->selecteditem = M_NextSelectableItem(currentmenu, currentmenu->selecteditem);
|
|
|
|
|
|
|
|
if (currentmenu->selecteditem)
|
|
|
|
{
|
|
|
|
S_LocalSound ("misc/menu1.wav");
|
|
|
|
if (currentmenu->cursoritem)
|
|
|
|
currentmenu->cursoritem->common.posy = currentmenu->selecteditem->common.posy;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case K_UPARROW:
|
|
|
|
currentmenu->selecteditem = M_PrevSelectableItem(currentmenu, currentmenu->selecteditem);
|
|
|
|
|
|
|
|
if (currentmenu->selecteditem)
|
|
|
|
{
|
|
|
|
S_LocalSound ("misc/menu1.wav");
|
|
|
|
if (currentmenu->cursoritem)
|
|
|
|
currentmenu->cursoritem->common.posy = currentmenu->selecteditem->common.posy;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (!currentmenu->selecteditem)
|
|
|
|
{
|
|
|
|
if (!currentmenu->options)
|
|
|
|
return;
|
|
|
|
currentmenu->selecteditem = currentmenu->options;
|
|
|
|
}
|
|
|
|
switch(currentmenu->selecteditem->common.type)
|
|
|
|
{
|
|
|
|
case mt_slider:
|
|
|
|
MC_Slider_Key(¤tmenu->selecteditem->slider, key);
|
|
|
|
break;
|
|
|
|
case mt_checkbox:
|
|
|
|
MC_CheckBox_Key(¤tmenu->selecteditem->check, key);
|
|
|
|
break;
|
|
|
|
case mt_button:
|
|
|
|
case mt_buttonbigfont:
|
|
|
|
if (!currentmenu->selecteditem->button.command)
|
|
|
|
currentmenu->selecteditem->button.key(currentmenu->selecteditem, currentmenu, key);
|
|
|
|
else if (key == K_ENTER || key == K_MOUSE1)
|
2004-09-07 18:19:22 +00:00
|
|
|
{
|
2004-08-23 00:15:46 +00:00
|
|
|
Cbuf_AddText(currentmenu->selecteditem->button.command, RESTRICT_LOCAL);
|
2004-09-07 18:19:22 +00:00
|
|
|
S_LocalSound ("misc/menu2.wav");
|
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
break;
|
|
|
|
case mt_custom:
|
|
|
|
currentmenu->selecteditem->custom.key(¤tmenu->selecteditem->custom, currentmenu, key);
|
|
|
|
break;
|
|
|
|
case mt_edit:
|
|
|
|
MC_EditBox_Key(¤tmenu->selecteditem->edit, key);
|
|
|
|
break;
|
|
|
|
case mt_combo:
|
|
|
|
MC_Combo_Key(¤tmenu->selecteditem->combo, key);
|
|
|
|
break;
|
2004-09-07 18:19:22 +00:00
|
|
|
case mt_bind:
|
|
|
|
if (key == K_ENTER)
|
|
|
|
bindingactive = true;
|
|
|
|
else if (key == K_BACKSPACE || key == K_DEL)
|
|
|
|
M_UnbindCommand (currentmenu->selecteditem->bind.command);
|
2004-08-23 00:15:46 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
int itemselected;
|
|
|
|
menu_t *dropout;
|
|
|
|
menutext_t *op[64];
|
|
|
|
char *text[64];
|
|
|
|
|
|
|
|
menu_t *parent;
|
|
|
|
} guiinfo_t;
|
|
|
|
|
|
|
|
qboolean MC_GuiKey(int key, menu_t *menu)
|
|
|
|
{
|
|
|
|
guiinfo_t *info = (guiinfo_t *)menu->data;
|
|
|
|
switch(key)
|
|
|
|
{
|
|
|
|
case K_ESCAPE:
|
|
|
|
if (info->dropout)
|
|
|
|
MC_GuiKey(key, info->dropout);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
guiinfo_t *gui;
|
|
|
|
M_RemoveMenu(menu);
|
|
|
|
if (menu->parent)
|
|
|
|
{
|
|
|
|
gui = (guiinfo_t *)menu->parent->data;
|
|
|
|
gui->dropout = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case K_ENTER:
|
|
|
|
case K_RIGHTARROW:
|
|
|
|
if (info->dropout)
|
|
|
|
MC_GuiKey(key, info->dropout);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int y, i;
|
|
|
|
guiinfo_t *gui;
|
|
|
|
info->dropout = M_CreateMenu(sizeof(guiinfo_t));
|
|
|
|
currentmenu = info->dropout;
|
|
|
|
info->dropout->key = MC_GuiKey;
|
|
|
|
info->dropout->exclusive = false;
|
|
|
|
info->dropout->parent = menu;
|
|
|
|
info->dropout->xpos = 0;
|
|
|
|
info->dropout->ypos = menu->ypos+info->itemselected*8;
|
|
|
|
for (i = 0; info->text[i]; i++)
|
|
|
|
if (info->dropout->xpos < strlen(info->text[i]))
|
|
|
|
info->dropout->xpos = strlen(info->text[i]);
|
|
|
|
info->dropout->xpos*=8;
|
|
|
|
info->dropout->xpos+=menu->xpos;
|
|
|
|
gui = (guiinfo_t *)info->dropout->data;
|
|
|
|
gui->text[0] = "Hello";
|
|
|
|
gui->text[1] = "Hello again";
|
|
|
|
gui->text[2] = "Hello yet again";
|
|
|
|
for (y = 0, i = 0; gui->text[i]; i++, y+=1*8)
|
|
|
|
{
|
|
|
|
info->op[i] = MC_AddRedText(info->dropout, 0, y, gui->text[i], false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case K_LEFTARROW:
|
|
|
|
if (info->dropout)
|
|
|
|
MC_GuiKey(key, info->dropout);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
guiinfo_t *gui;
|
|
|
|
M_RemoveMenu(menu);
|
|
|
|
if (menu->parent)
|
|
|
|
{
|
|
|
|
gui = (guiinfo_t *)menu->parent->data;
|
|
|
|
gui->dropout = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case K_UPARROW:
|
|
|
|
info->op[info->itemselected]->isred = true;
|
|
|
|
if (info->itemselected)
|
|
|
|
info->itemselected--;
|
|
|
|
info->op[info->itemselected]->isred = false;
|
|
|
|
break;
|
|
|
|
case K_DOWNARROW:
|
|
|
|
if (!info->op[info->itemselected])
|
|
|
|
break;
|
|
|
|
info->op[info->itemselected]->isred = true;
|
|
|
|
if (info->text[info->itemselected+1])
|
|
|
|
info->itemselected++;
|
|
|
|
info->op[info->itemselected]->isred = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
qboolean MC_Main_Key (int key, menu_t *menu) //here purly to restart demos.
|
|
|
|
{
|
|
|
|
if (key == K_ESCAPE)
|
|
|
|
{
|
|
|
|
extern int m_save_demonum;
|
|
|
|
key_dest = key_game;
|
|
|
|
m_state = m_none;
|
|
|
|
cls.demonum = m_save_demonum;
|
2004-11-26 06:05:59 +00:00
|
|
|
if (cls.demonum != -1 && !cls.demoplayback && cls.state == ca_disconnected && COM_CheckParm("-demos"))
|
2004-08-23 00:15:46 +00:00
|
|
|
CL_NextDemo ();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void M_Menu_Main_f (void)
|
|
|
|
{
|
|
|
|
extern cvar_t m_helpismedia;
|
|
|
|
menubutton_t *b;
|
|
|
|
menu_t *mainm;
|
2004-12-24 08:45:56 +00:00
|
|
|
mpic_t *p;
|
2004-08-23 00:15:46 +00:00
|
|
|
|
|
|
|
int q1, q2, h2;
|
|
|
|
|
|
|
|
SCR_EndLoadingPlaque(); //just in case...
|
|
|
|
|
|
|
|
if (!Draw_SafeCachePic)
|
2004-12-15 19:39:21 +00:00
|
|
|
{
|
|
|
|
Con_ToggleConsole_f();
|
2004-08-23 00:15:46 +00:00
|
|
|
return;
|
2004-12-15 19:39:21 +00:00
|
|
|
}
|
2004-08-23 00:15:46 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
if (0)
|
|
|
|
{
|
|
|
|
int x, i;
|
|
|
|
guiinfo_t *gui;
|
|
|
|
m_state = m_complex;
|
|
|
|
key_dest = key_menu;
|
|
|
|
m_entersound = true;
|
|
|
|
|
|
|
|
mainm = M_CreateMenu(sizeof(guiinfo_t));
|
|
|
|
mainm->key = MC_GuiKey;
|
|
|
|
mainm->xpos=0;
|
|
|
|
gui = (guiinfo_t *)mainm->data;
|
|
|
|
gui->text[0] = "Single";
|
|
|
|
gui->text[1] = "Multiplayer";
|
|
|
|
gui->text[2] = "Quit";
|
|
|
|
for (x = 0, i = 0; gui->text[i]; i++)
|
|
|
|
{
|
|
|
|
gui->op[i] = MC_AddRedText(mainm, x, 0, gui->text[i], false);
|
|
|
|
x+=(strlen(gui->text[i])+1)*8;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
q1 = COM_FDepthFile("gfx/mainmenu.lmp", true);
|
|
|
|
q2 = COM_FDepthFile("pics/m_main.pcx", true);
|
|
|
|
h2 = COM_FDepthFile("gfx/menu/title0.lmp", true);
|
|
|
|
if (q2 < q1 && q2 < h2) //quake2 main menu.
|
|
|
|
{
|
|
|
|
if (Draw_SafeCachePic("pics/m_main_game"))
|
|
|
|
{
|
|
|
|
m_state = m_complex;
|
|
|
|
key_dest = key_menu;
|
|
|
|
m_entersound = true;
|
|
|
|
|
|
|
|
mainm = M_CreateMenu(0);
|
|
|
|
mainm->key = MC_Main_Key;
|
|
|
|
|
2005-01-13 16:29:20 +00:00
|
|
|
MC_AddPicture(mainm, 0, 4, "pics/m_main_plaque");
|
|
|
|
p = Draw_SafeCachePic("pics/m_main_logo");
|
2004-08-23 00:15:46 +00:00
|
|
|
if (!p)
|
|
|
|
return;
|
2005-01-13 16:29:20 +00:00
|
|
|
MC_AddPicture(mainm, 0, 173, "pics/m_main_logo");
|
|
|
|
MC_AddPicture(mainm, 68, 13, "pics/m_main_game");
|
|
|
|
MC_AddPicture(mainm, 68, 53, "pics/m_main_multiplayer");
|
|
|
|
MC_AddPicture(mainm, 68, 93, "pics/m_main_options");
|
|
|
|
MC_AddPicture(mainm, 68, 133, "pics/m_main_video");
|
|
|
|
MC_AddPicture(mainm, 68, 173, "pics/m_main_quit");
|
2004-08-23 00:15:46 +00:00
|
|
|
|
|
|
|
mainm->selecteditem = (menuoption_t *)
|
|
|
|
MC_AddConsoleCommand (mainm, 68, 13, "", "menu_single\n");
|
|
|
|
MC_AddConsoleCommand (mainm, 68, 53, "", "menu_multi\n");
|
|
|
|
MC_AddConsoleCommand (mainm, 68, 93, "", "menu_options\n");
|
|
|
|
MC_AddConsoleCommand (mainm, 68, 133, "", "menu_video\n");
|
|
|
|
MC_AddConsoleCommand (mainm, 68, 173, "", "menu_quit\n");
|
|
|
|
|
|
|
|
mainm->cursoritem = (menuoption_t *)MC_AddCursor(mainm, 42, 13);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (h2 < q1)
|
|
|
|
{
|
|
|
|
m_state = m_complex;
|
|
|
|
key_dest = key_menu;
|
|
|
|
m_entersound = true;
|
|
|
|
mainm = M_CreateMenu(0);
|
|
|
|
mainm->key = MC_Main_Key;
|
|
|
|
|
|
|
|
MC_AddPicture(mainm, 16, 0, "gfx/menu/hplaque.lmp");
|
|
|
|
p = Draw_SafeCachePic("gfx/menu/title0.lmp");
|
|
|
|
if (!p)
|
|
|
|
return;
|
|
|
|
MC_AddPicture(mainm, (320-p->width)/2, 0, "gfx/menu/title0.lmp");
|
|
|
|
|
|
|
|
b=MC_AddConsoleCommandBigFont (mainm, 80, 64, "Single Player", "menu_single\n");
|
|
|
|
b->common.width = 12*20;
|
|
|
|
b->common.height = 20;
|
|
|
|
b=MC_AddConsoleCommandBigFont (mainm, 80, 64+20, "MultiPlayer", "menu_multi\n");
|
|
|
|
b->common.width = 12*20;
|
|
|
|
b->common.height = 20;
|
|
|
|
b=MC_AddConsoleCommandBigFont (mainm, 80, 64+40, "Options", "menu_options\n");
|
|
|
|
b->common.width = 12*20;
|
|
|
|
b->common.height = 20;
|
|
|
|
if (m_helpismedia.value)
|
|
|
|
b=MC_AddConsoleCommandBigFont (mainm, 80, 64+60, "Media", "menu_media\n");
|
|
|
|
else
|
|
|
|
b=MC_AddConsoleCommandBigFont (mainm, 80, 64+60, "Help", "help\n");
|
|
|
|
b->common.width = 12*20;
|
|
|
|
b->common.height = 20;
|
|
|
|
b=MC_AddConsoleCommandBigFont (mainm, 80, 64+80, "Quit", "menu_quit\n");
|
|
|
|
b->common.width = 12*20;
|
|
|
|
b->common.height = 20;
|
|
|
|
|
|
|
|
mainm->cursoritem = (menuoption_t *)MC_AddCursor(mainm, 48, 64);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_state = m_complex;
|
|
|
|
key_dest = key_menu;
|
|
|
|
m_entersound = true;
|
2005-01-13 16:29:20 +00:00
|
|
|
mainm = M_CreateMenu(0);
|
2004-08-23 00:15:46 +00:00
|
|
|
|
|
|
|
p = Draw_SafeCachePic("gfx/ttl_main.lmp");
|
|
|
|
if (!p)
|
2004-12-15 19:39:21 +00:00
|
|
|
{
|
2005-01-13 16:29:20 +00:00
|
|
|
MC_AddRedText(mainm, 16, 0, "MAIN MENU", false);
|
|
|
|
|
|
|
|
mainm->selecteditem = (menuoption_t *)
|
|
|
|
MC_AddConsoleCommand (mainm, 64, 32, "Join server", "menu_servers\n");
|
|
|
|
MC_AddConsoleCommand (mainm, 64, 40, "Options", "menu_options\n");
|
|
|
|
MC_AddConsoleCommand (mainm, 64, 48, "Quit", "menu_quit\n");
|
2004-08-23 00:15:46 +00:00
|
|
|
return;
|
2004-12-15 19:39:21 +00:00
|
|
|
}
|
2005-01-13 16:29:20 +00:00
|
|
|
mainm->key = MC_Main_Key;
|
|
|
|
MC_AddPicture(mainm, 16, 4, "gfx/qplaque.lmp");
|
|
|
|
|
2004-08-23 00:15:46 +00:00
|
|
|
MC_AddPicture(mainm, (320-p->width)/2, 4, "gfx/ttl_main.lmp");
|
|
|
|
MC_AddPicture(mainm, 72, 32, "gfx/mainmenu.lmp");
|
|
|
|
|
|
|
|
b=MC_AddConsoleCommand (mainm, 16, 32, "", "menu_single\n");
|
|
|
|
mainm->selecteditem = (menuoption_t *)b;
|
|
|
|
b->common.width = p->width;
|
|
|
|
b->common.height = 20;
|
|
|
|
b=MC_AddConsoleCommand (mainm, 16, 52, "", "menu_multi\n");
|
|
|
|
b->common.width = p->width;
|
|
|
|
b->common.height = 20;
|
|
|
|
b=MC_AddConsoleCommand (mainm, 16, 72, "", "menu_options\n");
|
|
|
|
b->common.width = p->width;
|
|
|
|
b->common.height = 20;
|
|
|
|
if (m_helpismedia.value)
|
|
|
|
b=MC_AddConsoleCommand(mainm, 16, 92, "", "menu_media\n");
|
|
|
|
else
|
|
|
|
b=MC_AddConsoleCommand(mainm, 16, 92, "", "help\n");
|
|
|
|
b->common.width = p->width;
|
|
|
|
b->common.height = 20;
|
|
|
|
b=MC_AddConsoleCommand (mainm, 16, 112, "", "menu_quit\n");
|
|
|
|
b->common.width = p->width;
|
|
|
|
b->common.height = 20;
|
|
|
|
|
|
|
|
mainm->cursoritem = (menuoption_t *)MC_AddCursor(mainm, 54, 32);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|