Browse Source

Implement settings menu for gamepad customization

pull/5542/head
staphen 3 years ago committed by Anders Jenbo
parent
commit
f17ea8db98
  1. 2
      CMake/Assets.cmake
  2. BIN
      Packaging/resources/assets/fonts/24-e0.bin
  3. BIN
      Packaging/resources/assets/fonts/24-e0.clx
  4. 122
      Source/DiabloUI/settingsmenu.cpp
  5. 190
      Source/controls/controller_buttons.cpp
  6. 15
      Source/controls/controller_buttons.h
  7. 6
      Source/controls/devices/game_controller.cpp
  8. 46
      Source/options.cpp
  9. 6
      Source/options.h

2
CMake/Assets.cmake

@ -111,6 +111,8 @@ set(devilutionx_assets
fonts/24-20.bin
fonts/24-20.clx
fonts/24-26.clx
fonts/24-e0.bin
fonts/24-e0.clx
fonts/30-00.bin
fonts/30-00.clx
fonts/30-01.bin

BIN
Packaging/resources/assets/fonts/24-e0.bin

Binary file not shown.

BIN
Packaging/resources/assets/fonts/24-e0.clx

Binary file not shown.

122
Source/DiabloUI/settingsmenu.cpp

@ -5,6 +5,8 @@
#include "DiabloUI/diabloui.h"
#include "DiabloUI/scrollbar.h"
#include "control.h"
#include "controls/controller_motion.h"
#include "controls/plrctrls.h"
#include "controls/remap_keyboard.h"
#include "engine/render/text_render.hpp"
#include "hwcursor.hpp"
@ -17,7 +19,8 @@
namespace devilution {
namespace {
constexpr size_t IndexKeyInput = 1;
constexpr size_t IndexKeyOrPadInput = 1;
constexpr size_t IndexPadTimerText = 2;
bool endMenu = false;
bool backToMain = false;
@ -31,6 +34,7 @@ enum class ShownMenuType : uint8_t {
Settings,
ListOption,
KeyInput,
PadInput,
};
ShownMenuType shownMenu;
@ -44,8 +48,14 @@ enum class SpecialMenuEntry : int8_t {
None = -1,
PreviousMenu = -2,
UnbindKey = -3,
BindPadButton = -4,
UnbindPadButton = -5,
};
ControllerButtonCombo padEntryCombo {};
Uint32 padEntryStartTime = 0;
std::string padEntryTimerText;
bool IsValidEntry(OptionEntryBase *pOptionEntry)
{
auto flags = pOptionEntry->GetFlags();
@ -90,6 +100,41 @@ void GoBackOneMenuLevel()
shownMenu = ShownMenuType::Settings;
}
void StartPadEntryTimer()
{
padEntryCombo = ControllerButton_NONE;
padEntryStartTime = SDL_GetTicks();
if (padEntryStartTime == 0)
padEntryStartTime++;
// Removes access to these dialog items while entering bindings
for (size_t i = IndexPadTimerText + 1; i < vecDialogItems.size(); i++)
vecDialogItems[i]->uiFlags |= UiFlags::ElementHidden;
}
void StopPadEntryTimer()
{
padEntryCombo = ControllerButton_NONE;
padEntryStartTime = 0;
padEntryTimerText = "";
vecDialogItems[IndexPadTimerText]->m_text = padEntryTimerText;
// Restores access to these dialog items after binding is complete
for (size_t i = IndexPadTimerText + 1; i < vecDialogItems.size(); i++)
vecDialogItems[i]->uiFlags &= ~UiFlags::ElementHidden;
}
void UpdatePadEntryTimerText()
{
if (shownMenu != ShownMenuType::PadInput)
return;
Uint32 elapsed = SDL_GetTicks() - padEntryStartTime;
if (padEntryStartTime == 0 || elapsed > 10000) {
StopPadEntryTimer();
return;
}
padEntryTimerText = StrCat(_("Press gamepad buttons to change."), " ", 10 - elapsed / 1000);
vecDialogItems[IndexPadTimerText]->m_text = padEntryTimerText;
}
void UpdateDescription(const OptionEntryBase &option)
{
auto paragraphs = WordWrapString(option.GetDescription(), rectDescription.size.width, GameFont12, 1);
@ -159,10 +204,19 @@ void ItemSelected(int value)
case SpecialMenuEntry::PreviousMenu:
GoBackOneMenuLevel();
break;
case SpecialMenuEntry::UnbindKey:
case SpecialMenuEntry::UnbindKey: {
auto *pOptionKey = static_cast<KeymapperOptions::Action *>(selectedOption);
pOptionKey->SetValue(SDLK_UNKNOWN);
vecDialogItems[IndexKeyInput]->m_text = selectedOption->GetValueDescription().data();
vecDialogItems[IndexKeyOrPadInput]->m_text = selectedOption->GetValueDescription().data();
break;
}
case SpecialMenuEntry::BindPadButton:
StartPadEntryTimer();
break;
case SpecialMenuEntry::UnbindPadButton:
auto *pOptionPad = static_cast<PadmapperOptions::Action *>(selectedOption);
pOptionPad->SetValue(ControllerButton_NONE);
vecDialogItems[IndexKeyOrPadInput]->m_text = selectedOption->GetValueDescription().data();
break;
}
return;
@ -189,6 +243,10 @@ void ItemSelected(int value)
selectedOption = pOption;
endMenu = true;
shownMenu = ShownMenuType::KeyInput;
} else if (pOption->GetType() == OptionEntryType::PadButton) {
selectedOption = pOption;
endMenu = true;
shownMenu = ShownMenuType::PadInput;
} else {
updateValueDescription = ChangeOptionValue(pOption, 0);
}
@ -213,6 +271,7 @@ void ItemSelected(int value)
GoBackOneMenuLevel();
} break;
case ShownMenuType::KeyInput:
case ShownMenuType::PadInput:
break;
}
}
@ -312,10 +371,10 @@ void UiSettingsMenu()
case ShownMenuType::KeyInput: {
vecDialogItems.push_back(std::make_unique<UiListItem>(_("Bound key:"), static_cast<int>(SpecialMenuEntry::None), UiFlags::ColorWhitegold | UiFlags::ElementDisabled));
vecDialogItems.push_back(std::make_unique<UiListItem>(selectedOption->GetValueDescription(), static_cast<int>(SpecialMenuEntry::None), UiFlags::ColorUiGold));
assert(IndexKeyInput == vecDialogItems.size() - 1);
itemToSelect = IndexKeyInput;
assert(IndexKeyOrPadInput == vecDialogItems.size() - 1);
itemToSelect = IndexKeyOrPadInput;
eventHandler = [](SDL_Event &event) {
if (SelectedItem != IndexKeyInput)
if (SelectedItem != IndexKeyOrPadInput)
return false;
uint32_t key = SDLK_UNKNOWN;
switch (event.type) {
@ -343,7 +402,7 @@ void UiSettingsMenu()
auto *pOptionKey = static_cast<KeymapperOptions::Action *>(selectedOption);
if (!pOptionKey->SetValue(key))
return false;
vecDialogItems[IndexKeyInput]->m_text = selectedOption->GetValueDescription().data();
vecDialogItems[IndexKeyOrPadInput]->m_text = selectedOption->GetValueDescription().data();
return true;
};
vecDialogItems.push_back(std::make_unique<UiListItem>(_("Press any key to change."), static_cast<int>(SpecialMenuEntry::None), UiFlags::ColorUiSilver | UiFlags::ElementDisabled));
@ -351,6 +410,53 @@ void UiSettingsMenu()
vecDialogItems.push_back(std::make_unique<UiListItem>(_("Unbind key"), static_cast<int>(SpecialMenuEntry::UnbindKey), UiFlags::ColorUiGold));
UpdateDescription(*selectedOption);
} break;
case ShownMenuType::PadInput: {
vecDialogItems.push_back(std::make_unique<UiListItem>(_("Bound button combo:"), static_cast<int>(SpecialMenuEntry::None), UiFlags::ColorWhitegold | UiFlags::ElementDisabled));
vecDialogItems.push_back(std::make_unique<UiListItem>(selectedOption->GetValueDescription(), static_cast<int>(SpecialMenuEntry::BindPadButton), UiFlags::ColorUiGold));
assert(IndexKeyOrPadInput == vecDialogItems.size() - 1);
itemToSelect = IndexKeyOrPadInput;
vecDialogItems.push_back(std::make_unique<UiListItem>(padEntryTimerText, static_cast<int>(SpecialMenuEntry::None), UiFlags::ColorUiSilver | UiFlags::ElementDisabled));
assert(IndexPadTimerText == vecDialogItems.size() - 1);
vecDialogItems.push_back(std::make_unique<UiListItem>("", static_cast<int>(SpecialMenuEntry::None), UiFlags::ElementDisabled));
vecDialogItems.push_back(std::make_unique<UiListItem>(_("Unbind button combo"), static_cast<int>(SpecialMenuEntry::UnbindPadButton), UiFlags::ColorUiGold));
padEntryStartTime = 0;
eventHandler = [](SDL_Event &event) {
if (padEntryStartTime == 0)
return false;
ControllerButtonEvent ctrlEvent = ToControllerButtonEvent(event);
bool isGamepadMotion = ProcessControllerMotion(event, ctrlEvent);
DetectInputMethod(event, ctrlEvent);
if (event.type == SDL_KEYUP && event.key.keysym.sym == SDLK_ESCAPE) {
StopPadEntryTimer();
return true;
}
if (isGamepadMotion || IsAnyOf(ctrlEvent.button, ControllerButton_NONE, ControllerButton_IGNORE)) {
return true;
}
bool modifierPressed = padEntryCombo.modifier != ControllerButton_NONE && IsControllerButtonPressed(padEntryCombo.modifier);
bool buttonPressed = padEntryCombo.button != ControllerButton_NONE && IsControllerButtonPressed(padEntryCombo.button);
if (ctrlEvent.up) {
// When the player has released all relevant inputs, assume the binding is finished and stop the timer
if (padEntryCombo.button != ControllerButton_NONE && !modifierPressed && !buttonPressed)
StopPadEntryTimer();
return true;
}
auto *pOptionPad = static_cast<PadmapperOptions::Action *>(selectedOption);
if (!modifierPressed && buttonPressed)
padEntryCombo.modifier = padEntryCombo.button;
padEntryCombo.button = ctrlEvent.button;
if (pOptionPad->SetValue(padEntryCombo))
vecDialogItems[IndexKeyOrPadInput]->m_text = selectedOption->GetValueDescription().data();
return true;
};
UpdateDescription(*selectedOption);
} break;
}
vecDialogItems.push_back(std::make_unique<UiListItem>("", static_cast<int>(SpecialMenuEntry::None), UiFlags::ElementDisabled));
@ -362,7 +468,7 @@ void UiSettingsMenu()
while (!endMenu) {
UiClearScreen();
UiRenderItems(vecDialog);
UpdatePadEntryTimerText();
UiPollAndRender(eventHandler);
}

