Fuckhuge restructuring

- m_menu.c and m_menu.h are dead. Everything has now been moved to k_menudef.c, k_menufunc.c, k_menudraw.c, and k_menu.h.
- Expanded menu_t and menuitem_t to add transitions and tooltips
- Early character select screen
- Removed almost all menu definitions, I'll be reimporting them as they are needed
This commit is contained in:
TehRealSalt 2019-10-02 11:31:11 -04:00
parent bb809d2d2a
commit ca83b06d93
30 changed files with 3242 additions and 9948 deletions

View file

@ -467,7 +467,6 @@ DBGNAME?=$(EXENAME).debug
# $(OBJDIR)/dstrings.o \
# not too sophisticated dependency
# SRB2kart kart.o on line 433 below
OBJS:=$(i_main_o) \
$(OBJDIR)/comptime.o \
$(OBJDIR)/string.o \
@ -496,7 +495,9 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/m_cheat.o \
$(OBJDIR)/m_cond.o \
$(OBJDIR)/m_fixed.o \
$(OBJDIR)/m_menu.o \
$(OBJDIR)/k_menudef.o \
$(OBJDIR)/k_menufunc.o \
$(OBJDIR)/k_menudraw.o \
$(OBJDIR)/m_misc.o \
$(OBJDIR)/m_random.o \
$(OBJDIR)/m_queue.o \

View file

