diff --git a/Common/UI/Screen.cpp b/Common/UI/Screen.cpp index bd8c713da2dc..c66e665494d4 100644 --- a/Common/UI/Screen.cpp +++ b/Common/UI/Screen.cpp @@ -117,27 +117,9 @@ bool ScreenManager::key(const KeyInput &key) { return result; } -void ScreenManager::axis(const AxisInput &axis) { +void ScreenManager::axis(const AxisInput *axes, size_t count) { std::lock_guard guard(inputLock_); - - // Ignore duplicate values to prevent axis values overwriting each other. - uint64_t key = ((uint64_t)axis.axisId << 32) | axis.deviceId; - // Center value far from zero just to ensure we send the first zero. - // PSP games can't see higher resolution than this. - int value = 128 + ceilf(axis.value * 127.5f + 127.5f); - if (lastAxis_[key] == value) { - return; - } - lastAxis_[key] = value; - - // Send center axis to every screen layer. - if (axis.value == 0) { - for (auto &layer : stack_) { - layer.screen->UnsyncAxis(axis); - } - } else if (!stack_.empty()) { - stack_.back().screen->UnsyncAxis(axis); - } + stack_.back().screen->UnsyncAxis(axes, count); } void ScreenManager::deviceLost() { diff --git a/Common/UI/Screen.h b/Common/UI/Screen.h index 217f6d55dcd5..337c14dcee86 100644 --- a/Common/UI/Screen.h +++ b/Common/UI/Screen.h @@ -63,7 +63,7 @@ class Screen { virtual bool UnsyncTouch(const TouchInput &touch) = 0; // Return value of UnsyncKey is used to not block certain system keys like volume when unhandled, on Android. virtual bool UnsyncKey(const KeyInput &touch) = 0; - virtual void UnsyncAxis(const AxisInput &touch) = 0; + virtual void UnsyncAxis(const AxisInput *axes, size_t count) = 0; virtual void RecreateViews() {} @@ -135,7 +135,7 @@ class ScreenManager { // Instant touch, separate from the update() mechanism. void touch(const TouchInput &touch); bool key(const KeyInput &key); - void axis(const AxisInput &touch); + void axis(const AxisInput *axes, size_t count); // Generic facility for gross hacks :P void sendMessage(const char *msg, const char *value); diff --git a/Common/UI/UIScreen.cpp b/Common/UI/UIScreen.cpp index 520375dae502..1e136c9b99ad 100644 --- a/Common/UI/UIScreen.cpp +++ b/Common/UI/UIScreen.cpp @@ -99,12 +99,14 @@ bool UIScreen::UnsyncTouch(const TouchInput &touch) { return false; } -void UIScreen::UnsyncAxis(const AxisInput &axis) { +void UIScreen::UnsyncAxis(const AxisInput *axes, size_t count) { QueuedEvent ev{}; ev.type = QueuedEventType::AXIS; - ev.axis = axis; std::lock_guard guard(eventQueueLock_); - eventQueue_.push_back(ev); + for (size_t i = 0; i < count; i++) { + ev.axis = axes[i]; + eventQueue_.push_back(ev); + } } bool UIScreen::UnsyncKey(const KeyInput &key) { diff --git a/Common/UI/UIScreen.h b/Common/UI/UIScreen.h index f5e232f26c2e..956ebb228fb3 100644 --- a/Common/UI/UIScreen.h +++ b/Common/UI/UIScreen.h @@ -48,7 +48,7 @@ class UIScreen : public Screen { bool UnsyncTouch(const TouchInput &touch) override; bool UnsyncKey(const KeyInput &key) override; - void UnsyncAxis(const AxisInput &axis) override; + void UnsyncAxis(const AxisInput *axes, size_t count) override; TouchInput transformTouch(const TouchInput &touch) override; diff --git a/Common/VR/PPSSPPVR.cpp b/Common/VR/PPSSPPVR.cpp index bf07b9e68efa..83486dded871 100644 --- a/Common/VR/PPSSPPVR.cpp +++ b/Common/VR/PPSSPPVR.cpp @@ -473,11 +473,14 @@ void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale) { } } -bool UpdateVRAxis(const AxisInput &axis) { - if (pspAxis.find(axis.deviceId) == pspAxis.end()) { - pspAxis[axis.deviceId] = std::map(); +bool UpdateVRAxis(const AxisInput *axes, size_t count) { + for (size_t i = 0; i < count; i++) { + const AxisInput &axis = axes[i]; + if (pspAxis.find(axis.deviceId) == pspAxis.end()) { + pspAxis[axis.deviceId] = std::map(); + } + pspAxis[axis.deviceId][axis.axisId] = axis.value; } - pspAxis[axis.deviceId][axis.axisId] = axis.value; return !pspKeys[VIRTKEY_VR_CAMERA_ADJUST]; } diff --git a/Common/VR/PPSSPPVR.h b/Common/VR/PPSSPPVR.h index 489e70bdd726..b78000e4e17e 100644 --- a/Common/VR/PPSSPPVR.h +++ b/Common/VR/PPSSPPVR.h @@ -37,7 +37,7 @@ void SetVRCallbacks(void(*axis)(const AxisInput *axis, size_t count), bool(*key) // VR input integration void SetVRAppMode(VRAppMode mode); void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale); -bool UpdateVRAxis(const AxisInput &axis); +bool UpdateVRAxis(const AxisInput *axes, size_t count); bool UpdateVRKeys(const KeyInput &key); // VR games compatibility diff --git a/Core/ControlMapper.cpp b/Core/ControlMapper.cpp index b27a619cfa07..629b1eaca3ff 100644 --- a/Core/ControlMapper.cpp +++ b/Core/ControlMapper.cpp @@ -476,28 +476,31 @@ void ControlMapper::ToggleSwapAxes() { UpdateAnalogOutput(1); } -void ControlMapper::Axis(const AxisInput &axis) { +void ControlMapper::Axis(const AxisInput *axes, size_t count) { double now = time_now_d(); std::lock_guard guard(mutex_); - size_t deviceIndex = (size_t)axis.deviceId; // this'll wrap around ANY (-1) to max, which will eliminate it on the next line, if such an event appears by mistake. - if (deviceIndex < (size_t)DEVICE_ID_COUNT) { - deviceTimestamps_[deviceIndex] = now; - } - if (axis.value >= 0.0f) { - InputMapping mapping(axis.deviceId, axis.axisId, 1); - InputMapping opposite(axis.deviceId, axis.axisId, -1); - curInput_[mapping] = { axis.value, now }; - curInput_[opposite] = { 0.0f, now }; - UpdatePSPState(mapping, now); - UpdatePSPState(opposite, now); - } else if (axis.value < 0.0f) { - InputMapping mapping(axis.deviceId, axis.axisId, -1); - InputMapping opposite(axis.deviceId, axis.axisId, 1); - curInput_[mapping] = { -axis.value, now }; - curInput_[opposite] = { 0.0f, now }; - UpdatePSPState(mapping, now); - UpdatePSPState(opposite, now); + for (size_t i = 0; i < count; i++) { + const AxisInput &axis = axes[i]; + size_t deviceIndex = (size_t)axis.deviceId; // this wraps -1 up high, so will get rejected on the next line. + if (deviceIndex < (size_t)DEVICE_ID_COUNT) { + deviceTimestamps_[deviceIndex] = now; + } + if (axis.value >= 0.0f) { + InputMapping mapping(axis.deviceId, axis.axisId, 1); + InputMapping opposite(axis.deviceId, axis.axisId, -1); + curInput_[mapping] = { axis.value, now }; + curInput_[opposite] = { 0.0f, now }; + UpdatePSPState(mapping, now); + UpdatePSPState(opposite, now); + } else if (axis.value < 0.0f) { + InputMapping mapping(axis.deviceId, axis.axisId, -1); + InputMapping opposite(axis.deviceId, axis.axisId, 1); + curInput_[mapping] = { -axis.value, now }; + curInput_[opposite] = { 0.0f, now }; + UpdatePSPState(mapping, now); + UpdatePSPState(opposite, now); + } } } diff --git a/Core/ControlMapper.h b/Core/ControlMapper.h index c2d6c4cd1669..24c70a0527e4 100644 --- a/Core/ControlMapper.h +++ b/Core/ControlMapper.h @@ -16,7 +16,7 @@ class ControlMapper { // Inputs to the table-based mapping // These functions are free-threaded. bool Key(const KeyInput &key, bool *pauseTrigger); - void Axis(const AxisInput &axis); + void Axis(const AxisInput *axes, size_t count); // Required callbacks. // TODO: These are so many now that a virtual interface might be more appropriate.. @@ -76,6 +76,8 @@ class ControlMapper { bool swapAxes_ = false; // Protects basically all the state. + // TODO: Maybe we should piggyback on the screenmanager mutex - it's always locked + // when events come in here. std::mutex mutex_; std::map curInput_; diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index 9a4836dc3435..48a11adb68b3 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -535,7 +535,7 @@ void AnalogSetupScreen::axis(const AxisInput &axis) { // UIScreen::axis(axis); // Instead we just send the input directly to the mapper, that we'll visualize. - mapper_.Axis(axis); + mapper_.Axis(&axis, 1); } void AnalogSetupScreen::CreateViews() { diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 09ddf8141169..2397519624b1 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -865,9 +865,9 @@ bool EmuScreen::key(const KeyInput &key) { return retval; } -void EmuScreen::UnsyncAxis(const AxisInput &axis) { +void EmuScreen::UnsyncAxis(const AxisInput *axes, size_t count) { System_Notify(SystemNotification::ACTIVITY); - return controlMapper_.Axis(axis); + return controlMapper_.Axis(axes, count); } class GameInfoBGView : public UI::InertView { diff --git a/UI/EmuScreen.h b/UI/EmuScreen.h index 970844ba186b..e22695cb6d2f 100644 --- a/UI/EmuScreen.h +++ b/UI/EmuScreen.h @@ -53,7 +53,7 @@ class EmuScreen : public UIScreen { // to get minimal latency and full control. We forward to UIScreen when needed. bool UnsyncTouch(const TouchInput &touch) override; bool UnsyncKey(const KeyInput &key) override; - void UnsyncAxis(const AxisInput &axis) override; + void UnsyncAxis(const AxisInput *axes, size_t count) override; // We also need to do some special handling of queued UI events to handle closing the chat window. bool key(const KeyInput &key) override; diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index f4056c10b32b..fbcc24be0d33 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1319,9 +1319,9 @@ bool NativeKey(const KeyInput &key) { return retval; } -static void ProcessOneAxisEvent(const AxisInput &axis) { +void NativeAxis(const AxisInput *axes, size_t count) { // VR actions - if (IsVREnabled() && !UpdateVRAxis(axis)) { + if (IsVREnabled() && !UpdateVRAxis(axes, count)) { return; } @@ -1330,14 +1330,11 @@ static void ProcessOneAxisEvent(const AxisInput &axis) { return; } - // only do special handling of tilt events if tilt is enabled. - HLEPlugins::PluginDataAxis[axis.axisId] = axis.value; - g_screenManager->axis(axis); -} + g_screenManager->axis(axes, count); -void NativeAxis(const AxisInput *axes, size_t count) { for (size_t i = 0; i < count; i++) { - ProcessOneAxisEvent(axes[i]); + const AxisInput &axis = axes[i]; + HLEPlugins::PluginDataAxis[axis.axisId] = axis.value; } }