mirror of
https://github.com/ZDoom/gzdoom-last-svn.git
synced 2025-06-01 09:41:58 +00:00
Update to ZDoom r1747:
- Added A_Mushroom compatibility option for Dehacked. - Added Gez's submission for interhubamount DECORATE property. - Fixed: The big endian version of PalEntry did not add the DWORD d field. - Fixed: TObjPtr did not use a union to map its 2 pointers together. - Added a compatibility mode for A_Mushroom. For DECORATE it is an additional parameter but to force it for Dehacked mods some minor hacks using the Misc1 variable were needed. - Moved the terget->velz assignment to the end of A_VileAttack to remove the influence of vertical thrust from the radius attack, since ZDoom does explosions in three dimensions, but Doom only did it in two. - Fixed: The last three parameters to A_VileAttack had their references off by one. Most notably as a result, the blast radius was used as the thrust, so it sent you flying far faster than it should have. - Restored the reactiontime countdown for A_SpawnFly, since some Dehacked mod could conceivable rely on it. The deadline is now kept in special2 and used in preference as long as it is non-zero. - Removed -fno-strict-aliasing from the GCC flags for ZDoom and fixed the issues that caused its inclusion. Is an optimized GCC build any faster for being able to use strict aliasing rules? I dunno. It's still slower than a VC++ build. I did run into two cases where TAutoSegIterator caused intractable problems with breaking strict aliasing rules, so I removed the templating from it, and the caller is now responsible for casting the probe value from void *. - Removed #include "autosegs.h" from several files that did not need it (in particular, dobject.h when not compiling with VC++). - gdtoa now performs all type aliasing through unions. -Wall has been added to the GCC flags for the library to help verify this. - Changed A_SpawnFly to do nothing if reactiontime is 0. Reactiontime was originally a counter, so if it started at 0, A_SpawnFly would effectively never spawn anything. Fixes Dehacked patches that use A_SpawnSound to play a sound without shooting boss cubes, since it also calls A_SpawnFly. - 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. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@406 b0f79afe-0144-0410-b225-9a4edf0717df
This commit is contained in:
parent
cc54379b7c
commit
16ffba5673
73 changed files with 1068 additions and 571 deletions
548
src/m_menu.cpp
548
src/m_menu.cpp
|
@ -79,6 +79,9 @@
|
|||
#define SELECTOR_XOFFSET (-28)
|
||||
#define SELECTOR_YOFFSET (-1)
|
||||
|
||||
#define KEY_REPEAT_DELAY (TICRATE*5/12)
|
||||
#define KEY_REPEAT_RATE (3)
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
struct FSaveGameNode : public Node
|
||||
|
@ -149,6 +152,7 @@ static void M_ExtractSaveData (const FSaveGameNode *file);
|
|||
static void M_UnloadSaveData ();
|
||||
static void M_InsertSaveNode (FSaveGameNode *node);
|
||||
static bool M_SaveLoadResponder (event_t *ev);
|
||||
static void M_SaveLoadButtonHandler(EMenuKey key);
|
||||
static void M_DeleteSaveResponse (int choice);
|
||||
|
||||
static void M_DrawMainMenu ();
|
||||
|
@ -205,6 +209,8 @@ int skullAnimCounter; // skull animation counter
|
|||
bool drawSkull; // [RH] don't always draw skull
|
||||
bool M_DemoNoPlay;
|
||||
bool OptionsActive;
|
||||
FButtonStatus MenuButtons[NUM_MKEYS];
|
||||
int MenuButtonTickers[NUM_MKEYS];
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
|
@ -2783,184 +2789,346 @@ bool M_Responder (event_t *ev)
|
|||
{
|
||||
int ch;
|
||||
int i;
|
||||
EMenuKey mkey = NUM_MKEYS;
|
||||
bool keyup = true;
|
||||
|
||||
ch = -1;
|
||||
|
||||
if (chatmodeon)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (menuactive == MENU_Off && ev->type == EV_KeyDown)
|
||||
{
|
||||
// Pop-up menu?
|
||||
if (ev->data1 == KEY_ESCAPE)
|
||||
{
|
||||
M_StartControlPanel (true);
|
||||
M_SetupNextMenu (TopLevelMenu);
|
||||
M_StartControlPanel(true);
|
||||
M_SetupNextMenu(TopLevelMenu);
|
||||
return true;
|
||||
}
|
||||
// If devparm is set, pressing F1 always takes a screenshot no matter
|
||||
// what it's bound to. (for those who don't bother to read the docs)
|
||||
if (devparm && ev->data1 == KEY_F1)
|
||||
{
|
||||
G_ScreenShot (NULL);
|
||||
G_ScreenShot(NULL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (ev->type == EV_GUI_Event && menuactive == MENU_On && !chatmodeon)
|
||||
if (menuactive == MENU_WaitKey && OptionsActive)
|
||||
{
|
||||
if (ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat)
|
||||
{
|
||||
ch = ev->data1;
|
||||
}
|
||||
else if (ev->subtype == EV_GUI_Char && genStringEnter)
|
||||
{
|
||||
ch = ev->data1;
|
||||
if (saveCharIndex < genStringLen &&
|
||||
(genStringEnter==2 || (size_t)SmallFont->StringWidth (savegamestring) < (genStringLen-1)*8))
|
||||
{
|
||||
savegamestring[saveCharIndex] = ch;
|
||||
savegamestring[++saveCharIndex] = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (ev->subtype == EV_GUI_Char && messageToPrint && messageNeedsInput)
|
||||
{
|
||||
ch = ev->data1;
|
||||
}
|
||||
}
|
||||
|
||||
if (OptionsActive && !chatmodeon)
|
||||
{
|
||||
M_OptResponder (ev);
|
||||
M_OptResponder(ev);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ch == -1)
|
||||
return false;
|
||||
|
||||
// Save Game string input
|
||||
// [RH] and Player Name string input
|
||||
if (genStringEnter)
|
||||
if (menuactive != MENU_On && menuactive != MENU_OnNoPause &&
|
||||
!genStringEnter && !messageToPrint)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// There are a few input sources we are interested in:
|
||||
//
|
||||
// EV_KeyDown / EV_KeyUp : joysticks/gamepads/controllers
|
||||
// EV_GUI_KeyDown / EV_GUI_KeyUp : the keyboard
|
||||
// EV_GUI_Char : printable characters, which we want in string input mode
|
||||
//
|
||||
// This code previously listened for EV_GUI_KeyRepeat to handle repeating
|
||||
// in the menus, but that doesn't work with gamepads, so now we combine
|
||||
// the multiple inputs into buttons and handle the repetition manually.
|
||||
//
|
||||
// FIXME: genStringEnter and messageToPrint do not play well with game
|
||||
// controllers. In fact, you can still interact with the rest of
|
||||
// the menu using a controller while the menu waits for input. Especially
|
||||
// bad if you, say, select quit from the main menu. (Ideally,
|
||||
// genStringEnter will pop up a keypad if it detects a controller is
|
||||
// being used to navigate the menu. At the very least, it should
|
||||
// disable the controller.)
|
||||
if (ev->type == EV_GUI_Event)
|
||||
{
|
||||
// Save game and player name string input
|
||||
if (genStringEnter)
|
||||
{
|
||||
if (ev->subtype == EV_GUI_Char)
|
||||
{
|
||||
if (saveCharIndex < genStringLen &&
|
||||
(genStringEnter == 2 || (size_t)SmallFont->StringWidth(savegamestring) < (genStringLen-1)*8))
|
||||
{
|
||||
savegamestring[saveCharIndex] = (char)ev->data1;
|
||||
savegamestring[++saveCharIndex] = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyUp)
|
||||
{
|
||||
ch = ev->data1;
|
||||
|
||||
if (genStringEnter)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case '\b':
|
||||
if (saveCharIndex > 0)
|
||||
{
|
||||
saveCharIndex--;
|
||||
savegamestring[saveCharIndex] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case GK_ESCAPE:
|
||||
genStringEnter = 0;
|
||||
genStringCancel (); // [RH] Function to call when escape is pressed
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
if (savegamestring[0])
|
||||
{
|
||||
genStringEnter = 0;
|
||||
if (messageToPrint)
|
||||
M_ClearMenus ();
|
||||
genStringEnd (SelSaveGame); // [RH] Function to call when enter is pressed
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ev->subtype != EV_GUI_KeyDown && ev->subtype != EV_GUI_KeyUp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
ch = ev->data1;
|
||||
keyup = ev->subtype == EV_GUI_KeyUp;
|
||||
switch (ch)
|
||||
{
|
||||
case '\b':
|
||||
if (saveCharIndex > 0)
|
||||
case GK_ESCAPE: mkey = MKEY_Back; break;
|
||||
case GK_RETURN: mkey = MKEY_Enter; break;
|
||||
case GK_UP: mkey = MKEY_Up; break;
|
||||
case GK_DOWN: mkey = MKEY_Down; break;
|
||||
case GK_LEFT: mkey = MKEY_Left; break;
|
||||
case GK_RIGHT: mkey = MKEY_Right; break;
|
||||
case GK_BACKSPACE: mkey = MKEY_Clear; break;
|
||||
case GK_PGUP: mkey = MKEY_PageUp; break;
|
||||
case GK_PGDN: mkey = MKEY_PageDown; break;
|
||||
default:
|
||||
if (ch == ' ' && currentMenu == &PSetupDef)
|
||||
{
|
||||
saveCharIndex--;
|
||||
savegamestring[saveCharIndex] = 0;
|
||||
mkey = MKEY_Clear;
|
||||
}
|
||||
break;
|
||||
|
||||
case GK_ESCAPE:
|
||||
genStringEnter = 0;
|
||||
genStringCancel (); // [RH] Function to call when escape is pressed
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
if (savegamestring[0])
|
||||
else if (!keyup && !OptionsActive)
|
||||
{
|
||||
genStringEnter = 0;
|
||||
ch = tolower (ch);
|
||||
if (messageToPrint)
|
||||
M_ClearMenus ();
|
||||
genStringEnd (SelSaveGame); // [RH] Function to call when enter is pressed
|
||||
{
|
||||
// Take care of any messages that need input
|
||||
ch = tolower (ch);
|
||||
if (messageNeedsInput)
|
||||
{
|
||||
// For each printable keystroke, both EV_GUI_KeyDown and
|
||||
// EV_GUI_Char will be generated, in that order. If we close
|
||||
// the menu after the first event arrives and the fullscreen
|
||||
// console is up, the console will get the EV_GUI_Char event
|
||||
// next. Therefore, the message input should only respond to
|
||||
// EV_GUI_Char events (sans Escape, which only generates
|
||||
// EV_GUI_KeyDown.)
|
||||
if (ev->subtype != EV_GUI_Char && ch != GK_ESCAPE)
|
||||
{
|
||||
// return false;
|
||||
}
|
||||
if (ch != ' ' && ch != 'n' && ch != 'y' && ch != GK_ESCAPE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
menuactive = messageLastMenuActive;
|
||||
messageToPrint = 0;
|
||||
if (messageRoutine)
|
||||
messageRoutine (ch);
|
||||
|
||||
if (menuactive != MENU_Off)
|
||||
{
|
||||
M_DeactivateMenuInput();
|
||||
}
|
||||
SB_state = screen->GetPageCount(); // refresh the status bar
|
||||
BorderNeedRefresh = screen->GetPageCount();
|
||||
S_Sound(CHAN_VOICE | CHAN_UI, "menu/dismiss", 1, ATTN_NONE);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Search for a menu item associated with the pressed key.
|
||||
for (i = (itemOn + 1) % currentMenu->numitems;
|
||||
i != itemOn;
|
||||
i = (i + 1) % currentMenu->numitems)
|
||||
{
|
||||
if (currentMenu->menuitems[i].alphaKey == ch)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (currentMenu->menuitems[i].alphaKey == ch)
|
||||
{
|
||||
itemOn = i;
|
||||
S_Sound(CHAN_VOICE | CHAN_UI, "menu/cursor", 1, ATTN_NONE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (ev->type == EV_KeyDown || ev->type == EV_KeyUp)
|
||||
{
|
||||
keyup = ev->type == EV_KeyUp;
|
||||
ch = ev->data1;
|
||||
switch (ch)
|
||||
{
|
||||
case KEY_JOY1:
|
||||
case KEY_PAD_A:
|
||||
mkey = MKEY_Enter;
|
||||
break;
|
||||
|
||||
case KEY_JOY2:
|
||||
case KEY_PAD_B:
|
||||
mkey = MKEY_Back;
|
||||
break;
|
||||
|
||||
case KEY_JOY3:
|
||||
case KEY_PAD_X:
|
||||
mkey = MKEY_Clear;
|
||||
break;
|
||||
|
||||
case KEY_JOY5:
|
||||
case KEY_PAD_LSHOULDER:
|
||||
mkey = MKEY_PageUp;
|
||||
break;
|
||||
|
||||
case KEY_JOY6:
|
||||
case KEY_PAD_RSHOULDER:
|
||||
mkey = MKEY_PageDown;
|
||||
break;
|
||||
|
||||
case KEY_PAD_DPAD_UP:
|
||||
case KEY_PAD_LTHUMB_UP:
|
||||
case KEY_JOYAXIS1MINUS:
|
||||
case KEY_JOYPOV1_UP:
|
||||
mkey = MKEY_Up;
|
||||
break;
|
||||
|
||||
case KEY_PAD_DPAD_DOWN:
|
||||
case KEY_PAD_LTHUMB_DOWN:
|
||||
case KEY_JOYAXIS1PLUS:
|
||||
case KEY_JOYPOV1_DOWN:
|
||||
mkey = MKEY_Down;
|
||||
break;
|
||||
|
||||
case KEY_PAD_DPAD_LEFT:
|
||||
case KEY_PAD_LTHUMB_LEFT:
|
||||
case KEY_JOYAXIS2MINUS:
|
||||
case KEY_JOYPOV1_LEFT:
|
||||
mkey = MKEY_Left;
|
||||
break;
|
||||
|
||||
case KEY_PAD_DPAD_RIGHT:
|
||||
case KEY_PAD_LTHUMB_RIGHT:
|
||||
case KEY_JOYAXIS2PLUS:
|
||||
case KEY_JOYPOV1_RIGHT:
|
||||
mkey = MKEY_Right;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Take care of any messages that need input
|
||||
if (messageToPrint)
|
||||
if (mkey != NUM_MKEYS)
|
||||
{
|
||||
ch = tolower (ch);
|
||||
if (messageNeedsInput)
|
||||
if (keyup)
|
||||
{
|
||||
// For each printable keystroke, both EV_GUI_KeyDown and
|
||||
// EV_GUI_Char will be generated, in that order. If we close
|
||||
// the menu after the first event arrives and the fullscreen
|
||||
// console is up, the console will get the EV_GUI_Char event
|
||||
// next. Therefore, the message input should only respond to
|
||||
// EV_GUI_Char events (sans Escape, which only generates
|
||||
// EV_GUI_KeyDown.)
|
||||
if (ev->subtype != EV_GUI_Char && ch != GK_ESCAPE)
|
||||
MenuButtons[mkey].ReleaseKey(ch);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MenuButtons[mkey].PressKey(ch))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (ch != ' ' && ch != 'n' && ch != 'y' && ch != GK_ESCAPE)
|
||||
{
|
||||
return false;
|
||||
if (mkey <= MKEY_PageDown)
|
||||
{
|
||||
MenuButtonTickers[mkey] = KEY_REPEAT_DELAY;
|
||||
}
|
||||
M_ButtonHandler(mkey, false);
|
||||
}
|
||||
}
|
||||
|
||||
menuactive = messageLastMenuActive;
|
||||
messageToPrint = 0;
|
||||
if (messageRoutine)
|
||||
messageRoutine (ch);
|
||||
|
||||
if (menuactive != MENU_Off)
|
||||
{
|
||||
M_DeactivateMenuInput ();
|
||||
}
|
||||
SB_state = screen->GetPageCount (); // refresh the statbar
|
||||
BorderNeedRefresh = screen->GetPageCount ();
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/dismiss", 1, ATTN_NONE);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ch == GK_ESCAPE)
|
||||
{
|
||||
// [RH] Escape now moves back one menu instead of quitting
|
||||
// the menu system. Thus, backspace is ignored.
|
||||
currentMenu->lastOn = itemOn;
|
||||
M_PopMenuStack ();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (currentMenu == &SaveDef || currentMenu == &LoadDef)
|
||||
if (ev->type == EV_GUI_Event && (currentMenu == &SaveDef || currentMenu == &LoadDef))
|
||||
{
|
||||
return M_SaveLoadResponder (ev);
|
||||
}
|
||||
|
||||
// Keys usable within menu
|
||||
switch (ch)
|
||||
// Eat key downs, but let the rest through.
|
||||
return !keyup;
|
||||
}
|
||||
|
||||
void M_ButtonHandler(EMenuKey key, bool repeat)
|
||||
{
|
||||
if (OptionsActive)
|
||||
{
|
||||
case GK_DOWN:
|
||||
M_OptButtonHandler(key, repeat);
|
||||
return;
|
||||
}
|
||||
if (key == MKEY_Back)
|
||||
{
|
||||
// Save the cursor position on the current menu, and pop it off the stack
|
||||
// to go back to the previous menu.
|
||||
currentMenu->lastOn = itemOn;
|
||||
M_PopMenuStack();
|
||||
return;
|
||||
}
|
||||
if (currentMenu == &SaveDef || currentMenu == &LoadDef)
|
||||
{
|
||||
M_SaveLoadButtonHandler(key);
|
||||
return;
|
||||
}
|
||||
switch (key)
|
||||
{
|
||||
case MKEY_Down:
|
||||
do
|
||||
{
|
||||
if (itemOn+1 > currentMenu->numitems-1)
|
||||
if (itemOn + 1 >= currentMenu->numitems)
|
||||
itemOn = 0;
|
||||
else itemOn++;
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", 1, ATTN_NONE);
|
||||
} while(currentMenu->menuitems[itemOn].status==-1);
|
||||
return true;
|
||||
} while (currentMenu->menuitems[itemOn].status == -1);
|
||||
break;
|
||||
|
||||
case GK_UP:
|
||||
case MKEY_Up:
|
||||
do
|
||||
{
|
||||
if (!itemOn)
|
||||
itemOn = currentMenu->numitems-1;
|
||||
if (itemOn == 0)
|
||||
itemOn = currentMenu->numitems - 1;
|
||||
else itemOn--;
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", 1, ATTN_NONE);
|
||||
} while(currentMenu->menuitems[itemOn].status==-1);
|
||||
return true;
|
||||
} while (currentMenu->menuitems[itemOn].status == -1);
|
||||
break;
|
||||
|
||||
case GK_LEFT:
|
||||
case MKEY_Left:
|
||||
if (currentMenu->menuitems[itemOn].routine &&
|
||||
currentMenu->menuitems[itemOn].status == 2)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
|
||||
currentMenu->menuitems[itemOn].routine(0);
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
|
||||
case GK_RIGHT:
|
||||
case MKEY_Right:
|
||||
if (currentMenu->menuitems[itemOn].routine &&
|
||||
currentMenu->menuitems[itemOn].status == 2)
|
||||
{
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
|
||||
currentMenu->menuitems[itemOn].routine(1);
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
case MKEY_Enter:
|
||||
if (currentMenu->menuitems[itemOn].routine &&
|
||||
currentMenu->menuitems[itemOn].status)
|
||||
{
|
||||
|
@ -2976,47 +3144,81 @@ bool M_Responder (event_t *ev)
|
|||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", 1, ATTN_NONE);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
case MKEY_Clear:
|
||||
if (currentMenu == &PSetupDef)
|
||||
{
|
||||
PlayerRotation ^= 8;
|
||||
break;
|
||||
}
|
||||
// intentional fall-through
|
||||
|
||||
default:
|
||||
if (ch)
|
||||
{
|
||||
ch = tolower (ch);
|
||||
for (i = (itemOn + 1) % currentMenu->numitems;
|
||||
i != itemOn;
|
||||
i = (i + 1) % currentMenu->numitems)
|
||||
{
|
||||
if (currentMenu->menuitems[i].alphaKey == ch)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (currentMenu->menuitems[i].alphaKey == ch)
|
||||
{
|
||||
itemOn = i;
|
||||
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", 1, ATTN_NONE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// [RH] Menu eats all keydown events while active
|
||||
return (ev->subtype == EV_GUI_KeyDown);
|
||||
default:
|
||||
break; // Keep GCC quiet
|
||||
}
|
||||
}
|
||||
|
||||
bool M_SaveLoadResponder (event_t *ev)
|
||||
static void M_SaveLoadButtonHandler(EMenuKey key)
|
||||
{
|
||||
char workbuf[512];
|
||||
if (SelSaveGame == NULL || SelSaveGame->Succ == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch (key)
|
||||
{
|
||||
case MKEY_Up:
|
||||
if (SelSaveGame != SaveGames.Head)
|
||||
{
|
||||
if (SelSaveGame == TopSaveGame)
|
||||
{
|
||||
TopSaveGame = static_cast<FSaveGameNode *>(TopSaveGame->Pred);
|
||||
}
|
||||
SelSaveGame = static_cast<FSaveGameNode *>(SelSaveGame->Pred);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelSaveGame = static_cast<FSaveGameNode *>(SaveGames.TailPred);
|
||||
}
|
||||
M_UnloadSaveData ();
|
||||
M_ExtractSaveData (SelSaveGame);
|
||||
break;
|
||||
|
||||
case MKEY_Down:
|
||||
if (SelSaveGame != SaveGames.TailPred)
|
||||
{
|
||||
SelSaveGame = static_cast<FSaveGameNode *>(SelSaveGame->Succ);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelSaveGame = TopSaveGame =
|
||||
static_cast<FSaveGameNode *>(SaveGames.Head);
|
||||
}
|
||||
M_UnloadSaveData ();
|
||||
M_ExtractSaveData (SelSaveGame);
|
||||
break;
|
||||
|
||||
case MKEY_Enter:
|
||||
if (currentMenu == &LoadDef)
|
||||
{
|
||||
M_LoadSelect (SelSaveGame);
|
||||
}
|
||||
else
|
||||
{
|
||||
M_SaveSelect (SelSaveGame);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break; // Keep GCC quiet
|
||||
}
|
||||
}
|
||||
|
||||
static bool M_SaveLoadResponder (event_t *ev)
|
||||
{
|
||||
if (ev->subtype != EV_GUI_KeyDown)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (SelSaveGame != NULL && SelSaveGame->Succ != NULL)
|
||||
{
|
||||
switch (ev->data1)
|
||||
|
@ -3024,6 +3226,8 @@ bool M_SaveLoadResponder (event_t *ev)
|
|||
case GK_F1:
|
||||
if (!SelSaveGame->Filename.IsEmpty())
|
||||
{
|
||||
char workbuf[512];
|
||||
|
||||
mysnprintf (workbuf, countof(workbuf), "File on disk:\n%s", SelSaveGame->Filename.GetChars());
|
||||
if (SaveComment != NULL)
|
||||
{
|
||||
|
@ -3033,37 +3237,6 @@ bool M_SaveLoadResponder (event_t *ev)
|
|||
}
|
||||
break;
|
||||
|
||||
case GK_UP:
|
||||
if (SelSaveGame != SaveGames.Head)
|
||||
{
|
||||
if (SelSaveGame == TopSaveGame)
|
||||
{
|
||||
TopSaveGame = static_cast<FSaveGameNode *>(TopSaveGame->Pred);
|
||||
}
|
||||
SelSaveGame = static_cast<FSaveGameNode *>(SelSaveGame->Pred);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelSaveGame = static_cast<FSaveGameNode *>(SaveGames.TailPred);
|
||||
}
|
||||
M_UnloadSaveData ();
|
||||
M_ExtractSaveData (SelSaveGame);
|
||||
break;
|
||||
|
||||
case GK_DOWN:
|
||||
if (SelSaveGame != SaveGames.TailPred)
|
||||
{
|
||||
SelSaveGame = static_cast<FSaveGameNode *>(SelSaveGame->Succ);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelSaveGame = TopSaveGame =
|
||||
static_cast<FSaveGameNode *>(SaveGames.Head);
|
||||
}
|
||||
M_UnloadSaveData ();
|
||||
M_ExtractSaveData (SelSaveGame);
|
||||
break;
|
||||
|
||||
case GK_DEL:
|
||||
case '\b':
|
||||
if (SelSaveGame != &NewSaveNode)
|
||||
|
@ -3082,20 +3255,9 @@ bool M_SaveLoadResponder (event_t *ev)
|
|||
M_UnloadSaveData ();
|
||||
}
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
if (currentMenu == &LoadDef)
|
||||
{
|
||||
M_LoadSelect (SelSaveGame);
|
||||
}
|
||||
else
|
||||
{
|
||||
M_SaveSelect (SelSaveGame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (ev->subtype == EV_GUI_KeyDown);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void M_LoadSelect (const FSaveGameNode *file)
|
||||
|
@ -3166,7 +3328,11 @@ void M_StartControlPanel (bool makeSound)
|
|||
// intro might call this repeatedly
|
||||
if (menuactive == MENU_On)
|
||||
return;
|
||||
|
||||
|
||||
for (int i = 0; i < NUM_MKEYS; ++i)
|
||||
{
|
||||
MenuButtons[i].ResetTriggers();
|
||||
}
|
||||
drawSkull = true;
|
||||
MenuStackDepth = 0;
|
||||
currentMenu = TopLevelMenu;
|
||||
|
@ -3437,7 +3603,21 @@ void M_Ticker (void)
|
|||
skullAnimCounter = 8;
|
||||
}
|
||||
if (currentMenu == &PSetupDef || currentMenu == &ClassMenuDef)
|
||||
M_PlayerSetupTicker ();
|
||||
{
|
||||
M_PlayerSetupTicker();
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_MKEYS; ++i)
|
||||
{
|
||||
if (MenuButtons[i].bDown)
|
||||
{
|
||||
if (MenuButtonTickers[i] > 0 && --MenuButtonTickers[i] <= 0)
|
||||
{
|
||||
MenuButtonTickers[i] = KEY_REPEAT_RATE;
|
||||
M_ButtonHandler(EMenuKey(i), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue