diff options
| author | Narr the Reg <juangerman-13@hotmail.com> | 2022-11-05 10:39:03 -0600 | 
|---|---|---|
| committer | german77 <juangerman-13@hotmail.com> | 2022-11-19 08:44:33 -0600 | 
| commit | 38c48cf8d896f28f7424b28265110c34f69d2369 (patch) | |
| tree | 5777e9fafc1ec4182068daa8d7a0ab9630d1ee40 | |
| parent | 08091ff3e38665181fedcc476a7b83b84159e7a4 (diff) | |
core: hid: Implement true multitouch support
| -rw-r--r-- | src/core/hid/emulated_console.cpp | 94 | ||||
| -rw-r--r-- | src/core/hid/emulated_console.h | 15 | ||||
| -rw-r--r-- | src/core/hid/input_converter.cpp | 3 | ||||
| -rw-r--r-- | src/input_common/helpers/touch_from_buttons.cpp | 9 | ||||
| -rw-r--r-- | src/input_common/input_poller.cpp | 18 | 
5 files changed, 93 insertions, 46 deletions
| diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index aac45907d..fb7e5802a 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp @@ -19,27 +19,26 @@ void EmulatedConsole::ReloadFromSettings() {  }  void EmulatedConsole::SetTouchParams() { -    // TODO(german77): Support any number of fingers      std::size_t index = 0; -    // Hardcode mouse, touchscreen and cemuhook parameters +    // We can't use mouse as touch if native mouse is enabled      if (!Settings::values.mouse_enabled) { -        // We can't use mouse as touch if native mouse is enabled          touch_params[index++] = Common::ParamPackage{"engine:mouse,axis_x:10,axis_y:11,button:0"};      }      touch_params[index++] = -        Common::ParamPackage{"engine:touch,axis_x:0,axis_y:1,button:0,touch_id:0"}; +        Common::ParamPackage{"engine:cemuhookudp,axis_x:17,axis_y:18,button:65536"};      touch_params[index++] = -        Common::ParamPackage{"engine:touch,axis_x:2,axis_y:3,button:1,touch_id:1"}; -    touch_params[index++] = -        Common::ParamPackage{"engine:touch,axis_x:4,axis_y:5,button:2,touch_id:2"}; -    touch_params[index++] = -        Common::ParamPackage{"engine:touch,axis_x:6,axis_y:7,button:3,touch_id:3"}; -    touch_params[index++] = -        Common::ParamPackage{"engine:cemuhookudp,axis_x:17,axis_y:18,button:65536,touch_id:0"}; -    touch_params[index++] = -        Common::ParamPackage{"engine:cemuhookudp,axis_x:19,axis_y:20,button:131072,touch_id:1"}; +        Common::ParamPackage{"engine:cemuhookudp,axis_x:19,axis_y:20,button:131072"}; + +    for (int i = 0; i < static_cast<int>(MaxActiveTouchInputs); i++) { +        Common::ParamPackage touchscreen_param{}; +        touchscreen_param.Set("engine", "touch"); +        touchscreen_param.Set("axis_x", i * 2); +        touchscreen_param.Set("axis_y", (i * 2) + 1); +        touchscreen_param.Set("button", i); +        touch_params[index++] = touchscreen_param; +    }      const auto button_index =          static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue()); @@ -47,7 +46,7 @@ void EmulatedConsole::SetTouchParams() {      // Map the rest of the fingers from touch from button configuration      for (const auto& config_entry : touch_buttons) { -        if (index >= touch_params.size()) { +        if (index >= MaxTouchDevices) {              continue;          }          Common::ParamPackage params{config_entry}; @@ -60,7 +59,6 @@ void EmulatedConsole::SetTouchParams() {          touch_button_params.Set("button", params.Serialize());          touch_button_params.Set("x", x);          touch_button_params.Set("y", y); -        touch_button_params.Set("touch_id", static_cast<int>(index));          touch_params[index] = touch_button_params;          index++;      } @@ -178,12 +176,38 @@ void EmulatedConsole::SetMotion(const Common::Input::CallbackStatus& callback) {  }  void EmulatedConsole::SetTouch(const Common::Input::CallbackStatus& callback, std::size_t index) { -    if (index >= console.touch_values.size()) { +    if (index >= MaxTouchDevices) {          return;      }      std::unique_lock lock{mutex}; -    console.touch_values[index] = TransformToTouch(callback); +    const auto touch_input = TransformToTouch(callback); +    auto touch_index = GetIndexFromFingerId(index); +    bool is_new_input = false; + +    if (!touch_index.has_value() && touch_input.pressed.value) { +        touch_index = GetNextFreeIndex(); +        is_new_input = true; +    } + +    // No free entries or invalid state. Ignore input +    if (!touch_index.has_value()) { +        return; +    } + +    auto& touch_value = console.touch_values[touch_index.value()]; + +    if (is_new_input) { +        touch_value.pressed.value = true; +        touch_value.id = static_cast<u32>(index); +    } + +    touch_value.x = touch_input.x; +    touch_value.y = touch_input.y; + +    if (!touch_input.pressed.value) { +        touch_value.pressed.value = false; +    }      if (is_configuring) {          lock.unlock(); @@ -191,11 +215,15 @@ void EmulatedConsole::SetTouch(const Common::Input::CallbackStatus& callback, st          return;      } -    // TODO(german77): Remap touch id in sequential order -    console.touch_state[index] = { -        .position = {console.touch_values[index].x.value, console.touch_values[index].y.value}, -        .id = static_cast<u32>(console.touch_values[index].id), -        .pressed = console.touch_values[index].pressed.value, +    // Touch outside allowed range. Ignore input +    if (touch_index.value() >= MaxActiveTouchInputs) { +        return; +    } + +    console.touch_state[touch_index.value()] = { +        .position = {touch_value.x.value, touch_value.y.value}, +        .id = static_cast<u32>(touch_index.value()), +        .pressed = touch_input.pressed.value,      };      lock.unlock(); @@ -222,6 +250,28 @@ TouchFingerState EmulatedConsole::GetTouch() const {      return console.touch_state;  } +std::optional<std::size_t> EmulatedConsole::GetIndexFromFingerId(std::size_t finger_id) const { +    for (std::size_t index = 0; index < MaxTouchDevices; ++index) { +        const auto& finger = console.touch_values[index]; +        if (!finger.pressed.value) { +            continue; +        } +        if (finger.id == static_cast<int>(finger_id)) { +            return index; +        } +    } +    return std::nullopt; +} + +std::optional<std::size_t> EmulatedConsole::GetNextFreeIndex() const { +    for (std::size_t index = 0; index < MaxTouchDevices; ++index) { +        if (!console.touch_values[index].pressed.value) { +            return index; +        } +    } +    return std::nullopt; +} +  void EmulatedConsole::TriggerOnChange(ConsoleTriggerType type) {      std::scoped_lock lock{callback_mutex};      for (const auto& poller_pair : callback_list) { diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h index 1c510cd19..697ecd2d6 100644 --- a/src/core/hid/emulated_console.h +++ b/src/core/hid/emulated_console.h @@ -7,6 +7,7 @@  #include <functional>  #include <memory>  #include <mutex> +#include <optional>  #include <unordered_map>  #include "common/common_funcs.h" @@ -20,6 +21,8 @@  #include "core/hid/motion_input.h"  namespace Core::HID { +static constexpr std::size_t MaxTouchDevices = 32; +static constexpr std::size_t MaxActiveTouchInputs = 16;  struct ConsoleMotionInfo {      Common::Input::MotionStatus raw_status{}; @@ -27,13 +30,13 @@ struct ConsoleMotionInfo {  };  using ConsoleMotionDevices = std::unique_ptr<Common::Input::InputDevice>; -using TouchDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, 16>; +using TouchDevices = std::array<std::unique_ptr<Common::Input::InputDevice>, MaxTouchDevices>;  using ConsoleMotionParams = Common::ParamPackage; -using TouchParams = std::array<Common::ParamPackage, 16>; +using TouchParams = std::array<Common::ParamPackage, MaxTouchDevices>;  using ConsoleMotionValues = ConsoleMotionInfo; -using TouchValues = std::array<Common::Input::TouchStatus, 16>; +using TouchValues = std::array<Common::Input::TouchStatus, MaxTouchDevices>;  struct TouchFinger {      u64 last_touch{}; @@ -55,7 +58,7 @@ struct ConsoleMotion {      bool is_at_rest{};  }; -using TouchFingerState = std::array<TouchFinger, 16>; +using TouchFingerState = std::array<TouchFinger, MaxActiveTouchInputs>;  struct ConsoleStatus {      // Data from input_common @@ -166,6 +169,10 @@ private:       */      void SetTouch(const Common::Input::CallbackStatus& callback, std::size_t index); +    std::optional<std::size_t> GetIndexFromFingerId(std::size_t finger_id) const; + +    std::optional<std::size_t> GetNextFreeIndex() const; +      /**       * Triggers a callback that something has changed on the console status       * @param type Input type of the event to trigger diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp index 5d8b75b50..502692875 100644 --- a/src/core/hid/input_converter.cpp +++ b/src/core/hid/input_converter.cpp @@ -200,9 +200,6 @@ Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus&      x = std::clamp(x, 0.0f, 1.0f);      y = std::clamp(y, 0.0f, 1.0f); -    // Limit id to maximum number of fingers -    status.id = std::clamp(status.id, 0, 16); -      if (status.pressed.inverted) {          status.pressed.value = !status.pressed.value;      } diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp index da4a3dca5..003a38da5 100644 --- a/src/input_common/helpers/touch_from_buttons.cpp +++ b/src/input_common/helpers/touch_from_buttons.cpp @@ -10,8 +10,8 @@ namespace InputCommon {  class TouchFromButtonDevice final : public Common::Input::InputDevice {  public:      using Button = std::unique_ptr<Common::Input::InputDevice>; -    TouchFromButtonDevice(Button button_, int touch_id_, float x_, float y_) -        : button(std::move(button_)), touch_id(touch_id_), x(x_), y(y_) { +    TouchFromButtonDevice(Button button_, float x_, float y_) +        : button(std::move(button_)), x(x_), y(y_) {          last_button_value = false;          button->SetCallback({              .on_change = @@ -34,7 +34,6 @@ public:              .pressed = button_status,              .x = {},              .y = {}, -            .id = touch_id,          };          status.x.properties = properties;          status.y.properties = properties; @@ -62,7 +61,6 @@ public:  private:      Button button;      bool last_button_value; -    const int touch_id;      const float x;      const float y;      const Common::Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false}; @@ -73,10 +71,9 @@ std::unique_ptr<Common::Input::InputDevice> TouchFromButton::Create(      const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize();      auto button = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>(          params.Get("button", null_engine)); -    const auto touch_id = params.Get("touch_id", 0);      const float x = params.Get("x", 0.0f) / 1280.0f;      const float y = params.Get("y", 0.0f) / 720.0f; -    return std::make_unique<TouchFromButtonDevice>(std::move(button), touch_id, x, y); +    return std::make_unique<TouchFromButtonDevice>(std::move(button), x, y);  }  } // namespace InputCommon diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp index 4ac182147..fb8be42e2 100644 --- a/src/input_common/input_poller.cpp +++ b/src/input_common/input_poller.cpp @@ -229,13 +229,12 @@ private:  class InputFromTouch final : public Common::Input::InputDevice {  public: -    explicit InputFromTouch(PadIdentifier identifier_, int touch_id_, int button_, bool toggle_, -                            bool inverted_, int axis_x_, int axis_y_, -                            Common::Input::AnalogProperties properties_x_, +    explicit InputFromTouch(PadIdentifier identifier_, int button_, bool toggle_, bool inverted_, +                            int axis_x_, int axis_y_, Common::Input::AnalogProperties properties_x_,                              Common::Input::AnalogProperties properties_y_,                              InputEngine* input_engine_) -        : identifier(identifier_), touch_id(touch_id_), button(button_), toggle(toggle_), -          inverted(inverted_), axis_x(axis_x_), axis_y(axis_y_), properties_x(properties_x_), +        : identifier(identifier_), button(button_), toggle(toggle_), inverted(inverted_), +          axis_x(axis_x_), axis_y(axis_y_), properties_x(properties_x_),            properties_y(properties_y_), input_engine(input_engine_) {          UpdateCallback engine_callback{[this]() { OnChange(); }};          const InputIdentifier button_input_identifier{ @@ -271,8 +270,7 @@ public:      }      Common::Input::TouchStatus GetStatus() const { -        Common::Input::TouchStatus status; -        status.id = touch_id; +        Common::Input::TouchStatus status{};          status.pressed = {              .value = input_engine->GetButton(identifier, button),              .inverted = inverted, @@ -307,7 +305,6 @@ public:  private:      const PadIdentifier identifier; -    const int touch_id;      const int button;      const bool toggle;      const bool inverted; @@ -919,7 +916,6 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTriggerDevice(  std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTouchDevice(      const Common::ParamPackage& params) { -    const auto touch_id = params.Get("touch_id", 0);      const auto deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, 1.0f);      const auto range = std::clamp(params.Get("range", 1.0f), 0.25f, 1.50f);      const auto threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f); @@ -954,8 +950,8 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTouchDevice(      input_engine->PreSetAxis(identifier, axis_x);      input_engine->PreSetAxis(identifier, axis_y);      input_engine->PreSetButton(identifier, button); -    return std::make_unique<InputFromTouch>(identifier, touch_id, button, toggle, inverted, axis_x, -                                            axis_y, properties_x, properties_y, input_engine.get()); +    return std::make_unique<InputFromTouch>(identifier, button, toggle, inverted, axis_x, axis_y, +                                            properties_x, properties_y, input_engine.get());  }  std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateBatteryDevice( | 
