From c82806f9cb88f390ae3fb048ba7ff2bb138fa3ec Mon Sep 17 00:00:00 2001 From: german77 Date: Sun, 22 May 2022 20:34:32 -0500 Subject: input_common: touch: Rewrite touch driver to support multiple touch points --- src/input_common/drivers/touch_screen.cpp | 89 +++++++++++++++++++++++++------ src/input_common/drivers/touch_screen.h | 52 +++++++++++++----- 2 files changed, 110 insertions(+), 31 deletions(-) (limited to 'src/input_common/drivers') diff --git a/src/input_common/drivers/touch_screen.cpp b/src/input_common/drivers/touch_screen.cpp index 8acbe4584..1753e0893 100644 --- a/src/input_common/drivers/touch_screen.cpp +++ b/src/input_common/drivers/touch_screen.cpp @@ -14,38 +14,93 @@ constexpr PadIdentifier identifier = { TouchScreen::TouchScreen(std::string input_engine_) : InputEngine(std::move(input_engine_)) { PreSetController(identifier); + ReleaseAllTouch(); } -void TouchScreen::TouchMoved(float x, float y, std::size_t finger) { - if (finger >= 16) { +void TouchScreen::TouchMoved(float x, float y, std::size_t finger_id) { + const auto index = GetIndexFromFingerId(finger_id); + if (!index) { + // Touch doesn't exist handle it as a new one + TouchPressed(x, y, finger_id); return; } - TouchPressed(x, y, finger); + const auto i = index.value(); + fingers[i].is_active = true; + SetButton(identifier, static_cast(i), true); + SetAxis(identifier, static_cast(i * 2), x); + SetAxis(identifier, static_cast(i * 2 + 1), y); } -void TouchScreen::TouchPressed(float x, float y, std::size_t finger) { - if (finger >= 16) { +void TouchScreen::TouchPressed(float x, float y, std::size_t finger_id) { + if (GetIndexFromFingerId(finger_id)) { + // Touch already exist. Just update the data + TouchMoved(x, y, finger_id); return; } - SetButton(identifier, static_cast(finger), true); - SetAxis(identifier, static_cast(finger * 2), x); - SetAxis(identifier, static_cast(finger * 2 + 1), y); + const auto index = GetNextFreeIndex(); + if (!index) { + // No free entries. Ignore input + return; + } + const auto i = index.value(); + fingers[i].is_enabled = true; + fingers[i].finger_id = finger_id; + TouchMoved(x, y, finger_id); } -void TouchScreen::TouchReleased(std::size_t finger) { - if (finger >= 16) { +void TouchScreen::TouchReleased(std::size_t finger_id) { + const auto index = GetIndexFromFingerId(finger_id); + if (!index) { return; } - SetButton(identifier, static_cast(finger), false); - SetAxis(identifier, static_cast(finger * 2), 0.0f); - SetAxis(identifier, static_cast(finger * 2 + 1), 0.0f); + const auto i = index.value(); + fingers[i].is_enabled = false; + SetButton(identifier, static_cast(i), false); + SetAxis(identifier, static_cast(i * 2), 0.0f); + SetAxis(identifier, static_cast(i * 2 + 1), 0.0f); +} + +std::optional TouchScreen::GetIndexFromFingerId(std::size_t finger_id) const { + for (std::size_t index = 0; index < MAX_FINGER_COUNT; ++index) { + const auto& finger = fingers[index]; + if (!finger.is_enabled) { + continue; + } + if (finger.finger_id == finger_id) { + return index; + } + } + return std::nullopt; +} + +std::optional TouchScreen::GetNextFreeIndex() const { + for (std::size_t index = 0; index < MAX_FINGER_COUNT; ++index) { + if (!fingers[index].is_enabled) { + return index; + } + } + return std::nullopt; +} + +void TouchScreen::ClearActiveFlag() { + for (auto& finger : fingers) { + finger.is_active = false; + } +} + +void TouchScreen::ReleaseInactiveTouch() { + for (const auto& finger : fingers) { + if (!finger.is_active) { + TouchReleased(finger.finger_id); + } + } } void TouchScreen::ReleaseAllTouch() { - for (int index = 0; index < 16; ++index) { - SetButton(identifier, index, false); - SetAxis(identifier, index * 2, 0.0f); - SetAxis(identifier, index * 2 + 1, 0.0f); + for (const auto& finger : fingers) { + if (finger.is_enabled) { + TouchReleased(finger.finger_id); + } } } diff --git a/src/input_common/drivers/touch_screen.h b/src/input_common/drivers/touch_screen.h index 193478ead..f46036ffd 100644 --- a/src/input_common/drivers/touch_screen.h +++ b/src/input_common/drivers/touch_screen.h @@ -3,41 +3,65 @@ #pragma once +#include + #include "input_common/input_engine.h" namespace InputCommon { /** - * A button device factory representing a keyboard. It receives keyboard events and forward them - * to all button devices it created. + * A touch device factory representing a touch screen. It receives touch events and forward them + * to all touch devices it created. */ class TouchScreen final : public InputEngine { public: explicit TouchScreen(std::string input_engine_); /** - * Signals that mouse has moved. - * @param x the x-coordinate of the cursor - * @param y the y-coordinate of the cursor - * @param center_x the x-coordinate of the middle of the screen - * @param center_y the y-coordinate of the middle of the screen + * Signals that touch has moved and marks this touch point as active + * @param x new horizontal position + * @param y new vertical position + * @param finger_id of the touch point to be updated */ - void TouchMoved(float x, float y, std::size_t finger); + void TouchMoved(float x, float y, std::size_t finger_id); /** - * Sets the status of all buttons bound with the key to pressed - * @param key_code the code of the key to press + * Signals and creates a new touch point with this finger id + * @param x starting horizontal position + * @param y starting vertical position + * @param finger_id to be assigned to the new touch point */ - void TouchPressed(float x, float y, std::size_t finger); + void TouchPressed(float x, float y, std::size_t finger_id); /** - * Sets the status of all buttons bound with the key to released - * @param key_code the code of the key to release + * Signals and resets the touch point related to the this finger id + * @param finger_id to be released */ - void TouchReleased(std::size_t finger); + void TouchReleased(std::size_t finger_id); + + /// Resets the active flag for each touch point + void ClearActiveFlag(); + + /// Releases all touch that haven't been marked as active + void ReleaseInactiveTouch(); /// Resets all inputs to their initial value void ReleaseAllTouch(); + +private: + static constexpr std::size_t MAX_FINGER_COUNT = 16; + + struct TouchStatus { + std::size_t finger_id{}; + bool is_enabled{}; + bool is_active{}; + }; + + std::optional GetIndexFromFingerId(std::size_t finger_id) const; + + std::optional GetNextFreeIndex() const; + + std::array fingers{}; }; } // namespace InputCommon -- cgit v1.2.3