@ -21,7 +21,7 @@
#include "command.h"
#include "console.h"
#include "z_zone.h"
#include "m_menu.h"
#include "k_menu.h"
#include "m_misc.h"
#include "m_fixed.h"
#include "m_argv.h"
@ -75,7 +75,7 @@ CV_PossibleValue_t kartspeed_cons_t[] = {
// Filter consvars by EXECVERSION
// First implementation is 2 (1.0.2), so earlier configs default at 1 (1.0.0)
// Also set CV_HIDEN during runtime, after config is loaded
// Also set CV_HIDDEN during runtime, after config is loaded
static boolean execversion_enabled = false;
consvar_t cv_execversion = {"execversion","1",CV_CALL,CV_Unsigned, CV_EnforceExecVersion, 0, NULL, NULL, 0, 0, NULL};
@ -1112,7 +1112,7 @@ void CV_RegisterVar(consvar_t *variable)
}
// link the variable in
if (!(variable->flags & CV_HIDEN))
if (!(variable->flags & CV_HIDDEN))
{
variable->next = consvar_vars;
consvar_vars = variable;
@ -1628,6 +1628,7 @@ void CV_AddValue(consvar_t *var, INT32 increment)
if (var->PossibleValue)
{
#if 0
if (var == &cv_nextmap)
{
// Special case for the nextmap variable, used only directly from the menu
@ -1662,9 +1663,12 @@ void CV_AddValue(consvar_t *var, INT32 increment)
return;
}
}
else
#endif
#define MINVAL 0
#define MAXVAL 1
else if (var->PossibleValue[MINVAL].strvalue && !strcmp(var->PossibleValue[MINVAL].strvalue, "MIN"))
if (var->PossibleValue[MINVAL].strvalue && !strcmp(var->PossibleValue[MINVAL].strvalue, "MIN"))
{ // SRB2Kart
#ifdef PARANOIA
if (!var->PossibleValue[MAXVAL].strvalue)

View file

@ -95,7 +95,7 @@ typedef enum
CV_SHOWMODIF = 128, // say something when modified
CV_SHOWMODIFONETIME = 256, // same but will be reset to 0 when modified, set in toggle
CV_NOSHOWHELP = 512, // Don't show variable in the HELP list Tails 08-13-2002
CV_HIDEN = 1024, // variable is not part of the cvar list so cannot be accessed by the console
CV_HIDDEN = 1024, // variable is not part of the cvar list so cannot be accessed by the console
// can only be set when we have the pointer to it
// used on menus
CV_CHEAT = 2048, // Don't let this be used in multiplayer unless cheats are on.

View file

@ -32,7 +32,7 @@
#include "z_zone.h"
#include "i_system.h"
#include "d_main.h"
#include "m_menu.h"
#include "k_menu.h"
#include "filesrch.h"
#ifdef _WINDOWS
@ -140,28 +140,6 @@ static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Black"}, {
{0, NULL}};
consvar_t cons_backcolor = {"con_backcolor", "Black", CV_CALL|CV_SAVE, backcolor_cons_t, CONS_backcolor_Change, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t menuhighlight_cons_t[] =
{
{0, "Game type"},
{V_YELLOWMAP, "Always yellow"},
{V_PURPLEMAP, "Always purple"},
{V_GREENMAP, "Always green"},
{V_BLUEMAP, "Always blue"},
{V_REDMAP, "Always red"},
{V_GRAYMAP, "Always gray"},
{V_ORANGEMAP, "Always orange"},
{V_SKYMAP, "Always sky-blue"},
{V_GOLDMAP, "Always gold"},
{V_LAVENDERMAP, "Always lavender"},
{V_AQUAMAP, "Always aqua-green"},
{V_MAGENTAMAP, "Always magenta"},
{V_PINKMAP, "Always pink"},
{V_BROWNMAP, "Always brown"},
{V_TANMAP, "Always tan"},
{0, NULL}
};
consvar_t cons_menuhighlight = {"menuhighlight", "Game type", CV_SAVE, menuhighlight_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static void CON_Print(char *msg);
//
@ -406,7 +384,6 @@ void CON_Init(void)
CV_RegisterVar(&cons_height);
CV_RegisterVar(&cons_backpic);
CV_RegisterVar(&cons_backcolor);
CV_RegisterVar(&cons_menuhighlight);
COM_AddCommand("bind", CONS_Bind_f);
}
else

View file

@ -36,7 +36,7 @@ extern INT32 con_clearlines; // lines of top of screen to refresh
extern boolean con_hudupdate; // hud messages have changed, need refresh
extern UINT32 con_scalefactor; // console text scale factor
extern consvar_t cons_backcolor, cons_menuhighlight;
extern consvar_t cons_backcolor;
extern UINT8 *yellowmap, *purplemap, *greenmap, *bluemap, *graymap, *redmap, *orangemap,\
*skymap, *goldmap, *lavendermap, *aquamap, *magentamap, *pinkmap, *brownmap, *tanmap;

View file

@ -28,7 +28,7 @@
#include "hu_stuff.h"
#include "keys.h"
#include "g_input.h" // JOY1
#include "m_menu.h"
#include "k_menu.h"
#include "console.h"
#include "d_netfil.h"
#include "byteptr.h"

View file

@ -52,7 +52,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
#include "i_system.h"
#include "i_video.h"
#include "m_argv.h"
#include "m_menu.h"
#include "k_menu.h"
#include "m_misc.h"
#include "p_setup.h"
#include "p_saveg.h"
@ -1187,7 +1187,9 @@ void D_SRB2Main(void)
// Setup character tables
// Have to be done here before files are loaded
#ifdef USEPLAYERMENU
M_InitCharacterTables();
#endif
// load wad, including the main wad file
CONS_Printf("W_InitMultipleFiles(): Adding main IWAD and PWADs.\n");

View file

@ -20,7 +20,7 @@
#include "g_game.h"
#include "hu_stuff.h"
#include "g_input.h"
#include "m_menu.h"
#include "k_menu.h"
#include "r_local.h"
#include "r_things.h"
#include "p_local.h"
@ -300,8 +300,8 @@ consvar_t cv_joyscale2 = {"joyscale2", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale2,
consvar_t cv_joyscale3 = {"joyscale3", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale3, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_joyscale4 = {"joyscale4", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale4, 0, NULL, NULL, 0, 0, NULL};
#else
consvar_t cv_joyscale = {"joyscale", "1", CV_SAVE|CV_HIDEN, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: Dummy for save
consvar_t cv_joyscale2 = {"joyscale2", "1", CV_SAVE|CV_HIDEN, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: Dummy for save
consvar_t cv_joyscale = {"joyscale", "1", CV_SAVE|CV_HIDDEN, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: Dummy for save
consvar_t cv_joyscale2 = {"joyscale2", "1", CV_SAVE|CV_HIDDEN, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; //Alam: Dummy for save
#endif
#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON)
consvar_t cv_mouse2port = {"mouse2port", "/dev/gpmdata", CV_SAVE, mouse2port_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -794,18 +794,22 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_playername);
CV_RegisterVar(&cv_playercolor);
CV_RegisterVar(&cv_skin); // r_things.c (skin NAME)
// secondary player (splitscreen)
CV_RegisterVar(&cv_playername2);
CV_RegisterVar(&cv_playercolor2);
CV_RegisterVar(&cv_skin2);
// third player
CV_RegisterVar(&cv_playername3);
CV_RegisterVar(&cv_playercolor3);
CV_RegisterVar(&cv_skin3);
// fourth player
CV_RegisterVar(&cv_playername4);
CV_RegisterVar(&cv_playercolor4);
CV_RegisterVar(&cv_skin4);
// preferred number of players
CV_RegisterVar(&cv_splitplayers);
@ -839,7 +843,7 @@ void D_RegisterClientCommands(void)
// FIXME: not to be here.. but needs be done for config loading
CV_RegisterVar(&cv_usegamma);
// m_menu.c
// k_menu.c
//CV_RegisterVar(&cv_compactscoreboard);
CV_RegisterVar(&cv_chatheight);
CV_RegisterVar(&cv_chatwidth);
@ -925,10 +929,12 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_usejoystick2);
CV_RegisterVar(&cv_usejoystick3);
CV_RegisterVar(&cv_usejoystick4);
#ifdef LJOYSTICK
CV_RegisterVar(&cv_joyport);
CV_RegisterVar(&cv_joyport2);
#endif
CV_RegisterVar(&cv_joyscale);
CV_RegisterVar(&cv_joyscale2);
CV_RegisterVar(&cv_joyscale3);
@ -3958,7 +3964,7 @@ static void Got_Removal(UINT8 **cp, INT32 playernum)
}
// Join password stuff
consvar_t cv_dummyjoinpassword = {"dummyjoinpassword", "", CV_HIDEN|CV_NOSHOWHELP|CV_PASSWORD, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_dummyjoinpassword = {"dummyjoinpassword", "", CV_HIDDEN|CV_NOSHOWHELP|CV_PASSWORD, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
#define NUMJOINCHALLENGES 32
static UINT8 joinpassmd5[MD5_LEN+1];

View file

@ -56,7 +56,7 @@
#include "byteptr.h"
#include "p_setup.h"
#include "m_misc.h"
#include "m_menu.h"
#include "k_menu.h"
#include "md5.h"
#include "filesrch.h"

View file

@ -19,7 +19,7 @@
#include "m_argv.h"
#include "z_zone.h"
#include "w_wad.h"
#include "m_menu.h"
#include "k_menu.h"
#include "m_misc.h"
#include "filesrch.h" // for refreshdirmenu
#include "f_finale.h"
@ -34,6 +34,7 @@
#include "lua_script.h"
#include "lua_hook.h"
#include "d_clisrv.h"
#include "r_things.h"
#include "m_cond.h"
@ -432,7 +433,8 @@ static void readAnimTex(MYFILE *f, INT32 num)
}
*/
static boolean findFreeSlot(INT32 *num)
#ifdef USEPLAYERMENU
static boolean findPlayerFreeSlot(INT32 *num)
{
// Send the character select entry to a free slot.
while (*num < MAXSKINS && PlayerMenu[*num].status != IT_DISABLED)
@ -475,7 +477,7 @@ static void readPlayer(MYFILE *f, INT32 num)
{
char *playertext = NULL;
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
if (!slotfound && (slotfound = findPlayerFreeSlot(&num)) == false)
goto done;
PlayerMenu[num].status = IT_CALL;
@ -525,7 +527,7 @@ static void readPlayer(MYFILE *f, INT32 num)
/*if (fastcmp(word, "PLAYERNAME"))
{
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
if (!slotfound && (slotfound = findPlayerFreeSlot(&num)) == false)
goto done;
DEH_WriteUndoline(word, description[num].text, UNDO_NONE);
strlcpy(description[num].text, word2, sizeof (description[num].text));
@ -547,7 +549,7 @@ static void readPlayer(MYFILE *f, INT32 num)
} */
/*else*/ if (fastcmp(word, "PICNAME"))
{
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
if (!slotfound && (slotfound = findPlayerFreeSlot(&num)) == false)
goto done;
DEH_WriteUndoline(word, &description[num].picname[0], UNDO_NONE);
PlayerMenu[num].status = IT_CALL;
@ -571,7 +573,7 @@ static void readPlayer(MYFILE *f, INT32 num)
... Or use MENUPOSITION first, that works too. Hell, you could edit multiple character
slots in a single section that way, due to how SOC editing works.
*/
if (i != IT_DISABLED && !slotfound && (slotfound = findFreeSlot(&num)) == false)
if (i != IT_DISABLED && !slotfound && (slotfound = findPlayerFreeSlot(&num)) == false)
goto done;
DEH_WriteUndoline(word, va("%d", PlayerMenu[num].status), UNDO_NONE);
PlayerMenu[num].status = (INT16)i;
@ -579,7 +581,7 @@ static void readPlayer(MYFILE *f, INT32 num)
else if (fastcmp(word, "SKINNAME"))
{
// Send to free slot.
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
if (!slotfound && (slotfound = findPlayerFreeSlot(&num)) == false)
goto done;
DEH_WriteUndoline(word, description[num].skinname, UNDO_NONE);
PlayerMenu[num].status = IT_CALL;
@ -600,6 +602,7 @@ static void readPlayer(MYFILE *f, INT32 num)
done:
Z_Free(s);
}
#endif
static int freeslotusage[2][2] = {{0, 0}, {0, 0}}; // [S_, MT_][max, previous .wad's max]
@ -3452,6 +3455,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
continue;
}
word2 = strtok(NULL, " ");
#ifdef USEPLAYERMENU
if (fastcmp(word, "CHARACTER"))
{
if (word2) {
@ -3472,6 +3476,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
// This is not a major mod.
continue;
}
#endif
if (word2)
{
strupr(word2);
@ -8933,8 +8938,7 @@ struct {
{"CV_SHOWMODIF",CV_SHOWMODIF},
{"CV_SHOWMODIFONETIME",CV_SHOWMODIFONETIME},
{"CV_NOSHOWHELP",CV_NOSHOWHELP},
{"CV_HIDEN",CV_HIDEN},
{"CV_HIDDEN",CV_HIDEN},
{"CV_HIDDEN",CV_HIDDEN},
{"CV_CHEAT",CV_CHEAT},
// v_video flags

View file

@ -24,7 +24,7 @@
#include "w_wad.h"
#include "z_zone.h"
#include "i_system.h"
#include "m_menu.h"
#include "k_menu.h"
#include "dehacked.h"
#include "g_input.h"
#include "console.h"

View file

@ -26,7 +26,7 @@
#include "z_zone.h"
#include "i_system.h"
#include "m_menu.h"
#include "k_menu.h"
#include "console.h"
#include "d_main.h"
#include "m_misc.h" // movie mode

View file

@ -32,7 +32,7 @@
#include "d_netfil.h"
#include "m_misc.h"
#include "z_zone.h"
#include "m_menu.h" // Addons_option_Onchange
#include "k_menu.h" // Addons_option_Onchange
#if (defined (_WIN32) && !defined (_WIN32_WCE)) && defined (_MSC_VER) && !defined (_XBOX)

View file

@ -6,7 +6,7 @@
#include "doomdef.h"
#include "d_netfil.h"
#include "m_menu.h" // MAXSTRINGLENGTH
#include "k_menu.h" // MAXSTRINGLENGTH
extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_addons_search_type;

View file

@ -30,7 +30,7 @@
#include "g_game.h"
#include "m_cheat.h"
#include "m_misc.h"
#include "m_menu.h"
#include "k_menu.h"
#include "m_argv.h"
#include "hu_stuff.h"
#include "st_stuff.h"
@ -3831,9 +3831,11 @@ void G_AfterIntermission(void)
{
G_StopDemo();
#if 0
if (demo.inreplayhut)
M_ReplayHut(0);
else
#endif
D_StartTitle();
return;
@ -4327,7 +4329,7 @@ static void M_ForceLoadGameResponse(INT32 ch)
Z_Free(savebuffer);
save_p = savebuffer = NULL;
startonmapnum = 0;
M_SetupNextMenu(&SP_LoadDef);
M_SetupNextMenu(&SP_LoadDef, false);
return;
}

View file

@ -24,7 +24,7 @@
#include "../z_zone.h"
#include "../console.h"
#include "../v_video.h"
#include "../m_menu.h"
#include "../k_menu.h"
#include "../i_system.h"
#include "../m_argv.h"
#include "../i_video.h"

View file

@ -15,7 +15,7 @@
#include "byteptr.h"
#include "hu_stuff.h"
#include "m_menu.h" // gametype_cons_t
#include "k_menu.h" // gametype_cons_t
#include "m_cond.h" // emblems
#include "d_clisrv.h"
@ -111,7 +111,7 @@ static patch_t *tokenicon;
// misc vars
//-------------------------------------------
// crosshair 0 = off, 1 = cross, 2 = angle, 3 = point, see m_menu.c
// crosshair 0 = off, 1 = cross, 2 = angle, 3 = point, see k_menu.c
static patch_t *crosshair[HU_CROSSHAIRS]; // 3 precached crosshair graphics
// song credits
static patch_t *songcreditbg;
@ -1624,7 +1624,7 @@ static void HU_drawChatLog(INT32 offset)
INT32 x = chatx+2, y, dx = 0, dy = 0;
UINT32 i = 0;
INT32 chat_topy, chat_bottomy;
INT32 highlight = HU_GetHighlightColor();
INT32 highlight = V_YELLOWMAP;
boolean atbottom = false;
// make sure that our scroll position isn't "illegal";
@ -2947,9 +2947,7 @@ static void HU_DrawRankings(void)
V_DrawFadeScreen(0xFF00, 16); // A little more readable, and prevents cheating the fades under other circumstances.
if (cons_menuhighlight.value)
hilicol = cons_menuhighlight.value;
else if (modeattacking)
if (modeattacking)
hilicol = V_ORANGEMAP;
else
hilicol = ((gametype == GT_RACE) ? V_SKYMAP : V_REDMAP);

View file

@ -9,68 +9,15 @@
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file m_menu.h
/// \file k_menu.h
/// \brief Menu widget stuff, selection and such
#ifndef __X_MENU__
#define __X_MENU__
#ifndef __K_MENU__
#define __K_MENU__
#include "d_event.h"
#include "command.h"
#include "r_things.h" // for SKINNAMESIZE
//
// MENUS
//
// Called by main loop,
// saves config file and calls I_Quit when user exits.
// Even when the menu is not displayed,
// this can resize the view and change game parameters.
// Does all the real work of the menu interaction.
boolean M_Responder(event_t *ev);
// Called by main loop, only used for menu (skull cursor) animation.
void M_Ticker(void);
// Called by main loop, draws the menus directly into the screen buffer.
void M_Drawer(void);
// Called by D_SRB2Main, loads the config file.
void M_Init(void);
// Called by D_SRB2Main also, sets up the playermenu and description tables.
void M_InitCharacterTables(void);
// Called by intro code to force menu up upon a keypress,
// does nothing if menu is already up.
void M_StartControlPanel(void);
// Called upon end of a mode attack run
void M_EndModeAttackRun(void);
// Called on new server add, or other reasons
void M_SortServerList(void);
// Draws a box with a texture inside as background for messages
void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines);
// the function to show a message box typing with the string inside
// string must be static (not in the stack)
// routine is a function taking a INT32 in parameter
typedef enum
{
MM_NOTHING = 0, // is just displayed until the user do someting
MM_YESNO, // routine is called with only 'y' or 'n' in param
MM_EVENTHANDLER // the same of above but without 'y' or 'n' restriction
// and routine is void routine(event_t *) (ex: set control)
} menumessagetype_t;
void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtype);
// Called by linux_x/i_video_xshm.c
void M_QuitResponse(INT32 ch);
// Determines whether to show a level in the list
boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt);
#include "doomstat.h" // MAXSPLITSCREENPLAYERS
// flags for items in the menu
// menu handle (what we do when key is pressed
@ -141,179 +88,220 @@ typedef union
//
typedef struct menuitem_s
{
// show IT_xxx
UINT16 status;
UINT16 status; // show IT_xxx
const char *patch;
const char *text; // used when FONTBxx lump is found
const char *text; // option title
const char *tooltip; // description of option used by K_MenuTooltips
const char *patch; // image of option used by K_MenuPreviews
// FIXME: should be itemaction_t
void *itemaction;
void *itemaction; // FIXME: should be itemaction_t
// extra variables
UINT8 mvar1;
UINT8 mvar2;
} menuitem_t;
extern menuitem_t PlayerMenu[MAXSKINS];
typedef struct menu_s
{
const char *menutitlepic;
INT16 numitems; // # of menu items
struct menu_s *prevMenu; // previous menu
menuitem_t *menuitems; // menu items
void (*drawroutine)(void); // draw routine
INT16 x, y; // x, y of menu
INT16 lastOn; // last item user was on in menu
menuitem_t *menuitems; // menu items
INT16 x, y; // x, y of menu
INT16 transitionInTics; // tics for transitions in
INT16 transitionOutTics; // tics for transitions out
void (*drawroutine)(void); // draw routine
boolean (*quitroutine)(void); // called before quit a menu return true if we can
} menu_t;
void M_SetupNextMenu(menu_t *menudef);
void M_ClearMenus(boolean callexitmenufunc);
typedef enum
{
MM_NOTHING = 0, // is just displayed until the user do someting
MM_YESNO, // routine is called with only 'y' or 'n' in param
MM_EVENTHANDLER // the same of above but without 'y' or 'n' restriction
// and routine is void routine(event_t *) (ex: set control)
} menumessagetype_t;
// ===========
// PROTOTYPING
// ===========
// K_MENUDEF.C
extern menuitem_t MainMenu[];
extern menu_t MainDef;
typedef enum
{
play = 0,
extra,
options,
quitkart
} main_e;
extern menuitem_t PLAY_MainMenu[];
extern menu_t PLAY_MainDef;
extern menuitem_t PLAY_CharSelect[];
extern menu_t PLAY_CharSelectDef;
extern menuitem_t PLAY_Gamemodes[];
extern menu_t PLAY_GamemodesDef;
extern menuitem_t PLAY_RaceGamemodesMenu[];
extern menu_t PLAY_RaceGamemodesDef;
extern menuitem_t PAUSE_PlaybackMenu[];
extern menu_t PAUSE_PlaybackMenuDef;
typedef enum
{
playback_hide,
playback_rewind,
playback_pause,
playback_fastforward,
playback_backframe,
playback_resume,
playback_advanceframe,
playback_viewcount,
playback_view1,
playback_view2,
playback_view3,
playback_view4,
playback_quit
} playback_e;
// K_MENUFUNC.C
extern menu_t *currentMenu;
extern menu_t MainDef;
extern menu_t SP_LoadDef;
extern char dummystaffname[22];
// Call upon joystick hotplug
void M_SetupJoystickMenu(INT32 choice);
extern menu_t OP_JoystickSetDef;
extern INT16 itemOn; // menu item skull is on, Hack by Tails 09-18-2002
extern INT16 skullAnimCounter; // skull animation counter
// Stuff for customizing the player select screen
typedef struct
{
char notes[441];
char picname[8];
char skinname[SKINNAMESIZE*2+2]; // skin&skin\0
} description_t;
extern struct menutransition_s {
INT16 tics;
INT16 dest;
struct menu_s *newmenu;
boolean in;
} menutransition;
// mode descriptions for video mode menu
typedef struct
{
INT32 modenum; // video mode number in the vidmodes list
const char *desc; // XXXxYYY
UINT8 goodratio; // aspect correct if 1
} modedesc_t;
// savegame struct for save game menu
typedef struct
{
char playername[37];
char levelname[32];
UINT8 actnum;
UINT8 skincolor;
UINT8 skinnum;
UINT8 botskin;
UINT8 botcolor;
UINT8 numemeralds;
INT32 lives;
INT32 continues;
INT32 gamemap;
UINT8 netgame;
} saveinfo_t;
extern description_t description[MAXSKINS];
extern boolean menuwipe;
extern consvar_t cv_showfocuslost;
extern consvar_t cv_newgametype, cv_nextmap, cv_chooseskin, cv_serversort;
extern CV_PossibleValue_t gametype_cons_t[];
extern char dummystaffname[22];
extern INT16 startmap;
extern INT32 ultimate_selectable;
#define MAXSAVEGAMES 31 //note: last save game is "no save"
#define NOSAVESLOT MAXSAVEGAMES-1 //slot where Play Without Saving appears
void M_ForceSaveSlotSelected(INT32 sslot);
void M_CheatActivationResponder(INT32 ch);
// Screenshot menu updating
void Moviemode_mode_Onchange(void);
void Screenshot_option_Onchange(void);
// Addons menu updating
void Addons_option_Onchange(void);
void M_ReplayHut(INT32 choice);
void M_SetPlaybackMenuPointer(void);
void M_SortServerList(void);
INT32 HU_GetHighlightColor(void);
boolean M_Responder(event_t *ev);
void M_StartControlPanel(void);
void M_ClearMenus(boolean callexitmenufunc);
void M_SelectableClearMenus(INT32 choice);
void M_SetupNextMenu(menu_t *menudef, boolean nofade);
void M_GoBack(INT32 choice);
void M_Ticker(void);
void M_Init(void);
menu_t MessageDef;
void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtype);
void M_StopMessage(INT32 choice);
void M_HandleImageDef(INT32 choice);
void M_QuitResponse(INT32 ch);
void M_QuitSRB2(INT32 choice);
// If you want to waste a bunch of memory for a limit no one will hit, feel free to boost this to MAXSKINS :P
// I figure this will be enough clone characters to fit onto the character select.
// (If someone runs into it after release I'll probably boost it, though.)
#define MAXCLONES MAXSKINS/16
extern struct setup_chargrid_s {
SINT8 skinlist[MAXCLONES];
UINT8 numskins;
} setup_chargrid[9][9];
typedef struct setup_player_s
{
SINT8 gridx, gridy;
SINT8 skin;
SINT8 clonenum;
UINT8 color;
UINT8 mdepth;
} setup_player_t;
extern setup_player_t setup_player[MAXSPLITSCREENPLAYERS];
extern UINT8 setup_numplayers;
typedef enum
{
SPLITCV_SKIN = 0,
SPLITCV_COLOR,
SPLITCV_NAME,
SPLITCV_MAX
} splitscreencvars_t;
consvar_t *setup_playercvars[MAXSPLITSCREENPLAYERS][SPLITCV_MAX];
void M_CharacterSelectInit(INT32 choice);
void M_CharacterSelectHandler(INT32 choice);
boolean M_CharacterSelectQuit(void);
void M_EndModeAttackRun(void);
void M_SetPlaybackMenuPointer(void);
void M_PlaybackRewind(INT32 choice);
void M_PlaybackPause(INT32 choice);
void M_PlaybackFastForward(INT32 choice);
void M_PlaybackAdvance(INT32 choice);
void M_PlaybackSetViews(INT32 choice);
void M_PlaybackAdjustView(INT32 choice);
void M_PlaybackQuit(INT32 choice);
void M_ReplayHut(INT32 choice);
// M_MENUDRAW.C
void M_Drawer(void);
void M_DrawGenericMenu(void);
void M_DrawKartGamemodeMenu(void);
void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines);
void M_DrawMessageMenu(void);
void M_DrawImageDef(void);
void M_DrawCharacterSelect(void);
void M_DrawPlaybackMenu(void);
// These defines make it a little easier to make menus
#define KARTGAMEMODEMENU(header, source, prev)\
#define DEFAULTMENUSTYLE(source, prev, x, y)\
{\
header,\
sizeof(source) / sizeof(menuitem_t),\
prev,\
source,\
M_DrawKartGamemodeMenu,\
0, 0,\
0,\
NULL\
}
#define DEFAULTMENUSTYLE(header, source, prev, x, y)\
{\
header,\
sizeof(source)/sizeof(menuitem_t),\
prev,\
source,\
x, y,\
0, 0,\
M_DrawGenericMenu,\
x, y,\
0,\
NULL\
}
#define PAUSEMENUSTYLE(source, x, y)\
{\
NULL,\
sizeof(source)/sizeof(menuitem_t),\
NULL,\
source,\
M_DrawPauseMenu,\
x, y,\
0,\
NULL\
}
#define MAPICONMENUSTYLE(header, source, prev)\
#define KARTGAMEMODEMENU(source, prev)\
{\
header,\
sizeof(source) / sizeof(menuitem_t),\
prev,\
source,\
M_DrawServerMenu,\
24,40,\
0,\
NULL\
}
#define CONTROLMENUSTYLE(source, prev)\
{\
"M_CONTRO",\
sizeof (source)/sizeof (menuitem_t),\
prev,\
source,\
M_DrawControl,\
26, 40,\
0,\
NULL\
}
#define IMAGEDEF(source)\
{\
NULL,\
sizeof (source)/sizeof (menuitem_t),\
NULL,\
source,\
M_DrawImageDef,\
0, 0,\
0,\
10, 10,\
M_DrawKartGamemodeMenu,\
NULL\
}
#endif //__X_MENU__
#endif //__K_MENU__

132
src/k_menudef.c Normal file
View file

@ -0,0 +1,132 @@
/// \file k_menudef.c
/// \brief SRB2Kart menu definitions
#include "k_menu.h"
#include "screen.h" // BASEVIDWIDTH
// ==========================================================================
// ORGANIZATION START.
// ==========================================================================
// Note: Never should we be jumping from one category of menu options to another
// without first going to the Main Menu.
// Note: Ignore the above if you're working with the Pause menu.
// Note: (Prefix)_MainMenu should be the target of all Main Menu options that
// point to submenus.
// ---------
// Main Menu
// ---------
menuitem_t MainMenu[] =
{
{IT_STRING | IT_CALL, "Play", "Cut to the chase and start playing!",
NULL, M_CharacterSelectInit, 48, 0},
{IT_STRING, "Extra", "Check out some bonus features.",
NULL, NULL, 80, 0},
{IT_STRING, "Option", "Configure your controls, settings, and preferences.",
NULL, NULL, 112, 0},
{IT_STRING | IT_CALL, "Quit", "Exit SRB2Kart.",
NULL, M_QuitSRB2, 160, 0},
};
menu_t MainDef = KARTGAMEMODEMENU(MainMenu, NULL);
// ---------
// Play Menu
// ---------
menuitem_t PLAY_CharSelect[] =
{
{IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, M_CharacterSelectHandler, 0, 0},
};
menu_t PLAY_CharSelectDef = {
sizeof (PLAY_CharSelect) / sizeof (menuitem_t),
&MainDef,
0,
PLAY_CharSelect,
0, 0,
0, 0,
M_DrawCharacterSelect,
M_CharacterSelectQuit
};
menuitem_t PLAY_MainMenu[] =
{
{IT_STRING | IT_SUBMENU, "Local Play", "Play only on this computer.",
NULL, &PLAY_GamemodesDef, 64, 0},
{IT_STRING, "Online", "Connect to other computers.",
NULL, NULL, 96, 0},
{IT_STRING | IT_CALL, "Back", NULL, NULL, M_GoBack, 160, 0},
};
menu_t PLAY_MainDef = KARTGAMEMODEMENU(PLAY_MainMenu, &PLAY_CharSelectDef);
menuitem_t PLAY_GamemodesMenu[] =
{
{IT_STRING | IT_SUBMENU, "Race", "A competition for the best time!",
NULL, &PLAY_RaceGamemodesDef, 64, 0},
{IT_STRING, "Battle", "Clash against other players in a survival match!",
NULL, NULL, 96, 0},
{IT_STRING | IT_CALL, "Back", NULL, NULL, M_GoBack, 160, 0},
};
menu_t PLAY_GamemodesDef = KARTGAMEMODEMENU(PLAY_GamemodesMenu, &PLAY_MainDef);
menuitem_t PLAY_RaceGamemodesMenu[] =
{
{IT_STRING, "Grand Prix", "Compete for the best rank over five races!",
NULL, NULL, 48, 0},
{IT_STRING, "Match Race", "Pick your own settings in a specialized single race.",
NULL, NULL, 80, 0},
{IT_STRING, "Time Attack", "Race against ghosts for the best time, no fluff.",
NULL, NULL, 112, 0},
{IT_STRING | IT_CALL, "Back", NULL, NULL, M_GoBack, 160, 0},
};
menu_t PLAY_RaceGamemodesDef = KARTGAMEMODEMENU(PLAY_RaceGamemodesMenu, &PLAY_GamemodesDef);
// -------------------
// In-game/pause menus
// -------------------
menuitem_t PAUSE_PlaybackMenu[] =
{
{IT_CALL | IT_STRING, "Hide Menu", NULL, "M_PHIDE", M_SelectableClearMenus, 0, 0},
{IT_CALL | IT_STRING, "Rewind", NULL, "M_PREW", M_PlaybackRewind, 20, 0},
{IT_CALL | IT_STRING, "Pause", NULL, "M_PPAUSE", M_PlaybackPause, 36, 0},
{IT_CALL | IT_STRING, "Fast-Forward", NULL, "M_PFFWD", M_PlaybackFastForward, 52, 0},
{IT_CALL | IT_STRING, "Backup Frame", NULL, "M_PSTEPB", M_PlaybackRewind, 20, 0},
{IT_CALL | IT_STRING, "Resume", NULL, "M_PRESUM", M_PlaybackPause, 36, 0},
{IT_CALL | IT_STRING, "Advance Frame", NULL, "M_PFADV", M_PlaybackAdvance, 52, 0},
{IT_ARROWS | IT_STRING, "View Count", NULL, "M_PVIEWS", M_PlaybackSetViews, 72, 0},
{IT_ARROWS | IT_STRING, "Viewpoint", NULL, "M_PNVIEW", M_PlaybackAdjustView, 88, 0},
{IT_ARROWS | IT_STRING, "Viewpoint 2", NULL, "M_PNVIEW", M_PlaybackAdjustView, 104, 0},
{IT_ARROWS | IT_STRING, "Viewpoint 3", NULL, "M_PNVIEW", M_PlaybackAdjustView, 120, 0},
{IT_ARROWS | IT_STRING, "Viewpoint 4", NULL, "M_PNVIEW", M_PlaybackAdjustView, 136, 0},
{IT_CALL | IT_STRING, "Stop Playback", NULL, "M_PEXIT", M_PlaybackQuit, 156, 0},
};
menu_t PAUSE_PlaybackMenuDef = {
sizeof (PAUSE_PlaybackMenu) / sizeof (menuitem_t),
NULL,
0,
PAUSE_PlaybackMenu,
BASEVIDWIDTH/2 - 88, 2,
0, 0,
M_DrawPlaybackMenu,
NULL
};

844
src/k_menudraw.c Normal file
View file

@ -0,0 +1,844 @@
/// \file k_menudraw.c
/// \brief SRB2Kart's menu drawer functions
#ifdef __GNUC__
#include <unistd.h>
#endif
#include "k_menu.h"
#include "doomdef.h"
#include "d_main.h"
#include "d_netcmd.h"
#include "console.h"
#include "r_local.h"
#include "hu_stuff.h"
#include "g_game.h"
#include "g_input.h"
#include "m_argv.h"
// Data.
#include "sounds.h"
#include "s_sound.h"
#include "i_system.h"
// Addfile
#include "filesrch.h"
#include "v_video.h"
#include "i_video.h"
#include "keys.h"
#include "z_zone.h"
#include "w_wad.h"
#include "p_local.h"
#include "p_setup.h"
#include "f_finale.h"
#ifdef HWRENDER
#include "hardware/hw_main.h"
#endif
#include "d_net.h"
#include "mserv.h"
#include "m_misc.h"
#include "m_anigif.h"
#include "byteptr.h"
#include "st_stuff.h"
#include "i_sound.h"
#include "k_kart.h" // SRB2kart
#include "d_player.h" // KITEM_ constants
#include "doomstat.h" // MAXSPLITSCREENPLAYERS
#include "i_joy.h" // for joystick menu controls
// Condition Sets
#include "m_cond.h"
// And just some randomness for the exits.
#include "m_random.h"
#if defined(HAVE_SDL)
#include "SDL.h"
#if SDL_VERSION_ATLEAST(2,0,0)
#include "sdl/sdlmain.h" // JOYSTICK_HOTPLUG
#endif
#endif
#ifdef PC_DOS
#include <stdio.h> // for snprintf
int snprintf(char *str, size_t n, const char *fmt, ...);
//int vsnprintf(char *str, size_t n, const char *fmt, va_list ap);
#endif
// flags for text highlights
#define highlightflags V_ORANGEMAP
#define recommendedflags V_GREENMAP
#define warningflags V_GRAYMAP
#define SKULLXOFF -32
#define LINEHEIGHT 16
#define STRINGHEIGHT 8
#define FONTBHEIGHT 20
#define SMALLLINEHEIGHT 8
#define SLIDER_RANGE 10
#define SLIDER_WIDTH (8*SLIDER_RANGE+6)
#define SERVERS_PER_PAGE 11
//
// M_Drawer
// Called after the view has been rendered,
// but before it has been blitted.
//
void M_Drawer(void)
{
if (currentMenu == &MessageDef)
menuactive = true;
if (menuwipe)
F_WipeStartScreen();
if (menuactive)
{
if (gamestate == GS_MENU) // draw BG
V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName("MENUBG", PU_CACHE), NULL);
else if (!WipeInAction && currentMenu != &PAUSE_PlaybackMenuDef)
V_DrawFadeScreen(0xFF00, 16); // now that's more readable with a faded background (yeah like Quake...)
if (currentMenu->drawroutine)
currentMenu->drawroutine(); // call current menu Draw routine
// draw non-green resolution border
if ((gamestate == GS_MENU) && ((vid.width % BASEVIDWIDTH != 0) || (vid.height % BASEVIDHEIGHT != 0)))
V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName("WEIRDRES", PU_CACHE), NULL);
// Draw version down in corner
// ... but only in the MAIN MENU. I'm a picky bastard.
if (currentMenu == &MainDef)
{
if (customversionstring[0] != '\0')
{
V_DrawThinString(vid.dupx, vid.height - 20*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT, "Mod version:");
V_DrawThinString(vid.dupx, vid.height - 10*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, customversionstring);
}
else
{
#ifdef DEVELOP // Development -- show revision / branch info
V_DrawThinString(vid.dupx, vid.height - 20*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, compbranch);
V_DrawThinString(vid.dupx, vid.height - 10*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, comprevision);
#else // Regular build
V_DrawThinString(vid.dupx, vid.height - 10*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, va("%s", VERSIONSTRING));
#endif
}
}
}
if (menuwipe)
{
F_WipeEndScreen();
F_RunWipe(wipedefs[wipe_menu_final], false, "FADEMAP0", true);
menuwipe = false;
}
// focus lost notification goes on top of everything, even the former everything
if (window_notinfocus && cv_showfocuslost.value)
{
M_DrawTextBox((BASEVIDWIDTH/2) - (60), (BASEVIDHEIGHT/2) - (16), 13, 2);
if (gamestate == GS_LEVEL && (P_AutoPause() || paused))
V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2) - (4), highlightflags, "Game Paused");
else
V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2) - (4), highlightflags, "Focus Lost");
}
}
// ==========================================================================
// GENERIC MENUS
// ==========================================================================
//
// M_DrawMenuTooltips
//
// Draw a banner across the top of the screen, with a description of the current option displayed
//
static void M_DrawMenuTooltips(void)
{
V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName("MENUHINT", PU_CACHE), NULL);
if (currentMenu->menuitems[itemOn].tooltip != NULL)
V_DrawCenteredThinString(BASEVIDWIDTH/2, 12, V_ALLOWLOWERCASE|V_6WIDTHSPACE, currentMenu->menuitems[itemOn].tooltip);
}
//
// M_DrawMenuPreviews
//
// Draw a box with a preview image of the current option
//
static void M_DrawMenuPreviews(void)
{
V_DrawFixedPatch(172<<FRACBITS, 29<<FRACBITS, FRACUNIT, 0, W_CachePatchName("MENUPREV", PU_CACHE), NULL);
if (currentMenu->menuitems[itemOn].patch != NULL)
V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName(currentMenu->menuitems[itemOn].patch, PU_CACHE), NULL);
}
// Converts a string into question marks.
// Used for the secrets menu, to hide yet-to-be-unlocked stuff.
static const char *M_CreateSecretMenuOption(const char *str)
{
static char qbuf[32];
int i;
for (i = 0; i < 31; ++i)
{
if (!str[i])
{
qbuf[i] = '\0';
return qbuf;
}
else if (str[i] != ' ')
qbuf[i] = '?';
else
qbuf[i] = ' ';
}
qbuf[31] = '\0';
return qbuf;
}
//
// M_DrawGenericMenu
//
// Default, generic text-based list menu, used for Options
//
void M_DrawGenericMenu(void)
{
INT32 x = 0, y = 0, w, i, cursory = 0;
M_DrawMenuTooltips();
for (i = 0; i < currentMenu->numitems; i++)
{
if (i == itemOn)
cursory = y;
switch (currentMenu->menuitems[i].status & IT_DISPLAY)
{
case IT_PATCH:
if (currentMenu->menuitems[i].patch && currentMenu->menuitems[i].patch[0])
{
if (currentMenu->menuitems[i].status & IT_CENTER)
{
patch_t *p;
p = W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE);
V_DrawScaledPatch((BASEVIDWIDTH - SHORT(p->width))/2, y, 0, p);
}
else
{
V_DrawScaledPatch(x, y, 0,
W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE));
}
}
/* FALLTHRU */
case IT_NOTHING:
case IT_DYBIGSPACE:
y = currentMenu->y + currentMenu->menuitems[i].mvar1;//+= LINEHEIGHT;
break;
#if 0
case IT_BIGSLIDER:
M_DrawThermo(x, y, (consvar_t *)currentMenu->menuitems[i].itemaction);
y += LINEHEIGHT;
break;
#endif
case IT_STRING:
case IT_WHITESTRING:
if (currentMenu->menuitems[i].mvar1)
y = currentMenu->y+currentMenu->menuitems[i].mvar1;
if (i == itemOn)
cursory = y;
if ((currentMenu->menuitems[i].status & IT_DISPLAY)==IT_STRING)
V_DrawString(x, y, 0, currentMenu->menuitems[i].text);
else
V_DrawString(x, y, highlightflags, currentMenu->menuitems[i].text);
// Cvar specific handling
switch (currentMenu->menuitems[i].status & IT_TYPE)
case IT_CVAR:
{
consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction;
char asterisks[MAXSTRINGLENGTH+1];
size_t sl;
switch (currentMenu->menuitems[i].status & IT_CVARTYPE)
{
#if 0
case IT_CV_SLIDER:
M_DrawSlider(x, y, cv, (i == itemOn));
case IT_CV_NOPRINT: // color use this
case IT_CV_INVISSLIDER: // monitor toggles use this
break;
#endif
case IT_CV_PASSWORD:
if (i == itemOn)
{
V_DrawRightAlignedThinString(x + MAXSTRINGLENGTH*8 + 10, y, V_ALLOWLOWERCASE, va(M_GetText("Tab: %s password"), cv->value ? "hide" : "show"));
}
if (!cv->value || i != itemOn)
{
sl = strlen(cv->string);
memset(asterisks, '*', sl);
memset(asterisks + sl, 0, MAXSTRINGLENGTH+1-sl);
M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1);
V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, asterisks);
if (skullAnimCounter < 4 && i == itemOn)
V_DrawCharacter(x + 8 + V_StringWidth(asterisks, 0), y + 12,
'_' | 0x80, false);
y += 16;
break;
}
/* fallthru */
case IT_CV_STRING:
M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1);
V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, cv->string);
if (skullAnimCounter < 4 && i == itemOn)
V_DrawCharacter(x + 8 + V_StringWidth(cv->string, 0), y + 12,
'_' | 0x80, false);
y += 16;
break;
default:
w = V_StringWidth(cv->string, 0);
V_DrawString(BASEVIDWIDTH - x - w, y,
((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? warningflags : highlightflags), cv->string);
if (i == itemOn)
{
V_DrawCharacter(BASEVIDWIDTH - x - 10 - w - (skullAnimCounter/5), y,
'\x1C' | highlightflags, false); // left arrow
V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y,
'\x1D' | highlightflags, false); // right arrow
}
break;
}
break;
}
y += STRINGHEIGHT;
break;
case IT_STRING2:
V_DrawString(x, y, 0, currentMenu->menuitems[i].text);
/* FALLTHRU */
case IT_DYLITLSPACE:
y += SMALLLINEHEIGHT;
break;
case IT_GRAYPATCH:
if (currentMenu->menuitems[i].patch && currentMenu->menuitems[i].patch[0])
V_DrawMappedPatch(x, y, 0,
W_CachePatchName(currentMenu->menuitems[i].patch,PU_CACHE), graymap);
y += LINEHEIGHT;
break;
case IT_TRANSTEXT:
if (currentMenu->menuitems[i].mvar1)
y = currentMenu->y+currentMenu->menuitems[i].mvar1;
/* FALLTHRU */
case IT_TRANSTEXT2:
V_DrawString(x, y, V_TRANSLUCENT, currentMenu->menuitems[i].text);
y += SMALLLINEHEIGHT;
break;
case IT_QUESTIONMARKS:
if (currentMenu->menuitems[i].mvar1)
y = currentMenu->y+currentMenu->menuitems[i].mvar1;
V_DrawString(x, y, V_TRANSLUCENT|V_OLDSPACING, M_CreateSecretMenuOption(currentMenu->menuitems[i].text));
y += SMALLLINEHEIGHT;
break;
case IT_HEADERTEXT: // draws 16 pixels to the left, in yellow text
if (currentMenu->menuitems[i].mvar1)
y = currentMenu->y+currentMenu->menuitems[i].mvar1;
V_DrawString(x-16, y, highlightflags, currentMenu->menuitems[i].text);
y += SMALLLINEHEIGHT;
break;
}
}
// DRAW THE SKULL CURSOR
if (((currentMenu->menuitems[itemOn].status & IT_DISPLAY) == IT_PATCH)
|| ((currentMenu->menuitems[itemOn].status & IT_DISPLAY) == IT_NOTHING))
{
V_DrawScaledPatch(currentMenu->x + SKULLXOFF, cursory - 5, 0,
W_CachePatchName("M_CURSOR", PU_CACHE));
}
else
{
V_DrawScaledPatch(currentMenu->x - 24, cursory, 0,
W_CachePatchName("M_CURSOR", PU_CACHE));
V_DrawString(currentMenu->x, cursory, highlightflags, currentMenu->menuitems[itemOn].text);
}
}
//
// M_DrawKartGamemodeMenu
//
// Huge gamemode-selection list for main menu
//
void M_DrawKartGamemodeMenu(void)
{
INT16 i, x = 170;
M_DrawMenuTooltips();
M_DrawMenuPreviews();
if (menutransition.tics)
x -= 24 * menutransition.tics;
for (i = 0; i < currentMenu->numitems; i++)
{
switch (currentMenu->menuitems[i].status & IT_DISPLAY)
{
case IT_STRING:
V_DrawRightAlignedGamemodeString(x, currentMenu->menuitems[i].mvar1, 0, currentMenu->menuitems[i].text,
(i == itemOn) ? SKINCOLOR_PLAGUE : SKINCOLOR_PIGEON);
break;
}
}
}
#define MAXMSGLINELEN 256
//
// Draw a textbox, like Quake does, because sometimes it's difficult
// to read the text with all the stuff in the background...
//
void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines)
{
// Solid color textbox.
V_DrawFill(x+5, y+5, width*8+6, boxlines*8+6, 159);
//V_DrawFill(x+8, y+8, width*8, boxlines*8, 31);
}
//
// M_DrawMessageMenu
//
// Generic message prompt
//
void M_DrawMessageMenu(void)
{
INT32 y = currentMenu->y;
size_t i, start = 0;
INT16 max;
char string[MAXMSGLINELEN];
INT32 mlines;
const char *msg = currentMenu->menuitems[0].text;
mlines = currentMenu->lastOn>>8;
max = (INT16)((UINT8)(currentMenu->lastOn & 0xFF)*8);
M_DrawTextBox(currentMenu->x, y - 8, (max+7)>>3, mlines);
while (*(msg+start))
{
size_t len = strlen(msg+start);
for (i = 0; i < len; i++)
{
if (*(msg+start+i) == '\n')
{
memset(string, 0, MAXMSGLINELEN);
if (i >= MAXMSGLINELEN)
{
CONS_Printf("M_DrawMessageMenu: too long segment in %s\n", msg);
return;
}
else
{
strncpy(string,msg+start, i);
string[i] = '\0';
start += i;
i = (size_t)-1; //added : 07-02-98 : damned!
start++;
}
break;
}
}
if (i == strlen(msg+start))
{
if (i >= MAXMSGLINELEN)
{
CONS_Printf("M_DrawMessageMenu: too long segment in %s\n", msg);
return;
}
else
{
strcpy(string, msg + start);
start += i;
}
}
V_DrawString((BASEVIDWIDTH - V_StringWidth(string, 0))/2,y,V_ALLOWLOWERCASE,string);
y += 8; //SHORT(hu_font[0]->height);
}
}
// Draw an Image Def. Aka, Help images.
// Defines what image is used in (menuitem_t)->patch.
// You can even put multiple images in one menu!
void M_DrawImageDef(void)
{
// Grr. Need to autodetect for pic_ts.
pic_t *pictest = (pic_t *)W_CachePatchName(currentMenu->menuitems[itemOn].patch, PU_CACHE);
if (!pictest->zero)
V_DrawScaledPic(0,0,0,W_GetNumForName(currentMenu->menuitems[itemOn].patch));
else
{
patch_t *patch = W_CachePatchName(currentMenu->menuitems[itemOn].patch, PU_CACHE);
if (patch->height <= BASEVIDHEIGHT)
V_DrawScaledPatch(0,0,0,patch);
else
V_DrawSmallScaledPatch(0,0,0,patch);
}
if (currentMenu->menuitems[itemOn].mvar1)
{
V_DrawString(2,BASEVIDHEIGHT-10, V_YELLOWMAP, va("%d", (itemOn<<1)-1)); // intentionally not highlightflags, unlike below
V_DrawRightAlignedString(BASEVIDWIDTH-2,BASEVIDHEIGHT-10, V_YELLOWMAP, va("%d", itemOn<<1)); // ditto
}
else
{
INT32 x = BASEVIDWIDTH>>1, y = (BASEVIDHEIGHT>>1) - 4;
x += (itemOn ? 1 : -1)*((BASEVIDWIDTH>>2) + 10);
V_DrawCenteredString(x, y-10, highlightflags, "USE ARROW KEYS");
V_DrawCharacter(x - 10 - (skullAnimCounter/5), y,
'\x1C' | highlightflags, false); // left arrow
V_DrawCharacter(x + 2 + (skullAnimCounter/5), y,
'\x1D' | highlightflags, false); // right arrow
V_DrawCenteredString(x, y+10, highlightflags, "TO LEAF THROUGH");
}
}
//
// PLAY MENUS
//
static void M_DrawCharSelectCircle(setup_player_t *p, INT16 x, INT16 y)
{
const fixed_t rad = 32<<FRACBITS;
fixed_t angamt = 360;
patch_t *patch = NULL;
UINT8 numoptions;
UINT8 i;
if (p->mdepth == 2)
numoptions = setup_chargrid[p->gridx][p->gridy].numskins;
else
{
numoptions = 16;
patch = W_CachePatchName("COLORSPH", PU_CACHE);
}
angamt /= numoptions*2;
for (i = 0; i < numoptions; i++)
{
fixed_t cx = x << FRACBITS, cy = y << FRACBITS;
fixed_t ang = -(angamt * i);
UINT8 *colormap;
INT16 n;
ang += 90;
cx += FixedMul(rad, FINECOSINE(FixedAngle(ang << FRACBITS) >> ANGLETOFINESHIFT));
cy += FixedMul(rad, FINESINE(FixedAngle(ang << FRACBITS) >> ANGLETOFINESHIFT)) >> 2;
if (p->mdepth == 2)
{
SINT8 skin;
cx -= 8<<FRACBITS;
n = (p->clonenum + i) % setup_chargrid[p->gridx][p->gridy].numskins;
skin = setup_chargrid[p->gridx][p->gridy].skinlist[n];
colormap = R_GetTranslationColormap(skin, skins[skin].prefcolor, GTC_MENUCACHE);
patch = facerankprefix[skin];
}
else
{
cx -= 4<<FRACBITS;
n = ((p->color + i) % (MAXSKINCOLORS-1));
colormap = R_GetTranslationColormap(TC_DEFAULT, n, GTC_MENUCACHE);
}
V_DrawFixedPatch(cx, cy, FRACUNIT, 0, patch, colormap);
}
}
static void M_DrawCharSelectPreview(UINT8 num)
{
INT16 x = 11, y = 5;
char letter = 'A' + num;
SINT8 skin;
UINT8 color;
UINT8 *colormap;
patch_t *sprpatch;
spritedef_t *sprdef;
spriteframe_t *sprframe;
setup_player_t *p = &setup_player[num];
if (num & 1)
x += 233;
if (num > 1)
y += 99;
V_DrawScaledPatch(x, y+6, V_TRANSLUCENT, W_CachePatchName("PREVBACK", PU_CACHE));
if (p->mdepth > 0)
{
skin = setup_chargrid[p->gridx][p->gridy].skinlist[p->clonenum];
color = p->color;
colormap = R_GetTranslationColormap(skin, color, GTC_MENUCACHE);
if (skin != -1)
{
statenum_t st = S_KART_WALK1;
UINT32 flags = 0;
UINT32 frame;
if (skullAnimCounter & 1)
st++;
sprdef = &skins[skin].spritedef;
if (sprdef->numframes) // No frames ??
{
frame = states[st].frame & FF_FRAMEMASK;
if (frame >= sprdef->numframes) // Walking animation missing
frame = 0; // Try to use standing frame
sprframe = &sprdef->spriteframes[frame];
sprpatch = W_CachePatchNum(sprframe->lumppat[1], PU_CACHE);
if (sprframe->flip & 1) // Only for first sprite
flags |= V_FLIP; // This sprite is left/right flipped!
// Flip for left-side players
if (!(num & 1))
flags ^= V_FLIP;
if (skins[skin].flags & SF_HIRES)
{
V_DrawFixedPatch((x+32)<<FRACBITS,
(y+75)<<FRACBITS,
skins[skin].highresscale,
flags, sprpatch, colormap);
}
else
V_DrawMappedPatch(x+32, y+75, flags, sprpatch, colormap);
}
}
if (p->mdepth == 2 || p->mdepth == 3)
M_DrawCharSelectCircle(p, x+32, y+48);
}
V_DrawScaledPatch(x+9, y+2, 0, W_CachePatchName("FILEBACK", PU_CACHE));
V_DrawScaledPatch(x, y, 0, W_CachePatchName(va("CHARSEL%c", letter), PU_CACHE));
if (p->mdepth == 0 && (skullAnimCounter/5))
V_DrawScaledPatch(x+1, y+36, 0, W_CachePatchName("4PSTART", PU_CACHE));
}
void M_DrawCharacterSelect(void)
{
UINT8 i, j, k;
UINT16 quadx, quady;
SINT8 skin;
// We have to loop twice -- first time to draw the drop shadows, a second time to draw the icons.
for (i = 0; i < 9; i++)
{
for (j = 0; j < 9; j++)
{
skin = setup_chargrid[i][j].skinlist[0];
quadx = 4 * (i / 3);
quady = 4 * (j / 3);
// Here's a quick little cheat to save on drawing time!
// Don't draw a shadow if it'll get covered by another icon
if ((i % 3 < 2) && (j % 3 < 2))
{
if ((setup_chargrid[i+1][j].skinlist[0] != -1)
&& (setup_chargrid[i][j+1].skinlist[0] != -1)
&& (setup_chargrid[i+1][j+1].skinlist[0] != -1))
continue;
}
if (skin != -1)
V_DrawScaledPatch(82 + (i*16) + quadx + 1, 22 + (j*16) + quady + 1, 0, W_CachePatchName("ICONBACK", PU_CACHE));
}
}
// Draw this inbetween. These drop shadows should be covered by the stat graph, but the icons shouldn't.
V_DrawScaledPatch(3, 2, 0, W_CachePatchName("STATGRPH", PU_CACHE));
// Draw the icons now
for (i = 0; i < 9; i++)
{
for (j = 0; j < 9; j++)
{
for (k = 0; k < setup_numplayers; k++)
{
if (setup_player[k].gridx == i && setup_player[k].gridy == j)
break; // k == setup_numplayers means no one has it selected
}
skin = setup_chargrid[i][j].skinlist[0];
quadx = 4 * (i / 3);
quady = 4 * (j / 3);
if (skin != -1)
{
UINT8 *colormap;
if (k == setup_numplayers)
colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_GREY, GTC_MENUCACHE);
else
colormap = R_GetTranslationColormap(skin, skins[skin].prefcolor, GTC_MENUCACHE);
V_DrawMappedPatch(82 + (i*16) + quadx, 22 + (j*16) + quady, 0, facerankprefix[skin], colormap);
}
}
}
// Draw a preview for each player
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
M_DrawCharSelectPreview(i);
}
//
// INGAME / PAUSE MENUS
//
void M_DrawPlaybackMenu(void)
{
INT16 i;
patch_t *icon = NULL;
UINT8 *activemap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_GOLD, GTC_MENUCACHE);
// Toggle items
if (paused && !demo.rewinding)
{
PAUSE_PlaybackMenu[playback_pause].status = PAUSE_PlaybackMenu[playback_fastforward].status = PAUSE_PlaybackMenu[playback_rewind].status = IT_DISABLED;
PAUSE_PlaybackMenu[playback_resume].status = PAUSE_PlaybackMenu[playback_advanceframe].status = PAUSE_PlaybackMenu[playback_backframe].status = IT_CALL|IT_STRING;
if (itemOn >= playback_rewind && itemOn <= playback_fastforward)
itemOn += playback_backframe - playback_rewind;
}
else
{
PAUSE_PlaybackMenu[playback_pause].status = PAUSE_PlaybackMenu[playback_fastforward].status = PAUSE_PlaybackMenu[playback_rewind].status = IT_CALL|IT_STRING;
PAUSE_PlaybackMenu[playback_resume].status = PAUSE_PlaybackMenu[playback_advanceframe].status = PAUSE_PlaybackMenu[playback_backframe].status = IT_DISABLED;
if (itemOn >= playback_backframe && itemOn <= playback_advanceframe)
itemOn -= playback_backframe - playback_rewind;
}
if (modeattacking)
{
for (i = playback_viewcount; i <= playback_view4; i++)
PAUSE_PlaybackMenu[i].status = IT_DISABLED;
//PAUSE_PlaybackMenu[playback_moreoptions].mvar1 = 72;
//PAUSE_PlaybackMenu[playback_quit].mvar1 = 88;
PAUSE_PlaybackMenu[playback_quit].mvar1 = 72;
//currentMenu->x = BASEVIDWIDTH/2 - 52;
currentMenu->x = BASEVIDWIDTH/2 - 44;
}
else
{
PAUSE_PlaybackMenu[playback_viewcount].status = IT_ARROWS|IT_STRING;
for (i = 0; i <= splitscreen; i++)
PAUSE_PlaybackMenu[playback_view1+i].status = IT_ARROWS|IT_STRING;
for (i = splitscreen+1; i < 4; i++)
PAUSE_PlaybackMenu[playback_view1+i].status = IT_DISABLED;
//PAUSE_PlaybackMenu[playback_moreoptions].mvar1 = 156;
//PAUSE_PlaybackMenu[playback_quit].mvar1 = 172;
PAUSE_PlaybackMenu[playback_quit].mvar1 = 156;
//currentMenu->x = BASEVIDWIDTH/2 - 94;
currentMenu->x = BASEVIDWIDTH/2 - 88;
}
// wip
//M_DrawTextBox(currentMenu->x-68, currentMenu->y-7, 15, 15);
//M_DrawCenteredMenu();
for (i = 0; i < currentMenu->numitems; i++)
{
UINT8 *inactivemap = NULL;
if (i >= playback_view1 && i <= playback_view4)
{
if (modeattacking) continue;
if (splitscreen >= i - playback_view1)
{
INT32 ply = displayplayers[i - playback_view1];
icon = facerankprefix[players[ply].skin];
if (i != itemOn)
inactivemap = R_GetTranslationColormap(players[ply].skin, players[ply].skincolor, GTC_MENUCACHE);
}
else if (currentMenu->menuitems[i].patch && W_CheckNumForName(currentMenu->menuitems[i].patch) != LUMPERROR)
icon = W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE);
}
else if (currentMenu->menuitems[i].status == IT_DISABLED)
continue;
else if (currentMenu->menuitems[i].patch && W_CheckNumForName(currentMenu->menuitems[i].patch) != LUMPERROR)
icon = W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE);
if ((i == playback_fastforward && cv_playbackspeed.value > 1) || (i == playback_rewind && demo.rewinding))
V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].mvar1, currentMenu->y, V_SNAPTOTOP, icon, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_JAWZ, GTC_MENUCACHE));
else
V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].mvar1, currentMenu->y, V_SNAPTOTOP, icon, (i == itemOn) ? activemap : inactivemap);
if (i == itemOn)
{
V_DrawCharacter(currentMenu->x + currentMenu->menuitems[i].mvar1 + 4, currentMenu->y + 14,
'\x1A' | V_SNAPTOTOP|highlightflags, false);
V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y + 18, V_SNAPTOTOP|V_ALLOWLOWERCASE, currentMenu->menuitems[i].text);
if ((currentMenu->menuitems[i].status & IT_TYPE) == IT_ARROWS)
{
char *str;
if (!(i == playback_viewcount && splitscreen == 3))
V_DrawCharacter(BASEVIDWIDTH/2 - 4, currentMenu->y + 28 - (skullAnimCounter/5),
'\x1A' | V_SNAPTOTOP|highlightflags, false); // up arrow
if (!(i == playback_viewcount && splitscreen == 0))
V_DrawCharacter(BASEVIDWIDTH/2 - 4, currentMenu->y + 48 + (skullAnimCounter/5),
'\x1B' | V_SNAPTOTOP|highlightflags, false); // down arrow
switch (i)
{
case playback_viewcount:
str = va("%d", splitscreen+1);
break;
case playback_view1:
case playback_view2:
case playback_view3:
case playback_view4:
str = player_names[displayplayers[i - playback_view1]]; // 0 to 3
break;
default: // shouldn't ever be reached but whatever
continue;
}
V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y + 38, V_SNAPTOTOP|V_ALLOWLOWERCASE|highlightflags, str);
}
}
}
}

