aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/yuzu/configuration/configure_input_player.h
blob: c4ae50de7d7fcd80a3e324b7e8b7a3414a45a375 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
// Copyright 2016 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

#pragma once

#include <array>
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include <QWidget>

#include "common/param_package.h"
#include "core/settings.h"
#include "ui_configure_input.h"

class QCheckBox;
class QKeyEvent;
class QLabel;
class QPushButton;
class QSlider;
class QSpinBox;
class QString;
class QTimer;
class QWidget;

class InputProfiles;

namespace InputCommon {
class InputSubsystem;
}

namespace InputCommon::Polling {
class DevicePoller;
enum class DeviceType;
} // namespace InputCommon::Polling

namespace Ui {
class ConfigureInputPlayer;
}

class ConfigureInputPlayer : public QWidget {
    Q_OBJECT

public:
    explicit ConfigureInputPlayer(QWidget* parent, std::size_t player_index, QWidget* bottom_row,
                                  InputCommon::InputSubsystem* input_subsystem_,
                                  InputProfiles* profiles_, bool debug = false);
    ~ConfigureInputPlayer() override;

    /// Save all button configurations to settings file.
    void ApplyConfiguration();

    /**
     * Attempts to connect the currently selected controller in the HID backend.
     * This function will not do anything if it is not connected in the frontend.
     */
    void TryConnectSelectedController();

    /**
     * Attempts to disconnect the currently selected controller in the HID backend.
     * This function will not do anything if the configuration has not changed.
     */
    void TryDisconnectSelectedController();

    /// Set the connection state checkbox (used to sync state).
    void ConnectPlayer(bool connected);

    /// Update the input devices combobox.
    void UpdateInputDeviceCombobox();

    /// Updates the list of controller profiles.
    void UpdateInputProfiles();

    /// Restore all buttons to their default values.
    void RestoreDefaults();

    /// Clear all input configuration.
    void ClearAll();

signals:
    /// Emitted when this controller is connected by the user.
    void Connected(bool connected);
    /// Emitted when the Handheld mode is selected (undocked with dual joycons attached).
    void HandheldStateChanged(bool is_handheld);
    /// Emitted when the input devices combobox is being refreshed.
    void RefreshInputDevices();
    /**
     * Emitted when the input profiles combobox is being refreshed.
     * The player_index represents the current player's index, and the profile combobox
     * will not be updated for this index as they are already updated by other mechanisms.
     */
    void RefreshInputProfiles(std::size_t player_index);

protected:
    void showEvent(QShowEvent* event) override;

private:
    void changeEvent(QEvent* event) override;
    void RetranslateUI();

    /// Load configuration settings.
    void LoadConfiguration();

    /// Called when the button was pressed.
    void HandleClick(QPushButton* button,
                     std::function<void(const Common::ParamPackage&)> new_input_setter,
                     InputCommon::Polling::DeviceType type);

    /// Finish polling and configure input using the input_setter.
    void SetPollingResult(const Common::ParamPackage& params, bool abort);

    /// Checks whether a given input can be accepted.
    bool IsInputAcceptable(const Common::ParamPackage& params) const;

    /// Handle mouse button press events.
    void mousePressEvent(QMouseEvent* event) override;

    /// Handle key press events.
    void keyPressEvent(QKeyEvent* event) override;

    /// Update UI to reflect current configuration.
    void UpdateUI();

    /// Sets the available controllers.
    void SetConnectableControllers();

    /// Gets the Controller Type for a given controller combobox index.
    Settings::ControllerType GetControllerTypeFromIndex(int index) const;

    /// Gets the controller combobox index for a given Controller Type.
    int GetIndexFromControllerType(Settings::ControllerType type) const;

    /// Update the available input devices.
    void UpdateInputDevices();

    /// Update the current controller icon.
    void UpdateControllerIcon();

    /// Hides and disables controller settings based on the current controller type.
    void UpdateControllerAvailableButtons();

    /// Shows or hides motion groupboxes based on the current controller type.
    void UpdateMotionButtons();

    /// Gets the default controller mapping for this device and auto configures the input to match.
    void UpdateMappingWithDefaults();

    /// Creates a controller profile.
    void CreateProfile();

    /// Deletes the selected controller profile.
    void DeleteProfile();

    /// Loads the selected controller profile.
    void LoadProfile();

    /// Saves the current controller configuration into a selected controller profile.
    void SaveProfile();

    std::unique_ptr<Ui::ConfigureInputPlayer> ui;

    std::size_t player_index;
    bool debug;

    InputCommon::InputSubsystem* input_subsystem;

    InputProfiles* profiles;

    std::unique_ptr<QTimer> timeout_timer;
    std::unique_ptr<QTimer> poll_timer;

    /// Stores a pair of "Connected Controllers" combobox index and Controller Type enum.
    std::vector<std::pair<int, Settings::ControllerType>> index_controller_type_pairs;

    static constexpr int PLAYER_COUNT = 8;
    std::array<QCheckBox*, PLAYER_COUNT> player_connected_checkbox;

    /// This will be the the setting function when an input is awaiting configuration.
    std::optional<std::function<void(const Common::ParamPackage&)>> input_setter;

    std::array<Common::ParamPackage, Settings::NativeButton::NumButtons> buttons_param;
    std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs> analogs_param;
    std::array<Common::ParamPackage, Settings::NativeMotion::NumMotions> motions_param;

    static constexpr int ANALOG_SUB_BUTTONS_NUM = 4;

    /// Each button input is represented by a QPushButton.
    std::array<QPushButton*, Settings::NativeButton::NumButtons> button_map;

    /// A group of four QPushButtons represent one analog input. The buttons each represent up,
    /// down, left, right, respectively.
    std::array<std::array<QPushButton*, ANALOG_SUB_BUTTONS_NUM>, Settings::NativeAnalog::NumAnalogs>
        analog_map_buttons;

    /// Each motion input is represented by a QPushButton.
    std::array<QPushButton*, Settings::NativeMotion::NumMotions> motion_map;

    std::array<QLabel*, Settings::NativeAnalog::NumAnalogs> analog_map_deadzone_label;
    std::array<QSlider*, Settings::NativeAnalog::NumAnalogs> analog_map_deadzone_slider;
    std::array<QGroupBox*, Settings::NativeAnalog::NumAnalogs> analog_map_modifier_groupbox;
    std::array<QPushButton*, Settings::NativeAnalog::NumAnalogs> analog_map_modifier_button;
    std::array<QLabel*, Settings::NativeAnalog::NumAnalogs> analog_map_modifier_label;
    std::array<QSlider*, Settings::NativeAnalog::NumAnalogs> analog_map_modifier_slider;
    std::array<QGroupBox*, Settings::NativeAnalog::NumAnalogs> analog_map_range_groupbox;
    std::array<QSpinBox*, Settings::NativeAnalog::NumAnalogs> analog_map_range_spinbox;

    static const std::array<std::string, ANALOG_SUB_BUTTONS_NUM> analog_sub_buttons;

    std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers;

    /// A flag to indicate that the "Map Analog Stick" pop-up has been shown and accepted once.
    bool map_analog_stick_accepted{};

    /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false,
    /// keyboard events are ignored.
    bool want_keyboard_mouse{};

    /// List of physical devices users can map with. If a SDL backed device is selected, then you
    /// can use this device to get a default mapping.
    std::vector<Common::ParamPackage> input_devices;

    /// Bottom row is where console wide settings are held, and its "owned" by the parent
    /// ConfigureInput widget. On show, add this widget to the main layout. This will change the
    /// parent of the widget to this widget (but thats fine).
    QWidget* bottom_row;
};