mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-02-01 19:26:11 +00:00
rethink input mapping menu (again (again))
This commit is contained in:
parent
0ee02ce1e1
commit
d0db7e4381
5 changed files with 146 additions and 63 deletions
13
src/k_menu.h
13
src/k_menu.h
|
|
@ -228,6 +228,15 @@ extern menu_t OPTIONS_ProfilesDef;
|
|||
extern menuitem_t MAIN_Profiles[];
|
||||
extern menu_t MAIN_ProfilesDef;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
popt_profilename = 0,
|
||||
popt_profilepname,
|
||||
popt_char,
|
||||
popt_controls,
|
||||
popt_confirm,
|
||||
} popt_e;
|
||||
|
||||
extern menuitem_t OPTIONS_EditProfile[];
|
||||
extern menu_t OPTIONS_EditProfileDef;
|
||||
|
||||
|
|
@ -679,6 +688,10 @@ extern struct optionsmenu_s {
|
|||
boolean resetprofile; // After going back from the edit menu, this tells the profile select menu to kill the profile data after the transition.
|
||||
profile_t *profile; // Pointer to the profile we're editing
|
||||
|
||||
INT32 tempcontrols[num_gamecontrols][MAXINPUTMAPPING];
|
||||
// Temporary buffer where we're gonna store game controls.
|
||||
// This is only applied to the profile when you exit out of the controls menu.
|
||||
|
||||
INT16 controlscroll; // scrolling for the control menu....
|
||||
UINT8 bindcontrol; // 0: not binding, 1: binding control #1, 2: binding control #2
|
||||
INT16 bindtimer; // Timer until binding is cancelled (5s)
|
||||
|
|
|
|||
|
|
@ -2634,44 +2634,37 @@ void M_DrawEditProfile(void)
|
|||
// Draw the menu options...
|
||||
for (i = 0; i < currentMenu->numitems; i++)
|
||||
{
|
||||
switch (currentMenu->menuitems[i].status & IT_DISPLAY)
|
||||
|
||||
UINT8 *colormap = NULL;
|
||||
INT32 tflag = (currentMenu->menuitems[i].status & IT_TRANSTEXT) ? V_TRANSLUCENT : 0;
|
||||
|
||||
if (i == itemOn)
|
||||
colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_PLAGUE, GTC_CACHE);
|
||||
|
||||
// Background
|
||||
V_DrawFill(0, y, 400 - (menutransition.tics*64), 24, itemOn == i ? 169 : 30); // 169 is the plague colourization
|
||||
// Text
|
||||
V_DrawGamemodeString(x + (menutransition.tics*32), y - 6, V_ALLOWLOWERCASE|tflag, colormap, currentMenu->menuitems[i].text);
|
||||
|
||||
// Cvar specific handling
|
||||
/*switch (currentMenu->menuitems[i].status & IT_TYPE)
|
||||
{
|
||||
case IT_STRING: {
|
||||
|
||||
UINT8 *colormap = NULL;
|
||||
if (i == itemOn)
|
||||
colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_PLAGUE, GTC_CACHE);
|
||||
|
||||
// Background
|
||||
V_DrawFill(0, y, 400 - (menutransition.tics*64), 24, itemOn == i ? 169 : 30); // 169 is the plague colourization
|
||||
// Text
|
||||
V_DrawGamemodeString(x + (menutransition.tics*32), y - 6, V_ALLOWLOWERCASE, colormap, currentMenu->menuitems[i].text);
|
||||
|
||||
// Cvar specific handling
|
||||
/*switch (currentMenu->menuitems[i].status & IT_TYPE)
|
||||
case IT_CVAR:
|
||||
{
|
||||
consvar_t *cv = currentMenu->menuitems[i].itemaction.cvar;
|
||||
switch (currentMenu->menuitems[i].status & IT_CVARTYPE)
|
||||
{
|
||||
case IT_CVAR:
|
||||
{
|
||||
consvar_t *cv = currentMenu->menuitems[i].itemaction.cvar;
|
||||
switch (currentMenu->menuitems[i].status & IT_CVARTYPE)
|
||||
{
|
||||
case IT_CV_STRING:
|
||||
V_DrawFill(0, y+24, 400 - (menutransition.tics*64), 16, itemOn == i ? 169 : 30); // 169 is the plague colourization
|
||||
V_DrawString(x + 8, y + 29, V_ALLOWLOWERCASE, cv->string);
|
||||
if (skullAnimCounter < 4 && i == itemOn)
|
||||
V_DrawCharacter(x + 8 + V_StringWidth(cv->string, 0), y + 29,
|
||||
'_' | 0x80, false);
|
||||
y += 16;
|
||||
break;
|
||||
}
|
||||
case IT_CV_STRING:
|
||||
V_DrawFill(0, y+24, 400 - (menutransition.tics*64), 16, itemOn == i ? 169 : 30); // 169 is the plague colourization
|
||||
V_DrawString(x + 8, y + 29, V_ALLOWLOWERCASE, cv->string);
|
||||
if (skullAnimCounter < 4 && i == itemOn)
|
||||
V_DrawCharacter(x + 8 + V_StringWidth(cv->string, 0), y + 29, '_' | 0x80, false);
|
||||
y += 16;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}*/
|
||||
|
||||
y += 34;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
y += 34;
|
||||
}
|
||||
|
||||
// Finally, draw the card ontop
|
||||
|
|
@ -2758,20 +2751,6 @@ void M_DrawProfileControls(void)
|
|||
return; // Don't draw the rest if we're trying the controller.
|
||||
}
|
||||
|
||||
// If we're past here, draw some text warnings.
|
||||
if (gamestate == GS_MENU || PR_GetProfileNum(optionsmenu.profile) == cv_lastprofile[pid].value)
|
||||
{
|
||||
if (gamestate != GS_MENU) // If we're in a menu we'll always use the current profile to map controls from regardless.
|
||||
V_DrawCenteredThinString(229, 180, highlightflags|V_ALLOWLOWERCASE|V_6WIDTHSPACE, "This is your last used profile,");
|
||||
|
||||
V_DrawCenteredThinString(229, 190, highlightflags|V_ALLOWLOWERCASE|V_6WIDTHSPACE, "Control changes will happen in real time");
|
||||
}
|
||||
else
|
||||
{
|
||||
V_DrawCenteredThinString(229, 180, highlightflags|V_ALLOWLOWERCASE|V_6WIDTHSPACE, "This isn't your last used profile,");
|
||||
V_DrawCenteredThinString(229, 180, highlightflags|V_ALLOWLOWERCASE|V_6WIDTHSPACE, "Changes will apply on next profile selection.");
|
||||
}
|
||||
|
||||
// Tooltip
|
||||
// The text is slightly shifted hence why we don't just use M_DrawMenuTooltips()
|
||||
V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName("MENUHINT", PU_CACHE), NULL);
|
||||
|
|
@ -2841,7 +2820,7 @@ void M_DrawProfileControls(void)
|
|||
// Get userbound controls...
|
||||
for (k = 0; k < MAXINPUTMAPPING; k++)
|
||||
{
|
||||
keys[k] = optionsmenu.profile->controls[gc][k];
|
||||
keys[k] = optionsmenu.tempcontrols[gc][k];
|
||||
if (keys[k] == KEY_NULL)
|
||||
continue;
|
||||
set++;
|
||||
|
|
|
|||
100
src/k_menufunc.c
100
src/k_menufunc.c
|
|
@ -3718,10 +3718,6 @@ void M_InitOptions(INT32 choice)
|
|||
OPTIONS_MainDef.menuitems[mopt_server].status = IT_STRING | IT_TRANSTEXT;
|
||||
}
|
||||
|
||||
// disable profiles outside of gs_menu altogether.
|
||||
if (gamestate != GS_MENU)
|
||||
OPTIONS_MainDef.menuitems[mopt_profiles].status = IT_STRING | IT_TRANSTEXT;
|
||||
|
||||
M_ResetOptions();
|
||||
|
||||
// So that pause doesn't go to the main menu...
|
||||
|
|
@ -3977,6 +3973,9 @@ static void M_StartEditProfile(INT32 c)
|
|||
PR_InitNewProfile(); // initialize the new profile.
|
||||
|
||||
optionsmenu.profile = PR_GetProfile(optionsmenu.profilen);
|
||||
// copy this profile's controls into optionsmenu so that we can edit controls without changing them directly.
|
||||
// we do this so that we don't edit a profile's controls in real-time and end up doing really weird shit.
|
||||
memcpy(&optionsmenu.tempcontrols, optionsmenu.profile->controls, sizeof(gamecontroldefault));
|
||||
|
||||
// This is now used to move the card we've selected.
|
||||
optionsmenu.optx = 160;
|
||||
|
|
@ -3998,6 +3997,18 @@ static void M_StartEditProfile(INT32 c)
|
|||
CV_StealthSetValue(&cv_dummyprofilekickstart, 0); // off
|
||||
}
|
||||
|
||||
// Setup greyout and stuff.
|
||||
OPTIONS_EditProfile[popt_profilename].status = IT_STRING | IT_CVAR | IT_CV_STRING;
|
||||
OPTIONS_EditProfile[popt_profilepname].status = IT_STRING | IT_CVAR | IT_CV_STRING;
|
||||
OPTIONS_EditProfile[popt_char].status = IT_STRING | IT_CALL;
|
||||
|
||||
if (gamestate != GS_MENU) // If we're modifying things mid game, transtext some of those!
|
||||
{
|
||||
OPTIONS_EditProfile[popt_profilename].status |= IT_TRANSTEXT;
|
||||
OPTIONS_EditProfile[popt_profilepname].status |= IT_TRANSTEXT;
|
||||
OPTIONS_EditProfile[popt_char].status |= IT_TRANSTEXT;
|
||||
}
|
||||
|
||||
M_SetupNextMenu(&OPTIONS_EditProfileDef, false);
|
||||
return;
|
||||
}
|
||||
|
|
@ -4157,6 +4168,11 @@ boolean M_ProfileEditInputs(INT32 ch)
|
|||
}
|
||||
return true;
|
||||
}
|
||||
else if (M_MenuConfirmPressed(pid))
|
||||
{
|
||||
if (currentMenu->menuitems[itemOn].status & IT_TRANSTEXT)
|
||||
return true; // No.
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -4369,18 +4385,54 @@ void M_HandleProfileControls(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void M_ProfileTryControllerResponse(INT32 choice)
|
||||
{
|
||||
if (choice == MA_YES)
|
||||
{
|
||||
optionsmenu.trycontroller = TICRATE*3;
|
||||
// Apply these controls right now on P1's end.
|
||||
memcpy(&gamecontrol[0], optionsmenu.tempcontrols, sizeof(gamecontroldefault));
|
||||
}
|
||||
}
|
||||
|
||||
void M_ProfileTryController(INT32 choice)
|
||||
{
|
||||
(void) choice;
|
||||
|
||||
// I managed to softlock myself during testing lol.
|
||||
if (!optionsmenu.profile->controls[gc_x][0])
|
||||
if (!optionsmenu.tempcontrols[gc_x][0])
|
||||
{
|
||||
M_StartMessage(M_GetText("You need to bind a key to [X]\nto use this feature.\n"), NULL, MM_NOTHING);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
M_StartMessage(M_GetText("Your inputs will temporarily be\nremapped to match this Profile's settings.\nThe controller graphic will animate\nto show you what buttons are being pressed.\nIs this okay?\n\n(Press A to continue)"),
|
||||
FUNCPTRCAST(M_ProfileTryControllerResponse), MM_YESNO);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
optionsmenu.trycontroller = TICRATE*3;
|
||||
static void M_ProfileControlSaveResponse(INT32 choice)
|
||||
{
|
||||
|
||||
if (choice == MA_YES)
|
||||
{
|
||||
SINT8 belongsto = PR_ProfileUsedBy(optionsmenu.profile);
|
||||
// Save the profile
|
||||
optionsmenu.profile->kickstartaccel = cv_dummyprofilekickstart.value;
|
||||
memcpy(&optionsmenu.profile->controls, optionsmenu.tempcontrols, sizeof(gamecontroldefault));
|
||||
|
||||
// If this profile is in-use by anyone, apply the changes immediately upon exiting.
|
||||
// Don't apply the profile itself as that would lead to issues mid-game.
|
||||
if (belongsto > -1 && belongsto < MAXSPLITSCREENPLAYERS)
|
||||
{
|
||||
memcpy(&gamecontrol[belongsto], optionsmenu.tempcontrols, sizeof(gamecontroldefault));
|
||||
CV_StealthSetValue(&cv_kickstartaccel[belongsto], cv_dummyprofilekickstart.value);
|
||||
}
|
||||
|
||||
M_GoBack(0);
|
||||
}
|
||||
}
|
||||
|
||||
boolean M_ProfileControlsInputs(INT32 ch)
|
||||
|
|
@ -4396,13 +4448,21 @@ boolean M_ProfileControlsInputs(INT32 ch)
|
|||
else
|
||||
optionsmenu.trycontroller = TICRATE*3;
|
||||
|
||||
if (!optionsmenu.trycontroller)
|
||||
{
|
||||
// Reset controls to that of the current profile.
|
||||
profile_t *cpr = PR_GetProfile(cv_currprofile.value);
|
||||
memcpy(&gamecontrol[0], cpr->controls, sizeof(gamecontroldefault));
|
||||
|
||||
M_StartMessage(M_GetText("Your controls have been\nreverted to their previous state.\n\n(Press any key)"), NULL, MM_NOTHING);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (optionsmenu.bindcontrol)
|
||||
return true; // Eat all inputs there. We'll use a stupid hack in M_Responder instead.
|
||||
|
||||
SetDeviceOnPress(); // Update device constantly so that we don't stay stuck with otpions saying a device is unavailable just because we're mapping multiple devices...
|
||||
//SetDeviceOnPress(); // Update device constantly so that we don't stay stuck with otpions saying a device is unavailable just because we're mapping multiple devices...
|
||||
|
||||
if (M_MenuExtraPressed(pid))
|
||||
{
|
||||
|
|
@ -4413,7 +4473,7 @@ boolean M_ProfileControlsInputs(INT32 ch)
|
|||
INT32 i;
|
||||
|
||||
for (i = 0; i < MAXINPUTMAPPING; i++)
|
||||
optionsmenu.profile->controls[currentMenu->menuitems[itemOn].mvar1][i] = KEY_NULL;
|
||||
optionsmenu.tempcontrols[currentMenu->menuitems[itemOn].mvar1][i] = KEY_NULL;
|
||||
|
||||
S_StartSound(NULL, sfx_s3k66);
|
||||
}
|
||||
|
|
@ -4422,10 +4482,20 @@ boolean M_ProfileControlsInputs(INT32 ch)
|
|||
}
|
||||
else if (M_MenuBackPressed(pid))
|
||||
{
|
||||
|
||||
SINT8 usedby = PR_ProfileUsedBy(optionsmenu.profile);
|
||||
|
||||
if (usedby > -1)
|
||||
M_StartMessage(M_GetText(va("As this is Player %d's active Profile,\ncontrol changes will be applied \nimmediately upon exiting this menu.\nIs this okay?\n\n(Press A to confirm)", usedby+1)), FUNCPTRCAST(M_ProfileControlSaveResponse), MM_YESNO);
|
||||
else
|
||||
M_StartMessage(M_GetText("Exiting will save the control changes\nfor this Profile.\nIs this okay?\n\n(Press A to confirm)"), FUNCPTRCAST(M_ProfileControlSaveResponse), MM_YESNO);
|
||||
|
||||
optionsmenu.profile->kickstartaccel = cv_dummyprofilekickstart.value; // Make sure to save kickstart accel.
|
||||
|
||||
// Reapply player 1's real profile.
|
||||
PR_ApplyProfile(cv_lastprofile[0].value, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -4441,7 +4511,7 @@ void M_ProfileSetControl(INT32 ch)
|
|||
|
||||
for (i = 0; i < MAXINPUTMAPPING; i++)
|
||||
{
|
||||
if (optionsmenu.profile->controls[controln][i] == KEY_NULL)
|
||||
if (optionsmenu.tempcontrols[controln][i] == KEY_NULL)
|
||||
{
|
||||
optionsmenu.bindcontrol = i+1;
|
||||
break;
|
||||
|
|
@ -4465,7 +4535,7 @@ void M_MapProfileControl(event_t *ev)
|
|||
UINT8 where = n; // By default, we'll save the bind where we're supposed to map.
|
||||
INT32 i;
|
||||
|
||||
SetDeviceOnPress(); // Update cv_usejoystick
|
||||
//SetDeviceOnPress(); // Update cv_usejoystick
|
||||
|
||||
// Only consider keydown and joystick events to make sure we ignore ev_mouse and other events
|
||||
// See also G_MapEventsToControls
|
||||
|
|
@ -4572,7 +4642,7 @@ void M_MapProfileControl(event_t *ev)
|
|||
// If that's the case, simply do nothing.
|
||||
for (i = 0; i < MAXINPUTMAPPING; i++)
|
||||
{
|
||||
if (optionsmenu.profile->controls[controln][i] == c)
|
||||
if (optionsmenu.tempcontrols[controln][i] == c)
|
||||
{
|
||||
optionsmenu.bindcontrol = 0;
|
||||
return;
|
||||
|
|
@ -4582,11 +4652,13 @@ void M_MapProfileControl(event_t *ev)
|
|||
// With the way we do things, there cannot be instances of 'gaps' within the controls, so we don't need to pretend like we need to handle that.
|
||||
// Unless of course you tamper with the cfg file, but then it's *your* fault, not mine.
|
||||
|
||||
optionsmenu.profile->controls[controln][where] = c;
|
||||
optionsmenu.tempcontrols[controln][where] = c;
|
||||
optionsmenu.bindcontrol = 0; // not binding anymore
|
||||
|
||||
// If possible, reapply the profile...
|
||||
if (gamestate == GS_MENU) // In menu? Apply this to P1, no questions asked.
|
||||
// 19/05/22: Actually, no, don't do that, it just fucks everything up in too many cases.
|
||||
|
||||
/*if (gamestate == GS_MENU) // In menu? Apply this to P1, no questions asked.
|
||||
{
|
||||
// Apply the profile's properties to player 1 but keep the last profile cv to p1's ACTUAL profile to revert once we exit.
|
||||
UINT8 lastp = cv_lastprofile[0].value;
|
||||
|
|
@ -4605,7 +4677,7 @@ void M_MapProfileControl(event_t *ev)
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
#undef KEYHOLDFOR
|
||||
|
||||
|
|
|
|||
|
|
@ -198,4 +198,18 @@ UINT8 PR_GetProfileNum(profile_t *p)
|
|||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SINT8 PR_ProfileUsedBy(profile_t *p)
|
||||
{
|
||||
UINT8 i;
|
||||
UINT8 prn = PR_GetProfileNum(p);
|
||||
|
||||
for (i=0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
{
|
||||
if (prn == cv_lastprofile[i].value)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -117,4 +117,9 @@ void PR_ApplyProfile(UINT8 profilenum, UINT8 playernum);
|
|||
// Gets the profile's index # in profilesList
|
||||
UINT8 PR_GetProfileNum(profile_t *p);
|
||||
|
||||
// PR_ProfileUsedBy(profile_t *p)
|
||||
// Returns the player # this profile is used by (if any)
|
||||
// If the profile belongs to no player, then this returns -1
|
||||
SINT8 PR_ProfileUsedBy(profile_t *p);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue