summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Zach Hilman2018-11-01 22:11:44 -0400
committerGravatar Zach Hilman2018-11-18 23:22:36 -0500
commit3d1a221893127f2be317d9237d26c607a4b736e1 (patch)
tree22386e3e1e159a0668625f9f83b1c5c3b5ff033c /src
parentqt: Add UI to configure touchscreen parameters (diff)
downloadyuzu-3d1a221893127f2be317d9237d26c607a4b736e1.tar.gz
yuzu-3d1a221893127f2be317d9237d26c607a4b736e1.tar.xz
yuzu-3d1a221893127f2be317d9237d26c607a4b736e1.zip
qt: Move controller button config to separate dialog
Handles button configuration for all controller layouts and debug pads. Configurable at construction.
Diffstat (limited to 'src')
-rw-r--r--src/yuzu/CMakeLists.txt3
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp506
-rw-r--r--src/yuzu/configuration/configure_input_player.h102
-rw-r--r--src/yuzu/configuration/configure_input_player.ui1156
4 files changed, 1767 insertions, 0 deletions
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index ff06d2a9a..34f36f06b 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -27,6 +27,8 @@ add_executable(yuzu
27 configuration/configure_graphics.h 27 configuration/configure_graphics.h
28 configuration/configure_input.cpp 28 configuration/configure_input.cpp
29 configuration/configure_input.h 29 configuration/configure_input.h
30 configuration/configure_input_player.cpp
31 configuration/configure_input_player.h
30 configuration/configure_mouse_advanced.cpp 32 configuration/configure_mouse_advanced.cpp
31 configuration/configure_mouse_advanced.h 33 configuration/configure_mouse_advanced.h
32 configuration/configure_system.cpp 34 configuration/configure_system.cpp
@@ -80,6 +82,7 @@ set(UIS
80 configuration/configure_general.ui 82 configuration/configure_general.ui
81 configuration/configure_graphics.ui 83 configuration/configure_graphics.ui
82 configuration/configure_input.ui 84 configuration/configure_input.ui
85 configuration/configure_input_player.ui
83 configuration/configure_mouse_advanced.ui 86 configuration/configure_mouse_advanced.ui
84 configuration/configure_system.ui 87 configuration/configure_system.ui
85 configuration/configure_touchscreen_advanced.ui 88 configuration/configure_touchscreen_advanced.ui
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
new file mode 100644
index 000000000..5de7dd962
--- /dev/null
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -0,0 +1,506 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include <memory>
7#include <utility>
8#include <QColorDialog>
9#include <QMenu>
10#include <QMessageBox>
11#include <QTimer>
12#include "common/assert.h"
13#include "common/param_package.h"
14#include "input_common/main.h"
15#include "ui_configure_input_player.h"
16#include "yuzu/configuration/config.h"
17#include "yuzu/configuration/configure_input_player.h"
18
19const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM>
20 ConfigureInputPlayer::analog_sub_buttons{{
21 "up",
22 "down",
23 "left",
24 "right",
25 "modifier",
26 }};
27
28static void MoveGridElement(QGridLayout* grid, int row_old, int column_old, int row_new,
29 int column_new) {
30 const auto item = grid->itemAtPosition(row_old, column_old);
31 // grid->removeItem(item);
32 grid->addItem(item, row_new, column_new);
33}
34
35static void LayerGridElements(QGridLayout* grid, QWidget* item, QWidget* onTopOf) {
36 const int index1 = grid->indexOf(item);
37 const int index2 = grid->indexOf(onTopOf);
38 int row, column, rowSpan, columnSpan;
39 grid->getItemPosition(index2, &row, &column, &rowSpan, &columnSpan);
40 grid->takeAt(index1);
41 grid->addWidget(item, row, column, rowSpan, columnSpan);
42}
43
44static QString getKeyName(int key_code) {
45 switch (key_code) {
46 case Qt::Key_Shift:
47 return QObject::tr("Shift");
48 case Qt::Key_Control:
49 return QObject::tr("Ctrl");
50 case Qt::Key_Alt:
51 return QObject::tr("Alt");
52 case Qt::Key_Meta:
53 return "";
54 default:
55 return QKeySequence(key_code).toString();
56 }
57}
58
59static void SetAnalogButton(const Common::ParamPackage& input_param,
60 Common::ParamPackage& analog_param, const std::string& button_name) {
61 if (analog_param.Get("engine", "") != "analog_from_button") {
62 analog_param = {
63 {"engine", "analog_from_button"},
64 {"modifier_scale", "0.5"},
65 };
66 }
67 analog_param.Set(button_name, input_param.Serialize());
68}
69
70static QString ButtonToText(const Common::ParamPackage& param) {
71 if (!param.Has("engine")) {
72 return QObject::tr("[not set]");
73 } else if (param.Get("engine", "") == "keyboard") {
74 return getKeyName(param.Get("code", 0));
75 } else if (param.Get("engine", "") == "sdl") {
76 if (param.Has("hat")) {
77 return QString(QObject::tr("Hat %1 %2"))
78 .arg(param.Get("hat", "").c_str(), param.Get("direction", "").c_str());
79 }
80 if (param.Has("axis")) {
81 return QString(QObject::tr("Axis %1%2"))
82 .arg(param.Get("axis", "").c_str(), param.Get("direction", "").c_str());
83 }
84 if (param.Has("button")) {
85 return QString(QObject::tr("Button %1")).arg(param.Get("button", "").c_str());
86 }
87 return QString();
88 } else {
89 return QObject::tr("[unknown]");
90 }
91};
92
93static QString AnalogToText(const Common::ParamPackage& param, const std::string& dir) {
94 if (!param.Has("engine")) {
95 return QObject::tr("[not set]");
96 } else if (param.Get("engine", "") == "analog_from_button") {
97 return ButtonToText(Common::ParamPackage{param.Get(dir, "")});
98 } else if (param.Get("engine", "") == "sdl") {
99 if (dir == "modifier") {
100 return QString(QObject::tr("[unused]"));
101 }
102
103 if (dir == "left" || dir == "right") {
104 return QString(QObject::tr("Axis %1")).arg(param.Get("axis_x", "").c_str());
105 } else if (dir == "up" || dir == "down") {
106 return QString(QObject::tr("Axis %1")).arg(param.Get("axis_y", "").c_str());
107 }
108 return QString();
109 } else {
110 return QObject::tr("[unknown]");
111 }
112};
113
114ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, u8 player_index, bool debug)
115 : QDialog(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()),
116 timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()),
117 player_index(player_index), debug(debug) {
118
119 ui->setupUi(this);
120 setFocusPolicy(Qt::ClickFocus);
121
122 button_map = {
123 ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY,
124 ui->buttonLStick, ui->buttonRStick, ui->buttonL, ui->buttonR,
125 ui->buttonZL, ui->buttonZR, ui->buttonPlus, ui->buttonMinus,
126 ui->buttonDpadLeft, ui->buttonDpadUp, ui->buttonDpadRight, ui->buttonDpadDown,
127 ui->buttonLStickLeft, ui->buttonLStickUp, ui->buttonLStickRight, ui->buttonLStickDown,
128 ui->buttonRStickLeft, ui->buttonRStickUp, ui->buttonRStickRight, ui->buttonRStickDown,
129 ui->buttonSL, ui->buttonSR, ui->buttonHome, ui->buttonScreenshot,
130 };
131
132 analog_map_buttons = {{
133 {
134 ui->buttonLStickUp,
135 ui->buttonLStickDown,
136 ui->buttonLStickLeft,
137 ui->buttonLStickRight,
138 ui->buttonLStickMod,
139 },
140 {
141 ui->buttonRStickUp,
142 ui->buttonRStickDown,
143 ui->buttonRStickLeft,
144 ui->buttonRStickRight,
145 ui->buttonRStickMod,
146 },
147 }};
148
149 debug_hidden = {
150 ui->buttonSL, ui->labelSL,
151 ui->buttonSR, ui->labelSR,
152 ui->buttonLStick, ui->labelLStickPressed,
153 ui->buttonRStick, ui->labelRStickPressed,
154 ui->buttonHome, ui->labelHome,
155 ui->buttonScreenshot, ui->labelScreenshot,
156 };
157
158 auto layout = Settings::values.players[player_index].type;
159 if (debug)
160 layout = Settings::ControllerType::DualJoycon;
161
162 switch (layout) {
163 case Settings::ControllerType::ProController:
164 case Settings::ControllerType::DualJoycon:
165 layout_hidden = {
166 ui->buttonSL,
167 ui->labelSL,
168 ui->buttonSR,
169 ui->labelSR,
170 };
171 break;
172 case Settings::ControllerType::LeftJoycon:
173 layout_hidden = {
174 ui->right_body_button,
175 ui->right_buttons_button,
176 ui->right_body_label,
177 ui->right_buttons_label,
178 ui->buttonR,
179 ui->labelR,
180 ui->buttonZR,
181 ui->labelZR,
182 ui->labelHome,
183 ui->buttonHome,
184 ui->buttonPlus,
185 ui->labelPlus,
186 ui->RStick,
187 ui->faceButtons,
188 };
189 break;
190 case Settings::ControllerType::RightJoycon:
191 layout_hidden = {
192 ui->left_body_button, ui->left_buttons_button,
193 ui->left_body_label, ui->left_buttons_label,
194 ui->buttonL, ui->labelL,
195 ui->buttonZL, ui->labelZL,
196 ui->labelScreenshot, ui->buttonScreenshot,
197 ui->buttonMinus, ui->labelMinus,
198 ui->LStick, ui->Dpad,
199 };
200 break;
201 }
202
203 if (debug || layout == Settings::ControllerType::ProController) {
204 ui->controller_color->hide();
205 } else {
206 if (layout == Settings::ControllerType::LeftJoycon ||
207 layout == Settings::ControllerType::RightJoycon) {
208 ui->horizontalSpacer_4->setGeometry({0, 0, 0, 0});
209
210 LayerGridElements(ui->buttons, ui->shoulderButtons, ui->Dpad);
211 LayerGridElements(ui->buttons, ui->misc, ui->RStick);
212 LayerGridElements(ui->buttons, ui->Dpad, ui->faceButtons);
213 LayerGridElements(ui->buttons, ui->RStick, ui->LStick);
214 }
215 }
216
217 for (auto* widget : layout_hidden)
218 widget->setVisible(false);
219
220 analog_map_stick = {ui->buttonLStickAnalog, ui->buttonRStickAnalog};
221
222 for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) {
223 if (!button_map[button_id])
224 continue;
225 button_map[button_id]->setContextMenuPolicy(Qt::CustomContextMenu);
226 connect(button_map[button_id], &QPushButton::released, [=]() {
227 handleClick(
228 button_map[button_id],
229 [=](const Common::ParamPackage& params) { buttons_param[button_id] = params; },
230 InputCommon::Polling::DeviceType::Button);
231 });
232 connect(button_map[button_id], &QPushButton::customContextMenuRequested,
233 [=](const QPoint& menu_location) {
234 QMenu context_menu;
235 context_menu.addAction(tr("Clear"), [&] {
236 buttons_param[button_id].Clear();
237 button_map[button_id]->setText(tr("[not set]"));
238 });
239 context_menu.addAction(tr("Restore Default"), [&] {
240 buttons_param[button_id] = Common::ParamPackage{
241 InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])};
242 button_map[button_id]->setText(ButtonToText(buttons_param[button_id]));
243 });
244 context_menu.exec(button_map[button_id]->mapToGlobal(menu_location));
245 });
246 }
247
248 for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) {
249 for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) {
250 if (!analog_map_buttons[analog_id][sub_button_id])
251 continue;
252 analog_map_buttons[analog_id][sub_button_id]->setContextMenuPolicy(
253 Qt::CustomContextMenu);
254 connect(analog_map_buttons[analog_id][sub_button_id], &QPushButton::released, [=]() {
255 handleClick(analog_map_buttons[analog_id][sub_button_id],
256 [=](const Common::ParamPackage& params) {
257 SetAnalogButton(params, analogs_param[analog_id],
258 analog_sub_buttons[sub_button_id]);
259 },
260 InputCommon::Polling::DeviceType::Button);
261 });
262 connect(analog_map_buttons[analog_id][sub_button_id],
263 &QPushButton::customContextMenuRequested, [=](const QPoint& menu_location) {
264 QMenu context_menu;
265 context_menu.addAction(tr("Clear"), [&] {
266 analogs_param[analog_id].Erase(analog_sub_buttons[sub_button_id]);
267 analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]"));
268 });
269 context_menu.addAction(tr("Restore Default"), [&] {
270 Common::ParamPackage params{InputCommon::GenerateKeyboardParam(
271 Config::default_analogs[analog_id][sub_button_id])};
272 SetAnalogButton(params, analogs_param[analog_id],
273 analog_sub_buttons[sub_button_id]);
274 analog_map_buttons[analog_id][sub_button_id]->setText(AnalogToText(
275 analogs_param[analog_id], analog_sub_buttons[sub_button_id]));
276 });
277 context_menu.exec(analog_map_buttons[analog_id][sub_button_id]->mapToGlobal(
278 menu_location));
279 });
280 }
281 connect(analog_map_stick[analog_id], &QPushButton::released, [=]() {
282 QMessageBox::information(this, tr("Information"),
283 tr("After pressing OK, first move your joystick horizontally, "
284 "and then vertically."));
285 handleClick(
286 analog_map_stick[analog_id],
287 [=](const Common::ParamPackage& params) { analogs_param[analog_id] = params; },
288 InputCommon::Polling::DeviceType::Analog);
289 });
290 }
291
292 connect(ui->buttonClearAll, &QPushButton::released, [this] { ClearAll(); });
293 connect(ui->buttonRestoreDefaults, &QPushButton::released, [this]() { restoreDefaults(); });
294
295 timeout_timer->setSingleShot(true);
296 connect(timeout_timer.get(), &QTimer::timeout, [this]() { setPollingResult({}, true); });
297
298 connect(poll_timer.get(), &QTimer::timeout, [this]() {
299 Common::ParamPackage params;
300 for (auto& poller : device_pollers) {
301 params = poller->GetNextInput();
302 if (params.Has("engine")) {
303 setPollingResult(params, false);
304 return;
305 }
306 }
307 });
308
309 controller_color_buttons = {
310 ui->left_body_button,
311 ui->left_buttons_button,
312 ui->right_body_button,
313 ui->right_buttons_button,
314 };
315
316 for (std::size_t i = 0; i < controller_color_buttons.size(); ++i) {
317 connect(controller_color_buttons[i], &QPushButton::clicked, this,
318 std::bind(&ConfigureInputPlayer::OnControllerButtonClick, this, i));
319 }
320
321 this->loadConfiguration();
322 this->resize(0, 0);
323
324 // TODO(wwylele): enable this when we actually emulate it
325 ui->buttonHome->setEnabled(false);
326}
327
328void ConfigureInputPlayer::applyConfiguration() {
329 auto& buttons =
330 debug ? Settings::values.debug_pad_buttons : Settings::values.players[player_index].buttons;
331 auto& analogs =
332 debug ? Settings::values.debug_pad_analogs : Settings::values.players[player_index].analogs;
333
334 std::transform(buttons_param.begin(), buttons_param.end(), buttons.begin(),
335 [](const Common::ParamPackage& param) { return param.Serialize(); });
336 std::transform(analogs_param.begin(), analogs_param.end(), analogs.begin(),
337 [](const Common::ParamPackage& param) { return param.Serialize(); });
338
339 if (debug)
340 return;
341
342 std::array<u32, 4> colors{};
343 std::transform(controller_colors.begin(), controller_colors.end(), colors.begin(),
344 [](QColor color) { return color.rgb(); });
345
346 Settings::values.players[player_index].body_color_left = colors[0];
347 Settings::values.players[player_index].button_color_left = colors[1];
348 Settings::values.players[player_index].body_color_right = colors[2];
349 Settings::values.players[player_index].button_color_right = colors[3];
350}
351
352void ConfigureInputPlayer::OnControllerButtonClick(int i) {
353 const QColor new_bg_color = QColorDialog::getColor(controller_colors[i]);
354 if (!new_bg_color.isValid())
355 return;
356 controller_colors[i] = new_bg_color;
357 controller_color_buttons[i]->setStyleSheet(
358 QString("QPushButton { background-color: %1 }").arg(controller_colors[i].name()));
359}
360
361void ConfigureInputPlayer::loadConfiguration() {
362 if (debug) {
363 std::transform(Settings::values.debug_pad_buttons.begin(),
364 Settings::values.debug_pad_buttons.end(), buttons_param.begin(),
365 [](const std::string& str) { return Common::ParamPackage(str); });
366 std::transform(Settings::values.debug_pad_analogs.begin(),
367 Settings::values.debug_pad_analogs.end(), analogs_param.begin(),
368 [](const std::string& str) { return Common::ParamPackage(str); });
369 } else {
370 std::transform(Settings::values.players[player_index].buttons.begin(),
371 Settings::values.players[player_index].buttons.end(), buttons_param.begin(),
372 [](const std::string& str) { return Common::ParamPackage(str); });
373 std::transform(Settings::values.players[player_index].analogs.begin(),
374 Settings::values.players[player_index].analogs.end(), analogs_param.begin(),
375 [](const std::string& str) { return Common::ParamPackage(str); });
376 }
377
378 updateButtonLabels();
379
380 if (debug)
381 return;
382
383 std::array<u32, 4> colors = {
384 Settings::values.players[player_index].body_color_left,
385 Settings::values.players[player_index].button_color_left,
386 Settings::values.players[player_index].body_color_right,
387 Settings::values.players[player_index].button_color_right,
388 };
389
390 std::transform(colors.begin(), colors.end(), controller_colors.begin(),
391 [](u32 rgb) { return QColor::fromRgb(rgb); });
392
393 for (std::size_t i = 0; i < colors.size(); ++i) {
394 controller_color_buttons[i]->setStyleSheet(
395 QString("QPushButton { background-color: %1 }").arg(controller_colors[i].name()));
396 }
397}
398
399void ConfigureInputPlayer::restoreDefaults() {
400 for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) {
401 buttons_param[button_id] = Common::ParamPackage{
402 InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])};
403 }
404
405 for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) {
406 for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) {
407 Common::ParamPackage params{InputCommon::GenerateKeyboardParam(
408 Config::default_analogs[analog_id][sub_button_id])};
409 SetAnalogButton(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]);
410 }
411 }
412 updateButtonLabels();
413}
414
415void ConfigureInputPlayer::ClearAll() {
416 for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) {
417 if (button_map[button_id] && button_map[button_id]->isEnabled())
418 buttons_param[button_id].Clear();
419 }
420 for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) {
421 for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) {
422 if (analog_map_buttons[analog_id][sub_button_id] &&
423 analog_map_buttons[analog_id][sub_button_id]->isEnabled())
424 analogs_param[analog_id].Erase(analog_sub_buttons[sub_button_id]);
425 }
426 }
427
428 updateButtonLabels();
429}
430
431void ConfigureInputPlayer::updateButtonLabels() {
432 for (int button = 0; button < Settings::NativeButton::NumButtons; button++) {
433 button_map[button]->setText(ButtonToText(buttons_param[button]));
434 }
435
436 for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) {
437 for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) {
438 if (analog_map_buttons[analog_id][sub_button_id]) {
439 analog_map_buttons[analog_id][sub_button_id]->setText(
440 AnalogToText(analogs_param[analog_id], analog_sub_buttons[sub_button_id]));
441 }
442 }
443 analog_map_stick[analog_id]->setText(tr("Set Analog Stick"));
444 }
445}
446
447void ConfigureInputPlayer::handleClick(
448 QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter,
449 InputCommon::Polling::DeviceType type) {
450 button->setText(tr("[press key]"));
451 button->setFocus();
452
453 const auto iter = std::find(button_map.begin(), button_map.end(), button);
454 ASSERT(iter != button_map.end());
455 const auto index = std::distance(button_map.begin(), iter);
456 ASSERT(index < Settings::NativeButton::NumButtons && index >= 0);
457
458 input_setter = new_input_setter;
459
460 device_pollers = InputCommon::Polling::GetPollers(type);
461
462 // Keyboard keys can only be used as button devices
463 want_keyboard_keys = type == InputCommon::Polling::DeviceType::Button;
464
465 for (auto& poller : device_pollers) {
466 poller->Start();
467 }
468
469 grabKeyboard();
470 grabMouse();
471 timeout_timer->start(5000); // Cancel after 5 seconds
472 poll_timer->start(200); // Check for new inputs every 200ms
473}
474
475void ConfigureInputPlayer::setPollingResult(const Common::ParamPackage& params, bool abort) {
476 releaseKeyboard();
477 releaseMouse();
478 timeout_timer->stop();
479 poll_timer->stop();
480 for (auto& poller : device_pollers) {
481 poller->Stop();
482 }
483
484 if (!abort) {
485 (*input_setter)(params);
486 }
487
488 updateButtonLabels();
489 input_setter = boost::none;
490}
491
492void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) {
493 if (!input_setter || !event)
494 return;
495
496 if (event->key() != Qt::Key_Escape) {
497 if (want_keyboard_keys) {
498 setPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())},
499 false);
500 } else {
501 // Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling
502 return;
503 }
504 }
505 setPollingResult({}, true);
506}
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h
new file mode 100644
index 000000000..67cc6a8ca
--- /dev/null
+++ b/src/yuzu/configuration/configure_input_player.h
@@ -0,0 +1,102 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include <functional>
9#include <memory>
10#include <string>
11#include <unordered_map>
12#include <QDialog>
13#include <QKeyEvent>
14#include <boost/optional.hpp>
15#include "common/param_package.h"
16#include "core/settings.h"
17#include "input_common/main.h"
18#include "ui_configure_input.h"
19
20class QPushButton;
21class QString;
22class QTimer;
23
24namespace Ui {
25class ConfigureInputPlayer;
26}
27
28class ConfigureInputPlayer : public QDialog {
29 Q_OBJECT
30
31public:
32 explicit ConfigureInputPlayer(QWidget* parent, u8 player_index, bool debug = false);
33
34 /// Save all button configurations to settings file
35 void applyConfiguration();
36
37private:
38 std::unique_ptr<Ui::ConfigureInputPlayer> ui;
39
40 u8 player_index;
41 bool debug;
42
43 std::unique_ptr<QTimer> timeout_timer;
44 std::unique_ptr<QTimer> poll_timer;
45
46 /// This will be the the setting function when an input is awaiting configuration.
47 boost::optional<std::function<void(const Common::ParamPackage&)>> input_setter;
48
49 std::array<Common::ParamPackage, Settings::NativeButton::NumButtons> buttons_param;
50 std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs> analogs_param;
51
52 static constexpr int ANALOG_SUB_BUTTONS_NUM = 5;
53
54 /// Each button input is represented by a QPushButton.
55 std::array<QPushButton*, Settings::NativeButton::NumButtons> button_map;
56
57 std::vector<QWidget*> debug_hidden;
58 std::vector<QWidget*> layout_hidden;
59
60 /// A group of five QPushButtons represent one analog input. The buttons each represent up,
61 /// down, left, right, and modifier, respectively.
62 std::array<std::array<QPushButton*, ANALOG_SUB_BUTTONS_NUM>, Settings::NativeAnalog::NumAnalogs>
63 analog_map_buttons;
64
65 /// Analog inputs are also represented each with a single button, used to configure with an
66 /// actual analog stick
67 std::array<QPushButton*, Settings::NativeAnalog::NumAnalogs> analog_map_stick;
68
69 static const std::array<std::string, ANALOG_SUB_BUTTONS_NUM> analog_sub_buttons;
70
71 std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers;
72
73 /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false,
74 /// keyboard events are ignored.
75 bool want_keyboard_keys = false;
76
77 std::array<QPushButton*, 4> controller_color_buttons;
78 std::array<QColor, 4> controller_colors;
79
80 void OnControllerButtonClick(int i);
81
82 /// Load configuration settings.
83 void loadConfiguration();
84 /// Restore all buttons to their default values.
85 void restoreDefaults();
86 /// Clear all input configuration
87 void ClearAll();
88
89 /// Update UI to reflect current configuration.
90 void updateButtonLabels();
91
92 /// Called when the button was pressed.
93 void handleClick(QPushButton* button,
94 std::function<void(const Common::ParamPackage&)> new_input_setter,
95 InputCommon::Polling::DeviceType type);
96
97 /// Finish polling and configure input using the input_setter
98 void setPollingResult(const Common::ParamPackage& params, bool abort);
99
100 /// Handle key press events.
101 void keyPressEvent(QKeyEvent* event) override;
102};
diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui
new file mode 100644
index 000000000..191206663
--- /dev/null
+++ b/src/yuzu/configuration/configure_input_player.ui
@@ -0,0 +1,1156 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<ui version="4.0">
3 <class>ConfigureInputPlayer</class>
4 <widget class="QDialog" name="ConfigureInputPlayer">
5 <property name="geometry">
6 <rect>
7 <x>0</x>
8 <y>0</y>
9 <width>408</width>
10 <height>731</height>
11 </rect>
12 </property>
13 <property name="windowTitle">
14 <string>Configure Input</string>
15 </property>
16 <layout class="QVBoxLayout" name="verticalLayout_5">
17 <item>
18 <layout class="QGridLayout" name="buttons">
19 <item row="1" column="1">
20 <widget class="QGroupBox" name="RStick">
21 <property name="title">
22 <string>Right Stick</string>
23 </property>
24 <property name="alignment">
25 <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
26 </property>
27 <property name="flat">
28 <bool>false</bool>
29 </property>
30 <property name="checkable">
31 <bool>false</bool>
32 </property>
33 <layout class="QGridLayout" name="gridLayout_5">
34 <item row="1" column="1">
35 <layout class="QVBoxLayout" name="buttonRStickDownVerticalLayout">
36 <item>
37 <layout class="QHBoxLayout" name="buttonRStickDownHorizontalLayout">
38 <item>
39 <widget class="QLabel" name="labelRStickDown">
40 <property name="text">
41 <string>Down:</string>
42 </property>
43 </widget>
44 </item>
45 </layout>
46 </item>
47 <item>
48 <widget class="QPushButton" name="buttonRStickDown">
49 <property name="text">
50 <string/>
51 </property>
52 </widget>
53 </item>
54 </layout>
55 </item>
56 <item row="0" column="1">
57 <layout class="QVBoxLayout" name="buttonRStickRightVerticalLayout">
58 <item>
59 <layout class="QHBoxLayout" name="buttonRStickRightHorizontalLayout">
60 <item>
61 <widget class="QLabel" name="labelRStickRight">
62 <property name="text">
63 <string>Right:</string>
64 </property>
65 </widget>
66 </item>
67 </layout>
68 </item>
69 <item>
70 <widget class="QPushButton" name="buttonRStickRight">
71 <property name="text">
72 <string/>
73 </property>
74 </widget>
75 </item>
76 </layout>
77 </item>
78 <item row="3" column="0" colspan="2">
79 <widget class="QPushButton" name="buttonRStickAnalog">
80 <property name="text">
81 <string>Set Analog Stick</string>
82 </property>
83 </widget>
84 </item>
85 <item row="0" column="0">
86 <layout class="QVBoxLayout" name="buttonRStickLeftVerticalLayout">
87 <item>
88 <layout class="QHBoxLayout" name="buttonRStickLeftHorizontalLayout">
89 <item>
90 <widget class="QLabel" name="labelRStickLeft">
91 <property name="text">
92 <string>Left:</string>
93 </property>
94 </widget>
95 </item>
96 </layout>
97 </item>
98 <item>
99 <widget class="QPushButton" name="buttonRStickLeft">
100 <property name="text">
101 <string/>
102 </property>
103 </widget>
104 </item>
105 </layout>
106 </item>
107 <item row="1" column="0">
108 <layout class="QVBoxLayout" name="buttonRStickUpVerticalLayout">
109 <item>
110 <layout class="QHBoxLayout" name="buttonRStickUpHorizontalLayout">
111 <item>
112 <widget class="QLabel" name="labelRStickUp">
113 <property name="text">
114 <string>Up:</string>
115 </property>
116 </widget>
117 </item>
118 </layout>
119 </item>
120 <item>
121 <widget class="QPushButton" name="buttonRStickUp">
122 <property name="text">
123 <string/>
124 </property>
125 </widget>
126 </item>
127 </layout>
128 </item>
129 <item row="2" column="0">
130 <layout class="QVBoxLayout" name="buttonRStickPressedVerticalLayout">
131 <item>
132 <layout class="QHBoxLayout" name="buttonRStickPressedHorizontalLayout">
133 <item>
134 <widget class="QLabel" name="labelRStickPressed">
135 <property name="text">
136 <string>Pressed:</string>
137 </property>
138 </widget>
139 </item>
140 </layout>
141 </item>
142 <item>
143 <widget class="QPushButton" name="buttonRStick">
144 <property name="text">
145 <string/>
146 </property>
147 </widget>
148 </item>
149 </layout>
150 </item>
151 <item row="2" column="1">
152 <layout class="QVBoxLayout" name="buttonRStickModVerticalLayout">
153 <item>
154 <layout class="QHBoxLayout" name="buttonRStickModHorizontalLayout">
155 <item>
156 <widget class="QLabel" name="labelRStickMod">
157 <property name="text">
158 <string>Modifier:</string>
159 </property>
160 </widget>
161 </item>
162 </layout>
163 </item>
164 <item>
165 <widget class="QPushButton" name="buttonRStickMod">
166 <property name="text">
167 <string/>
168 </property>
169 </widget>
170 </item>
171 </layout>
172 </item>
173 </layout>
174 </widget>
175 </item>
176 <item row="0" column="1">
177 <widget class="QGroupBox" name="Dpad">
178 <property name="title">
179 <string>Directional Pad</string>
180 </property>
181 <property name="flat">
182 <bool>false</bool>
183 </property>
184 <property name="checkable">
185 <bool>false</bool>
186 </property>
187 <layout class="QGridLayout" name="gridLayout_2">
188 <item row="1" column="0">
189 <layout class="QVBoxLayout" name="buttonDpadUpVerticalLayout">
190 <item>
191 <layout class="QHBoxLayout" name="buttonDpadUpHorizontalLayout">
192 <item>
193 <widget class="QLabel" name="labelDpadUp">
194 <property name="text">
195 <string>Up:</string>
196 </property>
197 </widget>
198 </item>
199 </layout>
200 </item>
201 <item>
202 <widget class="QPushButton" name="buttonDpadUp">
203 <property name="text">
204 <string/>
205 </property>
206 </widget>
207 </item>
208 </layout>
209 </item>
210 <item row="1" column="1">
211 <layout class="QVBoxLayout" name="buttonDpadDownVerticalLayout">
212 <item>
213 <layout class="QHBoxLayout" name="buttonDpadDownHorizontalLayout">
214 <item>
215 <widget class="QLabel" name="labelDpadDown">
216 <property name="text">
217 <string>Down:</string>
218 </property>
219 </widget>
220 </item>
221 </layout>
222 </item>
223 <item>
224 <widget class="QPushButton" name="buttonDpadDown">
225 <property name="text">
226 <string/>
227 </property>
228 </widget>
229 </item>
230 </layout>
231 </item>
232 <item row="0" column="0">
233 <layout class="QVBoxLayout" name="buttonDpadLeftVerticalLayout">
234 <item>
235 <layout class="QHBoxLayout" name="buttonDpadLeftHorizontalLayout">
236 <item>
237 <widget class="QLabel" name="labelDpadLeft">
238 <property name="text">
239 <string>Left:</string>
240 </property>
241 </widget>
242 </item>
243 </layout>
244 </item>
245 <item>
246 <widget class="QPushButton" name="buttonDpadLeft">
247 <property name="text">
248 <string/>
249 </property>
250 </widget>
251 </item>
252 </layout>
253 </item>
254 <item row="0" column="1">
255 <layout class="QVBoxLayout" name="buttonDpadRightVerticalLayout">
256 <item>
257 <layout class="QHBoxLayout" name="buttonDpadRightHorizontalLayout">
258 <item>
259 <widget class="QLabel" name="labelDpadRight">
260 <property name="text">
261 <string>Right:</string>
262 </property>
263 </widget>
264 </item>
265 </layout>
266 </item>
267 <item>
268 <widget class="QPushButton" name="buttonDpadRight">
269 <property name="text">
270 <string/>
271 </property>
272 </widget>
273 </item>
274 </layout>
275 </item>
276 </layout>
277 </widget>
278 </item>
279 <item row="0" column="0">
280 <widget class="QGroupBox" name="faceButtons">
281 <property name="title">
282 <string>Face Buttons</string>
283 </property>
284 <property name="flat">
285 <bool>false</bool>
286 </property>
287 <property name="checkable">
288 <bool>false</bool>
289 </property>
290 <layout class="QGridLayout" name="gridLayout">
291 <item row="0" column="0">
292 <layout class="QVBoxLayout" name="buttonFaceButtonsAVerticalLayout">
293 <item>
294 <layout class="QHBoxLayout" name="buttonFaceButtonsAHorizontalLayout">
295 <item>
296 <widget class="QLabel" name="labelA">
297 <property name="text">
298 <string>A:</string>
299 </property>
300 </widget>
301 </item>
302 </layout>
303 </item>
304 <item>
305 <widget class="QPushButton" name="buttonA">
306 <property name="text">
307 <string/>
308 </property>
309 </widget>
310 </item>
311 </layout>
312 </item>
313 <item row="0" column="1">
314 <layout class="QVBoxLayout" name="buttonFaceButtonsBVerticalLayout">
315 <item>
316 <layout class="QHBoxLayout" name="buttonFaceButtonsBHorizontalLayout">
317 <item>
318 <widget class="QLabel" name="labelB">
319 <property name="text">
320 <string>B:</string>
321 </property>
322 </widget>
323 </item>
324 </layout>
325 </item>
326 <item>
327 <widget class="QPushButton" name="buttonB">
328 <property name="text">
329 <string/>
330 </property>
331 </widget>
332 </item>
333 </layout>
334 </item>
335 <item row="1" column="0">
336 <layout class="QVBoxLayout" name="buttonFaceButtonsXVerticalLayout">
337 <item>
338 <layout class="QHBoxLayout" name="buttonFaceButtonsXHorizontalLayout">
339 <item>
340 <widget class="QLabel" name="labelX">
341 <property name="text">
342 <string>X:</string>
343 </property>
344 </widget>
345 </item>
346 </layout>
347 </item>
348 <item>
349 <widget class="QPushButton" name="buttonX">
350 <property name="text">
351 <string/>
352 </property>
353 </widget>
354 </item>
355 </layout>
356 </item>
357 <item row="1" column="1">
358 <layout class="QVBoxLayout" name="buttonFaceButtonsYVerticalLayout">
359 <item>
360 <layout class="QHBoxLayout" name="buttonFaceButtonsYHorizontalLayout">
361 <item>
362 <widget class="QLabel" name="labelY">
363 <property name="text">
364 <string>Y:</string>
365 </property>
366 </widget>
367 </item>
368 </layout>
369 </item>
370 <item>
371 <widget class="QPushButton" name="buttonY">
372 <property name="text">
373 <string/>
374 </property>
375 </widget>
376 </item>
377 </layout>
378 </item>
379 </layout>
380 </widget>
381 </item>
382 <item row="5" column="0" colspan="2">
383 <widget class="QGroupBox" name="controller_color">
384 <property name="title">
385 <string>Controller Color</string>
386 </property>
387 <layout class="QGridLayout" name="gridLayout_10" columnstretch="0,0,0,0,0,0,0">
388 <item row="0" column="0">
389 <spacer name="horizontalSpacer_2">
390 <property name="orientation">
391 <enum>Qt::Horizontal</enum>
392 </property>
393 <property name="sizeHint" stdset="0">
394 <size>
395 <width>40</width>
396 <height>20</height>
397 </size>
398 </property>
399 </spacer>
400 </item>
401 <item row="0" column="1">
402 <widget class="QLabel" name="left_body_label">
403 <property name="text">
404 <string>Left Body</string>
405 </property>
406 </widget>
407 </item>
408 <item row="0" column="6">
409 <spacer name="horizontalSpacer_3">
410 <property name="orientation">
411 <enum>Qt::Horizontal</enum>
412 </property>
413 <property name="sizeHint" stdset="0">
414 <size>
415 <width>40</width>
416 <height>20</height>
417 </size>
418 </property>
419 </spacer>
420 </item>
421 <item row="1" column="1">
422 <widget class="QLabel" name="left_buttons_label">
423 <property name="minimumSize">
424 <size>
425 <width>90</width>
426 <height>0</height>
427 </size>
428 </property>
429 <property name="text">
430 <string>Left Buttons</string>
431 </property>
432 </widget>
433 </item>
434 <item row="1" column="5">
435 <widget class="QPushButton" name="right_buttons_button">
436 <property name="sizePolicy">
437 <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
438 <horstretch>0</horstretch>
439 <verstretch>0</verstretch>
440 </sizepolicy>
441 </property>
442 <property name="minimumSize">
443 <size>
444 <width>32</width>
445 <height>0</height>
446 </size>
447 </property>
448 <property name="maximumSize">
449 <size>
450 <width>40</width>
451 <height>16777215</height>
452 </size>
453 </property>
454 <property name="text">
455 <string/>
456 </property>
457 </widget>
458 </item>
459 <item row="0" column="4">
460 <widget class="QLabel" name="right_body_label">
461 <property name="text">
462 <string>Right Body</string>
463 </property>
464 </widget>
465 </item>
466 <item row="1" column="4">
467 <widget class="QLabel" name="right_buttons_label">
468 <property name="minimumSize">
469 <size>
470 <width>90</width>
471 <height>0</height>
472 </size>
473 </property>
474 <property name="text">
475 <string>Right Buttons</string>
476 </property>
477 </widget>
478 </item>
479 <item row="1" column="2">
480 <widget class="QPushButton" name="left_buttons_button">
481 <property name="sizePolicy">
482 <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
483 <horstretch>0</horstretch>
484 <verstretch>0</verstretch>
485 </sizepolicy>
486 </property>
487 <property name="minimumSize">
488 <size>
489 <width>32</width>
490 <height>0</height>
491 </size>
492 </property>
493 <property name="maximumSize">
494 <size>
495 <width>40</width>
496 <height>16777215</height>
497 </size>
498 </property>
499 <property name="text">
500 <string/>
501 </property>
502 </widget>
503 </item>
504 <item row="0" column="2">
505 <widget class="QPushButton" name="left_body_button">
506 <property name="sizePolicy">
507 <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
508 <horstretch>0</horstretch>
509 <verstretch>0</verstretch>
510 </sizepolicy>
511 </property>
512 <property name="minimumSize">
513 <size>
514 <width>32</width>
515 <height>0</height>
516 </size>
517 </property>
518 <property name="maximumSize">
519 <size>
520 <width>40</width>
521 <height>16777215</height>
522 </size>
523 </property>
524 <property name="text">
525 <string/>
526 </property>
527 </widget>
528 </item>
529 <item row="0" column="5">
530 <widget class="QPushButton" name="right_body_button">
531 <property name="sizePolicy">
532 <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
533 <horstretch>0</horstretch>
534 <verstretch>0</verstretch>
535 </sizepolicy>
536 </property>
537 <property name="minimumSize">
538 <size>
539 <width>32</width>
540 <height>0</height>
541 </size>
542 </property>
543 <property name="maximumSize">
544 <size>
545 <width>40</width>
546 <height>16777215</height>
547 </size>
548 </property>
549 <property name="text">
550 <string/>
551 </property>
552 </widget>
553 </item>
554 <item row="0" column="3">
555 <spacer name="horizontalSpacer_4">
556 <property name="orientation">
557 <enum>Qt::Horizontal</enum>
558 </property>
559 <property name="sizeType">
560 <enum>QSizePolicy::Fixed</enum>
561 </property>
562 <property name="sizeHint" stdset="0">
563 <size>
564 <width>20</width>
565 <height>20</height>
566 </size>
567 </property>
568 </spacer>
569 </item>
570 </layout>
571 </widget>
572 </item>
573 <item row="1" column="0">
574 <widget class="QGroupBox" name="LStick">
575 <property name="title">
576 <string>Left Stick</string>
577 </property>
578 <property name="flat">
579 <bool>false</bool>
580 </property>
581 <property name="checkable">
582 <bool>false</bool>
583 </property>
584 <layout class="QGridLayout" name="gridLayout_4">
585 <item row="1" column="1">
586 <layout class="QVBoxLayout" name="buttonLStickUpVerticalLayout">
587 <item>
588 <layout class="QHBoxLayout" name="buttonLStickUpHorizontalLayout">
589 <item>
590 <widget class="QLabel" name="labelLStickUp">
591 <property name="text">
592 <string>Up:</string>
593 </property>
594 </widget>
595 </item>
596 </layout>
597 </item>
598 <item>
599 <widget class="QPushButton" name="buttonLStickUp">
600 <property name="text">
601 <string/>
602 </property>
603 </widget>
604 </item>
605 </layout>
606 </item>
607 <item row="0" column="2">
608 <layout class="QVBoxLayout" name="buttonLStickRightVerticalLayout">
609 <item>
610 <layout class="QHBoxLayout" name="buttonLStickRightHorizontalLayout">
611 <item>
612 <widget class="QLabel" name="labelLStickRight">
613 <property name="text">
614 <string>Right:</string>
615 </property>
616 </widget>
617 </item>
618 </layout>
619 </item>
620 <item>
621 <widget class="QPushButton" name="buttonLStickRight">
622 <property name="text">
623 <string/>
624 </property>
625 </widget>
626 </item>
627 </layout>
628 </item>
629 <item row="4" column="1" colspan="2">
630 <widget class="QPushButton" name="buttonLStickAnalog">
631 <property name="text">
632 <string>Set Analog Stick</string>
633 </property>
634 </widget>
635 </item>
636 <item row="0" column="1">
637 <layout class="QVBoxLayout" name="buttonLStickLeftVerticalLayout">
638 <item>
639 <layout class="QHBoxLayout" name="buttonLStickLeftHorizontalLayout_2">
640 <item>
641 <widget class="QLabel" name="labelLStickLeft">
642 <property name="text">
643 <string>Left:</string>
644 </property>
645 </widget>
646 </item>
647 </layout>
648 </item>
649 <item>
650 <widget class="QPushButton" name="buttonLStickLeft">
651 <property name="text">
652 <string/>
653 </property>
654 </widget>
655 </item>
656 </layout>
657 </item>
658 <item row="1" column="2">
659 <layout class="QVBoxLayout" name="buttonLStickDownVerticalLayout">
660 <item>
661 <layout class="QHBoxLayout" name="buttonLStickDownHorizontalLayout">
662 <item>
663 <widget class="QLabel" name="labelLStickDown">
664 <property name="text">
665 <string>Down:</string>
666 </property>
667 </widget>
668 </item>
669 </layout>
670 </item>
671 <item>
672 <widget class="QPushButton" name="buttonLStickDown">
673 <property name="text">
674 <string/>
675 </property>
676 </widget>
677 </item>
678 </layout>
679 </item>
680 <item row="3" column="2">
681 <layout class="QVBoxLayout" name="buttonLStickModVerticalLayout">
682 <item>
683 <layout class="QHBoxLayout" name="buttonLStickModHorizontalLayout">
684 <item>
685 <widget class="QLabel" name="labelLStickMod">
686 <property name="text">
687 <string>Modifier:</string>
688 </property>
689 </widget>
690 </item>
691 </layout>
692 </item>
693 <item>
694 <widget class="QPushButton" name="buttonLStickMod">
695 <property name="text">
696 <string/>
697 </property>
698 </widget>
699 </item>
700 </layout>
701 </item>
702 <item row="3" column="1">
703 <layout class="QVBoxLayout" name="buttonLStickPressedVerticalLayout" stretch="0,0">
704 <item>
705 <layout class="QHBoxLayout" name="buttonLStickPressedHorizontalLayout">
706 <item>
707 <widget class="QLabel" name="labelLStickPressed">
708 <property name="text">
709 <string>Pressed:</string>
710 </property>
711 </widget>
712 </item>
713 </layout>
714 </item>
715 <item>
716 <widget class="QPushButton" name="buttonLStick">
717 <property name="text">
718 <string/>
719 </property>
720 </widget>
721 </item>
722 </layout>
723 </item>
724 </layout>
725 </widget>
726 </item>
727 <item row="3" column="0">
728 <widget class="QGroupBox" name="shoulderButtons">
729 <property name="title">
730 <string>Shoulder Buttons</string>
731 </property>
732 <property name="flat">
733 <bool>false</bool>
734 </property>
735 <property name="checkable">
736 <bool>false</bool>
737 </property>
738 <layout class="QGridLayout" name="gridLayout_3">
739 <item row="3" column="0">
740 <layout class="QVBoxLayout" name="buttonShoulderButtonsSLVerticalLayout">
741 <item>
742 <layout class="QHBoxLayout" name="buttonShoulderButtonsSLHorizontalLayout">
743 <item>
744 <widget class="QLabel" name="labelSL">
745 <property name="text">
746 <string>SL:</string>
747 </property>
748 </widget>
749 </item>
750 </layout>
751 </item>
752 <item>
753 <widget class="QPushButton" name="buttonSL">
754 <property name="text">
755 <string/>
756 </property>
757 </widget>
758 </item>
759 </layout>
760 </item>
761 <item row="2" column="1">
762 <layout class="QVBoxLayout" name="buttonShoulderButtonsZRVerticalLayout">
763 <item>
764 <layout class="QHBoxLayout" name="buttonShoulderButtonsZRHorizontalLayout">
765 <item>
766 <widget class="QLabel" name="labelZR">
767 <property name="text">
768 <string>ZR:</string>
769 </property>
770 </widget>
771 </item>
772 </layout>
773 </item>
774 <item>
775 <widget class="QPushButton" name="buttonZR">
776 <property name="text">
777 <string/>
778 </property>
779 </widget>
780 </item>
781 </layout>
782 </item>
783 <item row="3" column="1">
784 <layout class="QVBoxLayout" name="buttonShoulderButtonsSRVerticalLayout">
785 <item>
786 <layout class="QHBoxLayout" name="buttonShoulderButtonsSRHorizontalLayout">
787 <item>
788 <widget class="QLabel" name="labelSR">
789 <property name="text">
790 <string>SR:</string>
791 </property>
792 </widget>
793 </item>
794 </layout>
795 </item>
796 <item>
797 <widget class="QPushButton" name="buttonSR">
798 <property name="text">
799 <string/>
800 </property>
801 </widget>
802 </item>
803 </layout>
804 </item>
805 <item row="0" column="1">
806 <layout class="QVBoxLayout" name="buttonShoulderButtonsZLVerticalLayout">
807 <item>
808 <layout class="QHBoxLayout" name="buttonShoulderButtonsZLHorizontalLayout">
809 <item>
810 <widget class="QLabel" name="labelZL">
811 <property name="text">
812 <string>ZL:</string>
813 </property>
814 </widget>
815 </item>
816 </layout>
817 </item>
818 <item>
819 <widget class="QPushButton" name="buttonZL">
820 <property name="text">
821 <string/>
822 </property>
823 </widget>
824 </item>
825 </layout>
826 </item>
827 <item row="0" column="0">
828 <layout class="QVBoxLayout" name="buttonShoulderButtonsLVerticalLayout">
829 <item>
830 <layout class="QHBoxLayout" name="buttonShoulderButtonsLHorizontalLayout">
831 <item>
832 <widget class="QLabel" name="labelL">
833 <property name="text">
834 <string>L:</string>
835 </property>
836 </widget>
837 </item>
838 </layout>
839 </item>
840 <item>
841 <widget class="QPushButton" name="buttonL">
842 <property name="text">
843 <string/>
844 </property>
845 </widget>
846 </item>
847 </layout>
848 </item>
849 <item row="2" column="0">
850 <layout class="QVBoxLayout" name="buttonShoulderButtonsRVerticalLayout">
851 <item>
852 <layout class="QHBoxLayout" name="buttonShoulderButtonsRHorizontalLayout">
853 <item>
854 <widget class="QLabel" name="labelR">
855 <property name="text">
856 <string>R:</string>
857 </property>
858 </widget>
859 </item>
860 </layout>
861 </item>
862 <item>
863 <widget class="QPushButton" name="buttonR">
864 <property name="text">
865 <string/>
866 </property>
867 </widget>
868 </item>
869 </layout>
870 </item>
871 </layout>
872 </widget>
873 </item>
874 <item row="3" column="1">
875 <widget class="QGroupBox" name="misc">
876 <property name="title">
877 <string>Misc.</string>
878 </property>
879 <property name="flat">
880 <bool>false</bool>
881 </property>
882 <property name="checkable">
883 <bool>false</bool>
884 </property>
885 <layout class="QGridLayout" name="gridLayout_6">
886 <item row="1" column="0">
887 <layout class="QVBoxLayout" name="buttonMiscMinusVerticalLayout">
888 <item>
889 <layout class="QHBoxLayout" name="buttonMiscMinusHorizontalLayout">
890 <item>
891 <widget class="QLabel" name="labelMinus">
892 <property name="text">
893 <string>Minus:</string>
894 </property>
895 </widget>
896 </item>
897 </layout>
898 </item>
899 <item>
900 <widget class="QPushButton" name="buttonMinus">
901 <property name="text">
902 <string/>
903 </property>
904 </widget>
905 </item>
906 </layout>
907 </item>
908 <item row="3" column="1">
909 <spacer name="verticalSpacer_2">
910 <property name="orientation">
911 <enum>Qt::Vertical</enum>
912 </property>
913 <property name="sizeHint" stdset="0">
914 <size>
915 <width>20</width>
916 <height>40</height>
917 </size>
918 </property>
919 </spacer>
920 </item>
921 <item row="0" column="0">
922 <layout class="QVBoxLayout" name="buttonMiscPlusVerticalLayout">
923 <item>
924 <layout class="QHBoxLayout" name="buttonMiscPlusHorizontalLayout">
925 <item>
926 <widget class="QLabel" name="labelPlus">
927 <property name="text">
928 <string>Plus:</string>
929 </property>
930 </widget>
931 </item>
932 </layout>
933 </item>
934 <item>
935 <widget class="QPushButton" name="buttonPlus">
936 <property name="text">
937 <string/>
938 </property>
939 </widget>
940 </item>
941 </layout>
942 </item>
943 <item row="0" column="1">
944 <layout class="QVBoxLayout" name="buttonMiscHomeVerticalLayout">
945 <item>
946 <layout class="QHBoxLayout" name="buttonMiscHomeHorizontalLayout">
947 <item>
948 <widget class="QLabel" name="labelHome">
949 <property name="text">
950 <string>Home:</string>
951 </property>
952 </widget>
953 </item>
954 </layout>
955 </item>
956 <item>
957 <widget class="QPushButton" name="buttonHome">
958 <property name="text">
959 <string/>
960 </property>
961 </widget>
962 </item>
963 </layout>
964 </item>
965 <item row="1" column="1">
966 <layout class="QVBoxLayout" name="buttonMiscScrCapVerticalLayout">
967 <item>
968 <layout class="QHBoxLayout" name="buttonMiscScrCapHorizontalLayout">
969 <item>
970 <widget class="QLabel" name="labelScreenshot">
971 <property name="text">
972 <string>Screen Capture:</string>
973 </property>
974 <property name="wordWrap">
975 <bool>false</bool>
976 </property>
977 </widget>
978 </item>
979 </layout>
980 </item>
981 <item>
982 <widget class="QPushButton" name="buttonScreenshot">
983 <property name="sizePolicy">
984 <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
985 <horstretch>0</horstretch>
986 <verstretch>0</verstretch>
987 </sizepolicy>
988 </property>
989 <property name="maximumSize">
990 <size>
991 <width>80</width>
992 <height>16777215</height>
993 </size>
994 </property>
995 <property name="text">
996 <string/>
997 </property>
998 </widget>
999 </item>
1000 </layout>
1001 </item>
1002 </layout>
1003 </widget>
1004 </item>
1005 </layout>
1006 </item>
1007 <item>
1008 <spacer name="verticalSpacer">
1009 <property name="orientation">
1010 <enum>Qt::Vertical</enum>
1011 </property>
1012 <property name="sizeHint" stdset="0">
1013 <size>
1014 <width>20</width>
1015 <height>40</height>
1016 </size>
1017 </property>
1018 </spacer>
1019 </item>
1020 <item>
1021 <widget class="QLabel" name="override_label">
1022 <property name="sizePolicy">
1023 <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
1024 <horstretch>0</horstretch>
1025 <verstretch>0</verstretch>
1026 </sizepolicy>
1027 </property>
1028 <property name="text">
1029 <string>Check the box to override the global default key with this one for this game only.</string>
1030 </property>
1031 <property name="wordWrap">
1032 <bool>true</bool>
1033 </property>
1034 </widget>
1035 </item>
1036 <item>
1037 <layout class="QHBoxLayout" name="horizontalLayout"/>
1038 </item>
1039 <item>
1040 <layout class="QHBoxLayout" name="horizontalLayout_2">
1041 <item>
1042 <widget class="QPushButton" name="buttonClearAll">
1043 <property name="sizePolicy">
1044 <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
1045 <horstretch>0</horstretch>
1046 <verstretch>0</verstretch>
1047 </sizepolicy>
1048 </property>
1049 <property name="sizeIncrement">
1050 <size>
1051 <width>0</width>
1052 <height>0</height>
1053 </size>
1054 </property>
1055 <property name="baseSize">
1056 <size>
1057 <width>0</width>
1058 <height>0</height>
1059 </size>
1060 </property>
1061 <property name="layoutDirection">
1062 <enum>Qt::LeftToRight</enum>
1063 </property>
1064 <property name="text">
1065 <string>Clear All</string>
1066 </property>
1067 </widget>
1068 </item>
1069 <item>
1070 <widget class="QPushButton" name="buttonRestoreDefaults">
1071 <property name="sizePolicy">
1072 <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
1073 <horstretch>0</horstretch>
1074 <verstretch>0</verstretch>
1075 </sizepolicy>
1076 </property>
1077 <property name="sizeIncrement">
1078 <size>
1079 <width>0</width>
1080 <height>0</height>
1081 </size>
1082 </property>
1083 <property name="baseSize">
1084 <size>
1085 <width>0</width>
1086 <height>0</height>
1087 </size>
1088 </property>
1089 <property name="layoutDirection">
1090 <enum>Qt::LeftToRight</enum>
1091 </property>
1092 <property name="text">
1093 <string>Restore Defaults</string>
1094 </property>
1095 </widget>
1096 </item>
1097 <item>
1098 <spacer name="horizontalSpacer">
1099 <property name="orientation">
1100 <enum>Qt::Horizontal</enum>
1101 </property>
1102 <property name="sizeHint" stdset="0">
1103 <size>
1104 <width>40</width>
1105 <height>20</height>
1106 </size>
1107 </property>
1108 </spacer>
1109 </item>
1110 <item>
1111 <widget class="QDialogButtonBox" name="buttonBox">
1112 <property name="standardButtons">
1113 <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
1114 </property>
1115 </widget>
1116 </item>
1117 </layout>
1118 </item>
1119 </layout>
1120 </widget>
1121 <resources/>
1122 <connections>
1123 <connection>
1124 <sender>buttonBox</sender>
1125 <signal>accepted()</signal>
1126 <receiver>ConfigureInputPlayer</receiver>
1127 <slot>accept()</slot>
1128 <hints>
1129 <hint type="sourcelabel">
1130 <x>371</x>
1131 <y>730</y>
1132 </hint>
1133 <hint type="destinationlabel">
1134 <x>229</x>
1135 <y>375</y>
1136 </hint>
1137 </hints>
1138 </connection>
1139 <connection>
1140 <sender>buttonBox</sender>
1141 <signal>rejected()</signal>
1142 <receiver>ConfigureInputPlayer</receiver>
1143 <slot>reject()</slot>
1144 <hints>
1145 <hint type="sourcelabel">
1146 <x>371</x>
1147 <y>730</y>
1148 </hint>
1149 <hint type="destinationlabel">
1150 <x>229</x>
1151 <y>375</y>
1152 </hint>
1153 </hints>
1154 </connection>
1155 </connections>
1156</ui>