Merge branch 'menuforcustomcvars' into 'next'

Add menu for custom console variables

See merge request STJr/SRB2!2407
This commit is contained in:
Skydusk 2025-03-22 11:48:19 +00:00
commit 1a2cb022e2
5 changed files with 129 additions and 11 deletions

View file

@ -125,6 +125,7 @@ typedef enum
// used on menus
CV_CHEAT = 2048, // Don't let this be used in multiplayer unless cheats are on.
CV_ALLOWLUA = 4096,/* Let this be called from Lua */
CV_NOMENU = 8192, // Lua exclusive flag, to give choice to modders regarding custom options menu.
} cvflags_t;
typedef struct CV_PossibleValue_s

View file

@ -5642,6 +5642,7 @@ struct int_const_s const INT_CONST[] = {
{"CV_HIDDEN",CV_HIDEN},
{"CV_CHEAT",CV_CHEAT},
{"CV_ALLOWLUA",CV_ALLOWLUA},
{"CV_NOMENU",CV_NOMENU},
// v_video flags
{"V_NOSCALEPATCH",V_NOSCALEPATCH},

View file

@ -22,6 +22,11 @@
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
// Included for the custom options menu
#include "netcode/d_netfil.h"
#include "m_menu.h"
#include "w_wad.h"
// for functions not allowed in hud.add hooks
#define NOHUD if (hud_running)\
return luaL_error(L, "HUD rendering code should not call this function!");
@ -361,6 +366,9 @@ static int lib_cvRegisterVar(lua_State *L)
cvar = ZZ_Calloc(sizeof(consvar_t));
LUA_PushUserdata(L, cvar, META_CVAR);
const char* category = NULL;
const char* menu_name = NULL;
#define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to " LUA_QL("CV_RegisterVar") " (%s)", e);
#define TYPEERROR(f, t) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t), luaL_typename(L, -1)))
@ -408,7 +416,7 @@ static int lib_cvRegisterVar(lua_State *L)
{
if (lua_islightuserdata(L, 4))
{
CV_PossibleValue_t *pv = lua_touserdata(L, 4);
CV_PossibleValue_t* pv = lua_touserdata(L, 4);
if (pv == CV_OnOff || pv == CV_YesNo || pv == CV_Unsigned || pv == CV_Natural || pv == CV_TrueFalse)
cvar->PossibleValue = pv;
else
@ -423,9 +431,9 @@ static int lib_cvRegisterVar(lua_State *L)
// being used for multiple cvars will be converted and stored multiple times.
// So maybe instead it should be a seperate function which must be run beforehand or something.
size_t count = 0;
CV_PossibleValue_t *cvpv;
CV_PossibleValue_t* cvpv;
const char * const MINMAX[2] = {"MIN", "MAX"};
const char* const MINMAX[2] = { "MIN", "MAX" };
int minmax_unset = 3;
lua_pushnil(L);
@ -438,7 +446,7 @@ static int lib_cvRegisterVar(lua_State *L)
lua_getfield(L, LUA_REGISTRYINDEX, "CV_PossibleValue");
I_Assert(lua_istable(L, 5));
lua_pushlightuserdata(L, cvar);
cvpv = lua_newuserdata(L, sizeof(CV_PossibleValue_t) * (count+1));
cvpv = lua_newuserdata(L, sizeof(CV_PossibleValue_t) * (count + 1));
lua_rawset(L, 5);
lua_pop(L, 1); // pop CV_PossibleValue registry table
@ -447,25 +455,25 @@ static int lib_cvRegisterVar(lua_State *L)
while (lua_next(L, 4))
{
INT32 n;
const char * strval;
const char* strval;
// stack: [...] PossibleValue table, index, value
// 4 5 6
if (lua_type(L, 5) != LUA_TSTRING
|| lua_type(L, 6) != LUA_TNUMBER)
|| lua_type(L, 6) != LUA_TNUMBER)
FIELDERROR("PossibleValue", "custom PossibleValue table requires a format of string=integer, i.e. {MIN=0, MAX=9999}");
strval = lua_tostring(L, 5);
if (
stricmp(strval, MINMAX[n=0]) == 0 ||
stricmp(strval, MINMAX[n=1]) == 0
){
stricmp(strval, MINMAX[n = 0]) == 0 ||
stricmp(strval, MINMAX[n = 1]) == 0
) {
/* need to shift forward */
if (minmax_unset == 3)
{
memmove(&cvpv[2], &cvpv[0],
i * sizeof *cvpv);
i * sizeof * cvpv);
i += 2;
}
cvpv[n].strvalue = MINMAX[n];
@ -508,7 +516,7 @@ static int lib_cvRegisterVar(lua_State *L)
lua_pop(L, 1);
cvar->func = Lua_OnChange;
}
else if (cvar->flags & CV_CALL && (k && fasticmp(k, "can_change")))
else if (cvar->flags & CV_CALL && (i == 6 || (k && fasticmp(k, "can_change"))))
{
if (!lua_isfunction(L, 4))
{
@ -522,6 +530,19 @@ static int lib_cvRegisterVar(lua_State *L)
lua_pop(L, 1);
cvar->can_change = Lua_CanChange;
}
else if (((i == 5 && !(cvar->flags & CV_CALL))
|| (cvar->flags & CV_CALL && i == 7))
|| (k && fasticmp(k, "category")))
{
category = lua_isnoneornil(L, 4) ? NULL : lua_tostring(L, 4);
}
else if (((i == 6 && !(cvar->flags & CV_CALL))
|| (cvar->flags & CV_CALL && i == 8))
|| (k && fasticmp(k, "displayname")))
{
menu_name = lua_isnoneornil(L, 4) ? NULL : lua_tostring(L, 4);
}
lua_pop(L, 1);
}
@ -558,6 +579,24 @@ static int lib_cvRegisterVar(lua_State *L)
return luaL_error(L, "failed to register cvar (probable conflict with internal variable/command names)");
}
if (!((cvar->flags & CV_NOMENU)
|| (cvar->flags & CV_HIDEN))
|| (cvar->flags & CV_NOSHOWHELP))
{
if (!category)
{
char* temp = wadfiles[numwadfiles - 1]->filename;
temp += strlen(temp) - nameonlylength(temp);
category = temp;
}
if (menu_name && menu_name[0] != '\0')
M_FreeslotIntoCustomMenu(cvar, category, menu_name);
else
M_FreeslotIntoCustomMenu(cvar, category, cvar->name);
}
// return cvar userdata
return 1;
}