190
Source/controls/controller_buttons.cpp

@ -1,5 +1,7 @@
#include "controller_buttons.h"
#include "plrctrls.h"
namespace devilution {
namespace controller_button_icon {
const string_view Playstation_Triangle = "\uE000";
@ -56,7 +58,7 @@ const string_view Nintendo_LStick_W = "\uE032";
const string_view Nintendo_LStick_SW = "\uE033";
const string_view Nintendo_LStick_N = "\uE034";
const string_view Nintendo_LStick = "\uE035";
const string_view Nintendoo_LStick_S = "\uE036";
const string_view Nintendo_LStick_S = "\uE036";
const string_view Nintendo_LStick_NE = "\uE037";
const string_view Nintendo_LStick_E = "\uE038";
const string_view Nintendo_LStick_SE = "\uE039";
@ -86,9 +88,9 @@ const string_view Xbox_RT = "\uE050";
const string_view Xbox_LB = "\uE051";
const string_view Xbox_RB = "\uE052";
const string_view Xbox_DPad_Up = "\uE053";
const string_view Xbox_Dpad_Right = "\uE054";
const string_view Xbox_Dpad_Down = "\uE055";
const string_view Xbox_Dpad_Left = "\uE056";
const string_view Xbox_DPad_Right = "\uE054";
const string_view Xbox_DPad_Down = "\uE055";
const string_view Xbox_DPad_Left = "\uE056";
const string_view Xbox_LStick_NW = "\uE057";
const string_view Xbox_LStick_W = "\uE058";
const string_view Xbox_LStick_SW = "\uE059";
@ -110,4 +112,184 @@ const string_view Xbox_RStick_SE = "\uE068";
const string_view Xbox_RStick_Click = "\uE069";
const string_view Xbox_Xbox = "\uE06A";
} // namespace controller_button_icon
string_view ToPlayStationIcon(ControllerButton button)
{
switch (button) {
case devilution::ControllerButton_BUTTON_A:
return controller_button_icon::Playstation_X;
case devilution::ControllerButton_BUTTON_B:
return controller_button_icon::Playstation_Circle;
case devilution::ControllerButton_BUTTON_X:
return controller_button_icon::Playstation_Square;
case devilution::ControllerButton_BUTTON_Y:
return controller_button_icon::Playstation_Triangle;
case devilution::ControllerButton_BUTTON_START:
return controller_button_icon::Playstation_Options;
case devilution::ControllerButton_BUTTON_BACK:
return controller_button_icon::Playstation_Share;
case devilution::ControllerButton_AXIS_TRIGGERLEFT:
return controller_button_icon::Playstation_L2;
case devilution::ControllerButton_AXIS_TRIGGERRIGHT:
return controller_button_icon::Playstation_R2;
case devilution::ControllerButton_BUTTON_LEFTSHOULDER:
return controller_button_icon::Playstation_L1;
case devilution::ControllerButton_BUTTON_RIGHTSHOULDER:
return controller_button_icon::Playstation_R1;
case devilution::ControllerButton_BUTTON_LEFTSTICK:
return controller_button_icon::Playstation_L3;
case devilution::ControllerButton_BUTTON_RIGHTSTICK:
return controller_button_icon::Playstation_R3;
case devilution::ControllerButton_BUTTON_DPAD_UP:
return controller_button_icon::Playstation_DPad_Up;
case devilution::ControllerButton_BUTTON_DPAD_DOWN:
return controller_button_icon::Playstation_DPad_Down;
case devilution::ControllerButton_BUTTON_DPAD_LEFT:
return controller_button_icon::Playstation_DPad_Left;
case devilution::ControllerButton_BUTTON_DPAD_RIGHT:
return controller_button_icon::Playstation_DPad_Right;
default:
return ToGenericButtonText(button);
}
}
string_view ToNintendoIcon(ControllerButton button)
{
switch (button) {
case devilution::ControllerButton_BUTTON_A:
return controller_button_icon::Nintendo_B;
case devilution::ControllerButton_BUTTON_B:
return controller_button_icon::Nintendo_A;
case devilution::ControllerButton_BUTTON_X:
return controller_button_icon::Nintendo_Y;
case devilution::ControllerButton_BUTTON_Y:
return controller_button_icon::Nintendo_X;
case devilution::ControllerButton_BUTTON_START:
return controller_button_icon::Nintendo_Plus;
case devilution::ControllerButton_BUTTON_BACK:
return controller_button_icon::Nintendo_Minus;
case devilution::ControllerButton_AXIS_TRIGGERLEFT:
return controller_button_icon::Nintendo_ZL;
case devilution::ControllerButton_AXIS_TRIGGERRIGHT:
return controller_button_icon::Nintendo_ZR;
case devilution::ControllerButton_BUTTON_LEFTSHOULDER:
return controller_button_icon::Nintendo_L;
case devilution::ControllerButton_BUTTON_RIGHTSHOULDER:
return controller_button_icon::Nintendo_R;
case devilution::ControllerButton_BUTTON_LEFTSTICK:
return controller_button_icon::Nintendo_LStick_Click;
case devilution::ControllerButton_BUTTON_RIGHTSTICK:
return controller_button_icon::Nintendo_RStick_Click;
case devilution::ControllerButton_BUTTON_DPAD_UP:
return controller_button_icon::Nintendo_DPad_Up;
case devilution::ControllerButton_BUTTON_DPAD_DOWN:
return controller_button_icon::Nintendo_DPad_Down;
case devilution::ControllerButton_BUTTON_DPAD_LEFT:
return controller_button_icon::Nintendo_DPad_Left;
case devilution::ControllerButton_BUTTON_DPAD_RIGHT:
return controller_button_icon::Nintendo_DPad_Right;
default:
return ToGenericButtonText(button);
}
}
string_view ToXboxIcon(ControllerButton button)
{
switch (button) {
case devilution::ControllerButton_BUTTON_A:
return controller_button_icon::Xbox_A;
case devilution::ControllerButton_BUTTON_B:
return controller_button_icon::Xbox_B;
case devilution::ControllerButton_BUTTON_X:
return controller_button_icon::Xbox_X;
case devilution::ControllerButton_BUTTON_Y:
return controller_button_icon::Xbox_Y;
case devilution::ControllerButton_BUTTON_START:
return controller_button_icon::Xbox_Menu;
case devilution::ControllerButton_BUTTON_BACK:
return controller_button_icon::Xbox_View;
case devilution::ControllerButton_AXIS_TRIGGERLEFT:
return controller_button_icon::Xbox_LT;
case devilution::ControllerButton_AXIS_TRIGGERRIGHT:
return controller_button_icon::Xbox_RT;
case devilution::ControllerButton_BUTTON_LEFTSHOULDER:
return controller_button_icon::Xbox_LB;
case devilution::ControllerButton_BUTTON_RIGHTSHOULDER:
return controller_button_icon::Xbox_RB;
case devilution::ControllerButton_BUTTON_LEFTSTICK:
return controller_button_icon::Xbox_LStick_Click;
case devilution::ControllerButton_BUTTON_RIGHTSTICK:
return controller_button_icon::Xbox_RStick_Click;
case devilution::ControllerButton_BUTTON_DPAD_UP:
return controller_button_icon::Xbox_DPad_Up;
case devilution::ControllerButton_BUTTON_DPAD_DOWN:
return controller_button_icon::Xbox_DPad_Down;
case devilution::ControllerButton_BUTTON_DPAD_LEFT:
return controller_button_icon::Xbox_DPad_Left;
case devilution::ControllerButton_BUTTON_DPAD_RIGHT:
return controller_button_icon::Xbox_DPad_Right;
default:
return ToGenericButtonText(button);
}
}
string_view ToGenericButtonText(ControllerButton button)
{
switch (button) {
case devilution::ControllerButton_BUTTON_A:
return "A";
case devilution::ControllerButton_BUTTON_B:
return "B";
case devilution::ControllerButton_BUTTON_X:
return "X";
case devilution::ControllerButton_BUTTON_Y:
return "Y";
case devilution::ControllerButton_BUTTON_START:
return "Start";
case devilution::ControllerButton_BUTTON_BACK:
return "Select";
case devilution::ControllerButton_AXIS_TRIGGERLEFT:
return "LT";
case devilution::ControllerButton_AXIS_TRIGGERRIGHT:
return "RT";
case devilution::ControllerButton_BUTTON_LEFTSHOULDER:
return "LB";
case devilution::ControllerButton_BUTTON_RIGHTSHOULDER:
return "RB";
case devilution::ControllerButton_BUTTON_LEFTSTICK:
return "LS";
case devilution::ControllerButton_BUTTON_RIGHTSTICK:
return "RS";
case devilution::ControllerButton_BUTTON_DPAD_UP:
return "Up";
case devilution::ControllerButton_BUTTON_DPAD_DOWN:
return "Down";
case devilution::ControllerButton_BUTTON_DPAD_LEFT:
return "Left";
case devilution::ControllerButton_BUTTON_DPAD_RIGHT:
return "Right";
case devilution::ControllerButton_NONE:
return "None";
case devilution::ControllerButton_IGNORE:
return "Ignored";
default:
return "Unknown";
}
}
string_view ToString(ControllerButton button)
{
switch (GamepadType) {
case devilution::GamepadLayout::PlayStation:
return ToPlayStationIcon(button);
case devilution::GamepadLayout::Nintendo:
return ToNintendoIcon(button);
case devilution::GamepadLayout::Xbox:
return ToXboxIcon(button);
default:
case devilution::GamepadLayout::Generic:
return ToGenericButtonText(button);
}
}
} // namespace devilution