2021
src/k_menufunc.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -22,7 +22,7 @@
#include "d_net.h"
#include "m_cheat.h"
#include "m_menu.h"
#include "k_menu.h"
#include "m_random.h"
#include "m_misc.h"

File diff suppressed because it is too large Load diff

View file

@ -42,7 +42,7 @@
#include "m_anigif.h"
// So that the screenshot menu auto-updates...
#include "m_menu.h"
#include "k_menu.h"
#ifdef HWRENDER
#include "hardware/hw_main.h"

View file

@ -87,7 +87,7 @@
#include "i_tcp.h"
#include "i_system.h"
#include "byteptr.h"
#include "m_menu.h"
#include "k_menu.h"
#include "m_argv.h" // Alam is going to kill me <3
#include "m_misc.h" // GetRevisionString()

View file

@ -2598,7 +2598,7 @@ static void P_ForceCharacter(const char *forcecharskin)
static void P_LoadRecordGhosts(void)
{
// see also m_menu.c's Nextmap_OnChange
// see also k_menu.c's Nextmap_OnChange
const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1;
char *gpath = malloc(glen);
INT32 i;

View file

@ -23,7 +23,7 @@
#include "p_local.h"
#include "keys.h"
#include "i_video.h"
#include "m_menu.h"
#include "k_menu.h"
#include "am_map.h"
#include "d_main.h"
#include "v_video.h"

View file

@ -61,7 +61,7 @@
#include "../i_system.h"
#include "../v_video.h"
#include "../m_argv.h"
#include "../m_menu.h"
#include "../k_menu.h"
#include "../d_main.h"
#include "../s_sound.h"
#include "../i_sound.h" // midi pause/unpause
@ -1081,9 +1081,11 @@ void I_GetEvent(void)
CONS_Debug(DBG_GAMELOGIC, "Joystick3 device index: %d\n", JoyInfo3.oldjoy);
CONS_Debug(DBG_GAMELOGIC, "Joystick4 device index: %d\n", JoyInfo4.oldjoy);
#if 0
// update the menu
if (currentMenu == &OP_JoystickSetDef)
M_SetupJoystickMenu(0);
#endif
if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy)
SDL_JoystickClose(newjoy);
@ -1242,9 +1244,11 @@ void I_GetEvent(void)
CONS_Debug(DBG_GAMELOGIC, "Joystick3 device index: %d\n", JoyInfo3.oldjoy);
CONS_Debug(DBG_GAMELOGIC, "Joystick4 device index: %d\n", JoyInfo4.oldjoy);
#if 0
// update the menu
if (currentMenu == &OP_JoystickSetDef)
M_SetupJoystickMenu(0);
#endif
break;
case SDL_QUIT:
I_Quit();

