Addons menu refactor part 3

Search finally works again!
- Now uses a cvar which is copied into static memory to uppercase it, instead of a weird static string uppercased into zone memory.
- You have to scroll to the top of the menu to use it, one entry above the previous first file/folder/"UP...".
- Don't play menu sound if you've reached the end of an un-looping menu.
This commit is contained in:
toaster 2022-09-03 21:15:23 +01:00
parent 88f04da180
commit 26461d568c
5 changed files with 83 additions and 74 deletions

View file

@ -561,15 +561,15 @@ char exttable[NUM_EXT_TABLE][7] = { // maximum extension length (currently 4) pl
char filenamebuf[MAX_WADFILES][MAX_WADPATH]; char filenamebuf[MAX_WADFILES][MAX_WADPATH];
static boolean filemenucmp(char *haystack, char *needle) static boolean filemenucmp(char *haystack)
{ {
static char localhaystack[128]; static char localhaystack[128];
strlcpy(localhaystack, haystack, 128); strlcpy(localhaystack, haystack, 128);
if (!cv_addons_search_case.value) if (!cv_addons_search_case.value)
strupr(localhaystack); strupr(localhaystack);
if (cv_addons_search_type.value) if (cv_addons_search_type.value)
return (strstr(localhaystack, needle) != 0); return (strstr(localhaystack, menusearch+1) != 0);
return (!strncmp(localhaystack, needle, menusearch[0])); return (!strncmp(localhaystack, menusearch+1, menusearch[0]));
} }
void closefilemenu(boolean validsize) void closefilemenu(boolean validsize)
@ -616,7 +616,6 @@ void closefilemenu(boolean validsize)
void searchfilemenu(char *tempname) void searchfilemenu(char *tempname)
{ {
size_t i, first; size_t i, first;
char localmenusearch[MAXSTRINGLENGTH] = "";
if (dirmenu) if (dirmenu)
{ {
@ -662,14 +661,10 @@ void searchfilemenu(char *tempname)
return; return;
} }
strcpy(localmenusearch, menusearch+1);
if (!cv_addons_search_case.value)
strupr(localmenusearch);
sizedirmenu = 0; sizedirmenu = 0;
for (i = first; i < sizecoredirmenu; i++) for (i = first; i < sizecoredirmenu; i++)
{ {
if (filemenucmp(coredirmenu[i]+DIR_STRING, localmenusearch)) if (filemenucmp(coredirmenu[i]+DIR_STRING))
sizedirmenu++; sizedirmenu++;
} }
@ -691,7 +686,7 @@ void searchfilemenu(char *tempname)
sizedirmenu = 0; sizedirmenu = 0;
for (i = first; i < sizecoredirmenu; i++) for (i = first; i < sizecoredirmenu; i++)
{ {
if (filemenucmp(coredirmenu[i]+DIR_STRING, localmenusearch)) if (filemenucmp(coredirmenu[i]+DIR_STRING))
{ {
if (tempname && !strcmp(coredirmenu[i]+DIR_STRING, tempname)) if (tempname && !strcmp(coredirmenu[i]+DIR_STRING, tempname))
{ {
@ -724,7 +719,10 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut)
tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL
} }
else else
{
menusearch[0] = menusearch[1] = 0; // clear search menusearch[0] = menusearch[1] = 0; // clear search
CV_StealthSet(&cv_dummyaddonsearch, "");
}
if (!(dirhandle = opendir(menupath))) // get directory if (!(dirhandle = opendir(menupath))) // get directory
{ {

View file

@ -966,6 +966,7 @@ void M_Addons(INT32 choice);
void M_AddonsRefresh(void); void M_AddonsRefresh(void);
void M_HandleAddons(INT32 choice); void M_HandleAddons(INT32 choice);
char *M_AddonsHeaderPath(void); char *M_AddonsHeaderPath(void);
extern consvar_t cv_dummyaddonsearch;
void M_Manual(INT32 choice); void M_Manual(INT32 choice);
void M_HandleImageDef(INT32 choice); void M_HandleImageDef(INT32 choice);

View file

@ -1726,9 +1726,11 @@ menuitem_t MISC_Manual[] = {
menu_t MISC_ManualDef = IMAGEDEF(MISC_Manual); menu_t MISC_ManualDef = IMAGEDEF(MISC_Manual);
// Addons menu! (Just a straight port for now) // Addons menu!
menuitem_t MISC_AddonsMenu[] = menuitem_t MISC_AddonsMenu[] =
{ {
{IT_STRING | IT_CVAR | IT_CV_STRING, NULL, NULL,
NULL, {.cvar = &cv_dummyaddonsearch}, 0, 0},
{IT_KEYHANDLER | IT_NOTHING, NULL, NULL, {IT_KEYHANDLER | IT_NOTHING, NULL, NULL,
NULL, {.routine = M_HandleAddons}, 0, 0}, // dummy menuitem for the control func NULL, {.routine = M_HandleAddons}, 0, 0}, // dummy menuitem for the control func
}; };

View file

@ -4191,7 +4191,7 @@ void M_DrawReplayStartMenu(void)
// Draw misc menus: // Draw misc menus:
// Addons (this is merely copypasted, original code by toaster) // Addons
#define lsheadingheight 16 #define lsheadingheight 16
@ -4318,16 +4318,23 @@ void M_DrawAddons(void)
y += 10; y += 10;
M_DrawTextBox(x - (21 + 5), y, MAXSTRINGLENGTH, 1); M_DrawTextBox(x - (21 + 5), y, MAXSTRINGLENGTH, 1);
if (menusearch[0]) {
V_DrawString(x - 18, y+8, V_ALLOWLOWERCASE, menusearch+1); const char *str = (menusearch[0] ? cv_dummyaddonsearch.string : "Search...");
else INT32 tflag = (menusearch[0] ? 0 : V_TRANSLUCENT);
V_DrawString(x - 18, y+8, V_ALLOWLOWERCASE|V_TRANSLUCENT, "Type to search..."); INT32 xoffs = 0;
if (itemOn == 0)
{
xoffs += 8;
V_DrawString(x + (skullAnimCounter/5) - 20, y+8, highlightflags, "\x1D");
}
V_DrawString(x + xoffs - 18, y+8, V_ALLOWLOWERCASE|tflag, str);
}
V_DrawSmallScaledPatch(x - (21 + 5 + 16), y+4, (menusearch[0] ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+3]); V_DrawSmallScaledPatch(x - (21 + 5 + 16), y+4, (menusearch[0] ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+3]);
y += 21; y += 21;
m = (addonsseperation*(2*numaddonsshown + 1)) + 2*(16-addonsseperation); m = (addonsseperation*(2*numaddonsshown + 1)) + 1 + 2*(16-addonsseperation);
V_DrawFill(x - 21, y - 1, MAXSTRINGLENGTH*8+6, m, 159); V_DrawFill(x - 21, y - 1, MAXSTRINGLENGTH*8+6, m, 159);
// scrollbar! // scrollbar!
@ -4385,7 +4392,7 @@ void M_DrawAddons(void)
else else
V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[(type & ~EXT_LOADED)]); V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[(type & ~EXT_LOADED)]);
if ((size_t)i == dir_on[menudepthleft]) if (itemOn == 1 && (size_t)i == dir_on[menudepthleft])
{ {
V_DrawFixedPatch((x-(16+4))<<FRACBITS, (y)<<FRACBITS, FRACUNIT/2, 0, addonsp[NUM_EXT+1], flashcol); V_DrawFixedPatch((x-(16+4))<<FRACBITS, (y)<<FRACBITS, FRACUNIT/2, 0, addonsp[NUM_EXT+1], flashcol);
flags = V_ALLOWLOWERCASE|highlightflags; flags = V_ALLOWLOWERCASE|highlightflags;

View file

@ -208,6 +208,9 @@ consvar_t cv_dummygpdifficulty = CVAR_INIT ("dummygpdifficulty", "Normal", CV_HI
consvar_t cv_dummykartspeed = CVAR_INIT ("dummykartspeed", "Auto", CV_HIDDEN, dummykartspeed_cons_t, NULL); consvar_t cv_dummykartspeed = CVAR_INIT ("dummykartspeed", "Auto", CV_HIDDEN, dummykartspeed_cons_t, NULL);
consvar_t cv_dummygpencore = CVAR_INIT ("dummygpencore", "No", CV_HIDDEN, CV_YesNo, NULL); consvar_t cv_dummygpencore = CVAR_INIT ("dummygpencore", "No", CV_HIDDEN, CV_YesNo, NULL);
static void M_UpdateAddonsSearch(void);
consvar_t cv_dummyaddonsearch = CVAR_INIT ("dummyaddonsearch", "", CV_HIDDEN|CV_CALL|CV_NOINIT, NULL, M_UpdateAddonsSearch);
static CV_PossibleValue_t dummymatchbots_cons_t[] = { static CV_PossibleValue_t dummymatchbots_cons_t[] = {
{0, "Off"}, {0, "Off"},
{1, "Lv.1"}, {1, "Lv.1"},
@ -719,7 +722,7 @@ static boolean M_ChangeStringCvar(INT32 choice)
return false; return false;
} }
static void M_NextOpt(void) static boolean M_NextOpt(void)
{ {
INT16 oldItemOn = itemOn; // prevent infinite loop INT16 oldItemOn = itemOn; // prevent infinite loop
@ -729,15 +732,24 @@ static void M_NextOpt(void)
do do
{ {
if (itemOn + 1 > currentMenu->numitems - 1) if (itemOn + 1 > currentMenu->numitems - 1)
{
// Prevent looparound here
// If you're going to add any extra exceptions, DON'T.
// Add a "don't loop" flag to the menu_t struct instead.
if (currentMenu == &MISC_AddonsDef)
return false;
itemOn = 0; itemOn = 0;
}
else else
itemOn++; itemOn++;
} while (oldItemOn != itemOn && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_SPACE); } while (oldItemOn != itemOn && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_SPACE);
M_UpdateMenuBGImage(false); M_UpdateMenuBGImage(false);
return true;
} }
static void M_PrevOpt(void) static boolean M_PrevOpt(void)
{ {
INT16 oldItemOn = itemOn; // prevent infinite loop INT16 oldItemOn = itemOn; // prevent infinite loop
@ -747,12 +759,21 @@ static void M_PrevOpt(void)
do do
{ {
if (!itemOn) if (!itemOn)
{
// Prevent looparound here
// If you're going to add any extra exceptions, DON'T.
// Add a "don't loop" flag to the menu_t struct instead.
if (currentMenu == &MISC_AddonsDef)
return false;
itemOn = currentMenu->numitems - 1; itemOn = currentMenu->numitems - 1;
}
else else
itemOn--; itemOn--;
} while (oldItemOn != itemOn && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_SPACE); } while (oldItemOn != itemOn && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_SPACE);
M_UpdateMenuBGImage(false); M_UpdateMenuBGImage(false);
return true;
} }
// //
@ -1436,15 +1457,15 @@ static void M_HandleMenuInput(void)
// Keys usable within menu // Keys usable within menu
if (ud > 0) if (ud > 0)
{ {
M_NextOpt(); if (M_NextOpt())
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
M_SetMenuDelay(pid); M_SetMenuDelay(pid);
return; return;
} }
else if (ud < 0) else if (ud < 0)
{ {
M_PrevOpt(); if (M_PrevOpt())
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
M_SetMenuDelay(pid); M_SetMenuDelay(pid);
return; return;
} }
@ -1683,6 +1704,8 @@ void M_Init(void)
CV_RegisterVar(&cv_dummygpencore); CV_RegisterVar(&cv_dummygpencore);
CV_RegisterVar(&cv_dummymatchbots); CV_RegisterVar(&cv_dummymatchbots);
CV_RegisterVar(&cv_dummyaddonsearch);
M_UpdateMenuBGImage(true); M_UpdateMenuBGImage(true);
#if 0 #if 0
@ -6280,6 +6303,8 @@ void M_Addons(INT32 choice)
else else
dir_on[menudepthleft] = 0; dir_on[menudepthleft] = 0;
MISC_AddonsDef.lastOn = 0; // Always start on search
MISC_AddonsDef.prevMenu = currentMenu; MISC_AddonsDef.prevMenu = currentMenu;
M_SetupNextMenu(&MISC_AddonsDef, false); M_SetupNextMenu(&MISC_AddonsDef, false);
} }
@ -6387,43 +6412,23 @@ static void M_AddonExec(INT32 ch)
} }
} }
#define len menusearch[0] static void M_UpdateAddonsSearch(void)
static boolean M_ChangeStringAddons(INT32 choice)
{ {
if (shiftdown && choice >= 32 && choice <= 127) menusearch[0] = strlen(cv_dummyaddonsearch.string);
choice = shiftxform[choice]; strlcpy(menusearch+1, cv_dummyaddonsearch.string, MAXSTRINGLENGTH);
if (!cv_addons_search_case.value)
strupr(menusearch+1);
switch (choice) #if 0 // much slower
if (!preparefilemenu(true, false))
{ {
case KEY_DEL: UNEXIST;
if (len) return;
{
len = menusearch[1] = 0;
return true;
}
break;
case KEY_BACKSPACE:
if (len)
{
menusearch[1+--len] = 0;
return true;
}
break;
default:
if (choice >= 32 && choice <= 127)
{
if (len < MAXSTRINGLENGTH - 1)
{
menusearch[1+len++] = (char)choice;
menusearch[1+len] = 0;
return true;
}
}
break;
} }
return false; #else // streamlined
searchfilemenu(NULL);
#endif
} }
#undef len
void M_HandleAddons(INT32 choice) void M_HandleAddons(INT32 choice)
{ {
@ -6432,34 +6437,30 @@ void M_HandleAddons(INT32 choice)
(void) choice; (void) choice;
if (M_ChangeStringAddons(choice))
{
char *tempname = NULL;
if (dirmenu && dirmenu[dir_on[menudepthleft]])
tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL
#if 0 // much slower
if (!preparefilemenu(true, false))
{
UNEXIST;
return;
}
#else // streamlined
searchfilemenu(tempname);
#endif
}
if (menucmd[pid].dpad_ud > 0) if (menucmd[pid].dpad_ud > 0)
{ {
if (dir_on[menudepthleft] < sizedirmenu-1) if (dir_on[menudepthleft] < sizedirmenu-1)
{
dir_on[menudepthleft]++; dir_on[menudepthleft]++;
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
}
else if (M_NextOpt())
{
S_StartSound(NULL, sfx_s3k5b);
}
M_SetMenuDelay(pid); M_SetMenuDelay(pid);
} }
else if (menucmd[pid].dpad_ud < 0) else if (menucmd[pid].dpad_ud < 0)
{ {
if (dir_on[menudepthleft]) if (dir_on[menudepthleft])
{
dir_on[menudepthleft]--; dir_on[menudepthleft]--;
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
}
else if (M_PrevOpt())
{
S_StartSound(NULL, sfx_s3k5b);
}
M_SetMenuDelay(pid); M_SetMenuDelay(pid);
} }