15
Source/controls/controller_buttons.h

@ -119,7 +119,7 @@ extern const string_view Nintendo_LStick_W;
extern const string_view Nintendo_LStick_SW;
extern const string_view Nintendo_LStick_N;
extern const string_view Nintendo_LStick;
extern const string_view Nintendoo_LStick_S;
extern const string_view Nintendo_LStick_S;
extern const string_view Nintendo_LStick_NE;
extern const string_view Nintendo_LStick_E;
extern const string_view Nintendo_LStick_SE;
@ -149,9 +149,9 @@ extern const string_view Xbox_RT;
extern const string_view Xbox_LB;
extern const string_view Xbox_RB;
extern const string_view Xbox_DPad_Up;
extern const string_view Xbox_Dpad_Right;
extern const string_view Xbox_Dpad_Down;
extern const string_view Xbox_Dpad_Left;
extern const string_view Xbox_DPad_Right;
extern const string_view Xbox_DPad_Down;
extern const string_view Xbox_DPad_Left;
extern const string_view Xbox_LStick_NW;
extern const string_view Xbox_LStick_W;
extern const string_view Xbox_LStick_SW;
@ -173,4 +173,11 @@ extern const string_view Xbox_RStick_SE;
extern const string_view Xbox_RStick_Click;
extern const string_view Xbox_Xbox;
} // namespace controller_button_icon
string_view ToPlayStationIcon(ControllerButton button);
string_view ToNintendoIcon(ControllerButton button);
string_view ToXboxIcon(ControllerButton button);
string_view ToGenericButtonText(ControllerButton button);
string_view ToString(ControllerButton button);
} // namespace devilution

