3
0
Fork 0
forked from suyu/suyu

input_common: Move touch and analog from button. Move udp protocol

This commit is contained in:
german77 2021-09-20 16:57:55 -05:00 committed by Narr the Reg
parent 854c933716
commit 4c6f2c2547
10 changed files with 173 additions and 133 deletions

View file

@ -1,8 +1,12 @@
add_library(input_common STATIC add_library(input_common STATIC
analog_from_button.cpp
analog_from_button.h
keyboard.cpp keyboard.cpp
keyboard.h keyboard.h
helpers/stick_from_buttons.cpp
helpers/stick_from_buttons.h
helpers/touch_from_buttons.cpp
helpers/touch_from_buttons.h
helpers/udp_protocol.cpp
helpers/udp_protocol.h
input_engine.cpp input_engine.cpp
input_engine.h input_engine.h
input_mapping.cpp input_mapping.cpp
@ -15,8 +19,6 @@ add_library(input_common STATIC
motion_from_button.h motion_from_button.h
motion_input.cpp motion_input.cpp
motion_input.h motion_input.h
touch_from_button.cpp
touch_from_button.h
gcadapter/gc_adapter.cpp gcadapter/gc_adapter.cpp
gcadapter/gc_adapter.h gcadapter/gc_adapter.h
gcadapter/gc_poller.cpp gcadapter/gc_poller.cpp
@ -33,8 +35,6 @@ add_library(input_common STATIC
tas/tas_poller.h tas/tas_poller.h
udp/client.cpp udp/client.cpp
udp/client.h udp/client.h
udp/protocol.cpp
udp/protocol.h
udp/udp.cpp udp/udp.cpp
udp/udp.h udp/udp.h
) )

View file

@ -2,32 +2,38 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <atomic>
#include <chrono> #include <chrono>
#include <cmath> #include <cmath>
#include <thread>
#include "common/math_util.h" #include "common/math_util.h"
#include "common/settings.h" #include "common/settings.h"
#include "input_common/analog_from_button.h" #include "input_common/helpers/stick_from_buttons.h"
namespace InputCommon { namespace InputCommon {
class Analog final : public Input::AnalogDevice { class Stick final : public Input::InputDevice {
public: public:
using Button = std::unique_ptr<Input::ButtonDevice>; using Button = std::unique_ptr<Input::InputDevice>;
Analog(Button up_, Button down_, Button left_, Button right_, Button modifier_, Stick(Button up_, Button down_, Button left_, Button right_, Button modifier_,
float modifier_scale_, float modifier_angle_) float modifier_scale_, float modifier_angle_)
: up(std::move(up_)), down(std::move(down_)), left(std::move(left_)), : up(std::move(up_)), down(std::move(down_)), left(std::move(left_)),
right(std::move(right_)), modifier(std::move(modifier_)), modifier_scale(modifier_scale_), right(std::move(right_)), modifier(std::move(modifier_)), modifier_scale(modifier_scale_),
modifier_angle(modifier_angle_) { modifier_angle(modifier_angle_) {
Input::InputCallback<bool> callbacks{ Input::InputCallback button_up_callback{
[this]([[maybe_unused]] bool status) { UpdateStatus(); }}; [this](Input::CallbackStatus callback_) { UpdateUpButtonStatus(callback_); }};
up->SetCallback(callbacks); Input::InputCallback button_down_callback{
down->SetCallback(callbacks); [this](Input::CallbackStatus callback_) { UpdateDownButtonStatus(callback_); }};
left->SetCallback(callbacks); Input::InputCallback button_left_callback{
right->SetCallback(callbacks); [this](Input::CallbackStatus callback_) { UpdateLeftButtonStatus(callback_); }};
modifier->SetCallback(callbacks); Input::InputCallback button_right_callback{
[this](Input::CallbackStatus callback_) { UpdateRightButtonStatus(callback_); }};
Input::InputCallback button_modifier_callback{
[this](Input::CallbackStatus callback_) { UpdateModButtonStatus(callback_); }};
up->SetCallback(button_up_callback);
down->SetCallback(button_down_callback);
left->SetCallback(button_left_callback);
right->SetCallback(button_right_callback);
modifier->SetCallback(button_modifier_callback);
} }
bool IsAngleGreater(float old_angle, float new_angle) const { bool IsAngleGreater(float old_angle, float new_angle) const {
@ -123,13 +129,38 @@ public:
} }
} }
void UpdateStatus() { void UpdateUpButtonStatus(Input::CallbackStatus button_callback) {
const float coef = modifier->GetStatus() ? modifier_scale : 1.0f; up_status = button_callback.button_status.value;
UpdateStatus();
}
bool r = right->GetStatus(); void UpdateDownButtonStatus(Input::CallbackStatus button_callback) {
bool l = left->GetStatus(); down_status = button_callback.button_status.value;
bool u = up->GetStatus(); UpdateStatus();
bool d = down->GetStatus(); }
void UpdateLeftButtonStatus(Input::CallbackStatus button_callback) {
left_status = button_callback.button_status.value;
UpdateStatus();
}
void UpdateRightButtonStatus(Input::CallbackStatus button_callback) {
right_status = button_callback.button_status.value;
UpdateStatus();
}
void UpdateModButtonStatus(Input::CallbackStatus button_callback) {
modifier_status = button_callback.button_status.value;
UpdateStatus();
}
void UpdateStatus() {
const float coef = modifier_status ? modifier_scale : 1.0f;
bool r = right_status;
bool l = left_status;
bool u = up_status;
bool d = down_status;
// Eliminate contradictory movements // Eliminate contradictory movements
if (r && l) { if (r && l) {
@ -162,49 +193,42 @@ public:
} }
last_update = now; last_update = now;
Input::CallbackStatus status{
.type = Input::InputType::Stick,
.stick_status = GetStatus(),
};
TriggerOnChange(status);
} }
std::tuple<float, float> GetStatus() const override { Input::StickStatus GetStatus() const {
Input::StickStatus status{};
status.x.properties = properties;
status.y.properties = properties;
if (Settings::values.emulate_analog_keyboard) { if (Settings::values.emulate_analog_keyboard) {
const auto now = std::chrono::steady_clock::now(); const auto now = std::chrono::steady_clock::now();
float angle_ = GetAngle(now); float angle_ = GetAngle(now);
return std::make_tuple(std::cos(angle_) * amplitude, std::sin(angle_) * amplitude); status.x.raw_value = std::cos(angle_) * amplitude;
status.y.raw_value = std::sin(angle_) * amplitude;
return status;
} }
constexpr float SQRT_HALF = 0.707106781f; constexpr float SQRT_HALF = 0.707106781f;
int x = 0, y = 0; int x = 0, y = 0;
if (right->GetStatus()) { if (right_status) {
++x; ++x;
} }
if (left->GetStatus()) { if (left_status) {
--x; --x;
} }
if (up->GetStatus()) { if (up_status) {
++y; ++y;
} }
if (down->GetStatus()) { if (down_status) {
--y; --y;
} }
const float coef = modifier->GetStatus() ? modifier_scale : 1.0f; const float coef = modifier_status ? modifier_scale : 1.0f;
return std::make_tuple(static_cast<float>(x) * coef * (y == 0 ? 1.0f : SQRT_HALF), status.x.raw_value = static_cast<float>(x) * coef * (y == 0 ? 1.0f : SQRT_HALF);
static_cast<float>(y) * coef * (x == 0 ? 1.0f : SQRT_HALF)); status.y.raw_value = static_cast<float>(y) * coef * (x == 0 ? 1.0f : SQRT_HALF);
} return status;
Input::AnalogProperties GetAnalogProperties() const override {
return {modifier_scale, 1.0f, 0.5f};
}
bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
switch (direction) {
case Input::AnalogDirection::RIGHT:
return right->GetStatus();
case Input::AnalogDirection::LEFT:
return left->GetStatus();
case Input::AnalogDirection::UP:
return up->GetStatus();
case Input::AnalogDirection::DOWN:
return down->GetStatus();
}
return false;
} }
private: private:
@ -218,19 +242,27 @@ private:
float angle{}; float angle{};
float goal_angle{}; float goal_angle{};
float amplitude{}; float amplitude{};
bool up_status;
bool down_status;
bool left_status;
bool right_status;
bool modifier_status;
const Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false};
std::chrono::time_point<std::chrono::steady_clock> last_update; std::chrono::time_point<std::chrono::steady_clock> last_update;
}; };
std::unique_ptr<Input::AnalogDevice> AnalogFromButton::Create(const Common::ParamPackage& params) { std::unique_ptr<Input::InputDevice> StickFromButton::Create(const Common::ParamPackage& params) {
const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize(); const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize();
auto up = Input::CreateDevice<Input::ButtonDevice>(params.Get("up", null_engine)); auto up = Input::CreateDeviceFromString<Input::InputDevice>(params.Get("up", null_engine));
auto down = Input::CreateDevice<Input::ButtonDevice>(params.Get("down", null_engine)); auto down = Input::CreateDeviceFromString<Input::InputDevice>(params.Get("down", null_engine));
auto left = Input::CreateDevice<Input::ButtonDevice>(params.Get("left", null_engine)); auto left = Input::CreateDeviceFromString<Input::InputDevice>(params.Get("left", null_engine));
auto right = Input::CreateDevice<Input::ButtonDevice>(params.Get("right", null_engine)); auto right =
auto modifier = Input::CreateDevice<Input::ButtonDevice>(params.Get("modifier", null_engine)); Input::CreateDeviceFromString<Input::InputDevice>(params.Get("right", null_engine));
auto modifier =
Input::CreateDeviceFromString<Input::InputDevice>(params.Get("modifier", null_engine));
auto modifier_scale = params.Get("modifier_scale", 0.5f); auto modifier_scale = params.Get("modifier_scale", 0.5f);
auto modifier_angle = params.Get("modifier_angle", 5.5f); auto modifier_angle = params.Get("modifier_angle", 5.5f);
return std::make_unique<Analog>(std::move(up), std::move(down), std::move(left), return std::make_unique<Stick>(std::move(up), std::move(down), std::move(left),
std::move(right), std::move(modifier), modifier_scale, std::move(right), std::move(modifier), modifier_scale,
modifier_angle); modifier_angle);
} }