View file

@ -25,7 +25,7 @@
#include "hu_stuff.h"
#include "s_sound.h"
#include "i_system.h"
#include "m_menu.h"
#include "k_menu.h"
#include "m_cheat.h"
#include "p_setup.h" // NiGHTS grading
#include "k_kart.h" // SRB2kart
@ -2045,11 +2045,11 @@ static void ST_overlayDrawer(void)
void ST_DrawDemoTitleEntry(void)
{
static UINT8 skullAnimCounter = 0;
static UINT8 anim = 0;
char *nametodraw;
skullAnimCounter++;
skullAnimCounter %= 8;
anim++;
anim %= 8;
nametodraw = demo.titlename;
while (V_StringWidth(nametodraw, 0) > MAXSTRINGLENGTH*8 - 8)
@ -2059,7 +2059,7 @@ void ST_DrawDemoTitleEntry(void)
#define y (BASEVIDHEIGHT/2)
M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1);
V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, nametodraw);
if (skullAnimCounter < 4)
if (anim < 4)
V_DrawCharacter(x + 8 + V_StringWidth(nametodraw, 0), y + 12,
'_' | 0x80, false);

View file

@ -26,7 +26,7 @@
#include "w_wad.h"
#include "y_inter.h"
#include "z_zone.h"
#include "m_menu.h"
#include "k_menu.h"
#include "m_misc.h"
#include "i_system.h"
#include "p_setup.h"
@ -39,7 +39,6 @@
#include "m_random.h" // M_RandomKey
#include "g_input.h" // PLAYER1INPUTDOWN
#include "k_kart.h" // colortranslations
#include "console.h" // cons_menuhighlight
#include "lua_hook.h" // IntermissionThinker hook
#ifdef HWRENDER
@ -363,9 +362,7 @@ void Y_IntermissionDrawer(void)
if (!splitscreen)
whiteplayer = demo.playback ? displayplayers[0] : consoleplayer;
if (cons_menuhighlight.value)
hilicol = cons_menuhighlight.value;
else if (modeattacking)
if (modeattacking)
hilicol = V_ORANGEMAP;
else
hilicol = ((intertype == int_race) ? V_SKYMAP : V_REDMAP);
@ -1198,9 +1195,7 @@ void Y_VoteDrawer(void)
if (timer)
{
INT32 hilicol, tickdown = (timer+1)/TICRATE;
if (cons_menuhighlight.value)
hilicol = cons_menuhighlight.value;
else if (gametype == GT_RACE)
if (gametype == GT_RACE)
hilicol = V_SKYMAP;
else //if (gametype == GT_MATCH)
hilicol = V_REDMAP;