Three(!?) new methods for placing menu items

Relative: changes the coordinates relative to the current ones
Temporary relative: displaces the coordinates temporarily
Overlay: draws at absolute coordinates, no clipping

Along with custom cursor offsets and Item Styles(tm), this eliminates
M_DrawControl
This commit is contained in:
GenericHeroGuy 2025-06-12 16:49:50 +02:00
parent fd48ecd4ca
commit f30ddcfad2
4 changed files with 114 additions and 55 deletions

View file

@ -1908,10 +1908,28 @@ static void readmenuitem(MYFILE *f, menuitem_t *menuitem)
{
menuitem->x = get_number(word2);
}
else if (fastcmp(word, "OFSX"))
{
menuitem->x = get_number(word2);
status |= IT_OFSX;
}
else if (fastcmp(word, "Y"))
{
menuitem->y = get_number(word2);
}
else if (fastcmp(word, "OFSY"))
{
menuitem->y = get_number(word2);
status |= IT_OFSY;
}
else if (fastcmp(word, "OVERLAY"))
{
status |= IT_OVERLAY;
}
else if (fastcmp(word, "TEMPOFFSET"))
{
status |= IT_TEMPORARY;
}
else if (fastcmp(word, "ARGUMENT"))
{
menuitem->argument = get_number(word2);
@ -1924,6 +1942,13 @@ static void readmenuitem(MYFILE *f, menuitem_t *menuitem)
{
menuitem->tooltip = Z_StrDup(word2);
}
else if (fastcmp(word, "STYLE"))
{
if (fasticmp(word2, "CENTER"))
status |= IT_CENTER;
else
WARN("unknown style '%s'", word2);
}
else if (fastncmp(word, "TEXT", 4))
{
UINT16 flags = IT_STRING;
@ -1952,8 +1977,8 @@ static void readmenuitem(MYFILE *f, menuitem_t *menuitem)
flags |= IT_CV_SLIDER;
else if (fastcmp(word+4, "STRING"))
flags |= IT_CV_STRING;
else if (fastcmp(word+4, "INTEGER"))
flags |= IT_CV_INTEGERSTEP;
//else if (fastcmp(word+4, "INTEGER"))
//flags |= IT_CV_INTEGERSTEP;
else if (word[4])
{
WARN("unknown word '%s'", word);
@ -1984,7 +2009,6 @@ static void readmenuitem(MYFILE *f, menuitem_t *menuitem)
WARN("unknown menu '%s'", word2);
continue;
}
status |= IT_SUBMENU;
menuitem->submenu = mn;
}
else if (fastcmp(word, "CALL") || fastcmp(word, "ARROWS"))
@ -2256,6 +2280,14 @@ void readmenu(MYFILE *f, INT32 num)
{
menudef->scrollheight = get_number(word2);
}
else if (fastcmp(word, "CURSOROFFSET"))
{
menudef->cursoroffset = get_number(word2);
}
else if (fastcmp(word, "LINEHEIGHT"))
{
menudef->lineheight = get_number(word2);
}
else if (fastcmp(word, "ENTERROUTINE"))
{
menufunc_f *routine = get_menuroutine(word2);
@ -2291,6 +2323,10 @@ void readmenu(MYFILE *f, INT32 num)
}
} while (!myfeof(f)); // finish when the line is empty
// default line height
if (!menudef->lineheight)
menudef->lineheight = 8;
Z_Free(s);
}
#undef WARN

View file