View file

@ -1,11 +1,11 @@
// Copyright 2017 Citra Emulator Project // Copyright 2017 Citra Emulator Project
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#pragma once #pragma once
#include <memory> #include "common/input.h"
#include "core/frontend/input.h"
namespace InputCommon { namespace InputCommon {
@ -13,7 +13,7 @@ namespace InputCommon {
* An analog device factory that takes direction button devices and combines them into a analog * An analog device factory that takes direction button devices and combines them into a analog
* device. * device.
*/ */
class AnalogFromButton final : public Input::Factory<Input::AnalogDevice> { class StickFromButton final : public Input::Factory<Input::InputDevice> {
public: public:
/** /**
* Creates an analog device from direction button devices * Creates an analog device from direction button devices
@ -25,7 +25,7 @@ public:
* - "modifier": a serialized ParamPackage for creating a button device as the modifier * - "modifier": a serialized ParamPackage for creating a button device as the modifier
* - "modifier_scale": a float for the multiplier the modifier gives to the position * - "modifier_scale": a float for the multiplier the modifier gives to the position
*/ */
std::unique_ptr<Input::AnalogDevice> Create(const Common::ParamPackage& params) override; std::unique_ptr<Input::InputDevice> Create(const Common::ParamPackage& params) override;
}; };
} // namespace InputCommon } // namespace InputCommon

View file

@ -0,0 +1,70 @@
// Copyright 2020 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include "common/settings.h"
#include "core/frontend/framebuffer_layout.h"
#include "input_common/helpers/touch_from_buttons.h"
namespace InputCommon {
class TouchFromButtonDevice final : public Input::InputDevice {
public:
using Button = std::unique_ptr<Input::InputDevice>;
TouchFromButtonDevice(Button button_, u32 touch_id_, float x_, float y_)
: button(std::move(button_)), touch_id(touch_id_), x(x_), y(y_) {
Input::InputCallback button_up_callback{
[this](Input::CallbackStatus callback_) { UpdateButtonStatus(callback_); }};
button->SetCallback(button_up_callback);
}
Input::TouchStatus GetStatus(bool pressed) const {
const Input::ButtonStatus button_status{
.value = pressed,
};
Input::TouchStatus status{
.pressed = button_status,
.x = {},
.y = {},
.id = touch_id,
};
status.x.properties = properties;
status.y.properties = properties;
if (!pressed) {
return status;
}
status.x.raw_value = x;
status.y.raw_value = y;
return status;
}
void UpdateButtonStatus(Input::CallbackStatus button_callback) {
const Input::CallbackStatus status{
.type = Input::InputType::Touch,
.touch_status = GetStatus(button_callback.button_status.value),
};
TriggerOnChange(status);
}
private:
Button button;
const u32 touch_id;
const float x;
const float y;
const Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false};
};
std::unique_ptr<Input::InputDevice> TouchFromButton::Create(const Common::ParamPackage& params) {
const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize();
auto button =
Input::CreateDeviceFromString<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);
}
} // namespace InputCommon

