controller.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. // SPDX-FileCopyrightText: 2015 Citra Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <QAction>
  4. #include <QLayout>
  5. #include <QString>
  6. #include "common/settings.h"
  7. #include "core/hid/emulated_controller.h"
  8. #include "core/hid/hid_core.h"
  9. #include "input_common/drivers/tas_input.h"
  10. #include "input_common/main.h"
  11. #include "yuzu/configuration/configure_input_player_widget.h"
  12. #include "yuzu/debugger/controller.h"
  13. ControllerDialog::ControllerDialog(Core::HID::HIDCore& hid_core_,
  14. std::shared_ptr<InputCommon::InputSubsystem> input_subsystem_,
  15. QWidget* parent)
  16. : QWidget(parent, Qt::Dialog), hid_core{hid_core_}, input_subsystem{input_subsystem_} {
  17. setObjectName(QStringLiteral("Controller"));
  18. setWindowTitle(tr("Controller P1"));
  19. resize(500, 350);
  20. setMinimumSize(500, 350);
  21. // Enable the maximize button
  22. setWindowFlags(windowFlags() | Qt::WindowMaximizeButtonHint);
  23. widget = new PlayerControlPreview(this);
  24. refreshConfiguration();
  25. QLayout* layout = new QVBoxLayout(this);
  26. layout->setContentsMargins(0, 0, 0, 0);
  27. layout->addWidget(widget);
  28. setLayout(layout);
  29. // Configure focus so that widget is focusable and the dialog automatically forwards focus to
  30. // it.
  31. setFocusProxy(widget);
  32. widget->setFocusPolicy(Qt::StrongFocus);
  33. widget->setFocus();
  34. }
  35. void ControllerDialog::refreshConfiguration() {
  36. UnloadController();
  37. auto* player_1 = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
  38. auto* handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
  39. // Display the correct controller
  40. controller = handheld->IsConnected() ? handheld : player_1;
  41. Core::HID::ControllerUpdateCallback engine_callback{
  42. .on_change = [this](Core::HID::ControllerTriggerType type) { ControllerUpdate(type); },
  43. .is_npad_service = true,
  44. };
  45. callback_key = controller->SetCallback(engine_callback);
  46. widget->SetController(controller);
  47. is_controller_set = true;
  48. }
  49. QAction* ControllerDialog::toggleViewAction() {
  50. if (toggle_view_action == nullptr) {
  51. toggle_view_action = new QAction(tr("&Controller P1"), this);
  52. toggle_view_action->setCheckable(true);
  53. toggle_view_action->setChecked(isVisible());
  54. connect(toggle_view_action, &QAction::toggled, this, &ControllerDialog::setVisible);
  55. }
  56. return toggle_view_action;
  57. }
  58. void ControllerDialog::UnloadController() {
  59. widget->UnloadController();
  60. if (is_controller_set) {
  61. controller->DeleteCallback(callback_key);
  62. is_controller_set = false;
  63. }
  64. }
  65. void ControllerDialog::showEvent(QShowEvent* ev) {
  66. if (toggle_view_action) {
  67. toggle_view_action->setChecked(isVisible());
  68. }
  69. QWidget::showEvent(ev);
  70. }
  71. void ControllerDialog::hideEvent(QHideEvent* ev) {
  72. if (toggle_view_action) {
  73. toggle_view_action->setChecked(isVisible());
  74. }
  75. QWidget::hideEvent(ev);
  76. }
  77. void ControllerDialog::ControllerUpdate(Core::HID::ControllerTriggerType type) {
  78. // TODO(german77): Remove TAS from here
  79. switch (type) {
  80. case Core::HID::ControllerTriggerType::Button:
  81. case Core::HID::ControllerTriggerType::Stick: {
  82. const auto buttons_values = controller->GetButtonsValues();
  83. const auto stick_values = controller->GetSticks();
  84. u64 buttons = 0;
  85. std::size_t index = 0;
  86. for (const auto& button : buttons_values) {
  87. buttons |= button.value ? 1LLU << index : 0;
  88. index++;
  89. }
  90. const InputCommon::TasInput::TasAnalog left_axis = {
  91. .x = stick_values.left.x / 32767.f,
  92. .y = stick_values.left.y / 32767.f,
  93. };
  94. const InputCommon::TasInput::TasAnalog right_axis = {
  95. .x = stick_values.right.x / 32767.f,
  96. .y = stick_values.right.y / 32767.f,
  97. };
  98. input_subsystem->GetTas()->RecordInput(buttons, left_axis, right_axis);
  99. break;
  100. }
  101. default:
  102. break;
  103. }
  104. }