@ -772,7 +772,6 @@ struct menu_drawer_s const MENU_DRAWERS[] = {
{ "DRAWPLAYBACKMENU", &M_DrawPlaybackMenu },
{ "DRAWIMAGEDEF", &M_DrawImageDef },
{ "DRAWMUSICTEST", &M_DrawMusicTest },
{ "DRAWCONTROL", &M_DrawControl },
{ "DRAWJOYSTICK", &M_DrawJoystick },
{ "DRAWMONITORTOGGLES", &M_DrawMonitorToggles },
{ "DRAWCONNECTMENU", &M_DrawConnectMenu },

View file

@ -102,7 +102,6 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
#include "qs22j.h"
#define LINEHEIGHT 8
#define SLIDER_RANGE 10
#define SLIDER_WIDTH (8*SLIDER_RANGE+6)
#define MAXIPADDRESSLEN 28
@ -283,7 +282,7 @@ static void M_ChangeItemStatus(menutype_t type, const char *name, UINT16 flag, b
static boolean M_ItemSelectable(menuitem_t *item)
{
return !(item->status & (IT_HIDDEN|IT_GRAYEDOUT|IT_SECRET)) && (item->status & IT_TYPE);
return !(item->status & (IT_HIDDEN|IT_GRAYEDOUT|IT_SECRET)) && (item->submenu || item->routine || item->cvar);
}
// bruh...
@ -832,14 +831,14 @@ static INT32 M_ChangeCvar(INT32 choice)
}
else if (cv->flags & CV_FLOAT)
{
if (!(currentMenu->menuitems[itemOn].status & IT_CV_INTEGERSTEP))
/*if (!(currentMenu->menuitems[itemOn].status & IT_CV_INTEGERSTEP))
{
char s[20];
float n = FIXED_TO_FLOAT(cv->value)+(choice)*(1.0f/16.0f);
sprintf(s,"%ld%s",(long)n,M_Ftrim(n));
CV_Set(cv,s);
}
else
else*/
CV_SetValue(cv,FIXED_TO_FLOAT(cv->value)+(choice));
}
else
@ -2102,7 +2101,7 @@ static INT16 M_DrawMenuItem(menuitem_t *item, INT16 x, INT16 y, INT32 vflags, bo
break;
case IT_STRING:
case IT_WHITESTRING:
if (vflags & MDF_CENTERED)
if (vflags & MDF_CENTERED || item->status & IT_CENTER)
V_DrawCenteredString(x, y, vflags|highlight, string);
else
V_DrawString(x, y, vflags|highlight, string);
@ -2225,7 +2224,7 @@ static INT16 M_DrawMenuItem(menuitem_t *item, INT16 x, INT16 y, INT32 vflags, bo
}
break;
case IT_HEADERTEXT: // draws 16 pixels to the left, in yellow text
V_DrawString(x - (vflags & MDF_CONTROLS ? 7 : 16), y - (vflags & MDF_CONTROLS ? 2 : 0), vflags|highlight, string);
V_DrawString(x - 16, y, vflags|highlight, string);
break;
default:
break;
@ -2234,12 +2233,22 @@ static INT16 M_DrawMenuItem(menuitem_t *item, INT16 x, INT16 y, INT32 vflags, bo
return V_StringWidth(string, vflags);
}
// gets the absolute Y coordinate where this menuitem should be drawn (in a broken way)
// TODO: merge this with the actual drawing loop somehow
static INT16 getheight(INT16 index)
{
// gotta skip overlay items...
INT16 i = 0;
while (index + i < currentMenu->numitems && currentMenu->menuitems[index + i].status & IT_OVERLAY)
i++;
index += i;
if (index >= currentMenu->numitems)
return 0;
INT16 y = currentMenu->menuitems[index].y;
if (!y) for (INT16 i = 0; i < index; i++)
if (!(currentMenu->menuitems[i].status & IT_HIDDEN))
y += 8;
if (!y) while (i < index)
if (!(currentMenu->menuitems[i++].status & (IT_HIDDEN|IT_OVERLAY)))
y += currentMenu->lineheight;
return y;
}
@ -2249,6 +2258,8 @@ static void M_DrawBaseMenu(INT32 flags)
INT16 scrollheight = currentMenu->scrollheight;
if (!scrollheight)
scrollheight = INT16_MAX;
if (!currentMenu->numitems)
return;
INT16 topy = getheight(0);
INT16 boty = getheight(currentMenu->numitems-1);
@ -2275,48 +2286,68 @@ static void M_DrawBaseMenu(INT32 flags)
for (i = 0; i < currentMenu->numitems; i++)
{
INT16 dx, dy;
INT32 vflags = flags;
menuitem_t *item = &currentMenu->menuitems[i];
if (currentMenu->menuitems[i].status & IT_HIDDEN)
{
if (!(vflags & MDF_CONTROLS)) // don't leave gaps when buttons are hidden for P2/P3/P4
y += LINEHEIGHT;
if (item->status & IT_HIDDEN)
continue;
if (item->status & IT_OVERLAY)
{
// draw at absolute coordinates; no clipping needed
dx = item->x;
dy = item->y;
}
else
{
dx = x + item->x;
if (item->x)
{
if (!(item->status & IT_OFSX))
x = dx = item->x + scrollx;
else if (!(item->status & IT_TEMPORARY))
x = dx;
}
dy = y + item->y;
if (item->y)
{
if (!(item->status & IT_OFSY))
y = dy = item->y + scrolly;
else if (!(item->status & IT_TEMPORARY))
y = dy;
}
if (dy < currentMenu->y)
{
cliptop = true;
goto nodraw;
}
else if (dy > currentMenu->y + scrollheight)
{
clipbot = true;
goto nodraw;
}
}
if (currentMenu->menuitems[i].y)
y = currentMenu->menuitems[i].y + scrolly;
if (currentMenu->menuitems[i].x)
x = currentMenu->menuitems[i].x + scrollx;
if (y < currentMenu->y)
{
cliptop = true;
y += LINEHEIGHT;
continue;
}
else if (y > currentMenu->y + scrollheight)
{
clipbot = true;
y += LINEHEIGHT;
continue;
}
w = M_DrawMenuItem(&currentMenu->menuitems[i], x, y, vflags, i == itemOn);
w = M_DrawMenuItem(item, dx, dy, vflags, i == itemOn);
if (i == itemOn)
{
cursory = y;
cursorx = x - (vflags & MDF_CENTERED ? w/2 : 0) - (vflags & MDF_CONTROLS ? 18 : 24);
cursorx = x - (vflags & MDF_CENTERED ? w/2 : 0) - 24 + currentMenu->cursoroffset;
}
y += LINEHEIGHT;
nodraw:
if (!(item->status & IT_OVERLAY))
y += currentMenu->lineheight;
}
// DRAW THE SKULL CURSOR
V_DrawScaledPatch(cursorx, cursory, 0, W_CachePatchName("M_CURSOR", PU_CACHE));
x = currentMenu->x - (flags & MDF_CONTROLS ? 16 : 20);
x = currentMenu->x - 20 + currentMenu->cursoroffset;
if (cliptop)
V_DrawCharacter(x, currentMenu->y - (skullAnimCounter/5), '\x1A' | highlightflags, false); // up arrow
if (clipbot)
@ -3963,7 +3994,7 @@ void M_DrawPlaybackMenu(void)
V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y + 18, transmap|V_SNAPTOTOP|V_ALLOWLOWERCASE, currentMenu->menuitems[i].text);
if ((currentMenu->menuitems[i].status & IT_TYPE) == IT_ARROWS)
if (currentMenu->menuitems[i].status & IT_ARROWS)
{
char *str = NULL;
@ -6999,16 +7030,6 @@ INT32 MR_HandleControlsMenu(INT32 ch)
return true;
}
// Draws the Customise Controls menu
void M_DrawControl(void)
{
M_CentreText(28,
(setupcontrolplayer > 1 ? va("\x86""Set controls for ""\x82""Player %d", setupcontrolplayer) :
"\x86""Press ""\x82""ENTER""\x86"" to change, ""\x82""BACKSPACE""\x86"" to clear"));
M_DrawBaseMenu(MDF_CONTROLS|MENUCAPS);
}
static INT32 controltochange;
static char controltochangetext[33];

View file

@ -157,10 +157,9 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt);
// flags for items in the menu
// menu handle (what we do when key is pressed
#define IT_TYPE (1+2+4+8192)
#define IT_CALL 1 // call the function
#define IT_ARROWS 2 // call function with 0 for left arrow and 1 for right arrow in param
#define IT_SUBMENU 4 // go to sub menu
//#define IT_SUBMENU 4 // go to sub menu
#define IT_CVAR 8192 // handle as a cvar
// display flags
@ -176,18 +175,21 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt);
//consvar specific
#define IT_CV_SLIDER 64
#define IT_CV_STRING 128
#define IT_CV_INTEGERSTEP 256 // if cvar is CV_FLOAT, modify it by 1 instead of 0.0625
//#define IT_CV_INTEGERSTEP 256 // if cvar is CV_FLOAT, modify it by 1 instead of 0.0625
// extra flags
#define IT_CENTER 512 // if IT_PATCH, center it on screen
#define IT_HIDDEN 1024 // invisible, unselectable
#define IT_GRAYEDOUT 2048 // grayed out, unselectable
#define IT_SECRET 4096 // ??????? ????????????
#define IT_OFSX 16384 // x coordinate is relative
#define IT_OFSY 32768 // ditto
#define IT_TEMPORARY 4 // offset is only applied temporarily
#define IT_OVERLAY 256 // no scrolling, draw at absolute coordinates
// carefully chosen to not conflict with V_ flags
#define MDF_CENTERED 0x20
#define MDF_TIMEATTACK 0x40
#define MDF_CONTROLS 0x80
#define MAXSTRINGLENGTH 32
@ -226,6 +228,8 @@ struct menu_t
INT16 x, y; // x, y of menu
INT16 scrollheight; // height of scrolling area
INT16 lastOn; // last item user was on in menu
INT16 cursoroffset; // X offset of cursor
INT16 lineheight; // default Y offset to add for each item
menufunc_f *enterroutine; // called before enter a menu
menufunc_f *quitroutine; // called before quit a menu
menufunc_f *keyhandler; // called before key press is processed
@ -333,7 +337,6 @@ void M_DrawReplayStartMenu(void);
void M_DrawPlaybackMenu(void);
void M_DrawImageDef(void);
void M_DrawMusicTest(void);
void M_DrawControl(void);
void M_DrawJoystick(void);
void M_DrawMonitorToggles(void);
#ifdef HAVE_DISCORDRPC