View file

@ -4,20 +4,19 @@
#pragma once #pragma once
#include <memory> #include "common/input.h"
#include "core/frontend/input.h"
namespace InputCommon { namespace InputCommon {
/** /**
* A touch device factory that takes a list of button devices and combines them into a touch device. * A touch device factory that takes a list of button devices and combines them into a touch device.
*/ */
class TouchFromButtonFactory final : public Input::Factory<Input::TouchDevice> { class TouchFromButton final : public Input::Factory<Input::InputDevice> {
public: public:
/** /**
* Creates a touch device from a list of button devices * Creates a touch device from a list of button devices
*/ */
std::unique_ptr<Input::TouchDevice> Create(const Common::ParamPackage& params) override; std::unique_ptr<Input::InputDevice> Create(const Common::ParamPackage& params) override;
}; };
} // namespace InputCommon } // namespace InputCommon

View file

@ -5,7 +5,7 @@
#include <cstddef> #include <cstddef>
#include <cstring> #include <cstring>
#include "common/logging/log.h" #include "common/logging/log.h"
#include "input_common/udp/protocol.h" #include "input_common/helpers/udp_protocol.h"
namespace InputCommon::CemuhookUDP { namespace InputCommon::CemuhookUDP {

View file

@ -6,7 +6,6 @@
#include <thread> #include <thread>
#include "common/param_package.h" #include "common/param_package.h"
#include "common/settings.h" #include "common/settings.h"
#include "input_common/analog_from_button.h"
#include "input_common/gcadapter/gc_adapter.h" #include "input_common/gcadapter/gc_adapter.h"
#include "input_common/gcadapter/gc_poller.h" #include "input_common/gcadapter/gc_poller.h"
#include "input_common/keyboard.h" #include "input_common/keyboard.h"
@ -16,7 +15,6 @@
#include "input_common/mouse/mouse_poller.h" #include "input_common/mouse/mouse_poller.h"
#include "input_common/tas/tas_input.h" #include "input_common/tas/tas_input.h"
#include "input_common/tas/tas_poller.h" #include "input_common/tas/tas_poller.h"
#include "input_common/touch_from_button.h"
#include "input_common/udp/client.h" #include "input_common/udp/client.h"
#include "input_common/udp/udp.h" #include "input_common/udp/udp.h"
#ifdef HAVE_SDL2 #ifdef HAVE_SDL2
@ -37,12 +35,8 @@ struct InputSubsystem::Impl {
keyboard = std::make_shared<Keyboard>(); keyboard = std::make_shared<Keyboard>();
Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard); Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard);
Input::RegisterFactory<Input::AnalogDevice>("analog_from_button",
std::make_shared<AnalogFromButton>());
Input::RegisterFactory<Input::MotionDevice>("keyboard", Input::RegisterFactory<Input::MotionDevice>("keyboard",
std::make_shared<MotionFromButton>()); std::make_shared<MotionFromButton>());
Input::RegisterFactory<Input::TouchDevice>("touch_from_button",
std::make_shared<TouchFromButtonFactory>());
#ifdef HAVE_SDL2 #ifdef HAVE_SDL2
sdl = SDL::Init(); sdl = SDL::Init();
@ -75,8 +69,6 @@ struct InputSubsystem::Impl {
Input::UnregisterFactory<Input::ButtonDevice>("keyboard"); Input::UnregisterFactory<Input::ButtonDevice>("keyboard");
Input::UnregisterFactory<Input::MotionDevice>("keyboard"); Input::UnregisterFactory<Input::MotionDevice>("keyboard");
keyboard.reset(); keyboard.reset();
Input::UnregisterFactory<Input::AnalogDevice>("analog_from_button");
Input::UnregisterFactory<Input::TouchDevice>("touch_from_button");
#ifdef HAVE_SDL2 #ifdef HAVE_SDL2
sdl.reset(); sdl.reset();
#endif #endif

View file

@ -1,53 +0,0 @@
// Copyright 2020 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include "common/settings.h"
#include "core/frontend/framebuffer_layout.h"
#include "input_common/touch_from_button.h"
namespace InputCommon {
class TouchFromButtonDevice final : public Input::TouchDevice {
public:
TouchFromButtonDevice() {
const auto button_index =
static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue());
const auto& buttons = Settings::values.touch_from_button_maps[button_index].buttons;
for (const auto& config_entry : buttons) {
const Common::ParamPackage package{config_entry};
map.emplace_back(
Input::CreateDevice<Input::ButtonDevice>(config_entry),
std::clamp(package.Get("x", 0), 0, static_cast<int>(Layout::ScreenUndocked::Width)),
std::clamp(package.Get("y", 0), 0,
static_cast<int>(Layout::ScreenUndocked::Height)));
}
}
Input::TouchStatus GetStatus() const override {
Input::TouchStatus touch_status{};
for (std::size_t id = 0; id < map.size() && id < touch_status.size(); ++id) {
const bool state = std::get<0>(map[id])->GetStatus();
if (state) {
const float x = static_cast<float>(std::get<1>(map[id])) /
static_cast<int>(Layout::ScreenUndocked::Width);
const float y = static_cast<float>(std::get<2>(map[id])) /
static_cast<int>(Layout::ScreenUndocked::Height);
touch_status[id] = {x, y, true};
}
}
return touch_status;
}
private:
// A vector of the mapped button, its x and its y-coordinate
std::vector<std::tuple<std::unique_ptr<Input::ButtonDevice>, int, int>> map;
};
std::unique_ptr<Input::TouchDevice> TouchFromButtonFactory::Create(const Common::ParamPackage&) {
return std::make_unique<TouchFromButtonDevice>();
}
} // namespace InputCommon

View file

@ -11,7 +11,7 @@
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/settings.h" #include "common/settings.h"
#include "input_common/udp/client.h" #include "input_common/udp/client.h"
#include "input_common/udp/protocol.h" #include "input_common/helpers/udp_protocol.h"
using boost::asio::ip::udp; using boost::asio::ip::udp;