diff options
Diffstat (limited to 'src/yuzu/configuration/configure_ringcon.cpp')
-rw-r--r-- | src/yuzu/configuration/configure_ringcon.cpp | 497 |
1 files changed, 0 insertions, 497 deletions
diff --git a/src/yuzu/configuration/configure_ringcon.cpp b/src/yuzu/configuration/configure_ringcon.cpp deleted file mode 100644 index 9fd094ab6..000000000 --- a/src/yuzu/configuration/configure_ringcon.cpp +++ /dev/null @@ -1,497 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <memory> -#include <QKeyEvent> -#include <QMenu> -#include <QMessageBox> -#include <QTimer> -#include <fmt/format.h> - -#include "configuration/qt_config.h" -#include "hid_core/frontend/emulated_controller.h" -#include "hid_core/hid_core.h" -#include "input_common/drivers/keyboard.h" -#include "input_common/drivers/mouse.h" -#include "input_common/main.h" -#include "ui_configure_ringcon.h" -#include "yuzu/bootmanager.h" -#include "yuzu/configuration/configure_ringcon.h" - -const std::array<std::string, ConfigureRingController::ANALOG_SUB_BUTTONS_NUM> - ConfigureRingController::analog_sub_buttons{{ - "left", - "right", - }}; - -namespace { - -QString GetKeyName(int key_code) { - switch (key_code) { - case Qt::Key_Shift: - return QObject::tr("Shift"); - case Qt::Key_Control: - return QObject::tr("Ctrl"); - case Qt::Key_Alt: - return QObject::tr("Alt"); - case Qt::Key_Meta: - return {}; - default: - return QKeySequence(key_code).toString(); - } -} - -QString GetButtonName(Common::Input::ButtonNames button_name) { - switch (button_name) { - case Common::Input::ButtonNames::ButtonLeft: - return QObject::tr("Left"); - case Common::Input::ButtonNames::ButtonRight: - return QObject::tr("Right"); - case Common::Input::ButtonNames::ButtonDown: - return QObject::tr("Down"); - case Common::Input::ButtonNames::ButtonUp: - return QObject::tr("Up"); - case Common::Input::ButtonNames::TriggerZ: - return QObject::tr("Z"); - case Common::Input::ButtonNames::TriggerR: - return QObject::tr("R"); - case Common::Input::ButtonNames::TriggerL: - return QObject::tr("L"); - case Common::Input::ButtonNames::ButtonA: - return QObject::tr("A"); - case Common::Input::ButtonNames::ButtonB: - return QObject::tr("B"); - case Common::Input::ButtonNames::ButtonX: - return QObject::tr("X"); - case Common::Input::ButtonNames::ButtonY: - return QObject::tr("Y"); - case Common::Input::ButtonNames::ButtonStart: - return QObject::tr("Start"); - case Common::Input::ButtonNames::L1: - return QObject::tr("L1"); - case Common::Input::ButtonNames::L2: - return QObject::tr("L2"); - case Common::Input::ButtonNames::L3: - return QObject::tr("L3"); - case Common::Input::ButtonNames::R1: - return QObject::tr("R1"); - case Common::Input::ButtonNames::R2: - return QObject::tr("R2"); - case Common::Input::ButtonNames::R3: - return QObject::tr("R3"); - case Common::Input::ButtonNames::Circle: - return QObject::tr("Circle"); - case Common::Input::ButtonNames::Cross: - return QObject::tr("Cross"); - case Common::Input::ButtonNames::Square: - return QObject::tr("Square"); - case Common::Input::ButtonNames::Triangle: - return QObject::tr("Triangle"); - case Common::Input::ButtonNames::Share: - return QObject::tr("Share"); - case Common::Input::ButtonNames::Options: - return QObject::tr("Options"); - default: - return QObject::tr("[undefined]"); - } -} - -void SetAnalogParam(const Common::ParamPackage& input_param, Common::ParamPackage& analog_param, - const std::string& button_name) { - // The poller returned a complete axis, so set all the buttons - if (input_param.Has("axis_x") && input_param.Has("axis_y")) { - analog_param = input_param; - return; - } - // Check if the current configuration has either no engine or an axis binding. - // Clears out the old binding and adds one with analog_from_button. - if (!analog_param.Has("engine") || analog_param.Has("axis_x") || analog_param.Has("axis_y")) { - analog_param = { - {"engine", "analog_from_button"}, - }; - } - analog_param.Set(button_name, input_param.Serialize()); -} -} // namespace - -ConfigureRingController::ConfigureRingController(QWidget* parent, - InputCommon::InputSubsystem* input_subsystem_, - Core::HID::HIDCore& hid_core_) - : QDialog(parent), timeout_timer(std::make_unique<QTimer>()), - poll_timer(std::make_unique<QTimer>()), input_subsystem{input_subsystem_}, - - ui(std::make_unique<Ui::ConfigureRingController>()) { - ui->setupUi(this); - - analog_map_buttons = { - ui->buttonRingAnalogPull, - ui->buttonRingAnalogPush, - }; - - emulated_controller = hid_core_.GetEmulatedController(Core::HID::NpadIdType::Player1); - emulated_controller->SaveCurrentConfig(); - emulated_controller->EnableConfiguration(); - - Core::HID::ControllerUpdateCallback engine_callback{ - .on_change = [this](Core::HID::ControllerTriggerType type) { ControllerUpdate(type); }, - .is_npad_service = false, - }; - callback_key = emulated_controller->SetCallback(engine_callback); - is_controller_set = true; - - LoadConfiguration(); - - for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { - auto* const analog_button = analog_map_buttons[sub_button_id]; - - if (analog_button == nullptr) { - continue; - } - - connect(analog_button, &QPushButton::clicked, [=, this] { - HandleClick( - analog_map_buttons[sub_button_id], - [=, this](const Common::ParamPackage& params) { - Common::ParamPackage param = emulated_controller->GetRingParam(); - SetAnalogParam(params, param, analog_sub_buttons[sub_button_id]); - emulated_controller->SetRingParam(param); - }, - InputCommon::Polling::InputType::Stick); - }); - - analog_button->setContextMenuPolicy(Qt::CustomContextMenu); - - connect(analog_button, &QPushButton::customContextMenuRequested, - [=, this](const QPoint& menu_location) { - QMenu context_menu; - Common::ParamPackage param = emulated_controller->GetRingParam(); - context_menu.addAction(tr("Clear"), [&] { - emulated_controller->SetRingParam(param); - analog_map_buttons[sub_button_id]->setText(tr("[not set]")); - }); - context_menu.addAction(tr("Invert axis"), [&] { - const bool invert_value = param.Get("invert_x", "+") == "-"; - const std::string invert_str = invert_value ? "+" : "-"; - param.Set("invert_x", invert_str); - emulated_controller->SetRingParam(param); - for (int sub_button_id2 = 0; sub_button_id2 < ANALOG_SUB_BUTTONS_NUM; - ++sub_button_id2) { - analog_map_buttons[sub_button_id2]->setText( - AnalogToText(param, analog_sub_buttons[sub_button_id2])); - } - }); - context_menu.exec( - analog_map_buttons[sub_button_id]->mapToGlobal(menu_location)); - }); - } - - connect(ui->sliderRingAnalogDeadzone, &QSlider::valueChanged, [=, this] { - Common::ParamPackage param = emulated_controller->GetRingParam(); - const auto slider_value = ui->sliderRingAnalogDeadzone->value(); - ui->labelRingAnalogDeadzone->setText(tr("Deadzone: %1%").arg(slider_value)); - param.Set("deadzone", slider_value / 100.0f); - emulated_controller->SetRingParam(param); - }); - - connect(ui->restore_defaults_button, &QPushButton::clicked, this, - &ConfigureRingController::RestoreDefaults); - - connect(ui->enable_ring_controller_button, &QPushButton::clicked, this, - &ConfigureRingController::EnableRingController); - - timeout_timer->setSingleShot(true); - connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); }); - - connect(poll_timer.get(), &QTimer::timeout, [this] { - const auto& params = input_subsystem->GetNextInput(); - if (params.Has("engine") && IsInputAcceptable(params)) { - SetPollingResult(params, false); - return; - } - }); - - resize(0, 0); -} - -ConfigureRingController::~ConfigureRingController() { - emulated_controller->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex, - Common::Input::PollingMode::Active); - emulated_controller->DisableConfiguration(); - - if (is_controller_set) { - emulated_controller->DeleteCallback(callback_key); - is_controller_set = false; - } -}; - -void ConfigureRingController::changeEvent(QEvent* event) { - if (event->type() == QEvent::LanguageChange) { - RetranslateUI(); - } - - QDialog::changeEvent(event); -} - -void ConfigureRingController::RetranslateUI() { - ui->retranslateUi(this); -} - -void ConfigureRingController::UpdateUI() { - RetranslateUI(); - const Common::ParamPackage param = emulated_controller->GetRingParam(); - - for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { - auto* const analog_button = analog_map_buttons[sub_button_id]; - - if (analog_button == nullptr) { - continue; - } - - analog_button->setText(AnalogToText(param, analog_sub_buttons[sub_button_id])); - } - - const auto deadzone_label = ui->labelRingAnalogDeadzone; - const auto deadzone_slider = ui->sliderRingAnalogDeadzone; - - int slider_value = static_cast<int>(param.Get("deadzone", 0.15f) * 100); - deadzone_label->setText(tr("Deadzone: %1%").arg(slider_value)); - deadzone_slider->setValue(slider_value); -} - -void ConfigureRingController::ApplyConfiguration() { - emulated_controller->DisableConfiguration(); - emulated_controller->SaveCurrentConfig(); - emulated_controller->EnableConfiguration(); -} - -void ConfigureRingController::LoadConfiguration() { - UpdateUI(); -} - -void ConfigureRingController::RestoreDefaults() { - const std::string default_ring_string = InputCommon::GenerateAnalogParamFromKeys( - 0, 0, QtConfig::default_ringcon_analogs[0], QtConfig::default_ringcon_analogs[1], 0, 0.05f); - emulated_controller->SetRingParam(Common::ParamPackage(default_ring_string)); - UpdateUI(); -} - -void ConfigureRingController::EnableRingController() { - const auto dialog_title = tr("Error enabling ring input"); - - is_ring_enabled = false; - ui->ring_controller_sensor_value->setText(tr("Not connected")); - - if (!Settings::values.enable_joycon_driver) { - QMessageBox::warning(this, dialog_title, tr("Direct Joycon driver is not enabled")); - return; - } - - ui->enable_ring_controller_button->setEnabled(false); - ui->enable_ring_controller_button->setText(tr("Configuring")); - // SetPollingMode is blocking. Allow to update the button status before calling the command - repaint(); - - const auto result = emulated_controller->SetPollingMode( - Core::HID::EmulatedDeviceIndex::RightIndex, Common::Input::PollingMode::Ring); - switch (result) { - case Common::Input::DriverResult::Success: - is_ring_enabled = true; - break; - case Common::Input::DriverResult::NotSupported: - QMessageBox::warning(this, dialog_title, - tr("The current mapped device doesn't support the ring controller")); - break; - case Common::Input::DriverResult::NoDeviceDetected: - QMessageBox::warning(this, dialog_title, - tr("The current mapped device doesn't have a ring attached")); - break; - case Common::Input::DriverResult::InvalidHandle: - QMessageBox::warning(this, dialog_title, tr("The current mapped device is not connected")); - break; - default: - QMessageBox::warning(this, dialog_title, - tr("Unexpected driver result %1").arg(static_cast<int>(result))); - break; - } - ui->enable_ring_controller_button->setEnabled(true); - ui->enable_ring_controller_button->setText(tr("Enable")); -} - -void ConfigureRingController::ControllerUpdate(Core::HID::ControllerTriggerType type) { - if (!is_ring_enabled) { - return; - } - if (type != Core::HID::ControllerTriggerType::RingController) { - return; - } - - const auto value = emulated_controller->GetRingSensorValues(); - const auto tex_value = QString::fromStdString(fmt::format("{:.3f}", value.raw_value)); - ui->ring_controller_sensor_value->setText(tex_value); -} - -void ConfigureRingController::HandleClick( - QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, - InputCommon::Polling::InputType type) { - button->setText(tr("[waiting]")); - button->setFocus(); - - input_setter = new_input_setter; - - input_subsystem->BeginMapping(type); - - QWidget::grabMouse(); - QWidget::grabKeyboard(); - - timeout_timer->start(2500); // Cancel after 2.5 seconds - poll_timer->start(25); // Check for new inputs every 25ms -} - -void ConfigureRingController::SetPollingResult(const Common::ParamPackage& params, bool abort) { - timeout_timer->stop(); - poll_timer->stop(); - input_subsystem->StopMapping(); - - QWidget::releaseMouse(); - QWidget::releaseKeyboard(); - - if (!abort) { - (*input_setter)(params); - } - - UpdateUI(); - - input_setter = std::nullopt; -} - -bool ConfigureRingController::IsInputAcceptable(const Common::ParamPackage& params) const { - return true; -} - -void ConfigureRingController::mousePressEvent(QMouseEvent* event) { - if (!input_setter || !event) { - return; - } - - const auto button = GRenderWindow::QtButtonToMouseButton(event->button()); - input_subsystem->GetMouse()->PressButton(0, 0, button); -} - -void ConfigureRingController::keyPressEvent(QKeyEvent* event) { - if (!input_setter || !event) { - return; - } - event->ignore(); - if (event->key() != Qt::Key_Escape) { - input_subsystem->GetKeyboard()->PressKey(event->key()); - } -} - -QString ConfigureRingController::ButtonToText(const Common::ParamPackage& param) { - if (!param.Has("engine")) { - return QObject::tr("[not set]"); - } - - const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : ""); - const QString inverted = QString::fromStdString(param.Get("inverted", false) ? "!" : ""); - const auto common_button_name = input_subsystem->GetButtonName(param); - - // Retrieve the names from Qt - if (param.Get("engine", "") == "keyboard") { - const QString button_str = GetKeyName(param.Get("code", 0)); - return QObject::tr("%1%2").arg(toggle, button_str); - } - - if (common_button_name == Common::Input::ButtonNames::Invalid) { - return QObject::tr("[invalid]"); - } - - if (common_button_name == Common::Input::ButtonNames::Engine) { - return QString::fromStdString(param.Get("engine", "")); - } - - if (common_button_name == Common::Input::ButtonNames::Value) { - if (param.Has("hat")) { - const QString hat = QString::fromStdString(param.Get("direction", "")); - return QObject::tr("%1%2Hat %3").arg(toggle, inverted, hat); - } - if (param.Has("axis")) { - const QString axis = QString::fromStdString(param.Get("axis", "")); - return QObject::tr("%1%2Axis %3").arg(toggle, inverted, axis); - } - if (param.Has("axis_x") && param.Has("axis_y") && param.Has("axis_z")) { - const QString axis_x = QString::fromStdString(param.Get("axis_x", "")); - const QString axis_y = QString::fromStdString(param.Get("axis_y", "")); - const QString axis_z = QString::fromStdString(param.Get("axis_z", "")); - return QObject::tr("%1%2Axis %3,%4,%5").arg(toggle, inverted, axis_x, axis_y, axis_z); - } - if (param.Has("motion")) { - const QString motion = QString::fromStdString(param.Get("motion", "")); - return QObject::tr("%1%2Motion %3").arg(toggle, inverted, motion); - } - if (param.Has("button")) { - const QString button = QString::fromStdString(param.Get("button", "")); - return QObject::tr("%1%2Button %3").arg(toggle, inverted, button); - } - } - - QString button_name = GetButtonName(common_button_name); - if (param.Has("hat")) { - return QObject::tr("%1%2Hat %3").arg(toggle, inverted, button_name); - } - if (param.Has("axis")) { - return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); - } - if (param.Has("motion")) { - return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); - } - if (param.Has("button")) { - return QObject::tr("%1%2Button %3").arg(toggle, inverted, button_name); - } - - return QObject::tr("[unknown]"); -} - -QString ConfigureRingController::AnalogToText(const Common::ParamPackage& param, - const std::string& dir) { - if (!param.Has("engine")) { - return QObject::tr("[not set]"); - } - - if (param.Get("engine", "") == "analog_from_button") { - return ButtonToText(Common::ParamPackage{param.Get(dir, "")}); - } - - if (!param.Has("axis_x") || !param.Has("axis_y")) { - return QObject::tr("[unknown]"); - } - - const auto engine_str = param.Get("engine", ""); - const QString axis_x_str = QString::fromStdString(param.Get("axis_x", "")); - const QString axis_y_str = QString::fromStdString(param.Get("axis_y", "")); - const bool invert_x = param.Get("invert_x", "+") == "-"; - const bool invert_y = param.Get("invert_y", "+") == "-"; - - if (dir == "modifier") { - return QObject::tr("[unused]"); - } - - if (dir == "left") { - const QString invert_x_str = QString::fromStdString(invert_x ? "+" : "-"); - return QObject::tr("Axis %1%2").arg(axis_x_str, invert_x_str); - } - if (dir == "right") { - const QString invert_x_str = QString::fromStdString(invert_x ? "-" : "+"); - return QObject::tr("Axis %1%2").arg(axis_x_str, invert_x_str); - } - if (dir == "up") { - const QString invert_y_str = QString::fromStdString(invert_y ? "-" : "+"); - return QObject::tr("Axis %1%2").arg(axis_y_str, invert_y_str); - } - if (dir == "down") { - const QString invert_y_str = QString::fromStdString(invert_y ? "+" : "-"); - return QObject::tr("Axis %1%2").arg(axis_y_str, invert_y_str); - } - - return QObject::tr("[unknown]"); -} |