mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-26 11:40:44 +00:00
7601 lines
302 KiB
C++
7601 lines
302 KiB
C++
//-------------------------------------------------------------------------
|
|
/*
|
|
Copyright (C) 2016 EDuke32 developers and contributors
|
|
|
|
This file is part of EDuke32.
|
|
|
|
EDuke32 is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License version 2
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
//-------------------------------------------------------------------------
|
|
#include "ns.h" // Must come before everything else!
|
|
|
|
#include "compat.h"
|
|
#include "duke3d.h"
|
|
#include "osdcmds.h"
|
|
#include "savegame.h"
|
|
#include "demo.h"
|
|
#include "input.h"
|
|
#include "menus.h"
|
|
#include "cheats.h"
|
|
#include "gamecvars.h"
|
|
#include "../../glbackend/glbackend.h"
|
|
|
|
BEGIN_RR_NS
|
|
|
|
// common positions
|
|
#define MENU_MARGIN_REGULAR 40
|
|
#define MENU_MARGIN_WIDE 32
|
|
#define MENU_MARGIN_CENTER 160
|
|
#define MENU_HEIGHT_CENTER 100
|
|
|
|
int32_t g_skillSoundVoice = -1;
|
|
|
|
#define USERMAPENTRYLENGTH 25
|
|
|
|
static FORCE_INLINE void Menu_StartTextInput()
|
|
{
|
|
inputState.keyFlushChars();
|
|
inputState.ClearKeysDown();
|
|
}
|
|
|
|
static FORCE_INLINE void Menu_StopTextInput()
|
|
{
|
|
}
|
|
|
|
static FORCE_INLINE void rotatesprite_ybounds(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, int8_t dashade, uint8_t dapalnum, int32_t dastat, int32_t ydim_upper, int32_t ydim_lower)
|
|
{
|
|
rotatesprite_(sx, sy, z, a, picnum, dashade, dapalnum, dastat, 0, 0, 0, ydim_upper, xdim-1, ydim_lower);
|
|
}
|
|
|
|
static void mgametext(int32_t x, int32_t y, char const * t)
|
|
{
|
|
G_ScreenText(MF_Bluefont.tilenum, x, y, MF_Bluefont.zoom, 0, 0, t, 0, MF_Bluefont.pal, 2|8|16|ROTATESPRITE_FULL16, 0, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, MF_Bluefont.between.x, MF_Bluefont.between.y, MF_Bluefont.textflags, 0, 0, xdim-1, ydim-1);
|
|
}
|
|
|
|
static vec2_t mgametextcenter(int32_t x, int32_t y, char const * t, int32_t f = 0)
|
|
{
|
|
return G_ScreenText(MF_Bluefont.tilenum, (MENU_MARGIN_CENTER<<16) + x, y, MF_Bluefont.zoom, 0, 0, t, 0, MF_Bluefont.pal, 2|8|16|ROTATESPRITE_FULL16, 0, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, MF_Bluefont.between.x, MF_Bluefont.between.y, MF_Bluefont.textflags|f|TEXT_XCENTER, 0, 0, xdim-1, ydim-1);
|
|
}
|
|
|
|
#define mminitext(x,y,t,p) minitext_(x, y, t, 0, p, 2|8|16|ROTATESPRITE_FULL16)
|
|
#define mmenutext menutext
|
|
|
|
static void shadowminitext(int32_t x, int32_t y, const char *t, int32_t p)
|
|
{
|
|
int32_t f = 0;
|
|
|
|
if (!minitext_lowercase)
|
|
f |= TEXT_UPPERCASE;
|
|
|
|
G_ScreenTextShadow(1, 1, MINIFONT, x, y, RR ? 32768 : 65536, 0, 0, t, 0, p, 2|8|16|ROTATESPRITE_FULL16, 0, 4<<16, 8<<16, 1<<16, 0, f, 0, 0, xdim-1, ydim-1);
|
|
}
|
|
|
|
static void creditsminitext(int32_t x, int32_t y, const char *t, int32_t p)
|
|
{
|
|
int32_t f = TEXT_XCENTER;
|
|
|
|
if (!minitext_lowercase)
|
|
f |= TEXT_UPPERCASE;
|
|
|
|
G_ScreenTextShadow(1, 1, MINIFONT, x, y, RR ? 32768 : 65536, 0, 0, t, 0, p, 2|8|16|ROTATESPRITE_FULL16, 0, 4<<16, 8<<16, 1<<16, 0, f, 0, 0, xdim-1, ydim-1);
|
|
}
|
|
|
|
#pragma pack(push,1)
|
|
static savehead_t savehead;
|
|
#pragma pack(pop)
|
|
|
|
static void Menu_DrawBackground(const vec2_t origin)
|
|
{
|
|
rotatesprite_fs(origin.x + (MENU_MARGIN_CENTER<<16), origin.y + (100<<16), 65536L,0,MENUSCREEN,16,0,10+64);
|
|
}
|
|
|
|
static void Menu_DrawTopBar(const vec2_t origin)
|
|
{
|
|
rotatesprite_fs(origin.x + (MENU_MARGIN_CENTER<<16), origin.y + (19<<16), MF_Redfont.cursorScale3, 0,MENUBAR,16,0,10);
|
|
}
|
|
|
|
static void Menu_DrawTopBarCaption(const char *caption, const vec2_t origin)
|
|
{
|
|
static char t[64];
|
|
size_t const srclen = strlen(caption);
|
|
size_t const dstlen = min(srclen, ARRAY_SIZE(t)-1);
|
|
memcpy(t, caption, dstlen);
|
|
t[dstlen] = '\0';
|
|
char *p = &t[dstlen-1];
|
|
if (*p == ':')
|
|
*p = '\0';
|
|
captionmenutext(origin.x + (MENU_MARGIN_CENTER<<16), origin.y + (24<<16) + (15<<15), t);
|
|
}
|
|
|
|
static FORCE_INLINE int32_t Menu_CursorShade(void)
|
|
{
|
|
return 4-(sintable[((int32_t) totalclock<<4)&2047]>>11);
|
|
}
|
|
static void Menu_DrawCursorCommon(int32_t x, int32_t y, int32_t z, int32_t picnum, int32_t ydim_upper = 0, int32_t ydim_lower = ydim-1)
|
|
{
|
|
rotatesprite_(x, y, z, 0, picnum, Menu_CursorShade(), 0, 2|8, 0, 0, 0, ydim_upper, xdim-1, ydim_lower);
|
|
}
|
|
static void Menu_DrawCursorLeft(int32_t x, int32_t y, int32_t z)
|
|
{
|
|
const int frames = RR ? 16 : 7;
|
|
Menu_DrawCursorCommon(x, y, z, SPINNINGNUKEICON+(((int32_t) totalclock>>3)%frames));
|
|
}
|
|
static void Menu_DrawCursorRight(int32_t x, int32_t y, int32_t z)
|
|
{
|
|
const int frames = RR ? 16 : 7;
|
|
Menu_DrawCursorCommon(x, y, z, SPINNINGNUKEICON+frames-1-((frames-1+((int32_t) totalclock>>3))%frames));
|
|
}
|
|
static void Menu_DrawCursorTextTile(int32_t x, int32_t y, int32_t h, int32_t picnum, vec2_16_t const & siz, int32_t ydim_upper = 0, int32_t ydim_lower = ydim-1)
|
|
{
|
|
vec2_t const adjsiz = { siz.x<<15, siz.y<<16 };
|
|
Menu_DrawCursorCommon(x + scale(adjsiz.x, h, adjsiz.y), y, divscale16(h, adjsiz.y), picnum, ydim_upper, ydim_lower);
|
|
}
|
|
static void Menu_DrawCursorText(int32_t x, int32_t y, int32_t h, int32_t ydim_upper = 0, int32_t ydim_lower = ydim-1)
|
|
{
|
|
vec2_16_t const & siz = tilesiz[SPINNINGNUKEICON];
|
|
const int frames = RR ? 16 : 7;
|
|
|
|
if (siz.x == 0)
|
|
{
|
|
Menu_DrawCursorTextTile(x, y, h, SMALLFNTCURSOR, tilesiz[SMALLFNTCURSOR], ydim_upper, ydim_lower);
|
|
return;
|
|
}
|
|
|
|
Menu_DrawCursorTextTile(x, y, h, SPINNINGNUKEICON+(((int32_t) totalclock>>3)%frames), siz, ydim_upper, ydim_lower);
|
|
}
|
|
|
|
|
|
static uint16_t g_oldSaveCnt;
|
|
|
|
|
|
|
|
|
|
/*
|
|
All MAKE_* macros are generally for the purpose of keeping state initialization
|
|
separate from actual data. Alternatively, they can serve to factor out repetitive
|
|
stuff and keep the important bits from getting lost to our eyes.
|
|
|
|
They serve as a stand-in for C++ default value constructors, since we're using C89.
|
|
|
|
Note that I prefer to include a space on the inside of the macro parentheses, since
|
|
they effectively stand in for curly braces as struct initializers.
|
|
*/
|
|
|
|
|
|
// common font types
|
|
// tilenums are set after namesdyn runs
|
|
|
|
// emptychar x,y between x,y zoom cursorLeft cursorCenter cursorScale textflags
|
|
// tilenum shade_deselected shade_disabled pal pal_selected pal_deselected pal_disabled
|
|
MenuFont_t MF_Redfont = { { 5<<16, 15<<16 }, { 0, 0 }, 65536, 20<<16, 110<<16, 65536, 65536, 65536, TEXT_BIGALPHANUM | TEXT_UPPERCASE,
|
|
-1, 10, 0, 0, 0, 0, 1,
|
|
0, 0, 1 };
|
|
MenuFont_t MF_Bluefont = { { 5<<16, 7<<16 }, { 0, 0 }, 65536, 10<<16, 110<<16, 32768, 65536, 65536, 0,
|
|
-1, 10, 0, 0, 10, 10, 16,
|
|
0, 0, 16 };
|
|
MenuFont_t MF_Minifont = { { 4<<16, 5<<16 }, { 1<<16, 1<<16 }, 65536, 10<<16, 110<<16, 32768, 65536, 65536, 0,
|
|
-1, 10, 0, 0, 2, 2, 0,
|
|
0, 0, 16 };
|
|
|
|
|
|
static MenuMenuFormat_t MMF_Top_Main = { { MENU_MARGIN_CENTER<<16, 55<<16, }, -(170<<16) };
|
|
static MenuMenuFormat_t MMF_Top_Episode = { { MENU_MARGIN_CENTER<<16, 48<<16, }, -(190<<16) };
|
|
static MenuMenuFormat_t MMF_Top_Skill = { { MENU_MARGIN_CENTER<<16, 58<<16, }, -(190<<16) };
|
|
static MenuMenuFormat_t MMF_Top_Options = { { MENU_MARGIN_CENTER<<16, 38<<16, }, -(190<<16) };
|
|
static MenuMenuFormat_t MMF_Top_Joystick_Network = { { MENU_MARGIN_CENTER<<16, 70<<16, }, -(190<<16) };
|
|
static MenuMenuFormat_t MMF_BigOptions = { { MENU_MARGIN_WIDE<<16, 38<<16, }, -(190<<16) };
|
|
static MenuMenuFormat_t MMF_SmallOptions = { { MENU_MARGIN_WIDE<<16, 37<<16, }, 170<<16 };
|
|
static MenuMenuFormat_t MMF_Macros = { { 26<<16, 40<<16, }, 160<<16 };
|
|
static MenuMenuFormat_t MMF_SmallOptionsNarrow = { { MENU_MARGIN_REGULAR<<16, 38<<16, }, -(190<<16) };
|
|
static MenuMenuFormat_t MMF_KeyboardSetupFuncs = { { 50<<16, 34<<16, }, 151<<16 };
|
|
static MenuMenuFormat_t MMF_MouseJoySetupBtns = { { 76<<16, 34<<16, }, 143<<16 };
|
|
static MenuMenuFormat_t MMF_FuncList = { { 100<<16, 51<<16, }, 152<<16 };
|
|
static MenuMenuFormat_t MMF_ColorCorrect = { { MENU_MARGIN_REGULAR<<16, 86<<16, }, 190<<16 };
|
|
static MenuMenuFormat_t MMF_BigSliders = { { MENU_MARGIN_WIDE<<16, 37<<16, }, 190<<16 };
|
|
static MenuMenuFormat_t MMF_LoadSave = { { 200<<16, 49<<16, }, 145<<16 };
|
|
static MenuMenuFormat_t MMF_NetSetup = { { 36<<16, 38<<16, }, 190<<16 };
|
|
static MenuMenuFormat_t MMF_FileSelectLeft = { { 40<<16, 45<<16, }, 162<<16 };
|
|
static MenuMenuFormat_t MMF_FileSelectRight = { { 164<<16, 45<<16, }, 162<<16 };
|
|
|
|
static MenuEntryFormat_t MEF_Null = { 0, 0, 0 };
|
|
static MenuEntryFormat_t MEF_MainMenu = { 4<<16, 0, 0 };
|
|
static MenuEntryFormat_t MEF_OptionsMenu = { 7<<16, 0, 0 };
|
|
static MenuEntryFormat_t MEF_CenterMenu = { 7<<16, 0, 0 };
|
|
static MenuEntryFormat_t MEF_BigOptions_Apply = { 4<<16, 16<<16, -(260<<16) };
|
|
static MenuEntryFormat_t MEF_BigOptionsRt = { 4<<16, 0, -(260<<16) };
|
|
#if defined USE_OPENGL || !defined EDUKE32_ANDROID_MENU
|
|
static MenuEntryFormat_t MEF_SmallOptions = { 1<<16, 0, -(260<<16) };
|
|
#endif
|
|
static MenuEntryFormat_t MEF_BigCheats = { 3<<16, 0, -(260<<16) };
|
|
static MenuEntryFormat_t MEF_Cheats = { 2<<16, 0, -(260<<16) };
|
|
static MenuEntryFormat_t MEF_PlayerNarrow = { 1<<16, 0, 90<<16 };
|
|
static MenuEntryFormat_t MEF_Macros = { 2<<16, -1, 268<<16 };
|
|
static MenuEntryFormat_t MEF_VideoSetup = { 4<<16, 0, 168<<16 };
|
|
static MenuEntryFormat_t MEF_VideoSetup_Apply = { 4<<16, 16<<16, 168<<16 };
|
|
static MenuEntryFormat_t MEF_KBFuncList = { 3<<16, 0, -(225<<16) };
|
|
static MenuEntryFormat_t MEF_FuncList = { 3<<16, 0, -(170<<16) };
|
|
static MenuEntryFormat_t MEF_ColorCorrect = { 2<<16, 0, -(240<<16) };
|
|
static MenuEntryFormat_t MEF_BigSliders = { 2<<16, 0, -(260<<16) };
|
|
static MenuEntryFormat_t MEF_LoadSave = { 2<<16, -1, 78<<16 };
|
|
static MenuEntryFormat_t MEF_NetSetup = { 4<<16, 0, 112<<16 };
|
|
static MenuEntryFormat_t MEF_NetSetup_Confirm = { 4<<16, 16<<16, 112<<16 };
|
|
|
|
// common menu option sets
|
|
#define MAKE_MENUOPTIONSET(optionNames, optionValues, features) { optionNames, optionValues, &MMF_FuncList, &MEF_FuncList, &MF_Minifont, ARRAY_SIZE(optionNames), -1, 0, features }
|
|
#define MAKE_MENUOPTIONSETDYN(optionNames, optionValues, numOptions, features) { optionNames, optionValues, &MMF_FuncList, &MEF_FuncList, &MF_Minifont, numOptions, -1, 0, features }
|
|
#define MAKE_MENUOPTIONSETNULL { NULL, NULL, &MMF_FuncList, &MEF_FuncList, &MF_Minifont, 0, -1, 0, 0 }
|
|
|
|
static char const *MEOSN_OffOn[] = { "Off", "On", };
|
|
static MenuOptionSet_t MEOS_OffOn = MAKE_MENUOPTIONSET( MEOSN_OffOn, NULL, 0x3 );
|
|
static char const *MEOSN_OnOff[] = { "On", "Off", };
|
|
static MenuOptionSet_t MEOS_OnOff = MAKE_MENUOPTIONSET( MEOSN_OnOff, NULL, 0x3 );
|
|
static char const *MEOSN_NoYes[] = { "No", "Yes", };
|
|
static MenuOptionSet_t MEOS_NoYes = MAKE_MENUOPTIONSET( MEOSN_NoYes, NULL, 0x3 );
|
|
static char const *MEOSN_YesNo[] = { "Yes", "No", };
|
|
static MenuOptionSet_t MEOS_YesNo = MAKE_MENUOPTIONSET( MEOSN_YesNo, NULL, 0x3 );
|
|
|
|
|
|
static FString MenuGameFuncs[NUMGAMEFUNCTIONS];
|
|
static char const *MenuGameFuncNone = " -None-";
|
|
static char const *MEOSN_Gamefuncs[NUMGAMEFUNCTIONS+1];
|
|
static int32_t MEOSV_Gamefuncs[NUMGAMEFUNCTIONS+1];
|
|
static MenuOptionSet_t MEOS_Gamefuncs = MAKE_MENUOPTIONSET( MEOSN_Gamefuncs, MEOSV_Gamefuncs, 0x1 );
|
|
|
|
|
|
|
|
/*
|
|
MenuEntry_t is passed in arrays of pointers so that the callback function
|
|
that is called when an entry is modified or activated can test equality of the current
|
|
entry pointer directly against the known ones, instead of relying on an ID number.
|
|
|
|
That way, individual menu entries can be ifdef'd out painlessly.
|
|
*/
|
|
|
|
static MenuLink_t MEO_NULL = { MENU_NULL, MA_None, };
|
|
static const char* MenuCustom = "Custom";
|
|
|
|
#define MAKE_MENUSTRING(...) { NULL, __VA_ARGS__, }
|
|
#define MAKE_MENUOPTION(...) { __VA_ARGS__, -1, }
|
|
#define MAKE_MENURANGE(...) { __VA_ARGS__, }
|
|
#define MAKE_MENUENTRY(...) { __VA_ARGS__, 0, 0, 0, }
|
|
|
|
|
|
#define MAKE_SPACER( EntryName, Height ) \
|
|
static MenuSpacer_t MEO_ ## EntryName = { Height };
|
|
|
|
MAKE_SPACER( Space2, 2<<16 ); // bigoptions
|
|
MAKE_SPACER( Space4, 4<<16 ); // usermap, smalloptions, anything else non-top
|
|
MAKE_SPACER( Space6, 6<<16 ); // videosetup
|
|
MAKE_SPACER( Space8, 8<<16 ); // colcorr, redslide
|
|
|
|
static MenuEntry_t ME_Space2_Redfont = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_Null, &MEO_Space2, Spacer );
|
|
static MenuEntry_t ME_Space4_Bluefont = MAKE_MENUENTRY( NULL, &MF_Bluefont, &MEF_Null, &MEO_Space4, Spacer );
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
static MenuEntry_t ME_Space4_Redfont = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_Null, &MEO_Space4, Spacer );
|
|
static MenuEntry_t ME_Space8_Bluefont = MAKE_MENUENTRY( NULL, &MF_Bluefont, &MEF_Null, &MEO_Space8, Spacer );
|
|
#endif
|
|
static MenuEntry_t ME_Space6_Redfont = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_Null, &MEO_Space6, Spacer );
|
|
static MenuEntry_t ME_Space8_Redfont = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_Null, &MEO_Space8, Spacer );
|
|
|
|
#define MAKE_MENU_TOP_ENTRYLINK( Title, Format, EntryName, LinkID ) \
|
|
static MenuLink_t MEO_ ## EntryName = { LinkID, MA_Advance, };\
|
|
static MenuEntry_t ME_ ## EntryName = MAKE_MENUENTRY( Title, &MF_Redfont, &Format, &MEO_ ## EntryName, Link )
|
|
|
|
static char const s_NewGame[] = "New Game";
|
|
static char const s_SaveGame[] = "Save Game";
|
|
static char const s_LoadGame[] = "Load Game";
|
|
static char const s_Continue[] = "Continue";
|
|
static char const s_Options[] = "Options";
|
|
static char const s_Credits[] = "Credits";
|
|
|
|
MAKE_MENU_TOP_ENTRYLINK( s_NewGame, MEF_MainMenu, MAIN_NEWGAME, MENU_EPISODE );
|
|
#ifdef EDUKE32_SIMPLE_MENU
|
|
MAKE_MENU_TOP_ENTRYLINK( "Resume Game", MEF_MainMenu, MAIN_RESUMEGAME, MENU_CLOSE );
|
|
#endif
|
|
MAKE_MENU_TOP_ENTRYLINK( s_NewGame, MEF_MainMenu, MAIN_NEWGAME_INGAME, MENU_NEWVERIFY );
|
|
static MenuLink_t MEO_MAIN_NEWGAME_NETWORK = { MENU_NETWORK, MA_Advance, };
|
|
MAKE_MENU_TOP_ENTRYLINK( s_SaveGame, MEF_MainMenu, MAIN_SAVEGAME, MENU_SAVE );
|
|
MAKE_MENU_TOP_ENTRYLINK( s_LoadGame, MEF_MainMenu, MAIN_LOADGAME, MENU_LOAD );
|
|
MAKE_MENU_TOP_ENTRYLINK( s_Options, MEF_MainMenu, MAIN_OPTIONS, MENU_OPTIONS );
|
|
MAKE_MENU_TOP_ENTRYLINK("Help", MEF_MainMenu, MAIN_HELP, MENU_STORY);
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
MAKE_MENU_TOP_ENTRYLINK( s_Credits, MEF_MainMenu, MAIN_CREDITS, MENU_CREDITS );
|
|
#endif
|
|
MAKE_MENU_TOP_ENTRYLINK( "End Game", MEF_MainMenu, MAIN_QUITTOTITLE, MENU_QUITTOTITLE );
|
|
MAKE_MENU_TOP_ENTRYLINK( "Quit", MEF_MainMenu, MAIN_QUIT, MENU_QUIT );
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
MAKE_MENU_TOP_ENTRYLINK( "Quit Game", MEF_MainMenu, MAIN_QUITGAME, MENU_QUIT );
|
|
#endif
|
|
|
|
static MenuEntry_t *MEL_MAIN[] = {
|
|
&ME_MAIN_NEWGAME,
|
|
&ME_MAIN_LOADGAME,
|
|
&ME_MAIN_OPTIONS,
|
|
&ME_MAIN_HELP,
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
&ME_MAIN_CREDITS,
|
|
#endif
|
|
&ME_MAIN_QUIT,
|
|
};
|
|
|
|
static MenuEntry_t *MEL_MAIN_INGAME[] = {
|
|
#ifdef EDUKE32_SIMPLE_MENU
|
|
&ME_MAIN_RESUMEGAME,
|
|
#else
|
|
&ME_MAIN_NEWGAME_INGAME,
|
|
#endif
|
|
&ME_MAIN_SAVEGAME,
|
|
&ME_MAIN_LOADGAME,
|
|
&ME_MAIN_OPTIONS,
|
|
&ME_MAIN_HELP,
|
|
&ME_MAIN_QUITTOTITLE,
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
&ME_MAIN_QUITGAME,
|
|
#endif
|
|
};
|
|
|
|
// Episode and Skill will be dynamically generated after CONs are parsed
|
|
static MenuLink_t MEO_EPISODE = { MENU_SKILL, MA_Advance, };
|
|
static MenuLink_t MEO_EPISODE_SHAREWARE = { MENU_BUYDUKE, MA_Advance, };
|
|
static MenuEntry_t ME_EPISODE_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_CenterMenu, &MEO_EPISODE, Link );
|
|
static MenuEntry_t ME_EPISODE[MAXVOLUMES];
|
|
static MenuLink_t MEO_EPISODE_USERMAP = { MENU_USERMAP, MA_Advance, };
|
|
static MenuEntry_t ME_EPISODE_USERMAP = MAKE_MENUENTRY( "User Map", &MF_Redfont, &MEF_CenterMenu, &MEO_EPISODE_USERMAP, Link );
|
|
static MenuEntry_t *MEL_EPISODE[MAXVOLUMES+2]; // +2 for spacer and User Map
|
|
|
|
static MenuEntry_t ME_SKILL_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_CenterMenu, &MEO_NULL, Link );
|
|
static MenuEntry_t ME_SKILL[MAXSKILLS];
|
|
static MenuEntry_t *MEL_SKILL[MAXSKILLS];
|
|
|
|
static char const *MEOSN_GAMESETUP_AIM_AUTO[] = { "Never", "Always", "Hitscan only",
|
|
};
|
|
static int32_t MEOSV_GAMESETUP_AIM_AUTO[] = { 0, 1, 2,
|
|
};
|
|
|
|
static MenuOptionSet_t MEOS_GAMESETUP_AIM_AUTO = MAKE_MENUOPTIONSET( MEOSN_GAMESETUP_AIM_AUTO, MEOSV_GAMESETUP_AIM_AUTO, 0x2 );
|
|
static MenuOption_t MEO_GAMESETUP_AIM_AUTO = MAKE_MENUOPTION( &MF_Redfont, &MEOS_GAMESETUP_AIM_AUTO, &cl_autoaim.Value );
|
|
static MenuEntry_t ME_GAMESETUP_AIM_AUTO = MAKE_MENUENTRY( "Auto aim:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_GAMESETUP_AIM_AUTO, Option );
|
|
|
|
static char const *MEOSN_GAMESETUP_WEAPSWITCH_PICKUP[] = { "Never", "If new", "By rating", };
|
|
static MenuOptionSet_t MEOS_GAMESETUP_WEAPSWITCH_PICKUP = MAKE_MENUOPTIONSET( MEOSN_GAMESETUP_WEAPSWITCH_PICKUP, NULL, 0x2 );
|
|
static MenuOption_t MEO_GAMESETUP_WEAPSWITCH_PICKUP = MAKE_MENUOPTION( &MF_Redfont, &MEOS_GAMESETUP_WEAPSWITCH_PICKUP, NULL );
|
|
static MenuEntry_t ME_GAMESETUP_WEAPSWITCH_PICKUP = MAKE_MENUENTRY( "Equip pickups:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_GAMESETUP_WEAPSWITCH_PICKUP, Option );
|
|
|
|
static char const *MEOSN_DemoRec[] = { "Off", "Running", };
|
|
static MenuOptionSet_t MEOS_DemoRec = MAKE_MENUOPTIONSET( MEOSN_DemoRec, NULL, 0x3 );
|
|
static MenuOption_t MEO_GAMESETUP_DEMOREC = MAKE_MENUOPTION( &MF_Redfont, &MEOS_OffOn, &ud.m_recstat );
|
|
static MenuEntry_t ME_GAMESETUP_DEMOREC = MAKE_MENUENTRY( "Record demo:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_GAMESETUP_DEMOREC, Option );
|
|
|
|
static MenuOption_t MEO_ADULTMODE = MAKE_MENUOPTION(&MF_Redfont, &MEOS_OffOn, &adult_lockout.Value);
|
|
static MenuEntry_t ME_ADULTMODE = MAKE_MENUENTRY( "Parental lock:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_ADULTMODE, Option );
|
|
|
|
#if defined(EDUKE32_ANDROID_MENU) || !defined(EDUKE32_SIMPLE_MENU)
|
|
static MenuLink_t MEO_GAMESETUP_CHEATS = { MENU_CHEATS, MA_Advance, };
|
|
static MenuEntry_t ME_GAMESETUP_CHEATS = MAKE_MENUENTRY( "Cheats", &MF_Redfont, &MEF_BigOptionsRt, &MEO_GAMESETUP_CHEATS, Link );
|
|
|
|
static MenuEntry_t *MEL_GAMESETUP[] = {
|
|
&ME_ADULTMODE,
|
|
#if defined STARTUP_SETUP_WINDOW && !defined EDUKE32_SIMPLE_MENU
|
|
&ME_GAMESETUP_STARTWIN,
|
|
#endif
|
|
&ME_GAMESETUP_AIM_AUTO,
|
|
//&ME_GAMESETUP_WEAPSWITCH_PICKUP,
|
|
#ifdef EDUKE32_ANDROID_MENU
|
|
&ME_GAMESETUP_QUICKSWITCH,
|
|
&ME_GAMESETUP_CROUCHLOCK,
|
|
#else
|
|
&ME_GAMESETUP_DEMOREC,
|
|
#endif
|
|
&ME_GAMESETUP_CHEATS,
|
|
};
|
|
#endif
|
|
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
MAKE_MENU_TOP_ENTRYLINK( "Game Setup", MEF_OptionsMenu, OPTIONS_GAMESETUP, MENU_GAMESETUP );
|
|
#endif
|
|
MAKE_MENU_TOP_ENTRYLINK( "Sound Setup", MEF_OptionsMenu, OPTIONS_SOUNDSETUP, MENU_SOUND );
|
|
MAKE_MENU_TOP_ENTRYLINK( "Display Setup", MEF_OptionsMenu, OPTIONS_DISPLAYSETUP, MENU_DISPLAYSETUP );
|
|
MAKE_MENU_TOP_ENTRYLINK( "Player Setup", MEF_OptionsMenu, OPTIONS_PLAYERSETUP, MENU_PLAYER );
|
|
#ifndef EDUKE32_ANDROID_MENU
|
|
MAKE_MENU_TOP_ENTRYLINK( "Control Setup", MEF_OptionsMenu, OPTIONS_CONTROLS, MENU_CONTROLS );
|
|
|
|
MAKE_MENU_TOP_ENTRYLINK( "Keyboard Setup", MEF_CenterMenu, OPTIONS_KEYBOARDSETUP, MENU_KEYBOARDSETUP );
|
|
MAKE_MENU_TOP_ENTRYLINK( "Mouse Setup", MEF_CenterMenu, OPTIONS_MOUSESETUP, MENU_MOUSESETUP );
|
|
#endif
|
|
MAKE_MENU_TOP_ENTRYLINK( "Joystick Setup", MEF_CenterMenu, OPTIONS_JOYSTICKSETUP, MENU_JOYSTICKSETUP );
|
|
#ifdef EDUKE32_ANDROID_MENU
|
|
MAKE_MENU_TOP_ENTRYLINK( "Touch Setup", MEF_CenterMenu, OPTIONS_TOUCHSETUP, MENU_TOUCHSETUP );
|
|
#endif
|
|
#ifdef EDUKE32_SIMPLE_MENU
|
|
MAKE_MENU_TOP_ENTRYLINK("Cheats", MEF_OptionsMenu, OPTIONS_CHEATS, MENU_CHEATS);
|
|
#endif
|
|
|
|
static int32_t newresolution, newrendermode, newfullscreen, newvsync;
|
|
|
|
enum resflags_t {
|
|
RES_FS = 0x1,
|
|
RES_WIN = 0x2,
|
|
};
|
|
|
|
#define MAXRESOLUTIONSTRINGLENGTH 19
|
|
|
|
typedef struct resolution_t {
|
|
int32_t xdim, ydim;
|
|
int32_t flags;
|
|
int32_t bppmax;
|
|
char name[MAXRESOLUTIONSTRINGLENGTH];
|
|
} resolution_t;
|
|
|
|
resolution_t resolution[MAXVALIDMODES];
|
|
|
|
static char const *MEOSN_VIDEOSETUP_RESOLUTION[MAXVALIDMODES];
|
|
static MenuOptionSet_t MEOS_VIDEOSETUP_RESOLUTION = MAKE_MENUOPTIONSETDYN( MEOSN_VIDEOSETUP_RESOLUTION, NULL, 0, 0x0 );
|
|
static MenuOption_t MEO_VIDEOSETUP_RESOLUTION = MAKE_MENUOPTION( &MF_Redfont, &MEOS_VIDEOSETUP_RESOLUTION, &newresolution );
|
|
static MenuEntry_t ME_VIDEOSETUP_RESOLUTION = MAKE_MENUENTRY( "Resolution:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_VIDEOSETUP_RESOLUTION, Option );
|
|
|
|
#ifdef USE_OPENGL
|
|
#ifdef POLYMER
|
|
static char const *MEOSN_VIDEOSETUP_RENDERER[] = { "Classic", "Polymost", "Polymer", };
|
|
static int32_t MEOSV_VIDEOSETUP_RENDERER[] = { REND_CLASSIC, REND_POLYMOST, REND_POLYMER, };
|
|
#else
|
|
static char const *MEOSN_VIDEOSETUP_RENDERER[] = { "Classic", "OpenGL", };
|
|
static int32_t MEOSV_VIDEOSETUP_RENDERER[] = { REND_CLASSIC, REND_POLYMOST, };
|
|
#endif
|
|
|
|
static MenuOptionSet_t MEOS_VIDEOSETUP_RENDERER = MAKE_MENUOPTIONSET( MEOSN_VIDEOSETUP_RENDERER, MEOSV_VIDEOSETUP_RENDERER, 0x2 );
|
|
|
|
static MenuOption_t MEO_VIDEOSETUP_RENDERER = MAKE_MENUOPTION( &MF_Redfont, &MEOS_VIDEOSETUP_RENDERER, &newrendermode );
|
|
static MenuEntry_t ME_VIDEOSETUP_RENDERER = MAKE_MENUENTRY( "Renderer:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_VIDEOSETUP_RENDERER, Option );
|
|
#endif
|
|
|
|
static MenuOption_t MEO_VIDEOSETUP_FULLSCREEN = MAKE_MENUOPTION( &MF_Redfont, &MEOS_NoYes, &newfullscreen );
|
|
static MenuEntry_t ME_VIDEOSETUP_FULLSCREEN = MAKE_MENUENTRY( "Fullscreen:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_VIDEOSETUP_FULLSCREEN, Option );
|
|
|
|
|
|
static char const *MEOSN_VIDEOSETUP_VSYNC [] = { "Adaptive", "Off", "On", };
|
|
static int32_t MEOSV_VIDEOSETUP_VSYNC [] = { -1, 0, 1, };
|
|
static MenuOptionSet_t MEOS_VIDEOSETUP_VSYNC = MAKE_MENUOPTIONSET(MEOSN_VIDEOSETUP_VSYNC, MEOSV_VIDEOSETUP_VSYNC, 0x2);
|
|
static MenuOption_t MEO_VIDEOSETUP_VSYNC = MAKE_MENUOPTION(&MF_Redfont, &MEOS_VIDEOSETUP_VSYNC, &newvsync);
|
|
static MenuEntry_t ME_VIDEOSETUP_VSYNC = MAKE_MENUENTRY("VSync:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_VIDEOSETUP_VSYNC, Option);
|
|
|
|
//static char const *MEOSN_VIDEOSETUP_FRAMELIMIT [] = { "30 fps", "60 fps", "75 fps", "100 fps", "120 fps", "144 fps", "165 fps", "240 fps" };
|
|
|
|
static MenuEntry_t ME_VIDEOSETUP_APPLY = MAKE_MENUENTRY( "Apply Changes", &MF_Redfont, &MEF_BigOptions_Apply, &MEO_NULL, Link );
|
|
|
|
|
|
static MenuLink_t MEO_DISPLAYSETUP_COLORCORR = { MENU_COLCORR, MA_Advance, };
|
|
static MenuEntry_t ME_DISPLAYSETUP_COLORCORR = MAKE_MENUENTRY( "Color Correction", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_COLORCORR, Link );
|
|
|
|
|
|
static char const *MEOSN_DISPLAYSETUP_UPSCALING[] = { "None", "2x", "4x" };
|
|
static int32_t MEOSV_DISPLAYSETUP_UPSCALING[] = { 1, 2, 4 };
|
|
static MenuOptionSet_t MEOS_DISPLAYSETUP_UPSCALING = MAKE_MENUOPTIONSET( MEOSN_DISPLAYSETUP_UPSCALING, MEOSV_DISPLAYSETUP_UPSCALING, 0x0 );
|
|
static MenuOption_t MEO_DISPLAYSETUP_UPSCALING = MAKE_MENUOPTION( &MF_Redfont, &MEOS_DISPLAYSETUP_UPSCALING, &ud.detail );
|
|
static MenuEntry_t ME_DISPLAYSETUP_UPSCALING = MAKE_MENUENTRY( "Upscaling:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_UPSCALING, Option );
|
|
|
|
|
|
#ifndef EDUKE32_ANDROID_MENU
|
|
static MenuOption_t MEO_DISPLAYSETUP_ASPECTRATIO = MAKE_MENUOPTION(&MF_Redfont, &MEOS_OffOn, &r_usenewaspect);
|
|
static MenuEntry_t ME_DISPLAYSETUP_ASPECTRATIO = MAKE_MENUENTRY( "Widescreen:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_ASPECTRATIO, Option );
|
|
#endif
|
|
|
|
|
|
static MenuRangeInt32_t MEO_DISPLAYSETUP_FOV = MAKE_MENURANGE( &r_fov.Value, &MF_Redfont, 75, 120, 0, 10, 0 );
|
|
static MenuEntry_t ME_DISPLAYSETUP_FOV = MAKE_MENUENTRY( "FOV:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_FOV, RangeInt32 );
|
|
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
//POGOTODO: allow filtering again in standalone once indexed colour textures support filtering
|
|
static char const *MEOSN_DISPLAYSETUP_TEXFILTER[] = { "Classic", "Filtered" };
|
|
static int32_t MEOSV_DISPLAYSETUP_TEXFILTER[] = { TEXFILTER_OFF, TEXFILTER_ON };
|
|
static MenuOptionSet_t MEOS_DISPLAYSETUP_TEXFILTER = MAKE_MENUOPTIONSET( MEOSN_DISPLAYSETUP_TEXFILTER, MEOSV_DISPLAYSETUP_TEXFILTER, 0x2 );
|
|
static MenuOption_t MEO_DISPLAYSETUP_TEXFILTER = MAKE_MENUOPTION( &MF_Redfont, &MEOS_DISPLAYSETUP_TEXFILTER, &hw_texfilter.Value);
|
|
static MenuEntry_t ME_DISPLAYSETUP_TEXFILTER = MAKE_MENUENTRY( "Texture Mode:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_TEXFILTER, Option );
|
|
|
|
static char const *MEOSN_DISPLAYSETUP_ANISOTROPY[] = { "Max", "None", "2x", "4x", "8x", "16x", };
|
|
static int32_t MEOSV_DISPLAYSETUP_ANISOTROPY[] = { 0, 1, 2, 4, 8, 16, };
|
|
static MenuOptionSet_t MEOS_DISPLAYSETUP_ANISOTROPY = MAKE_MENUOPTIONSET( MEOSN_DISPLAYSETUP_ANISOTROPY, MEOSV_DISPLAYSETUP_ANISOTROPY, 0x0 );
|
|
static MenuOption_t MEO_DISPLAYSETUP_ANISOTROPY = MAKE_MENUOPTION(&MF_Redfont, &MEOS_DISPLAYSETUP_ANISOTROPY, &hw_anisotropy.Value);
|
|
static MenuEntry_t ME_DISPLAYSETUP_ANISOTROPY = MAKE_MENUENTRY( "Anisotropy:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_ANISOTROPY, Option );
|
|
# endif
|
|
|
|
# ifdef EDUKE32_ANDROID_MENU
|
|
static MenuOption_t MEO_DISPLAYSETUP_HIDEDPAD = MAKE_MENUOPTION(&MF_Redfont, &MEOS_NoYes, &droidinput.hideStick);
|
|
static MenuEntry_t ME_DISPLAYSETUP_HIDEDPAD = MAKE_MENUENTRY("Hide touch D-pad:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_HIDEDPAD, Option);
|
|
|
|
static MenuRangeFloat_t MEO_DISPLAYSETUP_TOUCHALPHA = MAKE_MENURANGE(&droidinput.gameControlsAlpha, &MF_Redfont, 0, 1, 0, 16, 2);
|
|
static MenuEntry_t ME_DISPLAYSETUP_TOUCHALPHA = MAKE_MENUENTRY("UI opacity:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_TOUCHALPHA, RangeFloat);
|
|
# endif
|
|
|
|
|
|
static char const s_Scale[] = "Scale:";
|
|
|
|
static MenuOption_t MEO_SCREENSETUP_CROSSHAIR = MAKE_MENUOPTION(&MF_Redfont, &MEOS_OffOn, &cl_crosshair.Value);
|
|
static MenuEntry_t ME_SCREENSETUP_CROSSHAIR = MAKE_MENUENTRY( "Crosshair:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SCREENSETUP_CROSSHAIR, Option );
|
|
static MenuRangeInt32_t MEO_SCREENSETUP_CROSSHAIRSIZE = MAKE_MENURANGE( &cl_crosshairscale.Value, &MF_Redfont, 25, 100, 0, 16, 2 );
|
|
static MenuEntry_t ME_SCREENSETUP_CROSSHAIRSIZE = MAKE_MENUENTRY( s_Scale, &MF_Redfont, &MEF_BigOptions_Apply, &MEO_SCREENSETUP_CROSSHAIRSIZE, RangeInt32 );
|
|
|
|
static int32_t vpsize;
|
|
static MenuRangeInt32_t MEO_SCREENSETUP_SCREENSIZE = MAKE_MENURANGE( &vpsize, &MF_Redfont, 0, 0, 0, 1, EnforceIntervals );
|
|
static MenuEntry_t ME_SCREENSETUP_SCREENSIZE = MAKE_MENUENTRY( "Status bar:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SCREENSETUP_SCREENSIZE, RangeInt32 );
|
|
static MenuRangeInt32_t MEO_SCREENSETUP_TEXTSIZE = MAKE_MENURANGE( &hud_textscale.Value, &MF_Redfont, 100, 400, 0, 16, 2 );
|
|
static MenuEntry_t ME_SCREENSETUP_TEXTSIZE = MAKE_MENUENTRY( s_Scale, &MF_Redfont, &MEF_BigOptions_Apply, &MEO_SCREENSETUP_TEXTSIZE, RangeInt32 );
|
|
static MenuOption_t MEO_SCREENSETUP_LEVELSTATS = MAKE_MENUOPTION(&MF_Redfont, &MEOS_OffOn, &hud_stats.Value);
|
|
static MenuEntry_t ME_SCREENSETUP_LEVELSTATS = MAKE_MENUENTRY( "Level stats:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SCREENSETUP_LEVELSTATS, Option );
|
|
|
|
|
|
static MenuOption_t MEO_SCREENSETUP_SHOWPICKUPMESSAGES = MAKE_MENUOPTION(&MF_Redfont, &MEOS_OffOn, &ud.fta_on);
|
|
static MenuEntry_t ME_SCREENSETUP_SHOWPICKUPMESSAGES = MAKE_MENUENTRY( "Game messages:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SCREENSETUP_SHOWPICKUPMESSAGES, Option );
|
|
|
|
|
|
|
|
#ifdef EDUKE32_ANDROID_MENU
|
|
static char const *MEOSN_SCREENSETUP_STATUSBARONTOP[] = { "Bottom", "Top" };
|
|
static int32_t MEOSV_SCREENSETUP_STATUSBARONTOP[] = { 0, 1 };
|
|
static MenuOptionSet_t MEOS_SCREENSETUP_STATUSBARONTOP = MAKE_MENUOPTIONSET( MEOSN_SCREENSETUP_STATUSBARONTOP, MEOSV_SCREENSETUP_STATUSBARONTOP, 0x2 );
|
|
static MenuOption_t MEO_SCREENSETUP_STATUSBARONTOP = MAKE_MENUOPTION(&MF_Redfont, &MEOS_SCREENSETUP_STATUSBARONTOP, &hud_position.Value);
|
|
static MenuEntry_t ME_SCREENSETUP_STATUSBARONTOP = MAKE_MENUENTRY( "Status bar:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SCREENSETUP_STATUSBARONTOP, Option );
|
|
#endif
|
|
|
|
static MenuRangeInt32_t MEO_SCREENSETUP_SBARSIZE = MAKE_MENURANGE( &ud.statusbarscale, &MF_Redfont, 36, 100, 0, 17, 2 );
|
|
static MenuEntry_t ME_SCREENSETUP_SBARSIZE = MAKE_MENUENTRY( s_Scale, &MF_Redfont, &MEF_BigOptions_Apply, &MEO_SCREENSETUP_SBARSIZE, RangeInt32 );
|
|
|
|
|
|
static MenuLink_t MEO_DISPLAYSETUP_SCREENSETUP = { MENU_SCREENSETUP, MA_Advance, };
|
|
static MenuEntry_t ME_DISPLAYSETUP_SCREENSETUP = MAKE_MENUENTRY( "HUD setup", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_SCREENSETUP, Link );
|
|
|
|
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
#ifdef USE_OPENGL
|
|
static MenuLink_t MEO_DISPLAYSETUP_ADVANCED_GL_POLYMOST = { MENU_POLYMOST, MA_Advance, };
|
|
static MenuEntry_t ME_DISPLAYSETUP_ADVANCED_GL_POLYMOST = MAKE_MENUENTRY( "Polymost setup", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_ADVANCED_GL_POLYMOST, Link );
|
|
|
|
#ifdef POLYMER
|
|
static MenuLink_t MEO_DISPLAYSETUP_ADVANCED_GL_POLYMER = { MENU_POLYMER, MA_Advance, };
|
|
static MenuEntry_t ME_DISPLAYSETUP_ADVANCED_GL_POLYMER = MAKE_MENUENTRY("Polymer setup", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_ADVANCED_GL_POLYMER, Link);
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef EDUKE32_ANDROID_MENU
|
|
static MenuLink_t MEO_DISPLAYSETUP_VIDEOSETUP = { MENU_VIDEOSETUP, MA_Advance, };
|
|
static MenuEntry_t ME_DISPLAYSETUP_VIDEOSETUP = MAKE_MENUENTRY( "Video mode", &MF_Redfont, &MEF_BigOptionsRt, &MEO_DISPLAYSETUP_VIDEOSETUP, Link );
|
|
#endif
|
|
|
|
|
|
static MenuLink_t MEO_ENTERCHEAT = { MENU_CHEATENTRY, MA_None, };
|
|
static MenuEntry_t ME_ENTERCHEAT = MAKE_MENUENTRY( "Enter Cheat Code", &MF_Redfont, &MEF_BigCheats, &MEO_ENTERCHEAT, Link );
|
|
|
|
static MenuLink_t MEO_CHEAT_WARP = { MENU_CHEAT_WARP, MA_None, };
|
|
static MenuLink_t MEO_CHEAT_SKILL = { MENU_CHEAT_SKILL, MA_None, };
|
|
// KEEPINSYNC game.h: enum CheatCodeFunctions
|
|
// KEEPINSYNC game.c: uint8_t CheatFunctionIDs[]
|
|
#define MAKE_MENUCHEAT( Name ) MAKE_MENUENTRY( Name, &MF_Bluefont, &MEF_Cheats, &MEO_NULL, Link )
|
|
static MenuEntry_t ME_CheatCodes[] = {
|
|
MAKE_MENUCHEAT( "Toggle Cashman" ),
|
|
MAKE_MENUCHEAT( "Toggle God Mode" ),
|
|
MAKE_MENUCHEAT( "Give Everything" ),
|
|
MAKE_MENUCHEAT( "Give Weapons" ),
|
|
MAKE_MENUCHEAT( "Give All Items" ),
|
|
MAKE_MENUCHEAT( "Give Inventory" ),
|
|
MAKE_MENUCHEAT( "Give Keys" ),
|
|
MAKE_MENUCHEAT( "Toggle Hyper" ),
|
|
MAKE_MENUCHEAT( "Toggle 3rd-Person View" ),
|
|
MAKE_MENUCHEAT( "Toggle Show All Map" ),
|
|
MAKE_MENUCHEAT( "Toggle All Locks" ),
|
|
MAKE_MENUCHEAT( "Toggle Clipping" ),
|
|
MAKE_MENUENTRY( "Level Warp", &MF_Bluefont, &MEF_Cheats, &MEO_CHEAT_WARP, Link ),
|
|
MAKE_MENUENTRY( "Change Skill", &MF_Bluefont, &MEF_Cheats, &MEO_CHEAT_SKILL, Link ),
|
|
MAKE_MENUCHEAT( "Toggle Monsters" ),
|
|
MAKE_MENUCHEAT( "Toggle Framerate Display" ),
|
|
MAKE_MENUCHEAT( NULL ),
|
|
MAKE_MENUCHEAT( NULL ),
|
|
MAKE_MENUCHEAT( NULL ),
|
|
MAKE_MENUCHEAT( "Toggle Coordinate Display" ),
|
|
MAKE_MENUCHEAT( "Toggle Debug Data Dump" ),
|
|
};
|
|
|
|
static MenuEntry_t *MEL_OPTIONS[] = {
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
&ME_OPTIONS_GAMESETUP,
|
|
#endif
|
|
&ME_OPTIONS_DISPLAYSETUP,
|
|
&ME_OPTIONS_SOUNDSETUP,
|
|
#ifndef EDUKE32_ANDROID_MENU
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
&ME_OPTIONS_PLAYERSETUP,
|
|
#endif
|
|
&ME_OPTIONS_CONTROLS,
|
|
#else
|
|
&ME_OPTIONS_TOUCHSETUP,
|
|
#endif
|
|
#ifdef EDUKE32_SIMPLE_MENU
|
|
&ME_GAMESETUP_SAVESETUP,
|
|
&ME_OPTIONS_CHEATS
|
|
#endif
|
|
};
|
|
|
|
static MenuEntry_t *MEL_CONTROLS[] = {
|
|
#ifndef EDUKE32_ANDROID_MENU
|
|
&ME_OPTIONS_KEYBOARDSETUP,
|
|
&ME_OPTIONS_MOUSESETUP,
|
|
&ME_OPTIONS_JOYSTICKSETUP,
|
|
#else
|
|
&ME_OPTIONS_TOUCHSETUP
|
|
#endif
|
|
};
|
|
|
|
static MenuEntry_t *MEL_CHEATS[ARRAY_SIZE(ME_CheatCodes)+1] = {
|
|
&ME_ENTERCHEAT,
|
|
};
|
|
|
|
static MenuEntry_t *MEL_VIDEOSETUP[] = {
|
|
&ME_VIDEOSETUP_RESOLUTION,
|
|
#ifdef USE_OPENGL
|
|
&ME_VIDEOSETUP_RENDERER,
|
|
#endif
|
|
&ME_VIDEOSETUP_FULLSCREEN,
|
|
&ME_VIDEOSETUP_VSYNC,
|
|
&ME_Space6_Redfont,
|
|
&ME_VIDEOSETUP_APPLY,
|
|
};
|
|
static MenuEntry_t *MEL_DISPLAYSETUP[] = {
|
|
&ME_DISPLAYSETUP_SCREENSETUP,
|
|
&ME_DISPLAYSETUP_COLORCORR,
|
|
#ifndef EDUKE32_ANDROID_MENU
|
|
&ME_DISPLAYSETUP_VIDEOSETUP,
|
|
&ME_DISPLAYSETUP_ASPECTRATIO,
|
|
&ME_DISPLAYSETUP_FOV,
|
|
#endif
|
|
&ME_DISPLAYSETUP_UPSCALING,
|
|
};
|
|
|
|
#ifdef USE_OPENGL
|
|
static MenuEntry_t *MEL_DISPLAYSETUP_GL[] = {
|
|
&ME_DISPLAYSETUP_SCREENSETUP,
|
|
&ME_DISPLAYSETUP_COLORCORR,
|
|
#ifndef EDUKE32_ANDROID_MENU
|
|
&ME_DISPLAYSETUP_VIDEOSETUP,
|
|
&ME_DISPLAYSETUP_ASPECTRATIO,
|
|
&ME_DISPLAYSETUP_FOV,
|
|
#endif
|
|
&ME_DISPLAYSETUP_TEXFILTER,
|
|
#ifdef EDUKE32_ANDROID_MENU
|
|
&ME_DISPLAYSETUP_HIDEDPAD,
|
|
&ME_DISPLAYSETUP_TOUCHALPHA,
|
|
#else
|
|
&ME_DISPLAYSETUP_ANISOTROPY,
|
|
# ifdef EDUKE32_SIMPLE_MENU
|
|
&ME_DISPLAYSETUP_PALETTEEMULATION,
|
|
# else
|
|
&ME_DISPLAYSETUP_ADVANCED_GL_POLYMOST,
|
|
# endif
|
|
#endif
|
|
};
|
|
|
|
#ifdef POLYMER
|
|
static MenuEntry_t *MEL_DISPLAYSETUP_GL_POLYMER[] = {
|
|
&ME_DISPLAYSETUP_SCREENSETUP,
|
|
&ME_DISPLAYSETUP_COLORCORR,
|
|
#ifndef EDUKE32_ANDROID_MENU
|
|
&ME_DISPLAYSETUP_VIDEOSETUP,
|
|
&ME_DISPLAYSETUP_FOV,
|
|
#endif
|
|
&ME_DISPLAYSETUP_TEXFILTER,
|
|
&ME_DISPLAYSETUP_ANISOTROPY,
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
&ME_DISPLAYSETUP_ADVANCED_GL_POLYMER,
|
|
#endif
|
|
};
|
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
static char const *MenuKeyNone = " -";
|
|
static char const *MEOSN_Keys[NUMKEYS];
|
|
|
|
static MenuCustom2Col_t MEO_KEYBOARDSETUPFUNCS_TEMPLATE = { { NULL, NULL, }, MEOSN_Keys, &MF_Minifont, NUMKEYS, 54<<16, 0 };
|
|
static MenuCustom2Col_t MEO_KEYBOARDSETUPFUNCS[NUMGAMEFUNCTIONS];
|
|
static MenuEntry_t ME_KEYBOARDSETUPFUNCS_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Minifont, &MEF_KBFuncList, &MEO_KEYBOARDSETUPFUNCS_TEMPLATE, Custom2Col );
|
|
static MenuEntry_t ME_KEYBOARDSETUPFUNCS[NUMGAMEFUNCTIONS];
|
|
static MenuEntry_t *MEL_KEYBOARDSETUPFUNCS[NUMGAMEFUNCTIONS];
|
|
|
|
static MenuLink_t MEO_KEYBOARDSETUP_KEYS = { MENU_KEYBOARDKEYS, MA_Advance, };
|
|
static MenuEntry_t ME_KEYBOARDSETUP_KEYS = MAKE_MENUENTRY( "Configure Keys", &MF_Redfont, &MEF_CenterMenu, &MEO_KEYBOARDSETUP_KEYS, Link );
|
|
static MenuEntry_t ME_KEYBOARDSETUP_RESET = MAKE_MENUENTRY( "Reset To Defaults", &MF_Redfont, &MEF_CenterMenu, &MEO_NULL, Link );
|
|
static MenuEntry_t ME_KEYBOARDSETUP_RESETCLASSIC = MAKE_MENUENTRY( "Reset To Classic", &MF_Redfont, &MEF_CenterMenu, &MEO_NULL, Link );
|
|
|
|
static MenuEntry_t *MEL_KEYBOARDSETUP[] = {
|
|
&ME_KEYBOARDSETUP_KEYS,
|
|
&ME_KEYBOARDSETUP_RESET,
|
|
&ME_KEYBOARDSETUP_RESETCLASSIC,
|
|
};
|
|
|
|
|
|
// There is no better way to do this than manually.
|
|
|
|
#define MENUMOUSEFUNCTIONS 12
|
|
|
|
static char const *MenuMouseNames[MENUMOUSEFUNCTIONS] = {
|
|
"Button 1",
|
|
"Double Button 1",
|
|
"Button 2",
|
|
"Double Button 2",
|
|
"Button 3",
|
|
"Double Button 3",
|
|
|
|
"Wheel Up",
|
|
"Wheel Down",
|
|
|
|
"Button 4",
|
|
"Double Button 4",
|
|
"Button 5",
|
|
"Double Button 5",
|
|
};
|
|
static int32_t MenuMouseDataIndex[MENUMOUSEFUNCTIONS][2] = {
|
|
{ 0, 0, },
|
|
{ 0, 1, },
|
|
{ 1, 0, },
|
|
{ 1, 1, },
|
|
{ 2, 0, },
|
|
{ 2, 1, },
|
|
|
|
// note the mouse wheel
|
|
{ 4, 0, },
|
|
{ 5, 0, },
|
|
|
|
{ 3, 0, },
|
|
{ 3, 1, },
|
|
{ 6, 0, },
|
|
{ 6, 1, },
|
|
};
|
|
|
|
static MenuOption_t MEO_MOUSEJOYSETUPBTNS_TEMPLATE = MAKE_MENUOPTION( &MF_Minifont, &MEOS_Gamefuncs, NULL );
|
|
static MenuOption_t MEO_MOUSESETUPBTNS[MENUMOUSEFUNCTIONS];
|
|
static MenuEntry_t ME_MOUSEJOYSETUPBTNS_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Minifont, &MEF_FuncList, NULL, Option );
|
|
static MenuEntry_t ME_MOUSESETUPBTNS[MENUMOUSEFUNCTIONS];
|
|
static MenuEntry_t *MEL_MOUSESETUPBTNS[MENUMOUSEFUNCTIONS];
|
|
|
|
static MenuLink_t MEO_MOUSESETUP_BTNS = { MENU_MOUSEBTNS, MA_Advance, };
|
|
static MenuEntry_t ME_MOUSESETUP_BTNS = MAKE_MENUENTRY( "Button assignment", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSESETUP_BTNS, Link );
|
|
static MenuRangeFloat_t MEO_MOUSESETUP_SENSITIVITY = MAKE_MENURANGE( &CONTROL_MouseSensitivity, &MF_Redfont, .5f, 16.f, 0.f, 32, 1 );
|
|
static MenuEntry_t ME_MOUSESETUP_SENSITIVITY = MAKE_MENUENTRY( "Sensitivity:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSESETUP_SENSITIVITY, RangeFloat );
|
|
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
static char const *MEOSN_MOUSESETUP_AIM_TYPE [] = { "Toggle", "Hold" };
|
|
static MenuOptionSet_t MEOS_MOUSESETUP_AIM_TYPE = MAKE_MENUOPTIONSET(MEOSN_MOUSESETUP_AIM_TYPE, NULL, 0x2);
|
|
static MenuOption_t MEO_MOUSESETUP_MOUSEAIMINGTYPE = MAKE_MENUOPTION(&MF_Redfont, &MEOS_MOUSESETUP_AIM_TYPE, &in_aimmode.Value);
|
|
static MenuEntry_t ME_MOUSESETUP_MOUSEAIMINGTYPE = MAKE_MENUENTRY("Aiming type:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSESETUP_MOUSEAIMINGTYPE, Option);
|
|
static MenuOption_t MEO_MOUSESETUP_MOUSEAIMING = MAKE_MENUOPTION( &MF_Redfont, &MEOS_NoYes, &in_mousemode.Value );
|
|
static MenuEntry_t ME_MOUSESETUP_MOUSEAIMING = MAKE_MENUENTRY( "Vertical aiming:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSESETUP_MOUSEAIMING, Option );
|
|
#endif
|
|
static MenuOption_t MEO_MOUSESETUP_INVERT = MAKE_MENUOPTION( &MF_Redfont, &MEOS_YesNo, &in_mouseflip.Value );
|
|
static MenuEntry_t ME_MOUSESETUP_INVERT = MAKE_MENUENTRY( "Invert aiming:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSESETUP_INVERT, Option );
|
|
static MenuOption_t MEO_MOUSESETUP_SMOOTH = MAKE_MENUOPTION( &MF_Redfont, &MEOS_NoYes, &in_mousesmoothing.Value );
|
|
static MenuEntry_t ME_MOUSESETUP_SMOOTH = MAKE_MENUENTRY( "Filter input:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSESETUP_SMOOTH, Option );
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
static MenuLink_t MEO_MOUSESETUP_ADVANCED = { MENU_MOUSEADVANCED, MA_Advance, };
|
|
static MenuEntry_t ME_MOUSESETUP_ADVANCED = MAKE_MENUENTRY( "Advanced setup", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSESETUP_ADVANCED, Link );
|
|
#endif
|
|
static MenuRangeInt32_t MEO_MOUSEADVANCED_SCALEX = MAKE_MENURANGE(&MouseAnalogueScale[0], &MF_Redfont, -262144, 262144, 65536, 161, 3);
|
|
static MenuEntry_t ME_MOUSEADVANCED_SCALEX = MAKE_MENUENTRY("X-Scale:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSEADVANCED_SCALEX, RangeInt32);
|
|
static MenuRangeInt32_t MEO_MOUSEADVANCED_SCALEY = MAKE_MENURANGE(&MouseAnalogueScale[1], &MF_Redfont, -262144, 262144, 65536, 161, 3);
|
|
static MenuEntry_t ME_MOUSEADVANCED_SCALEY = MAKE_MENUENTRY("Y-Scale:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_MOUSEADVANCED_SCALEY, RangeInt32);
|
|
|
|
static MenuEntry_t *MEL_MOUSESETUP[] = {
|
|
&ME_MOUSESETUP_BTNS,
|
|
&ME_MOUSESETUP_SENSITIVITY,
|
|
#ifdef EDUKE32_SIMPLE_MENU
|
|
&ME_MOUSEADVANCED_SCALEX,
|
|
&ME_MOUSEADVANCED_SCALEY,
|
|
#endif
|
|
&ME_Space2_Redfont,
|
|
#ifdef EDUKE32_SIMPLE_MENU
|
|
&ME_GAMESETUP_AIM_AUTO,
|
|
#endif
|
|
&ME_MOUSESETUP_INVERT,
|
|
&ME_MOUSESETUP_SMOOTH,
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
&ME_MOUSESETUP_MOUSEAIMINGTYPE,
|
|
&ME_MOUSESETUP_MOUSEAIMING,
|
|
&ME_MOUSESETUP_ADVANCED,
|
|
#endif
|
|
};
|
|
|
|
#ifdef EDUKE32_ANDROID_MENU
|
|
static MenuRangeFloat_t MEO_TOUCHSETUP_SENSITIVITY_MOVE = MAKE_MENURANGE(&droidinput.forward_sens, &MF_Redfont, 1.f, 9.f, 0.f, 17, 1 + EnforceIntervals);
|
|
static MenuEntry_t ME_TOUCHSETUP_SENSITIVITY_MOVE = MAKE_MENUENTRY("Running:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_TOUCHSETUP_SENSITIVITY_MOVE, RangeFloat);
|
|
|
|
static MenuRangeFloat_t MEO_TOUCHSETUP_SENSITIVITY_STRAFE = MAKE_MENURANGE(&droidinput.strafe_sens, &MF_Redfont, 1.f, 9.f, 0.f, 17, 1 + EnforceIntervals);
|
|
static MenuEntry_t ME_TOUCHSETUP_SENSITIVITY_STRAFE = MAKE_MENUENTRY("Strafing:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_TOUCHSETUP_SENSITIVITY_STRAFE, RangeFloat);
|
|
|
|
static MenuRangeFloat_t MEO_TOUCHSETUP_SENSITIVITY_LOOK = MAKE_MENURANGE(&droidinput.pitch_sens, &MF_Redfont, 1.f, 9.f, 0.f, 17, 1 + EnforceIntervals);
|
|
static MenuEntry_t ME_TOUCHSETUP_SENSITIVITY_LOOK = MAKE_MENUENTRY("Looking:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_TOUCHSETUP_SENSITIVITY_LOOK, RangeFloat);
|
|
|
|
static MenuRangeFloat_t MEO_TOUCHSETUP_SENSITIVITY_TURN = MAKE_MENURANGE(&droidinput.yaw_sens, &MF_Redfont, 1.f, 9.f, 0.f, 17, 1 + EnforceIntervals);
|
|
static MenuEntry_t ME_TOUCHSETUP_SENSITIVITY_TURN = MAKE_MENUENTRY("Turning:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_TOUCHSETUP_SENSITIVITY_TURN, RangeFloat);
|
|
|
|
static MenuOption_t MEO_TOUCHSETUP_INVERT = MAKE_MENUOPTION(&MF_Redfont, &MEOS_NoYes, &droidinput.invertLook);
|
|
static MenuEntry_t ME_TOUCHSETUP_INVERT = MAKE_MENUENTRY("Invert look:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_TOUCHSETUP_INVERT, Option);
|
|
|
|
MAKE_MENU_TOP_ENTRYLINK("Sensitivity", MEF_CenterMenu, TOUCHSENS, MENU_TOUCHSENS);
|
|
MAKE_MENU_TOP_ENTRYLINK("Button Setup", MEF_CenterMenu, TOUCHBUTTONS, MENU_TOUCHBUTTONS);
|
|
|
|
static MenuEntry_t *MEL_TOUCHSETUP [] = {
|
|
&ME_TOUCHSENS,
|
|
&ME_TOUCHBUTTONS,
|
|
};
|
|
|
|
static MenuEntry_t *MEL_TOUCHSENS [] = {
|
|
&ME_TOUCHSETUP_SENSITIVITY_MOVE,
|
|
&ME_TOUCHSETUP_SENSITIVITY_STRAFE,
|
|
&ME_TOUCHSETUP_SENSITIVITY_LOOK,
|
|
&ME_TOUCHSETUP_SENSITIVITY_TURN,
|
|
&ME_Space2_Redfont,
|
|
&ME_TOUCHSETUP_INVERT,
|
|
};
|
|
#endif
|
|
|
|
MAKE_MENU_TOP_ENTRYLINK( "Edit Buttons", MEF_CenterMenu, JOYSTICK_EDITBUTTONS, MENU_JOYSTICKBTNS );
|
|
MAKE_MENU_TOP_ENTRYLINK( "Edit Axes", MEF_CenterMenu, JOYSTICK_EDITAXES, MENU_JOYSTICKAXES );
|
|
|
|
static MenuEntry_t *MEL_JOYSTICKSETUP[] = {
|
|
&ME_JOYSTICK_EDITBUTTONS,
|
|
&ME_JOYSTICK_EDITAXES,
|
|
};
|
|
|
|
#define MAXJOYBUTTONSTRINGLENGTH 32
|
|
|
|
static char MenuJoystickNames[MAXJOYBUTTONSANDHATS*2][MAXJOYBUTTONSTRINGLENGTH];
|
|
|
|
static MenuOption_t MEO_JOYSTICKBTNS[MAXJOYBUTTONSANDHATS*2];
|
|
static MenuEntry_t ME_JOYSTICKBTNS[MAXJOYBUTTONSANDHATS*2];
|
|
static MenuEntry_t *MEL_JOYSTICKBTNS[MAXJOYBUTTONSANDHATS*2];
|
|
|
|
static MenuLink_t MEO_JOYSTICKAXES = { MENU_JOYSTICKAXIS, MA_Advance, };
|
|
static MenuEntry_t ME_JOYSTICKAXES_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_BigSliders, &MEO_JOYSTICKAXES, Link );
|
|
static MenuEntry_t ME_JOYSTICKAXES[MAXJOYAXES];
|
|
static char MenuJoystickAxes[MAXJOYAXES][MAXJOYBUTTONSTRINGLENGTH];
|
|
|
|
static MenuEntry_t *MEL_JOYSTICKAXES[MAXJOYAXES];
|
|
|
|
static MenuOption_t MEO_MOUSEADVANCED_DAXES_UP = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_Gamefuncs, &MouseDigitalFunctions[1][0] );
|
|
static MenuEntry_t ME_MOUSEADVANCED_DAXES_UP = MAKE_MENUENTRY( "Digital Up", &MF_Redfont, &MEF_BigSliders, &MEO_MOUSEADVANCED_DAXES_UP, Option );
|
|
static MenuOption_t MEO_MOUSEADVANCED_DAXES_DOWN = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_Gamefuncs, &MouseDigitalFunctions[1][1] );
|
|
static MenuEntry_t ME_MOUSEADVANCED_DAXES_DOWN = MAKE_MENUENTRY( "Digital Down", &MF_Redfont, &MEF_BigSliders, &MEO_MOUSEADVANCED_DAXES_DOWN, Option );
|
|
static MenuOption_t MEO_MOUSEADVANCED_DAXES_LEFT = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_Gamefuncs, &MouseDigitalFunctions[0][0] );
|
|
static MenuEntry_t ME_MOUSEADVANCED_DAXES_LEFT = MAKE_MENUENTRY( "Digital Left", &MF_Redfont, &MEF_BigSliders, &MEO_MOUSEADVANCED_DAXES_LEFT, Option );
|
|
static MenuOption_t MEO_MOUSEADVANCED_DAXES_RIGHT = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_Gamefuncs, &MouseDigitalFunctions[0][1] );
|
|
static MenuEntry_t ME_MOUSEADVANCED_DAXES_RIGHT = MAKE_MENUENTRY( "Digital Right", &MF_Redfont, &MEF_BigSliders, &MEO_MOUSEADVANCED_DAXES_RIGHT, Option );
|
|
|
|
static MenuEntry_t *MEL_MOUSEADVANCED[] = {
|
|
&ME_MOUSEADVANCED_SCALEX,
|
|
&ME_MOUSEADVANCED_SCALEY,
|
|
&ME_Space8_Redfont,
|
|
&ME_MOUSEADVANCED_DAXES_UP,
|
|
&ME_MOUSEADVANCED_DAXES_DOWN,
|
|
&ME_MOUSEADVANCED_DAXES_LEFT,
|
|
&ME_MOUSEADVANCED_DAXES_RIGHT,
|
|
};
|
|
|
|
static MenuEntry_t *MEL_INTERNAL_MOUSEADVANCED_DAXES[] = {
|
|
&ME_MOUSEADVANCED_DAXES_UP,
|
|
&ME_MOUSEADVANCED_DAXES_DOWN,
|
|
&ME_MOUSEADVANCED_DAXES_LEFT,
|
|
&ME_MOUSEADVANCED_DAXES_RIGHT,
|
|
};
|
|
|
|
static const char *MenuJoystickHatDirections[] = { "Up", "Right", "Down", "Left", };
|
|
|
|
static char const *MEOSN_JOYSTICKAXIS_ANALOG[] = { " -None-", "Turning", "Strafing", "Looking", "Moving", };
|
|
static int32_t MEOSV_JOYSTICKAXIS_ANALOG[] = { -1, analog_turning, analog_strafing, analog_lookingupanddown, analog_moving, };
|
|
static MenuOptionSet_t MEOS_JOYSTICKAXIS_ANALOG = MAKE_MENUOPTIONSET( MEOSN_JOYSTICKAXIS_ANALOG, MEOSV_JOYSTICKAXIS_ANALOG, 0x0 );
|
|
static MenuOption_t MEO_JOYSTICKAXIS_ANALOG = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_JOYSTICKAXIS_ANALOG, NULL );
|
|
static MenuEntry_t ME_JOYSTICKAXIS_ANALOG = MAKE_MENUENTRY( "Analog", &MF_Redfont, &MEF_BigSliders, &MEO_JOYSTICKAXIS_ANALOG, Option );
|
|
static MenuRangeInt32_t MEO_JOYSTICKAXIS_SCALE = MAKE_MENURANGE( NULL, &MF_Bluefont, -262144, 262144, 65536, 65, 3 );
|
|
static MenuEntry_t ME_JOYSTICKAXIS_SCALE = MAKE_MENUENTRY( "Scale", &MF_Redfont, &MEF_BigSliders, &MEO_JOYSTICKAXIS_SCALE, RangeInt32 );
|
|
static MenuRangeInt32_t MEO_JOYSTICKAXIS_DEAD = MAKE_MENURANGE( NULL, &MF_Bluefont, 0, 1000000, 0, 33, 2 );
|
|
static MenuEntry_t ME_JOYSTICKAXIS_DEAD = MAKE_MENUENTRY( "Dead Zone", &MF_Redfont, &MEF_BigSliders, &MEO_JOYSTICKAXIS_DEAD, RangeInt32 );
|
|
static MenuRangeInt32_t MEO_JOYSTICKAXIS_SATU = MAKE_MENURANGE( NULL, &MF_Bluefont, 0, 1000000, 0, 33, 2 );
|
|
static MenuEntry_t ME_JOYSTICKAXIS_SATU = MAKE_MENUENTRY( "Saturation", &MF_Redfont, &MEF_BigSliders, &MEO_JOYSTICKAXIS_SATU, RangeInt32 );
|
|
|
|
static MenuOption_t MEO_JOYSTICKAXIS_DIGITALNEGATIVE = MAKE_MENUOPTION( &MF_Minifont, &MEOS_Gamefuncs, NULL );
|
|
static MenuEntry_t ME_JOYSTICKAXIS_DIGITALNEGATIVE = MAKE_MENUENTRY( "Digital -", &MF_Bluefont, &MEF_BigSliders, &MEO_JOYSTICKAXIS_DIGITALNEGATIVE, Option );
|
|
static MenuOption_t MEO_JOYSTICKAXIS_DIGITALPOSITIVE = MAKE_MENUOPTION( &MF_Minifont, &MEOS_Gamefuncs, NULL );
|
|
static MenuEntry_t ME_JOYSTICKAXIS_DIGITALPOSITIVE = MAKE_MENUENTRY( "Digital +", &MF_Bluefont, &MEF_BigSliders, &MEO_JOYSTICKAXIS_DIGITALPOSITIVE, Option );
|
|
|
|
static MenuEntry_t *MEL_JOYSTICKAXIS[] = {
|
|
&ME_JOYSTICKAXIS_ANALOG,
|
|
&ME_JOYSTICKAXIS_SCALE,
|
|
&ME_JOYSTICKAXIS_DEAD,
|
|
&ME_JOYSTICKAXIS_SATU,
|
|
&ME_Space8_Redfont,
|
|
&ME_JOYSTICKAXIS_DIGITALNEGATIVE,
|
|
&ME_JOYSTICKAXIS_DIGITALPOSITIVE,
|
|
};
|
|
|
|
static MenuEntry_t *MEL_INTERNAL_JOYSTICKAXIS_DIGITAL[] = {
|
|
&ME_JOYSTICKAXIS_DIGITALNEGATIVE,
|
|
&ME_JOYSTICKAXIS_DIGITALPOSITIVE,
|
|
};
|
|
|
|
#ifdef USE_OPENGL
|
|
static MenuOption_t MEO_RENDERERSETUP_HIGHTILE = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_NoYes, &hw_hightile.Value );
|
|
static MenuEntry_t ME_RENDERERSETUP_HIGHTILE = MAKE_MENUENTRY( "True color textures:", &MF_Bluefont, &MEF_SmallOptions, &MEO_RENDERERSETUP_HIGHTILE, Option );
|
|
|
|
static char const *MEOSN_RENDERERSETUP_TEXQUALITY [] = { "Full", "Half", "Barf", };
|
|
static MenuOptionSet_t MEOS_RENDERERSETUP_TEXQUALITY = MAKE_MENUOPTIONSET(MEOSN_RENDERERSETUP_TEXQUALITY, NULL, 0x2);
|
|
static MenuOption_t MEO_RENDERERSETUP_TEXQUALITY = MAKE_MENUOPTION(&MF_Bluefont, &MEOS_RENDERERSETUP_TEXQUALITY, &r_downsize);
|
|
static MenuEntry_t ME_RENDERERSETUP_TEXQUALITY = MAKE_MENUENTRY("GL texture quality:", &MF_Bluefont, &MEF_SmallOptions, &MEO_RENDERERSETUP_TEXQUALITY, Option);
|
|
|
|
|
|
static MenuOption_t MEO_RENDERERSETUP_PRECACHE = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_OffOn, &r_precache.Value );
|
|
static MenuEntry_t ME_RENDERERSETUP_PRECACHE = MAKE_MENUENTRY( "Pre-load map textures:", &MF_Bluefont, &MEF_SmallOptions, &MEO_RENDERERSETUP_PRECACHE, Option );
|
|
# ifndef EDUKE32_GLES
|
|
static char const *MEOSN_RENDERERSETUP_TEXCACHE[] = { "Off", "On", "Compr.", };
|
|
static MenuOptionSet_t MEOS_RENDERERSETUP_TEXCACHE = MAKE_MENUOPTIONSET( MEOSN_RENDERERSETUP_TEXCACHE, NULL, 0x2 );
|
|
# endif
|
|
# ifdef USE_GLEXT
|
|
static MenuOption_t MEO_RENDERERSETUP_DETAILTEX = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_NoYes, &hw_detailmapping.Value);
|
|
static MenuEntry_t ME_RENDERERSETUP_DETAILTEX = MAKE_MENUENTRY( "Detail textures:", &MF_Bluefont, &MEF_SmallOptions, &MEO_RENDERERSETUP_DETAILTEX, Option );
|
|
static MenuOption_t MEO_RENDERERSETUP_GLOWTEX = MAKE_MENUOPTION(&MF_Bluefont, &MEOS_NoYes, &hw_glowmapping.Value);
|
|
static MenuEntry_t ME_RENDERERSETUP_GLOWTEX = MAKE_MENUENTRY("Glow textures:", &MF_Bluefont, &MEF_SmallOptions, &MEO_RENDERERSETUP_GLOWTEX, Option);
|
|
# endif
|
|
static MenuOption_t MEO_RENDERERSETUP_MODELS = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_NoYes, &hw_models.Value );
|
|
static MenuEntry_t ME_RENDERERSETUP_MODELS = MAKE_MENUENTRY( "3D models:", &MF_Bluefont, &MEF_SmallOptions, &MEO_RENDERERSETUP_MODELS, Option );
|
|
#endif
|
|
|
|
|
|
#ifdef USE_OPENGL
|
|
static MenuEntry_t *MEL_RENDERERSETUP_POLYMOST[] = {
|
|
&ME_RENDERERSETUP_HIGHTILE,
|
|
&ME_RENDERERSETUP_TEXQUALITY,
|
|
&ME_RENDERERSETUP_PRECACHE,
|
|
# ifdef USE_GLEXT
|
|
&ME_RENDERERSETUP_DETAILTEX,
|
|
&ME_RENDERERSETUP_GLOWTEX,
|
|
# endif
|
|
&ME_Space4_Bluefont,
|
|
&ME_RENDERERSETUP_MODELS,
|
|
};
|
|
|
|
#endif
|
|
|
|
#ifdef EDUKE32_ANDROID_MENU
|
|
static MenuRangeFloat_t MEO_COLCORR_GAMMA = MAKE_MENURANGE( &g_videoGamma, &MF_Bluefont, 1.f, 2.5f, 0.f, 39, 1 );
|
|
#else
|
|
static MenuRangeFloat_t MEO_COLCORR_GAMMA = MAKE_MENURANGE( &g_videoGamma, &MF_Bluefont, 0.3f, 4.f, 0.f, 38, 1 );
|
|
#endif
|
|
static MenuEntry_t ME_COLCORR_GAMMA = MAKE_MENUENTRY( "Gamma:", &MF_Redfont, &MEF_ColorCorrect, &MEO_COLCORR_GAMMA, RangeFloat );
|
|
static MenuRangeFloat_t MEO_COLCORR_CONTRAST = MAKE_MENURANGE( &g_videoContrast, &MF_Bluefont, 0.1f, 2.7f, 0.f, 53, 1 );
|
|
static MenuEntry_t ME_COLCORR_CONTRAST = MAKE_MENUENTRY( "Contrast:", &MF_Redfont, &MEF_ColorCorrect, &MEO_COLCORR_CONTRAST, RangeFloat );
|
|
static MenuRangeFloat_t MEO_COLCORR_BRIGHTNESS = MAKE_MENURANGE( &g_videoBrightness, &MF_Bluefont, -0.8f, 0.8f, 0.f, 33, 1 );
|
|
static MenuEntry_t ME_COLCORR_BRIGHTNESS = MAKE_MENUENTRY( "Brightness:", &MF_Redfont, &MEF_ColorCorrect, &MEO_COLCORR_BRIGHTNESS, RangeFloat );
|
|
static MenuEntry_t ME_COLCORR_RESET = MAKE_MENUENTRY( "Reset To Defaults", &MF_Redfont, &MEF_ColorCorrect, &MEO_NULL, Link );
|
|
#ifdef EDUKE32_ANDROID_MENU
|
|
#define MINVIS 1.f
|
|
#else
|
|
#define MINVIS 0.125f
|
|
#endif
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
static MenuRangeFloat_t MEO_COLCORR_AMBIENT = MAKE_MENURANGE( &r_ambientlight.Value, &MF_Bluefont, MINVIS, 4.f, 0.f, 32, 1 );
|
|
static MenuEntry_t ME_COLCORR_AMBIENT = MAKE_MENUENTRY( "Visibility:", &MF_Redfont, &MEF_ColorCorrect, &MEO_COLCORR_AMBIENT, RangeFloat );
|
|
#endif
|
|
static MenuEntry_t *MEL_COLCORR[] = {
|
|
&ME_COLCORR_GAMMA,
|
|
#ifndef EDUKE32_ANDROID_MENU
|
|
&ME_COLCORR_CONTRAST,
|
|
&ME_COLCORR_BRIGHTNESS,
|
|
#endif
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
&ME_COLCORR_AMBIENT,
|
|
#endif
|
|
&ME_Space8_Redfont,
|
|
&ME_COLCORR_RESET,
|
|
};
|
|
|
|
static MenuEntry_t *MEL_SCREENSETUP[] = {
|
|
#ifdef EDUKE32_ANDROID_MENU
|
|
&ME_SCREENSETUP_STATUSBARONTOP,
|
|
#endif
|
|
&ME_SCREENSETUP_SCREENSIZE,
|
|
&ME_SCREENSETUP_SBARSIZE,
|
|
|
|
&ME_SCREENSETUP_CROSSHAIR,
|
|
&ME_SCREENSETUP_CROSSHAIRSIZE,
|
|
|
|
&ME_SCREENSETUP_LEVELSTATS,
|
|
&ME_SCREENSETUP_TEXTSIZE,
|
|
|
|
&ME_SCREENSETUP_SHOWPICKUPMESSAGES,
|
|
};
|
|
|
|
// Save and load will be filled in before every viewing of the save/load screen.
|
|
static MenuLink_t MEO_LOAD = { MENU_LOADVERIFY, MA_None, };
|
|
static MenuEntry_t ME_LOAD_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Minifont, &MEF_LoadSave, &MEO_LOAD, Link );
|
|
static MenuEntry_t ME_LOAD_EMPTY = MAKE_MENUENTRY( NULL, &MF_Minifont, &MEF_LoadSave, nullptr, Dummy );
|
|
static MenuEntry_t *ME_LOAD;
|
|
static MenuEntry_t **MEL_LOAD;
|
|
|
|
static char const s_NewSaveGame[] = "(New Save Game)";
|
|
static MenuString_t MEO_SAVE_TEMPLATE = MAKE_MENUSTRING( NULL, &MF_Minifont, MAXSAVEGAMENAME, 0 );
|
|
static MenuString_t MEO_SAVE_NEW = MAKE_MENUSTRING( NULL, &MF_Minifont, MAXSAVEGAMENAME, 0 );
|
|
static MenuString_t *MEO_SAVE;
|
|
static MenuEntry_t ME_SAVE_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Minifont, &MEF_LoadSave, &MEO_SAVE_TEMPLATE, String );
|
|
static MenuEntry_t ME_SAVE_NEW = MAKE_MENUENTRY( s_NewSaveGame, &MF_Minifont, &MEF_LoadSave, &MEO_SAVE_NEW, String );
|
|
static MenuEntry_t *ME_SAVE;
|
|
static MenuEntry_t **MEL_SAVE;
|
|
|
|
static int32_t soundrate, soundvoices;
|
|
static MenuOption_t MEO_SOUND = MAKE_MENUOPTION( &MF_Redfont, &MEOS_OffOn, &snd_enabled.Value );
|
|
static MenuEntry_t ME_SOUND = MAKE_MENUENTRY( "Sound:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND, Option );
|
|
|
|
static MenuOption_t MEO_SOUND_MUSIC = MAKE_MENUOPTION( &MF_Redfont, &MEOS_OffOn, &mus_enabled.Value );
|
|
static MenuEntry_t ME_SOUND_MUSIC = MAKE_MENUENTRY( "Music:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_MUSIC, Option );
|
|
|
|
static MenuLink_t MEO_SOUND_CDPLAYER = { MENU_CDPLAYER, MA_Advance, };
|
|
static MenuEntry_t ME_SOUND_CDPLAYER = MAKE_MENUENTRY( "8 Track Player", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_CDPLAYER, Link );
|
|
|
|
static MenuRangeInt32_t MEO_SOUND_VOLUME_FX = MAKE_MENURANGE( &snd_fxvolume.Value, &MF_Redfont, 0, 255, 0, 33, 2 );
|
|
static MenuEntry_t ME_SOUND_VOLUME_FX = MAKE_MENUENTRY( "Volume:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_VOLUME_FX, RangeInt32 );
|
|
|
|
static MenuRangeInt32_t MEO_SOUND_VOLUME_MUSIC = MAKE_MENURANGE( &mus_volume.Value, &MF_Redfont, 0, 255, 0, 33, 2 );
|
|
static MenuEntry_t ME_SOUND_VOLUME_MUSIC = MAKE_MENUENTRY( "Music:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_VOLUME_MUSIC, RangeInt32 );
|
|
|
|
static MenuOption_t MEO_SOUND_DUKETALK = MAKE_MENUOPTION(&MF_Redfont, &MEOS_NoYes, NULL);
|
|
static MenuEntry_t ME_SOUND_DUKETALK = MAKE_MENUENTRY( "Duke talk:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_DUKETALK, Option );
|
|
|
|
static char const *MEOSN_SOUND_SAMPLINGRATE[] = { "22050Hz", "44100Hz", "48000Hz", };
|
|
static int32_t MEOSV_SOUND_SAMPLINGRATE[] = { 22050, 44100, 48000, };
|
|
static MenuOptionSet_t MEOS_SOUND_SAMPLINGRATE = MAKE_MENUOPTIONSET( MEOSN_SOUND_SAMPLINGRATE, MEOSV_SOUND_SAMPLINGRATE, 0x3 );
|
|
static MenuOption_t MEO_SOUND_SAMPLINGRATE = MAKE_MENUOPTION( &MF_Redfont, &MEOS_SOUND_SAMPLINGRATE, &soundrate );
|
|
static MenuEntry_t ME_SOUND_SAMPLINGRATE = MAKE_MENUENTRY( "Sample rate:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_SAMPLINGRATE, Option );
|
|
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
static MenuRangeInt32_t MEO_SOUND_NUMVOICES = MAKE_MENURANGE( &soundvoices, &MF_Redfont, 16, 256, 0, 16, 1 );
|
|
static MenuEntry_t ME_SOUND_NUMVOICES = MAKE_MENUENTRY( "Voices:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SOUND_NUMVOICES, RangeInt32 );
|
|
#endif
|
|
|
|
static MenuEntry_t ME_SOUND_RESTART = MAKE_MENUENTRY( "Apply Changes", &MF_Redfont, &MEF_BigOptions_Apply, &MEO_NULL, Link );
|
|
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
static MenuLink_t MEO_ADVSOUND = { MENU_ADVSOUND, MA_Advance, };
|
|
static MenuEntry_t ME_SOUND_ADVSOUND = MAKE_MENUENTRY( "Advanced", &MF_Redfont, &MEF_BigOptionsRt, &MEO_ADVSOUND, Link );
|
|
#endif
|
|
|
|
static MenuEntry_t *MEL_SOUND[] = {
|
|
&ME_SOUND,
|
|
&ME_SOUND_MUSIC,
|
|
&ME_SOUND_VOLUME_FX,
|
|
&ME_SOUND_VOLUME_MUSIC,
|
|
&ME_SOUND_DUKETALK,
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
&ME_SOUND_ADVSOUND,
|
|
#endif
|
|
};
|
|
|
|
static MenuEntry_t *MEL_ADVSOUND[] = {
|
|
&ME_SOUND_SAMPLINGRATE,
|
|
&ME_Space2_Redfont,
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
&ME_SOUND_NUMVOICES,
|
|
&ME_Space2_Redfont,
|
|
#endif
|
|
&ME_SOUND_RESTART,
|
|
};
|
|
|
|
static MenuEntry_t ME_CDPLAYER_TRACK = MAKE_MENUENTRY( NULL, &MF_Redfont, &MEF_Null, &MEO_NULL, Dummy);
|
|
|
|
static MenuEntry_t *MEL_CDPLAYER[] = {
|
|
&ME_CDPLAYER_TRACK,
|
|
&ME_CDPLAYER_TRACK,
|
|
&ME_CDPLAYER_TRACK,
|
|
&ME_CDPLAYER_TRACK,
|
|
&ME_CDPLAYER_TRACK,
|
|
&ME_CDPLAYER_TRACK,
|
|
&ME_CDPLAYER_TRACK,
|
|
&ME_CDPLAYER_TRACK
|
|
};
|
|
|
|
|
|
static MenuOption_t MEO_SAVESETUP_AUTOSAVE = MAKE_MENUOPTION( &MF_Redfont, &MEOS_OffOn, &cl_autosave.Value );
|
|
static MenuEntry_t ME_SAVESETUP_AUTOSAVE = MAKE_MENUENTRY( "Autosaves:", &MF_Redfont, &MEF_BigOptionsRt, &MEO_SAVESETUP_AUTOSAVE, Option );
|
|
|
|
static MenuOption_t MEO_SAVESETUP_AUTOSAVEDELETION = MAKE_MENUOPTION( &MF_Redfont, &MEOS_NoYes, &cl_autosavedeletion.Value );
|
|
static MenuEntry_t ME_SAVESETUP_AUTOSAVEDELETION = MAKE_MENUENTRY( "Auto-Delete:", &MF_Redfont, &MEF_BigOptions_Apply, &MEO_SAVESETUP_AUTOSAVEDELETION, Option );
|
|
static MenuRangeInt32_t MEO_SAVESETUP_MAXAUTOSAVES = MAKE_MENURANGE( &cl_maxautosaves.Value, &MF_Redfont, 1, 10, 0, 10, 1 );
|
|
static MenuEntry_t ME_SAVESETUP_MAXAUTOSAVES = MAKE_MENUENTRY( "Limit:", &MF_Redfont, &MEF_BigOptions_Apply, &MEO_SAVESETUP_MAXAUTOSAVES, RangeInt32 );
|
|
|
|
static MenuEntry_t ME_SAVESETUP_CLEANUP = MAKE_MENUENTRY( "Clean Up Saves", &MF_Redfont, &MEF_BigOptionsRt, &MEO_NULL, Link );
|
|
|
|
static MenuEntry_t *MEL_SAVESETUP[] = {
|
|
&ME_SAVESETUP_AUTOSAVE,
|
|
&ME_SAVESETUP_AUTOSAVEDELETION,
|
|
&ME_SAVESETUP_MAXAUTOSAVES,
|
|
&ME_SAVESETUP_CLEANUP,
|
|
};
|
|
|
|
|
|
MAKE_MENU_TOP_ENTRYLINK( "Player Setup", MEF_CenterMenu, NETWORK_PLAYERSETUP, MENU_PLAYER );
|
|
MAKE_MENU_TOP_ENTRYLINK( "Join Game", MEF_CenterMenu, NETWORK_JOINGAME, MENU_NETJOIN );
|
|
MAKE_MENU_TOP_ENTRYLINK( "Host Game", MEF_CenterMenu, NETWORK_HOSTGAME, MENU_NETHOST );
|
|
|
|
static MenuEntry_t *MEL_NETWORK[] = {
|
|
&ME_NETWORK_PLAYERSETUP,
|
|
&ME_NETWORK_JOINGAME,
|
|
&ME_NETWORK_HOSTGAME,
|
|
};
|
|
|
|
//static MenuString_t MEO_PLAYER_NAME = MAKE_MENUSTRING( playername, &MF_Bluefont, MAXPLAYERNAME, 0 );
|
|
//static MenuEntry_t ME_PLAYER_NAME = MAKE_MENUENTRY( "Name", &MF_Bluefont, &MEF_PlayerNarrow, &MEO_PLAYER_NAME, String );
|
|
static char const *MEOSN_PLAYER_COLOR[] = { "Auto", "Blue", "Red", "Green", "Gray", "Dark gray", "Dark green", "Brown", "Dark blue", "Bright red", "Yellow", };
|
|
static int32_t MEOSV_PLAYER_COLOR[] = { 0, 9, 10, 11, 12, 13, 14, 15, 16, 21, 23, };
|
|
static MenuOptionSet_t MEOS_PLAYER_COLOR = MAKE_MENUOPTIONSET( MEOSN_PLAYER_COLOR, MEOSV_PLAYER_COLOR, 0x2 );
|
|
static MenuOption_t MEO_PLAYER_COLOR = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_PLAYER_COLOR, &ud.color );
|
|
static MenuEntry_t ME_PLAYER_COLOR = MAKE_MENUENTRY( "Color", &MF_Bluefont, &MEF_PlayerNarrow, &MEO_PLAYER_COLOR, Option );
|
|
static char const *MEOSN_PLAYER_TEAM[] = { "Blue", "Red", "Green", "Gray", };
|
|
static MenuOptionSet_t MEOS_PLAYER_TEAM = MAKE_MENUOPTIONSET( MEOSN_PLAYER_TEAM, NULL, 0x2 );
|
|
static MenuOption_t MEO_PLAYER_TEAM = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_PLAYER_TEAM, &ud.team );
|
|
static MenuEntry_t ME_PLAYER_TEAM = MAKE_MENUENTRY( "Team", &MF_Bluefont, &MEF_PlayerNarrow, &MEO_PLAYER_TEAM, Option );
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
static MenuLink_t MEO_PLAYER_MACROS = { MENU_MACROS, MA_Advance, };
|
|
static MenuEntry_t ME_PLAYER_MACROS = MAKE_MENUENTRY( "Multiplayer macros", &MF_Bluefont, &MEF_SmallOptions, &MEO_PLAYER_MACROS, Link );
|
|
#endif
|
|
|
|
static MenuEntry_t *MEL_PLAYER[] = {
|
|
//&ME_PLAYER_NAME,
|
|
&ME_Space4_Bluefont,
|
|
&ME_PLAYER_COLOR,
|
|
&ME_Space4_Bluefont,
|
|
&ME_PLAYER_TEAM,
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
&ME_Space8_Bluefont,
|
|
&ME_PLAYER_MACROS,
|
|
#endif
|
|
};
|
|
|
|
#define MAXRIDECULE 10
|
|
#define MAXRIDECULELENGTH 40
|
|
static MenuString_t MEO_MACROS_TEMPLATE = MAKE_MENUSTRING( NULL, &MF_Bluefont, MAXRIDECULELENGTH, 0 );
|
|
static MenuString_t MEO_MACROS[10];
|
|
static char sink[50];
|
|
static MenuEntry_t ME_MACROS_TEMPLATE = MAKE_MENUENTRY( NULL, &MF_Bluefont, &MEF_Macros, &MEO_MACROS_TEMPLATE, String );
|
|
static MenuEntry_t ME_MACROS[MAXRIDECULE];
|
|
static MenuEntry_t *MEL_MACROS[MAXRIDECULE];
|
|
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
static char const *MenuUserMap = "User Map";
|
|
#endif
|
|
static char const *MenuSkillNone = "None";
|
|
|
|
static char const *MEOSN_NetGametypes[MAXGAMETYPES];
|
|
static char const *MEOSN_NetEpisodes[MAXVOLUMES+1];
|
|
static int32_t MEOSV_NetEpisodes[MAXVOLUMES+1];
|
|
static char const *MEOSN_NetLevels[MAXVOLUMES][MAXLEVELS];
|
|
static char const *MEOSN_NetSkills[MAXSKILLS+1];
|
|
|
|
static MenuLink_t MEO_NETHOST_OPTIONS = { MENU_NETOPTIONS, MA_Advance, };
|
|
static MenuEntry_t ME_NETHOST_OPTIONS = MAKE_MENUENTRY( "Game Options", &MF_Redfont, &MEF_VideoSetup, &MEO_NETHOST_OPTIONS, Link );
|
|
static MenuEntry_t ME_NETHOST_LAUNCH = MAKE_MENUENTRY( "Launch Game", &MF_Redfont, &MEF_VideoSetup, &MEO_NULL, Link );
|
|
|
|
static MenuEntry_t *MEL_NETHOST[] = {
|
|
&ME_NETHOST_OPTIONS,
|
|
&ME_NETHOST_LAUNCH,
|
|
};
|
|
|
|
static MenuOptionSet_t MEOS_NETOPTIONS_GAMETYPE = MAKE_MENUOPTIONSET( MEOSN_NetGametypes, NULL, 0x0 );
|
|
static MenuOption_t MEO_NETOPTIONS_GAMETYPE = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_NETOPTIONS_GAMETYPE, &ud.m_coop );
|
|
static MenuEntry_t ME_NETOPTIONS_GAMETYPE = MAKE_MENUENTRY( "Game Type", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_GAMETYPE, Option );
|
|
static MenuOptionSet_t MEOS_NETOPTIONS_EPISODE = MAKE_MENUOPTIONSET( MEOSN_NetEpisodes, MEOSV_NetEpisodes, 0x0 );
|
|
static int32_t NetEpisode;
|
|
static MenuOption_t MEO_NETOPTIONS_EPISODE = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_NETOPTIONS_EPISODE, &NetEpisode );
|
|
static MenuEntry_t ME_NETOPTIONS_EPISODE = MAKE_MENUENTRY( "Episode", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_EPISODE, Option );
|
|
static MenuOptionSet_t MEOS_NETOPTIONS_LEVEL_TEMPLATE = MAKE_MENUOPTIONSETNULL;
|
|
static MenuOptionSet_t MEOS_NETOPTIONS_LEVEL[MAXVOLUMES];
|
|
static MenuOption_t MEO_NETOPTIONS_LEVEL = MAKE_MENUOPTION( &MF_Bluefont, NULL, &ud.m_level_number );
|
|
static MenuEntry_t ME_NETOPTIONS_LEVEL = MAKE_MENUENTRY( "Level", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_LEVEL, Option );
|
|
static MenuLink_t MEO_NETOPTIONS_USERMAP = { MENU_NETUSERMAP, MA_Advance, };
|
|
static MenuEntry_t ME_NETOPTIONS_USERMAP = MAKE_MENUENTRY( "User Map", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_USERMAP, Link );
|
|
static MenuOptionSet_t MEOS_NETOPTIONS_MONSTERS = MAKE_MENUOPTIONSET( MEOSN_NetSkills, NULL, 0x0 );
|
|
static MenuOption_t MEO_NETOPTIONS_MONSTERS = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_NETOPTIONS_MONSTERS, NULL );
|
|
static MenuEntry_t ME_NETOPTIONS_MONSTERS = MAKE_MENUENTRY( "Monsters", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_MONSTERS, Option );
|
|
static MenuOption_t MEO_NETOPTIONS_MARKERS = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_OffOn, &ud.m_marker );
|
|
static MenuEntry_t ME_NETOPTIONS_MARKERS = MAKE_MENUENTRY( "Markers", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_MARKERS, Option );
|
|
static MenuOption_t MEO_NETOPTIONS_MAPEXITS = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_OnOff, &ud.m_noexits );
|
|
static MenuEntry_t ME_NETOPTIONS_MAPEXITS = MAKE_MENUENTRY( "Map Exits", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_MAPEXITS, Option );
|
|
static MenuOption_t MEO_NETOPTIONS_FRFIRE = MAKE_MENUOPTION( &MF_Bluefont, &MEOS_OffOn, &ud.m_ffire );
|
|
static MenuEntry_t ME_NETOPTIONS_FRFIRE = MAKE_MENUENTRY( "Fr. Fire", &MF_Redfont, &MEF_NetSetup, &MEO_NETOPTIONS_FRFIRE, Option );
|
|
static MenuEntry_t ME_NETOPTIONS_ACCEPT = MAKE_MENUENTRY( "Accept", &MF_Redfont, &MEF_NetSetup_Confirm, &MEO_NETWORK_HOSTGAME, Link );
|
|
|
|
static MenuEntry_t *MEL_NETOPTIONS[] = {
|
|
&ME_NETOPTIONS_GAMETYPE,
|
|
&ME_NETOPTIONS_EPISODE,
|
|
&ME_NETOPTIONS_LEVEL,
|
|
&ME_NETOPTIONS_MONSTERS,
|
|
&ME_NETOPTIONS_MARKERS,
|
|
&ME_NETOPTIONS_MAPEXITS,
|
|
&ME_NETOPTIONS_ACCEPT,
|
|
};
|
|
|
|
static char MenuServer[BMAX_PATH] = "localhost";
|
|
static MenuString_t MEO_NETJOIN_SERVER = MAKE_MENUSTRING( MenuServer, &MF_Bluefont, BMAX_PATH, 0 );
|
|
static MenuEntry_t ME_NETJOIN_SERVER = MAKE_MENUENTRY( "Server", &MF_Redfont, &MEF_VideoSetup, &MEO_NETJOIN_SERVER, String );
|
|
#define MAXPORTSTRINGLENGTH 6 // unsigned 16-bit integer
|
|
static char MenuPort[MAXPORTSTRINGLENGTH] = "19014";
|
|
static MenuString_t MEO_NETJOIN_PORT = MAKE_MENUSTRING( MenuPort, &MF_Bluefont, MAXPORTSTRINGLENGTH, INPUT_NUMERIC );
|
|
static MenuEntry_t ME_NETJOIN_PORT = MAKE_MENUENTRY( "Port", &MF_Redfont, &MEF_VideoSetup, &MEO_NETJOIN_PORT, String );
|
|
static MenuEntry_t ME_NETJOIN_CONNECT = MAKE_MENUENTRY( "Connect", &MF_Redfont, &MEF_VideoSetup_Apply, &MEO_NULL, Link );
|
|
|
|
static MenuEntry_t *MEL_NETJOIN[] = {
|
|
&ME_NETJOIN_SERVER,
|
|
&ME_NETJOIN_PORT,
|
|
&ME_NETJOIN_CONNECT,
|
|
};
|
|
|
|
|
|
#define NoTitle NULL
|
|
|
|
#define MAKE_MENUMENU(Title, Format, Entries) { Title, Format, Entries, ARRAY_SIZE(Entries), 0, 0, 0 }
|
|
#define MAKE_MENUMENU_CUSTOMSIZE(Title, Format, Entries) { Title, Format, Entries, 0, 0, 0, 0 }
|
|
|
|
static MenuMenu_t M_MAIN = MAKE_MENUMENU( NoTitle, &MMF_Top_Main, MEL_MAIN );
|
|
static MenuMenu_t M_MAIN_INGAME = MAKE_MENUMENU( NoTitle, &MMF_Top_Main, MEL_MAIN_INGAME );
|
|
static MenuMenu_t M_EPISODE = MAKE_MENUMENU( "Select An Episode", &MMF_Top_Episode, MEL_EPISODE );
|
|
static MenuMenu_t M_SKILL = MAKE_MENUMENU( "Select Skill", &MMF_Top_Skill, MEL_SKILL );
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
static MenuMenu_t M_GAMESETUP = MAKE_MENUMENU( "Game Setup", &MMF_BigOptions, MEL_GAMESETUP );
|
|
#endif
|
|
static MenuMenu_t M_OPTIONS = MAKE_MENUMENU( s_Options, &MMF_Top_Options, MEL_OPTIONS );
|
|
static MenuMenu_t M_VIDEOSETUP = MAKE_MENUMENU( "Video Mode", &MMF_BigOptions, MEL_VIDEOSETUP );
|
|
static MenuMenu_t M_KEYBOARDSETUP = MAKE_MENUMENU( "Keyboard Setup", &MMF_Top_Options, MEL_KEYBOARDSETUP );
|
|
static MenuMenu_t M_CONTROLS = MAKE_MENUMENU( "Control Setup", &MMF_Top_Options, MEL_CONTROLS );
|
|
static MenuMenu_t M_CHEATS = MAKE_MENUMENU( "Cheats", &MMF_SmallOptions, MEL_CHEATS );
|
|
static MenuMenu_t M_MOUSESETUP = MAKE_MENUMENU( "Mouse Setup", &MMF_BigOptions, MEL_MOUSESETUP );
|
|
#ifdef EDUKE32_ANDROID_MENU
|
|
static MenuMenu_t M_TOUCHSETUP = MAKE_MENUMENU( "Touch Setup", &MMF_Top_Options, MEL_TOUCHSETUP );
|
|
static MenuMenu_t M_TOUCHSENS = MAKE_MENUMENU( "Sensitivity", &MMF_BigOptions, MEL_TOUCHSENS);
|
|
static MenuPanel_t M_TOUCHBUTTONS = { "Button Setup", MENU_TOUCHSETUP, MA_Return, MENU_TOUCHSETUP, MA_Advance, };
|
|
#endif
|
|
static MenuMenu_t M_JOYSTICKSETUP = MAKE_MENUMENU( "Joystick Setup", &MMF_Top_Joystick_Network, MEL_JOYSTICKSETUP );
|
|
static MenuMenu_t M_JOYSTICKBTNS = MAKE_MENUMENU( "Joystick Buttons", &MMF_MouseJoySetupBtns, MEL_JOYSTICKBTNS );
|
|
static MenuMenu_t M_JOYSTICKAXES = MAKE_MENUMENU( "Joystick Axes", &MMF_BigSliders, MEL_JOYSTICKAXES );
|
|
static MenuMenu_t M_KEYBOARDKEYS = MAKE_MENUMENU( "Key Configuration", &MMF_KeyboardSetupFuncs, MEL_KEYBOARDSETUPFUNCS );
|
|
static MenuMenu_t M_MOUSEBTNS = MAKE_MENUMENU( "Mouse Buttons", &MMF_MouseJoySetupBtns, MEL_MOUSESETUPBTNS );
|
|
static MenuMenu_t M_MOUSEADVANCED = MAKE_MENUMENU( "Advanced Mouse", &MMF_BigSliders, MEL_MOUSEADVANCED );
|
|
static MenuMenu_t M_JOYSTICKAXIS = MAKE_MENUMENU( NULL, &MMF_BigSliders, MEL_JOYSTICKAXIS );
|
|
#ifdef USE_OPENGL
|
|
static MenuMenu_t M_RENDERERSETUP_POLYMOST = MAKE_MENUMENU( "Polymost Setup", &MMF_SmallOptions, MEL_RENDERERSETUP_POLYMOST );
|
|
# ifdef POLYMER
|
|
static MenuMenu_t M_RENDERERSETUP_POLYMER = MAKE_MENUMENU("Polymer Setup", &MMF_SmallOptions, MEL_RENDERERSETUP_POLYMER );
|
|
# endif
|
|
#endif
|
|
static MenuMenu_t M_COLCORR = MAKE_MENUMENU( "Color Correction", &MMF_ColorCorrect, MEL_COLCORR );
|
|
static MenuMenu_t M_SCREENSETUP = MAKE_MENUMENU( "HUD Setup", &MMF_BigOptions, MEL_SCREENSETUP );
|
|
static MenuMenu_t M_DISPLAYSETUP = MAKE_MENUMENU( "Display Setup", &MMF_BigOptions, MEL_DISPLAYSETUP );
|
|
static MenuMenu_t M_LOAD = MAKE_MENUMENU_CUSTOMSIZE( s_LoadGame, &MMF_LoadSave, MEL_LOAD );
|
|
static MenuMenu_t M_SAVE = MAKE_MENUMENU_CUSTOMSIZE( s_SaveGame, &MMF_LoadSave, MEL_SAVE );
|
|
static MenuMenu_t M_SOUND = MAKE_MENUMENU( "Sound Setup", &MMF_BigOptions, MEL_SOUND );
|
|
static MenuMenu_t M_ADVSOUND = MAKE_MENUMENU( "Advanced Sound", &MMF_BigOptions, MEL_ADVSOUND );
|
|
static MenuMenu_t M_CDPLAYER = MAKE_MENUMENU( "8 Track Player", &MMF_BigOptions, MEL_CDPLAYER );
|
|
static MenuMenu_t M_SAVESETUP = MAKE_MENUMENU( "Save Setup", &MMF_BigOptions, MEL_SAVESETUP );
|
|
static MenuMenu_t M_NETWORK = MAKE_MENUMENU( "Network Game", &MMF_Top_Joystick_Network, MEL_NETWORK );
|
|
static MenuMenu_t M_PLAYER = MAKE_MENUMENU( "Player Setup", &MMF_SmallOptions, MEL_PLAYER );
|
|
static MenuMenu_t M_MACROS = MAKE_MENUMENU( "Multiplayer Macros", &MMF_Macros, MEL_MACROS );
|
|
static MenuMenu_t M_NETHOST = MAKE_MENUMENU( "Host Network Game", &MMF_SmallOptionsNarrow, MEL_NETHOST );
|
|
static MenuMenu_t M_NETOPTIONS = MAKE_MENUMENU( "Net Game Options", &MMF_NetSetup, MEL_NETOPTIONS );
|
|
static MenuMenu_t M_NETJOIN = MAKE_MENUMENU( "Join Network Game", &MMF_SmallOptionsNarrow, MEL_NETJOIN );
|
|
|
|
#ifdef EDUKE32_SIMPLE_MENU
|
|
static MenuPanel_t M_STORY = { NoTitle, MENU_STORY, MA_Return, MENU_STORY, MA_Advance, };
|
|
#else
|
|
static MenuPanel_t M_STORY = { NoTitle, MENU_F1HELP, MA_Return, MENU_F1HELP, MA_Advance, };
|
|
#endif
|
|
|
|
static MenuPanel_t M_F1HELP = { NoTitle, MENU_STORY, MA_Return, MENU_STORY, MA_Advance, };
|
|
static MenuPanel_t M_F1HELP2 = { NoTitle, MENU_F1HELP, MA_Return, MENU_STORY, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS = { NoTitle, MENU_CREDITS33, MA_Return, MENU_CREDITS2, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS2 = { NoTitle, MENU_CREDITS, MA_Return, MENU_CREDITS3, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS3 = { NoTitle, MENU_CREDITS2, MA_Return, MENU_CREDITS31, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS4 = { s_Credits, MENU_CREDITS3, MA_Return, MENU_CREDITS5, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS5 = { s_Credits, MENU_CREDITS4, MA_Return, MENU_CREDITS6, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS6 = { s_Credits, MENU_CREDITS5, MA_Return, MENU_CREDITS7, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS7 = { s_Credits, MENU_CREDITS6, MA_Return, MENU_CREDITS8, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS8 = { s_Credits, MENU_CREDITS7, MA_Return, MENU_CREDITS9, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS9 = { s_Credits, MENU_CREDITS8, MA_Return, MENU_CREDITS10, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS10 = { s_Credits, MENU_CREDITS9, MA_Return, MENU_CREDITS11, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS11 = { s_Credits, MENU_CREDITS10, MA_Return, MENU_CREDITS12, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS12 = { s_Credits, MENU_CREDITS11, MA_Return, MENU_CREDITS13, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS13 = { s_Credits, MENU_CREDITS12, MA_Return, MENU_CREDITS14, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS14 = { s_Credits, MENU_CREDITS13, MA_Return, MENU_CREDITS15, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS15 = { s_Credits, MENU_CREDITS14, MA_Return, MENU_CREDITS16, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS16 = { s_Credits, MENU_CREDITS15, MA_Return, MENU_CREDITS17, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS17 = { s_Credits, MENU_CREDITS16, MA_Return, MENU_CREDITS18, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS18 = { s_Credits, MENU_CREDITS17, MA_Return, MENU_CREDITS19, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS19 = { s_Credits, MENU_CREDITS18, MA_Return, MENU_CREDITS20, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS20 = { s_Credits, MENU_CREDITS19, MA_Return, MENU_CREDITS21, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS21 = { s_Credits, MENU_CREDITS20, MA_Return, MENU_CREDITS22, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS22 = { s_Credits, MENU_CREDITS21, MA_Return, MENU_CREDITS23, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS23 = { s_Credits, MENU_CREDITS22, MA_Return, MENU_CREDITS24, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS24 = { s_Credits, MENU_CREDITS23, MA_Return, MENU_CREDITS25, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS25 = { s_Credits, MENU_CREDITS24, MA_Return, MENU_CREDITS26, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS26 = { s_Credits, MENU_CREDITS25, MA_Return, MENU_CREDITS27, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS27 = { s_Credits, MENU_CREDITS26, MA_Return, MENU_CREDITS28, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS28 = { s_Credits, MENU_CREDITS27, MA_Return, MENU_CREDITS29, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS29 = { s_Credits, MENU_CREDITS28, MA_Return, MENU_CREDITS30, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS30 = { s_Credits, MENU_CREDITS29, MA_Return, MENU_CREDITS31, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS31 = { "About " APPNAME, MENU_CREDITS3, MA_Return, MENU_CREDITS32, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS32 = { "About EDuke32", MENU_CREDITS31, MA_Return, MENU_CREDITS33, MA_Advance, };
|
|
static MenuPanel_t M_CREDITS33 = { "About EDuke32", MENU_CREDITS32, MA_Return, MENU_CREDITS, MA_Advance, };
|
|
|
|
#define CURSOR_CENTER_2LINE { MENU_MARGIN_CENTER<<16, 120<<16, }
|
|
#define CURSOR_CENTER_3LINE { MENU_MARGIN_CENTER<<16, 129<<16, }
|
|
#define CURSOR_BOTTOMRIGHT { 304<<16, 186<<16, }
|
|
|
|
static MenuVerify_t M_SAVECLEANVERIFY = { CURSOR_CENTER_3LINE, MENU_SAVESETUP, MA_None, };
|
|
static MenuVerify_t M_QUIT = { CURSOR_CENTER_2LINE, MENU_CLOSE, MA_None, };
|
|
static MenuVerify_t M_QUITTOTITLE = { CURSOR_CENTER_2LINE, MENU_CLOSE, MA_None, };
|
|
static MenuVerify_t M_LOADVERIFY = { CURSOR_CENTER_3LINE, MENU_CLOSE, MA_None, };
|
|
static MenuVerify_t M_LOADDELVERIFY = { CURSOR_CENTER_3LINE, MENU_LOAD, MA_None, };
|
|
static MenuVerify_t M_NEWVERIFY = { CURSOR_CENTER_2LINE, MENU_EPISODE, MA_Advance, };
|
|
static MenuVerify_t M_SAVEVERIFY = { CURSOR_CENTER_2LINE, MENU_SAVE, MA_None, };
|
|
static MenuVerify_t M_SAVEDELVERIFY = { CURSOR_CENTER_3LINE, MENU_SAVE, MA_None, };
|
|
static MenuVerify_t M_RESETPLAYER = { CURSOR_CENTER_3LINE, MENU_CLOSE, MA_None, };
|
|
|
|
static MenuMessage_t M_NETWAITMASTER = { CURSOR_BOTTOMRIGHT, MENU_NULL, MA_None, };
|
|
static MenuMessage_t M_NETWAITVOTES = { CURSOR_BOTTOMRIGHT, MENU_NULL, MA_None, };
|
|
static MenuMessage_t M_BUYDUKE = { CURSOR_BOTTOMRIGHT, MENU_EPISODE, MA_Return, };
|
|
|
|
static MenuTextForm_t M_ADULTPASSWORD = { NULL, "Enter Password:", MAXPWLOCKOUT, MTF_Password };
|
|
static MenuTextForm_t M_CHEATENTRY = { NULL, "Enter Cheat Code:", MAXCHEATLEN, 0 };
|
|
static MenuTextForm_t M_CHEAT_WARP = { NULL, "Enter Warp #:", 3, 0 };
|
|
static MenuTextForm_t M_CHEAT_SKILL = { NULL, "Enter Skill #:", 1, 0 };
|
|
|
|
//#define MAKE_MENUFILESELECT(a, b, c) { a, { &MMF_FileSelectLeft, &MMF_FileSelectRight }, { &MF_Minifont, &MF_Minifont }, b, c, { NULL, NULL }, { 0, 0 }, { 3<<16, 3<<16 }, FNLIST_INITIALIZER, 0 }
|
|
|
|
//static MenuFileSelect_t M_USERMAP = MAKE_MENUFILESELECT( "Select A User Map", "*.map", boardfilename );
|
|
|
|
// MUST be in ascending order of MenuID enum values due to binary search
|
|
static Menu_t Menus[] = {
|
|
{ &M_MAIN, MENU_MAIN, MENU_CLOSE, MA_None, Menu },
|
|
{ &M_MAIN_INGAME, MENU_MAIN_INGAME, MENU_CLOSE, MA_None, Menu },
|
|
{ &M_EPISODE, MENU_EPISODE, MENU_MAIN, MA_Return, Menu },
|
|
//{ &M_USERMAP, MENU_USERMAP, MENU_EPISODE, MA_Return, FileSelect },
|
|
{ &M_SKILL, MENU_SKILL, MENU_EPISODE, MA_Return, Menu },
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
{ &M_GAMESETUP, MENU_GAMESETUP, MENU_OPTIONS, MA_Return, Menu },
|
|
#endif
|
|
{ &M_OPTIONS, MENU_OPTIONS, MENU_MAIN, MA_Return, Menu },
|
|
{ &M_VIDEOSETUP, MENU_VIDEOSETUP, MENU_DISPLAYSETUP, MA_Return, Menu },
|
|
{ &M_KEYBOARDSETUP, MENU_KEYBOARDSETUP, MENU_CONTROLS, MA_Return, Menu },
|
|
{ &M_MOUSESETUP, MENU_MOUSESETUP, MENU_CONTROLS, MA_Return, Menu },
|
|
{ &M_JOYSTICKSETUP, MENU_JOYSTICKSETUP, MENU_CONTROLS, MA_Return, Menu },
|
|
{ &M_JOYSTICKBTNS, MENU_JOYSTICKBTNS, MENU_JOYSTICKSETUP, MA_Return, Menu },
|
|
{ &M_JOYSTICKAXES, MENU_JOYSTICKAXES, MENU_JOYSTICKSETUP, MA_Return, Menu },
|
|
{ &M_KEYBOARDKEYS, MENU_KEYBOARDKEYS, MENU_KEYBOARDSETUP, MA_Return, Menu },
|
|
{ &M_MOUSEBTNS, MENU_MOUSEBTNS, MENU_MOUSESETUP, MA_Return, Menu },
|
|
{ &M_MOUSEADVANCED, MENU_MOUSEADVANCED, MENU_MOUSESETUP, MA_Return, Menu },
|
|
{ &M_JOYSTICKAXIS, MENU_JOYSTICKAXIS, MENU_JOYSTICKAXES, MA_Return, Menu },
|
|
#ifdef EDUKE32_ANDROID_MENU
|
|
{ &M_TOUCHSETUP, MENU_TOUCHSETUP, MENU_OPTIONS, MA_Return, Menu },
|
|
{ &M_TOUCHSENS, MENU_TOUCHSENS, MENU_TOUCHSETUP, MA_Return, Menu },
|
|
{ &M_TOUCHBUTTONS, MENU_TOUCHBUTTONS, MENU_TOUCHSETUP, MA_Return, Panel },
|
|
#endif
|
|
{ &M_CONTROLS, MENU_CONTROLS, MENU_OPTIONS, MA_Return, Menu },
|
|
#ifdef USE_OPENGL
|
|
{ &M_RENDERERSETUP_POLYMOST, MENU_POLYMOST, MENU_DISPLAYSETUP, MA_Return, Menu },
|
|
#endif
|
|
{ &M_COLCORR, MENU_COLCORR, MENU_DISPLAYSETUP, MA_Return, Menu },
|
|
{ &M_COLCORR, MENU_COLCORR_INGAME, MENU_CLOSE, MA_Return, Menu },
|
|
{ &M_SCREENSETUP, MENU_SCREENSETUP, MENU_DISPLAYSETUP, MA_Return, Menu },
|
|
{ &M_DISPLAYSETUP, MENU_DISPLAYSETUP, MENU_OPTIONS, MA_Return, Menu },
|
|
#ifdef POLYMER
|
|
{ &M_RENDERERSETUP_POLYMER, MENU_POLYMER, MENU_DISPLAYSETUP, MA_Return, Menu },
|
|
#endif
|
|
{ &M_LOAD, MENU_LOAD, MENU_MAIN, MA_Return, Menu },
|
|
{ &M_SAVE, MENU_SAVE, MENU_MAIN, MA_Return, Menu },
|
|
{ &M_STORY, MENU_STORY, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_F1HELP, MENU_F1HELP, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_F1HELP2, MENU_F1HELP2, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_QUIT, MENU_QUIT, MENU_PREVIOUS, MA_Return, Verify },
|
|
{ &M_QUITTOTITLE, MENU_QUITTOTITLE, MENU_PREVIOUS, MA_Return, Verify },
|
|
{ &M_QUIT, MENU_QUIT_INGAME, MENU_CLOSE, MA_None, Verify },
|
|
{ &M_NETHOST, MENU_NETSETUP, MENU_MAIN, MA_Return, Menu },
|
|
{ &M_NETWAITMASTER, MENU_NETWAITMASTER, MENU_MAIN, MA_Return, Message },
|
|
{ &M_NETWAITVOTES, MENU_NETWAITVOTES, MENU_MAIN, MA_Return, Message },
|
|
{ &M_SOUND, MENU_SOUND, MENU_OPTIONS, MA_Return, Menu },
|
|
{ &M_SOUND, MENU_SOUND_INGAME, MENU_CLOSE, MA_Return, Menu },
|
|
{ &M_ADVSOUND, MENU_ADVSOUND, MENU_SOUND, MA_Return, Menu },
|
|
{ &M_CDPLAYER, MENU_CDPLAYER, MENU_SOUND, MA_Return, CdPlayer },
|
|
{ &M_SAVESETUP, MENU_SAVESETUP, MENU_OPTIONS, MA_Return, Menu },
|
|
{ &M_SAVECLEANVERIFY, MENU_SAVECLEANVERIFY, MENU_SAVESETUP, MA_None, Verify },
|
|
#ifdef EDUKE32_SIMPLE_MENU
|
|
{ &M_CHEATS, MENU_CHEATS, MENU_OPTIONS, MA_Return, Menu },
|
|
#else
|
|
{ &M_CHEATS, MENU_CHEATS, MENU_GAMESETUP, MA_Return, Menu },
|
|
#endif
|
|
{ &M_CHEATENTRY, MENU_CHEATENTRY, MENU_CHEATS, MA_None, TextForm },
|
|
{ &M_CHEAT_WARP, MENU_CHEAT_WARP, MENU_CHEATS, MA_None, TextForm },
|
|
{ &M_CHEAT_SKILL, MENU_CHEAT_SKILL, MENU_CHEATS, MA_None, TextForm },
|
|
{ &M_CREDITS, MENU_CREDITS, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS2, MENU_CREDITS2, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS3, MENU_CREDITS3, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS4, MENU_CREDITS4, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS5, MENU_CREDITS5, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS6, MENU_CREDITS6, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS7, MENU_CREDITS7, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS8, MENU_CREDITS8, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS9, MENU_CREDITS9, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS10, MENU_CREDITS10, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS11, MENU_CREDITS11, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS12, MENU_CREDITS12, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS13, MENU_CREDITS13, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS14, MENU_CREDITS14, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS15, MENU_CREDITS15, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS16, MENU_CREDITS16, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS17, MENU_CREDITS17, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS18, MENU_CREDITS18, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS19, MENU_CREDITS19, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS20, MENU_CREDITS20, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS21, MENU_CREDITS21, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS22, MENU_CREDITS22, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS23, MENU_CREDITS23, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS24, MENU_CREDITS24, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS25, MENU_CREDITS25, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS26, MENU_CREDITS26, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS27, MENU_CREDITS27, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS28, MENU_CREDITS28, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS29, MENU_CREDITS29, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS30, MENU_CREDITS30, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS31, MENU_CREDITS31, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS32, MENU_CREDITS32, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_CREDITS33, MENU_CREDITS33, MENU_MAIN, MA_Return, Panel },
|
|
{ &M_LOADVERIFY, MENU_LOADVERIFY, MENU_LOAD, MA_None, Verify },
|
|
{ &M_LOADDELVERIFY, MENU_LOADDELVERIFY, MENU_LOAD, MA_None, Verify },
|
|
{ &M_NEWVERIFY, MENU_NEWVERIFY, MENU_PREVIOUS, MA_Return, Verify },
|
|
{ &M_SAVEVERIFY, MENU_SAVEVERIFY, MENU_SAVE, MA_None, Verify },
|
|
{ &M_SAVEDELVERIFY, MENU_SAVEDELVERIFY, MENU_SAVE, MA_None, Verify },
|
|
{ &M_ADULTPASSWORD, MENU_ADULTPASSWORD, MENU_GAMESETUP, MA_None, TextForm },
|
|
{ &M_RESETPLAYER, MENU_RESETPLAYER, MENU_CLOSE, MA_None, Verify },
|
|
{ &M_BUYDUKE, MENU_BUYDUKE, MENU_EPISODE, MA_Return, Message },
|
|
{ &M_NETWORK, MENU_NETWORK, MENU_MAIN, MA_Return, Menu },
|
|
{ &M_PLAYER, MENU_PLAYER, MENU_OPTIONS, MA_Return, Menu },
|
|
{ &M_MACROS, MENU_MACROS, MENU_PLAYER, MA_Return, Menu },
|
|
{ &M_NETHOST, MENU_NETHOST, MENU_NETWORK, MA_Return, Menu },
|
|
{ &M_NETOPTIONS, MENU_NETOPTIONS, MENU_NETWORK, MA_Return, Menu },
|
|
//{ &M_USERMAP, MENU_NETUSERMAP, MENU_NETOPTIONS, MA_Return, FileSelect },
|
|
{ &M_NETJOIN, MENU_NETJOIN, MENU_NETWORK, MA_Return, Menu },
|
|
};
|
|
|
|
static CONSTEXPR const uint16_t numMenus = ARRAY_SIZE(Menus);
|
|
|
|
Menu_t *m_currentMenu = &Menus[0];
|
|
static Menu_t *m_previousMenu = &Menus[0];
|
|
static Menu_t * m_parentMenu;
|
|
|
|
MenuID_t g_currentMenu;
|
|
static MenuID_t g_previousMenu;
|
|
|
|
#define MenuMenu_ChangeEntryList(m, el)\
|
|
do {\
|
|
m.entrylist = el;\
|
|
m.numEntries = ARRAY_SIZE(el);\
|
|
} while (0)
|
|
|
|
static void MenuEntry_DisableOnCondition(MenuEntry_t * const entry, const int32_t condition)
|
|
{
|
|
if (condition)
|
|
entry->flags |= MEF_Disabled;
|
|
else
|
|
entry->flags &= ~MEF_Disabled;
|
|
}
|
|
static void MenuEntry_LookDisabledOnCondition(MenuEntry_t * const entry, const int32_t condition)
|
|
{
|
|
if (condition)
|
|
entry->flags |= MEF_LookDisabled;
|
|
else
|
|
entry->flags &= ~MEF_LookDisabled;
|
|
}
|
|
static void MenuEntry_HideOnCondition(MenuEntry_t * const entry, const int32_t condition)
|
|
{
|
|
if (condition)
|
|
entry->flags |= MEF_Hidden;
|
|
else
|
|
entry->flags &= ~MEF_Hidden;
|
|
}
|
|
|
|
static int32_t M_RunMenu_Menu(Menu_t *cm, MenuMenu_t *menu, MenuEntry_t *currentry, int32_t state, vec2_t origin, bool actually_draw = true);
|
|
static void Menu_EntryFocus(/*MenuEntry_t *entry*/);
|
|
|
|
static MenuEntry_t *Menu_AdjustForCurrentEntryAssignment(MenuMenu_t *menu)
|
|
{
|
|
MenuEntry_t *currentry = menu->entrylist[menu->currentEntry];
|
|
|
|
Menu_EntryFocus(/*currentry*/);
|
|
|
|
if (currentry->ybottom - menu->scrollPos > klabs(menu->format->bottomcutoff))
|
|
menu->scrollPos = currentry->ybottom - klabs(menu->format->bottomcutoff);
|
|
else if (currentry->ytop - menu->scrollPos < menu->format->pos.y)
|
|
menu->scrollPos = currentry->ytop - menu->format->pos.y;
|
|
|
|
return currentry;
|
|
}
|
|
|
|
static MenuEntry_t *Menu_AdjustForCurrentEntryAssignmentBlind(MenuMenu_t *menu)
|
|
{
|
|
M_RunMenu_Menu(nullptr, menu, nullptr, 0, { 0, 0 }, false);
|
|
return Menu_AdjustForCurrentEntryAssignment(menu);
|
|
}
|
|
|
|
static int32_t SELECTDIR_z = 65536;
|
|
|
|
/*
|
|
This function prepares data after ART and CON have been processed.
|
|
It also initializes some data in loops rather than statically at compile time.
|
|
*/
|
|
void Menu_Init(void)
|
|
{
|
|
int32_t i, j, k;
|
|
|
|
// prepare menu fonts
|
|
// check if tilenum is -1 in case it was set in EVENT_SETDEFAULTS
|
|
if ((unsigned)MF_Redfont.tilenum >= MAXTILES) MF_Redfont.tilenum = BIGALPHANUM;
|
|
if ((unsigned)MF_Bluefont.tilenum >= MAXTILES) MF_Bluefont.tilenum = STARTALPHANUM;
|
|
if ((unsigned)MF_Minifont.tilenum >= MAXTILES) MF_Minifont.tilenum = MINIFONT;
|
|
MF_Redfont.emptychar.y = tilesiz[MF_Redfont.tilenum].y<<16;
|
|
MF_Bluefont.emptychar.y = tilesiz[MF_Bluefont.tilenum].y<<16;
|
|
MF_Minifont.emptychar.y = tilesiz[MF_Minifont.tilenum].y<<16;
|
|
if (!minitext_lowercase)
|
|
MF_Minifont.textflags |= TEXT_UPPERCASE;
|
|
|
|
// prepare gamefuncs and keys
|
|
MEOSN_Gamefuncs[0] = MenuGameFuncNone;
|
|
MEOSV_Gamefuncs[0] = -1;
|
|
k = 1;
|
|
for (i = 0; i < NUMGAMEFUNCTIONS; ++i)
|
|
{
|
|
MenuGameFuncs[i] = buttonMap.GetButtonName(i);
|
|
MenuGameFuncs[i].Substitute('_', ' ');
|
|
}
|
|
if (RR)
|
|
{
|
|
MenuGameFuncs[gamefunc_Holo_Duke] = "Beer";
|
|
MenuGameFuncs[gamefunc_Jetpack] = "CowPie";
|
|
MenuGameFuncs[gamefunc_NightVision] = "Yeehaa";
|
|
MenuGameFuncs[gamefunc_MedKit] = "Whiskey";
|
|
MenuGameFuncs[gamefunc_Steroids] = "Moonshine";
|
|
MenuGameFuncs[gamefunc_Quick_Kick] = "Pee";
|
|
}
|
|
for (i = 0; i < NUMGAMEFUNCTIONS; ++i)
|
|
{
|
|
if (MenuGameFuncs[i][0] != '\0')
|
|
{
|
|
MEOSN_Gamefuncs[k] = MenuGameFuncs[i];
|
|
MEOSV_Gamefuncs[k] = i;
|
|
++k;
|
|
}
|
|
}
|
|
|
|
MEOS_Gamefuncs.numOptions = k;
|
|
|
|
for (i = 0; i < NUMKEYS; ++i)
|
|
MEOSN_Keys[i] = KB_ScanCodeToString(i);
|
|
MEOSN_Keys[NUMKEYS-1] = MenuKeyNone;
|
|
|
|
|
|
// prepare episodes
|
|
k = 0;
|
|
for (i = 0; i < g_volumeCnt; ++i)
|
|
{
|
|
if (g_volumeNames[i][0])
|
|
{
|
|
if (!(g_volumeFlags[i] & EF_HIDEFROMSP))
|
|
{
|
|
MEL_EPISODE[i] = &ME_EPISODE[i];
|
|
ME_EPISODE[i] = ME_EPISODE_TEMPLATE;
|
|
ME_EPISODE[i].name = g_volumeNames[i];
|
|
}
|
|
|
|
// if (!(EpisodeFlags[i] & EF_HIDEFROMMP))
|
|
{
|
|
MEOSN_NetEpisodes[k] = g_volumeNames[i];
|
|
MEOSV_NetEpisodes[k] = i;
|
|
|
|
k++;
|
|
}
|
|
}
|
|
|
|
// prepare levels
|
|
MEOS_NETOPTIONS_LEVEL[i] = MEOS_NETOPTIONS_LEVEL_TEMPLATE;
|
|
for (j = 0; j < MAXLEVELS; ++j)
|
|
{
|
|
MEOSN_NetLevels[i][j] = g_mapInfo[MAXLEVELS*i+j].name;
|
|
if (g_mapInfo[i*MAXLEVELS+j].filename != NULL)
|
|
MEOS_NETOPTIONS_LEVEL[i].numOptions = j+1;
|
|
}
|
|
MEOS_NETOPTIONS_LEVEL[i].optionNames = MEOSN_NetLevels[i];
|
|
}
|
|
M_EPISODE.numEntries = g_volumeCnt+2;
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
MEL_EPISODE[g_volumeCnt] = &ME_Space4_Redfont;
|
|
MEL_EPISODE[g_volumeCnt+1] = &ME_EPISODE_USERMAP;
|
|
MEOSN_NetEpisodes[k] = MenuUserMap;
|
|
MEOSV_NetEpisodes[k] = MAXVOLUMES;
|
|
#else
|
|
M_EPISODE.numEntries = g_volumeCnt;
|
|
k--;
|
|
#endif
|
|
MEOS_NETOPTIONS_EPISODE.numOptions = k + 1;
|
|
NetEpisode = MEOSV_NetEpisodes[0];
|
|
MMF_Top_Episode.pos.y = (58 + (3-k)*6)<<16;
|
|
if (g_skillCnt == 0)
|
|
MEO_EPISODE.linkID = MENU_NULL;
|
|
M_EPISODE.currentEntry = ud.default_volume;
|
|
|
|
// prepare skills
|
|
k = -1;
|
|
for (i = 0; i < g_skillCnt && g_skillNames[i][0]; ++i)
|
|
{
|
|
MEL_SKILL[i] = &ME_SKILL[i];
|
|
ME_SKILL[i] = ME_SKILL_TEMPLATE;
|
|
ME_SKILL[i].name = g_skillNames[i];
|
|
|
|
MEOSN_NetSkills[i] = g_skillNames[i];
|
|
|
|
k = i;
|
|
}
|
|
++k;
|
|
M_SKILL.numEntries = g_skillCnt; // k;
|
|
MEOS_NETOPTIONS_MONSTERS.numOptions = g_skillCnt + 1; // k+1;
|
|
MEOSN_NetSkills[g_skillCnt] = MenuSkillNone;
|
|
MMF_Top_Skill.pos.y = (58 + (4-g_skillCnt)*6)<<16;
|
|
M_SKILL.currentEntry = ud.default_skill;
|
|
Menu_AdjustForCurrentEntryAssignmentBlind(&M_SKILL);
|
|
|
|
// prepare multiplayer gametypes
|
|
k = -1;
|
|
for (i = 0; i < MAXGAMETYPES; ++i)
|
|
if (g_gametypeNames[i][0])
|
|
{
|
|
MEOSN_NetGametypes[i] = g_gametypeNames[i];
|
|
k = i;
|
|
}
|
|
++k;
|
|
MEOS_NETOPTIONS_GAMETYPE.numOptions = k;
|
|
|
|
// prepare cheats
|
|
for (i = 0; i < NUMCHEATFUNCS; ++i)
|
|
MEL_CHEATS[i+1] = &ME_CheatCodes[i];
|
|
|
|
// prepare text chat macros
|
|
for (i = 0; i < MAXRIDECULE; ++i)
|
|
{
|
|
MEL_MACROS[i] = &ME_MACROS[i];
|
|
ME_MACROS[i] = ME_MACROS_TEMPLATE;
|
|
ME_MACROS[i].entry = &MEO_MACROS[i];
|
|
MEO_MACROS[i] = MEO_MACROS_TEMPLATE;
|
|
|
|
MEO_MACROS[i].variable = sink;// ud.ridecule[i]; temporarily disabled
|
|
}
|
|
|
|
// prepare input
|
|
for (i = 0; i < NUMGAMEFUNCTIONS; ++i)
|
|
{
|
|
if (MenuGameFuncs[i][0] == '\0')
|
|
{
|
|
MEL_KEYBOARDSETUPFUNCS[i] = NULL;
|
|
continue;
|
|
}
|
|
|
|
MEL_KEYBOARDSETUPFUNCS[i] = &ME_KEYBOARDSETUPFUNCS[i];
|
|
ME_KEYBOARDSETUPFUNCS[i] = ME_KEYBOARDSETUPFUNCS_TEMPLATE;
|
|
ME_KEYBOARDSETUPFUNCS[i].name = MenuGameFuncs[i];
|
|
ME_KEYBOARDSETUPFUNCS[i].entry = &MEO_KEYBOARDSETUPFUNCS[i];
|
|
MEO_KEYBOARDSETUPFUNCS[i] = MEO_KEYBOARDSETUPFUNCS_TEMPLATE;
|
|
}
|
|
M_KEYBOARDKEYS.numEntries = NUMGAMEFUNCTIONS;
|
|
for (i = 0; i < MENUMOUSEFUNCTIONS; ++i)
|
|
{
|
|
MEL_MOUSESETUPBTNS[i] = &ME_MOUSESETUPBTNS[i];
|
|
ME_MOUSESETUPBTNS[i] = ME_MOUSEJOYSETUPBTNS_TEMPLATE;
|
|
ME_MOUSESETUPBTNS[i].name = MenuMouseNames[i];
|
|
ME_MOUSESETUPBTNS[i].entry = &MEO_MOUSESETUPBTNS[i];
|
|
MEO_MOUSESETUPBTNS[i] = MEO_MOUSEJOYSETUPBTNS_TEMPLATE;
|
|
static int32_t sink;
|
|
MEO_MOUSESETUPBTNS[i].data = &sink;
|
|
}
|
|
for (i = 0; i < 2*joystick.numButtons + 8*joystick.numHats; ++i)
|
|
{
|
|
if (i < 2*joystick.numButtons)
|
|
{
|
|
if (i & 1)
|
|
Bsnprintf(MenuJoystickNames[i], MAXJOYBUTTONSTRINGLENGTH, "Double %s", joyGetName(1, i>>1));
|
|
else
|
|
Bstrncpy(MenuJoystickNames[i], joyGetName(1, i>>1), MAXJOYBUTTONSTRINGLENGTH);
|
|
}
|
|
else
|
|
{
|
|
Bsnprintf(MenuJoystickNames[i], MAXJOYBUTTONSTRINGLENGTH, (i & 1) ? "Double Hat %d %s" : "Hat %d %s", ((i - 2*joystick.numButtons)>>3), MenuJoystickHatDirections[((i - 2*joystick.numButtons)>>1) % 4]);
|
|
}
|
|
|
|
MEL_JOYSTICKBTNS[i] = &ME_JOYSTICKBTNS[i];
|
|
ME_JOYSTICKBTNS[i] = ME_MOUSEJOYSETUPBTNS_TEMPLATE;
|
|
ME_JOYSTICKBTNS[i].name = MenuJoystickNames[i];
|
|
ME_JOYSTICKBTNS[i].entry = &MEO_JOYSTICKBTNS[i];
|
|
MEO_JOYSTICKBTNS[i] = MEO_MOUSEJOYSETUPBTNS_TEMPLATE;
|
|
MEO_JOYSTICKBTNS[i].data = &JoystickFunctions[i>>1][i&1];
|
|
}
|
|
M_JOYSTICKBTNS.numEntries = 2*joystick.numButtons + 8*joystick.numHats;
|
|
for (i = 0; i < joystick.numAxes; ++i)
|
|
{
|
|
ME_JOYSTICKAXES[i] = ME_JOYSTICKAXES_TEMPLATE;
|
|
Bstrncpy(MenuJoystickAxes[i], joyGetName(0, i), MAXJOYBUTTONSTRINGLENGTH);
|
|
ME_JOYSTICKAXES[i].name = MenuJoystickAxes[i];
|
|
MEL_JOYSTICKAXES[i] = &ME_JOYSTICKAXES[i];
|
|
}
|
|
M_JOYSTICKAXES.numEntries = joystick.numAxes;
|
|
|
|
// prepare video setup
|
|
for (i = 0; i < validmodecnt; ++i)
|
|
{
|
|
for (j = 0; j < MEOS_VIDEOSETUP_RESOLUTION.numOptions; ++j)
|
|
{
|
|
if (validmode[i].xdim == resolution[j].xdim && validmode[i].ydim == resolution[j].ydim)
|
|
{
|
|
resolution[j].flags |= validmode[i].fs ? RES_FS : RES_WIN;
|
|
Bsnprintf(resolution[j].name, MAXRESOLUTIONSTRINGLENGTH, "%d x %d%s", resolution[j].xdim, resolution[j].ydim, (resolution[j].flags & RES_FS) ? "" : "Win");
|
|
MEOSN_VIDEOSETUP_RESOLUTION[j] = resolution[j].name;
|
|
if (validmode[i].bpp > resolution[j].bppmax)
|
|
resolution[j].bppmax = validmode[i].bpp;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (j == MEOS_VIDEOSETUP_RESOLUTION.numOptions) // no match found
|
|
{
|
|
resolution[j].xdim = validmode[i].xdim;
|
|
resolution[j].ydim = validmode[i].ydim;
|
|
resolution[j].bppmax = validmode[i].bpp;
|
|
resolution[j].flags = validmode[i].fs ? RES_FS : RES_WIN;
|
|
Bsnprintf(resolution[j].name, MAXRESOLUTIONSTRINGLENGTH, "%d x %d%s", resolution[j].xdim, resolution[j].ydim, (resolution[j].flags & RES_FS) ? "" : "Win");
|
|
MEOSN_VIDEOSETUP_RESOLUTION[j] = resolution[j].name;
|
|
++MEOS_VIDEOSETUP_RESOLUTION.numOptions;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
// prepare sound setup
|
|
if (WW2GI)
|
|
ME_SOUND_DUKETALK.name = "GI talk:";
|
|
else if (NAM)
|
|
ME_SOUND_DUKETALK.name = "Grunt talk:";
|
|
|
|
if (IONMAIDEN)
|
|
{
|
|
MF_Redfont.between.x = 2<<16;
|
|
MF_Redfont.cursorScale = 32768;
|
|
MF_Redfont.zoom = 16384;
|
|
MF_Bluefont.zoom = 16384;
|
|
|
|
// hack; should swap out pointers
|
|
MF_Minifont = MF_Bluefont;
|
|
|
|
MMF_Top_Main.pos.x = 40<<16;
|
|
MMF_Top_Main.pos.y = 130<<16;
|
|
MMF_Top_Main.bottomcutoff = 190<<16;
|
|
M_OPTIONS.format = &MMF_Top_Main;
|
|
|
|
MEF_MainMenu.width = MEF_OptionsMenu.width = -(160<<16);
|
|
MEF_MainMenu.marginBottom = 7<<16;
|
|
|
|
M_OPTIONS.title = NoTitle;
|
|
|
|
SELECTDIR_z = 16384;
|
|
}
|
|
#endif
|
|
|
|
if (RR)
|
|
{
|
|
MF_Redfont.zoom = 32768;
|
|
MF_Redfont.emptychar.x <<= 1;
|
|
MF_Redfont.cursorScale = 13107;
|
|
MF_Redfont.cursorScale2 = 6553;
|
|
//MF_Redfont.emptychar.y <<= 1;
|
|
MF_Bluefont.zoom = 32768;
|
|
MF_Bluefont.emptychar.x <<= 1;
|
|
MF_Bluefont.cursorScale = 6553;
|
|
MF_Bluefont.cursorScale2 = 6553;
|
|
//MF_Bluefont.emptychar.y <<= 1;
|
|
MF_Minifont.zoom = 32768;
|
|
MF_Minifont.emptychar.x <<= 1;
|
|
MF_Minifont.cursorScale = 6553;
|
|
MF_Minifont.cursorScale2 = 6553;
|
|
//MF_Minifont.emptychar.y <<= 1;
|
|
ME_SOUND_DUKETALK.name = "Leonard Talk:";
|
|
}
|
|
else if (NAPALM)
|
|
{
|
|
ME_SOUND_DUKETALK.name = "NAPALM Talk:";
|
|
}
|
|
else if (NAM)
|
|
{
|
|
ME_SOUND_DUKETALK.name = "NAM Talk:";
|
|
}
|
|
|
|
// prepare shareware
|
|
if (VOLUMEONE)
|
|
{
|
|
// blue out episodes beyond the first
|
|
for (i = 1; i < g_volumeCnt; ++i)
|
|
{
|
|
if (MEL_EPISODE[i])
|
|
{
|
|
ME_EPISODE[i].entry = &MEO_EPISODE_SHAREWARE;
|
|
ME_EPISODE[i].flags |= MEF_LookDisabled;
|
|
}
|
|
}
|
|
M_EPISODE.numEntries = g_volumeCnt; // remove User Map (and spacer)
|
|
MEOS_NETOPTIONS_EPISODE.numOptions = 1;
|
|
MenuEntry_DisableOnCondition(&ME_NETOPTIONS_EPISODE, 1);
|
|
}
|
|
|
|
if (RR)
|
|
{
|
|
MEL_SOUND[0] = &ME_SOUND_CDPLAYER;
|
|
MEL_SOUND[1] = &ME_SOUND;
|
|
M_CREDITS.title = M_CREDITS2.title = M_CREDITS3.title = s_Credits;
|
|
M_CREDITS3.nextID = MENU_CREDITS4;
|
|
M_STORY.previousID = M_STORY.nextID = MENU_F1HELP;
|
|
if (RRRA)
|
|
{
|
|
M_CREDITS31.previousID = MENU_CREDITS30;
|
|
M_STORY.previousID = MENU_F1HELP2;
|
|
M_F1HELP.nextID = MENU_F1HELP2;
|
|
}
|
|
else
|
|
{
|
|
M_CREDITS31.previousID = MENU_CREDITS23;
|
|
M_CREDITS23.nextID = MENU_CREDITS31;
|
|
}
|
|
}
|
|
// prepare pre-Atomic
|
|
else if (!VOLUMEALL || !PLUTOPAK)
|
|
{
|
|
// prepare credits
|
|
M_CREDITS.title = M_CREDITS2.title = M_CREDITS3.title = s_Credits;
|
|
}
|
|
}
|
|
|
|
static void Menu_Run(Menu_t *cm, vec2_t origin);
|
|
|
|
|
|
static void Menu_BlackRectangle(int32_t x, int32_t y, int32_t width, int32_t height, int32_t orientation);
|
|
|
|
/*
|
|
At present, no true difference is planned between Menu_Pre() and Menu_PreDraw().
|
|
They are separate for purposes of organization.
|
|
*/
|
|
|
|
static void Menu_Pre(MenuID_t cm)
|
|
{
|
|
int32_t i;
|
|
DukePlayer_t *ps = g_player[myconnectindex].ps;
|
|
|
|
switch (cm)
|
|
{
|
|
case MENU_MAIN_INGAME:
|
|
MenuEntry_DisableOnCondition(&ME_MAIN_LOADGAME, (RRRA && ud.player_skill == 4) || (RR && !RRRA && ud.player_skill == 5));
|
|
MenuEntry_DisableOnCondition(&ME_MAIN_SAVEGAME, ud.recstat == 2 || (RRRA && ud.player_skill == 4) || (RR && !RRRA && ud.player_skill == 5));
|
|
MenuEntry_DisableOnCondition(&ME_MAIN_QUITTOTITLE, g_netServer || numplayers > 1);
|
|
fallthrough__;
|
|
case MENU_MAIN:
|
|
if ((g_netServer || ud.multimode > 1) && ud.recstat != 2)
|
|
{
|
|
ME_MAIN_NEWGAME.entry = &MEO_MAIN_NEWGAME_NETWORK;
|
|
ME_MAIN_NEWGAME_INGAME.entry = &MEO_MAIN_NEWGAME_NETWORK;
|
|
}
|
|
else
|
|
{
|
|
ME_MAIN_NEWGAME.entry = &MEO_MAIN_NEWGAME;
|
|
ME_MAIN_NEWGAME_INGAME.entry = &MEO_MAIN_NEWGAME_INGAME;
|
|
}
|
|
break;
|
|
|
|
case MENU_GAMESETUP:
|
|
MEO_GAMESETUP_DEMOREC.options = (ps->gm&MODE_GAME) ? &MEOS_DemoRec : &MEOS_OffOn;
|
|
MenuEntry_DisableOnCondition(&ME_GAMESETUP_DEMOREC, (ps->gm&MODE_GAME) && ud.m_recstat != 1);
|
|
break;
|
|
|
|
#ifdef USE_OPENGL
|
|
case MENU_DISPLAYSETUP:
|
|
if (videoGetRenderMode() == REND_CLASSIC)
|
|
MenuMenu_ChangeEntryList(M_DISPLAYSETUP, MEL_DISPLAYSETUP);
|
|
#ifdef POLYMER
|
|
else if (videoGetRenderMode() == REND_POLYMER)
|
|
MenuMenu_ChangeEntryList(M_DISPLAYSETUP, MEL_DISPLAYSETUP_GL_POLYMER);
|
|
#endif
|
|
else
|
|
MenuMenu_ChangeEntryList(M_DISPLAYSETUP, MEL_DISPLAYSETUP_GL);
|
|
|
|
MEO_SCREENSETUP_SCREENSIZE.steps = !(ud.statusbarflags & STATUSBAR_NONONE) +
|
|
!(ud.statusbarflags & STATUSBAR_NOMODERN) +
|
|
!(ud.statusbarflags & STATUSBAR_NOMINI) +
|
|
!(ud.statusbarflags & STATUSBAR_NOOVERLAY) +
|
|
!(ud.statusbarflags & STATUSBAR_NOFULL) +
|
|
!(ud.statusbarflags & STATUSBAR_NOSHRINK) * 14;
|
|
MEO_SCREENSETUP_SCREENSIZE.max = MEO_SCREENSETUP_SCREENSIZE.steps - 1;
|
|
MenuEntry_DisableOnCondition(&ME_SCREENSETUP_SCREENSIZE, (MEO_SCREENSETUP_SCREENSIZE.steps < 2));
|
|
|
|
vpsize = -1;
|
|
|
|
if (videoGetRenderMode() != REND_CLASSIC)
|
|
{
|
|
//POGOTODO: allow setting anisotropy again while hw_useindexedcolortextures is set when support is added down the line
|
|
// don't allow setting anisotropy or changing palette emulation while in POLYMOST and hw_useindexedcolortextures is enabled
|
|
MenuEntry_DisableOnCondition(&ME_DISPLAYSETUP_ANISOTROPY, videoGetRenderMode() == REND_POLYMOST && hw_useindexedcolortextures);
|
|
#ifdef EDUKE32_SIMPLE_MENU
|
|
MenuEntry_DisableOnCondition(&ME_DISPLAYSETUP_PALETTEEMULATION, videoGetRenderMode() == REND_POLYMOST && hw_useindexedcolortextures);
|
|
#endif
|
|
|
|
for (i = (int32_t) ARRAY_SIZE(MEOSV_DISPLAYSETUP_ANISOTROPY) - 1; i >= 0; --i)
|
|
{
|
|
if (MEOSV_DISPLAYSETUP_ANISOTROPY[i] <= GLInterface.glinfo.maxanisotropy)
|
|
{
|
|
MEOS_DISPLAYSETUP_ANISOTROPY.numOptions = i + 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MENU_POLYMER:
|
|
case MENU_POLYMOST:
|
|
MenuEntry_DisableOnCondition(&ME_RENDERERSETUP_TEXQUALITY, !hw_hightile);
|
|
MenuEntry_DisableOnCondition(&ME_RENDERERSETUP_PRECACHE, !hw_hightile);
|
|
# ifdef USE_GLEXT
|
|
MenuEntry_DisableOnCondition(&ME_RENDERERSETUP_DETAILTEX, !hw_hightile);
|
|
MenuEntry_DisableOnCondition(&ME_RENDERERSETUP_GLOWTEX, !hw_hightile);
|
|
# endif
|
|
break;
|
|
#endif
|
|
|
|
case MENU_VIDEOSETUP:
|
|
{
|
|
const int32_t nr = newresolution;
|
|
|
|
// don't allow setting fullscreen mode if it's not supported by the resolution
|
|
MenuEntry_DisableOnCondition(&ME_VIDEOSETUP_FULLSCREEN, !(resolution[nr].flags & RES_FS));
|
|
|
|
MenuEntry_DisableOnCondition(&ME_VIDEOSETUP_APPLY,
|
|
(xres == resolution[nr].xdim && yres == resolution[nr].ydim &&
|
|
videoGetRenderMode() == newrendermode && fullscreen == newfullscreen
|
|
&& vid_vsync == newvsync
|
|
)
|
|
|| (newrendermode != REND_CLASSIC && resolution[nr].bppmax <= 8));
|
|
|
|
break;
|
|
}
|
|
|
|
case MENU_SOUND:
|
|
case MENU_SOUND_INGAME:
|
|
case MENU_ADVSOUND:
|
|
MenuEntry_DisableOnCondition(&ME_SOUND_VOLUME_FX, !snd_enabled);
|
|
MenuEntry_DisableOnCondition(&ME_SOUND_VOLUME_MUSIC, !mus_enabled);
|
|
MenuEntry_DisableOnCondition(&ME_SOUND_DUKETALK, !snd_enabled);
|
|
MenuEntry_DisableOnCondition(&ME_SOUND_SAMPLINGRATE, !snd_enabled && !mus_enabled);
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
MenuEntry_DisableOnCondition(&ME_SOUND_NUMVOICES, !snd_enabled);
|
|
#endif
|
|
MenuEntry_DisableOnCondition(&ME_SOUND_RESTART, soundrate == snd_mixrate &&
|
|
soundvoices == snd_numvoices);
|
|
break;
|
|
|
|
case MENU_SAVESETUP:
|
|
MenuEntry_DisableOnCondition(&ME_SAVESETUP_MAXAUTOSAVES, !cl_autosavedeletion);
|
|
break;
|
|
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
case MENU_MOUSESETUP:
|
|
MenuEntry_DisableOnCondition(&ME_MOUSESETUP_MOUSEAIMING, in_aimmode);
|
|
break;
|
|
#endif
|
|
case MENU_NETOPTIONS:
|
|
if (MEOSV_NetEpisodes[MEO_NETOPTIONS_EPISODE.currentOption] == MAXVOLUMES)
|
|
MEL_NETOPTIONS[2] = &ME_NETOPTIONS_USERMAP;
|
|
else
|
|
{
|
|
MEL_NETOPTIONS[2] = &ME_NETOPTIONS_LEVEL;
|
|
MEO_NETOPTIONS_LEVEL.options = &MEOS_NETOPTIONS_LEVEL[MEOSV_NetEpisodes[MEO_NETOPTIONS_EPISODE.currentOption]];
|
|
}
|
|
if (!(g_gametypeFlags[ud.m_coop] & GAMETYPE_MARKEROPTION))
|
|
{
|
|
ME_NETOPTIONS_MARKERS.type = Dummy;
|
|
ME_NETOPTIONS_MARKERS.flags |= MEF_Disabled;
|
|
}
|
|
else
|
|
{
|
|
ME_NETOPTIONS_MARKERS.type = Option;
|
|
ME_NETOPTIONS_MARKERS.flags &= ~MEF_Disabled;
|
|
}
|
|
MEL_NETOPTIONS[5] = (g_gametypeFlags[ud.m_coop] & (GAMETYPE_PLAYERSFRIENDLY|GAMETYPE_TDM)) ? &ME_NETOPTIONS_FRFIRE : &ME_NETOPTIONS_MAPEXITS;
|
|
break;
|
|
|
|
case MENU_OPTIONS:
|
|
MenuEntry_DisableOnCondition(&ME_OPTIONS_PLAYERSETUP, ud.recstat == 1);
|
|
MenuEntry_HideOnCondition(&ME_OPTIONS_JOYSTICKSETUP, !in_joystick || CONTROL_JoyPresent == 0);
|
|
break;
|
|
|
|
case MENU_COLCORR:
|
|
case MENU_COLCORR_INGAME:
|
|
break;
|
|
|
|
case MENU_CHEATS:
|
|
case MENU_CHEATENTRY:
|
|
case MENU_CHEAT_WARP:
|
|
case MENU_CHEAT_SKILL:
|
|
{
|
|
const int32_t menucheatsdisabled = numplayers != 1 || !(g_player[myconnectindex].ps->gm & MODE_GAME);
|
|
|
|
// refresh display names of quote cheats
|
|
ME_CheatCodes[CHEATFUNC_QUOTEBETA].name = apStrings[QUOTE_CHEAT_BETA];
|
|
ME_CheatCodes[CHEATFUNC_QUOTETODD].name = apStrings[QUOTE_CHEAT_TODD];
|
|
ME_CheatCodes[CHEATFUNC_QUOTEALLEN].name = apStrings[QUOTE_CHEAT_ALLEN];
|
|
|
|
for (i = 0; i < NUMCHEATFUNCS; i++)
|
|
{
|
|
uint32_t cheatmask = cl_cheatmask & (1<<i);
|
|
|
|
#if 0
|
|
// KEEPINSYNC: NAM_WW2GI_CHEATS
|
|
if (NAM_WW2GI)
|
|
{
|
|
switch (i)
|
|
{
|
|
case CHEATFUNC_CASHMAN:
|
|
case CHEATFUNC_GIVEALLITEMS:
|
|
case CHEATFUNC_QUOTEBETA:
|
|
case CHEATFUNC_MONSTERS:
|
|
case CHEATFUNC_QUOTEALLEN:
|
|
case CHEATFUNC_GIVEKEYS:
|
|
cheatmask = 0;
|
|
break;
|
|
}
|
|
}
|
|
if (WW2GI)
|
|
{
|
|
switch (i)
|
|
{
|
|
case CHEATFUNC_HYPER:
|
|
cheatmask = 0;
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
MenuEntry_t & entry = ME_CheatCodes[i];
|
|
|
|
// only show cheats that have been typed in before and are not undefined
|
|
MenuEntry_HideOnCondition(&entry, !cheatmask || CheatStrings[CheatFunctionIDs[i]][0] == '\0');
|
|
|
|
// disable outside of a single-player game
|
|
MenuEntry_DisableOnCondition(&entry, menucheatsdisabled);
|
|
}
|
|
|
|
MenuEntry_DisableOnCondition(&ME_ENTERCHEAT, (cl_cheatmask == UINT32_MAX));
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static void Menu_PreDrawBackground(MenuID_t cm, const vec2_t origin)
|
|
{
|
|
switch (cm)
|
|
{
|
|
case MENU_CREDITS:
|
|
case MENU_CREDITS2:
|
|
case MENU_CREDITS3:
|
|
if (!VOLUMEALL || !PLUTOPAK || RR)
|
|
Menu_DrawBackground(origin);
|
|
else
|
|
rotatesprite_fs(origin.x + (MENU_MARGIN_CENTER<<16), origin.y + (100<<16), 65536L,0,2504+cm-MENU_CREDITS,0,0,10+64);
|
|
break;
|
|
|
|
case MENU_LOAD:
|
|
case MENU_SAVE:
|
|
case MENU_CREDITS4:
|
|
case MENU_CREDITS5:
|
|
case MENU_CREDITS6:
|
|
case MENU_CREDITS7:
|
|
case MENU_CREDITS8:
|
|
case MENU_CREDITS9:
|
|
case MENU_CREDITS10:
|
|
case MENU_CREDITS11:
|
|
case MENU_CREDITS12:
|
|
case MENU_CREDITS13:
|
|
case MENU_CREDITS14:
|
|
case MENU_CREDITS15:
|
|
case MENU_CREDITS16:
|
|
case MENU_CREDITS17:
|
|
case MENU_CREDITS18:
|
|
case MENU_CREDITS19:
|
|
case MENU_CREDITS20:
|
|
case MENU_CREDITS21:
|
|
case MENU_CREDITS22:
|
|
case MENU_CREDITS23:
|
|
case MENU_CREDITS24:
|
|
case MENU_CREDITS25:
|
|
case MENU_CREDITS26:
|
|
case MENU_CREDITS27:
|
|
case MENU_CREDITS28:
|
|
case MENU_CREDITS29:
|
|
case MENU_CREDITS30:
|
|
case MENU_CREDITS31:
|
|
case MENU_CREDITS32:
|
|
case MENU_CREDITS33:
|
|
Menu_DrawBackground(origin);
|
|
break;
|
|
|
|
case MENU_STORY:
|
|
rotatesprite_fs(origin.x + (MENU_MARGIN_CENTER<<16), origin.y + (100<<16), 65536L,0,TEXTSTORY,0,0,10+64);
|
|
break;
|
|
|
|
case MENU_F1HELP:
|
|
rotatesprite_fs(origin.x + (MENU_MARGIN_CENTER<<16), origin.y + (100<<16), 65536L,0,F1HELP,0,0,10+64);
|
|
break;
|
|
|
|
case MENU_F1HELP2:
|
|
rotatesprite_fs(origin.x + (MENU_MARGIN_CENTER<<16), origin.y + (100<<16), 65536L,0,RRTILE1636,0,0,10+64);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static void Menu_PreDraw(MenuID_t cm, MenuEntry_t *entry, const vec2_t origin)
|
|
{
|
|
int32_t i, j, l = 0;
|
|
|
|
switch (cm)
|
|
{
|
|
case MENU_MAIN_INGAME:
|
|
l += 4;
|
|
fallthrough__;
|
|
case MENU_MAIN:
|
|
if (RR)
|
|
{
|
|
if (RRRA)
|
|
rotatesprite_fs(origin.x + ((MENU_MARGIN_CENTER-5)<<16), origin.y + ((57+l)<<16), 16592L,0,THREEDEE,0,0,10);
|
|
else
|
|
rotatesprite_fs(origin.x + ((MENU_MARGIN_CENTER+5)<<16), origin.y + ((24+l)<<16), 23592L,0,INGAMEDUKETHREEDEE,0,0,10);
|
|
}
|
|
else
|
|
{
|
|
rotatesprite_fs(origin.x + (MENU_MARGIN_CENTER<<16), origin.y + ((28+l)<<16), 65536L,0,INGAMEDUKETHREEDEE,0,0,10);
|
|
if (PLUTOPAK) // JBF 20030804
|
|
rotatesprite_fs(origin.x + ((MENU_MARGIN_CENTER+100)<<16), origin.y + (36<<16), 65536L,0,PLUTOPAKSPRITE+2,(sintable[((int32_t) totalclock<<4)&2047]>>11),0,2+8);
|
|
}
|
|
break;
|
|
|
|
case MENU_CDPLAYER:
|
|
rotatesprite_fs(origin.x + (MENU_MARGIN_CENTER<<16), origin.y+(100<<16),32768L,0,CDPLAYER,16,0,10);
|
|
break;
|
|
|
|
case MENU_PLAYER:
|
|
if (RR)
|
|
rotatesprite_fs(origin.x + (260<<16), origin.y + ((24+(tilesiz[APLAYER].y>>2))<<16), 24576L,0,3845+36-((((8-((int32_t) totalclock>>4)))&7)*5),0,entry == &ME_PLAYER_TEAM ? G_GetTeamPalette(ud.team) : ud.color,10);
|
|
else
|
|
rotatesprite_fs(origin.x + (260<<16), origin.y + ((24+(tilesiz[APLAYER].y>>1))<<16), 49152L,0,1441-((((4-((int32_t) totalclock>>4)))&3)*5),0,entry == &ME_PLAYER_TEAM ? G_GetTeamPalette(ud.team) : ud.color,10);
|
|
break;
|
|
|
|
case MENU_MACROS:
|
|
mgametextcenter(origin.x, origin.y + (144<<16), "Activate in-game with Shift-F#");
|
|
break;
|
|
|
|
case MENU_COLCORR:
|
|
case MENU_COLCORR_INGAME:
|
|
// center panel
|
|
if (!RR)
|
|
rotatesprite_fs(origin.x + (120<<16), origin.y + (32<<16), 16384, 0, 3290, 0, 0, 2|8|16);
|
|
rotatesprite_fs(origin.x + (160<<16) - (tilesiz[BOTTOMSTATUSBAR].x<<(RR ? 12 : 13)), origin.y + (82<<16) - (tilesiz[BOTTOMSTATUSBAR].y<<14), RR ? 8192 : 16384, 0, BOTTOMSTATUSBAR, 0, 0, 2|8|16);
|
|
|
|
// left panel
|
|
rotatesprite_fs(origin.x + (40<<16), origin.y + (32<<16), 16384, 0, RR ? RRTILE403 : BONUSSCREEN, 0, 0, 2|8|16);
|
|
|
|
// right panel
|
|
rotatesprite_fs(origin.x + (200<<16), origin.y + (32<<16), 16384, 0, LOADSCREEN, 0, 0, 2|8|16);
|
|
break;
|
|
|
|
case MENU_NETSETUP:
|
|
case MENU_NETHOST:
|
|
mminitext(origin.x + (90<<16), origin.y + (90<<16), "Game Type", MF_Minifont.pal_deselected);
|
|
mminitext(origin.x + (90<<16), origin.y + ((90+8)<<16), "Episode", MF_Minifont.pal_deselected);
|
|
mminitext(origin.x + (90<<16), origin.y + ((90+8+8)<<16), "Level", MF_Minifont.pal_deselected);
|
|
mminitext(origin.x + (90<<16), origin.y + ((90+8+8+8)<<16), ME_NETOPTIONS_MONSTERS.name, MF_Minifont.pal_deselected);
|
|
if (ud.m_coop == 0)
|
|
mminitext(origin.x + (90<<16), origin.y + ((90+8+8+8+8)<<16), "Markers", MF_Minifont.pal_deselected);
|
|
else if (ud.m_coop == 1)
|
|
mminitext(origin.x + (90<<16), origin.y + ((90+8+8+8+8)<<16), "Friendly Fire", MF_Minifont.pal_deselected);
|
|
mminitext(origin.x + (90<<16), origin.y + ((90+8+8+8+8+8)<<16), "User Map", MF_Minifont.pal_deselected);
|
|
|
|
mminitext(origin.x + ((90+60)<<16), origin.y + (90<<16), g_gametypeNames[ud.m_coop], MF_Minifont.pal_deselected_right);
|
|
|
|
mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8)<<16), g_volumeNames[ud.m_volume_number], MF_Minifont.pal_deselected_right);
|
|
mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8)<<16), g_mapInfo[MAXLEVELS*ud.m_volume_number+ud.m_level_number].name, MF_Minifont.pal_deselected_right);
|
|
if (ud.m_monsters_off == 0 || ud.m_player_skill > 0)
|
|
mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8)<<16), g_skillNames[ud.m_player_skill], MF_Minifont.pal_deselected_right);
|
|
else mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8)<<16), "None", MF_Minifont.pal_deselected_right);
|
|
if (ud.m_coop == 0)
|
|
{
|
|
if (ud.m_marker) mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8+8)<<16), "On", MF_Minifont.pal_deselected_right);
|
|
else mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8+8)<<16), "Off", MF_Minifont.pal_deselected_right);
|
|
}
|
|
else if (ud.m_coop == 1)
|
|
{
|
|
if (ud.m_ffire) mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8+8)<<16), "On", MF_Minifont.pal_deselected_right);
|
|
else mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8+8)<<16), "Off", MF_Minifont.pal_deselected_right);
|
|
}
|
|
break;
|
|
|
|
case MENU_MOUSEADVANCED:
|
|
{
|
|
for (auto & i : MEL_INTERNAL_MOUSEADVANCED_DAXES)
|
|
if (entry == i)
|
|
{
|
|
mgametextcenter(origin.x, origin.y + (162<<16), "Digital axes are not for mouse look\n"
|
|
"or for aiming up and down");
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MENU_RESETPLAYER:
|
|
videoFadeToBlack(1);
|
|
Bsprintf(tempbuf, "Load last game:\n\"%s\""
|
|
#ifndef EDUKE32_ANDROID_MENU
|
|
"\n(Y/N)"
|
|
#endif
|
|
, g_quickload->name);
|
|
mgametextcenter(origin.x, origin.y + (90<<16), tempbuf);
|
|
break;
|
|
|
|
case MENU_LOAD:
|
|
{
|
|
#if 0
|
|
for (i = 0; i <= 108; i += 12)
|
|
rotatesprite_fs(origin.x + ((160+64+91-64)<<16), origin.y + ((i+56)<<16), 65536L,0,TEXTBOX,24,0,10);
|
|
#endif
|
|
Menu_BlackRectangle(origin.x + (198<<16), origin.y + (47<<16), 102<<16, 100<<16, 1|32);
|
|
|
|
rotatesprite_fs(origin.x + (22<<16), origin.y + (97<<16), 65536L,0,WINDOWBORDER2,24,0,10);
|
|
rotatesprite_fs(origin.x + (180<<16), origin.y + (97<<16), 65536L,1024,WINDOWBORDER2,24,0,10);
|
|
rotatesprite_fs(origin.x + (99<<16), origin.y + (50<<16), 65536L,512,WINDOWBORDER1,24,0,10);
|
|
rotatesprite_fs(origin.x + (103<<16), origin.y + (144<<16), 65536L,1024+512,WINDOWBORDER1,24,0,10);
|
|
|
|
if (M_LOAD.currentEntry >= (int32_t)g_nummenusaves)
|
|
{
|
|
menutext_centeralign(origin.x + (101<<16), origin.y + (97<<16), "Empty");
|
|
break;
|
|
}
|
|
|
|
menusave_t & msv = g_menusaves[M_LOAD.currentEntry];
|
|
|
|
if (msv.brief.isValid())
|
|
{
|
|
rotatesprite_fs(origin.x + (101<<16), origin.y + (97<<16), 65536>>1,512,TILE_LOADSHOT,-32,0,4+10+64);
|
|
|
|
if (msv.isOldVer)
|
|
{
|
|
menutext_centeralign(origin.x + (101<<16), origin.y + (97<<16), "Previous\nVersion");
|
|
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
Bsprintf(tempbuf,"Saved: %d.%d.%d.%u %d-bit", savehead.majorver, savehead.minorver,
|
|
savehead.bytever, savehead.userbytever, 8*savehead.getPtrSize());
|
|
mgametext(origin.x + (31<<16), origin.y + (104<<16), tempbuf);
|
|
Bsprintf(tempbuf,"Our: %d.%d.%d.%u %d-bit", SV_MAJOR_VER, SV_MINOR_VER, BYTEVERSION,
|
|
ud.userbytever, (int32_t)(8*sizeof(intptr_t)));
|
|
mgametext(origin.x + ((31+16)<<16), origin.y + (114<<16), tempbuf);
|
|
#endif
|
|
|
|
break;
|
|
}
|
|
|
|
if (savehead.numplayers > 1)
|
|
{
|
|
Bsprintf(tempbuf, "Players: %-2d ", savehead.numplayers);
|
|
mgametextcenter(origin.x, origin.y + (156<<16), tempbuf);
|
|
}
|
|
|
|
{
|
|
const char *name = g_mapInfo[(savehead.volnum*MAXLEVELS) + savehead.levnum].name;
|
|
Bsprintf(tempbuf, "%s / %s", name ? name : "^10unnamed^0", g_skillNames[savehead.skill-1]);
|
|
}
|
|
|
|
mgametextcenter(origin.x, origin.y + (168<<16), tempbuf);
|
|
if (savehead.volnum == 0 && savehead.levnum == 7)
|
|
mgametextcenter(origin.x, origin.y + (180<<16), savehead.boardfn);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case MENU_SAVE:
|
|
{
|
|
#if 0
|
|
for (i = 0; i <= 108; i += 12)
|
|
rotatesprite_fs(origin.x + ((160+64+91-64)<<16), origin.y + ((i+56)<<16), 65536L,0,TEXTBOX,24,0,10);
|
|
#endif
|
|
Menu_BlackRectangle(origin.x + (198<<16), origin.y + (47<<16), 102<<16, 100<<16, 1|32);
|
|
|
|
rotatesprite_fs(origin.x + (22<<16), origin.y + (97<<16), 65536L,0,WINDOWBORDER2,24,0,10);
|
|
rotatesprite_fs(origin.x + (180<<16), origin.y + (97<<16), 65536L,1024,WINDOWBORDER2,24,0,10);
|
|
rotatesprite_fs(origin.x + (99<<16), origin.y + (50<<16), 65536L,512,WINDOWBORDER1,24,0,10);
|
|
rotatesprite_fs(origin.x + (103<<16), origin.y + (144<<16), 65536L,1024+512,WINDOWBORDER1,24,0,10);
|
|
|
|
j = 0;
|
|
for (int k = 0; k < g_nummenusaves+1; ++k)
|
|
if (((MenuString_t*)M_SAVE.entrylist[k]->entry)->editfield)
|
|
j |= 1;
|
|
|
|
if (j)
|
|
rotatesprite_fs(origin.x + (101<<16), origin.y + (97<<16), 65536L>>1,512,TILE_SAVESHOT,-32,0,4+10+64);
|
|
else if (0 < M_SAVE.currentEntry && M_SAVE.currentEntry <= (int32_t)g_nummenusaves)
|
|
{
|
|
if (g_menusaves[M_SAVE.currentEntry-1].brief.isValid())
|
|
{
|
|
rotatesprite_fs(origin.x + (101<<16), origin.y + (97<<16), 65536L>>1,512,TILE_LOADSHOT,-32,0,4+10+64);
|
|
|
|
if (g_menusaves[M_SAVE.currentEntry-1].isOldVer)
|
|
{
|
|
menutext_centeralign(origin.x + (101<<16), origin.y + (97<<16), "Previous\nVersion");
|
|
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
Bsprintf(tempbuf,"Saved: %d.%d.%d.%u %d-bit", savehead.majorver, savehead.minorver,
|
|
savehead.bytever, savehead.userbytever, 8*savehead.getPtrSize());
|
|
mgametext(origin.x + (31<<16), origin.y + (104<<16), tempbuf);
|
|
Bsprintf(tempbuf,"Our: %d.%d.%d.%u %d-bit", SV_MAJOR_VER, SV_MINOR_VER, BYTEVERSION,
|
|
ud.userbytever, (int32_t)(8*sizeof(intptr_t)));
|
|
mgametext(origin.x + ((31+16)<<16), origin.y + (114<<16), tempbuf);
|
|
#endif
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
menutext_centeralign(origin.x + (101<<16), origin.y + (97<<16), "New");
|
|
|
|
if (ud.multimode > 1)
|
|
{
|
|
Bsprintf(tempbuf, "Players: %-2d ", ud.multimode);
|
|
mgametextcenter(origin.x, origin.y + (156<<16), tempbuf);
|
|
}
|
|
|
|
Bsprintf(tempbuf,"%s / %s",g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name, g_skillNames[ud.player_skill-1]);
|
|
mgametextcenter(origin.x, origin.y + (168<<16), tempbuf);
|
|
if (ud.volume_number == 0 && ud.level_number == 7)
|
|
mgametextcenter(origin.x, origin.y + (180<<16), currentboardfilename);
|
|
break;
|
|
}
|
|
|
|
#ifdef EDUKE32_ANDROID_MENU
|
|
case MENU_SKILL:
|
|
{
|
|
static const char *s[] = { "EASY - Few enemies, and lots of stuff.", "MEDIUM - Normal difficulty.", "HARD - For experienced players.", "EXPERTS - Lots of enemies, plus they respawn!" };
|
|
if (M_SKILL.currentEntry < ARRAY_SSIZE(s))
|
|
mgametextcenter(origin.x, origin.y + (168<<16), s[M_SKILL.currentEntry]);
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case MENU_SAVECLEANVERIFY:
|
|
videoFadeToBlack(1);
|
|
|
|
if (g_oldSaveCnt)
|
|
{
|
|
Bsprintf(tempbuf, "Delete %d obsolete saves?\nThis action cannot be undone."
|
|
#ifndef EDUKE32_ANDROID_MENU
|
|
"\n(Y/N)"
|
|
#endif
|
|
, g_oldSaveCnt);
|
|
}
|
|
else
|
|
Bsprintf(tempbuf, "No obsolete saves found!");
|
|
|
|
mgametextcenter(origin.x, origin.y + (90<<16), tempbuf);
|
|
break;
|
|
|
|
case MENU_LOADVERIFY:
|
|
{
|
|
videoFadeToBlack(1);
|
|
menusave_t & msv = g_menusaves[M_LOAD.currentEntry];
|
|
if (msv.isOldVer)
|
|
{
|
|
Bsprintf(tempbuf, "Start new game:\n%s / %s"
|
|
#ifndef EDUKE32_ANDROID_MENU
|
|
"\n(Y/N)"
|
|
#endif
|
|
, g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name, g_skillNames[ud.player_skill-1]);
|
|
mgametextcenter(origin.x, origin.y + (90<<16), tempbuf);
|
|
}
|
|
else
|
|
{
|
|
Bsprintf(tempbuf, "Load game:\n\"%s\""
|
|
#ifndef EDUKE32_ANDROID_MENU
|
|
"\n(Y/N)"
|
|
#endif
|
|
, msv.brief.name);
|
|
mgametextcenter(origin.x, origin.y + (90<<16), tempbuf);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case MENU_SAVEVERIFY:
|
|
videoFadeToBlack(1);
|
|
mgametextcenter(origin.x, origin.y + (90<<16), "Overwrite previous saved game?"
|
|
#ifndef EDUKE32_ANDROID_MENU
|
|
"\n(Y/N)"
|
|
#endif
|
|
);
|
|
break;
|
|
|
|
case MENU_LOADDELVERIFY:
|
|
case MENU_SAVEDELVERIFY:
|
|
{
|
|
videoFadeToBlack(1);
|
|
menusave_t & msv = cm == MENU_LOADDELVERIFY ? g_menusaves[M_LOAD.currentEntry] : g_menusaves[M_SAVE.currentEntry-1];
|
|
Bsprintf(tempbuf, "Delete saved game:\n\"%s\"?"
|
|
#ifndef EDUKE32_ANDROID_MENU
|
|
"\n(Y/N)"
|
|
#endif
|
|
, msv.brief.name);
|
|
mgametextcenter(origin.x, origin.y + (90<<16), tempbuf);
|
|
break;
|
|
}
|
|
|
|
case MENU_NEWVERIFY:
|
|
videoFadeToBlack(1);
|
|
mgametextcenter(origin.x, origin.y + (90<<16), "Abort this game?"
|
|
#ifndef EDUKE32_ANDROID_MENU
|
|
"\n(Y/N)"
|
|
#endif
|
|
);
|
|
break;
|
|
|
|
case MENU_QUIT:
|
|
case MENU_QUIT_INGAME:
|
|
videoFadeToBlack(1);
|
|
mgametextcenter(origin.x, origin.y + (90<<16), "Are you sure you want to quit?"
|
|
#ifndef EDUKE32_ANDROID_MENU
|
|
"\n(Y/N)"
|
|
#endif
|
|
);
|
|
break;
|
|
|
|
case MENU_QUITTOTITLE:
|
|
videoFadeToBlack(1);
|
|
mgametextcenter(origin.x, origin.y + (90<<16), "End game and return to title screen?"
|
|
#ifndef EDUKE32_ANDROID_MENU
|
|
"\n(Y/N)"
|
|
#endif
|
|
);
|
|
break;
|
|
|
|
case MENU_NETWAITMASTER:
|
|
G_DrawFrags();
|
|
mgametextcenter(origin.x, origin.y + (50<<16), "Waiting for master\n"
|
|
"to select level");
|
|
break;
|
|
|
|
case MENU_NETWAITVOTES:
|
|
G_DrawFrags();
|
|
mgametextcenter(origin.x, origin.y + (90<<16), "Waiting for votes");
|
|
break;
|
|
|
|
case MENU_BUYDUKE:
|
|
mgametextcenter(origin.x, origin.y + (33<<16), "You are playing the shareware\n"
|
|
"version of Duke Nukem 3D. While\n"
|
|
"this version is really cool, you\n"
|
|
"are missing over 75% of the total\n"
|
|
"game, along with other great extras\n"
|
|
"which you'll get when you order\n"
|
|
"the complete version and get\n"
|
|
"the final three episodes.");
|
|
|
|
mgametextcenter(origin.x, origin.y + ((148+16)<<16), "Press any key or button...");
|
|
break;
|
|
|
|
case MENU_CREDITS:
|
|
case MENU_CREDITS2:
|
|
case MENU_CREDITS3:
|
|
case MENU_CREDITS4:
|
|
case MENU_CREDITS5:
|
|
case MENU_CREDITS6:
|
|
case MENU_CREDITS7:
|
|
case MENU_CREDITS8:
|
|
case MENU_CREDITS9:
|
|
case MENU_CREDITS10:
|
|
case MENU_CREDITS11:
|
|
case MENU_CREDITS12:
|
|
case MENU_CREDITS13:
|
|
case MENU_CREDITS14:
|
|
case MENU_CREDITS15:
|
|
case MENU_CREDITS16:
|
|
case MENU_CREDITS17:
|
|
case MENU_CREDITS18:
|
|
case MENU_CREDITS19:
|
|
case MENU_CREDITS20:
|
|
case MENU_CREDITS21:
|
|
case MENU_CREDITS22:
|
|
case MENU_CREDITS23:
|
|
case MENU_CREDITS24:
|
|
case MENU_CREDITS25:
|
|
case MENU_CREDITS26:
|
|
case MENU_CREDITS27:
|
|
case MENU_CREDITS28:
|
|
case MENU_CREDITS29:
|
|
case MENU_CREDITS30:
|
|
if (RR)
|
|
{
|
|
if (RRRA)
|
|
{
|
|
switch (cm)
|
|
{
|
|
case MENU_CREDITS:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "ORIGINAL CONCEPT, DESIGN AND DIRECTION\n\n"
|
|
"DREW MARKHAM");
|
|
break;
|
|
|
|
case MENU_CREDITS2:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "ART DIRECTION AND ADDITIONAL DESIGN\n\n"
|
|
"CORKY LEHMKUHL");
|
|
break;
|
|
|
|
case MENU_CREDITS3:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "PRODUCED BY\n\n"
|
|
"GREG GOODRICH");
|
|
break;
|
|
|
|
case MENU_CREDITS4:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "GAME PROGRAMMING\n\n"
|
|
"JOSEPH AURILI");
|
|
break;
|
|
|
|
case MENU_CREDITS5:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "ORIGINAL GAME PROGRAMMING\n\n"
|
|
"RAFAEL PAIZ");
|
|
break;
|
|
|
|
case MENU_CREDITS6:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "LEVEL DESIGN\n\n"
|
|
"RHETT BALDWIN & AARON BARBER");
|
|
break;
|
|
|
|
case MENU_CREDITS7:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "ORIGINAL ART DIRECTION AND SUPPORT\n\n"
|
|
"MAXX KAUFMAN & CLAIRE PRADERIE-MARKHAM");
|
|
break;
|
|
|
|
case MENU_CREDITS8:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "COMPUTER GRAPHICS SUPERVISOR &\n"
|
|
"CHARACTER ANIMATION DIRECTION\n\n"
|
|
"BARRY DEMPSEY");
|
|
break;
|
|
|
|
case MENU_CREDITS9:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "SENIOR ANIMATOR & MODELER\n\n"
|
|
"JASON HOOVER");
|
|
break;
|
|
|
|
case MENU_CREDITS10:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "CHARACTER ANIMATION &\n"
|
|
"MOTION CAPTURE SPECIALIST\n\n"
|
|
"AMIT DORON");
|
|
break;
|
|
|
|
case MENU_CREDITS11:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "SOUND DESIGN &\n"
|
|
"MUSIC PRODUCTION COORDINATION\n\n"
|
|
"GARY BRADFIELD");
|
|
break;
|
|
|
|
case MENU_CREDITS12:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "INTRODUCTION ANIMATION\n\n"
|
|
"DOMINIQUE DROZDZ");
|
|
break;
|
|
|
|
case MENU_CREDITS13:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "ARTIST\n\n"
|
|
"MATTHIAS BEEGUER");
|
|
break;
|
|
|
|
case MENU_CREDITS14:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "ADDITIONAL ART\n\n"
|
|
"VIKTOR ANTONOV");
|
|
break;
|
|
|
|
case MENU_CREDITS15:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "PRODUCTION COORDINATOR\n\n"
|
|
"VICTORIA SYLVESTER");
|
|
break;
|
|
|
|
case MENU_CREDITS16:
|
|
mgametextcenter(origin.x, origin.y + (40<<16), "CHARACTER VOICES\n\n"
|
|
"LEONARD\n"
|
|
"BURTON GILLIAM\n\n"
|
|
"DAISY MAE\n"
|
|
"TARA CHARENDOFF\n\n"
|
|
"BUBBA, BILLY RAY, SKINNY OL' COOT,\n"
|
|
"FRANK THE BIKER, THE TURD MINION\n"
|
|
"& ALL OTHER VARIOUS RAMBLINGS...\n"
|
|
"DREW MARKHAM");
|
|
break;
|
|
|
|
case MENU_CREDITS17:
|
|
mgametextcenter(origin.x, origin.y + (70<<16), "SPECIAL APPEARENCE BY\n\n"
|
|
"SHERIFF LESTER T. HOBBES\n"
|
|
"MOJO NIXON\n\n"
|
|
"ALIEN VIXEN\n"
|
|
"PEGGY JO JACOBS");
|
|
break;
|
|
|
|
case MENU_CREDITS18:
|
|
mgametextcenter(origin.x, origin.y + (70<<16), "REDNECK RAMPAGE TITLE TRACK & CYBERSEX\n"
|
|
"WRITTEN & PERFORMED BY\n"
|
|
"MOJO NIXON\n\n"
|
|
"(c) MUFFIN'STUFFIN' MUSIC (BMI)\n"
|
|
"ADMINISTERED BY BUG.");
|
|
break;
|
|
|
|
case MENU_CREDITS19:
|
|
mgametextcenter(origin.x, origin.y + (60<<16), "MUSIC\n\n"
|
|
"DISGRACELAND\n"
|
|
"TINY D & THE SOFA KINGS\n\n"
|
|
"BANJO AND GUITAR PICKIN\n"
|
|
"JOHN SCHLOCKER\n"
|
|
"HOWARD YEARWOOD");
|
|
break;
|
|
|
|
case MENU_CREDITS20:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "RECORDING ENGINEER\n"
|
|
"DAVE AHLERT\n\n"
|
|
"RECORDING ASSISTANCE\n"
|
|
"JEFF GILBERT");
|
|
break;
|
|
|
|
case MENU_CREDITS21:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "MOTION CAPTURE ACTOR\n"
|
|
"J.P. MANOUX\n\n"
|
|
"MOTION CAPTURE ACTRESS\n"
|
|
"SHAWN WOLFE");
|
|
break;
|
|
|
|
case MENU_CREDITS22:
|
|
mgametextcenter(origin.x, origin.y + (50<<16), "THIS GAME COULD NOT HAVE BEEN MADE WITHOUT\n"
|
|
"ALEX MAYBERRY\n"
|
|
"MAL BLACKWELL\n\n"
|
|
"NUTS AND BOLTS\n"
|
|
"STEVE GOLDBERG\n\n"
|
|
"BEAN COUNTING\n"
|
|
"MAX YOSHIKAWA\n\n"
|
|
"ADMINISTRATIVE ASSISTANCE\n"
|
|
"MINERVA MAYBERRY");
|
|
break;
|
|
|
|
case MENU_CREDITS23:
|
|
mgametextcenter(origin.x, origin.y + (60<<16), "FOR INTERPLAY\n\n"
|
|
"PRODUCER\n"
|
|
"BILL DUGAN\n\n"
|
|
"LINE PRODUCER\n"
|
|
"CHRIS BENSON\n\n"
|
|
"LEAD TESTER\n"
|
|
"DARRELL JONES");
|
|
break;
|
|
|
|
case MENU_CREDITS24:
|
|
mgametextcenter(origin.x, origin.y + (70<<16), "TESTERS\n\n"
|
|
"TIM ANDERSON\n"
|
|
"PRIMO PULANCO\n"
|
|
"MARK MCCARTY\n"
|
|
"BRIAN AXLINE");
|
|
break;
|
|
|
|
case MENU_CREDITS25:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "PRODUCTION BABY\n\n"
|
|
"PAULINE MARIE MARKHAM");
|
|
break;
|
|
|
|
case MENU_CREDITS26:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "ORIGINAL PRODUCTION BABY\n\n"
|
|
"ALYSON KAUFMAN");
|
|
break;
|
|
|
|
case MENU_CREDITS27:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "3D BUILD ENGINE LICENSED FROM\n"
|
|
"3D REALMS ENTERTAINMENT\n\n"
|
|
"BUILD ENGINE AND RELATED TOOLS\n"
|
|
"CREATED BY KEN SILVERMAN");
|
|
break;
|
|
|
|
case MENU_CREDITS28:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "SPECIAL THANKS\n\n"
|
|
"SCOTT MILLER\n"
|
|
"GEORGE BROUSSARD");
|
|
break;
|
|
|
|
case MENU_CREDITS29:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "EXTRA SPECIAL THANKS\n\n"
|
|
"BRIAN FARGO");
|
|
break;
|
|
|
|
case MENU_CREDITS30:
|
|
mgametextcenter(origin.x, origin.y + (70<<16), "REDNECK RAMPAGE RIDES AGAIN\n"
|
|
"(c) 1998 XATRIX ENTERTAINMENT, INC.\n\n"
|
|
"REDNECK RAMPAGE RIDES AGAIN\n"
|
|
"IS A TRADEMARK OF\n"
|
|
"INTERPLAY PRODUCTIONS");
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (cm)
|
|
{
|
|
case MENU_CREDITS:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "ORIGINAL CONCEPT, DESIGN AND DIRECTION\n\n"
|
|
"DREW MARKHAM");
|
|
break;
|
|
|
|
case MENU_CREDITS2:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "PRODUCED BY\n\n"
|
|
"GREG GOODRICH");
|
|
break;
|
|
|
|
case MENU_CREDITS3:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "GAME PROGRAMMING\n\n"
|
|
"RAFAEL PAIZ");
|
|
break;
|
|
|
|
case MENU_CREDITS4:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "ART DIRECTORS\n\n"
|
|
"CLAIRE PRADERIE MAXX KAUFMAN ");
|
|
break;
|
|
|
|
case MENU_CREDITS5:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "LEAD LEVEL DESIGNER\n"
|
|
"ALEX MAYBERRY\n\n"
|
|
"LEVEL DESIGN\n"
|
|
"MAL BLACKWELL\n"
|
|
"SVERRE KVERNMO");
|
|
break;
|
|
|
|
case MENU_CREDITS6:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "SENIOR ANIMATOR AND ARTIST\n\n"
|
|
"JASON HOOVER");
|
|
break;
|
|
|
|
case MENU_CREDITS7:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "TECHNICAL DIRECTOR\n\n"
|
|
"BARRY DEMPSEY");
|
|
break;
|
|
|
|
case MENU_CREDITS8:
|
|
mgametextcenter(origin.x, origin.y + (60<<16), "MOTION CAPTURE SPECIALIST AND\n"
|
|
"CHARACTER ANIMATION\n"
|
|
"AMIT DORON\n\n"
|
|
"A.I. PROGRAMMING\n"
|
|
"ARTHUR DONAVAN\n\n"
|
|
"ADDITIONAL ANIMATION\n"
|
|
"GEORGE KARL");
|
|
break;
|
|
|
|
case MENU_CREDITS9:
|
|
mgametextcenter(origin.x, origin.y + (50<<16), "CHARACTER DESIGN\n"
|
|
"CORKY LEHMKUHL\n\n"
|
|
"MAP PAINTERS\n"
|
|
"VIKTOR ANTONOV\n"
|
|
"MATTHIAS BEEGUER\n"
|
|
"STEPHAN BURLE\n\n"
|
|
"SCULPTORS\n"
|
|
"GEORGE ENGEL\n"
|
|
"JAKE GARBER\n"
|
|
"JEFF HIMMEL");
|
|
break;
|
|
|
|
case MENU_CREDITS10:
|
|
mgametextcenter(origin.x, origin.y + (40<<16), "CHARACTER VOICES\n\n"
|
|
"LEONARD\n"
|
|
"BURTON GILLIAM\n\n"
|
|
"BUBBA, BILLY RAY, SKINNY OL' COOT\n"
|
|
"AND THE TURD MINION\n"
|
|
"DREW MARKHAM\n\n"
|
|
"SHERIFF LESTER T. HOBBES\n"
|
|
"MOJO NIXON\n\n"
|
|
"ALIEN VIXEN\n"
|
|
"PEGGY JO JACOBS");
|
|
break;
|
|
|
|
case MENU_CREDITS11:
|
|
mgametextcenter(origin.x, origin.y + (50<<16), "SOUND DESIGN\n"
|
|
"GARY BRADFIELD\n\n"
|
|
"MUSIC\n"
|
|
"MOJO NIXON\n"
|
|
"THE BEAT FARMERS\n"
|
|
"THE REVEREND HORTON HEAT\n"
|
|
"CEMENT POND\n\n"
|
|
"ADDITIONAL SOUND EFFECTS\n"
|
|
"JIM SPURGIN");
|
|
break;
|
|
|
|
case MENU_CREDITS12:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "MOTION CAPTURE ACTOR\n"
|
|
"J.P. MANOUX\n\n"
|
|
"MOTION CAPTURE VIXEN\n"
|
|
"SHAWN WOLFE");
|
|
break;
|
|
|
|
case MENU_CREDITS13:
|
|
mgametextcenter(origin.x, origin.y + (50<<16), "PRODUCTION ASSISTANCE\n"
|
|
"MINERVA MAYBERRY\n\n"
|
|
"NUTS AND BOLTS\n"
|
|
"STEVE GOLDBERG\n"
|
|
"MARCUS HUTCHINSON\n\n"
|
|
"BEAN COUNTING\n"
|
|
"MAX YOSHIKAWA\n\n"
|
|
"ADMINISTRATIVE ASSISTANCE\n"
|
|
"SERAFIN LEWIS");
|
|
break;
|
|
|
|
case MENU_CREDITS14:
|
|
mgametextcenter(origin.x, origin.y + (70<<16), "LOCATION MANAGER, LOUISIANA\n"
|
|
"RICK SKINNER\n\n"
|
|
"LOCATION SCOUT, LOUISIANA\n"
|
|
"BRIAN BENOS\n\n"
|
|
"PHOTOGRAPHER\n"
|
|
"CARLOS SERRAO");
|
|
break;
|
|
|
|
case MENU_CREDITS15:
|
|
mgametextcenter(origin.x, origin.y + (50<<16), "ADDITIONAL 3D MODELING BY\n"
|
|
"3 NAME 3D\n"
|
|
"VIEWPOINT DATALABS INTERNATIONAL\n\n"
|
|
"AUDIO RECORDED AT\n"
|
|
"PACIFIC OCEAN POST, SANTA MONICA, C.A.\n\n"
|
|
"CEMENT POND TRACKS RECORDED AT\n"
|
|
"DREAMSTATE RECORDING, BURBANK, C.A.\n\n"
|
|
"RECORDING ENGINEER\n"
|
|
"DAVE AHLERT");
|
|
break;
|
|
|
|
case MENU_CREDITS16:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "3D BUILD ENGINE LICENSED FROM\n"
|
|
"3D REALMS ENTERTAINMENT\n\n"
|
|
"BUILD ENGINE AND RELATED TOOLS\n"
|
|
"CREATED BY KEN SILVERMAN");
|
|
break;
|
|
|
|
case MENU_CREDITS17:
|
|
mgametextcenter(origin.x, origin.y + (60<<16), "FOR INTERPLAY\n\n"
|
|
"LEAD TESTER\n"
|
|
"DARRELL JONES\n\n"
|
|
"TESTERS\n"
|
|
"TIM ANDERSON\n"
|
|
"ERICK LUJAN\n"
|
|
"TIEN TRAN");
|
|
break;
|
|
|
|
case MENU_CREDITS18:
|
|
mgametextcenter(origin.x, origin.y + (60<<16), "IS TECHS\n"
|
|
"BILL DELK\n"
|
|
"AARON MEYERS\n\n"
|
|
"COMPATIBILITY TECHS\n"
|
|
"MARC DURAN\n"
|
|
"DAN FORSYTH\n"
|
|
"DEREK GIBBS\n"
|
|
"AARON OLAIZ\n"
|
|
"JACK PARKER");
|
|
break;
|
|
|
|
case MENU_CREDITS19:
|
|
mgametextcenter(origin.x, origin.y + (70<<16), "DIRECTOR OF COMPATIBILITY\n"
|
|
"PHUONG NGUYEN\n\n"
|
|
"ASSISTANT QA DIRECTOR\n"
|
|
"COLIN TOTMAN\n\n"
|
|
"QA DIRECTOR\n"
|
|
"CHAD ALLISON");
|
|
break;
|
|
|
|
case MENU_CREDITS20:
|
|
mgametextcenter(origin.x, origin.y + (50<<16), "INTERPLAY PRODUCER\n"
|
|
"BILL DUGAN\n\n"
|
|
"INTERPLAY LINE PRODUCER\n"
|
|
"CHRIS BENSON\n\n"
|
|
"PRODUCT MANAGER\n"
|
|
"JIM VEEVAERT\n\n"
|
|
"PUBLIC RELATIONS\n"
|
|
"ERIKA PRICE");
|
|
break;
|
|
|
|
case MENU_CREDITS21:
|
|
mgametextcenter(origin.x, origin.y + (60<<16), "SPECIAL THANKS\n\n"
|
|
"JIM GAUER\n"
|
|
"PAUL VAIS\n"
|
|
"SCOTT MILLER\n"
|
|
"TODD REPLOGLE\n"
|
|
"CHUCK BUECHE\n"
|
|
"CARTER LIPSCOMB\n"
|
|
"JOHN CONLEY\n"
|
|
"DON MAGGI");
|
|
break;
|
|
|
|
case MENU_CREDITS22:
|
|
mgametextcenter(origin.x, origin.y + (80<<16), "EXTRA SPECIAL THANKS\n\n"
|
|
"BRIAN FARGO");
|
|
break;
|
|
|
|
case MENU_CREDITS23:
|
|
mgametextcenter(origin.x, origin.y + (60<<16), "REDNECK RAMPAGE\n"
|
|
"(c) 1997 XATRIX ENTERTAINMENT, INC.\n\n"
|
|
"REDNECK RAMPAGE IS A TRADEMARK OF\n"
|
|
"INTERPLAY PRODUCTIONS");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (!VOLUMEALL || !PLUTOPAK)
|
|
{
|
|
int32_t m;
|
|
switch (cm)
|
|
{
|
|
case MENU_CREDITS:
|
|
m = origin.x + (20<<16);
|
|
l = origin.y + (33<<16);
|
|
|
|
shadowminitext(m, l, "Original Concept", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Todd Replogle and Allen H. Blum III", 12); l += 7<<16;
|
|
l += 3<<16;
|
|
shadowminitext(m, l, "Produced & Directed By", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Greg Malone", 12); l += 7<<16;
|
|
l += 3<<16;
|
|
shadowminitext(m, l, "Executive Producer", 12); l += 7<<16;
|
|
shadowminitext(m, l, "George Broussard", 12); l += 7<<16;
|
|
l += 3<<16;
|
|
shadowminitext(m, l, "BUILD Engine", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Ken Silverman", 12); l += 7<<16;
|
|
l += 3<<16;
|
|
shadowminitext(m, l, "Game Programming", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Todd Replogle", 12); l += 7<<16;
|
|
l += 3<<16;
|
|
shadowminitext(m, l, "3D Engine/Tools/Net", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Ken Silverman", 12); l += 7<<16;
|
|
l += 3<<16;
|
|
shadowminitext(m, l, "Network Layer/Setup Program", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Mark Dochtermann", 12); l += 7<<16;
|
|
l += 3<<16;
|
|
shadowminitext(m, l, "Map Design", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Allen H. Blum III", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Richard Gray", 12); l += 7<<16;
|
|
|
|
m = origin.x + (180<<16);
|
|
l = origin.y + (33<<16);
|
|
|
|
shadowminitext(m, l, "3D Modeling", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Chuck Jones", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Sapphire Corporation", 12); l += 7<<16;
|
|
l += 3<<16;
|
|
shadowminitext(m, l, "Artwork", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Dirk Jones, Stephen Hornback", 12); l += 7<<16;
|
|
shadowminitext(m, l, "James Storey, David Demaret", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Douglas R. Wood", 12); l += 7<<16;
|
|
l += 3<<16;
|
|
shadowminitext(m, l, "Sound Engine", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Jim Dose", 12); l += 7<<16;
|
|
l += 3<<16;
|
|
shadowminitext(m, l, "Sound & Music Development", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Robert Prince", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Lee Jackson", 12); l += 7<<16;
|
|
l += 3<<16;
|
|
shadowminitext(m, l, "Voice Talent", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Lani Minella - Voice Producer", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Jon St. John as \"Duke Nukem\"", 12); l += 7<<16;
|
|
l += 3<<16;
|
|
shadowminitext(m, l, "Graphic Design", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Packaging, Manual, Ads", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Robert M. Atkins", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Michael Hadwin", 12); l += 7<<16;
|
|
break;
|
|
|
|
case MENU_CREDITS2:
|
|
m = origin.x + (20<<16);
|
|
l = origin.y + (33<<16);
|
|
|
|
shadowminitext(m, l, "Special Thanks To", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Steven Blackburn, Tom Hall", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Scott Miller, Joe Siegler", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Terry Nagy, Colleen Compton", 12); l += 7<<16;
|
|
shadowminitext(m, l, "HASH, Inc., FormGen, Inc.", 12); l += 7<<16;
|
|
l += 3<<16;
|
|
shadowminitext(m, l, "The 3D Realms Beta Testers", 12); l += 7<<16;
|
|
l += 3<<16;
|
|
shadowminitext(m, l, "Nathan Anderson, Wayne Benner", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Glenn Brensinger, Rob Brown", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Erik Harris, Ken Heckbert", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Terry Herrin, Greg Hively", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Hank Leukart, Eric Baker", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Jeff Rausch, Kelly Rogers", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Mike Duncan, Doug Howell", 12); l += 7<<16;
|
|
shadowminitext(m, l, "Bill Blair", 12); l += 7<<16;
|
|
|
|
m = origin.x + (160<<16);
|
|
l = origin.y + (33<<16);
|
|
|
|
shadowminitext(m, l, "Company Product Support", 12); l += 7<<16;
|
|
l += 3<<16;
|
|
shadowminitext(m, l, "The following companies were cool", 12); l += 7<<16;
|
|
shadowminitext(m, l, "enough to give us lots of stuff", 12); l += 7<<16;
|
|
shadowminitext(m, l, "during the making of Duke Nukem 3D.", 12); l += 7<<16;
|
|
l += 3<<16;
|
|
shadowminitext(m, l, "Altec Lansing Multimedia", 12); l += 7<<16;
|
|
shadowminitext(m, l, "for tons of speakers and the", 12); l += 7<<16;
|
|
shadowminitext(m, l, "THX-licensed sound system.", 12); l += 7<<16;
|
|
shadowminitext(m, l, "For info call 1-800-548-0620", 12); l += 7<<16;
|
|
l += 3<<16;
|
|
shadowminitext(m, l, "Creative Labs, Inc.", 12); l += 7<<16;
|
|
l += 3<<16;
|
|
shadowminitext(m, l, "Thanks for the hardware, guys.", 12); l += 7<<16;
|
|
break;
|
|
|
|
case MENU_CREDITS3:
|
|
mgametextcenter(origin.x, origin.y + (50<<16), "Duke Nukem 3D is a trademark of\n"
|
|
"3D Realms Entertainment"
|
|
"\n"
|
|
"Duke Nukem 3D\n"
|
|
"(C) 1996 3D Realms Entertainment");
|
|
|
|
if (VOLUMEONE)
|
|
{
|
|
mgametextcenter(origin.x, origin.y + (106<<16), "Please read LICENSE.DOC for shareware\n"
|
|
"distribution grants and restrictions.");
|
|
}
|
|
mgametextcenter(origin.x, origin.y + ((VOLUMEONE?134:115)<<16), "Made in Dallas, Texas USA");
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MENU_CREDITS31:
|
|
l = 7;
|
|
|
|
mgametextcenter(origin.x, origin.y + ((55-l)<<16), "Developer");
|
|
creditsminitext(origin.x + (160<<16), origin.y + ((60+10-l)<<16), "Alexey \"Nuke.YKT\" Skrybykin", 8);
|
|
|
|
mgametextcenter(origin.x, origin.y + ((85-l)<<16), "Tester & support");
|
|
creditsminitext(origin.x + (160<<16), origin.y + ((90+10-l)<<16), "Sergey \"Maxi Clouds\" Skrybykin", 8);
|
|
|
|
mgametextcenter(origin.x, origin.y + ((115-l)<<16), "Special thanks to");
|
|
creditsminitext(origin.x + (160<<16), origin.y + ((120+10-l)<<16), "Evan \"Hendricks266\" Ramos", 8);
|
|
creditsminitext(origin.x + (160<<16), origin.y + ((120+20-l)<<16), "Richard \"TerminX\" Gobeille", 8);
|
|
creditsminitext(origin.x + (160<<16), origin.y + ((120+30-l)<<16), "\"NY00123\"", 8);
|
|
creditsminitext(origin.x + (160<<16), origin.y + ((120+40-l)<<16), "\"MetHy\"", 8);
|
|
|
|
break;
|
|
|
|
case MENU_CREDITS32: // JBF 20031220
|
|
l = 7;
|
|
|
|
mgametextcenter(origin.x, origin.y + ((50-l)<<16), "Developers");
|
|
creditsminitext(origin.x + (160<<16), origin.y + ((50+10-l)<<16), "Richard \"TerminX\" Gobeille", 8);
|
|
creditsminitext(origin.x + (160<<16), origin.y + ((50+7+10-l)<<16), "Evan \"Hendricks266\" Ramos", 8);
|
|
|
|
mgametextcenter(origin.x, origin.y + ((80-l)<<16), "Retired developers");
|
|
creditsminitext(origin.x + (160<<16), origin.y + ((80+10-l)<<16), "Pierre-Loup \"Plagman\" Griffais", 8);
|
|
creditsminitext(origin.x + (160<<16), origin.y + ((80+7+10-l)<<16), "Philipp \"Helixhorned\" Kutin", 8);
|
|
|
|
mgametextcenter(origin.x, origin.y + ((130+7-l)<<16), "Special thanks to");
|
|
creditsminitext(origin.x + (160<<16), origin.y + ((130+7+10-l)<<16), "Jonathon \"JonoF\" Fowler", 8);
|
|
|
|
mgametextcenter(origin.x, origin.y + ((150+7-l)<<16), "Uses BUILD Engine technology by");
|
|
creditsminitext(origin.x + (160<<16), origin.y + ((150+7+10-l)<<16), "Ken \"Awesoken\" Silverman", 8);
|
|
|
|
|
|
break;
|
|
|
|
case MENU_CREDITS33:
|
|
l = 7;
|
|
|
|
mgametextcenter(origin.x, origin.y + ((38-l)<<16), "License and Other Contributors");
|
|
{
|
|
static const char *header[] =
|
|
{
|
|
"This program is distributed under the terms of the",
|
|
"GNU General Public License version 2 as published by the",
|
|
"Free Software Foundation. See gpl-2.0.txt for details.",
|
|
"BUILD engine technology available under license. See buildlic.txt.",
|
|
nullptr,
|
|
"The EDuke32 team thanks the following people for their contributions:",
|
|
nullptr,
|
|
};
|
|
static const char *body[] =
|
|
{
|
|
"Alex Dawson", // "pogokeen" - Polymost2, renderer work, bugfixes
|
|
"Bioman", // GTK work, APT repository and package upkeep
|
|
"Brandon Bergren", // "Bdragon" - tiles.cfg
|
|
"Charlie Honig", // "CONAN" - showview command
|
|
"Dan Gaskill", // "DeeperThought" - testing
|
|
"David Koenig", // "Bargle" - Merged a couple of things from duke3d_w32
|
|
"Ed Coolidge", // Mapster32 improvements
|
|
"Emile Belanger", // original Android work
|
|
"Fox", // various patches
|
|
"Hunter_rus", // tons of stuff
|
|
"James Bentler", // Mapster32 improvements
|
|
"Jasper Foreman", // netcode contributions
|
|
"Javier Martinez", // "Malone3D" - EDuke 2.1.1 components
|
|
"Jeff Hart", // website graphics
|
|
"Jonathan Strander", // "Mblackwell" - testing and feature speccing
|
|
"Jordon Moss", // "Striker" - various patches, OldMP work
|
|
"Jose del Castillo", // "Renegado" - EDuke 2.1.1 components
|
|
"Lachlan McDonald", // official EDuke32 icon
|
|
"LSDNinja", // OS X help and testing
|
|
"Marcus Herbert", // "rhoenie" - OS X compatibility work
|
|
"Matthew Palmer", // "Usurper" - testing and eduke32.com domain
|
|
"Matt Saettler", // original DOS EDuke/WW2GI enhancements
|
|
"NY00123", // Linux / SDL usability patches
|
|
"Ozkan Sezer", // SDL/GTK version checking improvements
|
|
"Peter Green", // "Plugwash" - dynamic remapping, custom gametypes
|
|
"Peter Veenstra", // "Qbix" - port to 64-bit
|
|
"Robin Green", // CON array support
|
|
"Ryan Gordon", // "icculus" - icculus.org Duke3D port sound code
|
|
"Stephen Anthony", // early 64-bit porting work
|
|
"tueidj", // Wii port
|
|
};
|
|
EDUKE32_STATIC_ASSERT(ARRAY_SIZE(body) % 3 == 0);
|
|
static const char *footer[] =
|
|
{
|
|
nullptr,
|
|
"Visit eduke32.com for news and updates",
|
|
};
|
|
|
|
static constexpr int header_numlines = ARRAY_SIZE(header);
|
|
static constexpr int body_numlines = ARRAY_SIZE(body);
|
|
static constexpr int footer_numlines = ARRAY_SIZE(footer);
|
|
|
|
static constexpr int CCOLUMNS = 3;
|
|
static constexpr int CCOLXBUF = 20;
|
|
|
|
int c;
|
|
i = 0;
|
|
for (c = 0; c < header_numlines; c++)
|
|
if (header[c])
|
|
creditsminitext(origin.x + (160<<16), origin.y + ((17+10+10+8+4+(c*7)-l)<<16), header[c], 8);
|
|
i += c;
|
|
for (c = 0; c < body_numlines; c++)
|
|
if (body[c])
|
|
creditsminitext(origin.x + ((CCOLXBUF+((320-CCOLXBUF*2)/(CCOLUMNS*2)) +((320-CCOLXBUF*2)/CCOLUMNS)*(c/(body_numlines/CCOLUMNS)))<<16), origin.y + ((17+10+10+8+4+((c%(body_numlines/CCOLUMNS))*7)+(i*7)-l)<<16), body[c], 8);
|
|
i += c/CCOLUMNS;
|
|
for (c = 0; c < footer_numlines; c++)
|
|
if (footer[c])
|
|
creditsminitext(origin.x + (160<<16), origin.y + ((17+10+10+8+4+(c*7)+(i*7)-l)<<16), footer[c], 8);
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static void Menu_ReadSaveGameHeaders();
|
|
|
|
static void Menu_LoadReadHeaders()
|
|
{
|
|
Menu_ReadSaveGameHeaders();
|
|
|
|
for (int i = 0; i < g_nummenusaves; ++i)
|
|
MenuEntry_DisableOnCondition(&ME_LOAD[i], g_menusaves[i].isOldVer);
|
|
}
|
|
|
|
static void Menu_SaveReadHeaders()
|
|
{
|
|
Menu_ReadSaveGameHeaders();
|
|
|
|
for (int i = 0; i < g_nummenusaves; ++i)
|
|
MenuEntry_LookDisabledOnCondition(&ME_SAVE[i], g_menusaves[i].isOldVer);
|
|
}
|
|
|
|
static void Menu_PreInput(MenuEntry_t *entry)
|
|
{
|
|
switch (g_currentMenu)
|
|
{
|
|
|
|
case MENU_KEYBOARDKEYS:
|
|
if (inputState.GetKeyStatus(sc_Delete))
|
|
{
|
|
Bindings.UnbindACommand(buttonMap.GetButtonName(M_KEYBOARDKEYS.currentEntry));
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
inputState.ClearKeyStatus(sc_Delete);
|
|
}
|
|
break;
|
|
|
|
case MENU_LOAD:
|
|
if (inputState.GetKeyStatus(sc_Delete))
|
|
{
|
|
inputState.ClearKeyStatus(sc_Delete);
|
|
if (M_LOAD.currentEntry < g_nummenusaves)
|
|
Menu_Change(MENU_LOADDELVERIFY);
|
|
}
|
|
break;
|
|
case MENU_SAVE:
|
|
if (inputState.GetKeyStatus(sc_Delete))
|
|
{
|
|
inputState.ClearKeyStatus(sc_Delete);
|
|
if (0 < M_SAVE.currentEntry && M_SAVE.currentEntry <= (int32_t)g_nummenusaves)
|
|
Menu_Change(MENU_SAVEDELVERIFY);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void Menu_PreOptionListDraw(MenuEntry_t *entry, const vec2_t origin)
|
|
{
|
|
switch (g_currentMenu)
|
|
{
|
|
case MENU_MOUSEBTNS:
|
|
case MENU_MOUSEADVANCED:
|
|
case MENU_JOYSTICKBTNS:
|
|
case MENU_JOYSTICKAXIS:
|
|
mgametextcenter(origin.x, origin.y + (31<<16), "Select a function to assign");
|
|
|
|
Bsprintf(tempbuf, "to %s", entry->name);
|
|
|
|
mgametextcenter(origin.x, origin.y + ((31+9)<<16), tempbuf);
|
|
|
|
mgametextcenter(origin.x, origin.y + (161<<16), "Press \"Escape\" To Cancel");
|
|
break;
|
|
}
|
|
}
|
|
|
|
static int32_t Menu_PreCustom2ColScreen(MenuEntry_t *entry)
|
|
{
|
|
if (g_currentMenu == MENU_KEYBOARDKEYS)
|
|
{
|
|
auto *column = (MenuCustom2Col_t*)entry->entry;
|
|
|
|
int32_t sc = inputState.GetLastScanCode();
|
|
if (sc != sc_None)
|
|
{
|
|
S_PlaySound(PISTOL_BODYHIT);
|
|
*column->column[M_KEYBOARDKEYS.currentColumn] = sc;
|
|
Bindings.SetBind(sc, buttonMap.GetButtonName(M_KEYBOARDKEYS.currentEntry));
|
|
inputState.ClearKeyStatus(sc);
|
|
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void Menu_PreCustom2ColScreenDraw(MenuEntry_t *entry, const vec2_t origin)
|
|
{
|
|
if (g_currentMenu == MENU_KEYBOARDKEYS)
|
|
{
|
|
Bsprintf(tempbuf, "Press the key to assign as\n"
|
|
"%s for \"%s\"\n"
|
|
"\n"
|
|
"Press \"Escape\" To Cancel"
|
|
, M_KEYBOARDKEYS.currentColumn?"secondary":"primary", entry->name);
|
|
mgametextcenter(origin.x, origin.y + (90<<16), tempbuf);
|
|
}
|
|
}
|
|
|
|
static void Menu_EntryFocus(/*MenuEntry_t *entry*/)
|
|
{
|
|
switch (g_currentMenu)
|
|
{
|
|
case MENU_LOAD:
|
|
if (M_LOAD.currentEntry < (int32_t)g_nummenusaves)
|
|
{
|
|
savebrief_t & sv = g_menusaves[M_LOAD.currentEntry].brief;
|
|
if (sv.isValid())
|
|
G_LoadSaveHeaderNew(sv.path, &savehead);
|
|
}
|
|
break;
|
|
|
|
case MENU_SAVE:
|
|
if (0 < M_SAVE.currentEntry && M_SAVE.currentEntry <= (int32_t)g_nummenusaves)
|
|
{
|
|
savebrief_t & sv = g_menusaves[M_SAVE.currentEntry-1].brief;
|
|
if (sv.isValid())
|
|
G_LoadSaveHeaderNew(sv.path, &savehead);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void Menu_StartGameWithoutSkill(void)
|
|
{
|
|
ud.m_player_skill = M_SKILL.currentEntry+1;
|
|
|
|
g_skillSoundVoice = S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
|
|
ud.m_respawn_monsters = 0;
|
|
|
|
ud.m_monsters_off = ud.monsters_off = 0;
|
|
|
|
ud.m_respawn_items = 0;
|
|
ud.m_respawn_inventory = 0;
|
|
|
|
ud.multimode = 1;
|
|
|
|
G_NewGame_EnterLevel();
|
|
}
|
|
|
|
static void Menu_DoCheat(int32_t cheatID)
|
|
{
|
|
if (numplayers != 1 || !(g_player[myconnectindex].ps->gm & MODE_GAME))
|
|
return;
|
|
|
|
osdcmd_cheatsinfo_stat.cheatnum = cheatID;
|
|
}
|
|
|
|
static int32_t Menu_Cheat_Warp(char const * const numbers)
|
|
{
|
|
if (numplayers != 1 || !(g_player[myconnectindex].ps->gm & MODE_GAME))
|
|
return 0;
|
|
|
|
if (numbers == NULL || !numbers[0] || !numbers[1] || (VOLUMEALL && !numbers[2]))
|
|
return 1;
|
|
|
|
if (VOLUMEALL)
|
|
{
|
|
osdcmd_cheatsinfo_stat.volume = numbers[0] - '0';
|
|
osdcmd_cheatsinfo_stat.level = (numbers[1] - '0')*10+(numbers[2]-'0');
|
|
}
|
|
else
|
|
{
|
|
osdcmd_cheatsinfo_stat.volume = numbers[0] - '0';
|
|
osdcmd_cheatsinfo_stat.level = numbers[1] - '0';
|
|
}
|
|
|
|
osdcmd_cheatsinfo_stat.volume--;
|
|
osdcmd_cheatsinfo_stat.level--;
|
|
|
|
if ((VOLUMEONE && osdcmd_cheatsinfo_stat.volume > 0) || osdcmd_cheatsinfo_stat.volume > g_volumeCnt-1 ||
|
|
osdcmd_cheatsinfo_stat.level >= MAXLEVELS || g_mapInfo[osdcmd_cheatsinfo_stat.volume *MAXLEVELS+osdcmd_cheatsinfo_stat.level].filename == NULL)
|
|
return 1;
|
|
|
|
osdcmd_cheatsinfo_stat.cheatnum = CHEAT_SCOTTY;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int32_t Menu_Cheat_Skill(char const * const number)
|
|
{
|
|
if (numplayers != 1 || !(g_player[myconnectindex].ps->gm & MODE_GAME))
|
|
return 0;
|
|
|
|
if (number == NULL || !number[0])
|
|
return 1;
|
|
|
|
osdcmd_cheatsinfo_stat.volume = number[0] - '1';
|
|
|
|
osdcmd_cheatsinfo_stat.cheatnum = CHEAT_SKILL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
Functions where a "newValue" or similar is passed are run *before* the linked variable is actually changed.
|
|
That way you can compare the new and old values and potentially block the change.
|
|
*/
|
|
static void Menu_EntryLinkActivate(MenuEntry_t *entry)
|
|
{
|
|
switch (g_currentMenu)
|
|
{
|
|
case MENU_EPISODE:
|
|
if (entry != &ME_EPISODE_USERMAP)
|
|
{
|
|
ud.m_volume_number = M_EPISODE.currentEntry;
|
|
ud.m_level_number = 0;
|
|
|
|
if (g_skillCnt == 0)
|
|
Menu_StartGameWithoutSkill();
|
|
}
|
|
break;
|
|
|
|
case MENU_SKILL:
|
|
{
|
|
int32_t skillsound = RR ? 341 : PISTOL_BODYHIT;
|
|
|
|
if (RR)
|
|
switch (M_SKILL.currentEntry)
|
|
{
|
|
case 0:
|
|
skillsound = 427;
|
|
break;
|
|
case 1:
|
|
skillsound = 428;
|
|
break;
|
|
case 2:
|
|
skillsound = 196;
|
|
break;
|
|
case 3:
|
|
skillsound = 195;
|
|
break;
|
|
case 4:
|
|
skillsound = 197;
|
|
break;
|
|
}
|
|
else
|
|
switch (M_SKILL.currentEntry)
|
|
{
|
|
case 0:
|
|
skillsound = JIBBED_ACTOR6;
|
|
break;
|
|
case 1:
|
|
skillsound = BONUS_SPEECH1;
|
|
break;
|
|
case 2:
|
|
skillsound = DUKE_GETWEAPON2;
|
|
break;
|
|
case 3:
|
|
skillsound = JIBBED_ACTOR5;
|
|
break;
|
|
}
|
|
|
|
ud.m_player_skill = M_SKILL.currentEntry+(RRRA ? 0 : 1);
|
|
|
|
g_skillSoundVoice = S_PlaySound(skillsound);
|
|
|
|
if (M_SKILL.currentEntry == 3) ud.m_respawn_monsters = 1;
|
|
else ud.m_respawn_monsters = 0;
|
|
|
|
ud.m_monsters_off = ud.monsters_off = 0;
|
|
|
|
ud.m_respawn_items = 0;
|
|
ud.m_respawn_inventory = 0;
|
|
|
|
ud.multimode = 1;
|
|
|
|
G_NewGame_EnterLevel();
|
|
break;
|
|
}
|
|
|
|
case MENU_JOYSTICKAXES:
|
|
M_JOYSTICKAXIS.title = joyGetName(0, M_JOYSTICKAXES.currentEntry);
|
|
MEO_JOYSTICKAXIS_ANALOG.data = &JoystickAnalogueAxes[M_JOYSTICKAXES.currentEntry];
|
|
MEO_JOYSTICKAXIS_SCALE.variable = &JoystickAnalogueScale[M_JOYSTICKAXES.currentEntry];
|
|
MEO_JOYSTICKAXIS_DEAD.variable = &JoystickAnalogueDead[M_JOYSTICKAXES.currentEntry];
|
|
MEO_JOYSTICKAXIS_SATU.variable = &JoystickAnalogueSaturate[M_JOYSTICKAXES.currentEntry];
|
|
MEO_JOYSTICKAXIS_DIGITALNEGATIVE.data = &JoystickDigitalFunctions[M_JOYSTICKAXES.currentEntry][0];
|
|
MEO_JOYSTICKAXIS_DIGITALPOSITIVE.data = &JoystickDigitalFunctions[M_JOYSTICKAXES.currentEntry][1];
|
|
break;
|
|
|
|
case MENU_CHEATS:
|
|
{
|
|
const int32_t cheatFuncID = M_CHEATS.currentEntry - 1;
|
|
switch (cheatFuncID)
|
|
{
|
|
case -1:
|
|
case CHEATFUNC_WARP:
|
|
case CHEATFUNC_SKILL:
|
|
break;
|
|
default:
|
|
Menu_DoCheat(CheatFunctionIDs[cheatFuncID]);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (entry == &ME_VIDEOSETUP_APPLY)
|
|
{
|
|
resolution_t p = { xres, yres, fullscreen, bpp, 0 };
|
|
int32_t prend = videoGetRenderMode();
|
|
int32_t pvsync = vid_vsync;
|
|
|
|
resolution_t n = { resolution[newresolution].xdim, resolution[newresolution].ydim,
|
|
(resolution[newresolution].flags & RES_FS) ? newfullscreen : 0,
|
|
(newrendermode == REND_CLASSIC) ? 8 : resolution[newresolution].bppmax, 0 };
|
|
int32_t nrend = newrendermode;
|
|
int32_t nvsync = newvsync;
|
|
|
|
if (videoSetGameMode(n.flags, n.xdim, n.ydim, n.bppmax, upscalefactor) < 0)
|
|
{
|
|
if (videoSetGameMode(p.flags, p.xdim, p.ydim, p.bppmax, upscalefactor) < 0)
|
|
{
|
|
videoSetRenderMode(prend);
|
|
G_GameExit("Failed restoring old video mode.");
|
|
}
|
|
else
|
|
{
|
|
onvideomodechange(p.bppmax > 8);
|
|
vid_vsync = videoSetVsync(pvsync);
|
|
}
|
|
}
|
|
else onvideomodechange(n.bppmax > 8);
|
|
|
|
g_restorePalette = -1;
|
|
G_UpdateScreenArea();
|
|
videoSetRenderMode(nrend);
|
|
vid_vsync = videoSetVsync(nvsync);
|
|
ScreenMode = fullscreen;
|
|
ScreenWidth = xres;
|
|
ScreenHeight = yres;
|
|
ScreenBPP = bpp;
|
|
}
|
|
else if (entry == &ME_SOUND_RESTART)
|
|
{
|
|
snd_mixrate = soundrate;
|
|
snd_numvoices = soundvoices;
|
|
|
|
S_SoundShutdown();
|
|
S_MusicShutdown();
|
|
|
|
S_MusicStartup();
|
|
S_SoundStartup();
|
|
|
|
FX_StopAllSounds();
|
|
S_ClearSoundLocks();
|
|
|
|
if (MusicEnabled())
|
|
S_RestartMusic();
|
|
}
|
|
else if (entry == &ME_SAVESETUP_CLEANUP)
|
|
{
|
|
g_oldSaveCnt = G_CountOldSaves();
|
|
Menu_Change(MENU_SAVECLEANVERIFY);
|
|
}
|
|
else if (entry == &ME_COLCORR_RESET)
|
|
{
|
|
g_videoGamma = DEFAULT_GAMMA;
|
|
g_videoContrast = DEFAULT_CONTRAST;
|
|
g_videoBrightness = DEFAULT_BRIGHTNESS;
|
|
r_ambientlight = 1.f;
|
|
videoSetPalette(0,g_player[myconnectindex].ps->palette,0);
|
|
}
|
|
else if (entry == &ME_KEYBOARDSETUP_RESET)
|
|
CONFIG_SetDefaultKeys("demolition/defbinds.txt");
|
|
else if (entry == &ME_KEYBOARDSETUP_RESETCLASSIC)
|
|
CONFIG_SetDefaultKeys("demolition/origbinds.txt");
|
|
else if (entry == &ME_NETHOST_LAUNCH)
|
|
{
|
|
// master does whatever it wants
|
|
if (g_netServer)
|
|
{
|
|
Net_FillNewGame(&pendingnewgame, 1);
|
|
Net_SendNewGame(1, NULL);
|
|
Net_StartNewGame();
|
|
}
|
|
else if (voting == -1)
|
|
{
|
|
Net_SendMapVoteInitiate();
|
|
Menu_Change(MENU_NETWAITVOTES);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int32_t Menu_EntryOptionModify(MenuEntry_t *entry, int32_t newOption)
|
|
{
|
|
int32_t x;
|
|
DukePlayer_t *ps = g_player[myconnectindex].ps;
|
|
|
|
if (entry == &ME_GAMESETUP_DEMOREC)
|
|
{
|
|
if ((ps->gm&MODE_GAME))
|
|
G_CloseDemoWrite();
|
|
}
|
|
else if (entry == &ME_GAMESETUP_WEAPSWITCH_PICKUP)
|
|
{
|
|
ud.weaponswitch = ud.weaponswitch & ~(1|4);
|
|
switch (newOption)
|
|
{
|
|
case 2:
|
|
ud.weaponswitch = ud.weaponswitch | 4;
|
|
fallthrough__;
|
|
case 1:
|
|
ud.weaponswitch = ud.weaponswitch | 1;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if (entry == &ME_SOUND)
|
|
{
|
|
if (newOption == 0)
|
|
{
|
|
FX_StopAllSounds();
|
|
S_ClearSoundLocks();
|
|
}
|
|
}
|
|
else if (entry == &ME_SOUND_MUSIC || entry == &ME_CDPLAYER_TRACK)
|
|
{
|
|
mus_enabled = newOption;
|
|
|
|
if (newOption == 0)
|
|
S_PauseMusic(true);
|
|
else
|
|
{
|
|
S_RestartMusic();
|
|
S_PauseMusic(false);
|
|
}
|
|
}
|
|
else if (entry == &ME_SOUND_DUKETALK)
|
|
snd_speech = (snd_speech&~1) | newOption;
|
|
else if (entry == &ME_MOUSESETUP_SMOOTH)
|
|
CONTROL_SmoothMouse = in_mousesmoothing;
|
|
else if (entry == &ME_JOYSTICKAXIS_ANALOG)
|
|
CONTROL_MapAnalogAxis(M_JOYSTICKAXES.currentEntry, newOption, controldevice_joystick);
|
|
else if (entry == &ME_NETOPTIONS_EPISODE)
|
|
{
|
|
if (newOption < g_volumeCnt)
|
|
ud.m_volume_number = newOption;
|
|
}
|
|
else if (entry == &ME_NETOPTIONS_MONSTERS)
|
|
{
|
|
ud.m_monsters_off = (newOption == g_skillCnt);
|
|
if (newOption < g_skillCnt)
|
|
ud.m_player_skill = newOption;
|
|
}
|
|
else if (entry == &ME_ADULTMODE)
|
|
{
|
|
if (newOption)
|
|
{
|
|
for (x=0; x<g_animWallCnt; x++)
|
|
switch (DYNAMICTILEMAP(wall[animwall[x].wallnum].picnum))
|
|
{
|
|
case FEMPIC1__STATIC:
|
|
wall[animwall[x].wallnum].picnum = BLANKSCREEN;
|
|
break;
|
|
case FEMPIC2__STATIC:
|
|
case FEMPIC3__STATIC:
|
|
wall[animwall[x].wallnum].picnum = SCREENBREAK6;
|
|
break;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
adult_lockout = 0;
|
|
}
|
|
}
|
|
|
|
switch (g_currentMenu)
|
|
{
|
|
case MENU_MOUSEBTNS:
|
|
break;
|
|
case MENU_MOUSEADVANCED:
|
|
{
|
|
for (int i = 0; i < ARRAY_SSIZE(MEL_INTERNAL_MOUSEADVANCED_DAXES); i++)
|
|
if (entry == MEL_INTERNAL_MOUSEADVANCED_DAXES[i])
|
|
CONTROL_MapDigitalAxis(i>>1, newOption, i&1, controldevice_mouse);
|
|
}
|
|
break;
|
|
case MENU_JOYSTICKBTNS:
|
|
break;
|
|
case MENU_JOYSTICKAXIS:
|
|
{
|
|
for (int i = 0; i < ARRAY_SSIZE(MEL_INTERNAL_JOYSTICKAXIS_DIGITAL); i++)
|
|
if (entry == MEL_INTERNAL_JOYSTICKAXIS_DIGITAL[i])
|
|
CONTROL_MapDigitalAxis(i>>1, newOption, i&1, controldevice_joystick);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void Menu_EntryOptionDidModify(MenuEntry_t *entry)
|
|
{
|
|
#ifdef USE_OPENGL
|
|
int domodechange = 0;
|
|
#endif
|
|
|
|
if (entry == &ME_GAMESETUP_AIM_AUTO ||
|
|
entry == &ME_GAMESETUP_WEAPSWITCH_PICKUP ||
|
|
//entry == &ME_PLAYER_NAME ||
|
|
entry == &ME_PLAYER_COLOR ||
|
|
entry == &ME_PLAYER_TEAM)
|
|
G_UpdatePlayerFromMenu();
|
|
else if (entry == &ME_DISPLAYSETUP_UPSCALING)
|
|
{
|
|
if (in3dmode())
|
|
{
|
|
videoSetGameMode(fullscreen, xres, yres, bpp, ud.detail);
|
|
}
|
|
}
|
|
#ifdef USE_OPENGL
|
|
else if (entry == &ME_DISPLAYSETUP_ANISOTROPY || entry == &ME_DISPLAYSETUP_TEXFILTER)
|
|
gltexapplyprops();
|
|
else if (entry == &ME_RENDERERSETUP_TEXQUALITY)
|
|
{
|
|
r_downsizevar = r_downsize;
|
|
domodechange = 1;
|
|
}
|
|
|
|
if (domodechange)
|
|
{
|
|
videoResetMode();
|
|
if (videoSetGameMode(fullscreen, xres, yres, bpp, upscalefactor))
|
|
OSD_Printf("restartvid: Reset failed...\n");
|
|
onvideomodechange(ScreenBPP>8);
|
|
G_RefreshLights();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void Menu_Custom2ColScreen(/*MenuEntry_t *entry*/)
|
|
{
|
|
if (g_currentMenu == MENU_KEYBOARDKEYS)
|
|
{
|
|
inputState.keyFlushChars();
|
|
inputState.ClearLastScanCode();
|
|
}
|
|
}
|
|
|
|
static int32_t Menu_EntryRangeInt32Modify(MenuEntry_t *entry, int32_t newValue)
|
|
{
|
|
if (entry == &ME_SCREENSETUP_SBARSIZE)
|
|
G_SetStatusBarScale(newValue);
|
|
else if (entry == &ME_SOUND_VOLUME_FX)
|
|
FX_SetVolume(newValue);
|
|
else if (entry == &ME_SOUND_VOLUME_MUSIC)
|
|
S_MusicVolume(newValue);
|
|
else if (entry == &ME_MOUSEADVANCED_SCALEX)
|
|
CONTROL_SetAnalogAxisScale(0, newValue, controldevice_mouse);
|
|
else if (entry == &ME_MOUSEADVANCED_SCALEY)
|
|
CONTROL_SetAnalogAxisScale(1, newValue, controldevice_mouse);
|
|
else if (entry == &ME_JOYSTICKAXIS_SCALE)
|
|
CONTROL_SetAnalogAxisScale(M_JOYSTICKAXES.currentEntry, newValue, controldevice_joystick);
|
|
else if (entry == &ME_JOYSTICKAXIS_DEAD)
|
|
joySetDeadZone(M_JOYSTICKAXES.currentEntry, newValue, *MEO_JOYSTICKAXIS_SATU.variable);
|
|
else if (entry == &ME_JOYSTICKAXIS_SATU)
|
|
joySetDeadZone(M_JOYSTICKAXES.currentEntry, *MEO_JOYSTICKAXIS_DEAD.variable, newValue);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int32_t Menu_EntryRangeFloatModify(MenuEntry_t *entry, float newValue)
|
|
{
|
|
#ifndef EDUKE32_SIMPLE_MENU
|
|
if (entry == &ME_COLCORR_AMBIENT)
|
|
r_ambientlightrecip = 1.f/newValue;
|
|
#else
|
|
UNREFERENCED_PARAMETER(entry);
|
|
UNREFERENCED_PARAMETER(newValue);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int32_t Menu_EntryRangeFloatDidModify(MenuEntry_t *entry)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
#ifdef MENU_ENABLE_RANGEDOUBLE
|
|
static int32_t Menu_EntryRangeDoubleModify(void /*MenuEntry_t *entry, double newValue*/)
|
|
{
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
static uint32_t save_xxh = 0;
|
|
|
|
static void Menu_EntryStringActivate(/*MenuEntry_t *entry*/)
|
|
{
|
|
switch (g_currentMenu)
|
|
{
|
|
case MENU_SAVE:
|
|
if (M_SAVE.currentEntry > 0)
|
|
{
|
|
savebrief_t & sv = g_menusaves[M_SAVE.currentEntry-1].brief;
|
|
if (!save_xxh)
|
|
save_xxh = SuperFastHash(sv.name, MAXSAVEGAMENAME);
|
|
if (sv.isValid())
|
|
Menu_Change(MENU_SAVEVERIFY);
|
|
}
|
|
else
|
|
{
|
|
ME_SAVE_NEW.name = nullptr;
|
|
save_xxh = 0;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static int32_t Menu_EntryStringSubmit(/*MenuEntry_t *entry, */char *input)
|
|
{
|
|
int32_t returnvar = 0;
|
|
|
|
switch (g_currentMenu)
|
|
{
|
|
case MENU_SAVE:
|
|
{
|
|
savebrief_t & sv = g_lastusersave = M_SAVE.currentEntry == 0 ? savebrief_t{input} : g_menusaves[M_SAVE.currentEntry-1].brief;
|
|
|
|
// dirty hack... char 127 in last position indicates an auto-filled name
|
|
#ifdef __ANDROID__
|
|
if (1)
|
|
#else
|
|
if (input[0] == 0 || (sv.name[MAXSAVEGAMENAME] == 127 &&
|
|
strncmp(sv.name, input, MAXSAVEGAMENAME) == 0 &&
|
|
save_xxh == SuperFastHash(sv.name, MAXSAVEGAMENAME)))
|
|
#endif
|
|
{
|
|
strncpy(sv.name, g_mapInfo[ud.volume_number * MAXLEVELS + ud.level_number].name, MAXSAVEGAMENAME);
|
|
sv.name[MAXSAVEGAMENAME] = 127;
|
|
returnvar = -1;
|
|
}
|
|
else
|
|
{
|
|
strncpy(sv.name, input, MAXSAVEGAMENAME);
|
|
sv.name[MAXSAVEGAMENAME] = 0;
|
|
}
|
|
|
|
G_SavePlayerMaybeMulti(sv);
|
|
|
|
g_quickload = &sv;
|
|
g_player[myconnectindex].ps->gm = MODE_GAME;
|
|
|
|
Menu_Change(MENU_CLOSE);
|
|
save_xxh = 0;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return returnvar;
|
|
}
|
|
|
|
static void Menu_EntryStringCancel(/*MenuEntry_t *entry*/)
|
|
{
|
|
switch (g_currentMenu)
|
|
{
|
|
case MENU_SAVE:
|
|
save_xxh = 0;
|
|
ME_SAVE_NEW.name = s_NewSaveGame;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
This is polled when the menu code is populating the screen but for some reason doesn't have the data.
|
|
*/
|
|
static int32_t Menu_EntryOptionSource(MenuEntry_t *entry, int32_t currentValue)
|
|
{
|
|
if (entry == &ME_GAMESETUP_WEAPSWITCH_PICKUP)
|
|
return (cl_weaponswitch & 1) ? ((cl_weaponswitch & 4) ? 2 : 1) : 0;
|
|
else if (entry == &ME_SOUND_DUKETALK)
|
|
return snd_speech & 1;
|
|
else if (entry == &ME_NETOPTIONS_MONSTERS)
|
|
return (ud.m_monsters_off ? g_skillCnt : ud.m_player_skill);
|
|
|
|
return currentValue;
|
|
}
|
|
|
|
static void Menu_Verify(int32_t input)
|
|
{
|
|
switch (g_currentMenu)
|
|
{
|
|
case MENU_SAVECLEANVERIFY:
|
|
if (input)
|
|
{
|
|
G_DeleteOldSaves();
|
|
}
|
|
break;
|
|
|
|
case MENU_RESETPLAYER:
|
|
switch (input)
|
|
{
|
|
default:
|
|
inputState.keyFlushChars();
|
|
inputState.ClearKeysDown();
|
|
FX_StopAllSounds();
|
|
|
|
if (G_LoadPlayerMaybeMulti(*g_quickload) == 0)
|
|
break;
|
|
|
|
// error state, consider as a no instead of yes
|
|
g_quickload->reset();
|
|
|
|
fallthrough__;
|
|
case 0:
|
|
if (sprite[g_player[myconnectindex].ps->i].extra <= 0)
|
|
{
|
|
if (G_EnterLevel(MODE_GAME)) G_BackToMenu();
|
|
return;
|
|
}
|
|
|
|
Menu_Change(MENU_CLOSE);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case MENU_LOADVERIFY:
|
|
if (input)
|
|
{
|
|
savebrief_t & sv = g_menusaves[M_LOAD.currentEntry].brief;
|
|
|
|
if (strcmp(sv.path, g_lastusersave.path) != 0)
|
|
{
|
|
g_freshload = sv;
|
|
g_lastusersave.reset();
|
|
g_lastautosave.reset();
|
|
g_quickload = &g_freshload;
|
|
}
|
|
else
|
|
{
|
|
g_quickload = &g_lastusersave;
|
|
}
|
|
|
|
inputState.keyFlushChars();
|
|
inputState.ClearKeysDown();
|
|
|
|
Menu_Change(MENU_CLOSE);
|
|
|
|
G_LoadPlayerMaybeMulti(sv);
|
|
}
|
|
break;
|
|
|
|
case MENU_SAVEVERIFY:
|
|
if (!input)
|
|
{
|
|
save_xxh = 0;
|
|
|
|
((MenuString_t*)M_SAVE.entrylist[M_SAVE.currentEntry]->entry)->editfield = NULL;
|
|
}
|
|
break;
|
|
|
|
case MENU_LOADDELVERIFY:
|
|
if (input)
|
|
{
|
|
G_DeleteSave(g_menusaves[M_LOAD.currentEntry].brief);
|
|
Menu_LoadReadHeaders();
|
|
M_LOAD.currentEntry = clamp(M_LOAD.currentEntry, 0, (int32_t)g_nummenusaves-1);
|
|
}
|
|
break;
|
|
case MENU_SAVEDELVERIFY:
|
|
if (input)
|
|
{
|
|
G_DeleteSave(g_menusaves[M_SAVE.currentEntry-1].brief);
|
|
Menu_SaveReadHeaders();
|
|
M_SAVE.currentEntry = clamp(M_SAVE.currentEntry, 0, (int32_t)g_nummenusaves);
|
|
}
|
|
break;
|
|
|
|
case MENU_QUIT:
|
|
case MENU_QUIT_INGAME:
|
|
if (input)
|
|
G_GameQuit();
|
|
else
|
|
g_quitDeadline = 0;
|
|
break;
|
|
|
|
case MENU_QUITTOTITLE:
|
|
if (input)
|
|
{
|
|
g_player[myconnectindex].ps->gm = MODE_DEMO;
|
|
if (ud.recstat == 1)
|
|
G_CloseDemoWrite();
|
|
artClearMapArt();
|
|
}
|
|
break;
|
|
|
|
case MENU_NETWAITVOTES:
|
|
if (!input)
|
|
Net_SendMapVoteCancel(0);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static int Menu_CheatStringMatch(char const * input, char const * cheat)
|
|
{
|
|
while (*cheat || *input)
|
|
{
|
|
if (*cheat != *input)
|
|
{
|
|
if (!(*cheat == '#' && Bisdigit(*input)))
|
|
return 0;
|
|
}
|
|
|
|
++cheat;
|
|
++input;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static void Menu_TextFormSubmit(char *input)
|
|
{
|
|
switch (g_currentMenu)
|
|
{
|
|
case MENU_ADULTPASSWORD:
|
|
break;
|
|
|
|
case MENU_CHEATENTRY:
|
|
{
|
|
const size_t inputlength = Bstrlen(input);
|
|
Bstrcpy(tempbuf, input);
|
|
for (size_t i = 0; i < inputlength; i++)
|
|
tempbuf[i] = Btolower(tempbuf[i]);
|
|
|
|
int8_t cheatID = -1;
|
|
|
|
if (inputlength > 2 && tempbuf[0] == g_keyAsciiTable[CheatKeys[0]] && tempbuf[1] == g_keyAsciiTable[CheatKeys[1]])
|
|
{
|
|
for (int i = 0; i < NUMCHEATS; i++)
|
|
if (Menu_CheatStringMatch(tempbuf+2, CheatStrings[i]))
|
|
{
|
|
cheatID = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch (cheatID)
|
|
{
|
|
case -1:
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
break;
|
|
case CHEAT_SCOTTY:
|
|
{
|
|
char const * const numberpos = Bstrchr(CheatStrings[CHEAT_SCOTTY], '#');
|
|
if (numberpos == NULL)
|
|
{
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
break;
|
|
}
|
|
|
|
Menu_Cheat_Warp(input + (numberpos - CheatStrings[CHEAT_SCOTTY]) + 2);
|
|
if (g_player[myconnectindex].ps->gm&MODE_MENU)
|
|
S_PlaySound(DUKE_GET);
|
|
break;
|
|
}
|
|
case CHEAT_SKILL:
|
|
{
|
|
char const * const numberpos = Bstrchr(CheatStrings[CHEAT_SKILL], '#');
|
|
if (numberpos == NULL)
|
|
{
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
break;
|
|
}
|
|
|
|
Menu_Cheat_Skill(input + (numberpos - CheatStrings[CHEAT_SKILL]) + 2);
|
|
if (g_player[myconnectindex].ps->gm&MODE_MENU)
|
|
S_PlaySound(DUKE_GET);
|
|
break;
|
|
}
|
|
default:
|
|
Menu_DoCheat(cheatID);
|
|
S_PlaySound(DUKE_GET);
|
|
break;
|
|
}
|
|
|
|
if (cheatID >= 0)
|
|
cl_cheatmask = cl_cheatmask | CheatFunctionFlags[cheatID];
|
|
|
|
if (((cl_cheatmask & (1<<CHEATFUNC_QUOTEBETA)) && (cl_cheatmask & (1<<CHEATFUNC_QUOTETODD)) && (cl_cheatmask & (1<<CHEATFUNC_QUOTEALLEN))))
|
|
{
|
|
S_PlaySound(DUKE_GETWEAPON6);
|
|
cl_cheatmask = ~0;
|
|
}
|
|
|
|
Menu_Change(MENU_CHEATS);
|
|
break;
|
|
}
|
|
|
|
case MENU_CHEAT_WARP:
|
|
if (Menu_Cheat_Warp(input))
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
Menu_Change(MENU_CHEATS);
|
|
break;
|
|
|
|
case MENU_CHEAT_SKILL:
|
|
if (Menu_Cheat_Skill(input))
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
Menu_Change(MENU_CHEATS);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void Menu_FileSelectInit(MenuFileSelect_t *object)
|
|
{
|
|
// Same crap as everywhere - it expects the user to dump all the shit in the game directory so that it gets in the way of everything.
|
|
// Needs to be redone - or removed.
|
|
if (usermapfolder)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
}
|
|
#if 0
|
|
fnlist_clearnames(&object->fnlist);
|
|
|
|
if (object->destination[0] == 0)
|
|
Bstrcpy(object->destination, "./");
|
|
Bcorrectfilename(object->destination, 1);
|
|
|
|
fnlist_getnames(&object->fnlist, object->destination, object->pattern, 0, 0);
|
|
object->findhigh[0] = object->fnlist.finddirs;
|
|
object->findhigh[1] = object->fnlist.findfiles;
|
|
|
|
for (int i = 0; i < 2; ++i)
|
|
{
|
|
object->scrollPos[i] = 0;
|
|
klistbookends(object->findhigh[i]);
|
|
}
|
|
|
|
object->currentList = 0;
|
|
if (object->findhigh[1])
|
|
object->currentList = 1;
|
|
|
|
#endif
|
|
inputState.keyFlushChars();
|
|
}
|
|
|
|
static void Menu_FileSelect(int32_t input)
|
|
{
|
|
#if 0
|
|
switch (g_currentMenu)
|
|
{
|
|
case MENU_NETUSERMAP:
|
|
if ((g_netServer || ud.multimode > 1))
|
|
Net_SendUserMapName();
|
|
fallthrough__;
|
|
case MENU_USERMAP:
|
|
if (input)
|
|
{
|
|
ud.m_volume_number = 0;
|
|
ud.m_level_number = 7;
|
|
|
|
if (g_skillCnt > 0)
|
|
Menu_AnimateChange(MENU_SKILL, MA_Advance);
|
|
else
|
|
Menu_StartGameWithoutSkill();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static Menu_t* Menu_BinarySearch(MenuID_t query, uint16_t searchstart, uint16_t searchend)
|
|
{
|
|
const uint16_t thissearch = (searchstart + searchend) / 2;
|
|
const MenuID_t difference = query - Menus[thissearch].menuID;
|
|
|
|
if (difference == 0)
|
|
return &Menus[thissearch];
|
|
else if (searchstart == searchend)
|
|
return NULL;
|
|
else if (difference > 0)
|
|
{
|
|
if (thissearch == searchend)
|
|
return NULL;
|
|
searchstart = thissearch + 1;
|
|
}
|
|
else if (difference < 0)
|
|
{
|
|
if (thissearch == searchstart)
|
|
return NULL;
|
|
searchend = thissearch - 1;
|
|
}
|
|
|
|
return Menu_BinarySearch(query, searchstart, searchend);
|
|
}
|
|
|
|
static Menu_t* Menu_Find(MenuID_t query)
|
|
{
|
|
if ((unsigned) query > (unsigned) Menus[numMenus-1].menuID)
|
|
return NULL;
|
|
|
|
return Menu_BinarySearch(query, 0, numMenus-1);
|
|
}
|
|
|
|
static Menu_t* Menu_FindFiltered(MenuID_t query)
|
|
{
|
|
if ((g_player[myconnectindex].ps->gm&MODE_GAME) && query == MENU_MAIN)
|
|
query = MENU_MAIN_INGAME;
|
|
|
|
return Menu_Find(query);
|
|
}
|
|
|
|
MenuAnimation_t m_animation;
|
|
|
|
int32_t Menu_Anim_SinOutRight(MenuAnimation_t *animdata)
|
|
{
|
|
return sintable[divscale10((int32_t) totalclock - animdata->start, animdata->length) + 512] - 16384;
|
|
}
|
|
int32_t Menu_Anim_SinInRight(MenuAnimation_t *animdata)
|
|
{
|
|
return sintable[divscale10((int32_t) totalclock - animdata->start, animdata->length) + 512] + 16384;
|
|
}
|
|
int32_t Menu_Anim_SinOutLeft(MenuAnimation_t *animdata)
|
|
{
|
|
return -sintable[divscale10((int32_t) totalclock - animdata->start, animdata->length) + 512] + 16384;
|
|
}
|
|
int32_t Menu_Anim_SinInLeft(MenuAnimation_t *animdata)
|
|
{
|
|
return -sintable[divscale10((int32_t) totalclock - animdata->start, animdata->length) + 512] - 16384;
|
|
}
|
|
|
|
void Menu_AnimateChange(int32_t cm, MenuAnimationType_t animtype)
|
|
{
|
|
switch (animtype)
|
|
{
|
|
case MA_Advance:
|
|
{
|
|
Menu_t * const previousMenu = m_currentMenu;
|
|
|
|
if (!Menu_Change(cm))
|
|
{
|
|
m_animation.out = Menu_Anim_SinOutRight;
|
|
m_animation.in = Menu_Anim_SinInRight;
|
|
m_animation.start = (int32_t) totalclock;
|
|
m_animation.length = 30;
|
|
|
|
m_animation.previous = previousMenu;
|
|
m_animation.current = m_currentMenu;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case MA_Return:
|
|
{
|
|
Menu_t * const previousMenu = m_currentMenu;
|
|
|
|
if (!Menu_Change(cm))
|
|
{
|
|
m_animation.out = Menu_Anim_SinOutLeft;
|
|
m_animation.in = Menu_Anim_SinInLeft;
|
|
m_animation.start = (int32_t) totalclock;
|
|
m_animation.length = 30;
|
|
|
|
m_animation.previous = previousMenu;
|
|
m_animation.current = m_currentMenu;
|
|
}
|
|
|
|
break;
|
|
}
|
|
default:
|
|
m_animation.start = 0;
|
|
m_animation.length = 0;
|
|
Menu_Change(cm);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void Menu_MaybeSetSelectionToChild(Menu_t * m, MenuID_t id)
|
|
{
|
|
if (m->type == Menu)
|
|
{
|
|
auto * menu = (MenuMenu_t *)m->object;
|
|
|
|
if (menu->currentEntry < menu->numEntries)
|
|
{
|
|
MenuEntry_t const * currentEntry = menu->entrylist[menu->currentEntry];
|
|
if (currentEntry != NULL && currentEntry->type == Link)
|
|
{
|
|
auto const * link = (MenuLink_t const *)currentEntry->entry;
|
|
if (link->linkID == id)
|
|
return; // already good to go
|
|
}
|
|
}
|
|
|
|
for (int i = 0, i_end = menu->numEntries; i < i_end; ++i)
|
|
{
|
|
MenuEntry_t const * entry = menu->entrylist[i];
|
|
if (entry != NULL && entry->type == Link && !(entry->flags & MEF_Hidden))
|
|
{
|
|
auto const * link = (MenuLink_t const *)entry->entry;
|
|
if (link->linkID == id)
|
|
{
|
|
menu->currentEntry = i;
|
|
Menu_AdjustForCurrentEntryAssignmentBlind(menu);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void Menu_ReadSaveGameHeaders()
|
|
{
|
|
ReadSaveGameHeaders();
|
|
|
|
int const numloaditems = max<int>(g_nummenusaves, 1), numsaveitems = g_nummenusaves+1;
|
|
ME_LOAD = (MenuEntry_t *)Xrealloc(ME_LOAD, g_nummenusaves * sizeof(MenuEntry_t));
|
|
MEL_LOAD = (MenuEntry_t **)Xrealloc(MEL_LOAD, numloaditems * sizeof(MenuEntry_t *));
|
|
MEO_SAVE = (MenuString_t *)Xrealloc(MEO_SAVE, g_nummenusaves * sizeof(MenuString_t));
|
|
ME_SAVE = (MenuEntry_t *)Xrealloc(ME_SAVE, g_nummenusaves * sizeof(MenuEntry_t));
|
|
MEL_SAVE = (MenuEntry_t **)Xrealloc(MEL_SAVE, numsaveitems * sizeof(MenuEntry_t *));
|
|
|
|
MEL_SAVE[0] = &ME_SAVE_NEW;
|
|
ME_SAVE_NEW.name = s_NewSaveGame;
|
|
for (int i = 0; i < g_nummenusaves; ++i)
|
|
{
|
|
MEL_LOAD[i] = &ME_LOAD[i];
|
|
MEL_SAVE[i+1] = &ME_SAVE[i];
|
|
ME_LOAD[i] = ME_LOAD_TEMPLATE;
|
|
ME_SAVE[i] = ME_SAVE_TEMPLATE;
|
|
ME_SAVE[i].entry = &MEO_SAVE[i];
|
|
MEO_SAVE[i] = MEO_SAVE_TEMPLATE;
|
|
|
|
ME_LOAD[i].name = g_menusaves[i].brief.name;
|
|
MEO_SAVE[i].variable = g_menusaves[i].brief.name;
|
|
}
|
|
|
|
if (g_nummenusaves == 0)
|
|
MEL_LOAD[0] = &ME_LOAD_EMPTY;
|
|
|
|
M_LOAD.entrylist = MEL_LOAD;
|
|
M_LOAD.numEntries = numloaditems;
|
|
M_SAVE.entrylist = MEL_SAVE;
|
|
M_SAVE.numEntries = numsaveitems;
|
|
|
|
// lexicographical sorting?
|
|
}
|
|
|
|
static void Menu_AboutToStartDisplaying(Menu_t * m)
|
|
{
|
|
switch (m->menuID)
|
|
{
|
|
case MENU_MAIN:
|
|
break;
|
|
|
|
case MENU_MAIN_INGAME:
|
|
break;
|
|
|
|
case MENU_LOAD:
|
|
Menu_LoadReadHeaders();
|
|
|
|
if (g_quickload && g_quickload->isValid())
|
|
{
|
|
for (int i = 0; i < g_nummenusaves; ++i)
|
|
{
|
|
if (strcmp(g_menusaves[i].brief.path, g_quickload->path) == 0)
|
|
{
|
|
M_LOAD.currentEntry = i;
|
|
Menu_AdjustForCurrentEntryAssignmentBlind(&M_LOAD);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MENU_SAVE:
|
|
if (g_previousMenu == MENU_SAVEVERIFY || g_previousMenu == MENU_SAVEDELVERIFY)
|
|
break;
|
|
|
|
Menu_SaveReadHeaders();
|
|
|
|
if (g_lastusersave.isValid())
|
|
{
|
|
for (int i = 0; i < g_nummenusaves; ++i)
|
|
{
|
|
if (strcmp(g_menusaves[i].brief.path, g_lastusersave.path) == 0)
|
|
{
|
|
M_SAVE.currentEntry = i+1;
|
|
Menu_AdjustForCurrentEntryAssignmentBlind(&M_SAVE);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (g_player[myconnectindex].ps->gm&MODE_GAME)
|
|
{
|
|
g_screenCapture = 1;
|
|
G_DrawRooms(myconnectindex,65536);
|
|
g_screenCapture = 0;
|
|
}
|
|
break;
|
|
|
|
case MENU_VIDEOSETUP:
|
|
newresolution = 0;
|
|
for (int i = 0; i < MAXVALIDMODES; ++i)
|
|
{
|
|
if (resolution[i].xdim == xres && resolution[i].ydim == yres)
|
|
{
|
|
newresolution = i;
|
|
break;
|
|
}
|
|
}
|
|
newrendermode = videoGetRenderMode();
|
|
newfullscreen = fullscreen;
|
|
newvsync = vid_vsync;
|
|
break;
|
|
|
|
case MENU_ADVSOUND:
|
|
soundrate = snd_mixrate;
|
|
soundvoices = snd_numvoices;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
switch (m->type)
|
|
{
|
|
case TextForm:
|
|
typebuf[0] = 0;
|
|
((MenuTextForm_t*)m->object)->input = typebuf;
|
|
break;
|
|
case FileSelect:
|
|
Menu_FileSelectInit((MenuFileSelect_t*)m->object);
|
|
break;
|
|
case CdPlayer:
|
|
{
|
|
auto *menu = (MenuMenu_t*)m->object;
|
|
menu->currentEntry = g_cdTrack-2;
|
|
// MenuEntry_t* currentry = menu->entrylist[menu->currentEntry];
|
|
|
|
if (menu->currentEntry < 0 || menu->currentEntry >= menu->numEntries)
|
|
menu->currentEntry = 0;
|
|
|
|
Menu_EntryFocus(/*currentry*/);
|
|
break;
|
|
}
|
|
case Menu:
|
|
{
|
|
auto *menu = (MenuMenu_t*)m->object;
|
|
// MenuEntry_t* currentry = menu->entrylist[menu->currentEntry];
|
|
|
|
// need this for MENU_SKILL
|
|
if (menu->currentEntry >= menu->numEntries)
|
|
menu->currentEntry = 0;
|
|
|
|
int32_t i = menu->currentEntry;
|
|
while (!menu->entrylist[menu->currentEntry] ||
|
|
(((MenuEntry_t*)menu->entrylist[menu->currentEntry])->flags & MEF_Hidden) ||
|
|
((MenuEntry_t*)menu->entrylist[menu->currentEntry])->type == Spacer)
|
|
{
|
|
menu->currentEntry++;
|
|
if (menu->currentEntry >= menu->numEntries)
|
|
menu->currentEntry = 0;
|
|
if (menu->currentEntry == i)
|
|
G_GameExit("Menu_Change: Attempted to show a menu with no entries.");
|
|
}
|
|
|
|
Menu_EntryFocus(/*currentry*/);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void Menu_ChangingTo(Menu_t * m)
|
|
{
|
|
#ifdef __ANDROID__
|
|
if (m->menuID == MENU_TOUCHBUTTONS)
|
|
AndroidToggleButtonEditor();
|
|
#endif
|
|
|
|
switch (m->type)
|
|
{
|
|
case TextForm:
|
|
Menu_StartTextInput();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
int Menu_Change(MenuID_t cm)
|
|
{
|
|
Menu_t * beginMenu = m_currentMenu;
|
|
|
|
if (cm == MENU_PREVIOUS)
|
|
{
|
|
m_currentMenu = m_previousMenu;
|
|
g_currentMenu = g_previousMenu;
|
|
}
|
|
else if (cm == MENU_CLOSE)
|
|
Menu_Close(myconnectindex);
|
|
else if (cm >= 0)
|
|
{
|
|
Menu_t * search = Menu_FindFiltered(cm);
|
|
|
|
if (search == NULL)
|
|
return 0; // intentional, so that users don't use any random value as "don't change"
|
|
|
|
// security
|
|
if (search->type == Verify &&
|
|
search->parentID != MENU_PREVIOUS &&
|
|
search->parentID != MENU_CLOSE &&
|
|
search->parentID != g_currentMenu)
|
|
return 1;
|
|
|
|
m_previousMenu = m_currentMenu;
|
|
g_previousMenu = g_currentMenu;
|
|
m_currentMenu = search;
|
|
g_currentMenu = search->menuID;
|
|
}
|
|
else
|
|
return 1;
|
|
|
|
Menu_MaybeSetSelectionToChild(m_currentMenu, beginMenu->menuID);
|
|
Menu_AboutToStartDisplaying(m_currentMenu);
|
|
Menu_ChangingTo(m_currentMenu);
|
|
|
|
#if !defined EDUKE32_TOUCH_DEVICES
|
|
m_menuchange_watchpoint = 1;
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int G_CheckPlayerColor(int color)
|
|
{
|
|
for (int i : MEOSV_PLAYER_COLOR)
|
|
if (i == color)
|
|
return color;
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
int32_t Menu_DetermineSpecialState(MenuEntry_t *entry)
|
|
{
|
|
if (entry == NULL)
|
|
return 0;
|
|
|
|
if (entry->type == String)
|
|
{
|
|
if (((MenuString_t*)entry->entry)->editfield)
|
|
return 1;
|
|
}
|
|
else if (entry->type == Option)
|
|
{
|
|
if (((MenuOption_t*)entry->entry)->options->currentEntry >= 0)
|
|
return 2;
|
|
}
|
|
else if (entry->type == Custom2Col)
|
|
{
|
|
if (((MenuCustom2Col_t*)entry->entry)->screenOpen)
|
|
return 2;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int32_t Menu_IsTextInput(Menu_t *cm)
|
|
{
|
|
switch (m_currentMenu->type)
|
|
{
|
|
case Verify:
|
|
case TextForm:
|
|
case FileSelect:
|
|
case Message:
|
|
return 1;
|
|
break;
|
|
case Panel:
|
|
case CdPlayer:
|
|
return 0;
|
|
break;
|
|
case Menu:
|
|
{
|
|
auto *menu = (MenuMenu_t *)cm->object;
|
|
auto *entry = menu->entrylist[menu->currentEntry];
|
|
return Menu_DetermineSpecialState(entry);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static inline int32_t Menu_BlackTranslucentBackgroundOK(MenuID_t cm)
|
|
{
|
|
switch (cm)
|
|
{
|
|
case MENU_COLCORR:
|
|
case MENU_COLCORR_INGAME:
|
|
return 0;
|
|
break;
|
|
default:
|
|
return 1;
|
|
break;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static inline int32_t Menu_UpdateScreenOK(MenuID_t cm)
|
|
{
|
|
switch (cm)
|
|
{
|
|
case MENU_LOAD:
|
|
case MENU_SAVE:
|
|
case MENU_LOADVERIFY:
|
|
case MENU_LOADDELVERIFY:
|
|
case MENU_SAVEVERIFY:
|
|
case MENU_SAVEDELVERIFY:
|
|
return 0;
|
|
break;
|
|
default:
|
|
return 1;
|
|
break;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*
|
|
Code below this point is entirely general,
|
|
so if you want to change or add a menu,
|
|
chances are you should scroll up.
|
|
*/
|
|
|
|
int32_t m_mouselastactivity;
|
|
#if !defined EDUKE32_TOUCH_DEVICES
|
|
int32_t m_mousewake_watchpoint, m_menuchange_watchpoint;
|
|
#endif
|
|
int32_t m_mousecaught;
|
|
static vec2_t m_prevmousepos, m_mousepos, m_mousedownpos;
|
|
|
|
void Menu_Open(uint8_t playerID)
|
|
{
|
|
g_player[playerID].ps->gm |= MODE_MENU;
|
|
|
|
mouseReadAbs(&m_prevmousepos, &g_mouseAbs);
|
|
m_mouselastactivity = -M_MOUSETIMEOUT;
|
|
|
|
#if !defined EDUKE32_TOUCH_DEVICES
|
|
m_mousewake_watchpoint = 0;
|
|
#endif
|
|
|
|
mouseLockToWindow(0);
|
|
}
|
|
|
|
void Menu_Close(uint8_t playerID)
|
|
{
|
|
if (g_player[playerID].ps->gm & (MODE_GAME|MODE_DEMO))
|
|
{
|
|
// The following lines are here so that you cannot close the menu when no game is running.
|
|
g_player[playerID].ps->gm &= ~MODE_MENU;
|
|
mouseLockToWindow(1);
|
|
|
|
if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2)
|
|
{
|
|
ready2send = 1;
|
|
totalclock = ototalclock;
|
|
CAMERACLOCK = (int32_t) totalclock;
|
|
CAMERADIST = 65536;
|
|
m_animation.start = 0;
|
|
m_animation.length = 0;
|
|
|
|
// Reset next-viewscreen-redraw counter.
|
|
// XXX: are there any other cases like that in need of handling?
|
|
if (g_curViewscreen >= 0)
|
|
actor[g_curViewscreen].t_data[0] = (int32_t) totalclock;
|
|
}
|
|
|
|
G_UpdateScreenArea();
|
|
|
|
if (!ud.pause_on)
|
|
S_PauseSounds(false);
|
|
}
|
|
}
|
|
|
|
static int32_t x_widescreen_left(void)
|
|
{
|
|
return (320<<15) - scale(240<<15, xdim, ydim);
|
|
}
|
|
|
|
static int32_t xdim_from_320_16(int32_t x)
|
|
{
|
|
const int32_t screenwidth = scale(240<<16, xdim, ydim);
|
|
return scale(x + (screenwidth>>1) - (160<<16), xdim, screenwidth);
|
|
}
|
|
static int32_t ydim_from_200_16(int32_t y)
|
|
{
|
|
return scale(y, ydim, 200<<16);
|
|
}
|
|
|
|
static void Menu_BlackRectangle(int32_t x, int32_t y, int32_t width, int32_t height, int32_t orientation)
|
|
{
|
|
const int32_t xscale = divscale16(width, tilesiz[0].x<<16), yscale = divscale16(height, tilesiz[0].y<<16);
|
|
|
|
rotatesprite_(x, y, max(xscale, yscale), 0, 0, 127, ud.shadow_pal, (orientation&(1|32))|2|8|16, 0, 0, xdim_from_320_16(x), ydim_from_200_16(y), xdim_from_320_16(x + width), ydim_from_200_16(y + height));
|
|
}
|
|
|
|
enum MenuTextFlags_t
|
|
{
|
|
MT_Selected = 1<<0,
|
|
MT_Disabled = 1<<1,
|
|
MT_XCenter = 1<<2,
|
|
MT_XRight = 1<<3,
|
|
MT_YCenter = 1<<4,
|
|
MT_Literal = 1<<5,
|
|
MT_RightSide = 1<<6,
|
|
};
|
|
|
|
static void Menu_GetFmt(const MenuFont_t *font, uint8_t const status, int32_t *s)
|
|
{
|
|
if (status & MT_Selected)
|
|
*s = sintable[((int32_t) totalclock<<5)&2047]>>12;
|
|
else
|
|
*s = font->shade_deselected;
|
|
// sum shade values
|
|
if (status & MT_Disabled)
|
|
*s += font->shade_disabled;
|
|
}
|
|
|
|
static vec2_t Menu_Text(int32_t x, int32_t y, const MenuFont_t *font, const char *t, uint8_t status, int32_t ydim_upper, int32_t ydim_lower)
|
|
{
|
|
int32_t s, p, ybetween = font->between.y;
|
|
int32_t f = font->textflags | TEXT_RRMENUTEXTHACK;
|
|
if (status & MT_XCenter)
|
|
f |= TEXT_XCENTER;
|
|
if (status & MT_XRight)
|
|
f |= TEXT_XRIGHT;
|
|
if (status & MT_YCenter)
|
|
{
|
|
f |= TEXT_YCENTER | TEXT_YOFFSETZERO;
|
|
ybetween = font->emptychar.y; // <^ the battle against 'Q'
|
|
}
|
|
if (status & MT_Literal)
|
|
f |= TEXT_LITERALESCAPE;
|
|
|
|
int32_t z = font->zoom;
|
|
|
|
if (status & MT_Disabled)
|
|
p = (status & MT_RightSide) ? font->pal_disabled_right : font->pal_disabled;
|
|
else if (status & MT_Selected)
|
|
p = (status & MT_RightSide) ? font->pal_selected_right : font->pal_selected;
|
|
else
|
|
p = (status & MT_RightSide) ? font->pal_deselected_right : font->pal_deselected;
|
|
|
|
Menu_GetFmt(font, status, &s);
|
|
|
|
return G_ScreenText(font->tilenum, x, y, z, 0, 0, t, s, p, 2|8|16|ROTATESPRITE_FULL16, 0, font->emptychar.x, font->emptychar.y, font->between.x, ybetween, f, 0, ydim_upper, xdim-1, ydim_lower);
|
|
}
|
|
|
|
#if 0
|
|
static vec2_t Menu_TextSize(int32_t x, int32_t y, const MenuFont_t *font, const char *t, uint8_t status)
|
|
{
|
|
int32_t f = font->textflags;
|
|
if (status & MT_Literal)
|
|
f |= TEXT_LITERALESCAPE;
|
|
|
|
return G_ScreenTextSize(font->tilenum, x, y, font->zoom, 0, t, 2|8|16|ROTATESPRITE_FULL16, font->emptychar.x, font->emptychar.y, font->between.x, font->between.y, f, 0, 0, xdim-1, ydim-1);
|
|
}
|
|
#endif
|
|
|
|
static int32_t Menu_FindOptionBinarySearch(MenuOption_t *object, const int32_t query, uint16_t searchstart, uint16_t searchend)
|
|
{
|
|
const uint16_t thissearch = (searchstart + searchend) / 2;
|
|
const bool isIdentityMap = object->options->optionValues == NULL;
|
|
const int32_t destination = isIdentityMap ? (int32_t)thissearch : object->options->optionValues[thissearch];
|
|
const int32_t difference = query - destination;
|
|
|
|
Bassert(!isIdentityMap || query >= 0);
|
|
|
|
if (difference == 0)
|
|
return thissearch;
|
|
else if (searchstart == searchend)
|
|
return -1;
|
|
else if (difference > 0)
|
|
{
|
|
if (thissearch == searchend)
|
|
return -1;
|
|
searchstart = thissearch + 1;
|
|
}
|
|
else if (difference < 0)
|
|
{
|
|
if (thissearch == searchstart)
|
|
return -1;
|
|
searchend = thissearch - 1;
|
|
}
|
|
|
|
return Menu_FindOptionBinarySearch(object, query, searchstart, searchend);
|
|
}
|
|
|
|
static int32_t Menu_MouseOutsideBounds(vec2_t const * const pos, const int32_t x, const int32_t y, const int32_t width, const int32_t height)
|
|
{
|
|
return pos->x < x || pos->x >= x + width || pos->y < y || pos->y >= y + height;
|
|
}
|
|
|
|
static void Menu_RunScrollbar(Menu_t *cm, MenuMenuFormat_t const * const format, const int32_t totalextent, int32_t * const scrollPos, const int32_t rightedge, const vec2_t origin)
|
|
{
|
|
if (totalextent > klabs(format->bottomcutoff))
|
|
{
|
|
int32_t scrollTile = (ud.menu_scrollbartilenum >= 0) ? ud.menu_scrollbartilenum : -1;
|
|
int32_t scrollTileTop = (ud.menu_scrollbartilenum >= 0) ? ud.menu_scrollbartilenum + 1 : -1;
|
|
int32_t scrollTileBottom = (ud.menu_scrollbartilenum >= 0) ? ud.menu_scrollbartilenum + 2 : -1;
|
|
int32_t scrollTileCursor = (ud.menu_scrollbartilenum >= 0) ? ud.menu_scrollbartilenum + 3 : SELECTDIR;
|
|
|
|
const int32_t scrollwidth = (scrollTile >= 0) ? tilesiz[scrollTile].x*ud.menu_scrollbarz : tilesiz[scrollTileCursor].x*ud.menu_scrollcursorz;
|
|
const int32_t scrollx = origin.x + rightedge - scrollwidth, scrolly = origin.y + format->pos.y;
|
|
const int32_t scrollheight = klabs(format->bottomcutoff) - format->pos.y;
|
|
int32_t scrollregionstart = scrolly;
|
|
int32_t scrollregionend = scrolly + scrollheight;
|
|
if (ud.menu_scrollbartilenum >= 0)
|
|
{
|
|
scrollregionstart += tilesiz[scrollTileTop].y*ud.menu_scrollbarz;
|
|
scrollregionend -= tilesiz[scrollTileBottom].y*ud.menu_scrollbarz;
|
|
}
|
|
const int32_t scrollregionheight = scrollregionend - scrollregionstart - (tilesiz[scrollTileCursor].y*ud.menu_scrollcursorz);
|
|
const int32_t scrollPosMax = totalextent - klabs(format->bottomcutoff);
|
|
|
|
if (scrollTile >= 0)
|
|
{
|
|
// draw the scrollbar (minus the top tile) twice to fill the gaps between tiles
|
|
if (tilesiz[scrollTile].y > 0)
|
|
{
|
|
for (int32_t y = scrollregionstart + ((tilesiz[scrollTileTop].y == 0)*tilesiz[scrollTile].y*ud.menu_scrollbarz); y < scrollregionend; y += tilesiz[scrollTile].y*ud.menu_scrollbarz)
|
|
rotatesprite(scrollx, y - (ud.menu_scrollbarz>>1), ud.menu_scrollbarz, 0, scrollTile, 0, 0, 26, 0, 0, xdim-1, mulscale16(scrollregionend, ydim*200)-1);
|
|
}
|
|
rotatesprite_fs(scrollx, scrollregionend - (ud.menu_scrollbarz>>1), ud.menu_scrollbarz, 0, scrollTileBottom, 0, 0, 26);
|
|
|
|
if (tilesiz[scrollTile].y > 0)
|
|
{
|
|
for (int32_t y = scrollregionstart; y < scrollregionend; y += tilesiz[scrollTile].y*ud.menu_scrollbarz)
|
|
rotatesprite(scrollx, y, ud.menu_scrollbarz, 0, scrollTile, 0, 0, 26, 0, 0, xdim-1, mulscale16(scrollregionend, ydim*200)-1);
|
|
}
|
|
rotatesprite_fs(scrollx, scrolly, ud.menu_scrollbarz, 0, scrollTileTop, 0, 0, 26);
|
|
rotatesprite_fs(scrollx, scrollregionend, ud.menu_scrollbarz, 0, scrollTileBottom, 0, 0, 26);
|
|
}
|
|
else
|
|
Menu_BlackRectangle(scrollx, scrolly, scrollwidth, scrollheight, 1|32);
|
|
|
|
rotatesprite_fs(scrollx + (scrollwidth>>1) - ((tilesiz[scrollTileCursor].x*ud.menu_scrollcursorz)>>1), scrollregionstart + scale(scrollregionheight, *scrollPos, scrollPosMax), ud.menu_scrollcursorz, 0, scrollTileCursor, 0, 0, 26);
|
|
|
|
if (cm == m_currentMenu && !m_mousecaught && MOUSEACTIVECONDITIONAL(inputState.mouseClickState() == MOUSE_PRESSED || inputState.mouseClickState() == MOUSE_HELD))
|
|
{
|
|
const int32_t scrolltilehalfheight = (tilesiz[scrollTileCursor].y*ud.menu_scrollcursorz)>>1;
|
|
const int32_t scrollregiony = scrollregionstart + scrolltilehalfheight;
|
|
|
|
// region between the y-midline of the arrow at the extremes scrolls proportionally
|
|
if (!Menu_MouseOutsideBounds(&m_mousepos, scrollx, scrollregiony, scrollwidth, scrollregionheight))
|
|
{
|
|
*scrollPos = scale(m_mousepos.y - scrollregiony, scrollPosMax, scrollregionheight);
|
|
|
|
m_mousecaught = 1;
|
|
}
|
|
// region outside the y-midlines clamps to the extremes
|
|
else if (!Menu_MouseOutsideBounds(&m_mousepos, scrollx, scrolly, scrollwidth, scrollheight))
|
|
{
|
|
if (m_mousepos.y > scrolly + scrollheight/2)
|
|
*scrollPos = scrollPosMax;
|
|
else
|
|
*scrollPos = 0;
|
|
|
|
m_mousecaught = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
typedef enum MenuMovement_t
|
|
{
|
|
MM_Up = 1,
|
|
MM_End = 3,
|
|
MM_Down = 4,
|
|
MM_Home = 12,
|
|
MM_Left = 16,
|
|
MM_AllTheWayLeft = 48,
|
|
MM_Right = 64,
|
|
MM_AllTheWayRight = 192,
|
|
MM_Swap = 80,
|
|
} MenuMovement_t;
|
|
|
|
static MenuEntry_t *Menu_RunInput_Menu_MovementVerify(MenuMenu_t *menu);
|
|
static MenuEntry_t *Menu_RunInput_Menu_Movement(MenuMenu_t *menu, MenuMovement_t direction);
|
|
static void Menu_RunInput_EntryLink_Activate(MenuEntry_t *entry);
|
|
static void Menu_RunInput_EntryOptionList_MovementVerify(MenuOption_t *object);
|
|
static void Menu_RunInput_EntryOptionList_Movement(MenuOption_t *object, MenuMovement_t direction);
|
|
static int32_t Menu_RunInput_EntryOption_Modify(MenuEntry_t *entry, MenuOption_t *object, int32_t newValueIndex);
|
|
static int32_t Menu_RunInput_EntryOption_Movement(MenuEntry_t *entry, MenuOption_t *object, MenuMovement_t direction);
|
|
static int32_t Menu_RunInput_EntryOption_Activate(MenuEntry_t *entry, MenuOption_t *object);
|
|
static int32_t Menu_RunInput_EntryOptionList_Activate(MenuEntry_t *entry, MenuOption_t *object);
|
|
static void Menu_RunInput_EntryCustom2Col_Activate(MenuEntry_t *entry);
|
|
static void Menu_RunInput_EntryRangeInt32_MovementVerify(MenuEntry_t *entry, MenuRangeInt32_t *object, int32_t newValue);
|
|
static void Menu_RunInput_EntryRangeInt32_MovementArbitrary(MenuEntry_t *entry, MenuRangeInt32_t *object, int32_t newValue);
|
|
static void Menu_RunInput_EntryRangeInt32_Movement(MenuEntry_t *entry, MenuRangeInt32_t *object, MenuMovement_t direction);
|
|
static void Menu_RunInput_EntryRangeFloat_MovementVerify(MenuEntry_t *entry, MenuRangeFloat_t *object, float newValue);
|
|
static void Menu_RunInput_EntryRangeFloat_MovementArbitrary(MenuEntry_t *entry, MenuRangeFloat_t *object, float newValue);
|
|
static void Menu_RunInput_EntryRangeFloat_Movement(MenuEntry_t *entry, MenuRangeFloat_t *object, MenuMovement_t direction);
|
|
#ifdef MENU_ENABLE_RANGEDOUBLE
|
|
static void Menu_RunInput_EntryRangeDouble_MovementVerify(/*MenuEntry_t *entry, */MenuRangeDouble_t *object, double newValue);
|
|
static void Menu_RunInput_EntryRangeDouble_MovementArbitrary(/*MenuEntry_t *entry, */MenuRangeDouble_t *object, double newValue);
|
|
static void Menu_RunInput_EntryRangeDouble_Movement(/*MenuEntry_t *entry, */MenuRangeDouble_t *object, MenuMovement_t direction);
|
|
#endif
|
|
static void Menu_RunInput_EntryString_Activate(MenuEntry_t *entry);
|
|
static void Menu_RunInput_EntryString_Submit(/*MenuEntry_t *entry, */MenuString_t *object);
|
|
static void Menu_RunInput_EntryString_Cancel(/*MenuEntry_t *entry, */MenuString_t *object);
|
|
static void Menu_RunInput_FileSelect_MovementVerify(MenuFileSelect_t *object);
|
|
static void Menu_RunInput_FileSelect_Movement(MenuFileSelect_t *object, MenuMovement_t direction);
|
|
static void Menu_RunInput_FileSelect_Select(MenuFileSelect_t *object);
|
|
|
|
static int32_t M_RunMenu_Menu(Menu_t *cm, MenuMenu_t *menu, MenuEntry_t *currentry, int32_t state, const vec2_t origin, bool actually_draw)
|
|
{
|
|
int32_t totalHeight = 0;
|
|
|
|
// RIP MenuGroup_t b. 2014-03-?? d. 2014-11-29
|
|
{
|
|
int32_t e;
|
|
const int32_t y_upper = menu->format->pos.y;
|
|
const int32_t y_lower = klabs(menu->format->bottomcutoff);
|
|
int32_t y = 0;
|
|
int32_t calculatedentryspacing = 0;
|
|
|
|
if (menu->format->bottomcutoff < 0)
|
|
{
|
|
int32_t totalheight = 0, numvalidentries = 0;
|
|
|
|
for (e = 0; e < menu->numEntries; ++e)
|
|
{
|
|
MenuEntry_t *entry = menu->entrylist[e];
|
|
|
|
if (entry == NULL || (entry->flags & MEF_Hidden))
|
|
continue;
|
|
|
|
++numvalidentries;
|
|
|
|
// assumes height == font->get_yline()!
|
|
totalheight += entry->getHeight();
|
|
}
|
|
|
|
calculatedentryspacing = (klabs(menu->format->bottomcutoff) - menu->format->pos.y - totalheight) / (numvalidentries > 1 ? numvalidentries - 1 : 1);
|
|
}
|
|
|
|
// totalHeight calculating pass
|
|
for (e = 0; e < menu->numEntries; ++e)
|
|
{
|
|
MenuEntry_t *entry = menu->entrylist[e];
|
|
|
|
if (entry == NULL || (entry->flags & MEF_Hidden))
|
|
continue;
|
|
|
|
int32_t const height = entry->getHeight();
|
|
|
|
y += height;
|
|
totalHeight = y;
|
|
y += (!calculatedentryspacing || calculatedentryspacing > entry->getMarginBottom()) ? entry->getMarginBottom() : calculatedentryspacing;
|
|
}
|
|
y = 0;
|
|
|
|
int32_t ydim_upper, ydim_lower;
|
|
if (y_upper + totalHeight > y_lower)
|
|
{
|
|
ydim_upper = ydim_from_200_16(origin.y + y_upper);
|
|
ydim_lower = ydim_from_200_16(origin.y + y_lower);
|
|
}
|
|
else
|
|
{
|
|
ydim_upper = 0;
|
|
ydim_lower = ydim-1;
|
|
}
|
|
|
|
for (e = 0; e < menu->numEntries; ++e)
|
|
{
|
|
MenuEntry_t *entry = menu->entrylist[e];
|
|
|
|
if (entry == NULL || (entry->flags & MEF_Hidden))
|
|
continue;
|
|
|
|
int32_t const indent = entry->getIndent();
|
|
int32_t x = menu->format->pos.x;
|
|
|
|
uint8_t status = 0;
|
|
if (e == menu->currentEntry)
|
|
status |= MT_Selected;
|
|
if (entry->flags & (MEF_Disabled|MEF_LookDisabled))
|
|
status |= MT_Disabled;
|
|
if (entry->format->width == 0)
|
|
status |= MT_XCenter;
|
|
|
|
bool const dodraw = entry->type != Spacer && actually_draw &&
|
|
0 <= y - menu->scrollPos + entry->font->get_yline() &&
|
|
y - menu->scrollPos <= klabs(menu->format->bottomcutoff) - menu->format->pos.y;
|
|
|
|
int32_t const height = entry->getHeight(); // max(textsize.y, entry->font->get_yline()); // bluefont Q ruins this
|
|
status |= MT_YCenter;
|
|
int32_t const y_internal = origin.y + y_upper + y + (height>>1) - menu->scrollPos;
|
|
|
|
vec2_t textsize;
|
|
if (dodraw)
|
|
textsize = Menu_Text(origin.x + x + indent, y_internal, entry->font, entry->name, status, ydim_upper, ydim_lower);
|
|
|
|
if (entry->format->width < 0)
|
|
status |= MT_XRight;
|
|
|
|
if (dodraw && (status & MT_Selected) && state != 1)
|
|
{
|
|
if (status & MT_XCenter)
|
|
{
|
|
Menu_DrawCursorLeft(origin.x + (MENU_MARGIN_CENTER<<16) + entry->font->cursorCenterPosition, y_internal, entry->font->cursorScale);
|
|
Menu_DrawCursorRight(origin.x + (MENU_MARGIN_CENTER<<16) - entry->font->cursorCenterPosition, y_internal, entry->font->cursorScale);
|
|
}
|
|
else
|
|
Menu_DrawCursorLeft(origin.x + x + indent - entry->font->cursorLeftPosition, y_internal, entry->font->cursorScale2);
|
|
}
|
|
|
|
if (entry->name != nullptr && entry->name[0] != '\0')
|
|
status |= MT_RightSide;
|
|
|
|
// need this up here to avoid race conditions
|
|
entry->ybottom = (entry->ytop = y_upper + y) + height;
|
|
|
|
if (dodraw)
|
|
{
|
|
const int32_t mousex = origin.x + indent + entry->format->width == 0 ? x - textsize.x/2 : x;
|
|
const int32_t mousey = origin.y + y_upper + y - menu->scrollPos;
|
|
int32_t mousewidth = entry->format->width == 0 ? textsize.x : klabs(entry->format->width);
|
|
|
|
if (entry->name)
|
|
x += klabs(entry->format->width);
|
|
|
|
switch (entry->type)
|
|
{
|
|
case Spacer:
|
|
break;
|
|
case Dummy:
|
|
if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height)))
|
|
{
|
|
if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height)))
|
|
{
|
|
menu->currentEntry = e;
|
|
Menu_RunInput_Menu_MovementVerify(menu);
|
|
}
|
|
}
|
|
break;
|
|
case Link:
|
|
if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height)))
|
|
{
|
|
if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height)))
|
|
{
|
|
menu->currentEntry = e;
|
|
Menu_RunInput_Menu_MovementVerify(menu);
|
|
}
|
|
|
|
if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, mousex, mousey, mousewidth, entry->font->get_yline()))
|
|
{
|
|
menu->currentEntry = e;
|
|
Menu_RunInput_Menu_MovementVerify(menu);
|
|
|
|
if (entry->flags & MEF_Disabled)
|
|
break;
|
|
|
|
Menu_RunInput_EntryLink_Activate(entry);
|
|
|
|
if (g_player[myconnectindex].ps->gm&MODE_MENU) // for skill selection
|
|
S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
|
|
m_mousecaught = 1;
|
|
}
|
|
}
|
|
break;
|
|
case Option:
|
|
{
|
|
auto *object = (MenuOption_t*)entry->entry;
|
|
int32_t currentOption = Menu_FindOptionBinarySearch(object, object->data == NULL ? Menu_EntryOptionSource(entry, object->currentOption) : *object->data, 0, object->options->numOptions);
|
|
|
|
if (currentOption >= 0)
|
|
object->currentOption = currentOption;
|
|
|
|
int32_t optiontextx = origin.x + x;
|
|
const int32_t optiontexty = origin.y + y_upper + y - menu->scrollPos;
|
|
|
|
const vec2_t optiontextsize = Menu_Text(optiontextx, optiontexty + (height>>1), object->font,
|
|
currentOption < 0 ? MenuCustom : currentOption < object->options->numOptions ? object->options->optionNames[currentOption] : NULL,
|
|
status, ydim_upper, ydim_lower);
|
|
|
|
if (entry->format->width > 0)
|
|
mousewidth += optiontextsize.x;
|
|
else
|
|
optiontextx -= optiontextsize.x;
|
|
|
|
if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height)))
|
|
{
|
|
if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height)))
|
|
{
|
|
menu->currentEntry = e;
|
|
Menu_RunInput_Menu_MovementVerify(menu);
|
|
}
|
|
|
|
if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, mousex, mousey, mousewidth, entry->font->get_yline()))
|
|
{
|
|
menu->currentEntry = e;
|
|
Menu_RunInput_Menu_MovementVerify(menu);
|
|
|
|
if (entry->flags & MEF_Disabled)
|
|
break;
|
|
|
|
Menu_RunInput_EntryOption_Activate(entry, object);
|
|
|
|
S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
|
|
m_mousecaught = 1;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case Custom2Col:
|
|
{
|
|
auto *object = (MenuCustom2Col_t*)entry->entry;
|
|
int32_t columnx[2] = { origin.x + x - ((status & MT_XRight) ? object->columnWidth : 0), origin.x + x + ((status & MT_XRight) ? 0 : object->columnWidth) };
|
|
const int32_t columny = origin.y + y_upper + y - menu->scrollPos;
|
|
|
|
const vec2_t column0textsize = Menu_Text(columnx[0], columny + (height>>1), object->font, object->key[*object->column[0]], menu->currentColumn == 0 ? status : (status & ~MT_Selected), ydim_upper, ydim_lower);
|
|
const vec2_t column1textsize = Menu_Text(columnx[1], columny + (height>>1), object->font, object->key[*object->column[1]], menu->currentColumn == 1 ? status : (status & ~MT_Selected), ydim_upper, ydim_lower);
|
|
|
|
if (entry->format->width > 0)
|
|
mousewidth += object->columnWidth + column1textsize.x;
|
|
else
|
|
{
|
|
columnx[0] -= column0textsize.x;
|
|
columnx[1] -= column0textsize.x;
|
|
}
|
|
|
|
if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height)))
|
|
{
|
|
if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height)))
|
|
{
|
|
menu->currentEntry = e;
|
|
Menu_RunInput_Menu_MovementVerify(menu);
|
|
}
|
|
|
|
if (!Menu_MouseOutsideBounds(&m_mousepos, columnx[1], mousey, column1textsize.x, object->font->get_yline()))
|
|
{
|
|
if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, columnx[1], mousey, column1textsize.x, object->font->get_yline())))
|
|
{
|
|
menu->currentColumn = 1;
|
|
}
|
|
|
|
if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, columnx[1], mousey, column1textsize.x, object->font->get_yline()))
|
|
{
|
|
menu->currentEntry = e;
|
|
Menu_RunInput_Menu_MovementVerify(menu);
|
|
menu->currentColumn = 1;
|
|
|
|
if (entry->flags & MEF_Disabled)
|
|
break;
|
|
|
|
Menu_RunInput_EntryCustom2Col_Activate(entry);
|
|
|
|
S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
|
|
m_mousecaught = 1;
|
|
}
|
|
}
|
|
else if (!Menu_MouseOutsideBounds(&m_mousepos, columnx[0], mousey, column0textsize.x, object->font->get_yline()))
|
|
{
|
|
if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, columnx[0], mousey, column0textsize.x, object->font->get_yline())))
|
|
{
|
|
menu->currentColumn = 0;
|
|
}
|
|
|
|
if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, columnx[0], mousey, column0textsize.x, object->font->get_yline()))
|
|
{
|
|
menu->currentEntry = e;
|
|
Menu_RunInput_Menu_MovementVerify(menu);
|
|
menu->currentColumn = 0;
|
|
|
|
if (entry->flags & MEF_Disabled)
|
|
break;
|
|
|
|
Menu_RunInput_EntryCustom2Col_Activate(entry);
|
|
|
|
S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
|
|
m_mousecaught = 1;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case RangeInt32:
|
|
{
|
|
auto *object = (MenuRangeInt32_t*)entry->entry;
|
|
|
|
int32_t s, p;
|
|
int32_t z = entry->font->cursorScale3;
|
|
Menu_GetFmt(object->font, status|MT_RightSide, &s);
|
|
|
|
if (status & MT_Disabled)
|
|
p = ud.slidebar_paldisabled;
|
|
else if (status & MT_Selected)
|
|
p = ud.slidebar_palselected;
|
|
else
|
|
p = 0;
|
|
|
|
const int32_t slidebarwidth = mulscale16(tilesiz[SLIDEBAR].x * ud.menu_slidebarz, z);
|
|
const int32_t slidebarheight = mulscale16(tilesiz[SLIDEBAR].y * ud.menu_slidebarz, z);
|
|
|
|
if (status & MT_XRight)
|
|
x -= slidebarwidth;
|
|
else
|
|
mousewidth += slidebarwidth;
|
|
|
|
const int32_t slidebarx = origin.x + x;
|
|
const int32_t slidebary = origin.y + y_upper + y + ((height - slidebarheight)>>1) - menu->scrollPos;
|
|
|
|
rotatesprite_ybounds(slidebarx, slidebary, mulscale16(ud.menu_slidebarz, z), 0, SLIDEBAR, s, p, 2|8|16|ROTATESPRITE_FULL16, ydim_upper, ydim_lower);
|
|
|
|
const int32_t cursorTile = RR ? BIGALPHANUM-9 : SLIDEBAR+1;
|
|
const int32_t slideregionwidth = mulscale16((tilesiz[SLIDEBAR].x * ud.menu_slidebarz) - (ud.menu_slidebarmargin<<1) - (tilesiz[cursorTile].x * ud.menu_slidecursorz), z);
|
|
const int32_t slidepointx = slidebarx + mulscale16(ud.menu_slidebarmargin, z) + scale(slideregionwidth, *object->variable - object->min, object->max - object->min);
|
|
const int32_t slidepointy = slidebary + mulscale16(((tilesiz[SLIDEBAR].y * ud.menu_slidebarz) - (tilesiz[cursorTile].y * ud.menu_slidecursorz))>>1, z);
|
|
|
|
rotatesprite_ybounds(slidepointx, slidepointy, mulscale16(ud.menu_slidecursorz, z), 0, cursorTile, s, p, 2|8|16|ROTATESPRITE_FULL16, ydim_upper, ydim_lower);
|
|
|
|
if (object->flags & DisplayTypeMask)
|
|
{
|
|
status |= MT_XRight;
|
|
|
|
int32_t onehundredpercent = object->onehundredpercent;
|
|
if (onehundredpercent == 0)
|
|
onehundredpercent = object->max;
|
|
|
|
switch (object->flags & DisplayTypeMask)
|
|
{
|
|
case DisplayTypeInteger:
|
|
Bsprintf(tempbuf, "%d", *object->variable);
|
|
break;
|
|
case DisplayTypePercent:
|
|
Bsprintf(tempbuf, "%d%%", roundscale(*object->variable, 100, onehundredpercent));
|
|
break;
|
|
case DisplayTypeNormalizedDecimal:
|
|
Bsprintf(tempbuf, "%.2f", (double) *object->variable / (double) onehundredpercent);
|
|
break;
|
|
}
|
|
|
|
Menu_Text(origin.x + x - (4<<16), origin.y + y_upper + y + (height>>1) - menu->scrollPos, object->font, tempbuf, status, ydim_upper, ydim_lower);
|
|
}
|
|
|
|
if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height)))
|
|
{
|
|
if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height)))
|
|
{
|
|
menu->currentEntry = e;
|
|
Menu_RunInput_Menu_MovementVerify(menu);
|
|
}
|
|
|
|
if (!m_mousecaught && (inputState.mouseClickState() == MOUSE_PRESSED || inputState.mouseClickState() == MOUSE_HELD))
|
|
{
|
|
const int32_t slidepointhalfwidth = mulscale16((((tilesiz[cursorTile].x)*ud.menu_slidecursorz)>>2) + ud.menu_slidebarmargin, z);
|
|
const int32_t slideregionx = slidebarx + slidepointhalfwidth;
|
|
|
|
menu->currentEntry = e;
|
|
Menu_RunInput_Menu_MovementVerify(menu);
|
|
|
|
if (entry->flags & MEF_Disabled)
|
|
break;
|
|
|
|
// region between the x-midline of the slidepoint at the extremes slides proportionally
|
|
if (!Menu_MouseOutsideBounds(&m_mousepos, slideregionx, mousey, slideregionwidth, height))
|
|
{
|
|
Menu_RunInput_EntryRangeInt32_MovementArbitrary(entry, object, roundscale(object->max - object->min, m_mousepos.x - slideregionx, slideregionwidth) + object->min);
|
|
|
|
m_mousecaught = 1;
|
|
}
|
|
// region outside the x-midlines clamps to the extremes
|
|
else if (!Menu_MouseOutsideBounds(&m_mousepos, slidebarx, mousey, slidebarwidth, height))
|
|
{
|
|
if (m_mousepos.x > slideregionx + slideregionwidth/2)
|
|
Menu_RunInput_EntryRangeInt32_MovementVerify(entry, object, object->max);
|
|
else
|
|
Menu_RunInput_EntryRangeInt32_MovementVerify(entry, object, object->min);
|
|
|
|
m_mousecaught = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case RangeFloat:
|
|
{
|
|
auto *object = (MenuRangeFloat_t*)entry->entry;
|
|
|
|
int32_t s, p;
|
|
int32_t z = entry->font->cursorScale3;
|
|
Menu_GetFmt(object->font, status|MT_RightSide, &s);
|
|
|
|
if (status & MT_Disabled)
|
|
p = ud.slidebar_paldisabled;
|
|
else if (status & MT_Selected)
|
|
p = ud.slidebar_palselected;
|
|
else
|
|
p = 0;
|
|
|
|
const int32_t slidebarwidth = mulscale16(tilesiz[SLIDEBAR].x * ud.menu_slidebarz, z);
|
|
const int32_t slidebarheight = mulscale16(tilesiz[SLIDEBAR].y * ud.menu_slidebarz, z);
|
|
|
|
if (status & MT_XRight)
|
|
x -= slidebarwidth;
|
|
else
|
|
mousewidth += slidebarwidth;
|
|
|
|
const int32_t slidebarx = origin.x + x;
|
|
const int32_t slidebary = origin.y + y_upper + y + ((height - slidebarheight)>>1) - menu->scrollPos;
|
|
|
|
rotatesprite_ybounds(slidebarx, slidebary, mulscale16(ud.menu_slidebarz, z), 0, SLIDEBAR, s, p, 2|8|16|ROTATESPRITE_FULL16, ydim_upper, ydim_lower);
|
|
|
|
const int32_t cursorTile = RR ? BIGALPHANUM-9 : SLIDEBAR+1;
|
|
const int32_t slideregionwidth = mulscale16((tilesiz[SLIDEBAR].x * ud.menu_slidebarz) - (ud.menu_slidebarmargin<<1) - (tilesiz[cursorTile].x * ud.menu_slidecursorz), z);
|
|
const int32_t slidepointx = slidebarx + mulscale16(ud.menu_slidebarmargin, z) + Blrintf((float) slideregionwidth * (*object->variable - object->min) / (object->max - object->min));
|
|
const int32_t slidepointy = slidebary + mulscale16(((tilesiz[SLIDEBAR].y * ud.menu_slidebarz) - (tilesiz[cursorTile].y * ud.menu_slidecursorz))>>1, z);
|
|
|
|
rotatesprite_ybounds(slidepointx, slidepointy, mulscale16(ud.menu_slidecursorz, z), 0, cursorTile, s, p, 2|8|16|ROTATESPRITE_FULL16, ydim_upper, ydim_lower);
|
|
|
|
if (object->flags & DisplayTypeMask)
|
|
{
|
|
status |= MT_XRight;
|
|
|
|
float onehundredpercent = object->onehundredpercent;
|
|
if (onehundredpercent == 0.f)
|
|
onehundredpercent = 1.f;
|
|
|
|
switch (object->flags & DisplayTypeMask)
|
|
{
|
|
case DisplayTypeInteger:
|
|
Bsprintf(tempbuf, "%.2f", *object->variable);
|
|
break;
|
|
case DisplayTypePercent:
|
|
Bsprintf(tempbuf, "%ld%%", lrintf(*object->variable * 100.f / onehundredpercent));
|
|
break;
|
|
case DisplayTypeNormalizedDecimal:
|
|
Bsprintf(tempbuf, "%.2f", *object->variable / onehundredpercent);
|
|
break;
|
|
}
|
|
|
|
Menu_Text(origin.x + x - (4<<16), origin.y + y_upper + y + (height>>1) - menu->scrollPos, object->font, tempbuf, status, ydim_upper, ydim_lower);
|
|
}
|
|
|
|
if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height)))
|
|
{
|
|
if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height)))
|
|
{
|
|
menu->currentEntry = e;
|
|
Menu_RunInput_Menu_MovementVerify(menu);
|
|
}
|
|
|
|
if (!m_mousecaught && (inputState.mouseClickState() == MOUSE_PRESSED || inputState.mouseClickState() == MOUSE_HELD))
|
|
{
|
|
const int32_t slidepointhalfwidth = mulscale16((2+tilesiz[cursorTile].x)<<15, z);
|
|
const int32_t slideregionx = slidebarx + slidepointhalfwidth;
|
|
|
|
menu->currentEntry = e;
|
|
Menu_RunInput_Menu_MovementVerify(menu);
|
|
|
|
if (entry->flags & MEF_Disabled)
|
|
break;
|
|
|
|
// region between the x-midline of the slidepoint at the extremes slides proportionally
|
|
if (!Menu_MouseOutsideBounds(&m_mousepos, slideregionx, mousey, slideregionwidth, height))
|
|
{
|
|
Menu_RunInput_EntryRangeFloat_MovementArbitrary(entry, object, (object->max - object->min) * (m_mousepos.x - slideregionx) / slideregionwidth + object->min);
|
|
|
|
m_mousecaught = 1;
|
|
}
|
|
// region outside the x-midlines clamps to the extremes
|
|
else if (!Menu_MouseOutsideBounds(&m_mousepos, slidebarx, mousey, slidebarwidth, height))
|
|
{
|
|
if (m_mousepos.x > slideregionx + slideregionwidth/2)
|
|
Menu_RunInput_EntryRangeFloat_MovementVerify(entry, object, object->max);
|
|
else
|
|
Menu_RunInput_EntryRangeFloat_MovementVerify(entry, object, object->min);
|
|
|
|
m_mousecaught = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
#ifdef MENU_ENABLE_RANGEDOUBLE
|
|
case RangeDouble:
|
|
{
|
|
MenuRangeDouble_t *object = (MenuRangeDouble_t*)entry->entry;
|
|
|
|
int32_t s, p;
|
|
int32_t z = entry->font->cursorScale3;
|
|
Menu_GetFmt(object->font, status|MT_RightSide, &s);
|
|
|
|
if (status & MT_Disabled)
|
|
p = ud.slidebar_paldisabled;
|
|
else if (status & MT_Selected)
|
|
p = ud.slidebar_palselected;
|
|
else
|
|
p = 0;
|
|
|
|
const int32_t slidebarwidth = mulscale16(tilesiz[SLIDEBAR].x * ud.menu_slidebarz, z);
|
|
const int32_t slidebarheight = mulscale16(tilesiz[SLIDEBAR].y * ud.menu_slidebarz, z);
|
|
|
|
if (status & MT_XRight)
|
|
x -= slidebarwidth;
|
|
else
|
|
mousewidth += slidebarwidth;
|
|
|
|
const int32_t slidebarx = origin.x + x;
|
|
const int32_t slidebary = origin.y + y_upper + y + ((height - slidebarheight)>>1) - menu->scrollPos;
|
|
|
|
rotatesprite_ybounds(slidebarx, slidebary, mulscale16(ud.menu_slidebarz, z), 0, SLIDEBAR, s, p, 2|8|16|ROTATESPRITE_FULL16, ydim_upper, ydim_lower);
|
|
|
|
const int32_t cursorTile = RR ? BIGALPHANUM-9 : SLIDEBAR+1;
|
|
const int32_t slideregionwidth = mulscale16((tilesiz[SLIDEBAR].x * ud.menu_slidebarz) - (ud.menu_slidebarmargin<<1) - (tilesiz[cursorTile].x * ud.menu_slidecursorz), z);
|
|
const int32_t slidepointx = slidebarx + mulscale16(ud.menu_slidebarmargin, z) + lrint((double) slideregionwidth * (*object->variable - object->min) / (object->max - object->min));
|
|
const int32_t slidepointy = slidebary + mulscale16(((tilesiz[SLIDEBAR].y * ud.menu_slidebarz) - (tilesiz[cursorTile].y * ud.menu_slidecursorz))>>1, z);
|
|
|
|
rotatesprite_ybounds(slidepointx, slidepointy, mulscale16(ud.menu_slidecursorz, z), 0, cursorTile, s, p, 2|8|16|ROTATESPRITE_FULL16, ydim_upper, ydim_lower);
|
|
|
|
if (object->flags & DisplayTypeMask)
|
|
{
|
|
status |= MT_XRight;
|
|
|
|
double onehundredpercent = object->onehundredpercent;
|
|
if (onehundredpercent == 0.)
|
|
onehundredpercent = 1.;
|
|
|
|
switch (object->flags & DisplayTypeMask)
|
|
{
|
|
case DisplayTypeInteger:
|
|
Bsprintf(tempbuf, "%.2f", *object->variable);
|
|
break;
|
|
case DisplayTypePercent:
|
|
Bsprintf(tempbuf, "%ld%%", lrint(*object->variable * 100. / onehundredpercent));
|
|
break;
|
|
case DisplayTypeNormalizedDecimal:
|
|
Bsprintf(tempbuf, "%.2f", *object->variable / onehundredpercent);
|
|
break;
|
|
}
|
|
|
|
Menu_Text(origin.x + x - (4<<16), origin.y + y_upper + y + (height>>1) - menu->scrollPos, object->font, tempbuf, status, ydim_upper, ydim_lower);
|
|
}
|
|
|
|
if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height)))
|
|
{
|
|
if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height)))
|
|
{
|
|
menu->currentEntry = e;
|
|
Menu_RunInput_Menu_MovementVerify(menu);
|
|
}
|
|
|
|
if (!m_mousecaught && (inputState.mouseClickState() == MOUSE_PRESSED || inputState.mouseClickState() == MOUSE_HELD))
|
|
{
|
|
const int32_t slidepointhalfwidth = mulscale16((2+tilesiz[cursorTile].x)<<15, z);
|
|
const int32_t slideregionx = slidebarx + slidepointhalfwidth;
|
|
|
|
menu->currentEntry = e;
|
|
Menu_RunInput_Menu_MovementVerify(menu);
|
|
|
|
if (entry->flags & MEF_Disabled)
|
|
break;
|
|
|
|
// region between the x-midline of the slidepoint at the extremes slides proportionally
|
|
if (!Menu_MouseOutsideBounds(&m_mousepos, slideregionx, mousey, slideregionwidth, height))
|
|
{
|
|
Menu_RunInput_EntryRangeDouble_MovementArbitrary(/*entry, */object, (object->max - object->min) * (m_mousepos.x - slideregionx) / slideregionwidth + object->min);
|
|
|
|
m_mousecaught = 1;
|
|
}
|
|
// region outside the x-midlines clamps to the extremes
|
|
else if (!Menu_MouseOutsideBounds(&m_mousepos, slidebarx, mousey, slidebarwidth, height))
|
|
{
|
|
if (m_mousepos.x > slideregionx + slideregionwidth/2)
|
|
Menu_RunInput_EntryRangeDouble_MovementVerify(/*entry, */object, object->max);
|
|
else
|
|
Menu_RunInput_EntryRangeDouble_MovementVerify(/*entry, */object, object->min);
|
|
|
|
m_mousecaught = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
#endif
|
|
case String:
|
|
{
|
|
auto *object = (MenuString_t*)entry->entry;
|
|
|
|
vec2_t dim;
|
|
int32_t stringx = x;
|
|
const int32_t stringy = origin.y + y_upper + y + (height>>1) - menu->scrollPos;
|
|
int32_t h;
|
|
|
|
if (entry == currentry && object->editfield != NULL)
|
|
{
|
|
dim = Menu_Text(origin.x + stringx, stringy, object->font, object->editfield, (status & ~MT_Disabled) | MT_Literal, ydim_upper, ydim_lower);
|
|
h = max(dim.y, entry->font->get_yline());
|
|
|
|
Menu_DrawCursorText(origin.x + x + dim.x + (1<<16), stringy, h, ydim_upper, ydim_lower);
|
|
}
|
|
else
|
|
{
|
|
dim = Menu_Text(origin.x + stringx, stringy, object->font, object->variable, status, ydim_upper, ydim_lower);
|
|
h = max(dim.y, entry->font->get_yline());
|
|
}
|
|
|
|
if (entry->format->width > 0)
|
|
{
|
|
if (entry->name)
|
|
mousewidth += dim.x;
|
|
}
|
|
else
|
|
stringx -= dim.x;
|
|
|
|
if (MOUSEACTIVECONDITIONAL(cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, h)))
|
|
{
|
|
if (state != 1 && Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, h))
|
|
{
|
|
menu->currentEntry = e;
|
|
Menu_RunInput_Menu_MovementVerify(menu);
|
|
}
|
|
|
|
#ifndef EDUKE32_TOUCH_DEVICES
|
|
if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, h) && !Menu_MouseOutsideBounds(&m_mousedownpos, mousex, mousey, mousewidth, h))
|
|
#endif
|
|
{
|
|
if (entry == currentry && object->editfield != NULL)
|
|
{
|
|
Menu_RunInput_EntryString_Submit(/*entry, */object);
|
|
|
|
S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
|
|
m_mousecaught = 1;
|
|
}
|
|
else if (state != 1)
|
|
{
|
|
menu->currentEntry = e;
|
|
Menu_RunInput_Menu_MovementVerify(menu);
|
|
|
|
if (entry->flags & MEF_Disabled)
|
|
break;
|
|
|
|
Menu_RunInput_EntryString_Activate(entry);
|
|
|
|
S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
|
|
m_mousecaught = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// prepare for the next line
|
|
y += height;
|
|
y += (!calculatedentryspacing || calculatedentryspacing > entry->getMarginBottom()) ? entry->getMarginBottom() : calculatedentryspacing;
|
|
}
|
|
|
|
// draw indicators if applicable
|
|
if (actually_draw)
|
|
Menu_RunScrollbar(cm, menu->format, y_upper + totalHeight, &menu->scrollPos, 320<<16, origin);
|
|
}
|
|
|
|
return totalHeight;
|
|
}
|
|
|
|
static void M_RunMenu_CdPlayer(Menu_t *cm, MenuMenu_t *menu, const vec2_t origin)
|
|
{
|
|
static const vec2_t entryPos[8] = {
|
|
{ 22, 15 }, { 64, 15 }, { 104, 15 }, { 142, 15 },
|
|
{ 22, 25 }, { 64, 25 }, { 104, 25 }, { 142, 25 },
|
|
};
|
|
|
|
// RIP MenuGroup_t b. 2014-03-?? d. 2014-11-29
|
|
{
|
|
int32_t e;
|
|
|
|
for (e = 0; e < menu->numEntries; ++e)
|
|
{
|
|
const int32_t x = entryPos[e].x-154+(MENU_MARGIN_CENTER<<1);
|
|
const int32_t y = entryPos[e].y+65;
|
|
|
|
const int32_t mousex = origin.x+(x<<15)-(4<<16);
|
|
const int32_t mousey = origin.y+(y<<16)-(4<<16);
|
|
|
|
if (e == menu->currentEntry && mus_enabled)
|
|
rotatesprite_fs(origin.x+(x<<15), origin.y+(y<<16), 32768, 0, CDPLAYER+1, 16, 0, 10);
|
|
|
|
|
|
if (MOUSEACTIVECONDITIONAL(cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, 8<<16, 8<<16)))
|
|
{
|
|
if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED)
|
|
{
|
|
menu->currentEntry = e;
|
|
|
|
S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
|
|
if (MusicEnabled())
|
|
{
|
|
S_StopMusic();
|
|
S_PlayRRMusic(2+menu->currentEntry);
|
|
}
|
|
|
|
m_mousecaught = 1;
|
|
}
|
|
}
|
|
//switch (entry->type)
|
|
//{
|
|
// case Spacer:
|
|
// break;
|
|
// case Dummy:
|
|
//if (MOUSEACTIVECONDITIONAL(state != 1 && cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, height)))
|
|
//{
|
|
// if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, height)))
|
|
// {
|
|
// menu->currentEntry = e;
|
|
// Menu_RunInput_Menu_MovementVerify(menu);
|
|
// }
|
|
//}
|
|
//break;
|
|
//}
|
|
}
|
|
}
|
|
|
|
const int32_t mousex = origin.x+((MENU_MARGIN_CENTER-60)<<16)-(8<<16);
|
|
const int32_t mousey = origin.y+(113<<16)-(8<<16);
|
|
if (MOUSEACTIVECONDITIONAL(cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, 16<<16, 16<<16)))
|
|
{
|
|
if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED)
|
|
{
|
|
mus_enabled = !mus_enabled;
|
|
|
|
if (mus_enabled == 0)
|
|
S_PauseMusic(true);
|
|
else
|
|
{
|
|
S_PlayRRMusic(2+menu->currentEntry);
|
|
S_PauseMusic(false);
|
|
}
|
|
|
|
m_mousecaught = 1;
|
|
}
|
|
}
|
|
|
|
if (mus_enabled)
|
|
rotatesprite_fs(origin.x+((MENU_MARGIN_CENTER-60)<<16), origin.y+(113<<16), 32768, 0, CDPLAYER+3, 16, 0, 10);
|
|
else
|
|
rotatesprite_fs(origin.x+((MENU_MARGIN_CENTER-60)<<16), origin.y+(113<<16), 32768, 0, CDPLAYER+2, 16, 0, 10);
|
|
|
|
return;
|
|
}
|
|
|
|
static void Menu_RunOptionList(Menu_t *cm, MenuEntry_t *entry, MenuOption_t *object, const vec2_t origin)
|
|
{
|
|
int32_t e, y = 0;
|
|
const int32_t y_upper = object->options->menuFormat->pos.y;
|
|
const int32_t y_lower = object->options->menuFormat->bottomcutoff;
|
|
int32_t calculatedentryspacing = object->options->getMarginBottom();
|
|
|
|
// assumes height == font->get_yline()!
|
|
if (calculatedentryspacing < 0)
|
|
calculatedentryspacing = (-calculatedentryspacing - object->options->font->get_yline()) / (object->options->numOptions - 1) - object->options->font->get_yline();
|
|
|
|
int32_t totalHeight = 0;
|
|
for (e = 0; e < object->options->numOptions; ++e)
|
|
{
|
|
int32_t const height = object->options->font->get_yline();
|
|
|
|
y += height;
|
|
totalHeight = y;
|
|
y += calculatedentryspacing;
|
|
}
|
|
y = 0;
|
|
|
|
int32_t ydim_upper, ydim_lower;
|
|
if (y_upper + totalHeight > y_lower)
|
|
{
|
|
ydim_upper = ydim_from_200_16(origin.y + y_upper);
|
|
ydim_lower = ydim_from_200_16(origin.y + y_lower);
|
|
}
|
|
else
|
|
{
|
|
ydim_upper = 0;
|
|
ydim_lower = ydim-1;
|
|
}
|
|
|
|
for (e = 0; e < object->options->numOptions; ++e)
|
|
{
|
|
int32_t const x = object->options->menuFormat->pos.x;
|
|
|
|
uint8_t status = 0;
|
|
if (e == object->options->currentEntry)
|
|
status |= MT_Selected;
|
|
if (object->options->entryFormat->width == 0)
|
|
status |= MT_XCenter;
|
|
|
|
bool const dodraw = 0 <= y - object->options->scrollPos + object->options->font->get_yline() &&
|
|
y - object->options->scrollPos <= object->options->menuFormat->bottomcutoff - object->options->menuFormat->pos.y;
|
|
|
|
int32_t const height = object->options->font->get_yline(); // max(textsize.y, object->options->font->get_yline());
|
|
status |= MT_YCenter;
|
|
int32_t const y_internal = origin.y + y_upper + y + (height>>1) - object->options->scrollPos;
|
|
|
|
vec2_t textsize;
|
|
if (dodraw)
|
|
textsize = Menu_Text(origin.x + x, y_internal, object->options->font, object->options->optionNames[e], status, ydim_upper, ydim_lower);
|
|
|
|
if (object->options->entryFormat->width < 0)
|
|
status |= MT_XRight;
|
|
|
|
if (dodraw && (status & MT_Selected))
|
|
{
|
|
if (status & MT_XCenter)
|
|
{
|
|
Menu_DrawCursorLeft(origin.x + (MENU_MARGIN_CENTER<<16) + object->options->font->cursorCenterPosition, y_internal, object->options->font->cursorScale);
|
|
Menu_DrawCursorRight(origin.x + (MENU_MARGIN_CENTER<<16) - object->options->font->cursorCenterPosition, y_internal, object->options->font->cursorScale);
|
|
}
|
|
else
|
|
Menu_DrawCursorLeft(origin.x + x - object->options->font->cursorLeftPosition, y_internal, object->options->font->cursorScale2);
|
|
}
|
|
|
|
if (dodraw)
|
|
{
|
|
const int32_t mousex = origin.x + object->options->entryFormat->width == 0 ? x - textsize.x/2 : x;
|
|
const int32_t mousey = origin.y + y_upper + y - object->options->scrollPos;
|
|
const int32_t mousewidth = object->options->entryFormat->width == 0 ? textsize.x : klabs(object->options->entryFormat->width);
|
|
|
|
if (MOUSEACTIVECONDITIONAL(cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, mousewidth, object->options->font->get_yline())))
|
|
{
|
|
if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, mousewidth, object->options->font->get_yline())))
|
|
{
|
|
object->options->currentEntry = e;
|
|
}
|
|
|
|
if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, mousex, mousey, mousewidth, object->options->font->get_yline()))
|
|
{
|
|
object->options->currentEntry = e;
|
|
|
|
if (!Menu_RunInput_EntryOptionList_Activate(entry, object))
|
|
S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
|
|
m_mousecaught = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// prepare for the next line
|
|
y += height;
|
|
y += calculatedentryspacing;
|
|
}
|
|
|
|
// draw indicators if applicable
|
|
Menu_RunScrollbar(cm, object->options->menuFormat, y_upper + totalHeight, &object->options->scrollPos, 320<<16, origin);
|
|
}
|
|
|
|
static int32_t Menu_RunInput_MouseAdvance(void)
|
|
{
|
|
return MOUSEACTIVECONDITIONAL(!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED);
|
|
}
|
|
|
|
static int32_t Menu_RunInput_MouseReturn_status;
|
|
|
|
#if !defined EDUKE32_TOUCH_DEVICES
|
|
static void Menu_Run_MouseReturn(Menu_t *cm, const vec2_t origin)
|
|
{
|
|
if (!MOUSEACTIVECONDITION)
|
|
return;
|
|
|
|
if (cm->menuID == MENU_MAIN)
|
|
return;
|
|
|
|
uint32_t const posx = tilesiz[SELECTDIR].y * SELECTDIR_z;
|
|
|
|
rotatesprite_(origin.x + posx, 0, SELECTDIR_z, 512, SELECTDIR,
|
|
Menu_RunInput_MouseReturn_status ? 4 - (sintable[((int32_t) totalclock << 4) & 2047] >> 11) : 6, 0,
|
|
2 | 8 | 16 | RS_ALIGN_L, MOUSEALPHA, 0, xdim_from_320_16(origin.x + x_widescreen_left()), 0,
|
|
xdim_from_320_16(origin.x + x_widescreen_left() + (posx>>1)), ydim - 1);
|
|
}
|
|
#endif
|
|
|
|
static int32_t Menu_RunInput_MouseReturn(void)
|
|
{
|
|
#if !defined EDUKE32_TOUCH_DEVICES
|
|
if (!MOUSEACTIVECONDITION)
|
|
{
|
|
Menu_RunInput_MouseReturn_status = 0;
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
if (g_currentMenu == MENU_MAIN)
|
|
return 0;
|
|
|
|
const int32_t MouseReturnRegionX = x_widescreen_left();
|
|
|
|
vec2_t backbuttonbound = { (tilesiz[SELECTDIR].y * SELECTDIR_z)>>1, tilesiz[SELECTDIR].x * SELECTDIR_z };
|
|
|
|
if (!Menu_MouseOutsideBounds(&m_mousepos, MouseReturnRegionX, 0, backbuttonbound.x, backbuttonbound.y))
|
|
{
|
|
#if !defined EDUKE32_TOUCH_DEVICES
|
|
Menu_RunInput_MouseReturn_status = 1;
|
|
#else
|
|
Menu_RunInput_MouseReturn_status = (inputState.mouseClickState() == MOUSE_PRESSED || inputState.mouseClickState() == MOUSE_HELD);
|
|
#endif
|
|
|
|
return !m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, MouseReturnRegionX, 0, backbuttonbound.x, backbuttonbound.y);
|
|
}
|
|
|
|
Menu_RunInput_MouseReturn_status = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void Menu_Run_AbbreviateNameIntoBuffer(const char* name, int32_t entrylength)
|
|
{
|
|
int32_t len = Bstrlen(name);
|
|
Bstrncpy(tempbuf, name, ARRAY_SIZE(tempbuf));
|
|
if (len > entrylength)
|
|
{
|
|
len = entrylength-3;
|
|
tempbuf[len] = 0;
|
|
while (len < entrylength)
|
|
tempbuf[len++] = '.';
|
|
}
|
|
tempbuf[len] = 0;
|
|
}
|
|
|
|
static void Menu_Recurse(MenuID_t cm, const vec2_t origin)
|
|
{
|
|
switch (cm)
|
|
{
|
|
case MENU_SAVECLEANVERIFY:
|
|
case MENU_LOADVERIFY:
|
|
case MENU_LOADDELVERIFY:
|
|
case MENU_SAVEVERIFY:
|
|
case MENU_SAVEDELVERIFY:
|
|
case MENU_ADULTPASSWORD:
|
|
case MENU_CHEATENTRY:
|
|
case MENU_CHEAT_WARP:
|
|
case MENU_CHEAT_SKILL:
|
|
Menu_Run(m_previousMenu, origin);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void Menu_Run(Menu_t *cm, const vec2_t origin)
|
|
{
|
|
Menu_Recurse(cm->menuID, origin);
|
|
|
|
switch (cm->type)
|
|
{
|
|
case Verify:
|
|
{
|
|
auto *object = (MenuVerify_t*)cm->object;
|
|
|
|
Menu_Pre(cm->menuID);
|
|
|
|
Menu_PreDrawBackground(cm->menuID, origin);
|
|
|
|
Menu_PreDraw(cm->menuID, NULL, origin);
|
|
|
|
Menu_DrawCursorLeft(origin.x + object->cursorpos.x, origin.y + object->cursorpos.y, RR ? 3276 : 65536);
|
|
|
|
break;
|
|
}
|
|
|
|
case Message:
|
|
{
|
|
auto *object = (MenuMessage_t*)cm->object;
|
|
|
|
Menu_Pre(cm->menuID);
|
|
|
|
Menu_PreDrawBackground(cm->menuID, origin);
|
|
|
|
Menu_PreDraw(cm->menuID, NULL, origin);
|
|
|
|
Menu_DrawCursorLeft(origin.x + object->cursorpos.x, origin.y + object->cursorpos.y, RR ? 3276 : 65536);
|
|
|
|
break;
|
|
}
|
|
|
|
case TextForm:
|
|
{
|
|
auto *object = (MenuTextForm_t*)cm->object;
|
|
|
|
Menu_Pre(cm->menuID);
|
|
|
|
Menu_PreDrawBackground(cm->menuID, origin);
|
|
|
|
Menu_BlackRectangle(origin.x + (60<<16), origin.y + (86<<16), 200<<16, 28<<16, 0);
|
|
|
|
mgametextcenter(origin.x, origin.y + (98<<16), object->instructions, TEXT_YBOTTOM);
|
|
|
|
const char *displaytext = object->input;
|
|
|
|
if (object->flags & MTF_Password)
|
|
{
|
|
size_t x;
|
|
for (x = 0; x < Bstrlen(object->input); ++x)
|
|
tempbuf[x] = '*';
|
|
tempbuf[x] = 0;
|
|
|
|
displaytext = tempbuf;
|
|
}
|
|
|
|
const vec2_t textreturn = mgametextcenter(origin.x, origin.y + (102<<16), displaytext);
|
|
|
|
Menu_PreDraw(cm->menuID, NULL, origin);
|
|
|
|
int32_t const h = MF_Bluefont.get_yline();
|
|
|
|
Menu_DrawCursorText(origin.x + (MENU_MARGIN_CENTER<<16) + (textreturn.x>>1) + (1<<16), origin.y + (102<<16) + (h>>1), h);
|
|
|
|
break;
|
|
}
|
|
|
|
case FileSelect:
|
|
{
|
|
#if 0
|
|
auto *object = (MenuFileSelect_t*)cm->object;
|
|
const int32_t MenuFileSelect_scrollbar_rightedge[2] = { 160<<16, 284<<16 };
|
|
int32_t i, selected = 0;
|
|
|
|
Menu_Pre(cm->menuID);
|
|
|
|
Menu_PreDrawBackground(cm->menuID, origin);
|
|
|
|
if (object->title != NoTitle)
|
|
Menu_DrawTopBar(origin);
|
|
|
|
|
|
// black translucent background underneath file lists
|
|
Menu_BlackRectangle(origin.x + (36<<16), origin.y + (42<<16), 248<<16, 123<<16, 1|32);
|
|
|
|
// path
|
|
Bsnprintf(tempbuf, sizeof(tempbuf), "Path: %s", object->destination);
|
|
mgametext(origin.x + object->format[0]->pos.x, origin.y + (32<<16), tempbuf);
|
|
|
|
uint8_t column_status[2] = { 0, MT_RightSide };
|
|
|
|
for (i = 0; i < 2; ++i)
|
|
{
|
|
if (object->findhigh[i])
|
|
{
|
|
CACHE1D_FIND_REC *dir;
|
|
int32_t y = 0;
|
|
const int32_t y_upper = object->format[i]->pos.y;
|
|
const int32_t y_lower = klabs(object->format[i]->bottomcutoff);
|
|
|
|
int32_t totalHeight = 0;
|
|
for (dir = object->findhigh[i]->usera; dir; dir = dir->next)
|
|
{
|
|
y += object->font[i]->get_yline();
|
|
totalHeight = y;
|
|
y += object->getMarginBottom(i);
|
|
}
|
|
y = 0;
|
|
|
|
int32_t ydim_upper, ydim_lower;
|
|
if (y_upper + totalHeight > y_lower)
|
|
{
|
|
ydim_upper = ydim_from_200_16(origin.y + y_upper);
|
|
ydim_lower = ydim_from_200_16(origin.y + y_lower);
|
|
}
|
|
else
|
|
{
|
|
ydim_upper = 0;
|
|
ydim_lower = ydim-1;
|
|
}
|
|
|
|
for (dir = object->findhigh[i]->usera; dir; dir = dir->next)
|
|
{
|
|
uint8_t status = column_status[i];
|
|
if (dir == object->findhigh[i] && object->currentList == i)
|
|
status |= MT_Selected;
|
|
|
|
Menu_Run_AbbreviateNameIntoBuffer(dir->name, USERMAPENTRYLENGTH);
|
|
|
|
const int32_t thisx = object->format[i]->pos.x;
|
|
const int32_t thisy = y - object->scrollPos[i];
|
|
|
|
int32_t const height = object->font[i]->get_yline();
|
|
|
|
if (0 <= thisy + height && thisy <= klabs(object->format[i]->bottomcutoff) - object->format[i]->pos.y)
|
|
{
|
|
status |= MT_YCenter;
|
|
|
|
const int32_t mousex = origin.x + thisx;
|
|
const int32_t mousey = origin.y + y_upper + thisy + (height>>1);
|
|
|
|
vec2_t textdim = Menu_Text(mousex, mousey, object->font[i], tempbuf, status, ydim_upper, ydim_lower);
|
|
|
|
if (MOUSEACTIVECONDITIONAL(cm == m_currentMenu && !Menu_MouseOutsideBounds(&m_mousepos, mousex, mousey, textdim.x, object->font[i]->get_yline())))
|
|
{
|
|
if (MOUSEWATCHPOINTCONDITIONAL(Menu_MouseOutsideBounds(&m_prevmousepos, mousex, mousey, textdim.x, object->font[i]->get_yline())))
|
|
{
|
|
object->findhigh[i] = dir;
|
|
object->currentList = i;
|
|
|
|
Menu_RunInput_FileSelect_MovementVerify(object);
|
|
}
|
|
|
|
if (!m_mousecaught && inputState.mouseClickState() == MOUSE_RELEASED && !Menu_MouseOutsideBounds(&m_mousedownpos, mousex, mousey, textdim.x, object->font[i]->get_yline()))
|
|
{
|
|
object->findhigh[i] = dir;
|
|
object->currentList = i;
|
|
|
|
Menu_RunInput_FileSelect_MovementVerify(object);
|
|
|
|
m_mousecaught = 1;
|
|
selected = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
y += object->font[i]->get_yline() + object->getMarginBottom(i);
|
|
}
|
|
|
|
Menu_RunScrollbar(cm, object->format[i], y_upper + totalHeight, &object->scrollPos[i], MenuFileSelect_scrollbar_rightedge[i], origin);
|
|
}
|
|
}
|
|
|
|
Menu_PreDraw(cm->menuID, NULL, origin);
|
|
|
|
if (object->title != NoTitle)
|
|
Menu_DrawTopBarCaption(object->title, origin);
|
|
|
|
if (selected)
|
|
{
|
|
Menu_RunInput_FileSelect_Select(object);
|
|
|
|
S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
|
|
m_mousecaught = 1;
|
|
}
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
case Panel:
|
|
{
|
|
auto *object = (MenuPanel_t*)cm->object;
|
|
|
|
Menu_Pre(cm->menuID);
|
|
|
|
Menu_PreDrawBackground(cm->menuID, origin);
|
|
|
|
if (object->title != NoTitle)
|
|
Menu_DrawTopBar(origin);
|
|
|
|
Menu_PreDraw(cm->menuID, NULL, origin);
|
|
|
|
if (object->title != NoTitle)
|
|
Menu_DrawTopBarCaption(object->title, origin);
|
|
|
|
break;
|
|
}
|
|
|
|
case CdPlayer:
|
|
{
|
|
auto *menu = (MenuMenu_t*)cm->object;
|
|
Menu_Pre(cm->menuID);
|
|
|
|
Menu_PreDrawBackground(cm->menuID, origin);
|
|
|
|
if (menu->title != NoTitle)
|
|
Menu_DrawTopBar(origin);
|
|
|
|
Menu_PreDraw(cm->menuID, NULL, origin);
|
|
|
|
M_RunMenu_CdPlayer(cm, menu, origin);
|
|
|
|
if (menu->title != NoTitle)
|
|
Menu_DrawTopBarCaption(menu->title, origin);
|
|
|
|
break;
|
|
}
|
|
|
|
case Menu:
|
|
{
|
|
int32_t state;
|
|
|
|
auto *menu = (MenuMenu_t*)cm->object;
|
|
MenuEntry_t *currentry = menu->entrylist[menu->currentEntry];
|
|
|
|
state = Menu_DetermineSpecialState(currentry);
|
|
|
|
if (state != 2)
|
|
{
|
|
Menu_Pre(cm->menuID);
|
|
|
|
Menu_PreDrawBackground(cm->menuID, origin);
|
|
|
|
if (menu->title != NoTitle)
|
|
Menu_DrawTopBar(origin);
|
|
|
|
Menu_PreDraw(cm->menuID, currentry, origin);
|
|
|
|
M_RunMenu_Menu(cm, menu, currentry, state, origin);
|
|
}
|
|
else
|
|
{
|
|
Menu_PreDrawBackground(cm->menuID, origin);
|
|
|
|
if (menu->title != NoTitle)
|
|
Menu_DrawTopBar(origin);
|
|
|
|
if (currentry->type == Option)
|
|
{
|
|
if (currentry->name)
|
|
Menu_DrawTopBarCaption(currentry->name, origin);
|
|
|
|
Menu_PreOptionListDraw(currentry, origin);
|
|
|
|
Menu_RunOptionList(cm, currentry, (MenuOption_t*)currentry->entry, origin);
|
|
}
|
|
else if (currentry->type == Custom2Col)
|
|
{
|
|
Menu_PreCustom2ColScreenDraw(currentry, origin);
|
|
}
|
|
}
|
|
|
|
if ((currentry->type != Option || state != 2) && menu->title != NoTitle)
|
|
Menu_DrawTopBarCaption(menu->title, origin);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if !defined EDUKE32_TOUCH_DEVICES
|
|
Menu_Run_MouseReturn(cm, origin);
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
Note: When menus are exposed to scripting, care will need to be taken so that
|
|
a user cannot define an empty MenuEntryList, or one containing only spacers,
|
|
or else this function will recurse infinitely.
|
|
*/
|
|
static MenuEntry_t *Menu_RunInput_Menu_MovementVerify(MenuMenu_t *menu)
|
|
{
|
|
return Menu_AdjustForCurrentEntryAssignment(menu);
|
|
}
|
|
|
|
static MenuEntry_t *Menu_RunInput_Menu_Movement(MenuMenu_t *menu, MenuMovement_t direction)
|
|
{
|
|
if (menu->numEntries == 1)
|
|
return menu->entrylist[menu->currentEntry];
|
|
|
|
switch (direction)
|
|
{
|
|
case MM_End:
|
|
menu->currentEntry = menu->numEntries;
|
|
fallthrough__;
|
|
case MM_Up:
|
|
do
|
|
{
|
|
--menu->currentEntry;
|
|
if (menu->currentEntry < 0)
|
|
return Menu_RunInput_Menu_Movement(menu, MM_End);
|
|
}
|
|
while (!menu->entrylist[menu->currentEntry] ||
|
|
(menu->entrylist[menu->currentEntry]->flags & MEF_Hidden) ||
|
|
menu->entrylist[menu->currentEntry]->type == Spacer);
|
|
break;
|
|
|
|
case MM_Home:
|
|
menu->currentEntry = -1;
|
|
fallthrough__;
|
|
case MM_Down:
|
|
do
|
|
{
|
|
++menu->currentEntry;
|
|
if (menu->currentEntry >= menu->numEntries)
|
|
return Menu_RunInput_Menu_Movement(menu, MM_Home);
|
|
}
|
|
while (!menu->entrylist[menu->currentEntry] ||
|
|
(menu->entrylist[menu->currentEntry]->flags & MEF_Hidden) ||
|
|
menu->entrylist[menu->currentEntry]->type == Spacer);
|
|
break;
|
|
|
|
case MM_Swap:
|
|
menu->currentColumn = !menu->currentColumn;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return Menu_RunInput_Menu_MovementVerify(menu);
|
|
}
|
|
|
|
static void Menu_RunInput_EntryLink_Activate(MenuEntry_t *entry)
|
|
{
|
|
auto *link = (MenuLink_t*)entry->entry;
|
|
|
|
Menu_EntryLinkActivate(entry);
|
|
|
|
Menu_AnimateChange(link->linkID, link->animation);
|
|
}
|
|
|
|
static void Menu_RunInput_EntryOptionList_MovementVerify(MenuOption_t *object)
|
|
{
|
|
const int32_t listytop = object->options->menuFormat->pos.y;
|
|
// assumes height == font->get_yline()!
|
|
const int32_t unitheight = object->options->getMarginBottom() < 0 ? (-object->options->getMarginBottom() - object->options->font->get_yline()) / object->options->numOptions : (object->options->font->get_yline() + object->options->getMarginBottom());
|
|
const int32_t ytop = listytop + object->options->currentEntry * unitheight;
|
|
const int32_t ybottom = ytop + object->options->font->get_yline();
|
|
|
|
if (ybottom - object->options->scrollPos > object->options->menuFormat->bottomcutoff)
|
|
object->options->scrollPos = ybottom - object->options->menuFormat->bottomcutoff;
|
|
else if (ytop - object->options->scrollPos < listytop)
|
|
object->options->scrollPos = ytop - listytop;
|
|
}
|
|
|
|
static void Menu_RunInput_EntryOptionList_Movement(MenuOption_t *object, MenuMovement_t direction)
|
|
{
|
|
switch (direction)
|
|
{
|
|
case MM_Up:
|
|
--object->options->currentEntry;
|
|
if (object->options->currentEntry >= 0)
|
|
break;
|
|
fallthrough__;
|
|
case MM_End:
|
|
object->options->currentEntry = object->options->numOptions-1;
|
|
break;
|
|
|
|
case MM_Down:
|
|
++object->options->currentEntry;
|
|
if (object->options->currentEntry < object->options->numOptions)
|
|
break;
|
|
fallthrough__;
|
|
case MM_Home:
|
|
object->options->currentEntry = 0;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
Menu_RunInput_EntryOptionList_MovementVerify(object);
|
|
}
|
|
|
|
static int32_t Menu_RunInput_EntryOption_Modify(MenuEntry_t *entry, MenuOption_t *object, int32_t newValueIndex)
|
|
{
|
|
int32_t newValue = (object->options->optionValues == NULL) ? newValueIndex : object->options->optionValues[newValueIndex];
|
|
if (!Menu_EntryOptionModify(entry, newValue))
|
|
{
|
|
object->currentOption = newValueIndex;
|
|
|
|
if ((int32_t*)object->data != NULL) // NULL implies the functions will handle it
|
|
*((int32_t*)object->data) = newValue;
|
|
|
|
Menu_EntryOptionDidModify(entry);
|
|
|
|
return 0;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static int32_t Menu_RunInput_EntryOption_Movement(MenuEntry_t *entry, MenuOption_t *object, MenuMovement_t direction)
|
|
{
|
|
int32_t newValueIndex = object->currentOption;
|
|
|
|
switch (direction)
|
|
{
|
|
case MM_Left:
|
|
--newValueIndex;
|
|
if (newValueIndex >= 0)
|
|
break;
|
|
fallthrough__;
|
|
case MM_AllTheWayRight:
|
|
newValueIndex = object->options->numOptions-1;
|
|
break;
|
|
|
|
case MM_Right:
|
|
++newValueIndex;
|
|
if (newValueIndex < object->options->numOptions)
|
|
break;
|
|
fallthrough__;
|
|
case MM_AllTheWayLeft:
|
|
newValueIndex = 0;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return Menu_RunInput_EntryOption_Modify(entry, object, newValueIndex);
|
|
}
|
|
|
|
static int32_t Menu_RunInput_EntryOption_Activate(MenuEntry_t *entry, MenuOption_t *object)
|
|
{
|
|
if (object->options->features & 2)
|
|
return Menu_RunInput_EntryOption_Movement(entry, object, MM_Right);
|
|
else
|
|
{
|
|
object->options->currentEntry = object->currentOption >= 0 ? object->currentOption : 0;
|
|
Menu_RunInput_EntryOptionList_MovementVerify(object);
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static int32_t Menu_RunInput_EntryOptionList_Activate(MenuEntry_t *entry, MenuOption_t *object)
|
|
{
|
|
if (!Menu_RunInput_EntryOption_Modify(entry, object, object->options->currentEntry))
|
|
{
|
|
object->options->currentEntry = -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static void Menu_RunInput_EntryCustom2Col_Activate(MenuEntry_t *entry)
|
|
{
|
|
auto *object = (MenuCustom2Col_t*)entry->entry;
|
|
|
|
Menu_Custom2ColScreen(/*entry*/);
|
|
|
|
object->screenOpen = 1;
|
|
}
|
|
|
|
static void Menu_RunInput_EntryRangeInt32_MovementVerify(MenuEntry_t *entry, MenuRangeInt32_t *object, int32_t newValue)
|
|
{
|
|
if (!Menu_EntryRangeInt32Modify(entry, newValue))
|
|
*object->variable = newValue;
|
|
}
|
|
|
|
static void Menu_RunInput_EntryRangeInt32_MovementArbitrary(MenuEntry_t *entry, MenuRangeInt32_t *object, int32_t newValue)
|
|
{
|
|
if (object->flags & EnforceIntervals)
|
|
{
|
|
int32_t const range = object->max - object->min;
|
|
int32_t const maxInterval = object->steps - 1;
|
|
int32_t const newValueIndex = roundscale(newValue - object->min, maxInterval, range);
|
|
newValue = newValueIndex * range / maxInterval + object->min;
|
|
}
|
|
|
|
Menu_RunInput_EntryRangeInt32_MovementVerify(entry, object, newValue);
|
|
}
|
|
|
|
static void Menu_RunInput_EntryRangeInt32_Movement(MenuEntry_t *entry, MenuRangeInt32_t *object, MenuMovement_t direction)
|
|
{
|
|
int32_t const oldValue = *object->variable;
|
|
int32_t const range = object->max - object->min;
|
|
int32_t const maxInterval = object->steps - 1;
|
|
int32_t const oldValueIndex = roundscale(oldValue - object->min, maxInterval, range);
|
|
int32_t const oldValueQuantized = oldValueIndex * range / maxInterval + object->min;
|
|
int32_t newValueIndex = oldValueIndex;
|
|
|
|
switch (direction)
|
|
{
|
|
case MM_Left:
|
|
if (oldValueQuantized >= oldValue)
|
|
--newValueIndex;
|
|
if (newValueIndex >= 0)
|
|
break;
|
|
fallthrough__;
|
|
case MM_AllTheWayLeft:
|
|
newValueIndex = 0;
|
|
break;
|
|
|
|
case MM_Right:
|
|
if (oldValueQuantized <= oldValue)
|
|
++newValueIndex;
|
|
if (newValueIndex <= maxInterval)
|
|
break;
|
|
fallthrough__;
|
|
case MM_AllTheWayRight:
|
|
newValueIndex = maxInterval;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
int32_t const newValue = newValueIndex * range / maxInterval + object->min;
|
|
Menu_RunInput_EntryRangeInt32_MovementVerify(entry, object, newValue);
|
|
}
|
|
|
|
static void Menu_RunInput_EntryRangeFloat_MovementVerify(MenuEntry_t *entry, MenuRangeFloat_t *object, float newValue)
|
|
{
|
|
if (!Menu_EntryRangeFloatModify(entry, newValue))
|
|
{
|
|
*object->variable = newValue;
|
|
Menu_EntryRangeFloatDidModify(entry);
|
|
}
|
|
}
|
|
|
|
static void Menu_RunInput_EntryRangeFloat_MovementArbitrary(MenuEntry_t *entry, MenuRangeFloat_t *object, float newValue)
|
|
{
|
|
if (object->flags & EnforceIntervals)
|
|
{
|
|
float const range = object->max - object->min;
|
|
float const maxInterval = (float)(object->steps - 1);
|
|
float const newValueIndex = rintf((newValue - object->min) * maxInterval / range);
|
|
newValue = newValueIndex * range / maxInterval + object->min;
|
|
}
|
|
|
|
Menu_RunInput_EntryRangeFloat_MovementVerify(entry, object, newValue);
|
|
}
|
|
|
|
static void Menu_RunInput_EntryRangeFloat_Movement(MenuEntry_t *entry, MenuRangeFloat_t *object, MenuMovement_t direction)
|
|
{
|
|
float const oldValue = *object->variable;
|
|
float const range = object->max - object->min;
|
|
float const maxInterval = (float)(object->steps - 1);
|
|
float const oldValueIndexUnrounded = (oldValue - object->min) * maxInterval / range;
|
|
float const oldValueIndex = rintf(oldValueIndexUnrounded);
|
|
float const oldValueQuantized = oldValueIndex * range / maxInterval + object->min;
|
|
float newValueIndex = oldValueIndex;
|
|
|
|
switch (direction)
|
|
{
|
|
case MM_Left:
|
|
if (oldValueQuantized >= oldValue)
|
|
newValueIndex -= 1.f;
|
|
if (newValueIndex >= 0.f)
|
|
break;
|
|
fallthrough__;
|
|
case MM_AllTheWayLeft:
|
|
newValueIndex = 0.f;
|
|
break;
|
|
|
|
case MM_Right:
|
|
if (oldValueQuantized <= oldValue)
|
|
newValueIndex += 1.f;
|
|
if (newValueIndex <= maxInterval)
|
|
break;
|
|
fallthrough__;
|
|
case MM_AllTheWayRight:
|
|
newValueIndex = maxInterval;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
float const newValue = newValueIndex * range / maxInterval + object->min;
|
|
Menu_RunInput_EntryRangeFloat_MovementVerify(entry, object, newValue);
|
|
}
|
|
|
|
#ifdef MENU_ENABLE_RANGEDOUBLE
|
|
static void Menu_RunInput_EntryRangeDouble_MovementVerify(/*MenuEntry_t *entry, */MenuRangeDouble_t *object, double newValue)
|
|
{
|
|
if (!Menu_EntryRangeDoubleModify(/*entry, newValue*/))
|
|
*object->variable = newValue;
|
|
}
|
|
|
|
static void Menu_RunInput_EntryRangeDouble_MovementArbitrary(/*MenuEntry_t *entry, */MenuRangeDouble_t *object, double newValue)
|
|
{
|
|
if (object->flags & EnforceIntervals)
|
|
{
|
|
double const range = object->max - object->min;
|
|
double const maxInterval = object->steps - 1;
|
|
double const newValueIndex = rint((newValue - object->min) * maxInterval / range);
|
|
newValue = newValueIndex * range / maxInterval + object->min;
|
|
}
|
|
|
|
Menu_RunInput_EntryRangeDouble_MovementVerify(/*entry, */object, newValue);
|
|
}
|
|
|
|
static void Menu_RunInput_EntryRangeDouble_Movement(/*MenuEntry_t *entry, */MenuRangeDouble_t *object, MenuMovement_t direction)
|
|
{
|
|
double const oldValue = *object->variable;
|
|
double const range = object->max - object->min;
|
|
double const maxInterval = object->steps - 1;
|
|
double const oldValueIndex = rint((oldValue - object->min) * maxInterval / range);
|
|
double const oldValueQuantized = oldValueIndex * range / maxInterval + object->min;
|
|
double newValueIndex = oldValueIndex;
|
|
|
|
switch (direction)
|
|
{
|
|
case MM_Left:
|
|
if (oldValueQuantized >= oldValue)
|
|
newValueIndex -= 1.;
|
|
if (newValueIndex >= 0.)
|
|
break;
|
|
fallthrough__;
|
|
case MM_AllTheWayLeft:
|
|
newValueIndex = 0.;
|
|
break;
|
|
|
|
case MM_Right:
|
|
if (oldValueQuantized <= oldValue)
|
|
newValueIndex += 1.;
|
|
if (newValueIndex <= maxInterval)
|
|
break;
|
|
fallthrough__;
|
|
case MM_AllTheWayRight:
|
|
newValueIndex = maxInterval;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
double const newValue = newValueIndex * range / maxInterval + object->min;
|
|
Menu_RunInput_EntryRangeDouble_MovementVerify(/*entry, */object, newValue);
|
|
}
|
|
#endif
|
|
|
|
static void Menu_RunInput_EntryString_Activate(MenuEntry_t *entry)
|
|
{
|
|
auto *object = (MenuString_t*)entry->entry;
|
|
|
|
if (object->variable)
|
|
strncpy(typebuf, object->variable, TYPEBUFSIZE);
|
|
else
|
|
typebuf[0] = '\0';
|
|
object->editfield = typebuf;
|
|
|
|
// this limitation is an arbitrary implementation detail
|
|
if (object->bufsize > TYPEBUFSIZE)
|
|
object->bufsize = TYPEBUFSIZE;
|
|
|
|
Menu_EntryStringActivate(/*entry*/);
|
|
Menu_StartTextInput();
|
|
}
|
|
|
|
static void Menu_RunInput_EntryString_Submit(/*MenuEntry_t *entry, */MenuString_t *object)
|
|
{
|
|
if (!Menu_EntryStringSubmit(/*entry, */object->editfield))
|
|
{
|
|
if (object->variable)
|
|
strncpy(object->variable, object->editfield, object->bufsize);
|
|
}
|
|
|
|
object->editfield = NULL;
|
|
Menu_StopTextInput();
|
|
}
|
|
|
|
static void Menu_RunInput_EntryString_Cancel(/*MenuEntry_t *entry, */MenuString_t *object)
|
|
{
|
|
Menu_EntryStringCancel(/*entry*/);
|
|
|
|
object->editfield = NULL;
|
|
Menu_StopTextInput();
|
|
}
|
|
|
|
static void Menu_RunInput_FileSelect_MovementVerify(MenuFileSelect_t *object)
|
|
{
|
|
#if 0
|
|
const int32_t listytop = object->format[object->currentList]->pos.y;
|
|
const int32_t listybottom = klabs(object->format[object->currentList]->bottomcutoff);
|
|
const int32_t ytop = listytop + object->findhigh[object->currentList]->type * (object->font[object->currentList]->get_yline() + object->getMarginBottom(object->currentList));
|
|
const int32_t ybottom = ytop + object->font[object->currentList]->get_yline();
|
|
|
|
if (ybottom - object->scrollPos[object->currentList] > listybottom)
|
|
object->scrollPos[object->currentList] = ybottom - listybottom;
|
|
else if (ytop - object->scrollPos[object->currentList] < listytop)
|
|
object->scrollPos[object->currentList] = ytop - listytop;
|
|
#endif
|
|
}
|
|
|
|
static void Menu_RunInput_FileSelect_Movement(MenuFileSelect_t *object, MenuMovement_t direction)
|
|
{
|
|
#if 0
|
|
switch (direction)
|
|
{
|
|
case MM_Up:
|
|
if (!object->findhigh[object->currentList])
|
|
break;
|
|
if (object->findhigh[object->currentList]->prev)
|
|
{
|
|
object->findhigh[object->currentList] = object->findhigh[object->currentList]->prev;
|
|
break;
|
|
}
|
|
fallthrough__;
|
|
case MM_End:
|
|
object->findhigh[object->currentList] = object->findhigh[object->currentList]->userb;
|
|
break;
|
|
|
|
case MM_Down:
|
|
if (!object->findhigh[object->currentList])
|
|
break;
|
|
if (object->findhigh[object->currentList]->next)
|
|
{
|
|
object->findhigh[object->currentList] = object->findhigh[object->currentList]->next;
|
|
break;
|
|
}
|
|
fallthrough__;
|
|
case MM_Home:
|
|
object->findhigh[object->currentList] = object->findhigh[object->currentList]->usera;
|
|
break;
|
|
|
|
case MM_Swap:
|
|
object->currentList = !object->currentList;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
Menu_RunInput_FileSelect_MovementVerify(object);
|
|
#endif
|
|
}
|
|
|
|
static void Menu_RunInput_FileSelect_Select(MenuFileSelect_t *object)
|
|
{
|
|
#if 0
|
|
if (!object->findhigh[object->currentList])
|
|
return;
|
|
|
|
Bstrcat(object->destination, object->findhigh[object->currentList]->name);
|
|
|
|
if (object->currentList == 0)
|
|
{
|
|
Bstrcat(object->destination, "/");
|
|
Bcorrectfilename(object->destination, 1);
|
|
|
|
Menu_FileSelectInit(object);
|
|
}
|
|
else
|
|
{
|
|
Menu_FileSelect(1);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void Menu_RunInput(Menu_t *cm)
|
|
{
|
|
switch (cm->type)
|
|
{
|
|
case Panel:
|
|
{
|
|
auto *panel = (MenuPanel_t*)cm->object;
|
|
|
|
if (I_ReturnTrigger() || Menu_RunInput_MouseReturn())
|
|
{
|
|
I_ReturnTriggerClear();
|
|
m_mousecaught = 1;
|
|
|
|
S_PlaySound(EXITMENUSOUND);
|
|
|
|
Menu_AnimateChange(cm->parentID, cm->parentAnimation);
|
|
}
|
|
else if (I_PanelUp())
|
|
{
|
|
I_PanelUpClear();
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
Menu_AnimateChange(panel->previousID, panel->previousAnimation);
|
|
}
|
|
else if (I_PanelDown() || Menu_RunInput_MouseAdvance())
|
|
{
|
|
I_PanelDownClear();
|
|
m_mousecaught = 1;
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
Menu_AnimateChange(panel->nextID, panel->nextAnimation);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case TextForm:
|
|
{
|
|
auto *object = (MenuTextForm_t*)cm->object;
|
|
int32_t hitstate = I_EnterText(object->input, object->bufsize-1, 0);
|
|
|
|
if (hitstate == -1 || Menu_RunInput_MouseReturn())
|
|
{
|
|
m_mousecaught = 1;
|
|
|
|
S_PlaySound(EXITMENUSOUND);
|
|
|
|
object->input = NULL;
|
|
|
|
Menu_AnimateChange(cm->parentID, cm->parentAnimation);
|
|
Menu_StopTextInput();
|
|
}
|
|
else if (hitstate == 1 || Menu_RunInput_MouseAdvance())
|
|
{
|
|
m_mousecaught = 1;
|
|
|
|
Menu_TextFormSubmit(object->input);
|
|
|
|
object->input = NULL;
|
|
Menu_StopTextInput();
|
|
}
|
|
break;
|
|
}
|
|
|
|
case FileSelect:
|
|
{
|
|
#if 0
|
|
auto *object = (MenuFileSelect_t*)cm->object;
|
|
|
|
if (I_ReturnTrigger() || Menu_RunInput_MouseReturn())
|
|
{
|
|
I_ReturnTriggerClear();
|
|
m_mousecaught = 1;
|
|
|
|
S_PlaySound(EXITMENUSOUND);
|
|
|
|
object->destination[0] = 0;
|
|
|
|
Menu_FileSelect(0);
|
|
|
|
Menu_AnimateChange(cm->parentID, MA_Return);
|
|
}
|
|
else if (I_AdvanceTrigger())
|
|
{
|
|
I_AdvanceTriggerClear();
|
|
|
|
Menu_RunInput_FileSelect_Select(object);
|
|
|
|
S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
}
|
|
else if (inputState.GetKeyStatus(sc_Home))
|
|
{
|
|
inputState.ClearKeyStatus(sc_Home);
|
|
|
|
Menu_RunInput_FileSelect_Movement(object, MM_Home);
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
}
|
|
else if (inputState.GetKeyStatus(sc_End))
|
|
{
|
|
inputState.ClearKeyStatus(sc_End);
|
|
|
|
Menu_RunInput_FileSelect_Movement(object, MM_End);
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
}
|
|
else if (inputState.GetKeyStatus(sc_PgUp))
|
|
{
|
|
int32_t i;
|
|
|
|
CACHE1D_FIND_REC *seeker = object->findhigh[object->currentList];
|
|
|
|
inputState.ClearKeyStatus(sc_PgUp);
|
|
|
|
for (i = 0; i < 6; ++i)
|
|
{
|
|
if (seeker && seeker->prev)
|
|
seeker = seeker->prev;
|
|
}
|
|
|
|
if (seeker)
|
|
{
|
|
object->findhigh[object->currentList] = seeker;
|
|
|
|
Menu_RunInput_FileSelect_MovementVerify(object);
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
}
|
|
}
|
|
else if (inputState.GetKeyStatus(sc_PgDn))
|
|
{
|
|
int32_t i;
|
|
|
|
CACHE1D_FIND_REC *seeker = object->findhigh[object->currentList];
|
|
|
|
inputState.ClearKeyStatus(sc_PgDn);
|
|
|
|
for (i = 0; i < 6; ++i)
|
|
{
|
|
if (seeker && seeker->next)
|
|
seeker = seeker->next;
|
|
}
|
|
|
|
if (seeker)
|
|
{
|
|
object->findhigh[object->currentList] = seeker;
|
|
|
|
Menu_RunInput_FileSelect_MovementVerify(object);
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
}
|
|
}
|
|
else if (I_MenuLeft() || I_MenuRight())
|
|
{
|
|
I_MenuLeftClear();
|
|
I_MenuRightClear();
|
|
|
|
if ((object->currentList ? object->fnlist.numdirs : object->fnlist.numfiles) > 0)
|
|
{
|
|
Menu_RunInput_FileSelect_Movement(object, MM_Swap);
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
}
|
|
}
|
|
else if (I_MenuUp())
|
|
{
|
|
I_MenuUpClear();
|
|
|
|
Menu_RunInput_FileSelect_Movement(object, MM_Up);
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
}
|
|
else if (I_MenuDown())
|
|
{
|
|
I_MenuDownClear();
|
|
|
|
Menu_RunInput_FileSelect_Movement(object, MM_Down);
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
}
|
|
else
|
|
{
|
|
// JBF 20040208: seek to first name matching pressed character
|
|
char ch2, ch;
|
|
ch = inputState.keyGetChar();
|
|
if (ch > 0 && ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')))
|
|
{
|
|
CACHE1D_FIND_REC *seeker = object->findhigh[object->currentList]->usera;
|
|
if (ch >= 'a')
|
|
ch -= ('a'-'A');
|
|
while (seeker)
|
|
{
|
|
ch2 = seeker->name[0];
|
|
if (ch2 >= 'a' && ch2 <= 'z')
|
|
ch2 -= ('a'-'A');
|
|
if (ch2 == ch)
|
|
break;
|
|
seeker = seeker->next;
|
|
}
|
|
if (seeker)
|
|
{
|
|
object->findhigh[object->currentList] = seeker;
|
|
|
|
Menu_RunInput_FileSelect_MovementVerify(object);
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
Menu_PreInput(NULL);
|
|
break;
|
|
}
|
|
|
|
case Message:
|
|
if (I_ReturnTrigger() || Menu_RunInput_MouseReturn())
|
|
{
|
|
I_ReturnTriggerClear();
|
|
m_mousecaught = 1;
|
|
|
|
S_PlaySound(EXITMENUSOUND);
|
|
|
|
Menu_AnimateChange(cm->parentID, cm->parentAnimation);
|
|
}
|
|
|
|
if (I_CheckAllInput())
|
|
{
|
|
auto *message = (MenuMessage_t*)cm->object;
|
|
|
|
I_ClearAllInput();
|
|
|
|
S_PlaySound(EXITMENUSOUND);
|
|
|
|
Menu_AnimateChange(message->linkID, message->animation);
|
|
}
|
|
|
|
Menu_PreInput(NULL);
|
|
break;
|
|
|
|
case Verify:
|
|
if (I_ReturnTrigger() || inputState.GetKeyStatus(sc_N) || Menu_RunInput_MouseReturn())
|
|
{
|
|
I_ReturnTriggerClear();
|
|
inputState.ClearKeyStatus(sc_N);
|
|
m_mousecaught = 1;
|
|
|
|
Menu_Verify(0);
|
|
|
|
Menu_AnimateChange(cm->parentID, cm->parentAnimation);
|
|
|
|
S_PlaySound(EXITMENUSOUND);
|
|
}
|
|
|
|
if (I_AdvanceTrigger() || inputState.GetKeyStatus(sc_Y) || Menu_RunInput_MouseAdvance())
|
|
{
|
|
auto *verify = (MenuVerify_t*)cm->object;
|
|
|
|
I_AdvanceTriggerClear();
|
|
inputState.ClearKeyStatus(sc_Y);
|
|
m_mousecaught = 1;
|
|
|
|
Menu_Verify(1);
|
|
|
|
Menu_AnimateChange(verify->linkID, verify->animation);
|
|
|
|
S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
}
|
|
|
|
Menu_PreInput(NULL);
|
|
break;
|
|
|
|
case CdPlayer:
|
|
{
|
|
auto *menu = (MenuMenu_t*)cm->object;
|
|
MenuEntry_t *currentry = menu->entrylist[menu->currentEntry];
|
|
|
|
if (I_AdvanceTrigger())
|
|
{
|
|
I_AdvanceTriggerClear();
|
|
|
|
mus_enabled = !mus_enabled;
|
|
|
|
if (mus_enabled == 0)
|
|
S_PauseMusic(true);
|
|
else
|
|
{
|
|
S_PlayRRMusic(2+menu->currentEntry);
|
|
S_PauseMusic(false);
|
|
}
|
|
|
|
S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
}
|
|
|
|
if (I_ReturnTrigger() || I_EscapeTrigger() || Menu_RunInput_MouseReturn())
|
|
{
|
|
I_ReturnTriggerClear();
|
|
I_EscapeTriggerClear();
|
|
m_mousecaught = 1;
|
|
|
|
if (cm->parentID != MENU_CLOSE || (g_player[myconnectindex].ps->gm & MODE_GAME))
|
|
S_PlaySound(EXITMENUSOUND);
|
|
|
|
Menu_AnimateChange(cm->parentID, cm->parentAnimation);
|
|
}
|
|
else if (I_MenuUp() || I_MenuLeft())
|
|
{
|
|
I_MenuUpClear();
|
|
I_MenuLeftClear();
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
|
|
currentry = Menu_RunInput_Menu_Movement(menu, MM_Up);
|
|
|
|
if (MusicEnabled())
|
|
{
|
|
S_StopMusic();
|
|
S_PlayRRMusic(2+menu->currentEntry);
|
|
}
|
|
}
|
|
else if (I_MenuDown() || I_MenuRight())
|
|
{
|
|
I_MenuDownClear();
|
|
I_MenuRightClear();
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
|
|
currentry = Menu_RunInput_Menu_Movement(menu, MM_Down);
|
|
|
|
if (MusicEnabled())
|
|
{
|
|
S_StopMusic();
|
|
S_PlayRRMusic(2+menu->currentEntry);
|
|
}
|
|
}
|
|
else if (inputState.GetKeyStatus(sc_1))
|
|
{
|
|
inputState.ClearKeyStatus(sc_1);
|
|
menu->currentEntry = 0;
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
if (MusicEnabled())
|
|
{
|
|
S_StopMusic();
|
|
S_PlayRRMusic(2+menu->currentEntry);
|
|
}
|
|
}
|
|
else if (inputState.GetKeyStatus(sc_2))
|
|
{
|
|
inputState.ClearKeyStatus(sc_2);
|
|
menu->currentEntry = 1;
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
if (MusicEnabled())
|
|
{
|
|
S_StopMusic();
|
|
S_PlayRRMusic(2+menu->currentEntry);
|
|
}
|
|
}
|
|
else if (inputState.GetKeyStatus(sc_3))
|
|
{
|
|
inputState.ClearKeyStatus(sc_3);
|
|
menu->currentEntry = 2;
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
if (MusicEnabled())
|
|
{
|
|
S_StopMusic();
|
|
S_PlayRRMusic(2+menu->currentEntry);
|
|
}
|
|
}
|
|
else if (inputState.GetKeyStatus(sc_4))
|
|
{
|
|
inputState.ClearKeyStatus(sc_4);
|
|
menu->currentEntry = 3;
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
if (MusicEnabled())
|
|
{
|
|
S_StopMusic();
|
|
S_PlayRRMusic(2+menu->currentEntry);
|
|
}
|
|
}
|
|
else if (inputState.GetKeyStatus(sc_5))
|
|
{
|
|
inputState.ClearKeyStatus(sc_5);
|
|
menu->currentEntry = 4;
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
if (MusicEnabled())
|
|
{
|
|
S_StopMusic();
|
|
S_PlayRRMusic(2+menu->currentEntry);
|
|
}
|
|
}
|
|
else if (inputState.GetKeyStatus(sc_6))
|
|
{
|
|
inputState.ClearKeyStatus(sc_6);
|
|
menu->currentEntry = 5;
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
if (MusicEnabled())
|
|
{
|
|
S_StopMusic();
|
|
S_PlayRRMusic(2+menu->currentEntry);
|
|
}
|
|
}
|
|
else if (inputState.GetKeyStatus(sc_7))
|
|
{
|
|
inputState.ClearKeyStatus(sc_7);
|
|
menu->currentEntry = 6;
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
if (MusicEnabled())
|
|
{
|
|
S_StopMusic();
|
|
S_PlayRRMusic(2+menu->currentEntry);
|
|
}
|
|
}
|
|
else if (inputState.GetKeyStatus(sc_8))
|
|
{
|
|
inputState.ClearKeyStatus(sc_8);
|
|
menu->currentEntry = 7;
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
if (MusicEnabled())
|
|
{
|
|
S_StopMusic();
|
|
S_PlayRRMusic(2+menu->currentEntry);
|
|
}
|
|
}
|
|
|
|
if (currentry != NULL)
|
|
Menu_PreInput(currentry);
|
|
|
|
break;
|
|
}
|
|
|
|
case Menu:
|
|
{
|
|
int32_t state;
|
|
|
|
auto *menu = (MenuMenu_t*)cm->object;
|
|
MenuEntry_t *currentry = menu->entrylist[menu->currentEntry];
|
|
|
|
state = Menu_DetermineSpecialState(currentry);
|
|
|
|
if (state == 0)
|
|
{
|
|
if (currentry != NULL)
|
|
switch (currentry->type)
|
|
{
|
|
case Dummy:
|
|
case Spacer:
|
|
break;
|
|
case Link:
|
|
if (currentry->flags & MEF_Disabled)
|
|
break;
|
|
if (I_AdvanceTrigger())
|
|
{
|
|
I_AdvanceTriggerClear();
|
|
|
|
Menu_RunInput_EntryLink_Activate(currentry);
|
|
|
|
if (g_player[myconnectindex].ps->gm&MODE_MENU) // for skill selection
|
|
S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
}
|
|
break;
|
|
case Option:
|
|
{
|
|
auto *object = (MenuOption_t*)currentry->entry;
|
|
|
|
if (currentry->flags & MEF_Disabled)
|
|
break;
|
|
|
|
if (I_AdvanceTrigger())
|
|
{
|
|
I_AdvanceTriggerClear();
|
|
|
|
Menu_RunInput_EntryOption_Activate(currentry, object);
|
|
|
|
S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
}
|
|
else if (I_MenuRight())
|
|
{
|
|
I_MenuRightClear();
|
|
|
|
Menu_RunInput_EntryOption_Movement(currentry, object, MM_Right);
|
|
|
|
S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
}
|
|
else if (I_MenuLeft())
|
|
{
|
|
I_MenuLeftClear();
|
|
|
|
Menu_RunInput_EntryOption_Movement(currentry, object, MM_Left);
|
|
|
|
S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
}
|
|
}
|
|
break;
|
|
case Custom2Col:
|
|
if (I_MenuLeft() || I_MenuRight())
|
|
{
|
|
I_MenuLeftClear();
|
|
I_MenuRightClear();
|
|
|
|
Menu_RunInput_Menu_Movement(menu, MM_Swap);
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
}
|
|
|
|
if (currentry->flags & MEF_Disabled)
|
|
break;
|
|
|
|
if (I_AdvanceTrigger())
|
|
{
|
|
I_AdvanceTriggerClear();
|
|
|
|
Menu_RunInput_EntryCustom2Col_Activate(currentry);
|
|
|
|
S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
}
|
|
break;
|
|
case RangeInt32:
|
|
{
|
|
auto *object = (MenuRangeInt32_t*)currentry->entry;
|
|
|
|
if (currentry->flags & MEF_Disabled)
|
|
break;
|
|
|
|
if (I_SliderLeft())
|
|
{
|
|
I_SliderLeftClear();
|
|
|
|
Menu_RunInput_EntryRangeInt32_Movement(currentry, object, MM_Left);
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
}
|
|
else if (I_SliderRight())
|
|
{
|
|
I_SliderRightClear();
|
|
|
|
Menu_RunInput_EntryRangeInt32_Movement(currentry, object, MM_Right);
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
}
|
|
break;
|
|
}
|
|
case RangeFloat:
|
|
{
|
|
auto *object = (MenuRangeFloat_t*)currentry->entry;
|
|
|
|
if (currentry->flags & MEF_Disabled)
|
|
break;
|
|
|
|
if (I_SliderLeft())
|
|
{
|
|
I_SliderLeftClear();
|
|
|
|
Menu_RunInput_EntryRangeFloat_Movement(currentry, object, MM_Left);
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
}
|
|
else if (I_SliderRight())
|
|
{
|
|
I_SliderRightClear();
|
|
|
|
Menu_RunInput_EntryRangeFloat_Movement(currentry, object, MM_Right);
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
}
|
|
break;
|
|
}
|
|
#ifdef MENU_ENABLE_RANGEDOUBLE
|
|
case RangeDouble:
|
|
{
|
|
MenuRangeDouble_t *object = (MenuRangeDouble_t*)currentry->entry;
|
|
|
|
if (currentry->flags & MEF_Disabled)
|
|
break;
|
|
|
|
if (I_SliderLeft())
|
|
{
|
|
I_SliderLeftClear();
|
|
|
|
Menu_RunInput_EntryRangeDouble_Movement(/*currentry, */object, MM_Left);
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
}
|
|
else if (I_SliderRight())
|
|
{
|
|
I_SliderRightClear();
|
|
|
|
Menu_RunInput_EntryRangeDouble_Movement(/*currentry, */object, MM_Right);
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
}
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
case String:
|
|
{
|
|
if (currentry->flags & MEF_Disabled)
|
|
break;
|
|
|
|
if (I_AdvanceTrigger())
|
|
{
|
|
I_AdvanceTriggerClear();
|
|
|
|
Menu_RunInput_EntryString_Activate(currentry);
|
|
|
|
S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (I_ReturnTrigger() || I_EscapeTrigger() || Menu_RunInput_MouseReturn())
|
|
{
|
|
I_ReturnTriggerClear();
|
|
I_EscapeTriggerClear();
|
|
m_mousecaught = 1;
|
|
|
|
if (cm->parentID != MENU_CLOSE || (g_player[myconnectindex].ps->gm & MODE_GAME))
|
|
S_PlaySound(EXITMENUSOUND);
|
|
|
|
Menu_AnimateChange(cm->parentID, cm->parentAnimation);
|
|
}
|
|
else if (inputState.GetKeyStatus(sc_Home))
|
|
{
|
|
inputState.ClearKeyStatus(sc_Home);
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
|
|
currentry = Menu_RunInput_Menu_Movement(menu, MM_Home);
|
|
}
|
|
else if (inputState.GetKeyStatus(sc_End))
|
|
{
|
|
inputState.ClearKeyStatus(sc_End);
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
|
|
currentry = Menu_RunInput_Menu_Movement(menu, MM_End);
|
|
}
|
|
else if (I_MenuUp())
|
|
{
|
|
I_MenuUpClear();
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
|
|
currentry = Menu_RunInput_Menu_Movement(menu, MM_Up);
|
|
}
|
|
else if (I_MenuDown())
|
|
{
|
|
I_MenuDownClear();
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
|
|
currentry = Menu_RunInput_Menu_Movement(menu, MM_Down);
|
|
}
|
|
|
|
if (currentry != NULL)
|
|
Menu_PreInput(currentry);
|
|
}
|
|
else if (state == 1)
|
|
{
|
|
if (currentry->type == String)
|
|
{
|
|
auto *object = (MenuString_t*)currentry->entry;
|
|
|
|
int32_t hitstate = I_EnterText(object->editfield, object->bufsize-1, object->flags);
|
|
|
|
if (hitstate == -1 || Menu_RunInput_MouseReturn())
|
|
{
|
|
m_mousecaught = 1;
|
|
|
|
Menu_RunInput_EntryString_Cancel(/*currentry, */object);
|
|
|
|
S_PlaySound(EXITMENUSOUND);
|
|
}
|
|
else if (hitstate == 1)
|
|
{
|
|
Menu_RunInput_EntryString_Submit(/*currentry, */object);
|
|
|
|
S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
}
|
|
}
|
|
}
|
|
else if (state == 2)
|
|
{
|
|
if (currentry->type == Option)
|
|
{
|
|
auto *object = (MenuOption_t*)currentry->entry;
|
|
|
|
if (I_ReturnTrigger() || Menu_RunInput_MouseReturn())
|
|
{
|
|
I_ReturnTriggerClear();
|
|
m_mousecaught = 1;
|
|
|
|
S_PlaySound(EXITMENUSOUND);
|
|
|
|
object->options->currentEntry = -1;
|
|
}
|
|
else if (I_AdvanceTrigger())
|
|
{
|
|
I_AdvanceTriggerClear();
|
|
|
|
if (!Menu_RunInput_EntryOptionList_Activate(currentry, object))
|
|
S_PlaySound(RR ? 341 : PISTOL_BODYHIT);
|
|
}
|
|
else if (inputState.GetKeyStatus(sc_Home))
|
|
{
|
|
inputState.ClearKeyStatus(sc_Home);
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
|
|
Menu_RunInput_EntryOptionList_Movement(object, MM_Home);
|
|
}
|
|
else if (inputState.GetKeyStatus(sc_End))
|
|
{
|
|
inputState.ClearKeyStatus(sc_End);
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
|
|
Menu_RunInput_EntryOptionList_Movement(object, MM_End);
|
|
}
|
|
else if (I_MenuUp())
|
|
{
|
|
I_MenuUpClear();
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
|
|
Menu_RunInput_EntryOptionList_Movement(object, MM_Up);
|
|
}
|
|
else if (I_MenuDown())
|
|
{
|
|
I_MenuDownClear();
|
|
|
|
S_PlaySound(RR ? 335 : KICK_HIT);
|
|
|
|
Menu_RunInput_EntryOptionList_Movement(object, MM_Down);
|
|
}
|
|
}
|
|
else if (currentry->type == Custom2Col)
|
|
{
|
|
if (I_EscapeTrigger() || Menu_RunInput_MouseReturn())
|
|
{
|
|
I_EscapeTriggerClear();
|
|
m_mousecaught = 1;
|
|
|
|
S_PlaySound(EXITMENUSOUND);
|
|
|
|
((MenuCustom2Col_t*)currentry->entry)->screenOpen = 0;
|
|
}
|
|
else if (Menu_PreCustom2ColScreen(currentry))
|
|
((MenuCustom2Col_t*)currentry->entry)->screenOpen = 0;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// This function MUST NOT RECURSE. That is why Menu_Run is separate.
|
|
void M_DisplayMenus(void)
|
|
{
|
|
vec2_t origin = { 0, 0 }, previousOrigin = { 0, 0 };
|
|
|
|
Net_GetPackets();
|
|
|
|
if ((g_player[myconnectindex].ps->gm&MODE_MENU) == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!Menu_IsTextInput(m_currentMenu) && inputState.GetKeyStatus(sc_Q))
|
|
Menu_AnimateChange(MENU_QUIT, MA_Advance);
|
|
|
|
int32_t mousestatus = mouseReadAbs(&m_mousepos, &g_mouseAbs);
|
|
if (mousestatus && inputState.mouseClickState() == MOUSE_PRESSED)
|
|
m_mousedownpos = m_mousepos;
|
|
|
|
Menu_RunInput(m_currentMenu);
|
|
|
|
g_player[myconnectindex].ps->gm &= (0xff-MODE_TYPE);
|
|
// g_player[myconnectindex].ps->fta = 0;
|
|
|
|
int32_t const backgroundOK = ud.menubackground && Menu_BlackTranslucentBackgroundOK(g_currentMenu);
|
|
|
|
// need EVENT_DISPLAYMENUBACKGROUND here
|
|
|
|
if (((g_player[myconnectindex].ps->gm&MODE_GAME) || ud.recstat==2) && backgroundOK)
|
|
videoFadeToBlack(1);
|
|
|
|
if (Menu_UpdateScreenOK(g_currentMenu))
|
|
G_UpdateScreenArea();
|
|
|
|
#if !defined EDUKE32_TOUCH_DEVICES
|
|
if (m_menuchange_watchpoint > 0)
|
|
m_menuchange_watchpoint++;
|
|
#endif
|
|
|
|
if (totalclock < m_animation.start)
|
|
{
|
|
m_animation.start = 0;
|
|
m_animation.length = 0;
|
|
}
|
|
|
|
// Determine animation values.
|
|
if (totalclock < m_animation.start + m_animation.length)
|
|
{
|
|
const int32_t screenwidth = scale(240<<16, xdim, ydim);
|
|
|
|
origin.x = mulscale15(screenwidth, m_animation.in(&m_animation));
|
|
previousOrigin.x = mulscale15(screenwidth, m_animation.out(&m_animation));
|
|
}
|
|
|
|
if (m_parentMenu && backgroundOK)
|
|
{
|
|
Menu_Run(m_parentMenu, origin);
|
|
}
|
|
|
|
// Display the menu, with a transition animation if applicable.
|
|
if (totalclock < m_animation.start + m_animation.length)
|
|
{
|
|
Menu_Run(m_animation.previous, previousOrigin);
|
|
Menu_Run(m_animation.current, origin);
|
|
}
|
|
else
|
|
Menu_Run(m_currentMenu, origin);
|
|
|
|
#if !defined EDUKE32_TOUCH_DEVICES
|
|
if (m_menuchange_watchpoint >= 3)
|
|
m_menuchange_watchpoint = 0;
|
|
#endif
|
|
|
|
#if !defined EDUKE32_TOUCH_DEVICES
|
|
if (tilesiz[CROSSHAIR].x > 0 && mousestatus)
|
|
#else
|
|
if (mousestatus)
|
|
#endif
|
|
{
|
|
#if !defined EDUKE32_TOUCH_DEVICES
|
|
if (!MOUSEACTIVECONDITION)
|
|
m_mousewake_watchpoint = 1;
|
|
#endif
|
|
|
|
if (MOUSEACTIVECONDITIONAL(inputState.mouseAdvanceClickState()) || m_mousepos.x != m_prevmousepos.x || m_mousepos.y != m_prevmousepos.y)
|
|
{
|
|
m_prevmousepos = m_mousepos;
|
|
m_mouselastactivity = (int32_t) totalclock;
|
|
}
|
|
#if !defined EDUKE32_TOUCH_DEVICES
|
|
else
|
|
m_mousewake_watchpoint = 0;
|
|
#endif
|
|
|
|
m_mousecaught = 0;
|
|
}
|
|
else
|
|
{
|
|
m_mouselastactivity = -M_MOUSETIMEOUT;
|
|
|
|
#if !defined EDUKE32_TOUCH_DEVICES
|
|
m_mousewake_watchpoint = 0;
|
|
#endif
|
|
}
|
|
|
|
#ifndef EDUKE32_TOUCH_DEVICES
|
|
// Display the mouse cursor, except on touch devices.
|
|
if (MOUSEACTIVECONDITION)
|
|
{
|
|
int32_t a = CROSSHAIR;
|
|
|
|
if ((unsigned) a < MAXTILES)
|
|
{
|
|
vec2_t cursorpos = m_mousepos;
|
|
int32_t z = RR ? 32768 : 65536;
|
|
uint8_t p = CROSSHAIR_PAL;
|
|
uint32_t o = 2;
|
|
|
|
int32_t alpha = CURSORALPHA;
|
|
|
|
rotatesprite_fs_alpha(cursorpos.x, cursorpos.y, z, 0, a, 0, p, o, alpha);
|
|
}
|
|
}
|
|
else
|
|
inputState.clearMouseClickState();
|
|
|
|
#endif
|
|
|
|
if ((g_player[myconnectindex].ps->gm&MODE_MENU) != MODE_MENU)
|
|
{
|
|
G_UpdateScreenArea();
|
|
CAMERACLOCK = (int32_t) totalclock;
|
|
CAMERADIST = 65536;
|
|
}
|
|
}
|
|
|
|
bool GameInterface::mouseInactiveConditional(bool condition)
|
|
{
|
|
return MOUSEINACTIVECONDITIONAL(condition);
|
|
}
|
|
|
|
END_RR_NS
|