The menu code sucks!

- Joystick devices now send key up events for any buttons that are held
  down when they are destroyed.
- Changed the joystick enable-y menu items to be nonrepeatable so that you
  can't create several device scans per second. Changing them with a
  controller is also disabled so that you can't, for example, toggle XInput
  support using an XInput controller and have things go haywire when the
  game receives an infinite number of key down events when the controller
  is reinitialized with the other input system.
- Changed menu input to use a consolidated set of buttons, so most menus
  can be navigated with a controller as well as a keyboard.
- Changed the way that X/Y analog axes are converted to digital axes.
  Previously, this was done by checking if each axis was outside its deadzone.
  Now they are checked together based on their angle, so straight up/down/
  left/right are much easier to achieve.


SVN r1739 (trunk)
This commit is contained in:
Randy Heit 2009-07-26 03:25:18 +00:00
commit a90bde274e
12 changed files with 615 additions and 282 deletions

View file

@ -86,6 +86,8 @@
// Data.
#include "m_menu.h"
extern FButtonStatus MenuButtons[NUM_MKEYS];
EXTERN_CVAR(Bool, nomonsterinterpolation)
EXTERN_CVAR(Int, showendoom)
EXTERN_CVAR(Bool, hud_althud)
@ -1509,7 +1511,7 @@ static void CalcIndent (menu_t *menu)
{
item = menu->items + i;
if (item->type != whitetext && item->type != redtext && item->type != screenres &&
item->type != joymore && (item->type != discrete || !item->c.discretecenter))
item->type != joymore && (item->type != discrete || item->c.discretecenter != 1))
{
thiswidth = SmallFont->StringWidth (item->label);
if (thiswidth > widest)
@ -1681,7 +1683,7 @@ void M_OptDrawer ()
item = CurrentMenu->items + i;
overlay = 0;
if (item->type == discrete && item->c.discretecenter)
if (item->type == discrete && item->c.discretecenter == 1)
{
indent = 160;
}
@ -2095,50 +2097,79 @@ void M_OptDrawer ()
}
}
void M_OptResponder (event_t *ev)
void M_OptResponder(event_t *ev)
{
menuitem_t *item;
int ch = tolower (ev->data1);
UCVarValue value;
item = CurrentMenu->items + CurrentItem;
menuitem_t *item = CurrentMenu->items + CurrentItem;
if (menuactive == MENU_WaitKey && ev->type == EV_KeyDown)
{
if (ev->data1 != KEY_ESCAPE)
{
C_ChangeBinding (item->e.command, ev->data1);
M_BuildKeyList (CurrentMenu->items, CurrentMenu->numitems);
C_ChangeBinding(item->e.command, ev->data1);
M_BuildKeyList(CurrentMenu->items, CurrentMenu->numitems);
}
menuactive = MENU_On;
CurrentMenu->items[0].label = OldMessage;
CurrentMenu->items[0].type = OldType;
return;
}
if (ev->subtype == EV_GUI_KeyRepeat)
else if (ev->type == EV_GUI_Event && ev->subtype == EV_GUI_KeyDown && tolower(ev->data1) == 't')
{
if (ch != GK_LEFT && ch != GK_RIGHT && ch != GK_UP && ch != GK_DOWN)
// Test selected resolution
if (CurrentMenu == &ModesMenu)
{
return;
if (!(item->type == screenres &&
GetSelectedSize (CurrentItem, &NewWidth, &NewHeight)))
{
NewWidth = SCREENWIDTH;
NewHeight = SCREENHEIGHT;
}
OldWidth = SCREENWIDTH;
OldHeight = SCREENHEIGHT;
OldBits = DisplayBits;
NewBits = BitTranslate[DummyDepthCvar];
setmodeneeded = true;
testingmode = I_GetTime(false) + 5 * TICRATE;
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", 1, ATTN_NONE);
SetModesMenu (NewWidth, NewHeight, NewBits);
}
}
else if (ev->subtype != EV_GUI_KeyDown)
{
return;
}
}
void M_OptButtonHandler(EMenuKey key, bool repeat)
{
menuitem_t *item;
UCVarValue value;
item = CurrentMenu->items + CurrentItem;
if (item->type == bitflag &&
(ch == GK_LEFT || ch == GK_RIGHT || ch == '\r')
(key == MKEY_Left || key == MKEY_Right || key == MKEY_Enter)
&& !demoplayback)
{
*(item->a.intcvar) = (*(item->a.intcvar)) ^ item->e.flagmask;
return;
}
switch (ch)
// The controls that manipulate joystick interfaces can only be changed from the
// keyboard, because I can't think of a good way to avoid problems otherwise.
if (item->type == discrete && item->c.discretecenter == 2 && (key == MKEY_Left || key == MKEY_Right))
{
case GK_DOWN:
if (repeat)
{
return;
}
for (int i = 0; i < FButtonStatus::MAX_KEYS; ++i)
{
if (MenuButtons[key].Keys[i] >= KEY_FIRSTJOYBUTTON)
{
return;
}
}
}
switch (key)
{
case MKEY_Down:
if (CurrentMenu->numitems > 1)
{
int modecol;
@ -2187,7 +2218,7 @@ void M_OptResponder (event_t *ev)
}
break;
case GK_UP:
case MKEY_Up:
if (CurrentMenu->numitems > 1)
{
int modecol;
@ -2255,7 +2286,7 @@ void M_OptResponder (event_t *ev)
}
break;
case GK_PGUP:
case MKEY_PageUp:
if (CurrentMenu->scrollpos > 0)
{
CurrentMenu->scrollpos -= VisBottom - CurrentMenu->scrollpos - CurrentMenu->scrolltop;
@ -2277,7 +2308,7 @@ void M_OptResponder (event_t *ev)
}
break;
case GK_PGDN:
case MKEY_PageDown:
if (CanScrollDown)
{
int pagesize = VisBottom - CurrentMenu->scrollpos - CurrentMenu->scrolltop;
@ -2300,7 +2331,7 @@ void M_OptResponder (event_t *ev)
}
break;
case GK_LEFT:
case MKEY_Left:
switch (item->type)
{
case slider:
@ -2497,7 +2528,7 @@ void M_OptResponder (event_t *ev)
}
break;
case GK_RIGHT:
case MKEY_Right:
switch (item->type)
{
case slider:
@ -2697,14 +2728,14 @@ void M_OptResponder (event_t *ev)
}
break;
case '\b':
case MKEY_Clear:
if (item->type == control)
{
C_UnbindACommand (item->e.command);
item->b.key1 = item->c.key2 = 0;
}
break;
/*
case '0':
case '1':
case '2':
@ -2732,8 +2763,8 @@ void M_OptResponder (event_t *ev)
}
// Otherwise, fall through to '\r' below
}
case '\r':
*/
case MKEY_Enter:
if (CurrentMenu == &ModesMenu && item->type == screenres)
{
if (!GetSelectedSize (CurrentItem, &NewWidth, &NewHeight))
@ -2839,7 +2870,7 @@ void M_OptResponder (event_t *ev)
}
break;
case GK_ESCAPE:
case MKEY_Back:
CurrentMenu->lastOn = CurrentItem;
if (CurrentMenu->EscapeHandler != NULL)
{
@ -2847,30 +2878,6 @@ void M_OptResponder (event_t *ev)
}
M_PopMenuStack ();
break;
default:
if (ch == 't')
{
// Test selected resolution
if (CurrentMenu == &ModesMenu)
{
if (!(item->type == screenres &&
GetSelectedSize (CurrentItem, &NewWidth, &NewHeight)))
{
NewWidth = SCREENWIDTH;
NewHeight = SCREENHEIGHT;
}
OldWidth = SCREENWIDTH;
OldHeight = SCREENHEIGHT;
OldBits = DisplayBits;
NewBits = BitTranslate[DummyDepthCvar];
setmodeneeded = true;
testingmode = I_GetTime(false) + 5 * TICRATE;
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", 1, ATTN_NONE);
SetModesMenu (NewWidth, NewHeight, NewBits);
}
}
break;
}
}
@ -3203,6 +3210,7 @@ void UpdateJoystickMenu(IJoystickConfig *selected)
item.label = "Enable controller support";
item.a.cvar = &use_joystick;
item.b.numvalues = 2;
item.c.discretecenter = 2;
item.e.values = YesNo;
JoystickItems.Push(item);
@ -3222,6 +3230,7 @@ void UpdateJoystickMenu(IJoystickConfig *selected)
item.type = redtext;
item.label = " ";
item.c.discretecenter = 0;
JoystickItems.Push(item);
if (Joysticks.Size() == 0)