6
Source/controls/devices/game_controller.cpp

@ -25,8 +25,9 @@ ControllerButton GameController::ToControllerButton(const SDL_Event &event)
case SDL_CONTROLLERAXISMOTION:
switch (event.caxis.axis) {
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
if (event.caxis.value < 8192) { // 25% pressed
if (event.caxis.value < 8192 && trigger_left_is_down_) { // 25% pressed
trigger_left_is_down_ = false;
trigger_left_state_ = ControllerButton_AXIS_TRIGGERLEFT;
}
if (event.caxis.value > 16384 && !trigger_left_is_down_) { // 50% pressed
trigger_left_is_down_ = true;
@ -34,8 +35,9 @@ ControllerButton GameController::ToControllerButton(const SDL_Event &event)
}
return trigger_left_state_;
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
if (event.caxis.value < 8192) { // 25% pressed
if (event.caxis.value < 8192 && trigger_right_is_down_) { // 25% pressed
trigger_right_is_down_ = false;
trigger_right_state_ = ControllerButton_AXIS_TRIGGERRIGHT;
}
if (event.caxis.value > 16384 && !trigger_right_is_down_) { // 50% pressed
trigger_right_is_down_ = true;

46
Source/options.cpp

@ -16,6 +16,7 @@
#include "control.h"
#include "controls/controller.h"
#include "controls/game_controls.h"
#include "controls/plrctrls.h"
#include "discord/discord.h"
#include "engine/demomode.h"
#include "engine/sound_defs.hpp"
@ -1462,7 +1463,7 @@ std::vector<OptionEntryBase *> PadmapperOptions::GetEntries()
}
PadmapperOptions::Action::Action(string_view key, const char *name, const char *description, ControllerButtonCombo defaultInput, std::function<void()> actionPressed, std::function<void()> actionReleased, std::function<bool()> enable, unsigned index)
: OptionEntryBase(key, OptionEntryFlags::Invisible, name, description)
: OptionEntryBase(key, OptionEntryFlags::None, name, description)
, defaultInput(defaultInput)
, actionPressed(std::move(actionPressed))
, actionReleased(std::move(actionReleased))
@ -1553,37 +1554,36 @@ void PadmapperOptions::Action::SaveToIni(string_view category) const
SetIniValue(category.data(), key.data(), inputName.data());
}
void PadmapperOptions::Action::UpdateValueDescription() const
{
boundInputDescriptionType = GamepadType;
if (boundInput.button == ControllerButton_NONE) {
boundInputDescription = "";
return;
}
string_view buttonName = ToString(boundInput.button);
if (boundInput.modifier == ControllerButton_NONE) {
boundInputDescription = std::string(buttonName);
return;
}
string_view modifierName = ToString(boundInput.modifier);
boundInputDescription = StrCat(modifierName, "+", buttonName);
}
string_view PadmapperOptions::Action::GetValueDescription() const
{
if (GamepadType != boundInputDescriptionType)
UpdateValueDescription();
return boundInputDescription;
}
bool PadmapperOptions::Action::SetValue(ControllerButtonCombo value)
{
const std::string &modifierName = sgOptions.Padmapper.buttonToButtonName[static_cast<size_t>(value.modifier)];
const std::string &buttonName = sgOptions.Padmapper.buttonToButtonName[static_cast<size_t>(value.button)];
if ((value.modifier != ControllerButton_NONE && modifierName.empty())
|| (value.button != ControllerButton_NONE && buttonName.empty())) {
// Ignore invalid button combos
return false;
}
// Remove old button combo
if (boundInput.button != ControllerButton_NONE) {
if (boundInput.button != ControllerButton_NONE)
boundInput = {};
boundInputDescription = "";
}
// Add new button combo
if (value.button != ControllerButton_NONE) {
if (value.button != ControllerButton_NONE)
boundInput = value;
boundInputDescription = buttonName;
if (!modifierName.empty()) {
boundInputDescription = StrCat(modifierName, "+", boundInputDescription);
}
}
UpdateValueDescription();
return true;
}

6
Source/options.h

@ -10,6 +10,7 @@
#include "controls/controller.h"
#include "controls/controller_buttons.h"
#include "controls/game_controls.h"
#include "engine/sound_defs.hpp"
#include "miniwin/misc_msg.h"
#include "pack.h"
@ -722,11 +723,14 @@ struct PadmapperOptions : OptionCategoryBase {
std::function<void()> actionReleased;
std::function<bool()> enable;
ControllerButtonCombo boundInput {};
std::string boundInputDescription;
mutable GamepadLayout boundInputDescriptionType = GamepadLayout::Generic;
mutable std::string boundInputDescription;
unsigned dynamicIndex;
std::string dynamicKey;
mutable std::string dynamicName;
void UpdateValueDescription() const;
friend struct PadmapperOptions;
};

Loading…
Cancel
Save