Skip to content

Commit

Permalink
Control sliders via mouse cursor
Browse files Browse the repository at this point in the history
Control via arrows and mouse wheel is still possible as well.

Co-Authored-By: Polina "Aura" N. <185700473+pvictress@users.noreply.github.com>
  • Loading branch information
JNechaevsky and pvictress committed Jan 11, 2025
1 parent 696c524 commit d182d43
Show file tree
Hide file tree
Showing 5 changed files with 296 additions and 152 deletions.
142 changes: 94 additions & 48 deletions src/doom/m_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,7 @@ typedef struct menu_s
#define M_SKIP -1,0 // Skippable, cursor can't get here.
#define M_SWTC 1,0 // On/off type or entering function.
#define M_LFRT 2,0 // Multichoice function.
#define M_SLD1 3,0 // Slider 1st line.
#define M_SLD2 4,0 // Slider 2st line.
#define M_SLDR 3,0 // Slider line.

// [JN] Small cursor timer for glowing effect.
static short cursor_tics = 0;
Expand Down Expand Up @@ -250,6 +249,7 @@ static int M_StringHeight(const char *string);
static void M_StartMessage(const char *string, void (*routine)(int), boolean input);
static void M_ClearMenus (void);

static void M_ID_HandleSliderMouseControl (int x, int y, int width, void *value, boolean is_float, float min, float max);

// =============================================================================
// DOOM MENU
Expand Down Expand Up @@ -431,10 +431,10 @@ enum

static menuitem_t SoundMenu[]=
{
{ M_LFRT, "M_SFXVOL", M_SfxVol, 's' },
{ M_SLD1, "", 0, '\0' },
{ M_LFRT, "M_MUSVOL", M_MusicVol, 'm' },
{ M_SLD1, "", 0, '\0' }
{ M_SLDR, "M_SFXVOL", M_SfxVol, 's' },
{ M_SKIP, "", 0, '\0' },
{ M_SLDR, "M_MUSVOL", M_MusicVol, 'm' },
{ M_SKIP, "", 0, '\0' }
};

