diff --git a/Source/controls/controller_motion.cpp b/Source/controls/controller_motion.cpp index 26b7c1fbb..9ad07ac46 100644 --- a/Source/controls/controller_motion.cpp +++ b/Source/controls/controller_motion.cpp @@ -78,47 +78,40 @@ void SetSimulatingMouseWithPadmapper(bool value) } } -// SELECT + D-Pad to simulate right stick movement. -bool SimulateRightStickWithDpad(ControllerButtonEvent ctrlEvent) +void SimulateRightStickWithPadmapper(ControllerButtonEvent ctrlEvent) { if (IsAnyOf(ctrlEvent.button, ControllerButton_NONE, ControllerButton_IGNORE)) - return false; + return; + if (!ctrlEvent.up && ctrlEvent.button == SuppressedButton) + return; - ControllerButtonCombo upCombo = sgOptions.Padmapper.ButtonComboForAction("MouseUp"); - ControllerButtonCombo downCombo = sgOptions.Padmapper.ButtonComboForAction("MouseDown"); - ControllerButtonCombo leftCombo = sgOptions.Padmapper.ButtonComboForAction("MouseLeft"); - ControllerButtonCombo rightCombo = sgOptions.Padmapper.ButtonComboForAction("MouseRight"); - if (IsNoneOf(ctrlEvent.button, upCombo.button, downCombo.button, leftCombo.button, rightCombo.button)) { + string_view actionName = sgOptions.Padmapper.ActionNameTriggeredByButtonEvent(ctrlEvent); + bool upTriggered = actionName == "MouseUp"; + bool downTriggered = actionName == "MouseDown"; + bool leftTriggered = actionName == "MouseLeft"; + bool rightTriggered = actionName == "MouseRight"; + if (!upTriggered && !downTriggered && !leftTriggered && !rightTriggered) { if (rightStickX == 0 && rightStickY == 0) SetSimulatingMouseWithPadmapper(false); - return false; + return; } + bool upActive = (upTriggered && !ctrlEvent.up) || (!upTriggered && sgOptions.Padmapper.IsActive("MouseUp")); + bool downActive = (downTriggered && !ctrlEvent.up) || (!downTriggered && sgOptions.Padmapper.IsActive("MouseDown")); + bool leftActive = (leftTriggered && !ctrlEvent.up) || (!leftTriggered && sgOptions.Padmapper.IsActive("MouseLeft")); + bool rightActive = (rightTriggered && !ctrlEvent.up) || (!rightTriggered && sgOptions.Padmapper.IsActive("MouseRight")); + rightStickX = 0; rightStickY = 0; - - // Cannot use PadmapperOptions::IsActive() because this function - // is invoked before PadmapperOptions::ButtonPressed() - if (IsControllerButtonComboPressed(upCombo)) + if (upActive) rightStickY += 1.F; - if (IsControllerButtonComboPressed(downCombo)) + if (downActive) rightStickY -= 1.F; - if (IsControllerButtonComboPressed(leftCombo)) + if (leftActive) rightStickX -= 1.F; - if (IsControllerButtonComboPressed(rightCombo)) + if (rightActive) rightStickX += 1.F; - - if (rightStickX == 0 && rightStickY == 0) { - // In this case, PadmapperOptions::IsActive() can be used to anticipate PadmapperOptions::ButtonReleased() - bool upReleased = ctrlEvent.up && ctrlEvent.button == upCombo.button && sgOptions.Padmapper.IsActive("MouseUp"); - bool downReleased = ctrlEvent.up && ctrlEvent.button == downCombo.button && sgOptions.Padmapper.IsActive("MouseDown"); - bool leftReleased = ctrlEvent.up && ctrlEvent.button == leftCombo.button && sgOptions.Padmapper.IsActive("MouseLeft"); - bool rightReleased = ctrlEvent.up && ctrlEvent.button == rightCombo.button && sgOptions.Padmapper.IsActive("MouseRight"); - return upReleased || downReleased || leftReleased || rightReleased; - } - SetSimulatingMouseWithPadmapper(true); - return true; } } // namespace @@ -174,7 +167,8 @@ bool ProcessControllerMotion(const SDL_Event &event, ControllerButtonEvent ctrlE return true; } #endif - return SimulateRightStickWithDpad(ctrlEvent); + SimulateRightStickWithPadmapper(ctrlEvent); + return false; } AxisDirection GetLeftStickOrDpadDirection(bool usePadmapper) @@ -194,7 +188,7 @@ AxisDirection GetLeftStickOrDpadDirection(bool usePadmapper) isDownPressed |= sgOptions.Padmapper.IsActive("MoveDown"); isLeftPressed |= sgOptions.Padmapper.IsActive("MoveLeft"); isRightPressed |= sgOptions.Padmapper.IsActive("MoveRight"); - } else { + } else if (!SimulatingMouseWithPadmapper) { isUpPressed |= IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_UP); isDownPressed |= IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_DOWN); isLeftPressed |= IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_LEFT); diff --git a/Source/controls/game_controls.cpp b/Source/controls/game_controls.cpp index a82d6af13..d20422dda 100644 --- a/Source/controls/game_controls.cpp +++ b/Source/controls/game_controls.cpp @@ -332,14 +332,12 @@ bool SkipsMovie(ControllerButtonEvent ctrlEvent) bool IsSimulatedMouseClickBinding(ControllerButtonEvent ctrlEvent) { - ControllerButtonCombo leftMouseClickBinding1 = sgOptions.Padmapper.ButtonComboForAction("LeftMouseClick1"); - ControllerButtonCombo leftMouseClickBinding2 = sgOptions.Padmapper.ButtonComboForAction("LeftMouseClick2"); - ControllerButtonCombo rightMouseClickBinding1 = sgOptions.Padmapper.ButtonComboForAction("RightMouseClick1"); - ControllerButtonCombo rightMouseClickBinding2 = sgOptions.Padmapper.ButtonComboForAction("RightMouseClick2"); - return (ctrlEvent.button == leftMouseClickBinding1.button && IsControllerButtonComboPressed(leftMouseClickBinding1)) - || (ctrlEvent.button == leftMouseClickBinding2.button && IsControllerButtonComboPressed(leftMouseClickBinding2)) - || (ctrlEvent.button == rightMouseClickBinding1.button && IsControllerButtonComboPressed(rightMouseClickBinding1)) - || (ctrlEvent.button == rightMouseClickBinding2.button && IsControllerButtonComboPressed(rightMouseClickBinding2)); + if (IsAnyOf(ctrlEvent.button, ControllerButton_NONE, ControllerButton_IGNORE)) + return false; + if (!ctrlEvent.up && ctrlEvent.button == SuppressedButton) + return false; + string_view actionName = sgOptions.Padmapper.ActionNameTriggeredByButtonEvent(ctrlEvent); + return IsAnyOf(actionName, "LeftMouseClick1", "LeftMouseClick2", "RightMouseClick1", "RightMouseClick2"); } AxisDirection GetMoveDirection() @@ -365,8 +363,11 @@ bool HandleControllerButtonEvent(const SDL_Event &event, GameAction &action) if (isGamepadMotion) { return true; } + if (IsAnyOf(ctrlEvent.button, ControllerButton_NONE, ControllerButton_IGNORE)) { + return false; + } - if (ctrlEvent.button != ControllerButton_NONE && ctrlEvent.button == SuppressedButton) { + if (ctrlEvent.button == SuppressedButton) { if (!ctrlEvent.up) return true; SuppressedButton = ControllerButton_NONE; diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index 1c3e6afe6..e25898f79 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -1481,7 +1481,7 @@ float rightStickLastMove = 0; bool ContinueSimulatedMouseEvent(const SDL_Event &event, const ControllerButtonEvent &gamepadEvent) { - if (IsAutomapActive()) + if (AutomapActive) return false; #if !defined(USE_SDL1) && !defined(JOY_AXIS_RIGHTX) && !defined(JOY_AXIS_RIGHTY) @@ -1691,11 +1691,6 @@ void ProcessGameAction(const GameAction &action) } } -bool IsAutomapActive() -{ - return AutomapActive && leveltype != DTYPE_TOWN; -} - void HandleRightStickMotion() { static RightStickAccumulator acc; @@ -1705,7 +1700,7 @@ void HandleRightStickMotion() return; } - if (IsAutomapActive()) { // move map + if (AutomapActive) { // move map int dx = 0; int dy = 0; acc.Pool(&dx, &dy, 32); diff --git a/Source/controls/plrctrls.h b/Source/controls/plrctrls.h index 04ce9c903..5dcbc6f08 100644 --- a/Source/controls/plrctrls.h +++ b/Source/controls/plrctrls.h @@ -67,9 +67,6 @@ bool IsPointAndClick(); void DetectInputMethod(const SDL_Event &event, const ControllerButtonEvent &gamepadEvent); void ProcessGameAction(const GameAction &action); -// Whether the automap is being displayed. -bool IsAutomapActive(); - void UseBeltItem(int type); // Talk to towners, click on inv items, attack, etc. diff --git a/Source/options.cpp b/Source/options.cpp index 627626abd..fe0482a2f 100644 --- a/Source/options.cpp +++ b/Source/options.cpp @@ -1597,39 +1597,13 @@ void PadmapperOptions::CommitActions() void PadmapperOptions::ButtonPressed(ControllerButton button) { - // To give preference to button combinations, - // first pass ignores mappings where no modifier is bound - for (Action &action : actions) { - ControllerButtonCombo combo = action.boundInput; - if (combo.modifier == ControllerButton_NONE) - continue; - if (button != combo.button) - continue; - if (!IsControllerButtonPressed(combo.modifier)) - continue; - if (action.enable && !action.enable()) - continue; - if (action.actionPressed) - action.actionPressed(); - SuppressedButton = combo.modifier; - buttonToReleaseAction.insert_or_assign(combo.button, action); - return; - } - - for (Action &action : actions) { - ControllerButtonCombo combo = action.boundInput; - if (combo.modifier != ControllerButton_NONE) - continue; - if (button != combo.button) - continue; - if (action.enable && !action.enable()) - continue; - if (action.actionPressed) - action.actionPressed(); - SuppressedButton = combo.modifier; - buttonToReleaseAction.insert_or_assign(combo.button, action); + const Action *action = FindAction(button); + if (action == nullptr) return; - } + if (action->actionPressed) + action->actionPressed(); + SuppressedButton = action->boundInput.modifier; + buttonToReleaseAction.insert_or_assign(button, *action); } void PadmapperOptions::ButtonReleased(ControllerButton button, bool invokeAction) @@ -1663,6 +1637,22 @@ bool PadmapperOptions::IsActive(string_view actionName) const return false; } +string_view PadmapperOptions::ActionNameTriggeredByButtonEvent(ControllerButtonEvent ctrlEvent) const +{ + if (!gbRunGame) + return ""; + + if (!ctrlEvent.up) { + const Action *pressAction = FindAction(ctrlEvent.button); + return pressAction != nullptr ? pressAction->key : ""; + } + auto it = buttonToReleaseAction.find(ctrlEvent.button); + if (it == buttonToReleaseAction.end()) + return ""; + const Action &releaseAction = it->second.get(); + return releaseAction.key; +} + string_view PadmapperOptions::InputNameForAction(string_view actionName) const { for (const Action &action : actions) { @@ -1683,6 +1673,37 @@ ControllerButtonCombo PadmapperOptions::ButtonComboForAction(string_view actionN return ControllerButton_NONE; } +const PadmapperOptions::Action *PadmapperOptions::FindAction(ControllerButton button) const +{ + // To give preference to button combinations, + // first pass ignores mappings where no modifier is bound + for (const Action &action : actions) { + ControllerButtonCombo combo = action.boundInput; + if (combo.modifier == ControllerButton_NONE) + continue; + if (button != combo.button) + continue; + if (!IsControllerButtonPressed(combo.modifier)) + continue; + if (action.enable && !action.enable()) + continue; + return &action; + } + + for (const Action &action : actions) { + ControllerButtonCombo combo = action.boundInput; + if (combo.modifier != ControllerButton_NONE) + continue; + if (button != combo.button) + continue; + if (action.enable && !action.enable()) + continue; + return &action; + } + + return nullptr; +} + namespace { constexpr char ResamplerSpeex[] = "Speex"; constexpr char ResamplerSDL[] = "SDL"; diff --git a/Source/options.h b/Source/options.h index 2a90fb52a..16d678015 100644 --- a/Source/options.h +++ b/Source/options.h @@ -7,6 +7,7 @@ #include +#include "controls/controller.h" #include "controls/controller_buttons.h" #include "engine/sound_defs.hpp" #include "miniwin/misc_msg.h" @@ -739,15 +740,18 @@ struct PadmapperOptions : OptionCategoryBase { void ButtonPressed(ControllerButton button); void ButtonReleased(ControllerButton button, bool invokeAction = true); bool IsActive(string_view actionName) const; + string_view ActionNameTriggeredByButtonEvent(ControllerButtonEvent ctrlEvent) const; string_view InputNameForAction(string_view actionName) const; ControllerButtonCombo ButtonComboForAction(string_view actionName) const; private: std::forward_list actions; - std::unordered_map> buttonToReleaseAction; + std::unordered_map> buttonToReleaseAction; std::unordered_map buttonToButtonName; std::unordered_map buttonNameToButton; bool committed = false; + + const Action *FindAction(ControllerButton button) const; }; struct Options {