Browse Source

Further improve simulated mouse interaction

pull/5453/head
staphen 3 years ago committed by Anders Jenbo
parent
commit
6a565d3755
  1. 52
      Source/controls/controller_motion.cpp
  2. 19
      Source/controls/game_controls.cpp
  3. 9
      Source/controls/plrctrls.cpp
  4. 3
      Source/controls/plrctrls.h
  5. 85
      Source/options.cpp
  6. 6
      Source/options.h

52
Source/controls/controller_motion.cpp

@ -78,47 +78,40 @@ void SetSimulatingMouseWithPadmapper(bool value)
} }
} }
// SELECT + D-Pad to simulate right stick movement. void SimulateRightStickWithPadmapper(ControllerButtonEvent ctrlEvent)
bool SimulateRightStickWithDpad(ControllerButtonEvent ctrlEvent)
{ {
if (IsAnyOf(ctrlEvent.button, ControllerButton_NONE, ControllerButton_IGNORE)) if (IsAnyOf(ctrlEvent.button, ControllerButton_NONE, ControllerButton_IGNORE))
return false; return;
if (!ctrlEvent.up && ctrlEvent.button == SuppressedButton)
return;
ControllerButtonCombo upCombo = sgOptions.Padmapper.ButtonComboForAction("MouseUp"); string_view actionName = sgOptions.Padmapper.ActionNameTriggeredByButtonEvent(ctrlEvent);
ControllerButtonCombo downCombo = sgOptions.Padmapper.ButtonComboForAction("MouseDown"); bool upTriggered = actionName == "MouseUp";
ControllerButtonCombo leftCombo = sgOptions.Padmapper.ButtonComboForAction("MouseLeft"); bool downTriggered = actionName == "MouseDown";
ControllerButtonCombo rightCombo = sgOptions.Padmapper.ButtonComboForAction("MouseRight"); bool leftTriggered = actionName == "MouseLeft";
if (IsNoneOf(ctrlEvent.button, upCombo.button, downCombo.button, leftCombo.button, rightCombo.button)) { bool rightTriggered = actionName == "MouseRight";
if (!upTriggered && !downTriggered && !leftTriggered && !rightTriggered) {
if (rightStickX == 0 && rightStickY == 0) if (rightStickX == 0 && rightStickY == 0)
SetSimulatingMouseWithPadmapper(false); 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; rightStickX = 0;
rightStickY = 0; rightStickY = 0;
if (upActive)
// Cannot use PadmapperOptions::IsActive() because this function
// is invoked before PadmapperOptions::ButtonPressed()
if (IsControllerButtonComboPressed(upCombo))
rightStickY += 1.F; rightStickY += 1.F;
if (IsControllerButtonComboPressed(downCombo)) if (downActive)
rightStickY -= 1.F; rightStickY -= 1.F;
if (IsControllerButtonComboPressed(leftCombo)) if (leftActive)
rightStickX -= 1.F; rightStickX -= 1.F;
if (IsControllerButtonComboPressed(rightCombo)) if (rightActive)
rightStickX += 1.F; 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); SetSimulatingMouseWithPadmapper(true);
return true;
} }
} // namespace } // namespace
@ -174,7 +167,8 @@ bool ProcessControllerMotion(const SDL_Event &event, ControllerButtonEvent ctrlE
return true; return true;
} }
#endif #endif
return SimulateRightStickWithDpad(ctrlEvent); SimulateRightStickWithPadmapper(ctrlEvent);
return false;
} }
AxisDirection GetLeftStickOrDpadDirection(bool usePadmapper) AxisDirection GetLeftStickOrDpadDirection(bool usePadmapper)
@ -194,7 +188,7 @@ AxisDirection GetLeftStickOrDpadDirection(bool usePadmapper)
isDownPressed |= sgOptions.Padmapper.IsActive("MoveDown"); isDownPressed |= sgOptions.Padmapper.IsActive("MoveDown");
isLeftPressed |= sgOptions.Padmapper.IsActive("MoveLeft"); isLeftPressed |= sgOptions.Padmapper.IsActive("MoveLeft");
isRightPressed |= sgOptions.Padmapper.IsActive("MoveRight"); isRightPressed |= sgOptions.Padmapper.IsActive("MoveRight");
} else { } else if (!SimulatingMouseWithPadmapper) {
isUpPressed |= IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_UP); isUpPressed |= IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_UP);
isDownPressed |= IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_DOWN); isDownPressed |= IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_DOWN);
isLeftPressed |= IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_LEFT); isLeftPressed |= IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_LEFT);

