From 9ee41124c1b1b9bccfb7dd6bc6db39e243735bc8 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Sun, 7 Sep 2025 00:20:41 -0400 Subject: [PATCH 01/15] start porting my wip grid css from 2021 --- src/deh_soc.c | 1 + src/deh_tables.c | 5 + src/doomdef.h | 2 +- src/m_menu.c | 370 ++++++++++++++++++++++++++++++++++++++--------- src/m_menu.h | 9 ++ 5 files changed, 319 insertions(+), 68 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index e75221663..f78f101d1 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1844,6 +1844,7 @@ void readtextprompt(MYFILE *f, INT32 num) // super secret menu cvars... :shushing_face: static struct { const char *name; consvar_t *var; } HIDDENVARS[] = { { "CHOOSESKIN", &cv_chooseskin }, + { "DUMMYSKIN", &cv_dummyskin }, { "DUMMYGPDIFFICULTY", &cv_dummygpdifficulty }, { "DUMMYGPENCORE", &cv_dummygpencore }, { "DUMMYGPCUP", &cv_dummygpcup }, diff --git a/src/deh_tables.c b/src/deh_tables.c index e6037e5de..e8820039e 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -755,6 +755,8 @@ struct menu_routine_s const MENU_ROUTINES[] = { { "QUITVIEWSERVER", &MR_QuitViewServer }, { "HANDLEVIEWSERVER", &MR_HandleViewServer }, { "CAMERASETUP", &MR_CameraSetup }, + // { "BARCSS", &MR_HandleBarCss }, + { "HANDLESETUPMULTIPLAYERMENU", &MR_HandleSetupMultiPlayerMenu }, #ifdef HAVE_DISCORDRPC { "HANDLEDISCORDREQUESTS", &MR_HandleDiscordRequests }, #endif @@ -769,6 +771,9 @@ struct menu_drawer_s const MENU_DRAWERS[] = { { "DRAWTIMEATTACKMENU", &MD_DrawTimeAttackMenu }, { "DRAWMPMAINMENU", &MD_DrawMPMainMenu }, { "DRAWSETUPMULTIPLAYERMENU", &MD_DrawSetupMultiPlayerMenu }, + // { "DRAWCSSCHARACTER", &MD_DrawCssCharacter }, + // { "DRAWBARCSSSELECTOR", &MD_DrawBarCssSelector }, + // { "DRAWGRIDCSSSELECTOR", &MD_DrawGridCssSelector }, { "DRAWVIDEOMODE", &MD_DrawVideoMode }, { "DRAWADDONS", &MD_DrawAddons }, { "DRAWREPLAYSTARTMENU", &MD_DrawReplayStartMenu }, diff --git a/src/doomdef.h b/src/doomdef.h index f1e9a57fd..8355f8528 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -103,7 +103,7 @@ extern "C" { // Special Hashing. //#define NOFILEHASH -//#define NOVERIFYIWADS +#define NOVERIFYIWADS // Uncheck this to compile debugging code //#define RANGECHECK diff --git a/src/m_menu.c b/src/m_menu.c index 60371b6c1..00edf532c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -377,6 +377,7 @@ static INT16 lastnextmap = 1; static CV_PossibleValue_t skins_cons_t[] = {{0, "MIN"}, {MAXSKINS, "MAX"}, {0, NULL}}; consvar_t cv_chooseskin = CVAR_INIT ("chooseskin", "0", CV_HIDEN|CV_CALL|CV_NOINIT, skins_cons_t, Nextmap_OnChange); +consvar_t cv_dummyskin = CVAR_INIT ("dummyskin", "0", CV_HIDEN, skins_cons_t, NULL); // This gametype list is integral for many different reasons. // When you add gametypes here, don't forget to update them in dehacked.c and doomstat.h! @@ -6729,31 +6730,45 @@ static state_t *follower_state; // for either player 1 or 2 static UINT8 setupplayer; +#define charw 72 + void MD_DrawSetupMultiPlayerMenu(void) { - INT32 mx, my, st, flags = 0; - spritedef_t *sprdef; - spriteframe_t *sprframe; + // INT32 mx, my; + + // mx = menudefs[MN_MP_PLAYERSETUP].x; + // my = menudefs[MN_MP_PLAYERSETUP].y; + + // use generic drawer for cursor, items and title + // bg, text, arrows handled by generic drawer + MD_DrawGenericMenu(); + + // MD_DrawCssStatBacker(); + MD_DrawCssColourBar(); + MD_DrawCssCharacter(); + + // MD_DrawBarCssSelector(); + MD_DrawGridCssSelector(); +} + +void MD_DrawCssStatBacker(void) +{ + INT32 mx, my; patch_t *statdot = W_CachePatchName("K_SDOT0", PU_CACHE); - patch_t *patch; - UINT8 frame; UINT8 speed; UINT8 weight; const UINT8 *flashcol = V_GetStringColormap(highlightflags); INT16 i; + INT32 skintodisplay = M_IsItemOn(MN_MP_PLAYERSETUP, "SKIN") ? cv_dummyskin.value : cv_chooseskin.value; + mx = menudefs[MN_MP_PLAYERSETUP].x; my = menudefs[MN_MP_PLAYERSETUP].y; - // use generic drawer for cursor, items and title - MD_DrawGenericMenu(); - // SRB2Kart: draw the stat backer - // bg, text, arrows handled by generic drawer - for (i = 0; i < numskins; i++) // draw the stat dots { - if (i != cv_chooseskin.value && R_SkinAvailable(skins[i].name) != -1) + if (i != skintodisplay && R_SkinAvailable(skins[i].name) != -1) { speed = skins[i].kartspeed; weight = skins[i].kartweight; @@ -6761,8 +6776,8 @@ void MD_DrawSetupMultiPlayerMenu(void) } } - speed = skins[cv_chooseskin.value].kartspeed; - weight = skins[cv_chooseskin.value].kartweight; + speed = skins[skintodisplay].kartspeed; + weight = skins[skintodisplay].kartweight; statdot = W_CachePatchName("K_SDOT1", PU_CACHE); if (skullAnimCounter < 4) // SRB2Kart: we draw this dot later so that it's not covered if there's multiple skins with the same stats @@ -6772,9 +6787,17 @@ void MD_DrawSetupMultiPlayerMenu(void) statdot = W_CachePatchName("K_SDOT2", PU_CACHE); // coloured center V_DrawFixedPatch(((BASEVIDWIDTH - mx - 80) + ((speed-1)*8))< 7 * FRACUNIT; cursorframe -= 7 * FRACUNIT) {} + INT32 skintodisplay = M_IsItemOn(MN_MP_PLAYERSETUP, "SKIN") ? cv_dummyskin.value : cv_chooseskin.value; - cursor = W_CachePatchName(va("K_BHILI%d", (cursorframe >> FRACBITS) + 1), PU_CACHE); - - if (col < 0) - col += numskins; - while (k <= icons) - { - if (!(k++)) - { - scale = FRACUNIT; - face = faceprefix[col][FACE_WANTED]; - offx = 12; - offy = 0; - } - else - { - scale = FRACUNIT/2; - face = faceprefix[col][FACE_RANK]; - offx = 8; - offy = 8; - } - colmap = R_GetTranslationColormap(col, cv_dummycolor.value, GTC_MENUCACHE); - if (face) - V_DrawFixedPatch((x+offx)<= numskins) - col -= numskins; - x += FixedMul(iconwidth<numframes) // No frames ?? return; // Can't render! @@ -6900,10 +6889,10 @@ void MD_DrawSetupMultiPlayerMenu(void) V_DrawFill(mx + 43 - (charw/2), my+65, charw, 84, 159); // draw player sprite - UINT8 *colormap = R_GetTranslationColormap(cv_chooseskin.value, cv_dummycolor.value, GTC_MENUCACHE); + UINT8 *colormap = R_GetTranslationColormap(skintodisplay, cv_dummycolor.value, GTC_MENUCACHE); V_DrawFixedPatch((mx+43)<>ANGLETOFINESHIFT) & FINEMASK)); - UINT16 color = K_GetEffectiveFollowerColor(cv_followercolor[setupplayer].value, &fl, cv_dummycolor.value, &skins[cv_chooseskin.value]); + UINT16 color = K_GetEffectiveFollowerColor(cv_followercolor[setupplayer].value, &fl, cv_dummycolor.value, &skins[skintodisplay]); colormap = R_GetTranslationColormap(TC_DEFAULT, color, 0); // why does GTC_MENUCACHE not work here...? INT32 x = (mx+65)*FRACUNIT; @@ -6970,9 +6959,252 @@ void MD_DrawSetupMultiPlayerMenu(void) Z_Free(colormap); } } - -#undef charw } +#undef charw + +void MD_DrawBarCssSelector(void) +{ + INT32 my; + + // mx = menudefs[MN_MP_PLAYERSETUP].x; + my = menudefs[MN_MP_PLAYERSETUP].y; + + // character bar, ripped off the color bar :V +#define iconwidth 32 + { + const INT32 icons = 4; + INT32 k = -icons; + INT16 col = (cv_chooseskin.value - icons) % numskins; + INT32 x = BASEVIDWIDTH/2 - ((icons+1)*24) - 4; + fixed_t scale = FRACUNIT/2; + INT32 offx = 8, offy = 8; + patch_t *cursor; + static fixed_t cursorframe = 0; + patch_t *face; + UINT8 *colmap; + + cursorframe += renderdeltatics / 4; + for (; cursorframe > 7 * FRACUNIT; cursorframe -= 7 * FRACUNIT) {} + + cursor = W_CachePatchName(va("K_BHILI%d", (cursorframe >> FRACBITS) + 1), PU_CACHE); + + if (col < 0) + col += numskins; + while (k <= icons) + { + if (!(k++)) + { + scale = FRACUNIT; + face = faceprefix[col][FACE_WANTED]; + offx = 12; + offy = 0; + } + else + { + scale = FRACUNIT/2; + face = faceprefix[col][FACE_RANK]; + offx = 8; + offy = 8; + } + colmap = R_GetTranslationColormap(col, cv_dummycolor.value, GTC_MENUCACHE); + if (face) + V_DrawFixedPatch((x+offx)<= numskins) + col -= numskins; + x += FixedMul(iconwidth< 0) + listlen++; + if (listlen - SKINGRIDHEIGHT > 0) + barlen = dy/(listlen-SKINGRIDHEIGHT + 1); + else + barlen = dy; + barpos = barlen * gridcss_skinydrag; + + if (gridcss_skinydrag >= listlen - SKINGRIDHEIGHT) + barlen = dy - barpos; + + V_DrawFill(x, y + barpos, scrx, barlen, 5); + V_DrawFill(x, y + barpos, 1, barlen, 7); + V_DrawFill(x, y + barpos + barlen - 1, scrx, 1, 7); + } + // end background and scroll bar + + for (INT32 gridslot = 0; gridslot < SKINGRIDWIDTH*SKINGRIDHEIGHT; gridslot++) + { + gridx = ((gridslot % SKINGRIDWIDTH) * 18) + ((BASEVIDWIDTH / 2) - (18 * SKINGRIDWIDTH) - 8) + 100 + SKINXSHIFT; //BASEVIDWIDTH / 2 - ((icons + 1) * 24) - 4; + gridy = ((gridslot / SKINGRIDWIDTH) * 18) + ((BASEVIDHEIGHT / 2) - (18 * (SKINGRIDWIDTH/2))) + SKINYSHIFT; //BASEVIDWIDTH / 2 - ((icons + 1) * 24) - 4; + calcs = gridslot + (gridcss_skinydrag * SKINGRIDWIDTH); + + if (calcs < numskins) + // skinn = skinsorted[calcs]; + skinn = calcs; + else if (gridslot % SKINGRIDWIDTH == 0) + break; //really conveniant (sic) place to break out here + else + { + // draw an empty slot + V_DrawFill(gridx, gridy, 16, 16, 239); + continue; + } + + if (skinn == skintodisplay) + { + cursorx = gridx; + cursory = gridy; + } + else + { + face = faceprefix[skinn][FACE_RANK]; + colmap = R_GetTranslationColormap(skinn, skins[skinn].prefcolor, GTC_MENUCACHE); + V_DrawFixedPatch(gridx * FRACUNIT, gridy * FRACUNIT, FRACUNIT, 0, face, colmap); + } + } + // draw wanted portrait as a cursor + face = faceprefix[skintodisplay][FACE_WANTED]; + colmap = R_GetTranslationColormap(skintodisplay, cv_dummycolor.value, GTC_MENUCACHE); + V_DrawFixedPatch((cursorx * FRACUNIT) - (face->width * FRACUNIT/4), (cursory * FRACUNIT) - (face->height * FRACUNIT/4), FRACUNIT, 0, face, colmap); +} + +// +// Maps a CSS grid selection cursor column (x) and row (y) to a skin selection index +// +INT32 MapGridSelectToSkin(INT32 row, INT32 column) +{ + return (row % SKINGRIDWIDTH) + (column * SKINGRIDWIDTH); +} + +INT32 MR_HandleSetupMultiPlayerMenu(INT32 choice) +{ + INT32 gridrow_delta, gridcolumn_delta; + INT32 skintodisplay = M_IsItemOn(MN_MP_PLAYERSETUP, "SKIN") ? cv_dummyskin.value : cv_chooseskin.value; + INT32 gridrow = skintodisplay % SKINGRIDHEIGHT; + INT32 gridcolumn = skintodisplay / SKINGRIDHEIGHT; + + if (!M_IsItemOn(MN_MP_PLAYERSETUP, "SKIN")) + { + CV_SetValue(&cv_dummyskin, cv_chooseskin.value); + return false; + } + + switch (choice) + { + case KEY_DOWNARROW: + gridcolumn_delta = 1; + S_StartSound(NULL, sfx_menu1); + break; + case KEY_UPARROW: + gridcolumn_delta = -1; + S_StartSound(NULL, sfx_menu1); + break; + case KEY_LEFTARROW: + gridrow_delta = -1; + S_StartSound(NULL, sfx_menu1); + break; + case KEY_RIGHTARROW: + gridrow_delta = 1; + S_StartSound(NULL, sfx_menu1); + break; + case KEY_PGDN: + break; + case KEY_PGUP: + break; + case KEY_ENTER: + if (cv_dummyskin.value < numskins) + { + CV_SetValue(&cv_chooseskin, MapGridSelectToSkin(gridrow, gridcolumn)); + S_StartSound(NULL, sfx_s221); + } + break; + default: + return false; + } + + // vertical cursor movement + if (gridcolumn + gridcolumn_delta < 0) + { + gridcolumn = 0; + M_SetItemOn(MN_MP_PLAYERSETUP, "NAME"); + } + if (MapGridSelectToSkin(gridrow, gridcolumn + gridcolumn_delta) >= numskins) + { + gridcolumn = SKINGRIDHEIGHT; + M_SetItemOn(MN_MP_PLAYERSETUP, "FOLLOWER"); + } + if (gridcolumn + gridcolumn_delta > SKINGRIDHEIGHT - 1) + { + gridcss_skinydrag++; + } + gridcolumn += gridcolumn_delta; + + CV_SetValue(&cv_dummyskin, MapGridSelectToSkin(gridrow, gridcolumn)); + return true; +} +#undef SKINGRIDWIDTH +#undef SKINGRIDHEIGHT +#undef SKINXSHIFT +#undef SKINYSHIFT // follower state update. This is its own function so that it's at least somewhat clean static void M_GetFollowerState(void) @@ -7006,11 +7238,15 @@ INT32 MR_SetupMultiPlayer(INT32 arg) multi_state = &states[mobjinfo[MT_PLAYER].seestate]; multi_tics = multi_state->tics * FRACUNIT; + gridcss_skinydrag = 0; + CV_Set(&cv_dummyname, cv_playername[arg].string); - CV_SetValue(&cv_dummyfollower, cv_follower[arg].value); CV_SetValue(&cv_chooseskin, R_SkinAvailable(cv_skin[arg].string)); + CV_SetValue(&cv_dummyskin, cv_chooseskin.value); + CV_SetValue(&cv_dummyfollower, cv_follower[arg].value); CV_SetValue(&cv_dummycolor, cv_playercolor[arg].value); + M_GetFollowerState(); // update follower state // disable skin changes if we can't actually change skins diff --git a/src/m_menu.h b/src/m_menu.h index eebc36c86..ed6ef9bf2 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -302,6 +302,7 @@ INT32 MR_Retry(INT32 choice); INT32 MR_EndGame(INT32 choice); INT32 MR_MapChange(INT32 choice); INT32 MR_SetupMultiPlayer(INT32 choice); +INT32 MR_HandleSetupMultiPlayerMenu(INT32 choice); INT32 MR_ConfirmSpectate(INT32 choice); INT32 MR_ConfirmEnterGame(INT32 choice); INT32 MR_ConfirmTeamScramble(INT32 choice); @@ -339,6 +340,11 @@ void MD_DrawReplayHut(void); void MD_DrawTimeAttackMenu(void); void MD_DrawMPMainMenu(void); void MD_DrawSetupMultiPlayerMenu(void); +void MD_DrawCssStatBacker(void); +void MD_DrawCssColourBar(void); +void MD_DrawCssCharacter(void); +void MD_DrawBarCssSelector(void); +void MD_DrawGridCssSelector(void); void MD_DrawConnectMenu(void); void MD_DrawVideoMode(void); void MD_DrawAddons(void); @@ -353,6 +359,8 @@ void MD_DrawViewServer(void); void MD_DrawDiscordRequests(void); #endif +INT32 MapGridSelectToSkin(INT32 column, INT32 row); + // Maybe this goes here????? Who knows. boolean M_MouseNeeded(void); @@ -416,6 +424,7 @@ extern consvar_t cv_dummyattackingslipdash, cv_dummyattackingpurpledrift, cv_dum extern consvar_t cv_dummystaff; extern consvar_t cv_dummymultiplayer, cv_dummyip, cv_dummyname, cv_dummyfollower, cv_dummycolor; extern consvar_t cv_dummyserverpage; +extern consvar_t cv_dummyskin; extern consvar_t cv_menucaps; // allow menu text to be displayed in lowercase From 35483ccd8474998e30bce534af19b7272e17140b Mon Sep 17 00:00:00 2001 From: minenice55 Date: Sun, 7 Sep 2025 21:20:18 -0400 Subject: [PATCH 02/15] get controls working --- src/deh_soc.c | 1 - src/m_menu.c | 200 ++++++++++++++++++++++++++++++++++++++------------ src/m_menu.h | 1 - 3 files changed, 152 insertions(+), 50 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index f78f101d1..e75221663 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1844,7 +1844,6 @@ void readtextprompt(MYFILE *f, INT32 num) // super secret menu cvars... :shushing_face: static struct { const char *name; consvar_t *var; } HIDDENVARS[] = { { "CHOOSESKIN", &cv_chooseskin }, - { "DUMMYSKIN", &cv_dummyskin }, { "DUMMYGPDIFFICULTY", &cv_dummygpdifficulty }, { "DUMMYGPENCORE", &cv_dummygpencore }, { "DUMMYGPCUP", &cv_dummygpcup }, diff --git a/src/m_menu.c b/src/m_menu.c index 00edf532c..1512c96ae 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -377,7 +377,6 @@ static INT16 lastnextmap = 1; static CV_PossibleValue_t skins_cons_t[] = {{0, "MIN"}, {MAXSKINS, "MAX"}, {0, NULL}}; consvar_t cv_chooseskin = CVAR_INIT ("chooseskin", "0", CV_HIDEN|CV_CALL|CV_NOINIT, skins_cons_t, Nextmap_OnChange); -consvar_t cv_dummyskin = CVAR_INIT ("dummyskin", "0", CV_HIDEN, skins_cons_t, NULL); // This gametype list is integral for many different reasons. // When you add gametypes here, don't forget to update them in dehacked.c and doomstat.h! @@ -6721,6 +6720,11 @@ INT32 MR_ConnectIP(INT32 choice) static fixed_t multi_tics; static state_t *multi_state; +static INT32 gridcss_skinydrag; +static INT32 gridcss_skinmemory; +static INT32 gridcss_row; +static INT32 gridcss_column; + // used for follower display on player setup menu static fixed_t follower_tics; static UINT32 follower_frame; // used for FF_ANIMATE garbo @@ -6760,7 +6764,7 @@ void MD_DrawCssStatBacker(void) const UINT8 *flashcol = V_GetStringColormap(highlightflags); INT16 i; - INT32 skintodisplay = M_IsItemOn(MN_MP_PLAYERSETUP, "SKIN") ? cv_dummyskin.value : cv_chooseskin.value; + INT32 skintodisplay = cv_chooseskin.value; mx = menudefs[MN_MP_PLAYERSETUP].x; my = menudefs[MN_MP_PLAYERSETUP].y; @@ -6851,7 +6855,7 @@ void MD_DrawCssCharacter(void) spritedef_t *sprdef; spriteframe_t *sprframe; - INT32 skintodisplay = M_IsItemOn(MN_MP_PLAYERSETUP, "SKIN") ? cv_dummyskin.value : cv_chooseskin.value; + INT32 skintodisplay = cv_chooseskin.value; mx = menudefs[MN_MP_PLAYERSETUP].x; my = menudefs[MN_MP_PLAYERSETUP].y; @@ -7021,7 +7025,6 @@ void MD_DrawBarCssSelector(void) //callmore's skin select stuff taken with permission //fucked with by minenice -static INT32 gridcss_skinydrag; //width now 9 so we can make moe's "2D" grid just an option in the normal grid #define SKINGRIDWIDTH 9 @@ -7036,13 +7039,16 @@ void MD_DrawGridCssSelector(void) patch_t *face; UINT8 *colmap; + patch_t *cursor; + static fixed_t cursorframe = 0; + INT32 gridx; INT32 gridy; INT32 cursorx; INT32 cursory; INT32 calcs; - INT32 skintodisplay = M_IsItemOn(MN_MP_PLAYERSETUP, "SKIN") ? cv_dummyskin.value : cv_chooseskin.value; + INT32 skintodisplay = cv_chooseskin.value; // gridcss_skinydrag = 0; // draws background and scroll bar @@ -7121,10 +7127,35 @@ void MD_DrawGridCssSelector(void) V_DrawFixedPatch(gridx * FRACUNIT, gridy * FRACUNIT, FRACUNIT, 0, face, colmap); } } - // draw wanted portrait as a cursor - face = faceprefix[skintodisplay][FACE_WANTED]; - colmap = R_GetTranslationColormap(skintodisplay, cv_dummycolor.value, GTC_MENUCACHE); - V_DrawFixedPatch((cursorx * FRACUNIT) - (face->width * FRACUNIT/4), (cursory * FRACUNIT) - (face->height * FRACUNIT/4), FRACUNIT, 0, face, colmap); + + // draw wanted portrait and cursor + if (M_IsItemOn(MN_MP_PLAYERSETUP, "SKIN")) + { + face = faceprefix[skintodisplay][FACE_WANTED]; + colmap = R_GetTranslationColormap(skintodisplay, cv_dummycolor.value, GTC_MENUCACHE); + V_DrawFixedPatch((cursorx * FRACUNIT) - (face->width * FRACUNIT/4), (cursory * FRACUNIT) - (face->height * FRACUNIT/4), FRACUNIT, 0, face, colmap); + + + cursorframe += renderdeltatics / 4; + for (; cursorframe > 7 * FRACUNIT; cursorframe -= 7 * FRACUNIT) {} + cursor = W_CachePatchName(va("K_BHILI%d", (cursorframe >> FRACBITS) + 1), PU_CACHE); + // cursor patch offsets are wrong so draw at same coordinate as portrait + V_DrawFixedPatch((cursorx * FRACUNIT) - (face->width * FRACUNIT/4), (cursory * FRACUNIT) - (face->height * FRACUNIT/4), FRACUNIT, 0, cursor, colmap); + + } + else + { + face = faceprefix[skintodisplay][FACE_RANK]; + colmap = R_GetTranslationColormap(skintodisplay, cv_dummycolor.value, GTC_MENUCACHE); + V_DrawFixedPatch(cursorx * FRACUNIT, cursory * FRACUNIT, FRACUNIT, 0, face, colmap); + cursor = W_CachePatchName("M_FSEL", PU_CACHE); + + if (skullAnimCounter < 4) + { + colmap = V_GetStringColormap(skincolors[cv_dummycolor.value].chatcolor); + V_DrawFixedPatch(cursorx * FRACUNIT, cursory * FRACUNIT, FRACUNIT/2, 0, cursor, colmap); + } + } } // @@ -7137,74 +7168,139 @@ INT32 MapGridSelectToSkin(INT32 row, INT32 column) INT32 MR_HandleSetupMultiPlayerMenu(INT32 choice) { - INT32 gridrow_delta, gridcolumn_delta; - INT32 skintodisplay = M_IsItemOn(MN_MP_PLAYERSETUP, "SKIN") ? cv_dummyskin.value : cv_chooseskin.value; - INT32 gridrow = skintodisplay % SKINGRIDHEIGHT; - INT32 gridcolumn = skintodisplay / SKINGRIDHEIGHT; - if (!M_IsItemOn(MN_MP_PLAYERSETUP, "SKIN")) { - CV_SetValue(&cv_dummyskin, cv_chooseskin.value); return false; } switch (choice) { case KEY_DOWNARROW: - gridcolumn_delta = 1; + // gridcolumn_delta = 1; + if (gridcss_column == (numskins - 1) / SKINGRIDWIDTH) + { + M_SetItemOn(MN_MP_PLAYERSETUP, "FOLLOWER"); + CV_SetValue(&cv_chooseskin, gridcss_skinmemory); + gridcss_row = cv_chooseskin.value % SKINGRIDWIDTH; + gridcss_column = cv_chooseskin.value / SKINGRIDWIDTH; + + gridcss_skinydrag = CLAMP(gridcss_column - SKINGRIDHEIGHT + 1, 0, ((numskins - 1) / SKINGRIDWIDTH) - SKINGRIDHEIGHT - 1); + } + else + { + gridcss_column++; + + if (MapGridSelectToSkin(gridcss_row, gridcss_column) > (numskins - 1)) + { + gridcss_row = (numskins - 1) % SKINGRIDWIDTH; + gridcss_column = (numskins - 1) / SKINGRIDWIDTH; + } + + if ((gridcss_column - gridcss_skinydrag) > SKINGRIDHEIGHT - 1) + gridcss_skinydrag++; + } S_StartSound(NULL, sfx_menu1); break; case KEY_UPARROW: - gridcolumn_delta = -1; + if (gridcss_column == 0) + { + M_SetItemOn(MN_MP_PLAYERSETUP, "NAME"); + CV_SetValue(&cv_chooseskin, gridcss_skinmemory); + gridcss_row = cv_chooseskin.value % SKINGRIDWIDTH; + gridcss_column = cv_chooseskin.value / SKINGRIDWIDTH; + + gridcss_skinydrag = CLAMP(gridcss_column - SKINGRIDHEIGHT + 1, 0, ((numskins - 1) / SKINGRIDWIDTH) - SKINGRIDHEIGHT - 1); + } + else + { + gridcss_column--; + + if (gridcss_column < gridcss_skinydrag) + gridcss_skinydrag--; + } S_StartSound(NULL, sfx_menu1); break; case KEY_LEFTARROW: - gridrow_delta = -1; + // gridrow_delta = -1; + if (gridcss_row == 0) + { + if (MapGridSelectToSkin(SKINGRIDWIDTH - 1, gridcss_column) > (numskins-1)) + gridcss_row = numskins - (gridcss_column * SKINGRIDWIDTH) - 1; + else + gridcss_row = SKINGRIDWIDTH - 1; + if (gridcss_column > 0) + { + gridcss_row = SKINGRIDWIDTH - 1; + gridcss_column--; + + if (gridcss_column < gridcss_skinydrag) + gridcss_skinydrag--; + } + + } + else + { + gridcss_row--; + } S_StartSound(NULL, sfx_menu1); break; case KEY_RIGHTARROW: - gridrow_delta = 1; + // gridrow_delta = 1; + if ((gridcss_row + 1 == SKINGRIDWIDTH) || (MapGridSelectToSkin(gridcss_row + 1, gridcss_column) > (numskins - 1))) + { + gridcss_row = 0; + if (MapGridSelectToSkin(gridcss_row, gridcss_column + 1) <= (numskins - 1)) + { + gridcss_column++; + + if ((gridcss_column - gridcss_skinydrag) > SKINGRIDHEIGHT - 1) + gridcss_skinydrag++; + } + } + else + { + gridcss_row++; + } S_StartSound(NULL, sfx_menu1); break; case KEY_PGDN: + if (gridcss_column <= (numskins - 1) / SKINGRIDWIDTH) + { + gridcss_column = min(gridcss_column + SKINGRIDHEIGHT - 1, (numskins - 1) / SKINGRIDWIDTH); + + if (MapGridSelectToSkin(gridcss_row, gridcss_column) > (numskins - 1)) + { + gridcss_row = (numskins - 1) % SKINGRIDWIDTH; + gridcss_column = (numskins - 1) / SKINGRIDWIDTH; + } + + gridcss_skinydrag = min(gridcss_column - SKINGRIDHEIGHT + 1, ((numskins - 1) / SKINGRIDWIDTH) - SKINGRIDHEIGHT + 1); + + S_StartSound(NULL, sfx_menu1); + } break; case KEY_PGUP: + if (gridcss_column > 0) + { + gridcss_column = max(gridcss_column - SKINGRIDHEIGHT + 1, 0); + gridcss_skinydrag = max(gridcss_column, 0); + S_StartSound(NULL, sfx_menu1); + } break; case KEY_ENTER: - if (cv_dummyskin.value < numskins) + if (cv_chooseskin.value < numskins) { - CV_SetValue(&cv_chooseskin, MapGridSelectToSkin(gridrow, gridcolumn)); + gridcss_skinmemory = cv_chooseskin.value; S_StartSound(NULL, sfx_s221); } break; default: return false; } - - // vertical cursor movement - if (gridcolumn + gridcolumn_delta < 0) - { - gridcolumn = 0; - M_SetItemOn(MN_MP_PLAYERSETUP, "NAME"); - } - if (MapGridSelectToSkin(gridrow, gridcolumn + gridcolumn_delta) >= numskins) - { - gridcolumn = SKINGRIDHEIGHT; - M_SetItemOn(MN_MP_PLAYERSETUP, "FOLLOWER"); - } - if (gridcolumn + gridcolumn_delta > SKINGRIDHEIGHT - 1) - { - gridcss_skinydrag++; - } - gridcolumn += gridcolumn_delta; - - CV_SetValue(&cv_dummyskin, MapGridSelectToSkin(gridrow, gridcolumn)); + + CV_SetValue(&cv_chooseskin, MapGridSelectToSkin(gridcss_row, gridcss_column)); return true; } -#undef SKINGRIDWIDTH -#undef SKINGRIDHEIGHT -#undef SKINXSHIFT -#undef SKINYSHIFT // follower state update. This is its own function so that it's at least somewhat clean static void M_GetFollowerState(void) @@ -7238,14 +7334,15 @@ INT32 MR_SetupMultiPlayer(INT32 arg) multi_state = &states[mobjinfo[MT_PLAYER].seestate]; multi_tics = multi_state->tics * FRACUNIT; - gridcss_skinydrag = 0; - CV_Set(&cv_dummyname, cv_playername[arg].string); CV_SetValue(&cv_chooseskin, R_SkinAvailable(cv_skin[arg].string)); - CV_SetValue(&cv_dummyskin, cv_chooseskin.value); + gridcss_skinmemory = cv_chooseskin.value; CV_SetValue(&cv_dummyfollower, cv_follower[arg].value); CV_SetValue(&cv_dummycolor, cv_playercolor[arg].value); - + + gridcss_row = gridcss_skinmemory % SKINGRIDWIDTH; + gridcss_column = gridcss_skinmemory / SKINGRIDWIDTH; + gridcss_skinydrag = CLAMP(gridcss_column - SKINGRIDHEIGHT + 1, 0, ((numskins - 1) / SKINGRIDWIDTH) - SKINGRIDHEIGHT - 1); M_GetFollowerState(); // update follower state @@ -7258,6 +7355,9 @@ INT32 MR_SetupMultiPlayer(INT32 arg) INT32 MR_QuitMultiPlayerMenu(INT32 choice) { (void)choice; + + CV_SetValue(&cv_chooseskin, gridcss_skinmemory); + const char *followername = cv_dummyfollower.value == -1 ? "None" : followers[cv_dummyfollower.value].skinname; COM_BufInsertText(va( @@ -7269,6 +7369,10 @@ INT32 MR_QuitMultiPlayerMenu(INT32 choice) )); return true; } +#undef SKINGRIDWIDTH +#undef SKINGRIDHEIGHT +#undef SKINXSHIFT +#undef SKINYSHIFT void M_AddMenuColor(UINT16 color) { menucolor_t *c; diff --git a/src/m_menu.h b/src/m_menu.h index ed6ef9bf2..a0c87f5d9 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -424,7 +424,6 @@ extern consvar_t cv_dummyattackingslipdash, cv_dummyattackingpurpledrift, cv_dum extern consvar_t cv_dummystaff; extern consvar_t cv_dummymultiplayer, cv_dummyip, cv_dummyname, cv_dummyfollower, cv_dummycolor; extern consvar_t cv_dummyserverpage; -extern consvar_t cv_dummyskin; extern consvar_t cv_menucaps; // allow menu text to be displayed in lowercase From e1db6d59cd19e2914390955403fc9a459fffd05e Mon Sep 17 00:00:00 2001 From: minenice55 Date: Sun, 7 Sep 2025 21:52:59 -0400 Subject: [PATCH 03/15] fix inaccurate scroll bar --- src/m_menu.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 1512c96ae..faac64d6e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7060,11 +7060,11 @@ void MD_DrawGridCssSelector(void) INT32 dy = (SKINGRIDHEIGHT * 18); INT32 scrx = 4; //2 is added to make the final "thickness" - int listlen; - int barlen; - int barpos; + INT32 columncount; + INT32 barlen; + INT32 barpos; - listlen = (numskins)/SKINGRIDWIDTH; + columncount = ((numskins - 1) / SKINGRIDWIDTH); //draw BG V_DrawFill(x, y, dx, dy, 244); @@ -7080,16 +7080,24 @@ void MD_DrawGridCssSelector(void) V_DrawFill(x, y, scrx, dy, 15); //draw scroll bar bar - if ((numskins) % SKINGRIDWIDTH > 0) - listlen++; - if (listlen - SKINGRIDHEIGHT > 0) - barlen = dy/(listlen-SKINGRIDHEIGHT + 1); - else - barlen = dy; - barpos = barlen * gridcss_skinydrag; + // if ((numskins) % SKINGRIDWIDTH > 0) + // columncount++; + // if (columncount - SKINGRIDHEIGHT > 0) + // barlen = dy/(columncount-SKINGRIDHEIGHT + 1); + // else + // barlen = dy; + // barpos = barlen * gridcss_skinydrag; - if (gridcss_skinydrag >= listlen - SKINGRIDHEIGHT) + // if (gridcss_skinydrag >= columncount - SKINGRIDHEIGHT) + // barlen = dy - barpos; + + barlen = dy * SKINGRIDHEIGHT / columncount; + barpos = dy * gridcss_skinydrag / columncount; + + if (barpos + barlen > dy) + { barlen = dy - barpos; + } V_DrawFill(x, y + barpos, scrx, barlen, 5); V_DrawFill(x, y + barpos, 1, barlen, 7); From 8c480f9606aeb145d89f8c813193a4aa889c0001 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Sun, 7 Sep 2025 22:09:17 -0400 Subject: [PATCH 04/15] tweak colours, tab fast-exit --- src/m_menu.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index faac64d6e..8349e50b1 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7031,7 +7031,7 @@ void MD_DrawBarCssSelector(void) #define SKINGRIDHEIGHT 6 #define SKINXSHIFT 33 -#define SKINYSHIFT 23 +#define SKINYSHIFT 28 void MD_DrawGridCssSelector(void) { @@ -7067,7 +7067,7 @@ void MD_DrawGridCssSelector(void) columncount = ((numskins - 1) / SKINGRIDWIDTH); //draw BG - V_DrawFill(x, y, dx, dy, 244); + V_DrawFill(x, y, dx, dy, 159); //draw scroll bar "back" x += dx + 4; @@ -7080,17 +7080,6 @@ void MD_DrawGridCssSelector(void) V_DrawFill(x, y, scrx, dy, 15); //draw scroll bar bar - // if ((numskins) % SKINGRIDWIDTH > 0) - // columncount++; - // if (columncount - SKINGRIDHEIGHT > 0) - // barlen = dy/(columncount-SKINGRIDHEIGHT + 1); - // else - // barlen = dy; - // barpos = barlen * gridcss_skinydrag; - - // if (gridcss_skinydrag >= columncount - SKINGRIDHEIGHT) - // barlen = dy - barpos; - barlen = dy * SKINGRIDHEIGHT / columncount; barpos = dy * gridcss_skinydrag / columncount; @@ -7119,7 +7108,7 @@ void MD_DrawGridCssSelector(void) else { // draw an empty slot - V_DrawFill(gridx, gridy, 16, 16, 239); + V_DrawFill(gridx, gridy, 16, 16, 158); continue; } @@ -7295,6 +7284,16 @@ INT32 MR_HandleSetupMultiPlayerMenu(INT32 choice) S_StartSound(NULL, sfx_menu1); } break; + case KEY_TAB: + M_SetItemOn(MN_MP_PLAYERSETUP, "FOLLOWER"); + CV_SetValue(&cv_chooseskin, gridcss_skinmemory); + gridcss_row = cv_chooseskin.value % SKINGRIDWIDTH; + gridcss_column = cv_chooseskin.value / SKINGRIDWIDTH; + + gridcss_skinydrag = CLAMP(gridcss_column - SKINGRIDHEIGHT + 1, 0, ((numskins - 1) / SKINGRIDWIDTH) - SKINGRIDHEIGHT - 1); + + S_StartSound(NULL, sfx_menu1); + break; case KEY_ENTER: if (cv_chooseskin.value < numskins) { From 7b5a4c5529505cb5f3b14f103c934e4572076215 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Sun, 7 Sep 2025 22:10:04 -0400 Subject: [PATCH 05/15] remove commented code --- src/m_menu.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 8349e50b1..01180835e 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7173,7 +7173,6 @@ INT32 MR_HandleSetupMultiPlayerMenu(INT32 choice) switch (choice) { case KEY_DOWNARROW: - // gridcolumn_delta = 1; if (gridcss_column == (numskins - 1) / SKINGRIDWIDTH) { M_SetItemOn(MN_MP_PLAYERSETUP, "FOLLOWER"); @@ -7218,7 +7217,6 @@ INT32 MR_HandleSetupMultiPlayerMenu(INT32 choice) S_StartSound(NULL, sfx_menu1); break; case KEY_LEFTARROW: - // gridrow_delta = -1; if (gridcss_row == 0) { if (MapGridSelectToSkin(SKINGRIDWIDTH - 1, gridcss_column) > (numskins-1)) @@ -7233,7 +7231,6 @@ INT32 MR_HandleSetupMultiPlayerMenu(INT32 choice) if (gridcss_column < gridcss_skinydrag) gridcss_skinydrag--; } - } else { @@ -7242,7 +7239,6 @@ INT32 MR_HandleSetupMultiPlayerMenu(INT32 choice) S_StartSound(NULL, sfx_menu1); break; case KEY_RIGHTARROW: - // gridrow_delta = 1; if ((gridcss_row + 1 == SKINGRIDWIDTH) || (MapGridSelectToSkin(gridcss_row + 1, gridcss_column) > (numskins - 1))) { gridcss_row = 0; From 779fcde3f47701b196b41b914b5f52d26ec357fe Mon Sep 17 00:00:00 2001 From: minenice55 Date: Sun, 7 Sep 2025 22:32:14 -0400 Subject: [PATCH 06/15] reword this note --- src/m_menu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 01180835e..3fe386607 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7023,8 +7023,8 @@ void MD_DrawBarCssSelector(void) #undef iconwidth } -//callmore's skin select stuff taken with permission -//fucked with by minenice +// minenice's grid style CSS from an unfinished moe mansion pull request +// originally based on callmore's skin select //width now 9 so we can make moe's "2D" grid just an option in the normal grid #define SKINGRIDWIDTH 9 From be8e46506aea79f226e923196e71813374fcc343 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Mon, 8 Sep 2025 08:50:17 -0400 Subject: [PATCH 07/15] cvar to swap css styles need to check this still --- src/m_menu.c | 27 ++++++++++++++++----------- src/m_menu.h | 2 ++ 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 3fe386607..55c5b4b7c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -378,6 +378,9 @@ static INT16 lastnextmap = 1; static CV_PossibleValue_t skins_cons_t[] = {{0, "MIN"}, {MAXSKINS, "MAX"}, {0, NULL}}; consvar_t cv_chooseskin = CVAR_INIT ("chooseskin", "0", CV_HIDEN|CV_CALL|CV_NOINIT, skins_cons_t, Nextmap_OnChange); +static CV_PossibleValue_t skinselectstyle_cons_t[] = {{0, "Bar"}, {1, "Grid"}, {0, NULL}}; +consvar_t cv_skinselectstyle = CVAR_INIT ("skinselectstyle", "Grid", CV_SAVE, skinselectstyle_cons_t, NULL); + // This gametype list is integral for many different reasons. // When you add gametypes here, don't forget to update them in dehacked.c and doomstat.h! CV_PossibleValue_t gametype_cons_t[NUMGAMETYPES+1]; @@ -6737,22 +6740,23 @@ static UINT8 setupplayer; #define charw 72 void MD_DrawSetupMultiPlayerMenu(void) -{ - // INT32 mx, my; - - // mx = menudefs[MN_MP_PLAYERSETUP].x; - // my = menudefs[MN_MP_PLAYERSETUP].y; - +{ // use generic drawer for cursor, items and title // bg, text, arrows handled by generic drawer MD_DrawGenericMenu(); - // MD_DrawCssStatBacker(); MD_DrawCssColourBar(); MD_DrawCssCharacter(); - - // MD_DrawBarCssSelector(); - MD_DrawGridCssSelector(); + + if (cv_skinselectstyle.value) + { + MD_DrawGridCssSelector(); + } + else + { + MD_DrawCssStatBacker(); + MD_DrawBarCssSelector(); + } } void MD_DrawCssStatBacker(void) @@ -7165,7 +7169,8 @@ INT32 MapGridSelectToSkin(INT32 row, INT32 column) INT32 MR_HandleSetupMultiPlayerMenu(INT32 choice) { - if (!M_IsItemOn(MN_MP_PLAYERSETUP, "SKIN")) + // don't consume input if we're not interacting with the grid CSS + if (!(M_IsItemOn(MN_MP_PLAYERSETUP, "SKIN") && cv_skinselectstyle.value)) { return false; } diff --git a/src/m_menu.h b/src/m_menu.h index a0c87f5d9..a5a74ef3d 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -425,6 +425,8 @@ extern consvar_t cv_dummystaff; extern consvar_t cv_dummymultiplayer, cv_dummyip, cv_dummyname, cv_dummyfollower, cv_dummycolor; extern consvar_t cv_dummyserverpage; +extern consvar_t cv_skinselectstyle; + extern consvar_t cv_menucaps; // allow menu text to be displayed in lowercase #define MENUCAPS (!cv_menucaps.value ? V_ALLOWLOWERCASE : 0) From 7f12437c762825a404c0e6395c85596fab292e0e Mon Sep 17 00:00:00 2001 From: minenice55 Date: Mon, 8 Sep 2025 13:15:33 -0400 Subject: [PATCH 08/15] implement sorting for grid CSS --- .vscode/settings.json | 16 ++++++ src/m_menu.c | 78 +++++++++++++++++++-------- src/m_menu.h | 4 +- src/r_skins.c | 120 ++++++++++++++++++++++++++++++++++++++++++ src/r_skins.h | 16 ++++++ 5 files changed, 209 insertions(+), 25 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..7a89862eb --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,16 @@ +{ + "files.associations": { + "charconv": "c", + "chrono": "c", + "optional": "c", + "format": "c", + "ranges": "c", + "ratio": "c", + "system_error": "c", + "array": "c", + "functional": "c", + "tuple": "c", + "type_traits": "c", + "utility": "c" + } +} \ No newline at end of file diff --git a/src/m_menu.c b/src/m_menu.c index 55c5b4b7c..a542938c6 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -381,6 +381,17 @@ consvar_t cv_chooseskin = CVAR_INIT ("chooseskin", "0", CV_HIDEN|CV_CALL|CV_NOIN static CV_PossibleValue_t skinselectstyle_cons_t[] = {{0, "Bar"}, {1, "Grid"}, {0, NULL}}; consvar_t cv_skinselectstyle = CVAR_INIT ("skinselectstyle", "Grid", CV_SAVE, skinselectstyle_cons_t, NULL); +static CV_PossibleValue_t skinselectsort_cons_t[] = { + {SKINMENUSORT_ID, "Order Added"}, + {SKINMENUSORT_NAME, "Name"}, + {SKINMENUSORT_SPEED, "Speed"}, + {SKINMENUSORT_WEIGHT, "Weight"}, + {SKINMENUSORT_ACCEL, "Accel"}, + {SKINMENUSORT_HANDLING, "Handling"}, + {0, NULL} +}; +consvar_t cv_skinselectsort = CVAR_INIT ("skinselectsort", "Order Added", CV_SAVE|CV_CALL|CV_NOINIT, skinselectsort_cons_t, Skinsort_option_Onchange); + // This gametype list is integral for many different reasons. // When you add gametypes here, don't forget to update them in dehacked.c and doomstat.h! CV_PossibleValue_t gametype_cons_t[NUMGAMETYPES+1]; @@ -821,6 +832,26 @@ void Moviemode_option_Onchange(void) ; } + +//width now 9 so we can make moe's "2D" grid just an option in the normal grid +#define SKINGRIDWIDTH 9 +#define SKINGRIDHEIGHT 6 + +static INT32 gridcss_skinydrag; +static INT32 gridcss_skinmemory; +static INT32 gridcss_row; +static INT32 gridcss_column; + +void Skinsort_option_Onchange(void) +{ + SortSkins(); + INT32 sortedIndex = FindSortedSkinIndex(cv_chooseskin.value); + gridcss_row = sortedIndex % SKINGRIDWIDTH; + gridcss_column = sortedIndex / SKINGRIDWIDTH; + + gridcss_skinydrag = CLAMP(gridcss_column - SKINGRIDHEIGHT + 1, 0, ((numskins - 1) / SKINGRIDWIDTH) - SKINGRIDHEIGHT - 1); +} + // ========================================================================== // END ORGANIZATION STUFF. // ========================================================================== @@ -2082,6 +2113,8 @@ void M_Init(void) CV_RegisterVar(&cv_nextmap); CV_RegisterVar(&cv_newgametype); CV_RegisterVar(&cv_chooseskin); + CV_RegisterVar(&cv_skinselectstyle); + CV_RegisterVar(&cv_skinselectsort); CV_RegisterVar(&cv_autorecord); if (dedicated) @@ -6723,11 +6756,6 @@ INT32 MR_ConnectIP(INT32 choice) static fixed_t multi_tics; static state_t *multi_state; -static INT32 gridcss_skinydrag; -static INT32 gridcss_skinmemory; -static INT32 gridcss_row; -static INT32 gridcss_column; - // used for follower display on player setup menu static fixed_t follower_tics; static UINT32 follower_frame; // used for FF_ANIMATE garbo @@ -7030,10 +7058,6 @@ void MD_DrawBarCssSelector(void) // minenice's grid style CSS from an unfinished moe mansion pull request // originally based on callmore's skin select -//width now 9 so we can make moe's "2D" grid just an option in the normal grid -#define SKINGRIDWIDTH 9 -#define SKINGRIDHEIGHT 6 - #define SKINXSHIFT 33 #define SKINYSHIFT 28 @@ -7105,8 +7129,8 @@ void MD_DrawGridCssSelector(void) calcs = gridslot + (gridcss_skinydrag * SKINGRIDWIDTH); if (calcs < numskins) - // skinn = skinsorted[calcs]; - skinn = calcs; + skinn = skinsorted[calcs]; + // skinn = calcs; else if (gridslot % SKINGRIDWIDTH == 0) break; //really conveniant (sic) place to break out here else @@ -7169,6 +7193,7 @@ INT32 MapGridSelectToSkin(INT32 row, INT32 column) INT32 MR_HandleSetupMultiPlayerMenu(INT32 choice) { + INT32 sortedIndex; // don't consume input if we're not interacting with the grid CSS if (!(M_IsItemOn(MN_MP_PLAYERSETUP, "SKIN") && cv_skinselectstyle.value)) { @@ -7182,8 +7207,9 @@ INT32 MR_HandleSetupMultiPlayerMenu(INT32 choice) { M_SetItemOn(MN_MP_PLAYERSETUP, "FOLLOWER"); CV_SetValue(&cv_chooseskin, gridcss_skinmemory); - gridcss_row = cv_chooseskin.value % SKINGRIDWIDTH; - gridcss_column = cv_chooseskin.value / SKINGRIDWIDTH; + sortedIndex = FindSortedSkinIndex(cv_chooseskin.value); + gridcss_row = sortedIndex % SKINGRIDWIDTH; + gridcss_column = sortedIndex / SKINGRIDWIDTH; gridcss_skinydrag = CLAMP(gridcss_column - SKINGRIDHEIGHT + 1, 0, ((numskins - 1) / SKINGRIDWIDTH) - SKINGRIDHEIGHT - 1); } @@ -7207,8 +7233,9 @@ INT32 MR_HandleSetupMultiPlayerMenu(INT32 choice) { M_SetItemOn(MN_MP_PLAYERSETUP, "NAME"); CV_SetValue(&cv_chooseskin, gridcss_skinmemory); - gridcss_row = cv_chooseskin.value % SKINGRIDWIDTH; - gridcss_column = cv_chooseskin.value / SKINGRIDWIDTH; + sortedIndex = FindSortedSkinIndex(cv_chooseskin.value); + gridcss_row = sortedIndex % SKINGRIDWIDTH; + gridcss_column = sortedIndex / SKINGRIDWIDTH; gridcss_skinydrag = CLAMP(gridcss_column - SKINGRIDHEIGHT + 1, 0, ((numskins - 1) / SKINGRIDWIDTH) - SKINGRIDHEIGHT - 1); } @@ -7288,8 +7315,9 @@ INT32 MR_HandleSetupMultiPlayerMenu(INT32 choice) case KEY_TAB: M_SetItemOn(MN_MP_PLAYERSETUP, "FOLLOWER"); CV_SetValue(&cv_chooseskin, gridcss_skinmemory); - gridcss_row = cv_chooseskin.value % SKINGRIDWIDTH; - gridcss_column = cv_chooseskin.value / SKINGRIDWIDTH; + sortedIndex = FindSortedSkinIndex(cv_chooseskin.value); + gridcss_row = sortedIndex % SKINGRIDWIDTH; + gridcss_column = sortedIndex / SKINGRIDWIDTH; gridcss_skinydrag = CLAMP(gridcss_column - SKINGRIDHEIGHT + 1, 0, ((numskins - 1) / SKINGRIDWIDTH) - SKINGRIDHEIGHT - 1); @@ -7306,7 +7334,7 @@ INT32 MR_HandleSetupMultiPlayerMenu(INT32 choice) return false; } - CV_SetValue(&cv_chooseskin, MapGridSelectToSkin(gridcss_row, gridcss_column)); + CV_SetValue(&cv_chooseskin, skinsorted[MapGridSelectToSkin(gridcss_row, gridcss_column)]); return true; } @@ -7333,6 +7361,7 @@ static void M_GetFollowerState(void) // start the multiplayer setup menu INT32 MR_SetupMultiPlayer(INT32 arg) { + INT32 sortedIndex; if (arg < 0 || arg >= MAXSPLITSCREENPLAYERS) return false; @@ -7348,8 +7377,9 @@ INT32 MR_SetupMultiPlayer(INT32 arg) CV_SetValue(&cv_dummyfollower, cv_follower[arg].value); CV_SetValue(&cv_dummycolor, cv_playercolor[arg].value); - gridcss_row = gridcss_skinmemory % SKINGRIDWIDTH; - gridcss_column = gridcss_skinmemory / SKINGRIDWIDTH; + sortedIndex = FindSortedSkinIndex(gridcss_skinmemory); + gridcss_row = sortedIndex % SKINGRIDWIDTH; + gridcss_column = sortedIndex / SKINGRIDWIDTH; gridcss_skinydrag = CLAMP(gridcss_column - SKINGRIDHEIGHT + 1, 0, ((numskins - 1) / SKINGRIDWIDTH) - SKINGRIDHEIGHT - 1); M_GetFollowerState(); // update follower state @@ -7364,7 +7394,8 @@ INT32 MR_QuitMultiPlayerMenu(INT32 choice) { (void)choice; - CV_SetValue(&cv_chooseskin, gridcss_skinmemory); + if (cv_skinselectstyle.value == 1) + CV_SetValue(&cv_chooseskin, gridcss_skinmemory); const char *followername = cv_dummyfollower.value == -1 ? "None" : followers[cv_dummyfollower.value].skinname; @@ -7377,11 +7408,12 @@ INT32 MR_QuitMultiPlayerMenu(INT32 choice) )); return true; } -#undef SKINGRIDWIDTH -#undef SKINGRIDHEIGHT #undef SKINXSHIFT #undef SKINYSHIFT +#undef SKINGRIDWIDTH +#undef SKINGRIDHEIGH + void M_AddMenuColor(UINT16 color) { menucolor_t *c; diff --git a/src/m_menu.h b/src/m_menu.h index a5a74ef3d..58d4a8172 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -425,8 +425,6 @@ extern consvar_t cv_dummystaff; extern consvar_t cv_dummymultiplayer, cv_dummyip, cv_dummyname, cv_dummyfollower, cv_dummycolor; extern consvar_t cv_dummyserverpage; -extern consvar_t cv_skinselectstyle; - extern consvar_t cv_menucaps; // allow menu text to be displayed in lowercase #define MENUCAPS (!cv_menucaps.value ? V_ALLOWLOWERCASE : 0) @@ -471,6 +469,8 @@ fixed_t M_GetMapThumbnail(INT16 mapnum, patch_t **out); // Moviemode menu updating void Moviemode_option_Onchange(void); +void Skinsort_option_Onchange(void); + // Player Setup menu colors linked list struct menucolor_t { menucolor_t *next; diff --git a/src/r_skins.c b/src/r_skins.c index bd381d20c..f9ca34c40 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -37,6 +37,7 @@ INT32 numskins = 0; skin_t skins[MAXSKINS]; +INT32 skinsorted[MAXSKINS]; // FIXTHIS: don't work because it must be inistilised before the config load //#define SKINVALUES @@ -214,6 +215,8 @@ void R_InitSkins(void) } #endif + // doesn't seem right but it's what the original did + memset(skinsorted, 0, sizeof(skinsorted)); // yes default skin! numskins = 1; @@ -246,6 +249,121 @@ UINT32 R_GetSkinAvailabilities(void) return response; } +// +// From callmore's skin select +// Sort function(s) for sorting skin names +// +static int CompareSkinIds(const void *a, const void *b) +{ + const INT32 val_a = *((const INT32 *)a); + const INT32 val_b = *((const INT32 *)b); + if (val_a > val_b) + return 1; + else if (val_a < val_b) + return -1; + else + return 0; +} + +static int CompareSkinNames(const void *a, const void *b) +{ + const skin_t *in1 = &skins[*(const INT32 *)a]; + const skin_t *in2 = &skins[*(const INT32 *)b]; + return strcmp(in1->realname, in2->realname); +} + +static int CompareSkinSpeeds(const void *a, const void *b) +{ + const skin_t *in1 = &skins[*(const INT32 *)a]; + const skin_t *in2 = &skins[*(const INT32 *)b]; + INT32 temp = 0; + // check speed + if (in1->kartspeed < in2->kartspeed) + return -1; + else if (in2->kartspeed < in1->kartspeed) + return 1; + // then check weight + if (in1->kartweight < in2->kartweight) + return -1; + else if (in2->kartweight < in1->kartweight) + return 1; + // then check name + if ((temp = strcmp(in1->realname, in2->realname))) + return temp; + // sort by internal name + return strcmp(in1->name, in2->name); +} + +static int CompareSkinWeights(const void *a, const void *b) +{ + const skin_t *in1 = &skins[*(const INT32 *)a]; + const skin_t *in2 = &skins[*(const INT32 *)b]; + INT32 temp = 0; + // check weight + if (in1->kartweight < in2->kartweight) + return -1; + else if (in2->kartweight < in1->kartweight) + return 1; + // then check speed + if (in1->kartspeed < in2->kartspeed) + return -1; + else if (in2->kartspeed < in1->kartspeed) + return 1; + // then check name + if ((temp = strcmp(in1->realname, in2->realname))) + return temp; + // sort by internal name + return strcmp(in1->name, in2->name); +} + +static int CompareSkinAccels(const void *a, const void *b) +{ + return CompareSkinSpeeds(b, a); +} + +static int CompareSkinHandlings(const void *a, const void *b) +{ + return CompareSkinWeights(b, a); +} + +void SortSkins(void) +{ + CONS_Printf("Sorting skin list (sort type %d)...\n", cv_skinselectsort.value); + + int (*_sortingFunc)(const void *, const void *); + switch (cv_skinselectsort.value) + { + case SKINMENUSORT_NAME: + _sortingFunc = CompareSkinNames; + break; + case SKINMENUSORT_SPEED: + _sortingFunc = CompareSkinSpeeds; + break; + case SKINMENUSORT_WEIGHT: + _sortingFunc = CompareSkinWeights; + break; + case SKINMENUSORT_ACCEL: + _sortingFunc = CompareSkinAccels; + break; + case SKINMENUSORT_HANDLING: + _sortingFunc = CompareSkinHandlings; + break; + default: + _sortingFunc = CompareSkinIds; + break; + } + qsort(skinsorted, numskins, sizeof(INT32), _sortingFunc); +} + +INT32 FindSortedSkinIndex(INT32 skinnum) +{ + for (INT32 i = 0; i < numskins; i++) + { + if (skinsorted[i] == skinnum) return i; + } + return 0; +} + // returns true if available in circumstances, otherwise nope // warning don't use with an invalid skinnum other than -1 which always returns true boolean R_SkinUsable(INT32 playernum, INT32 skinnum) @@ -911,8 +1029,10 @@ next_token: HWR_AddPlayerModel(numskins); #endif + skinsorted[numskins] = numskins; numskins++; } + SortSkins(); return; } diff --git a/src/r_skins.h b/src/r_skins.h index c66456b4a..a7311ed28 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -34,6 +34,8 @@ extern "C" { #define DEFAULTSKIN3 "knuckles" // third player #define DEFAULTSKIN4 "eggman" // fourth player +extern consvar_t cv_skinselectstyle, cv_skinselectsort; + /// The skin_t struct struct skin_t { @@ -76,9 +78,21 @@ enum facepatches { NUMFACES }; +enum skinmenusortoption +{ + SKINMENUSORT_ID = 0, + SKINMENUSORT_NAME, + SKINMENUSORT_SPEED, + SKINMENUSORT_WEIGHT, + SKINMENUSORT_ACCEL, + SKINMENUSORT_HANDLING, + NUMSKINMENUSORT, +}; + /// Externs extern INT32 numskins; extern skin_t skins[MAXSKINS]; +extern INT32 skinsorted[MAXSKINS]; extern CV_PossibleValue_t Forceskin_cons_t[]; @@ -86,6 +100,8 @@ extern const UINT8 kart2spr2[26][2]; /// Function prototypes void R_InitSkins(void); +void SortSkins(void); +INT32 FindSortedSkinIndex(INT32 skinnum); void SetPlayerSkin(INT32 playernum,const char *skinname); void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002 From 5b18297c68bc6199849f0cd882b1907b4427d55b Mon Sep 17 00:00:00 2001 From: minenice55 Date: Mon, 8 Sep 2025 13:21:10 -0400 Subject: [PATCH 09/15] prefcolor sorting --- src/m_menu.c | 1 + src/r_skins.c | 21 +++++++++++++++++++++ src/r_skins.h | 1 + 3 files changed, 23 insertions(+) diff --git a/src/m_menu.c b/src/m_menu.c index a542938c6..45a903763 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -388,6 +388,7 @@ static CV_PossibleValue_t skinselectsort_cons_t[] = { {SKINMENUSORT_WEIGHT, "Weight"}, {SKINMENUSORT_ACCEL, "Accel"}, {SKINMENUSORT_HANDLING, "Handling"}, + {SKINMENUSORT_PREFCOLOR, "Preferred Colour"}, {0, NULL} }; consvar_t cv_skinselectsort = CVAR_INIT ("skinselectsort", "Order Added", CV_SAVE|CV_CALL|CV_NOINIT, skinselectsort_cons_t, Skinsort_option_Onchange); diff --git a/src/r_skins.c b/src/r_skins.c index f9ca34c40..c39d37309 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -326,6 +326,24 @@ static int CompareSkinHandlings(const void *a, const void *b) return CompareSkinWeights(b, a); } +static int CompareSkinColours(const void *a, const void *b) +{ + const skin_t *in1 = &skins[*(const INT32 *)a]; + const skin_t *in2 = &skins[*(const INT32 *)b]; + INT32 temp = 0; + + // check prefcolor + if (in1->prefcolor < in2->prefcolor) + return -1; + else if (in2->prefcolor < in1->prefcolor) + return 1; + // then check name + if ((temp = strcmp(in1->realname, in2->realname))) + return temp; + // sort by internal name + return strcmp(in1->name, in2->name); +} + void SortSkins(void) { CONS_Printf("Sorting skin list (sort type %d)...\n", cv_skinselectsort.value); @@ -348,6 +366,9 @@ void SortSkins(void) case SKINMENUSORT_HANDLING: _sortingFunc = CompareSkinHandlings; break; + case SKINMENUSORT_PREFCOLOR: + _sortingFunc = CompareSkinColours; + break; default: _sortingFunc = CompareSkinIds; break; diff --git a/src/r_skins.h b/src/r_skins.h index a7311ed28..82669bc76 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -86,6 +86,7 @@ enum skinmenusortoption SKINMENUSORT_WEIGHT, SKINMENUSORT_ACCEL, SKINMENUSORT_HANDLING, + SKINMENUSORT_PREFCOLOR, NUMSKINMENUSORT, }; From 874687e9c7ce4eaef7b8128958e032327ca71b90 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Mon, 8 Sep 2025 14:40:03 -0400 Subject: [PATCH 10/15] don't draw scrollbar if no need to scroll --- src/m_menu.c | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 45a903763..d5e2a3c73 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7093,33 +7093,36 @@ void MD_DrawGridCssSelector(void) INT32 barlen; INT32 barpos; - columncount = ((numskins - 1) / SKINGRIDWIDTH); - //draw BG V_DrawFill(x, y, dx, dy, 159); + + columncount = ((numskins - 1) / SKINGRIDWIDTH); - //draw scroll bar "back" - x += dx + 4; - V_DrawFill(x, y, scrx+2, dy, 9); - V_DrawFill(x, y, 1, dy, 10); - V_DrawFill(x, y + dy - 1, scrx+2, 1, 10); - x++; - y++; - dy -= 2; - V_DrawFill(x, y, scrx, dy, 15); - - //draw scroll bar bar - barlen = dy * SKINGRIDHEIGHT / columncount; - barpos = dy * gridcss_skinydrag / columncount; - - if (barpos + barlen > dy) + if (columncount >= SKINGRIDHEIGHT) { - barlen = dy - barpos; - } + //draw scroll bar "back" + x += dx + 4; + V_DrawFill(x, y, scrx+2, dy, 9); + V_DrawFill(x, y, 1, dy, 10); + V_DrawFill(x, y + dy - 1, scrx+2, 1, 10); + x++; + y++; + dy -= 2; + V_DrawFill(x, y, scrx, dy, 15); - V_DrawFill(x, y + barpos, scrx, barlen, 5); - V_DrawFill(x, y + barpos, 1, barlen, 7); - V_DrawFill(x, y + barpos + barlen - 1, scrx, 1, 7); + //draw scroll bar bar + barlen = dy * SKINGRIDHEIGHT / columncount; + barpos = dy * gridcss_skinydrag / columncount; + + if (barpos + barlen > dy) + { + barlen = dy - barpos; + } + + V_DrawFill(x, y + barpos, scrx, barlen, 5); + V_DrawFill(x, y + barpos, 1, barlen, 7); + V_DrawFill(x, y + barpos + barlen - 1, scrx, 1, 7); + } } // end background and scroll bar From 1ef672ab9c00d9d9e27c47e2cedf75a5e3204561 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Mon, 8 Sep 2025 19:03:46 -0400 Subject: [PATCH 11/15] disable scrollbar when skins take up less than one complete page --- src/m_menu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index d5e2a3c73..0514ba4d4 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -7096,9 +7096,9 @@ void MD_DrawGridCssSelector(void) //draw BG V_DrawFill(x, y, dx, dy, 159); - columncount = ((numskins - 1) / SKINGRIDWIDTH); + columncount = ((numskins - 1) / SKINGRIDWIDTH) + 1; - if (columncount >= SKINGRIDHEIGHT) + if (columncount > SKINGRIDHEIGHT) { //draw scroll bar "back" x += dx + 4; @@ -7114,9 +7114,9 @@ void MD_DrawGridCssSelector(void) barlen = dy * SKINGRIDHEIGHT / columncount; barpos = dy * gridcss_skinydrag / columncount; - if (barpos + barlen > dy) + if (gridcss_skinydrag >= columncount - SKINGRIDHEIGHT) { - barlen = dy - barpos; + barpos = dy - barlen; } V_DrawFill(x, y + barpos, scrx, barlen, 5); From c82557529e2a2dcb74f5fcfd8ac74292fed24e67 Mon Sep 17 00:00:00 2001 From: minenice55 Date: Tue, 9 Sep 2025 14:04:00 -0400 Subject: [PATCH 12/15] hide bar-style stat backer in grid mode --- src/m_menu.c | 25 +++++++++++++++++-------- src/m_menu.h | 1 + src/r_skins.c | 2 -- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 0514ba4d4..17e7a2eca 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -379,7 +379,7 @@ static CV_PossibleValue_t skins_cons_t[] = {{0, "MIN"}, {MAXSKINS, "MAX"}, {0, N consvar_t cv_chooseskin = CVAR_INIT ("chooseskin", "0", CV_HIDEN|CV_CALL|CV_NOINIT, skins_cons_t, Nextmap_OnChange); static CV_PossibleValue_t skinselectstyle_cons_t[] = {{0, "Bar"}, {1, "Grid"}, {0, NULL}}; -consvar_t cv_skinselectstyle = CVAR_INIT ("skinselectstyle", "Grid", CV_SAVE, skinselectstyle_cons_t, NULL); +consvar_t cv_skinselectstyle = CVAR_INIT ("skinselectstyle", "Grid", CV_SAVE|CV_CALL|CV_NOINIT, skinselectstyle_cons_t, Skinselectstyle_option_Onchange); static CV_PossibleValue_t skinselectsort_cons_t[] = { {SKINMENUSORT_ID, "Order Added"}, @@ -849,10 +849,22 @@ void Skinsort_option_Onchange(void) INT32 sortedIndex = FindSortedSkinIndex(cv_chooseskin.value); gridcss_row = sortedIndex % SKINGRIDWIDTH; gridcss_column = sortedIndex / SKINGRIDWIDTH; - + // I really need to macro this lol gridcss_skinydrag = CLAMP(gridcss_column - SKINGRIDHEIGHT + 1, 0, ((numskins - 1) / SKINGRIDWIDTH) - SKINGRIDHEIGHT - 1); } +void Skinselectstyle_option_Onchange(void) +{ + boolean visible = cv_skinselectstyle.value == 0; + M_SetItemVisible(MN_MP_PLAYERSETUP, "ACCELERATION", visible); + M_SetItemVisible(MN_MP_PLAYERSETUP, "MAXSPEED", visible); + M_SetItemVisible(MN_MP_PLAYERSETUP, "HANDLING", visible); + M_SetItemVisible(MN_MP_PLAYERSETUP, "WEIGHT", visible); + M_SetItemVisible(MN_MP_PLAYERSETUP, "ARROWLR", visible); + M_SetItemVisible(MN_MP_PLAYERSETUP, "ARROWUD", visible); + M_SetItemVisible(MN_MP_PLAYERSETUP, "STATBG", visible); +} + // ========================================================================== // END ORGANIZATION STUFF. // ========================================================================== @@ -7303,7 +7315,7 @@ INT32 MR_HandleSetupMultiPlayerMenu(INT32 choice) gridcss_column = (numskins - 1) / SKINGRIDWIDTH; } - gridcss_skinydrag = min(gridcss_column - SKINGRIDHEIGHT + 1, ((numskins - 1) / SKINGRIDWIDTH) - SKINGRIDHEIGHT + 1); + gridcss_skinydrag = CLAMP(gridcss_column - SKINGRIDHEIGHT + 1, 0, ((numskins - 1) / SKINGRIDWIDTH) - SKINGRIDHEIGHT + 1); S_StartSound(NULL, sfx_menu1); } @@ -7365,7 +7377,6 @@ static void M_GetFollowerState(void) // start the multiplayer setup menu INT32 MR_SetupMultiPlayer(INT32 arg) { - INT32 sortedIndex; if (arg < 0 || arg >= MAXSPLITSCREENPLAYERS) return false; @@ -7381,15 +7392,13 @@ INT32 MR_SetupMultiPlayer(INT32 arg) CV_SetValue(&cv_dummyfollower, cv_follower[arg].value); CV_SetValue(&cv_dummycolor, cv_playercolor[arg].value); - sortedIndex = FindSortedSkinIndex(gridcss_skinmemory); - gridcss_row = sortedIndex % SKINGRIDWIDTH; - gridcss_column = sortedIndex / SKINGRIDWIDTH; - gridcss_skinydrag = CLAMP(gridcss_column - SKINGRIDHEIGHT + 1, 0, ((numskins - 1) / SKINGRIDWIDTH) - SKINGRIDHEIGHT - 1); + Skinsort_option_Onchange(); M_GetFollowerState(); // update follower state // disable skin changes if we can't actually change skins M_SetItemDisabled(MN_MP_PLAYERSETUP, "SKIN", splitscreen >= arg && !CanChangeSkin(arg == 0 ? consoleplayer : g_localplayers[arg])); + Skinselectstyle_option_Onchange(); return true; } diff --git a/src/m_menu.h b/src/m_menu.h index 58d4a8172..c359e72fc 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -470,6 +470,7 @@ fixed_t M_GetMapThumbnail(INT16 mapnum, patch_t **out); void Moviemode_option_Onchange(void); void Skinsort_option_Onchange(void); +void Skinselectstyle_option_Onchange(void); // Player Setup menu colors linked list struct menucolor_t { diff --git a/src/r_skins.c b/src/r_skins.c index c39d37309..009a61452 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -346,8 +346,6 @@ static int CompareSkinColours(const void *a, const void *b) void SortSkins(void) { - CONS_Printf("Sorting skin list (sort type %d)...\n", cv_skinselectsort.value); - int (*_sortingFunc)(const void *, const void *); switch (cv_skinselectsort.value) { From 31cca408a25003e691f90a39ddb477d7aae4040a Mon Sep 17 00:00:00 2001 From: minenice55 Date: Tue, 9 Sep 2025 15:31:52 -0400 Subject: [PATCH 13/15] fix scroll clamping --- src/m_menu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 17e7a2eca..2c3bae11f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -850,7 +850,7 @@ void Skinsort_option_Onchange(void) gridcss_row = sortedIndex % SKINGRIDWIDTH; gridcss_column = sortedIndex / SKINGRIDWIDTH; // I really need to macro this lol - gridcss_skinydrag = CLAMP(gridcss_column - SKINGRIDHEIGHT + 1, 0, ((numskins - 1) / SKINGRIDWIDTH) - SKINGRIDHEIGHT - 1); + gridcss_skinydrag = CLAMP(gridcss_column - SKINGRIDHEIGHT + 1, 0, ((numskins - 1) / SKINGRIDWIDTH) - SKINGRIDHEIGHT + 1); } void Skinselectstyle_option_Onchange(void) @@ -863,6 +863,8 @@ void Skinselectstyle_option_Onchange(void) M_SetItemVisible(MN_MP_PLAYERSETUP, "ARROWLR", visible); M_SetItemVisible(MN_MP_PLAYERSETUP, "ARROWUD", visible); M_SetItemVisible(MN_MP_PLAYERSETUP, "STATBG", visible); + + Skinsort_option_Onchange(); } // ========================================================================== From af2bc96101a16ac8fa1e35e1bc110f048a3a643f Mon Sep 17 00:00:00 2001 From: minenice55 Date: Wed, 10 Sep 2025 23:17:26 -0400 Subject: [PATCH 14/15] implement stat bars for grid style --- src/m_menu.c | 38 ++++++++++++++++++++++++++++++++++++++ src/m_menu.h | 1 + 2 files changed, 39 insertions(+) diff --git a/src/m_menu.c b/src/m_menu.c index 2c3bae11f..658afc457 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -864,6 +864,8 @@ void Skinselectstyle_option_Onchange(void) M_SetItemVisible(MN_MP_PLAYERSETUP, "ARROWUD", visible); M_SetItemVisible(MN_MP_PLAYERSETUP, "STATBG", visible); + M_SetItemVisible(MN_MP_PLAYERSETUP, "STATBAR", !visible); + Skinsort_option_Onchange(); } @@ -6793,6 +6795,7 @@ void MD_DrawSetupMultiPlayerMenu(void) if (cv_skinselectstyle.value) { + MD_DrawCssStatBars(); MD_DrawGridCssSelector(); } else @@ -6840,6 +6843,41 @@ void MD_DrawCssStatBacker(void) V_DrawFixedPatch(((BASEVIDWIDTH - mx - 80) + ((speed-1)*8))< Date: Thu, 11 Sep 2025 16:00:50 +0200 Subject: [PATCH 15/15] Use qs22j instead of qsort --- src/r_skins.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_skins.c b/src/r_skins.c index c66368531..2fb590a1b 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -371,7 +371,7 @@ void SortSkins(void) _sortingFunc = CompareSkinIds; break; } - qsort(skinsorted, numskins, sizeof(INT32), _sortingFunc); + qs22j(skinsorted, numskins, sizeof(INT32), _sortingFunc); } INT32 FindSortedSkinIndex(INT32 skinnum)