Resurrect and refactor the AxisSwap feature. Fixes #17292

This commit is contained in:
Henrik Rydgård 2023-04-20 00:00:46 +02:00
parent eeedc817e2
commit 7594ae8785
5 changed files with 79 additions and 28 deletions

View File

@ -202,6 +202,37 @@ float ControlMapper::MapAxisValue(float value, int vkId, const InputMapping &map
}
}
static bool IsSwappableVKey(uint32_t vkey) {
switch (vkey) {
case CTRL_UP:
case CTRL_LEFT:
case CTRL_DOWN:
case CTRL_RIGHT:
case VIRTKEY_AXIS_X_MIN:
case VIRTKEY_AXIS_X_MAX:
case VIRTKEY_AXIS_Y_MIN:
case VIRTKEY_AXIS_Y_MAX:
return true;
default:
return false;
}
}
void ControlMapper::SwapMappingIfEnabled(uint32_t *vkey) {
if (swapAxes_) {
switch (*vkey) {
case CTRL_UP: *vkey = VIRTKEY_AXIS_Y_MAX; break;
case VIRTKEY_AXIS_Y_MAX: *vkey = CTRL_UP; break;
case CTRL_DOWN: *vkey = VIRTKEY_AXIS_Y_MIN; break;
case VIRTKEY_AXIS_Y_MIN: *vkey = CTRL_DOWN; break;
case CTRL_LEFT: *vkey = VIRTKEY_AXIS_X_MIN; break;
case VIRTKEY_AXIS_X_MIN: *vkey = CTRL_LEFT; break;
case CTRL_RIGHT: *vkey = VIRTKEY_AXIS_X_MAX; break;
case VIRTKEY_AXIS_X_MAX: *vkey = CTRL_RIGHT; break;
}
}
}
// Can only be called from Key or Axis.
bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping) {
// Instead of taking an input key and finding what it outputs, we loop through the OUTPUTS and
@ -230,6 +261,8 @@ bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping) {
mappingBit = RotatePSPKeyCode(mappingBit);
}
SwapMappingIfEnabled(&mappingBit);
std::vector<MultiInputMapping> inputMappings;
if (!KeyMap::InputMappingsFromPspButton(mappingBit, &inputMappings, false))
continue;
@ -264,7 +297,11 @@ bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping) {
for (int i = 0; i < VIRTKEY_COUNT; i++) {
int vkId = i + VIRTKEY_FIRST;
std::vector<MultiInputMapping> inputMappings;
if (!KeyMap::InputMappingsFromPspButton(vkId, &inputMappings, false))
uint32_t idForMapping = vkId;
SwapMappingIfEnabled(&idForMapping);
if (!KeyMap::InputMappingsFromPspButton(idForMapping, &inputMappings, false))
continue;
// If a mapping could consist of a combo, we could trivially check it here.
@ -284,7 +321,7 @@ bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping) {
if (iter != curInput_.end()) {
if (mapping.IsAxis()) {
threshold = GetDeviceAxisThreshold(iter->first.deviceId);
product *= MapAxisValue(iter->second, vkId, mapping, changedMapping, &touchedByMapping);
product *= MapAxisValue(iter->second, idForMapping, mapping, changedMapping, &touchedByMapping);
} else {
product *= iter->second;
}
@ -386,6 +423,36 @@ bool ControlMapper::Key(const KeyInput &key, bool *pauseTrigger) {
return UpdatePSPState(mapping);
}
void ControlMapper::ToggleSwapAxes() {
swapAxes_ = !swapAxes_;
// To avoid stuck keys, just reset it all.
for (auto &mapping : curInput_) {
mapping.second = 0.0f;
}
updatePSPButtons_(0, CTRL_LEFT | CTRL_RIGHT | CTRL_UP | CTRL_DOWN);
for (uint32_t vkey = VIRTKEY_FIRST; vkey < VIRTKEY_LAST; vkey++) {
if (IsSwappableVKey(vkey)) {
if (virtKeyOn_[vkey - VIRTKEY_FIRST]) {
onVKey_(vkey, false);
virtKeyOn_[vkey - VIRTKEY_FIRST] = false;
}
if (virtKeys_[vkey - VIRTKEY_FIRST] > 0.0f) {
onVKeyAnalog_(vkey, 0.0f);
virtKeys_[vkey - VIRTKEY_FIRST] = 0.0f;
}
}
}
history_[0][0] = 0.0f;
history_[0][1] = 0.0f;
UpdateAnalogOutput(0);
UpdateAnalogOutput(1);
}
void ControlMapper::Axis(const AxisInput &axis) {
std::lock_guard<std::mutex> guard(mutex_);
if (axis.value >= 0.0f) {

View File

@ -32,11 +32,15 @@ public:
// virtual key codes, though not analog mappings.
void PSPKey(int deviceId, int pspKeyCode, int flags);
// Toggle swapping DPAD and Analog. Useful on some input devices with few buttons.
void ToggleSwapAxes();
void GetDebugString(char *buffer, size_t bufSize) const;
private:
bool UpdatePSPState(const InputMapping &changedMapping);
float MapAxisValue(float value, int vkId, const InputMapping &mapping, const InputMapping &changedMapping, bool *oppositeTouched);
void SwapMappingIfEnabled(uint32_t *vkey);
void SetPSPAxis(int deviceId, int stick, char axis, float value);
void UpdateAnalogOutput(int stick);
@ -57,6 +61,8 @@ private:
bool autoRotatingAnalogCW_ = false;
bool autoRotatingAnalogCCW_ = false;
bool swapAxes_ = false;
// Protects basically all the state.
std::mutex mutex_;

View File

@ -43,8 +43,6 @@ std::set<std::string> g_seenPads;
std::map<int, std::string> g_padNames;
std::set<int> g_seenDeviceIds;
bool g_swapDpadWithLStick = false;
// Utility...
void SingleInputMappingFromPspButton(int btn, std::vector<InputMapping> *mappings, bool ignoreMouse) {
std::vector<MultiInputMapping> multiMappings;
@ -484,29 +482,13 @@ std::vector<KeyMap_IntStrPair> GetMappableKeys() {
return temp;
}
inline int CheckAxisSwap(int btn) {
if (g_swapDpadWithLStick) {
switch (btn) {
case CTRL_UP: btn = VIRTKEY_AXIS_Y_MAX; break;
case VIRTKEY_AXIS_Y_MAX: btn = CTRL_UP; break;
case CTRL_DOWN: btn = VIRTKEY_AXIS_Y_MIN; break;
case VIRTKEY_AXIS_Y_MIN: btn = CTRL_DOWN; break;
case CTRL_LEFT: btn = VIRTKEY_AXIS_X_MIN; break;
case VIRTKEY_AXIS_X_MIN: btn = CTRL_LEFT; break;
case CTRL_RIGHT: btn = VIRTKEY_AXIS_X_MAX; break;
case VIRTKEY_AXIS_X_MAX: btn = CTRL_RIGHT; break;
}
}
return btn;
}
bool InputMappingToPspButton(const InputMapping &mapping, std::vector<int> *pspButtons) {
bool found = false;
for (auto iter = g_controllerMap.begin(); iter != g_controllerMap.end(); ++iter) {
for (auto iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2) {
if (iter2->EqualsSingleMapping(mapping)) {
if (pspButtons)
pspButtons->push_back(CheckAxisSwap(iter->first));
pspButtons->push_back(iter->first);
found = true;
}
}
@ -812,11 +794,6 @@ std::string PadName(int deviceId) {
return "";
}
// Swap direction buttons and left analog axis
void SwapAxis() {
g_swapDpadWithLStick = !g_swapDpadWithLStick;
}
bool HasChanged(int &prevGeneration) {
if (prevGeneration != g_controllerMapGeneration) {
prevGeneration = g_controllerMapGeneration;

View File

@ -199,7 +199,6 @@ namespace KeyMap {
void RestoreDefault();
void SwapAxis();
void UpdateNativeMenuKeys();
void NotifyPadConnected(int deviceId, const std::string &name);

View File

@ -561,6 +561,7 @@ void EmuScreen::touch(const TouchInput &touch) {
void EmuScreen::onVKey(int virtualKeyCode, bool down) {
auto sc = GetI18NCategory(I18NCat::SCREEN);
auto mc = GetI18NCategory(I18NCat::MAPPABLECONTROLS);
switch (virtualKeyCode) {
case VIRTKEY_FASTFORWARD:
@ -647,7 +648,8 @@ void EmuScreen::onVKey(int virtualKeyCode, bool down) {
case VIRTKEY_AXIS_SWAP:
if (down) {
KeyMap::SwapAxis();
controlMapper_.ToggleSwapAxes();
osm.Show(mc->T("AxisSwap")); // best string we have.
}
break;