19
Source/controls/game_controls.cpp

@ -332,14 +332,12 @@ bool SkipsMovie(ControllerButtonEvent ctrlEvent)
bool IsSimulatedMouseClickBinding(ControllerButtonEvent ctrlEvent) bool IsSimulatedMouseClickBinding(ControllerButtonEvent ctrlEvent)
{ {
ControllerButtonCombo leftMouseClickBinding1 = sgOptions.Padmapper.ButtonComboForAction("LeftMouseClick1"); if (IsAnyOf(ctrlEvent.button, ControllerButton_NONE, ControllerButton_IGNORE))
ControllerButtonCombo leftMouseClickBinding2 = sgOptions.Padmapper.ButtonComboForAction("LeftMouseClick2"); return false;
ControllerButtonCombo rightMouseClickBinding1 = sgOptions.Padmapper.ButtonComboForAction("RightMouseClick1"); if (!ctrlEvent.up && ctrlEvent.button == SuppressedButton)
ControllerButtonCombo rightMouseClickBinding2 = sgOptions.Padmapper.ButtonComboForAction("RightMouseClick2"); return false;
return (ctrlEvent.button == leftMouseClickBinding1.button && IsControllerButtonComboPressed(leftMouseClickBinding1)) string_view actionName = sgOptions.Padmapper.ActionNameTriggeredByButtonEvent(ctrlEvent);
|| (ctrlEvent.button == leftMouseClickBinding2.button && IsControllerButtonComboPressed(leftMouseClickBinding2)) return IsAnyOf(actionName, "LeftMouseClick1", "LeftMouseClick2", "RightMouseClick1", "RightMouseClick2");
|| (ctrlEvent.button == rightMouseClickBinding1.button && IsControllerButtonComboPressed(rightMouseClickBinding1))
|| (ctrlEvent.button == rightMouseClickBinding2.button && IsControllerButtonComboPressed(rightMouseClickBinding2));
} }
AxisDirection GetMoveDirection() AxisDirection GetMoveDirection()
@ -365,8 +363,11 @@ bool HandleControllerButtonEvent(const SDL_Event &event, GameAction &action)
if (isGamepadMotion) { if (isGamepadMotion) {
return true; 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) if (!ctrlEvent.up)
return true; return true;
SuppressedButton = ControllerButton_NONE; SuppressedButton = ControllerButton_NONE;

9
Source/controls/plrctrls.cpp

@ -1481,7 +1481,7 @@ float rightStickLastMove = 0;
bool ContinueSimulatedMouseEvent(const SDL_Event &event, const ControllerButtonEvent &gamepadEvent) bool ContinueSimulatedMouseEvent(const SDL_Event &event, const ControllerButtonEvent &gamepadEvent)
{ {
if (IsAutomapActive()) if (AutomapActive)
return false; return false;
#if !defined(USE_SDL1) && !defined(JOY_AXIS_RIGHTX) && !defined(JOY_AXIS_RIGHTY) #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() void HandleRightStickMotion()
{ {
static RightStickAccumulator acc; static RightStickAccumulator acc;
@ -1705,7 +1700,7 @@ void HandleRightStickMotion()
return; return;
} }
if (IsAutomapActive()) { // move map if (AutomapActive) { // move map
int dx = 0; int dx = 0;
int dy = 0; int dy = 0;
acc.Pool(&dx, &dy, 32); acc.Pool(&dx, &dy, 32);

3
Source/controls/plrctrls.h

@ -67,9 +67,6 @@ bool IsPointAndClick();
void DetectInputMethod(const SDL_Event &event, const ControllerButtonEvent &gamepadEvent); void DetectInputMethod(const SDL_Event &event, const ControllerButtonEvent &gamepadEvent);
void ProcessGameAction(const GameAction &action); void ProcessGameAction(const GameAction &action);
// Whether the automap is being displayed.
bool IsAutomapActive();
void UseBeltItem(int type); void UseBeltItem(int type);
// Talk to towners, click on inv items, attack, etc. // Talk to towners, click on inv items, attack, etc.

85
Source/options.cpp

@ -1597,39 +1597,13 @@ void PadmapperOptions::CommitActions()
void PadmapperOptions::ButtonPressed(ControllerButton button) void PadmapperOptions::ButtonPressed(ControllerButton button)
{ {
// To give preference to button combinations, const Action *action = FindAction(button);
// first pass ignores mappings where no modifier is bound if (action == nullptr)
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);
return; return;
} if (action->actionPressed)
action->actionPressed();
SuppressedButton = action->boundInput.modifier;
buttonToReleaseAction.insert_or_assign(button, *action);
} }
void PadmapperOptions::ButtonReleased(ControllerButton button, bool invokeAction) void PadmapperOptions::ButtonReleased(ControllerButton button, bool invokeAction)
@ -1663,6 +1637,22 @@ bool PadmapperOptions::IsActive(string_view actionName) const
return false; 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 string_view PadmapperOptions::InputNameForAction(string_view actionName) const
{ {
for (const Action &action : actions) { for (const Action &action : actions) {
@ -1683,6 +1673,37 @@ ControllerButtonCombo PadmapperOptions::ButtonComboForAction(string_view actionN
return ControllerButton_NONE; 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 { namespace {
constexpr char ResamplerSpeex[] = "Speex"; constexpr char ResamplerSpeex[] = "Speex";
constexpr char ResamplerSDL[] = "SDL"; constexpr char ResamplerSDL[] = "SDL";

6
Source/options.h

@ -7,6 +7,7 @@
#include <SDL_version.h> #include <SDL_version.h>
#include "controls/controller.h"
#include "controls/controller_buttons.h" #include "controls/controller_buttons.h"
#include "engine/sound_defs.hpp" #include "engine/sound_defs.hpp"
#include "miniwin/misc_msg.h" #include "miniwin/misc_msg.h"
@ -739,15 +740,18 @@ struct PadmapperOptions : OptionCategoryBase {
void ButtonPressed(ControllerButton button); void ButtonPressed(ControllerButton button);
void ButtonReleased(ControllerButton button, bool invokeAction = true); void ButtonReleased(ControllerButton button, bool invokeAction = true);
bool IsActive(string_view actionName) const; bool IsActive(string_view actionName) const;
string_view ActionNameTriggeredByButtonEvent(ControllerButtonEvent ctrlEvent) const;
string_view InputNameForAction(string_view actionName) const; string_view InputNameForAction(string_view actionName) const;
ControllerButtonCombo ButtonComboForAction(string_view actionName) const; ControllerButtonCombo ButtonComboForAction(string_view actionName) const;
private: private:
std::forward_list<Action> actions; std::forward_list<Action> actions;
std::unordered_map<ControllerButton, std::reference_wrapper<Action>> buttonToReleaseAction; std::unordered_map<ControllerButton, std::reference_wrapper<const Action>> buttonToReleaseAction;
std::unordered_map<ControllerButton, std::string> buttonToButtonName; std::unordered_map<ControllerButton, std::string> buttonToButtonName;
std::unordered_map<std::string, ControllerButton> buttonNameToButton; std::unordered_map<std::string, ControllerButton> buttonNameToButton;
bool committed = false; bool committed = false;
const Action *FindAction(ControllerButton button) const;
}; };
struct Options { struct Options {

Loading…
Cancel
Save