From a6bd7917cbc06f9b8f5a7ae24e75db776dc1cd6a Mon Sep 17 00:00:00 2001 From: wwylele Date: Sat, 21 Jan 2017 13:04:00 +0200 Subject: [PATCH] InputCommon: add AnalogFromButton --- src/citra/config.cpp | 20 +++++++++ src/citra_qt/config.cpp | 27 ++++++++++++ src/citra_qt/config.h | 2 + src/input_common/CMakeLists.txt | 2 + src/input_common/analog_from_button.cpp | 58 +++++++++++++++++++++++++ src/input_common/analog_from_button.h | 31 +++++++++++++ src/input_common/main.cpp | 18 ++++++++ src/input_common/main.h | 4 ++ 8 files changed, 162 insertions(+) create mode 100755 src/input_common/analog_from_button.cpp create mode 100755 src/input_common/analog_from_button.h diff --git a/src/citra/config.cpp b/src/citra/config.cpp index 818824596..ef1229912 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp @@ -8,6 +8,7 @@ #include "citra/default_ini.h" #include "common/file_util.h" #include "common/logging/log.h" +#include "common/param_package.h" #include "config.h" #include "core/settings.h" #include "input_common/main.h" @@ -44,6 +45,15 @@ static const std::array default_buttons SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_B, }; +static const std::array, Settings::NativeAnalog::NumAnalogs> default_analogs{{ + { + SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_D, + }, + { + SDL_SCANCODE_I, SDL_SCANCODE_K, SDL_SCANCODE_J, SDL_SCANCODE_L, SDL_SCANCODE_D, + }, +}}; + void Config::ReadValues() { // Controls for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { @@ -54,6 +64,16 @@ void Config::ReadValues() { Settings::values.buttons[i] = default_param; } + for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { + std::string default_param = InputCommon::GenerateAnalogParamFromKeys( + default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], + default_analogs[i][3], default_analogs[i][4], 0.5f); + Settings::values.analogs[i] = + sdl2_config->Get("Controls", Settings::NativeAnalog::mapping[i], default_param); + if (Settings::values.analogs[i].empty()) + Settings::values.analogs[i] = default_param; + } + // Core Settings::values.use_cpu_jit = sdl2_config->GetBoolean("Core", "use_cpu_jit", true); diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp index 5855c7105..6ccfa1577 100644 --- a/src/citra_qt/config.cpp +++ b/src/citra_qt/config.cpp @@ -22,6 +22,15 @@ const std::array Config::default_button Qt::Key_Q, Qt::Key_W, Qt::Key_M, Qt::Key_N, Qt::Key_1, Qt::Key_2, Qt::Key_B, }; +const std::array, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{ + { + Qt::Key_Up, Qt::Key_Down, Qt::Key_Left, Qt::Key_Right, Qt::Key_D, + }, + { + Qt::Key_I, Qt::Key_K, Qt::Key_J, Qt::Key_L, Qt::Key_D, + }, +}}; + void Config::ReadValues() { qt_config->beginGroup("Controls"); for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { @@ -34,6 +43,20 @@ void Config::ReadValues() { if (Settings::values.buttons[i].empty()) Settings::values.buttons[i] = default_param; } + + for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { + std::string default_param = InputCommon::GenerateAnalogParamFromKeys( + default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], + default_analogs[i][3], default_analogs[i][4], 0.5f); + Settings::values.analogs[i] = + qt_config + ->value(Settings::NativeAnalog::mapping[i], QString::fromStdString(default_param)) + .toString() + .toStdString(); + if (Settings::values.analogs[i].empty()) + Settings::values.analogs[i] = default_param; + } + qt_config->endGroup(); qt_config->beginGroup("Core"); @@ -158,6 +181,10 @@ void Config::SaveValues() { qt_config->setValue(QString::fromStdString(Settings::NativeButton::mapping[i]), QString::fromStdString(Settings::values.buttons[i])); } + for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { + qt_config->setValue(QString::fromStdString(Settings::NativeAnalog::mapping[i]), + QString::fromStdString(Settings::values.analogs[i])); + } qt_config->endGroup(); qt_config->beginGroup("Core"); diff --git a/src/citra_qt/config.h b/src/citra_qt/config.h index d7bf99442..cbf745ea2 100644 --- a/src/citra_qt/config.h +++ b/src/citra_qt/config.h @@ -24,5 +24,7 @@ public: void Reload(); void Save(); + static const std::array default_buttons; + static const std::array, Settings::NativeAnalog::NumAnalogs> default_analogs; }; diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt index ac1ad45a9..9f4422269 100644 --- a/src/input_common/CMakeLists.txt +++ b/src/input_common/CMakeLists.txt @@ -1,9 +1,11 @@ set(SRCS + analog_from_button.cpp keyboard.cpp main.cpp ) set(HEADERS + analog_from_button.h keyboard.h main.h ) diff --git a/src/input_common/analog_from_button.cpp b/src/input_common/analog_from_button.cpp new file mode 100755 index 000000000..e1a260762 --- /dev/null +++ b/src/input_common/analog_from_button.cpp @@ -0,0 +1,58 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "input_common/analog_from_button.h" + +namespace InputCommon { + +class Analog final : public Input::AnalogDevice { +public: + using Button = std::unique_ptr; + + Analog(Button up_, Button down_, Button left_, Button right_, Button modifier_, + float modifier_scale_) + : up(std::move(up_)), down(std::move(down_)), left(std::move(left_)), + right(std::move(right_)), modifier(std::move(modifier_)), + modifier_scale(modifier_scale_) {} + + std::tuple GetStatus() const override { + constexpr float SQRT_HALF = 0.707106781f; + int x = 0, y = 0; + + if (right->GetStatus()) + ++x; + if (left->GetStatus()) + --x; + if (up->GetStatus()) + ++y; + if (down->GetStatus()) + --y; + + float coef = modifier->GetStatus() ? modifier_scale : 1.0f; + return std::make_tuple(x * coef * (y == 0 ? 1.0f : SQRT_HALF), + y * coef * (x == 0 ? 1.0f : SQRT_HALF)); + } + +private: + Button up; + Button down; + Button left; + Button right; + Button modifier; + float modifier_scale; +}; + +std::unique_ptr AnalogFromButton::Create(const Common::ParamPackage& params) { + const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize(); + auto up = Input::CreateDevice(params.Get("up", null_engine)); + auto down = Input::CreateDevice(params.Get("down", null_engine)); + auto left = Input::CreateDevice(params.Get("left", null_engine)); + auto right = Input::CreateDevice(params.Get("right", null_engine)); + auto modifier = Input::CreateDevice(params.Get("modifier", null_engine)); + auto modifier_scale = params.Get("modifier_scale", 0.5f); + return std::make_unique(std::move(up), std::move(down), std::move(left), + std::move(right), std::move(modifier), modifier_scale); +} + +} // namespace InputCommon diff --git a/src/input_common/analog_from_button.h b/src/input_common/analog_from_button.h new file mode 100755 index 000000000..bbd583dd9 --- /dev/null +++ b/src/input_common/analog_from_button.h @@ -0,0 +1,31 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include "core/frontend/input.h" + +namespace InputCommon { + +/** + * An analog device factory that takes direction button devices and combines them into a analog + * device. + */ +class AnalogFromButton final : public Input::Factory { +public: + /** + * Creates an analog device from direction button devices + * @param params contains parameters for creating the device: + * - "up": a serialized ParamPackage for creating a button device for up direction + * - "down": a serialized ParamPackage for creating a button device for down direction + * - "left": a serialized ParamPackage for creating a button device for left direction + * - "right": a serialized ParamPackage for creating a button device for right direction + * - "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 + */ + std::unique_ptr Create(const Common::ParamPackage& params) override; +}; + +} // namespace InputCommon diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index ff25220b4..8455fdc17 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp @@ -4,6 +4,7 @@ #include #include "common/param_package.h" +#include "input_common/analog_from_button.h" #include "input_common/keyboard.h" #include "input_common/main.h" @@ -14,11 +15,14 @@ static std::shared_ptr keyboard; void Init() { keyboard = std::make_shared(); Input::RegisterFactory("keyboard", keyboard); + Input::RegisterFactory("analog_from_button", + std::make_shared()); } void Shutdown() { Input::UnregisterFactory("keyboard"); keyboard.reset(); + Input::UnregisterFactory("analog_from_button"); } Keyboard* GetKeyboard() { @@ -32,4 +36,18 @@ std::string GenerateKeyboardParam(int key_code) { return param.Serialize(); } +std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right, + int key_modifier, float modifier_scale) { + Common::ParamPackage circle_pad_param{ + {"engine", "analog_from_button"}, + {"up", GenerateKeyboardParam(key_up)}, + {"down", GenerateKeyboardParam(key_down)}, + {"left", GenerateKeyboardParam(key_left)}, + {"right", GenerateKeyboardParam(key_right)}, + {"modifier", GenerateKeyboardParam(key_modifier)}, + {"modifier_scale", std::to_string(modifier_scale)}, + }; + return circle_pad_param.Serialize(); +} + } // namespace InputCommon diff --git a/src/input_common/main.h b/src/input_common/main.h index a490dd829..140bbd014 100644 --- a/src/input_common/main.h +++ b/src/input_common/main.h @@ -22,4 +22,8 @@ Keyboard* GetKeyboard(); /// Generates a serialized param package for creating a keyboard button device std::string GenerateKeyboardParam(int key_code); +/// Generates a serialized param package for creating an analog device taking input from keyboard +std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right, + int key_modifier, float modifier_scale); + } // namespace InputCommon