static menu_t SoundDef =
Expand Down Expand Up @@ -1188,7 +1188,8 @@ static byte *M_SaveLoad_Glow (int itemSetOn, int tics, int type)
static const int M_INT_Slider (int val, int min, int max, int direction, boolean capped)
{
// [PN] Adjust the slider value based on direction and handle min/max limits
val += (direction == 0) ? -1 : 1;
val += (direction == -1) ? 0 : // [JN] Routine "-1" just reintializes value.
(direction == 0) ? -1 : 1; // Otherwise, move either left "0" or right "1".

if (val < min)
val = capped ? min : max;
Expand Down Expand Up @@ -1875,12 +1876,12 @@ static void M_ID_LocalTime (int choice)

static menuitem_t ID_Menu_Sound[]=
{
{ M_LFRT, "SFX VOLUME", M_SfxVol, 's' },
{ M_SLD1, "", 0, '\0' },
{ M_SLD2, "", 0, '\0' },
{ M_LFRT, "MUSIC VOLUME", M_MusicVol, 'm' },
{ M_SLD1, "", 0, '\0' },
{ M_SLD2, "", 0, '\0' },
{ M_SLDR, "SFX VOLUME", M_SfxVol, 's' },
{ M_SKIP, "", 0, '\0' },
{ M_SKIP, "", 0, '\0' },
{ M_SLDR, "MUSIC VOLUME", M_MusicVol, 'm' },
{ M_SKIP, "", 0, '\0' },
{ M_SKIP, "", 0, '\0' },
{ M_SKIP, "", 0, '\0' },
{ M_LFRT, "SFX PLAYBACK", M_ID_SFXSystem, 's' },
{ M_LFRT, "MUSIC PLAYBACK", M_ID_MusicSystem, 'm' },
Expand Down Expand Up @@ -1915,10 +1916,12 @@ static void M_Draw_ID_Sound (void)
M_WriteTextCentered(9, "VOLUME", cr[CR_YELLOW]);

M_DrawThermo(46, 27, 16, sfxVolume, 0);
M_ID_HandleSliderMouseControl(52, 27, 132, &sfxVolume, false, 0, 15);
sprintf(str,"%d", sfxVolume);
M_WriteText (192, 30, str, M_Item_Glow(0, GLOW_UNCOLORED));

M_DrawThermo(46, 54, 16, musicVolume, 3);
M_ID_HandleSliderMouseControl(52, 54, 132, &musicVolume, false, 0, 15);
sprintf(str,"%d", musicVolume);
M_WriteText (192, 57, str, M_Item_Glow(3, GLOW_UNCOLORED));

Expand Down Expand Up @@ -2168,15 +2171,15 @@ static menuitem_t ID_Menu_Controls[]=
{ M_SWTC, "KEYBOARD BINDINGS", M_Choose_ID_Keybinds, 'k' },
{ M_SWTC, "MOUSE BINDINGS", M_Choose_ID_MouseBinds, 'm' },
{ M_SKIP, "", 0, '\0' },
{ M_LFRT, "SENSIVITY", M_ID_Controls_Sensivity, 's' },
{ M_SLD1, "", 0, '\0' },
{ M_SLD2, "", 0, '\0' },
{ M_LFRT, "ACCELERATION", M_ID_Controls_Acceleration, 'a' },
{ M_SLD1, "", 0, '\0' },
{ M_SLD2, "", 0, '\0' },
{ M_LFRT, "ACCELERATION THRESHOLD", M_ID_Controls_Threshold, 'a' },
{ M_SLD1, "", 0, '\0' },
{ M_SLD2, "", 0, '\0' },
{ M_SLDR, "SENSIVITY", M_ID_Controls_Sensivity, 's' },
{ M_SKIP, "", 0, '\0' },
{ M_SKIP, "", 0, '\0' },
{ M_SLDR, "ACCELERATION", M_ID_Controls_Acceleration, 'a' },
{ M_SKIP, "", 0, '\0' },
{ M_SKIP, "", 0, '\0' },
{ M_SLDR, "ACCELERATION THRESHOLD", M_ID_Controls_Threshold, 'a' },
{ M_SKIP, "", 0, '\0' },
{ M_SKIP, "", 0, '\0' },
{ M_LFRT, "MOUSE LOOK", M_ID_Controls_MLook, 'm' },
{ M_LFRT, "VERTICAL MOUSE MOVEMENT", M_ID_Controls_NoVert, 'v' },
{ M_LFRT, "INVERT VERTICAL AXIS", M_ID_Controls_InvertY, 'v' },
Expand Down Expand Up @@ -2207,16 +2210,19 @@ static void M_Draw_ID_Controls (void)

M_WriteTextCentered(36, "MOUSE CONFIGURATION", cr[CR_YELLOW]);

M_DrawThermo(46, 54, 10, mouseSensitivity, 3);
M_DrawThermo(46, 54, 15, mouseSensitivity, 3);
M_ID_HandleSliderMouseControl(52, 54, 124, &mouseSensitivity, false, 0, 14);
sprintf(str,"%d", mouseSensitivity);
M_WriteText (144, 57, str, M_Item_Glow(3, mouseSensitivity == 255 ? GLOW_YELLOW :
mouseSensitivity > 9 ? GLOW_GREEN : GLOW_UNCOLORED));
M_WriteText (184, 57, str, M_Item_Glow(3, mouseSensitivity == 255 ? GLOW_YELLOW :
mouseSensitivity > 14 ? GLOW_GREEN : GLOW_UNCOLORED));

M_DrawThermo(46, 81, 12, (mouse_acceleration * 3) - 3, 6);
M_DrawThermo(46, 81, 8, (mouse_acceleration * 1.8f) - 2, 6);
M_ID_HandleSliderMouseControl(52, 81, 100, &mouse_acceleration, true, 0, 9);
sprintf(str,"%.1f", mouse_acceleration);
M_WriteText (160, 84, str, M_Item_Glow(6, GLOW_UNCOLORED));
M_WriteText (128, 84, str, M_Item_Glow(6, GLOW_UNCOLORED));

M_DrawThermo(46, 108, 15, mouse_threshold / 2, 9);
M_DrawThermo(46, 108, 15, mouse_threshold / 2.2f, 9);
M_ID_HandleSliderMouseControl(52, 108, 124, &mouse_threshold, false, 0, 32);
sprintf(str,"%d", mouse_threshold);
M_WriteText (184, 111, str, M_Item_Glow(9, GLOW_UNCOLORED));

Expand Down Expand Up @@ -5222,10 +5228,12 @@ static void M_DrawSound(void)
V_DrawShadowedPatchOptional(60, 38, 0, W_CacheLumpName(DEH_String("M_SVOL"), PU_CACHE));

M_DrawThermo(SoundDef.x, SoundDef.y + LINEHEIGHT * (sfx_vol + 1), 16, sfxVolume, 0);
M_ID_HandleSliderMouseControl(86, 80, 132, &sfxVolume, false, 0, 15);
sprintf(str,"%d", sfxVolume);
M_WriteText (226, 83, str, M_Item_Glow(0, sfxVolume ? GLOW_UNCOLORED : GLOW_DARKRED));

M_DrawThermo(SoundDef.x, SoundDef.y + LINEHEIGHT * (music_vol + 1), 16, musicVolume, 2);
M_ID_HandleSliderMouseControl(86, 112, 132, &musicVolume, false, 0, 15);
sprintf(str,"%d", musicVolume);
M_WriteText (226, 115, str, M_Item_Glow(2, musicVolume ? GLOW_UNCOLORED : GLOW_DARKRED));
}
Expand Down Expand Up @@ -5996,10 +6004,12 @@ boolean M_Responder (event_t* ev)
{
// [JN] Shows the mouse cursor when moved.
if (ev->data2 || ev->data3)
{
menu_mouse_allow = true;
menu_mouse_allow_click = false;
}

if (ev->type == ev_mouse && mousewait < I_GetTime()
&& !ev->data2 && !ev->data3) // [JN] Do not consider movement as pressing.
if (ev->type == ev_mouse && mousewait < I_GetTime())
{
// [crispy] mouse_novert disables controlling the menus with the mouse
// [JN] Not needed, as menu is fully controllable by mouse wheel and buttons.
Expand Down Expand Up @@ -6053,6 +6063,14 @@ boolean M_Responder (event_t* ev)

if (ev->data1&1)
{
if (menuactive && currentMenu->menuitems[itemOn].status == 3)
{
// [JN] Allow repetitive on sliders to move it while mouse movement.
menu_mouse_allow_click = true;
}
else
if (!ev->data2 && !ev->data3) // [JN] Do not consider movement as pressing.
{
if (!menuactive && !usergame)
{
M_StartControlPanel(); // [JN] Open the main menu if the game is not active.
Expand All @@ -6068,8 +6086,10 @@ boolean M_Responder (event_t* ev)
}
mousewait = I_GetTime() + 1;
}
}

if (ev->data1&2)
if (ev->data1&2
&& !ev->data2 && !ev->data3) // [JN] Do not consider movement as pressing.
{
if (!menuactive && !usergame)
{
Expand Down Expand Up @@ -6097,7 +6117,7 @@ boolean M_Responder (event_t* ev)
// [JN] Scrolls through menu item values or navigates between pages.
if (ev->data1 & (1 << 4) && menuactive)
{
if (currentMenu->menuitems[itemOn].status == 2)
if (currentMenu->menuitems[itemOn].status > 1)
{
// Scroll menu item backward
currentMenu->menuitems[itemOn].routine(0);
Expand All @@ -6113,7 +6133,7 @@ boolean M_Responder (event_t* ev)
else
if (ev->data1 & (1 << 3) && menuactive)
{
if (currentMenu->menuitems[itemOn].status == 2)
if (currentMenu->menuitems[itemOn].status > 1)
{
// Scroll menu item forward
currentMenu->menuitems[itemOn].routine(1);
Expand Down Expand Up @@ -6463,9 +6483,7 @@ boolean M_Responder (event_t* ev)
do
{
itemOn = (itemOn + 1) % currentMenu->numitems;
} while (currentMenu->menuitems[itemOn].status == -1 ||
currentMenu->menuitems[itemOn].status == 3 || // [JN] Skip sliders
currentMenu->menuitems[itemOn].status == 4);
} while (currentMenu->menuitems[itemOn].status == -1);

S_StartSound(NULL, sfx_pstop);
return true;
Expand All @@ -6476,9 +6494,7 @@ boolean M_Responder (event_t* ev)
do
{
itemOn = (itemOn == 0) ? currentMenu->numitems - 1 : itemOn - 1;
} while (currentMenu->menuitems[itemOn].status == -1 ||
currentMenu->menuitems[itemOn].status == 3 || // [JN] Skip sliders
currentMenu->menuitems[itemOn].status == 4);
} while (currentMenu->menuitems[itemOn].status == -1);

S_StartSound(NULL, sfx_pstop);
return true;
Expand All @@ -6493,7 +6509,7 @@ boolean M_Responder (event_t* ev)

// Slide slider left
if (currentMenu->menuitems[itemOn].routine
&& currentMenu->menuitems[itemOn].status == 2)
&& currentMenu->menuitems[itemOn].status > 1)
{
S_StartSound(NULL,sfx_stnmov);
currentMenu->menuitems[itemOn].routine(0);
Expand All @@ -6510,7 +6526,7 @@ boolean M_Responder (event_t* ev)

// Slide slider right
if (currentMenu->menuitems[itemOn].routine
&& currentMenu->menuitems[itemOn].status == 2)
&& currentMenu->menuitems[itemOn].status > 1)
{
S_StartSound(NULL,sfx_stnmov);
currentMenu->menuitems[itemOn].routine(1);
Expand Down Expand Up @@ -6689,25 +6705,55 @@ static void M_ID_MenuMouseControl (void)
// [PN] Check if the cursor is hovering over a menu item
for (int i = 0; i < currentMenu->numitems; i++)
{
// [JN] Slider takes three lines.
const int line_item = currentMenu->menuitems[i].status == 3 ? 3 : 1;

if (menu_mouse_x >= (currentMenu->x + WIDESCREENDELTA) * vid_resolution
&& menu_mouse_x <= (ORIGWIDTH + WIDESCREENDELTA - currentMenu->x) * vid_resolution
&& menu_mouse_y >= (currentMenu->y + i * line_height) * vid_resolution
&& menu_mouse_y <= (currentMenu->y + (i + 1) * line_height) * vid_resolution
&& menu_mouse_y <= (currentMenu->y + (i + line_item) * line_height) * vid_resolution
&& currentMenu->menuitems[i].status != -1)
{
// [PN] Highlight the current menu item
itemOn = i;

// [JN] Move menu cursor higher when hovering slider lines.
if (currentMenu->menuitems[itemOn].status == 3)
itemOn -= 1;
if (currentMenu->menuitems[itemOn].status == 4)
itemOn -= 2;
}
}
}
}

static void M_ID_HandleSliderMouseControl (int x, int y, int width, void *value, boolean is_float, float min, float max)
{
if (!menu_mouse_allow_click)
return;

// [JN/PN] Adjust slider boundaries
const int adj_x = (x + WIDESCREENDELTA) * vid_resolution;
const int adj_y = y * vid_resolution;
const int adj_width = width * vid_resolution;
const int adj_height = LINEHEIGHT * vid_resolution;

// [PN] Check cursor position and item status
if (menu_mouse_x < adj_x || menu_mouse_x > adj_x + adj_width
|| menu_mouse_y < adj_y || menu_mouse_y > adj_y + adj_height
|| currentMenu->menuitems[itemOn].status != 3)
return;

// [PN] Calculate and update slider value
const float normalized = (float)(menu_mouse_x - adj_x + 5) / adj_width;
const float newValue = min + normalized * (max - min);
if (is_float)
*((float *)value) = newValue;
else
*((int *)value) = (int)newValue;

// [JN/PN] Call related routine and reset mouse click allowance
currentMenu->menuitems[itemOn].routine(-1);
menu_mouse_allow_click = false;

// Play sound
S_StartSound(NULL, sfx_stnmov);
}

//
// M_Drawer
// Called after the view has been rendered,
Expand Down
Loading

0 comments on commit d182d43

Please sign in to comment.