From 526b4f782de8226bc72389b79067b93ab0b41f35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 29 Mar 2023 13:50:57 +0200 Subject: [PATCH] Fixes, add callback for analog virtual keys Some fixes --- Core/ControlMapper.cpp | 308 +++++++++++++----------------------- Core/ControlMapper.h | 29 +--- Core/KeyMap.cpp | 49 ++++++ Core/KeyMap.h | 4 +- UI/ControlMappingScreen.cpp | 1 + UI/EmuScreen.cpp | 1 + 6 files changed, 173 insertions(+), 219 deletions(-) diff --git a/Core/ControlMapper.cpp b/Core/ControlMapper.cpp index 13476e4973..354005a157 100644 --- a/Core/ControlMapper.cpp +++ b/Core/ControlMapper.cpp @@ -11,6 +11,27 @@ #include "Core/CoreParameter.h" #include "Core/System.h" +// TODO: Possibly make these configurable? +static float GetDeviceAxisThreshold(int device) { + return device == DEVICE_ID_MOUSE ? AXIS_BIND_THRESHOLD_MOUSE : AXIS_BIND_THRESHOLD; +} + +static int GetOppositeVKey(int vkey) { + switch (vkey) { + case VIRTKEY_AXIS_X_MIN: return VIRTKEY_AXIS_X_MAX; break; + case VIRTKEY_AXIS_X_MAX: return VIRTKEY_AXIS_X_MIN; break; + case VIRTKEY_AXIS_Y_MIN: return VIRTKEY_AXIS_Y_MAX; break; + case VIRTKEY_AXIS_Y_MAX: return VIRTKEY_AXIS_Y_MIN; break; + case VIRTKEY_AXIS_RIGHT_X_MIN: return VIRTKEY_AXIS_RIGHT_X_MAX; break; + case VIRTKEY_AXIS_RIGHT_X_MAX: return VIRTKEY_AXIS_RIGHT_X_MIN; break; + case VIRTKEY_AXIS_RIGHT_Y_MIN: return VIRTKEY_AXIS_RIGHT_Y_MAX; break; + case VIRTKEY_AXIS_RIGHT_Y_MAX: return VIRTKEY_AXIS_RIGHT_Y_MIN; break; + default: + return 0; + } +} + +// This is applied on the circular radius, not directly on the axes. static float MapAxisValue(float v) { const float deadzone = g_Config.fAnalogDeadzone; const float invDeadzone = g_Config.fAnalogInverseDeadzone; @@ -20,11 +41,6 @@ static float MapAxisValue(float v) { return sign * Clamp(invDeadzone + (abs(v) - deadzone) / (1.0f - deadzone) * (sensitivity - invDeadzone), 0.0f, 1.0f); } -// TODO: Possibly make these configurable? -float GetDeviceAxisThreshold(int device) { - return device == DEVICE_ID_MOUSE ? AXIS_BIND_THRESHOLD_MOUSE : AXIS_BIND_THRESHOLD; -} - void ConvertAnalogStick(float &x, float &y) { const bool isCircular = g_Config.bAnalogIsCircular; @@ -48,10 +64,12 @@ void ConvertAnalogStick(float &x, float &y) { void ControlMapper::SetCallbacks( std::function onVKey, + std::function onVKeyAnalog, std::function setAllPSPButtonStates, std::function setPSPButtonState, std::function setPSPAnalog) { onVKey_ = onVKey; + onVKeyAnalog_ = onVKey; setAllPSPButtonStates_ = setAllPSPButtonStates; setPSPButtonState_ = setPSPButtonState; setPSPAnalog_ = setPSPAnalog; @@ -61,7 +79,7 @@ void ControlMapper::SetRawCallback(std::function setRaw setRawAnalog_ = setRawAnalog; } -void ControlMapper::SetPSPAxis(int device, char axis, float value, int stick) { +void ControlMapper::SetPSPAxis(int device, int stick, char axis, float value) { int axisId = axis == 'X' ? 0 : 1; float position[2]; @@ -113,7 +131,7 @@ static int RotatePSPKeyCode(int x) { } } -bool ControlMapper::UpdatePSPState() { +bool ControlMapper::UpdatePSPState(const InputMapping &changedMapping) { // Instead of taking an input key and finding what it outputs, we loop through the OUTPUTS and // see if the input that corresponds to it has a value. That way we can easily implement all sorts // of crazy input combos if needed. @@ -127,6 +145,7 @@ bool ControlMapper::UpdatePSPState() { // For the PSP's button inputs, we just go through and put the flags together. uint32_t buttonMask = 0; + uint32_t changedButtonMask = 0; for (int i = 0; i < 32; i++) { uint32_t mask = 1 << i; if (!(mask & CTRL_MASK_USER)) { @@ -134,25 +153,31 @@ bool ControlMapper::UpdatePSPState() { continue; } - uint32_t mapping = mask; + uint32_t mappingBit = mask; for (int i = 0; i < rotations; i++) { - mapping = RotatePSPKeyCode(mapping); + mappingBit = RotatePSPKeyCode(mappingBit); } std::vector inputMappings; - if (!KeyMap::InputMappingsFromPspButton(mapping, &inputMappings, false)) + if (!KeyMap::InputMappingsFromPspButton(mappingBit, &inputMappings, false)) continue; // If a mapping could consist of a combo, we could trivially check it here. - for (int j = 0; j < inputMappings.size(); j++) { - auto iter = curInput_.find(inputMappings[j]) ; + for (auto &mapping : inputMappings) { + // Check if the changed mapping was involved in this PSP key. + if (changedMapping == mapping) { + changedButtonMask |= mask; + } + + auto iter = curInput_.find(mapping); if (iter != curInput_.end() && iter->second > GetDeviceAxisThreshold(iter->first.deviceId)) { buttonMask |= mask; } } } - setAllPSPButtonStates_(buttonMask); + // We only request changing the buttons where the mapped input was involved. + setAllPSPButtonStates_(buttonMask & changedButtonMask, (~buttonMask) & changedButtonMask); // OK, handle all the virtual keys next. For these we need to do deltas here and send events. for (int i = 0; i < VIRTKEY_COUNT; i++) { @@ -160,32 +185,50 @@ bool ControlMapper::UpdatePSPState() { std::vector inputMappings; if (!KeyMap::InputMappingsFromPspButton(vkId, &inputMappings, false)) continue; - bool value = false; + float value = 0.0f; // If a mapping could consist of a combo, we could trivially check it here. - for (int j = 0; j < inputMappings.size(); j++) { - auto iter = curInput_.find(inputMappings[j]); - if (iter != curInput_.end() && iter->second > GetDeviceAxisThreshold(iter->first.deviceId)) { - value = true; + // Save the first device ID so we can pass it into onVKeyDown, which in turn needs it for the analog + // mapping which gets a little hacky. + float threshold = 1.0f; + bool touchedByMapping = false; + for (auto &mapping : inputMappings) { + if (mapping == changedMapping) { + touchedByMapping = true; + } + + auto iter = curInput_.find(mapping); + if (iter != curInput_.end()) { + if (mapping.IsAxis()) { + threshold = GetDeviceAxisThreshold(iter->first.deviceId); + value += iter->second; + } else { + value += iter->second; + } } } - if (!lastVirtKeys_[i] && value) { - onVKeyDown_(vkId); - } else if (lastVirtKeys_[i] && !value) { - onVKeyUp_(vkId); + if (!touchedByMapping) { + continue; + } + + value = clamp_value(value, 0.0f, 1.0f); + + // Derive bools from the floats using the device's threshold. + bool bPrevValue = virtKeys_[i] >= threshold; + bool bValue = value >= threshold; + if (virtKeys_[i] != value) { + // INFO_LOG(G3D, "vkeyanalog %s : %f", KeyMap::GetVirtKeyName(vkId), value); + onVKeyAnalog(changedMapping.deviceId, vkId, value); + } + virtKeys_[i] = value; + if (!bPrevValue && bValue) { + onVKey(vkId, true); + } else if (bPrevValue && !bValue) { + onVKey(vkId, false); } - lastVirtKeys_[i] = value; } - // Now let's look at the four axes. - // for (int i = 0; i < 4; i++) { - - // } - - // TODO: Here we need to diff pspState with prevPspState_ to generate - // any new PSP key events. Though for the actual PSP buttons themselves (not the sticks), - // we could just or them together and set them all at once. return true; } @@ -200,10 +243,10 @@ bool ControlMapper::Key(const KeyInput &key, bool *pauseTrigger) { if (key.flags & KEY_DOWN) { curInput_[mapping] = 1.0f; } else if (key.flags & KEY_UP) { - curInput_.erase(mapping); + curInput_[mapping] = 0.0f; } - bool mappingFound = KeyMap::InputMappingToPspButton(InputMapping(key.deviceId, key.keyCode), nullptr); + bool mappingFound = KeyMap::InputMappingToPspButton(mapping, nullptr); DEBUG_LOG(SYSTEM, "Key: %d DeviceId: %d", key.keyCode, key.deviceId); if (!mappingFound || key.deviceId == DEVICE_ID_DEFAULT) { if ((key.flags & KEY_DOWN) && key.keyCode == NKCODE_BACK) { @@ -212,22 +255,26 @@ bool ControlMapper::Key(const KeyInput &key, bool *pauseTrigger) { } } - return UpdatePSPState(); + return UpdatePSPState(mapping); } void ControlMapper::Axis(const AxisInput &axis) { if (axis.value > 0) { InputMapping mapping(axis.deviceId, axis.axisId, 1); curInput_[mapping] = axis.value; + UpdatePSPState(mapping); } else if (axis.value < 0) { InputMapping mapping(axis.deviceId, axis.axisId, -1); - curInput_[mapping] = axis.value; + curInput_[mapping] = -axis.value; + UpdatePSPState(mapping); } else if (axis.value == 0.0f) { // Threshold? // Both directions! Prevents sticking for digital input devices that are axises (like HAT) - InputMapping mappingPositive(axis.deviceId, axis.axisId, -1); + InputMapping mappingPositive(axis.deviceId, axis.axisId, 1); InputMapping mappingNegative(axis.deviceId, axis.axisId, -1); curInput_[mappingPositive] = 0.0f; curInput_[mappingNegative] = 0.0f; + UpdatePSPState(mappingPositive); + UpdatePSPState(mappingNegative); } } @@ -248,55 +295,16 @@ void ControlMapper::Update() { } } -inline bool IsAnalogStickKey(int key) { - switch (key) { - case VIRTKEY_AXIS_X_MIN: - case VIRTKEY_AXIS_X_MAX: - case VIRTKEY_AXIS_Y_MIN: - case VIRTKEY_AXIS_Y_MAX: - case VIRTKEY_AXIS_RIGHT_X_MIN: - case VIRTKEY_AXIS_RIGHT_X_MAX: - case VIRTKEY_AXIS_RIGHT_Y_MIN: - case VIRTKEY_AXIS_RIGHT_Y_MAX: - return true; - default: - return false; - } -} - -void ControlMapper::SetVKeyAnalog(int deviceId, char axis, int stick, int virtualKeyMin, int virtualKeyMax, bool setZero) { - /* - // The down events can repeat, so just trust the virtKeys_ array. - bool minDown = virtKeys_[virtualKeyMin - VIRTKEY_FIRST]; - bool maxDown = virtKeys_[virtualKeyMax - VIRTKEY_FIRST]; - - const float scale = virtKeys_[VIRTKEY_ANALOG_LIGHTLY - VIRTKEY_FIRST] ? g_Config.fAnalogLimiterDeadzone : 1.0f; - float value = 0.0f; - if (minDown) - value -= scale; - if (maxDown) - value += scale; - if (setZero || minDown || maxDown) { - SetPSPAxis(deviceId, axis, value, stick); - } - */ -} - void ControlMapper::PSPKey(int deviceId, int pspKeyCode, int flags) { - SetPSPKey(deviceId, pspKeyCode, flags); -} - -void ControlMapper::SetPSPKey(int deviceId, int pspKeyCode, int flags) { - /* if (pspKeyCode >= VIRTKEY_FIRST) { int vk = pspKeyCode - VIRTKEY_FIRST; if (flags & KEY_DOWN) { - virtKeys_[vk] = true; - onVKey(deviceId, pspKeyCode, true); + virtKeys_[vk] = 1.0f; + onVKey(pspKeyCode, true); } if (flags & KEY_UP) { - virtKeys_[vk] = false; - onVKey(deviceId, pspKeyCode, false); + virtKeys_[vk] = 0.0f; + onVKey(pspKeyCode, false); } } else { // INFO_LOG(SYSTEM, "pspKey %d %d", pspKeyCode, flags); @@ -305,36 +313,35 @@ void ControlMapper::SetPSPKey(int deviceId, int pspKeyCode, int flags) { if (flags & KEY_UP) setPSPButtonState_(pspKeyCode, false); } - */ } -void ControlMapper::onVKey(int deviceId, int vkey, bool down) { +void ControlMapper::onVKeyAnalog(int deviceId, int vkey, float value) { + // Unfortunately, for digital->analog inputs to work sanely, we need to sum up + // with the opposite value too. + int stick = 0; + int axis = 'X'; + int opposite = GetOppositeVKey(vkey); + float sign = 1.0f; switch (vkey) { - case VIRTKEY_AXIS_X_MIN: - case VIRTKEY_AXIS_X_MAX: - SetVKeyAnalog(deviceId, 'X', CTRL_STICK_LEFT, VIRTKEY_AXIS_X_MIN, VIRTKEY_AXIS_X_MAX); - break; - case VIRTKEY_AXIS_Y_MIN: - case VIRTKEY_AXIS_Y_MAX: - SetVKeyAnalog(deviceId, 'Y', CTRL_STICK_LEFT, VIRTKEY_AXIS_Y_MIN, VIRTKEY_AXIS_Y_MAX); - break; - - case VIRTKEY_AXIS_RIGHT_X_MIN: - case VIRTKEY_AXIS_RIGHT_X_MAX: - SetVKeyAnalog(deviceId, 'X', CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_X_MIN, VIRTKEY_AXIS_RIGHT_X_MAX); - break; - case VIRTKEY_AXIS_RIGHT_Y_MIN: - case VIRTKEY_AXIS_RIGHT_Y_MAX: - SetVKeyAnalog(deviceId, 'Y', CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_Y_MIN, VIRTKEY_AXIS_RIGHT_Y_MAX); - break; - - case VIRTKEY_ANALOG_LIGHTLY: - SetVKeyAnalog(deviceId, 'X', CTRL_STICK_LEFT, VIRTKEY_AXIS_X_MIN, VIRTKEY_AXIS_X_MAX, false); - SetVKeyAnalog(deviceId, 'Y', CTRL_STICK_LEFT, VIRTKEY_AXIS_Y_MIN, VIRTKEY_AXIS_Y_MAX, false); - SetVKeyAnalog(deviceId, 'X', CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_X_MIN, VIRTKEY_AXIS_RIGHT_X_MAX, false); - SetVKeyAnalog(deviceId, 'Y', CTRL_STICK_RIGHT, VIRTKEY_AXIS_RIGHT_Y_MIN, VIRTKEY_AXIS_RIGHT_Y_MAX, false); - break; + case VIRTKEY_AXIS_X_MIN: sign = -1.0f; break; + case VIRTKEY_AXIS_X_MAX: break; + case VIRTKEY_AXIS_Y_MIN: axis = 'Y'; sign = -1.0f; break; + case VIRTKEY_AXIS_Y_MAX: axis = 'Y'; break; + case VIRTKEY_AXIS_RIGHT_X_MIN: stick = CTRL_STICK_RIGHT; sign = -1.0f; break; + case VIRTKEY_AXIS_RIGHT_X_MAX: stick = CTRL_STICK_RIGHT; break; + case VIRTKEY_AXIS_RIGHT_Y_MIN: stick = CTRL_STICK_RIGHT; axis = 'Y'; sign = -1.0f; break; + case VIRTKEY_AXIS_RIGHT_Y_MAX: stick = CTRL_STICK_RIGHT; axis = 'Y'; break; + default: + if (onVKeyAnalog_) + onVKeyAnalog_(vkey, value); + return; + } + value -= virtKeys_[opposite - VIRTKEY_FIRST]; + SetPSPAxis(deviceId, stick, axis, sign * value); +} +void ControlMapper::onVKey(int vkey, bool down) { + switch (vkey) { case VIRTKEY_ANALOG_ROTATE_CW: if (down) { autoRotatingAnalogCW_ = true; @@ -353,7 +360,6 @@ void ControlMapper::onVKey(int deviceId, int vkey, bool down) { setPSPAnalog_(0, 0.0f, 0.0f); } break; - default: if (onVKey_) onVKey_(vkey, down); @@ -361,96 +367,6 @@ void ControlMapper::onVKey(int deviceId, int vkey, bool down) { } } -void ControlMapper::ProcessAxis(const AxisInput &axis, int direction) { - // Sanity check - if (axis.axisId < 0 || axis.axisId >= JOYSTICK_AXIS_MAX) { - return; - } - - const float scale = lastVirtKeys_[VIRTKEY_ANALOG_LIGHTLY - VIRTKEY_FIRST] ? g_Config.fAnalogLimiterDeadzone : 1.0f; - - std::vector results; - KeyMap::InputMappingToPspButton(InputMapping(axis.deviceId, axis.axisId, direction), &results); - - for (int result : results) { - float value = fabs(axis.value) * scale; - switch (result) { - case VIRTKEY_AXIS_X_MIN: - SetPSPAxis(axis.deviceId, 'X', -value, CTRL_STICK_LEFT); - break; - case VIRTKEY_AXIS_X_MAX: - SetPSPAxis(axis.deviceId, 'X', value, CTRL_STICK_LEFT); - break; - case VIRTKEY_AXIS_Y_MIN: - SetPSPAxis(axis.deviceId, 'Y', -value, CTRL_STICK_LEFT); - break; - case VIRTKEY_AXIS_Y_MAX: - SetPSPAxis(axis.deviceId, 'Y', value, CTRL_STICK_LEFT); - break; - - case VIRTKEY_AXIS_RIGHT_X_MIN: - SetPSPAxis(axis.deviceId, 'X', -value, CTRL_STICK_RIGHT); - break; - case VIRTKEY_AXIS_RIGHT_X_MAX: - SetPSPAxis(axis.deviceId, 'X', value, CTRL_STICK_RIGHT); - break; - case VIRTKEY_AXIS_RIGHT_Y_MIN: - SetPSPAxis(axis.deviceId, 'Y', -value, CTRL_STICK_RIGHT); - break; - case VIRTKEY_AXIS_RIGHT_Y_MAX: - SetPSPAxis(axis.deviceId, 'Y', value, CTRL_STICK_RIGHT); - break; - - case VIRTKEY_SPEED_ANALOG: - ProcessAnalogSpeed(axis, false); - break; - } - } - - std::vector resultsOpposite; - KeyMap::InputMappingToPspButton(InputMapping(axis.deviceId, axis.axisId, -direction), &resultsOpposite); - - for (int result : resultsOpposite) { - if (result == VIRTKEY_SPEED_ANALOG) - ProcessAnalogSpeed(axis, true); - } - - int axisState = 0; - float threshold = GetDeviceAxisThreshold(axis.deviceId); - if (direction == 1 && axis.value >= threshold) { - axisState = 1; - } else if (direction == -1 && axis.value <= -threshold) { - axisState = -1; - } else { - axisState = 0; - } - - if (axisState != axisState_[axis.axisId]) { - axisState_[axis.axisId] = axisState; - if (axisState != 0) { - for (size_t i = 0; i < results.size(); i++) { - if (!IsAnalogStickKey(results[i])) - SetPSPKey(axis.deviceId, results[i], KEY_DOWN); - } - // Also unpress the other direction (unless both directions press the same key.) - for (size_t i = 0; i < resultsOpposite.size(); i++) { - if (!IsAnalogStickKey(resultsOpposite[i]) && std::find(results.begin(), results.end(), resultsOpposite[i]) == results.end()) - SetPSPKey(axis.deviceId, resultsOpposite[i], KEY_UP); - } - } else if (axisState == 0) { - // Release both directions, trying to deal with some erratic controllers that can cause it to stick. - for (size_t i = 0; i < results.size(); i++) { - if (!IsAnalogStickKey(results[i])) - SetPSPKey(axis.deviceId, results[i], KEY_UP); - } - for (size_t i = 0; i < resultsOpposite.size(); i++) { - if (!IsAnalogStickKey(resultsOpposite[i])) - SetPSPKey(axis.deviceId, resultsOpposite[i], KEY_UP); - } - } - } -} - void ControlMapper::ProcessAnalogSpeed(const AxisInput &axis, bool opposite) { static constexpr float DEADZONE_THRESHOLD = 0.15f; static constexpr float DEADZONE_SCALE = 1.0f / (1.0f - DEADZONE_THRESHOLD); diff --git a/Core/ControlMapper.h b/Core/ControlMapper.h index a84b285873..cbcab1ce0b 100644 --- a/Core/ControlMapper.h +++ b/Core/ControlMapper.h @@ -8,21 +8,6 @@ // Utilities for mapping input events to PSP inputs and virtual keys. // Main use is of course from EmuScreen.cpp, but also useful from control settings etc. - -// At some point I want to refactor this from using callbacks to simply providing lists of events. -// Still it won't be able to be completely stateless due to the 2-D processing of analog sticks. - -// Unified representation. Might spread across the code base later. -struct ControlInputKey { - int direction; // 0 if key, 1 or -1 if axis. - int deviceId; - int controlId; // key or axis. - - bool operator < (const ControlInputKey &other) const { - return memcmp(this, &other, sizeof(*this)) < 0; - } -}; - class ControlMapper { public: void Update(); @@ -34,6 +19,7 @@ public: // Required callbacks void SetCallbacks( std::function onVKey, + std::function onVKeyAnalog, std::function setAllPSPButtonStates_, std::function setPSPButtonState, std::function setPSPAnalog); @@ -46,19 +32,17 @@ public: void SetRawCallback(std::function setRawAnalog); private: - bool UpdatePSPState(); + bool UpdatePSPState(const InputMapping &changedMapping); - void ProcessAxis(const AxisInput &axis, int direction); - void SetVKeyAnalog(int deviceId, char axis, int stick, int virtualKeyMin, int virtualKeyMax, bool setZero = true); + void SetPSPAxis(int deviceId, int stick, char axis, float value); - void SetPSPKey(int deviceId, int pspKeyCode, int flags); - void SetPSPAxis(int deviceId, char axis, float value, int stick); void ProcessAnalogSpeed(const AxisInput &axis, bool opposite); - void onVKey(int deviceId, int vkey, bool down); + void onVKey(int vkey, bool down); + void onVKeyAnalog(int deviceId, int vkey, float value); // To track mappable virtual keys. We can have as many as we want. - bool lastVirtKeys_[VIRTKEY_COUNT]{}; + float virtKeys_[VIRTKEY_COUNT]{}; // De-noise mapped axis updates int axisState_[JOYSTICK_AXIS_MAX]{}; @@ -75,6 +59,7 @@ private: // Callbacks std::function onVKey_; + std::function onVKeyAnalog_; std::function setAllPSPButtonStates_; std::function setPSPButtonState_; std::function setPSPAnalog_; diff --git a/Core/KeyMap.cpp b/Core/KeyMap.cpp index f303ab3978..a7742296bc 100644 --- a/Core/KeyMap.cpp +++ b/Core/KeyMap.cpp @@ -784,4 +784,53 @@ bool HasChanged(int &prevGeneration) { return false; } +static const char *g_vKeyNames[] = { + "AXIS_X_MIN", + "AXIS_Y_MIN", + "AXIS_X_MAX", + "AXIS_Y_MAX", + "RAPID_FIRE", + "FASTFORWARD", + "PAUSE", + "SPEED_TOGGLE", + "AXIS_RIGHT_X_MIN", + "AXIS_RIGHT_Y_MIN", + "AXIS_RIGHT_X_MAX", + "AXIS_RIGHT_Y_MAX", + "REWIND", + "SAVE_STATE", + "LOAD_STATE", + "NEXT_SLOT", + "TOGGLE_FULLSCREEN", + "ANALOG_LIGHTLY", + "AXIS_SWAP", + "DEVMENU", + "FRAME_ADVANCE", + "RECORD", + "SPEED_CUSTOM1", + "SPEED_CUSTOM2", + "TEXTURE_DUMP", + "TEXTURE_REPLACE", + "SCREENSHOT", + "MUTE_TOGGLE", + "OPENCHAT", + "ANALOG_ROTATE_CW", + "ANALOG_ROTATE_CCW", + "SCREEN_ROTATION_VERTICAL", + "SCREEN_ROTATION_VERTICAL180", + "SCREEN_ROTATION_HORIZONTAL", + "SCREEN_ROTATION_HORIZONTAL180", + "SPEED_ANALOG", + "VR_CAMERA_ADJUST", + "VR_CAMERA_RESET", +}; + +const char *GetVirtKeyName(int vkey) { + int index = vkey - VIRTKEY_FIRST; + if (index < 0 || index >= ARRAY_SIZE(g_vKeyNames)) { + return "N/A"; + } + return g_vKeyNames[index]; +} + } // KeyMap diff --git a/Core/KeyMap.h b/Core/KeyMap.h index 3d41e86c29..113117173b 100644 --- a/Core/KeyMap.h +++ b/Core/KeyMap.h @@ -29,6 +29,7 @@ #define KEYMAP_ERROR_KEY_ALREADY_USED -1 #define KEYMAP_ERROR_UNKNOWN_KEY 0 +// Don't change any of these - it'll break backwards compatibility with configs. enum { VIRTKEY_FIRST = 0x40000001, VIRTKEY_AXIS_X_MIN = 0x40000001, @@ -118,7 +119,8 @@ namespace KeyMap { std::string GetKeyOrAxisName(const InputMapping &mapping); std::string GetAxisName(int axisId); std::string GetPspButtonName(int btn); - const char* GetPspButtonNameCharPointer(int btn); + const char *GetVirtKeyName(int vkey); + const char *GetPspButtonNameCharPointer(int btn); std::vector GetMappableKeys(); diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index 1c4ee31635..8aad793e0d 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -450,6 +450,7 @@ void KeyMappingNewMouseKeyDialog::axis(const AxisInput &axis) { AnalogSetupScreen::AnalogSetupScreen(const Path &gamePath) : UIDialogScreenWithGameBackground(gamePath) { mapper_.SetCallbacks( [](int vkey, bool down) {}, + [](int vkey, float analogValue) {}, [&](uint32_t bitsToSet, uint32_t bitsToClear) {}, [&](int button, bool down) {}, [&](int stick, float x, float y) { diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index af665bdd6c..74bc85fc33 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -177,6 +177,7 @@ EmuScreen::EmuScreen(const Path &filename) startDumping = false; controlMapper_.SetCallbacks( std::bind(&EmuScreen::onVKey, this, _1, _2), + [](int vkey, float analogValue) {}, [](uint32_t bitsToSet, uint32_t bitsToClear) { __CtrlSetAllButtons(bitsToSet, bitsToClear); },