View file

@ -48,6 +48,7 @@
#include "p_setup.h"
#include "f_finale.h"
#include "lua_hook.h"
#include "lua_libs.h"
#ifdef HWRENDER
#include "hardware/hw_main.h"
@ -316,6 +317,7 @@ menu_t OP_P1ControlsDef, OP_P2ControlsDef, OP_MouseOptionsDef;
menu_t OP_Mouse2OptionsDef, OP_Joystick1Def, OP_Joystick2Def;
menu_t OP_CameraOptionsDef, OP_Camera2OptionsDef;
menu_t OP_PlaystyleDef;
menu_t OP_AddonCustomOptionsDef;
static void M_VideoModeMenu(INT32 choice);
static void M_Setup1PControlsMenu(INT32 choice);
static void M_Setup2PControlsMenu(INT32 choice);
@ -349,6 +351,7 @@ static void M_EraseData(INT32 choice);
static void M_Addons(INT32 choice);
static void M_AddonsOptions(INT32 choice);
static void M_AddonsCvarOptions(INT32 choice);
static patch_t *addonsp[NUM_EXT+5];
#define addonmenusize 9 // number of items actually displayed in the addons menu view, formerly (2*numaddonsshown + 1)
@ -1037,6 +1040,7 @@ static menuitem_t OP_MainMenu[] =
{IT_CALL | IT_STRING, NULL, "Server Options...", M_ServerOptions, 80},
{IT_SUBMENU | IT_STRING, NULL, "Data Options...", &OP_DataOptionsDef, 100},
{IT_CALL | IT_STRING, NULL, "Custom Options...", M_AddonsCvarOptions,110},
};
static menuitem_t OP_P1ControlsMenu[] =
@ -1643,6 +1647,9 @@ static menuitem_t OP_MonitorToggleMenu[] =
{IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Eggman Box", &cv_eggmanbox, 140},
};
#define MAXADDONOPTIONS 999
menuitem_t OP_AddonOptionsSlots[MAXADDONOPTIONS];
// ==========================================================================
// ALL MENU DEFINITIONS GO HERE
// ==========================================================================
@ -2219,6 +2226,23 @@ menu_t OP_ScreenshotOptionsDef =
NULL
};
INT16 addoncvarpos = 0;
static void M_AddonsCvarOptions(INT32 choice)
{
(void)choice;
if (addoncvarpos)
M_SetupNextMenu(&OP_AddonCustomOptionsDef);
else
M_StartMessage(M_GetText("No Custom Option was found.\nTry to load any Addon!\n(Press a key)\n"), NULL, MM_NOTHING);
}
menu_t OP_AddonCustomOptionsDef = DEFAULTSCROLLMENUSTYLE(
MTREE3(MN_OP_MAIN, MN_OP_DATA, MN_OP_ADDONS),
"M_ADDONS", OP_AddonOptionsSlots, &OP_MainDef, 30, 30);
menu_t OP_AddonsOptionsDef = DEFAULTMENUSTYLE(
MTREE3(MN_OP_MAIN, MN_OP_DATA, MN_OP_ADDONS),
"M_ADDONS", OP_AddonsOptionsMenu, &OP_DataOptionsDef, 30, 30);
@ -6940,6 +6964,58 @@ static void M_SelectableClearMenus(INT32 choice)
M_ClearMenus(true);
}
#define CCVHEIGHT 5
#define CCVHEIGHTHEADER 1
#define CCVHEIGHTHEADERAFTER 6
UINT16 addonvaralphakey = 4;
INT16 addonlastheaderpos = 0;
INT32 CVARSETUP;
void M_FreeslotIntoCustomMenu(consvar_t* cvar, const char* category, const char* name)
{
if (addoncvarpos == INT16_MAX)
return;
if (addoncvarpos >= MAXADDONOPTIONS - 2)
{
CONS_Printf("Failed to register the console variable '%s' into the menu. Custom Options menu most likely reached the hard limit.\n", name);
addoncvarpos = INT16_MAX;
return;
}
if (!CVARSETUP)
{
CONS_Printf("Custom Options menu initiation.\n");
for (CVARSETUP = 0; CVARSETUP < MAXADDONOPTIONS; ++CVARSETUP)
OP_AddonOptionsSlots[CVARSETUP] = (menuitem_t){ IT_DISABLED, NULL, "", 0, INT16_MAX };
}
if (category && ((addoncvarpos == 0 && category[0] != '\0') || !fasticmp(category, OP_AddonOptionsSlots[addonlastheaderpos].text)))
{
addonlastheaderpos = addoncvarpos;
addonvaralphakey += CCVHEIGHTHEADER;
OP_AddonOptionsSlots[addoncvarpos] = (menuitem_t){ IT_HEADER, NULL, Z_StrDup(category), NULL, addonvaralphakey };
addonvaralphakey += CCVHEIGHTHEADERAFTER;
++addoncvarpos;
}
if (cvar->PossibleValue && fasticmp(cvar->PossibleValue[0].strvalue, "MIN"))
OP_AddonOptionsSlots[addoncvarpos] = (menuitem_t){ IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, Z_StrDup(name), cvar, addonvaralphakey };
else if (cvar->flags & CV_FLOAT)
OP_AddonOptionsSlots[addoncvarpos] = (menuitem_t){ IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, Z_StrDup(name), cvar, addonvaralphakey };
else
OP_AddonOptionsSlots[addoncvarpos] = (menuitem_t){ IT_STRING | IT_CVAR, NULL, Z_StrDup(name), cvar, addonvaralphakey };
addonvaralphakey += CCVHEIGHT;
++addoncvarpos;
}
// ======
// CHEATS
// ======

View file

@ -486,6 +486,7 @@ UINT16 M_GetColorIndex(UINT16 color);
menucolor_t* M_GetColorFromIndex(UINT16 index);
void M_InitPlayerSetupColors(void);
void M_FreePlayerSetupColors(void);
void M_FreeslotIntoCustomMenu(consvar_t* cvar, const char* category, const char* name);
// These defines make it a little easier to make menus
#define DEFAULTMENUSTYLE(id, header, source, prev, x, y)\