diff options
| author | 2020-11-17 20:02:27 -0800 | |
|---|---|---|
| committer | 2020-11-17 20:02:27 -0800 | |
| commit | abda36636245c416a75774165d2a5b49610952fc (patch) | |
| tree | 0bf3bab90e2155a3a16ffa21eabbc2a4c8f9d39d /src | |
| parent | Merge pull request #4933 from lioncash/nodisc-gpu (diff) | |
| parent | sdl_impl: Pump SDL Events at 1000 Hz (diff) | |
| download | yuzu-abda36636245c416a75774165d2a5b49610952fc.tar.gz yuzu-abda36636245c416a75774165d2a5b49610952fc.tar.xz yuzu-abda36636245c416a75774165d2a5b49610952fc.zip | |
Merge pull request #4866 from Morph1984/mjolnir-p3-prod
Project Mjölnir: Part 3 - Controller Profiles and Vibration Rework
Diffstat (limited to 'src')
66 files changed, 3265 insertions, 1431 deletions
diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp index 5582091f4..03bbedf8b 100644 --- a/src/core/frontend/applets/controller.cpp +++ b/src/core/frontend/applets/controller.cpp | |||
| @@ -27,19 +27,19 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb | |||
| 27 | ->GetAppletResource() | 27 | ->GetAppletResource() |
| 28 | ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad); | 28 | ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad); |
| 29 | 29 | ||
| 30 | auto& players = Settings::values.players; | 30 | auto& players = Settings::values.players.GetValue(); |
| 31 | 31 | ||
| 32 | const std::size_t min_supported_players = | 32 | const std::size_t min_supported_players = |
| 33 | parameters.enable_single_mode ? 1 : parameters.min_players; | 33 | parameters.enable_single_mode ? 1 : parameters.min_players; |
| 34 | 34 | ||
| 35 | // Disconnect Handheld first. | 35 | // Disconnect Handheld first. |
| 36 | npad.DisconnectNPadAtIndex(8); | 36 | npad.DisconnectNpadAtIndex(8); |
| 37 | 37 | ||
| 38 | // Deduce the best configuration based on the input parameters. | 38 | // Deduce the best configuration based on the input parameters. |
| 39 | for (std::size_t index = 0; index < players.size() - 2; ++index) { | 39 | for (std::size_t index = 0; index < players.size() - 2; ++index) { |
| 40 | // First, disconnect all controllers regardless of the value of keep_controllers_connected. | 40 | // First, disconnect all controllers regardless of the value of keep_controllers_connected. |
| 41 | // This makes it easy to connect the desired controllers. | 41 | // This makes it easy to connect the desired controllers. |
| 42 | npad.DisconnectNPadAtIndex(index); | 42 | npad.DisconnectNpadAtIndex(index); |
| 43 | 43 | ||
| 44 | // Only connect the minimum number of required players. | 44 | // Only connect the minimum number of required players. |
| 45 | if (index >= min_supported_players) { | 45 | if (index >= min_supported_players) { |
| @@ -66,7 +66,7 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb | |||
| 66 | npad.MapSettingsTypeToNPad(Settings::ControllerType::RightJoycon), index); | 66 | npad.MapSettingsTypeToNPad(Settings::ControllerType::RightJoycon), index); |
| 67 | } | 67 | } |
| 68 | } else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld && | 68 | } else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld && |
| 69 | !Settings::values.use_docked_mode) { | 69 | !Settings::values.use_docked_mode.GetValue()) { |
| 70 | // We should *never* reach here under any normal circumstances. | 70 | // We should *never* reach here under any normal circumstances. |
| 71 | npad.AddNewControllerAt(npad.MapSettingsTypeToNPad(Settings::ControllerType::Handheld), | 71 | npad.AddNewControllerAt(npad.MapSettingsTypeToNPad(Settings::ControllerType::Handheld), |
| 72 | index); | 72 | index); |
diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp index 1acc82497..b9a270a55 100644 --- a/src/core/frontend/framebuffer_layout.cpp +++ b/src/core/frontend/framebuffer_layout.cpp | |||
| @@ -47,7 +47,7 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height) { | |||
| 47 | FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) { | 47 | FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) { |
| 48 | u32 width, height; | 48 | u32 width, height; |
| 49 | 49 | ||
| 50 | if (Settings::values.use_docked_mode) { | 50 | if (Settings::values.use_docked_mode.GetValue()) { |
| 51 | width = ScreenDocked::Width * res_scale; | 51 | width = ScreenDocked::Width * res_scale; |
| 52 | height = ScreenDocked::Height * res_scale; | 52 | height = ScreenDocked::Height * res_scale; |
| 53 | } else { | 53 | } else { |
diff --git a/src/core/frontend/input.h b/src/core/frontend/input.h index 277b70e53..25ac5af46 100644 --- a/src/core/frontend/input.h +++ b/src/core/frontend/input.h | |||
| @@ -33,7 +33,7 @@ public: | |||
| 33 | virtual bool GetAnalogDirectionStatus(AnalogDirection direction) const { | 33 | virtual bool GetAnalogDirectionStatus(AnalogDirection direction) const { |
| 34 | return {}; | 34 | return {}; |
| 35 | } | 35 | } |
| 36 | virtual bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const { | 36 | virtual bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const { |
| 37 | return {}; | 37 | return {}; |
| 38 | } | 38 | } |
| 39 | }; | 39 | }; |
| @@ -122,6 +122,13 @@ using ButtonDevice = InputDevice<bool>; | |||
| 122 | using AnalogDevice = InputDevice<std::tuple<float, float>>; | 122 | using AnalogDevice = InputDevice<std::tuple<float, float>>; |
| 123 | 123 | ||
| 124 | /** | 124 | /** |
| 125 | * A vibration device is an input device that returns an unsigned byte as status. | ||
| 126 | * It represents whether the vibration device supports vibration or not. | ||
| 127 | * If the status returns 1, it supports vibration. Otherwise, it does not support vibration. | ||
| 128 | */ | ||
| 129 | using VibrationDevice = InputDevice<u8>; | ||
| 130 | |||
| 131 | /** | ||
| 125 | * A motion status is an object that returns a tuple of accelerometer state vector, | 132 | * A motion status is an object that returns a tuple of accelerometer state vector, |
| 126 | * gyroscope state vector, rotation state vector and orientation state matrix. | 133 | * gyroscope state vector, rotation state vector and orientation state matrix. |
| 127 | * | 134 | * |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 2ce742e35..eb097738a 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -751,7 +751,7 @@ void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext& | |||
| 751 | IPC::ResponseBuilder rb{ctx, 4}; | 751 | IPC::ResponseBuilder rb{ctx, 4}; |
| 752 | rb.Push(RESULT_SUCCESS); | 752 | rb.Push(RESULT_SUCCESS); |
| 753 | 753 | ||
| 754 | if (Settings::values.use_docked_mode) { | 754 | if (Settings::values.use_docked_mode.GetValue()) { |
| 755 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) * | 755 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) * |
| 756 | static_cast<u32>(Settings::values.resolution_factor.GetValue())); | 756 | static_cast<u32>(Settings::values.resolution_factor.GetValue())); |
| 757 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) * | 757 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) * |
| @@ -824,7 +824,7 @@ void IStorage::Open(Kernel::HLERequestContext& ctx) { | |||
| 824 | } | 824 | } |
| 825 | 825 | ||
| 826 | void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { | 826 | void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { |
| 827 | const bool use_docked_mode{Settings::values.use_docked_mode}; | 827 | const bool use_docked_mode{Settings::values.use_docked_mode.GetValue()}; |
| 828 | LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode); | 828 | LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode); |
| 829 | 829 | ||
| 830 | IPC::ResponseBuilder rb{ctx, 3}; | 830 | IPC::ResponseBuilder rb{ctx, 3}; |
diff --git a/src/core/hle/service/am/applets/controller.cpp b/src/core/hle/service/am/applets/controller.cpp index a0152b4ea..3ca63f020 100644 --- a/src/core/hle/service/am/applets/controller.cpp +++ b/src/core/hle/service/am/applets/controller.cpp | |||
| @@ -25,7 +25,7 @@ namespace Service::AM::Applets { | |||
| 25 | static Core::Frontend::ControllerParameters ConvertToFrontendParameters( | 25 | static Core::Frontend::ControllerParameters ConvertToFrontendParameters( |
| 26 | ControllerSupportArgPrivate private_arg, ControllerSupportArgHeader header, bool enable_text, | 26 | ControllerSupportArgPrivate private_arg, ControllerSupportArgHeader header, bool enable_text, |
| 27 | std::vector<IdentificationColor> identification_colors, std::vector<ExplainText> text) { | 27 | std::vector<IdentificationColor> identification_colors, std::vector<ExplainText> text) { |
| 28 | HID::Controller_NPad::NPadType npad_style_set; | 28 | HID::Controller_NPad::NpadStyleSet npad_style_set; |
| 29 | npad_style_set.raw = private_arg.style_set; | 29 | npad_style_set.raw = private_arg.style_set; |
| 30 | 30 | ||
| 31 | return { | 31 | return { |
| @@ -222,7 +222,7 @@ void Controller::Execute() { | |||
| 222 | void Controller::ConfigurationComplete() { | 222 | void Controller::ConfigurationComplete() { |
| 223 | ControllerSupportResultInfo result_info{}; | 223 | ControllerSupportResultInfo result_info{}; |
| 224 | 224 | ||
| 225 | const auto& players = Settings::values.players; | 225 | const auto& players = Settings::values.players.GetValue(); |
| 226 | 226 | ||
| 227 | // If enable_single_mode is enabled, player_count is 1 regardless of any other parameters. | 227 | // If enable_single_mode is enabled, player_count is 1 regardless of any other parameters. |
| 228 | // Otherwise, only count connected players from P1-P8. | 228 | // Otherwise, only count connected players from P1-P8. |
diff --git a/src/core/hle/service/apm/controller.cpp b/src/core/hle/service/apm/controller.cpp index 25a886238..ce993bad3 100644 --- a/src/core/hle/service/apm/controller.cpp +++ b/src/core/hle/service/apm/controller.cpp | |||
| @@ -69,7 +69,8 @@ void Controller::SetFromCpuBoostMode(CpuBoostMode mode) { | |||
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | PerformanceMode Controller::GetCurrentPerformanceMode() const { | 71 | PerformanceMode Controller::GetCurrentPerformanceMode() const { |
| 72 | return Settings::values.use_docked_mode ? PerformanceMode::Docked : PerformanceMode::Handheld; | 72 | return Settings::values.use_docked_mode.GetValue() ? PerformanceMode::Docked |
| 73 | : PerformanceMode::Handheld; | ||
| 73 | } | 74 | } |
| 74 | 75 | ||
| 75 | PerformanceConfiguration Controller::GetCurrentPerformanceConfiguration(PerformanceMode mode) { | 76 | PerformanceConfiguration Controller::GetCurrentPerformanceConfiguration(PerformanceMode mode) { |
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index e311bc18c..e2539ded8 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp | |||
| @@ -117,7 +117,10 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) { | |||
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {} | 119 | Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {} |
| 120 | Controller_NPad::~Controller_NPad() = default; | 120 | |
| 121 | Controller_NPad::~Controller_NPad() { | ||
| 122 | OnRelease(); | ||
| 123 | } | ||
| 121 | 124 | ||
| 122 | void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { | 125 | void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { |
| 123 | const auto controller_type = connected_controllers[controller_idx].type; | 126 | const auto controller_type = connected_controllers[controller_idx].type; |
| @@ -139,7 +142,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { | |||
| 139 | controller.properties.is_vertical.Assign(1); | 142 | controller.properties.is_vertical.Assign(1); |
| 140 | controller.properties.use_plus.Assign(1); | 143 | controller.properties.use_plus.Assign(1); |
| 141 | controller.properties.use_minus.Assign(1); | 144 | controller.properties.use_minus.Assign(1); |
| 142 | controller.pad_assignment = NPadAssignments::Single; | 145 | controller.pad_assignment = NpadAssignments::Single; |
| 143 | break; | 146 | break; |
| 144 | case NPadControllerType::Handheld: | 147 | case NPadControllerType::Handheld: |
| 145 | controller.joy_styles.handheld.Assign(1); | 148 | controller.joy_styles.handheld.Assign(1); |
| @@ -147,7 +150,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { | |||
| 147 | controller.properties.is_vertical.Assign(1); | 150 | controller.properties.is_vertical.Assign(1); |
| 148 | controller.properties.use_plus.Assign(1); | 151 | controller.properties.use_plus.Assign(1); |
| 149 | controller.properties.use_minus.Assign(1); | 152 | controller.properties.use_minus.Assign(1); |
| 150 | controller.pad_assignment = NPadAssignments::Dual; | 153 | controller.pad_assignment = NpadAssignments::Dual; |
| 151 | break; | 154 | break; |
| 152 | case NPadControllerType::JoyDual: | 155 | case NPadControllerType::JoyDual: |
| 153 | controller.joy_styles.joycon_dual.Assign(1); | 156 | controller.joy_styles.joycon_dual.Assign(1); |
| @@ -156,26 +159,26 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { | |||
| 156 | controller.properties.is_vertical.Assign(1); | 159 | controller.properties.is_vertical.Assign(1); |
| 157 | controller.properties.use_plus.Assign(1); | 160 | controller.properties.use_plus.Assign(1); |
| 158 | controller.properties.use_minus.Assign(1); | 161 | controller.properties.use_minus.Assign(1); |
| 159 | controller.pad_assignment = NPadAssignments::Dual; | 162 | controller.pad_assignment = NpadAssignments::Dual; |
| 160 | break; | 163 | break; |
| 161 | case NPadControllerType::JoyLeft: | 164 | case NPadControllerType::JoyLeft: |
| 162 | controller.joy_styles.joycon_left.Assign(1); | 165 | controller.joy_styles.joycon_left.Assign(1); |
| 163 | controller.device_type.joycon_left.Assign(1); | 166 | controller.device_type.joycon_left.Assign(1); |
| 164 | controller.properties.is_horizontal.Assign(1); | 167 | controller.properties.is_horizontal.Assign(1); |
| 165 | controller.properties.use_minus.Assign(1); | 168 | controller.properties.use_minus.Assign(1); |
| 166 | controller.pad_assignment = NPadAssignments::Single; | 169 | controller.pad_assignment = NpadAssignments::Single; |
| 167 | break; | 170 | break; |
| 168 | case NPadControllerType::JoyRight: | 171 | case NPadControllerType::JoyRight: |
| 169 | controller.joy_styles.joycon_right.Assign(1); | 172 | controller.joy_styles.joycon_right.Assign(1); |
| 170 | controller.device_type.joycon_right.Assign(1); | 173 | controller.device_type.joycon_right.Assign(1); |
| 171 | controller.properties.is_horizontal.Assign(1); | 174 | controller.properties.is_horizontal.Assign(1); |
| 172 | controller.properties.use_plus.Assign(1); | 175 | controller.properties.use_plus.Assign(1); |
| 173 | controller.pad_assignment = NPadAssignments::Single; | 176 | controller.pad_assignment = NpadAssignments::Single; |
| 174 | break; | 177 | break; |
| 175 | case NPadControllerType::Pokeball: | 178 | case NPadControllerType::Pokeball: |
| 176 | controller.joy_styles.pokeball.Assign(1); | 179 | controller.joy_styles.pokeball.Assign(1); |
| 177 | controller.device_type.pokeball.Assign(1); | 180 | controller.device_type.pokeball.Assign(1); |
| 178 | controller.pad_assignment = NPadAssignments::Single; | 181 | controller.pad_assignment = NpadAssignments::Single; |
| 179 | break; | 182 | break; |
| 180 | } | 183 | } |
| 181 | 184 | ||
| @@ -184,11 +187,14 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { | |||
| 184 | controller.single_color.button_color = 0; | 187 | controller.single_color.button_color = 0; |
| 185 | 188 | ||
| 186 | controller.dual_color_error = ColorReadError::ReadOk; | 189 | controller.dual_color_error = ColorReadError::ReadOk; |
| 187 | controller.left_color.body_color = Settings::values.players[controller_idx].body_color_left; | 190 | controller.left_color.body_color = |
| 188 | controller.left_color.button_color = Settings::values.players[controller_idx].button_color_left; | 191 | Settings::values.players.GetValue()[controller_idx].body_color_left; |
| 189 | controller.right_color.body_color = Settings::values.players[controller_idx].body_color_right; | 192 | controller.left_color.button_color = |
| 193 | Settings::values.players.GetValue()[controller_idx].button_color_left; | ||
| 194 | controller.right_color.body_color = | ||
| 195 | Settings::values.players.GetValue()[controller_idx].body_color_right; | ||
| 190 | controller.right_color.button_color = | 196 | controller.right_color.button_color = |
| 191 | Settings::values.players[controller_idx].button_color_right; | 197 | Settings::values.players.GetValue()[controller_idx].button_color_right; |
| 192 | 198 | ||
| 193 | controller.battery_level[0] = BATTERY_FULL; | 199 | controller.battery_level[0] = BATTERY_FULL; |
| 194 | controller.battery_level[1] = BATTERY_FULL; | 200 | controller.battery_level[1] = BATTERY_FULL; |
| @@ -199,7 +205,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) { | |||
| 199 | 205 | ||
| 200 | void Controller_NPad::OnInit() { | 206 | void Controller_NPad::OnInit() { |
| 201 | auto& kernel = system.Kernel(); | 207 | auto& kernel = system.Kernel(); |
| 202 | for (std::size_t i = 0; i < styleset_changed_events.size(); i++) { | 208 | for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) { |
| 203 | styleset_changed_events[i] = Kernel::WritableEvent::CreateEventPair( | 209 | styleset_changed_events[i] = Kernel::WritableEvent::CreateEventPair( |
| 204 | kernel, fmt::format("npad:NpadStyleSetChanged_{}", i)); | 210 | kernel, fmt::format("npad:NpadStyleSetChanged_{}", i)); |
| 205 | } | 211 | } |
| @@ -208,6 +214,8 @@ void Controller_NPad::OnInit() { | |||
| 208 | return; | 214 | return; |
| 209 | } | 215 | } |
| 210 | 216 | ||
| 217 | OnLoadInputDevices(); | ||
| 218 | |||
| 211 | if (style.raw == 0) { | 219 | if (style.raw == 0) { |
| 212 | // We want to support all controllers | 220 | // We want to support all controllers |
| 213 | style.handheld.Assign(1); | 221 | style.handheld.Assign(1); |
| @@ -218,12 +226,27 @@ void Controller_NPad::OnInit() { | |||
| 218 | style.pokeball.Assign(1); | 226 | style.pokeball.Assign(1); |
| 219 | } | 227 | } |
| 220 | 228 | ||
| 221 | std::transform(Settings::values.players.begin(), Settings::values.players.end(), | 229 | std::transform(Settings::values.players.GetValue().begin(), |
| 222 | connected_controllers.begin(), [](const Settings::PlayerInput& player) { | 230 | Settings::values.players.GetValue().end(), connected_controllers.begin(), |
| 231 | [](const Settings::PlayerInput& player) { | ||
| 223 | return ControllerHolder{MapSettingsTypeToNPad(player.controller_type), | 232 | return ControllerHolder{MapSettingsTypeToNPad(player.controller_type), |
| 224 | player.connected}; | 233 | player.connected}; |
| 225 | }); | 234 | }); |
| 226 | 235 | ||
| 236 | // Connect the Player 1 or Handheld controller if none are connected. | ||
| 237 | if (std::none_of(connected_controllers.begin(), connected_controllers.end(), | ||
| 238 | [](const ControllerHolder& controller) { return controller.is_connected; })) { | ||
| 239 | const auto controller = | ||
| 240 | MapSettingsTypeToNPad(Settings::values.players.GetValue()[0].controller_type); | ||
| 241 | if (controller == NPadControllerType::Handheld) { | ||
| 242 | Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true; | ||
| 243 | connected_controllers[HANDHELD_INDEX] = {controller, true}; | ||
| 244 | } else { | ||
| 245 | Settings::values.players.GetValue()[0].connected = true; | ||
| 246 | connected_controllers[0] = {controller, true}; | ||
| 247 | } | ||
| 248 | } | ||
| 249 | |||
| 227 | // Account for handheld | 250 | // Account for handheld |
| 228 | if (connected_controllers[HANDHELD_INDEX].is_connected) { | 251 | if (connected_controllers[HANDHELD_INDEX].is_connected) { |
| 229 | connected_controllers[HANDHELD_INDEX].type = NPadControllerType::Handheld; | 252 | connected_controllers[HANDHELD_INDEX].type = NPadControllerType::Handheld; |
| @@ -242,7 +265,7 @@ void Controller_NPad::OnInit() { | |||
| 242 | } | 265 | } |
| 243 | 266 | ||
| 244 | void Controller_NPad::OnLoadInputDevices() { | 267 | void Controller_NPad::OnLoadInputDevices() { |
| 245 | const auto& players = Settings::values.players; | 268 | const auto& players = Settings::values.players.GetValue(); |
| 246 | for (std::size_t i = 0; i < players.size(); ++i) { | 269 | for (std::size_t i = 0; i < players.size(); ++i) { |
| 247 | std::transform(players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, | 270 | std::transform(players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, |
| 248 | players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_END, | 271 | players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_END, |
| @@ -250,13 +273,26 @@ void Controller_NPad::OnLoadInputDevices() { | |||
| 250 | std::transform(players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, | 273 | std::transform(players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, |
| 251 | players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_END, | 274 | players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_END, |
| 252 | sticks[i].begin(), Input::CreateDevice<Input::AnalogDevice>); | 275 | sticks[i].begin(), Input::CreateDevice<Input::AnalogDevice>); |
| 276 | std::transform(players[i].vibrations.begin() + | ||
| 277 | Settings::NativeVibration::VIBRATION_HID_BEGIN, | ||
| 278 | players[i].vibrations.begin() + Settings::NativeVibration::VIBRATION_HID_END, | ||
| 279 | vibrations[i].begin(), Input::CreateDevice<Input::VibrationDevice>); | ||
| 253 | std::transform(players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN, | 280 | std::transform(players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN, |
| 254 | players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_END, | 281 | players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_END, |
| 255 | motions[i].begin(), Input::CreateDevice<Input::MotionDevice>); | 282 | motions[i].begin(), Input::CreateDevice<Input::MotionDevice>); |
| 283 | for (std::size_t device_idx = 0; device_idx < vibrations[i].size(); ++device_idx) { | ||
| 284 | InitializeVibrationDeviceAtIndex(i, device_idx); | ||
| 285 | } | ||
| 256 | } | 286 | } |
| 257 | } | 287 | } |
| 258 | 288 | ||
| 259 | void Controller_NPad::OnRelease() {} | 289 | void Controller_NPad::OnRelease() { |
| 290 | for (std::size_t npad_idx = 0; npad_idx < vibrations.size(); ++npad_idx) { | ||
| 291 | for (std::size_t device_idx = 0; device_idx < vibrations[npad_idx].size(); ++device_idx) { | ||
| 292 | VibrateControllerAtIndex(npad_idx, device_idx, {}); | ||
| 293 | } | ||
| 294 | } | ||
| 295 | } | ||
| 260 | 296 | ||
| 261 | void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { | 297 | void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { |
| 262 | const auto controller_idx = NPadIdToIndex(npad_id); | 298 | const auto controller_idx = NPadIdToIndex(npad_id); |
| @@ -339,7 +375,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* | |||
| 339 | if (!IsControllerActivated()) { | 375 | if (!IsControllerActivated()) { |
| 340 | return; | 376 | return; |
| 341 | } | 377 | } |
| 342 | for (std::size_t i = 0; i < shared_memory_entries.size(); i++) { | 378 | for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) { |
| 343 | auto& npad = shared_memory_entries[i]; | 379 | auto& npad = shared_memory_entries[i]; |
| 344 | const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states, | 380 | const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states, |
| 345 | &npad.handheld_states, | 381 | &npad.handheld_states, |
| @@ -481,7 +517,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing | |||
| 481 | if (!IsControllerActivated()) { | 517 | if (!IsControllerActivated()) { |
| 482 | return; | 518 | return; |
| 483 | } | 519 | } |
| 484 | for (std::size_t i = 0; i < shared_memory_entries.size(); i++) { | 520 | for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) { |
| 485 | auto& npad = shared_memory_entries[i]; | 521 | auto& npad = shared_memory_entries[i]; |
| 486 | 522 | ||
| 487 | const auto& controller_type = connected_controllers[i].type; | 523 | const auto& controller_type = connected_controllers[i].type; |
| @@ -515,7 +551,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing | |||
| 515 | // Try to read sixaxis sensor states | 551 | // Try to read sixaxis sensor states |
| 516 | std::array<MotionDevice, 2> motion_devices; | 552 | std::array<MotionDevice, 2> motion_devices; |
| 517 | 553 | ||
| 518 | if (sixaxis_sensors_enabled && Settings::values.motion_enabled) { | 554 | if (sixaxis_sensors_enabled && Settings::values.motion_enabled.GetValue()) { |
| 519 | sixaxis_at_rest = true; | 555 | sixaxis_at_rest = true; |
| 520 | for (std::size_t e = 0; e < motion_devices.size(); ++e) { | 556 | for (std::size_t e = 0; e < motion_devices.size(); ++e) { |
| 521 | const auto& device = motions[i][e]; | 557 | const auto& device = motions[i][e]; |
| @@ -601,15 +637,15 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing | |||
| 601 | shared_memory_entries.size() * sizeof(NPadEntry)); | 637 | shared_memory_entries.size() * sizeof(NPadEntry)); |
| 602 | } | 638 | } |
| 603 | 639 | ||
| 604 | void Controller_NPad::SetSupportedStyleSet(NPadType style_set) { | 640 | void Controller_NPad::SetSupportedStyleSet(NpadStyleSet style_set) { |
| 605 | style.raw = style_set.raw; | 641 | style.raw = style_set.raw; |
| 606 | } | 642 | } |
| 607 | 643 | ||
| 608 | Controller_NPad::NPadType Controller_NPad::GetSupportedStyleSet() const { | 644 | Controller_NPad::NpadStyleSet Controller_NPad::GetSupportedStyleSet() const { |
| 609 | return style; | 645 | return style; |
| 610 | } | 646 | } |
| 611 | 647 | ||
| 612 | void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) { | 648 | void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) { |
| 613 | ASSERT(length > 0 && (length % sizeof(u32)) == 0); | 649 | ASSERT(length > 0 && (length % sizeof(u32)) == 0); |
| 614 | supported_npad_id_types.clear(); | 650 | supported_npad_id_types.clear(); |
| 615 | supported_npad_id_types.resize(length / sizeof(u32)); | 651 | supported_npad_id_types.resize(length / sizeof(u32)); |
| @@ -621,7 +657,7 @@ void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) | |||
| 621 | std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size()); | 657 | std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size()); |
| 622 | } | 658 | } |
| 623 | 659 | ||
| 624 | std::size_t Controller_NPad::GetSupportedNPadIdTypesSize() const { | 660 | std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const { |
| 625 | return supported_npad_id_types.size(); | 661 | return supported_npad_id_types.size(); |
| 626 | } | 662 | } |
| 627 | 663 | ||
| @@ -641,7 +677,7 @@ Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActi | |||
| 641 | return handheld_activation_mode; | 677 | return handheld_activation_mode; |
| 642 | } | 678 | } |
| 643 | 679 | ||
| 644 | void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) { | 680 | void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) { |
| 645 | const std::size_t npad_index = NPadIdToIndex(npad_id); | 681 | const std::size_t npad_index = NPadIdToIndex(npad_id); |
| 646 | ASSERT(npad_index < shared_memory_entries.size()); | 682 | ASSERT(npad_index < shared_memory_entries.size()); |
| 647 | if (shared_memory_entries[npad_index].pad_assignment != assignment_mode) { | 683 | if (shared_memory_entries[npad_index].pad_assignment != assignment_mode) { |
| @@ -649,35 +685,140 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) | |||
| 649 | } | 685 | } |
| 650 | } | 686 | } |
| 651 | 687 | ||
| 652 | void Controller_NPad::VibrateController(const std::vector<u32>& controllers, | 688 | bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, |
| 653 | const std::vector<Vibration>& vibrations) { | 689 | const VibrationValue& vibration_value) { |
| 654 | LOG_TRACE(Service_HID, "called"); | 690 | if (!connected_controllers[npad_index].is_connected || !vibrations[npad_index][device_index]) { |
| 655 | 691 | return false; | |
| 656 | if (!Settings::values.vibration_enabled || !can_controllers_vibrate) { | ||
| 657 | return; | ||
| 658 | } | 692 | } |
| 659 | bool success = true; | 693 | |
| 660 | for (std::size_t i = 0; i < controllers.size(); ++i) { | 694 | const auto& player = Settings::values.players.GetValue()[npad_index]; |
| 661 | if (!connected_controllers[i].is_connected) { | 695 | |
| 662 | continue; | 696 | if (!player.vibration_enabled) { |
| 697 | if (latest_vibration_values[npad_index][device_index].amp_low != 0.0f || | ||
| 698 | latest_vibration_values[npad_index][device_index].amp_high != 0.0f) { | ||
| 699 | // Send an empty vibration to stop any vibrations. | ||
| 700 | vibrations[npad_index][device_index]->SetRumblePlay(0.0f, 160.0f, 0.0f, 320.0f); | ||
| 701 | // Then reset the vibration value to its default value. | ||
| 702 | latest_vibration_values[npad_index][device_index] = {}; | ||
| 663 | } | 703 | } |
| 664 | using namespace Settings::NativeButton; | 704 | |
| 665 | const auto& button_state = buttons[i]; | 705 | return false; |
| 666 | if (button_state[A - BUTTON_HID_BEGIN]) { | 706 | } |
| 667 | if (button_state[A - BUTTON_HID_BEGIN]->SetRumblePlay( | 707 | |
| 668 | vibrations[0].amp_high, vibrations[0].amp_low, vibrations[0].freq_high, | 708 | if (!Settings::values.enable_accurate_vibrations.GetValue()) { |
| 669 | vibrations[0].freq_low)) { | 709 | using std::chrono::duration_cast; |
| 670 | success = false; | 710 | using std::chrono::milliseconds; |
| 671 | } | 711 | using std::chrono::steady_clock; |
| 712 | |||
| 713 | const auto now = steady_clock::now(); | ||
| 714 | |||
| 715 | // Filter out non-zero vibrations that are within 10ms of each other. | ||
| 716 | if ((vibration_value.amp_low != 0.0f || vibration_value.amp_high != 0.0f) && | ||
| 717 | duration_cast<milliseconds>(now - last_vibration_timepoints[npad_index][device_index]) < | ||
| 718 | milliseconds(10)) { | ||
| 719 | return false; | ||
| 672 | } | 720 | } |
| 721 | |||
| 722 | last_vibration_timepoints[npad_index][device_index] = now; | ||
| 723 | } | ||
| 724 | |||
| 725 | auto& vibration = vibrations[npad_index][device_index]; | ||
| 726 | const auto player_vibration_strength = static_cast<f32>(player.vibration_strength); | ||
| 727 | const auto amp_low = | ||
| 728 | std::min(vibration_value.amp_low * player_vibration_strength / 100.0f, 1.0f); | ||
| 729 | const auto amp_high = | ||
| 730 | std::min(vibration_value.amp_high * player_vibration_strength / 100.0f, 1.0f); | ||
| 731 | return vibration->SetRumblePlay(amp_low, vibration_value.freq_low, amp_high, | ||
| 732 | vibration_value.freq_high); | ||
| 733 | } | ||
| 734 | |||
| 735 | void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle, | ||
| 736 | const VibrationValue& vibration_value) { | ||
| 737 | if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { | ||
| 738 | return; | ||
| 739 | } | ||
| 740 | |||
| 741 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); | ||
| 742 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 743 | |||
| 744 | if (!vibration_devices_mounted[npad_index][device_index] || | ||
| 745 | !connected_controllers[npad_index].is_connected) { | ||
| 746 | return; | ||
| 673 | } | 747 | } |
| 674 | if (success) { | 748 | |
| 675 | last_processed_vibration = vibrations.back(); | 749 | if (vibration_device_handle.device_index == DeviceIndex::None) { |
| 750 | UNREACHABLE_MSG("DeviceIndex should never be None!"); | ||
| 751 | return; | ||
| 752 | } | ||
| 753 | |||
| 754 | // Some games try to send mismatched parameters in the device handle, block these. | ||
| 755 | if ((connected_controllers[npad_index].type == NPadControllerType::JoyLeft && | ||
| 756 | (vibration_device_handle.npad_type == NpadType::JoyconRight || | ||
| 757 | vibration_device_handle.device_index == DeviceIndex::Right)) || | ||
| 758 | (connected_controllers[npad_index].type == NPadControllerType::JoyRight && | ||
| 759 | (vibration_device_handle.npad_type == NpadType::JoyconLeft || | ||
| 760 | vibration_device_handle.device_index == DeviceIndex::Left))) { | ||
| 761 | return; | ||
| 762 | } | ||
| 763 | |||
| 764 | // Filter out vibrations with equivalent values to reduce unnecessary state changes. | ||
| 765 | if (vibration_value.amp_low == latest_vibration_values[npad_index][device_index].amp_low && | ||
| 766 | vibration_value.amp_high == latest_vibration_values[npad_index][device_index].amp_high) { | ||
| 767 | return; | ||
| 768 | } | ||
| 769 | |||
| 770 | if (VibrateControllerAtIndex(npad_index, device_index, vibration_value)) { | ||
| 771 | latest_vibration_values[npad_index][device_index] = vibration_value; | ||
| 676 | } | 772 | } |
| 677 | } | 773 | } |
| 678 | 774 | ||
| 679 | Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { | 775 | void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles, |
| 680 | return last_processed_vibration; | 776 | const std::vector<VibrationValue>& vibration_values) { |
| 777 | if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { | ||
| 778 | return; | ||
| 779 | } | ||
| 780 | |||
| 781 | ASSERT_OR_EXECUTE_MSG( | ||
| 782 | vibration_device_handles.size() == vibration_values.size(), { return; }, | ||
| 783 | "The amount of device handles does not match with the amount of vibration values," | ||
| 784 | "this is undefined behavior!"); | ||
| 785 | |||
| 786 | for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) { | ||
| 787 | VibrateController(vibration_device_handles[i], vibration_values[i]); | ||
| 788 | } | ||
| 789 | } | ||
| 790 | |||
| 791 | Controller_NPad::VibrationValue Controller_NPad::GetLastVibration( | ||
| 792 | const DeviceHandle& vibration_device_handle) const { | ||
| 793 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); | ||
| 794 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 795 | return latest_vibration_values[npad_index][device_index]; | ||
| 796 | } | ||
| 797 | |||
| 798 | void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) { | ||
| 799 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); | ||
| 800 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 801 | InitializeVibrationDeviceAtIndex(npad_index, device_index); | ||
| 802 | } | ||
| 803 | |||
| 804 | void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index, | ||
| 805 | std::size_t device_index) { | ||
| 806 | if (vibrations[npad_index][device_index]) { | ||
| 807 | vibration_devices_mounted[npad_index][device_index] = | ||
| 808 | vibrations[npad_index][device_index]->GetStatus() == 1; | ||
| 809 | } else { | ||
| 810 | vibration_devices_mounted[npad_index][device_index] = false; | ||
| 811 | } | ||
| 812 | } | ||
| 813 | |||
| 814 | void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) { | ||
| 815 | permit_vibration_session_enabled = permit_vibration_session; | ||
| 816 | } | ||
| 817 | |||
| 818 | bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const { | ||
| 819 | const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id); | ||
| 820 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 821 | return vibration_devices_mounted[npad_index][device_index]; | ||
| 681 | } | 822 | } |
| 682 | 823 | ||
| 683 | std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { | 824 | std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const { |
| @@ -696,31 +837,38 @@ void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::siz | |||
| 696 | void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, | 837 | void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, |
| 697 | bool connected) { | 838 | bool connected) { |
| 698 | if (!connected) { | 839 | if (!connected) { |
| 699 | DisconnectNPadAtIndex(npad_index); | 840 | DisconnectNpadAtIndex(npad_index); |
| 700 | return; | 841 | return; |
| 701 | } | 842 | } |
| 702 | 843 | ||
| 703 | if (controller == NPadControllerType::Handheld) { | 844 | if (controller == NPadControllerType::Handheld) { |
| 704 | Settings::values.players[HANDHELD_INDEX].controller_type = | 845 | Settings::values.players.GetValue()[HANDHELD_INDEX].controller_type = |
| 705 | MapNPadToSettingsType(controller); | 846 | MapNPadToSettingsType(controller); |
| 706 | Settings::values.players[HANDHELD_INDEX].connected = true; | 847 | Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true; |
| 707 | connected_controllers[HANDHELD_INDEX] = {controller, true}; | 848 | connected_controllers[HANDHELD_INDEX] = {controller, true}; |
| 708 | InitNewlyAddedController(HANDHELD_INDEX); | 849 | InitNewlyAddedController(HANDHELD_INDEX); |
| 709 | return; | 850 | return; |
| 710 | } | 851 | } |
| 711 | 852 | ||
| 712 | Settings::values.players[npad_index].controller_type = MapNPadToSettingsType(controller); | 853 | Settings::values.players.GetValue()[npad_index].controller_type = |
| 713 | Settings::values.players[npad_index].connected = true; | 854 | MapNPadToSettingsType(controller); |
| 855 | Settings::values.players.GetValue()[npad_index].connected = true; | ||
| 714 | connected_controllers[npad_index] = {controller, true}; | 856 | connected_controllers[npad_index] = {controller, true}; |
| 715 | InitNewlyAddedController(npad_index); | 857 | InitNewlyAddedController(npad_index); |
| 716 | } | 858 | } |
| 717 | 859 | ||
| 718 | void Controller_NPad::DisconnectNPad(u32 npad_id) { | 860 | void Controller_NPad::DisconnectNpad(u32 npad_id) { |
| 719 | DisconnectNPadAtIndex(NPadIdToIndex(npad_id)); | 861 | DisconnectNpadAtIndex(NPadIdToIndex(npad_id)); |
| 720 | } | 862 | } |
| 721 | 863 | ||
| 722 | void Controller_NPad::DisconnectNPadAtIndex(std::size_t npad_index) { | 864 | void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) { |
| 723 | Settings::values.players[npad_index].connected = false; | 865 | for (std::size_t device_idx = 0; device_idx < vibrations[npad_index].size(); ++device_idx) { |
| 866 | // Send an empty vibration to stop any vibrations. | ||
| 867 | VibrateControllerAtIndex(npad_index, device_idx, {}); | ||
| 868 | vibration_devices_mounted[npad_index][device_idx] = false; | ||
| 869 | } | ||
| 870 | |||
| 871 | Settings::values.players.GetValue()[npad_index].connected = false; | ||
| 724 | connected_controllers[npad_index].is_connected = false; | 872 | connected_controllers[npad_index].is_connected = false; |
| 725 | 873 | ||
| 726 | auto& controller = shared_memory_entries[npad_index]; | 874 | auto& controller = shared_memory_entries[npad_index]; |
| @@ -758,7 +906,7 @@ void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) { | |||
| 758 | (connected_controllers[npad_index_2].type == NPadControllerType::JoyLeft && | 906 | (connected_controllers[npad_index_2].type == NPadControllerType::JoyLeft && |
| 759 | connected_controllers[npad_index_1].type == NPadControllerType::JoyRight)) { | 907 | connected_controllers[npad_index_1].type == NPadControllerType::JoyRight)) { |
| 760 | // Disconnect the joycon at the second id and connect the dual joycon at the first index. | 908 | // Disconnect the joycon at the second id and connect the dual joycon at the first index. |
| 761 | DisconnectNPad(npad_id_2); | 909 | DisconnectNpad(npad_id_2); |
| 762 | AddNewControllerAt(NPadControllerType::JoyDual, npad_index_1); | 910 | AddNewControllerAt(NPadControllerType::JoyDual, npad_index_1); |
| 763 | } | 911 | } |
| 764 | } | 912 | } |
| @@ -830,14 +978,6 @@ void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_prot | |||
| 830 | unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled; | 978 | unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled; |
| 831 | } | 979 | } |
| 832 | 980 | ||
| 833 | void Controller_NPad::SetVibrationEnabled(bool can_vibrate) { | ||
| 834 | can_controllers_vibrate = can_vibrate; | ||
| 835 | } | ||
| 836 | |||
| 837 | bool Controller_NPad::IsVibrationEnabled() const { | ||
| 838 | return can_controllers_vibrate; | ||
| 839 | } | ||
| 840 | |||
| 841 | void Controller_NPad::ClearAllConnectedControllers() { | 981 | void Controller_NPad::ClearAllConnectedControllers() { |
| 842 | for (auto& controller : connected_controllers) { | 982 | for (auto& controller : connected_controllers) { |
| 843 | if (controller.is_connected && controller.type != NPadControllerType::None) { | 983 | if (controller.is_connected && controller.type != NPadControllerType::None) { |
| @@ -882,7 +1022,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const | |||
| 882 | return false; | 1022 | return false; |
| 883 | } | 1023 | } |
| 884 | // Handheld should not be supported in docked mode | 1024 | // Handheld should not be supported in docked mode |
| 885 | if (Settings::values.use_docked_mode) { | 1025 | if (Settings::values.use_docked_mode.GetValue()) { |
| 886 | return false; | 1026 | return false; |
| 887 | } | 1027 | } |
| 888 | 1028 | ||
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index fd5c5a6eb..160dcbbe3 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h | |||
| @@ -39,28 +39,30 @@ public: | |||
| 39 | // Called when input devices should be loaded | 39 | // Called when input devices should be loaded |
| 40 | void OnLoadInputDevices() override; | 40 | void OnLoadInputDevices() override; |
| 41 | 41 | ||
| 42 | struct NPadType { | 42 | enum class NPadControllerType { |
| 43 | union { | 43 | None, |
| 44 | u32_le raw{}; | 44 | ProController, |
| 45 | 45 | Handheld, | |
| 46 | BitField<0, 1, u32> pro_controller; | 46 | JoyDual, |
| 47 | BitField<1, 1, u32> handheld; | 47 | JoyLeft, |
| 48 | BitField<2, 1, u32> joycon_dual; | 48 | JoyRight, |
| 49 | BitField<3, 1, u32> joycon_left; | 49 | Pokeball, |
| 50 | BitField<4, 1, u32> joycon_right; | 50 | }; |
| 51 | 51 | ||
| 52 | BitField<6, 1, u32> pokeball; // TODO(ogniK): Confirm when possible | 52 | enum class NpadType : u8 { |
| 53 | }; | 53 | ProController = 3, |
| 54 | Handheld = 4, | ||
| 55 | JoyconDual = 5, | ||
| 56 | JoyconLeft = 6, | ||
| 57 | JoyconRight = 7, | ||
| 58 | Pokeball = 9, | ||
| 54 | }; | 59 | }; |
| 55 | static_assert(sizeof(NPadType) == 4, "NPadType is an invalid size"); | ||
| 56 | 60 | ||
| 57 | struct Vibration { | 61 | enum class DeviceIndex : u8 { |
| 58 | f32 amp_low; | 62 | Left = 0, |
| 59 | f32 freq_low; | 63 | Right = 1, |
| 60 | f32 amp_high; | 64 | None = 2, |
| 61 | f32 freq_high; | ||
| 62 | }; | 65 | }; |
| 63 | static_assert(sizeof(Vibration) == 0x10, "Vibration is an invalid size"); | ||
| 64 | 66 | ||
| 65 | enum class GyroscopeZeroDriftMode : u32 { | 67 | enum class GyroscopeZeroDriftMode : u32 { |
| 66 | Loose = 0, | 68 | Loose = 0, |
| @@ -73,7 +75,7 @@ public: | |||
| 73 | Horizontal = 1, | 75 | Horizontal = 1, |
| 74 | }; | 76 | }; |
| 75 | 77 | ||
| 76 | enum class NPadAssignments : u32_le { | 78 | enum class NpadAssignments : u32 { |
| 77 | Dual = 0, | 79 | Dual = 0, |
| 78 | Single = 1, | 80 | Single = 1, |
| 79 | }; | 81 | }; |
| @@ -84,15 +86,36 @@ public: | |||
| 84 | None = 2, | 86 | None = 2, |
| 85 | }; | 87 | }; |
| 86 | 88 | ||
| 87 | enum class NPadControllerType { | 89 | struct DeviceHandle { |
| 88 | None, | 90 | NpadType npad_type{}; |
| 89 | ProController, | 91 | u8 npad_id{}; |
| 90 | Handheld, | 92 | DeviceIndex device_index{}; |
| 91 | JoyDual, | 93 | INSERT_PADDING_BYTES(1); |
| 92 | JoyLeft, | 94 | }; |
| 93 | JoyRight, | 95 | static_assert(sizeof(DeviceHandle) == 4, "DeviceHandle is an invalid size"); |
| 94 | Pokeball, | 96 | |
| 97 | struct NpadStyleSet { | ||
| 98 | union { | ||
| 99 | u32_le raw{}; | ||
| 100 | |||
| 101 | BitField<0, 1, u32> pro_controller; | ||
| 102 | BitField<1, 1, u32> handheld; | ||
| 103 | BitField<2, 1, u32> joycon_dual; | ||
| 104 | BitField<3, 1, u32> joycon_left; | ||
| 105 | BitField<4, 1, u32> joycon_right; | ||
| 106 | |||
| 107 | BitField<6, 1, u32> pokeball; // TODO(ogniK): Confirm when possible | ||
| 108 | }; | ||
| 109 | }; | ||
| 110 | static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); | ||
| 111 | |||
| 112 | struct VibrationValue { | ||
| 113 | f32 amp_low{0.0f}; | ||
| 114 | f32 freq_low{160.0f}; | ||
| 115 | f32 amp_high{0.0f}; | ||
| 116 | f32 freq_high{320.0f}; | ||
| 95 | }; | 117 | }; |
| 118 | static_assert(sizeof(VibrationValue) == 0x10, "Vibration is an invalid size"); | ||
| 96 | 119 | ||
| 97 | struct LedPattern { | 120 | struct LedPattern { |
| 98 | explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) { | 121 | explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) { |
| @@ -110,12 +133,12 @@ public: | |||
| 110 | }; | 133 | }; |
| 111 | }; | 134 | }; |
| 112 | 135 | ||
| 113 | void SetSupportedStyleSet(NPadType style_set); | 136 | void SetSupportedStyleSet(NpadStyleSet style_set); |
| 114 | NPadType GetSupportedStyleSet() const; | 137 | NpadStyleSet GetSupportedStyleSet() const; |
| 115 | 138 | ||
| 116 | void SetSupportedNPadIdTypes(u8* data, std::size_t length); | 139 | void SetSupportedNpadIdTypes(u8* data, std::size_t length); |
| 117 | void GetSupportedNpadIdTypes(u32* data, std::size_t max_length); | 140 | void GetSupportedNpadIdTypes(u32* data, std::size_t max_length); |
| 118 | std::size_t GetSupportedNPadIdTypesSize() const; | 141 | std::size_t GetSupportedNpadIdTypesSize() const; |
| 119 | 142 | ||
| 120 | void SetHoldType(NpadHoldType joy_hold_type); | 143 | void SetHoldType(NpadHoldType joy_hold_type); |
| 121 | NpadHoldType GetHoldType() const; | 144 | NpadHoldType GetHoldType() const; |
| @@ -123,12 +146,26 @@ public: | |||
| 123 | void SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode); | 146 | void SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode); |
| 124 | NpadHandheldActivationMode GetNpadHandheldActivationMode() const; | 147 | NpadHandheldActivationMode GetNpadHandheldActivationMode() const; |
| 125 | 148 | ||
| 126 | void SetNpadMode(u32 npad_id, NPadAssignments assignment_mode); | 149 | void SetNpadMode(u32 npad_id, NpadAssignments assignment_mode); |
| 150 | |||
| 151 | bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, | ||
| 152 | const VibrationValue& vibration_value); | ||
| 153 | |||
| 154 | void VibrateController(const DeviceHandle& vibration_device_handle, | ||
| 155 | const VibrationValue& vibration_value); | ||
| 156 | |||
| 157 | void VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles, | ||
| 158 | const std::vector<VibrationValue>& vibration_values); | ||
| 159 | |||
| 160 | VibrationValue GetLastVibration(const DeviceHandle& vibration_device_handle) const; | ||
| 161 | |||
| 162 | void InitializeVibrationDevice(const DeviceHandle& vibration_device_handle); | ||
| 163 | |||
| 164 | void InitializeVibrationDeviceAtIndex(std::size_t npad_index, std::size_t device_index); | ||
| 127 | 165 | ||
| 128 | void VibrateController(const std::vector<u32>& controllers, | 166 | void SetPermitVibrationSession(bool permit_vibration_session); |
| 129 | const std::vector<Vibration>& vibrations); | ||
| 130 | 167 | ||
| 131 | Vibration GetLastVibration() const; | 168 | bool IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const; |
| 132 | 169 | ||
| 133 | std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const; | 170 | std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const; |
| 134 | void SignalStyleSetChangedEvent(u32 npad_id) const; | 171 | void SignalStyleSetChangedEvent(u32 npad_id) const; |
| @@ -138,8 +175,8 @@ public: | |||
| 138 | // Adds a new controller at an index with connection status. | 175 | // Adds a new controller at an index with connection status. |
| 139 | void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected); | 176 | void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected); |
| 140 | 177 | ||
| 141 | void DisconnectNPad(u32 npad_id); | 178 | void DisconnectNpad(u32 npad_id); |
| 142 | void DisconnectNPadAtIndex(std::size_t index); | 179 | void DisconnectNpadAtIndex(std::size_t index); |
| 143 | 180 | ||
| 144 | void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); | 181 | void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); |
| 145 | GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; | 182 | GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; |
| @@ -148,8 +185,6 @@ public: | |||
| 148 | LedPattern GetLedPattern(u32 npad_id); | 185 | LedPattern GetLedPattern(u32 npad_id); |
| 149 | bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const; | 186 | bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const; |
| 150 | void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id); | 187 | void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id); |
| 151 | void SetVibrationEnabled(bool can_vibrate); | ||
| 152 | bool IsVibrationEnabled() const; | ||
| 153 | void ClearAllConnectedControllers(); | 188 | void ClearAllConnectedControllers(); |
| 154 | void DisconnectAllConnectedControllers(); | 189 | void DisconnectAllConnectedControllers(); |
| 155 | void ConnectAllDisconnectedControllers(); | 190 | void ConnectAllDisconnectedControllers(); |
| @@ -324,8 +359,8 @@ private: | |||
| 324 | }; | 359 | }; |
| 325 | 360 | ||
| 326 | struct NPadEntry { | 361 | struct NPadEntry { |
| 327 | NPadType joy_styles; | 362 | NpadStyleSet joy_styles; |
| 328 | NPadAssignments pad_assignment; | 363 | NpadAssignments pad_assignment; |
| 329 | 364 | ||
| 330 | ColorReadError single_color_error; | 365 | ColorReadError single_color_error; |
| 331 | ControllerColor single_color; | 366 | ControllerColor single_color; |
| @@ -368,7 +403,7 @@ private: | |||
| 368 | 403 | ||
| 369 | u32 press_state{}; | 404 | u32 press_state{}; |
| 370 | 405 | ||
| 371 | NPadType style{}; | 406 | NpadStyleSet style{}; |
| 372 | std::array<NPadEntry, 10> shared_memory_entries{}; | 407 | std::array<NPadEntry, 10> shared_memory_entries{}; |
| 373 | using ButtonArray = std::array< | 408 | using ButtonArray = std::array< |
| 374 | std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>, | 409 | std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>, |
| @@ -376,22 +411,28 @@ private: | |||
| 376 | using StickArray = std::array< | 411 | using StickArray = std::array< |
| 377 | std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>, | 412 | std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>, |
| 378 | 10>; | 413 | 10>; |
| 414 | using VibrationArray = std::array<std::array<std::unique_ptr<Input::VibrationDevice>, | ||
| 415 | Settings::NativeVibration::NUM_VIBRATIONS_HID>, | ||
| 416 | 10>; | ||
| 379 | using MotionArray = std::array< | 417 | using MotionArray = std::array< |
| 380 | std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTION_HID>, | 418 | std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTIONS_HID>, |
| 381 | 10>; | 419 | 10>; |
| 382 | ButtonArray buttons; | 420 | ButtonArray buttons; |
| 383 | StickArray sticks; | 421 | StickArray sticks; |
| 422 | VibrationArray vibrations; | ||
| 384 | MotionArray motions; | 423 | MotionArray motions; |
| 385 | std::vector<u32> supported_npad_id_types{}; | 424 | std::vector<u32> supported_npad_id_types{}; |
| 386 | NpadHoldType hold_type{NpadHoldType::Vertical}; | 425 | NpadHoldType hold_type{NpadHoldType::Vertical}; |
| 387 | NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; | 426 | NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; |
| 388 | // Each controller should have their own styleset changed event | 427 | // Each controller should have their own styleset changed event |
| 389 | std::array<Kernel::EventPair, 10> styleset_changed_events; | 428 | std::array<Kernel::EventPair, 10> styleset_changed_events; |
| 390 | Vibration last_processed_vibration{}; | 429 | std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10> last_vibration_timepoints; |
| 430 | std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{}; | ||
| 431 | bool permit_vibration_session_enabled{false}; | ||
| 432 | std::array<std::array<bool, 2>, 10> vibration_devices_mounted{}; | ||
| 391 | std::array<ControllerHolder, 10> connected_controllers{}; | 433 | std::array<ControllerHolder, 10> connected_controllers{}; |
| 392 | std::array<bool, 10> unintended_home_button_input_protection{}; | 434 | std::array<bool, 10> unintended_home_button_input_protection{}; |
| 393 | GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; | 435 | GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; |
| 394 | bool can_controllers_vibrate{true}; | ||
| 395 | bool sixaxis_sensors_enabled{true}; | 436 | bool sixaxis_sensors_enabled{true}; |
| 396 | bool sixaxis_at_rest{true}; | 437 | bool sixaxis_at_rest{true}; |
| 397 | std::array<ControllerPad, 10> npad_pad_states{}; | 438 | std::array<ControllerPad, 10> npad_pad_states{}; |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 50f709b25..902516b29 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -139,20 +139,34 @@ void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanose | |||
| 139 | 139 | ||
| 140 | class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> { | 140 | class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> { |
| 141 | public: | 141 | public: |
| 142 | IActiveVibrationDeviceList() : ServiceFramework("IActiveVibrationDeviceList") { | 142 | explicit IActiveVibrationDeviceList(std::shared_ptr<IAppletResource> applet_resource_) |
| 143 | : ServiceFramework("IActiveVibrationDeviceList"), applet_resource(applet_resource_) { | ||
| 144 | // clang-format off | ||
| 143 | static const FunctionInfo functions[] = { | 145 | static const FunctionInfo functions[] = { |
| 144 | {0, &IActiveVibrationDeviceList::ActivateVibrationDevice, "ActivateVibrationDevice"}, | 146 | {0, &IActiveVibrationDeviceList::InitializeVibrationDevice, "InitializeVibrationDevice"}, |
| 145 | }; | 147 | }; |
| 148 | // clang-format on | ||
| 149 | |||
| 146 | RegisterHandlers(functions); | 150 | RegisterHandlers(functions); |
| 147 | } | 151 | } |
| 148 | 152 | ||
| 149 | private: | 153 | private: |
| 150 | void ActivateVibrationDevice(Kernel::HLERequestContext& ctx) { | 154 | void InitializeVibrationDevice(Kernel::HLERequestContext& ctx) { |
| 151 | LOG_WARNING(Service_HID, "(STUBBED) called"); | 155 | IPC::RequestParser rp{ctx}; |
| 156 | const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; | ||
| 157 | |||
| 158 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 159 | .InitializeVibrationDevice(vibration_device_handle); | ||
| 160 | |||
| 161 | LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}", | ||
| 162 | vibration_device_handle.npad_type, vibration_device_handle.npad_id, | ||
| 163 | vibration_device_handle.device_index); | ||
| 152 | 164 | ||
| 153 | IPC::ResponseBuilder rb{ctx, 2}; | 165 | IPC::ResponseBuilder rb{ctx, 2}; |
| 154 | rb.Push(RESULT_SUCCESS); | 166 | rb.Push(RESULT_SUCCESS); |
| 155 | } | 167 | } |
| 168 | |||
| 169 | std::shared_ptr<IAppletResource> applet_resource; | ||
| 156 | }; | 170 | }; |
| 157 | 171 | ||
| 158 | std::shared_ptr<IAppletResource> Hid::GetAppletResource() { | 172 | std::shared_ptr<IAppletResource> Hid::GetAppletResource() { |
| @@ -241,7 +255,7 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) { | |||
| 241 | {208, nullptr, "GetActualVibrationGcErmCommand"}, | 255 | {208, nullptr, "GetActualVibrationGcErmCommand"}, |
| 242 | {209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, | 256 | {209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, |
| 243 | {210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"}, | 257 | {210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"}, |
| 244 | {211, nullptr, "IsVibrationDeviceMounted"}, | 258 | {211, &Hid::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"}, |
| 245 | {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, | 259 | {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, |
| 246 | {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, | 260 | {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, |
| 247 | {302, &Hid::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"}, | 261 | {302, &Hid::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"}, |
| @@ -320,142 +334,152 @@ void Hid::CreateAppletResource(Kernel::HLERequestContext& ctx) { | |||
| 320 | rb.PushIpcInterface<IAppletResource>(applet_resource); | 334 | rb.PushIpcInterface<IAppletResource>(applet_resource); |
| 321 | } | 335 | } |
| 322 | 336 | ||
| 323 | void Hid::ActivateXpad(Kernel::HLERequestContext& ctx) { | 337 | void Hid::ActivateDebugPad(Kernel::HLERequestContext& ctx) { |
| 324 | IPC::RequestParser rp{ctx}; | 338 | IPC::RequestParser rp{ctx}; |
| 325 | const auto basic_xpad_id{rp.Pop<u32>()}; | ||
| 326 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 339 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 327 | 340 | ||
| 328 | LOG_DEBUG(Service_HID, "called, basic_xpad_id={}, applet_resource_user_id={}", basic_xpad_id, | 341 | applet_resource->ActivateController(HidController::DebugPad); |
| 329 | applet_resource_user_id); | 342 | |
| 343 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | ||
| 330 | 344 | ||
| 331 | applet_resource->ActivateController(HidController::XPad); | ||
| 332 | IPC::ResponseBuilder rb{ctx, 2}; | 345 | IPC::ResponseBuilder rb{ctx, 2}; |
| 333 | rb.Push(RESULT_SUCCESS); | 346 | rb.Push(RESULT_SUCCESS); |
| 334 | } | 347 | } |
| 335 | 348 | ||
| 336 | void Hid::GetXpadIDs(Kernel::HLERequestContext& ctx) { | 349 | void Hid::ActivateTouchScreen(Kernel::HLERequestContext& ctx) { |
| 337 | IPC::RequestParser rp{ctx}; | 350 | IPC::RequestParser rp{ctx}; |
| 338 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 351 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 339 | 352 | ||
| 340 | LOG_DEBUG(Service_HID, "(STUBBED) called, applet_resource_user_id={}", applet_resource_user_id); | 353 | applet_resource->ActivateController(HidController::Touchscreen); |
| 341 | |||
| 342 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 343 | rb.Push(RESULT_SUCCESS); | ||
| 344 | rb.Push(0); | ||
| 345 | } | ||
| 346 | 354 | ||
| 347 | void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) { | 355 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 348 | IPC::RequestParser rp{ctx}; | ||
| 349 | const auto handle{rp.Pop<u32>()}; | ||
| 350 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 351 | applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(true); | ||
| 352 | LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, | ||
| 353 | applet_resource_user_id); | ||
| 354 | 356 | ||
| 355 | IPC::ResponseBuilder rb{ctx, 2}; | 357 | IPC::ResponseBuilder rb{ctx, 2}; |
| 356 | rb.Push(RESULT_SUCCESS); | 358 | rb.Push(RESULT_SUCCESS); |
| 357 | } | 359 | } |
| 358 | 360 | ||
| 359 | void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) { | 361 | void Hid::ActivateMouse(Kernel::HLERequestContext& ctx) { |
| 360 | IPC::RequestParser rp{ctx}; | 362 | IPC::RequestParser rp{ctx}; |
| 361 | const auto handle{rp.Pop<u32>()}; | ||
| 362 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 363 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 363 | applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(false); | ||
| 364 | 364 | ||
| 365 | LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, | 365 | applet_resource->ActivateController(HidController::Mouse); |
| 366 | applet_resource_user_id); | 366 | |
| 367 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | ||
| 367 | 368 | ||
| 368 | IPC::ResponseBuilder rb{ctx, 2}; | 369 | IPC::ResponseBuilder rb{ctx, 2}; |
| 369 | rb.Push(RESULT_SUCCESS); | 370 | rb.Push(RESULT_SUCCESS); |
| 370 | } | 371 | } |
| 371 | 372 | ||
| 372 | void Hid::ActivateDebugPad(Kernel::HLERequestContext& ctx) { | 373 | void Hid::ActivateKeyboard(Kernel::HLERequestContext& ctx) { |
| 373 | IPC::RequestParser rp{ctx}; | 374 | IPC::RequestParser rp{ctx}; |
| 374 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 375 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 375 | 376 | ||
| 377 | applet_resource->ActivateController(HidController::Keyboard); | ||
| 378 | |||
| 376 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 379 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 377 | 380 | ||
| 378 | applet_resource->ActivateController(HidController::DebugPad); | ||
| 379 | IPC::ResponseBuilder rb{ctx, 2}; | 381 | IPC::ResponseBuilder rb{ctx, 2}; |
| 380 | rb.Push(RESULT_SUCCESS); | 382 | rb.Push(RESULT_SUCCESS); |
| 381 | } | 383 | } |
| 382 | 384 | ||
| 383 | void Hid::ActivateTouchScreen(Kernel::HLERequestContext& ctx) { | 385 | void Hid::SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx) { |
| 384 | IPC::RequestParser rp{ctx}; | 386 | IPC::RequestParser rp{ctx}; |
| 385 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 387 | const auto flags{rp.Pop<u32>()}; |
| 386 | 388 | ||
| 387 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 389 | LOG_WARNING(Service_HID, "(STUBBED) called. flags={}", flags); |
| 388 | 390 | ||
| 389 | applet_resource->ActivateController(HidController::Touchscreen); | ||
| 390 | IPC::ResponseBuilder rb{ctx, 2}; | 391 | IPC::ResponseBuilder rb{ctx, 2}; |
| 391 | rb.Push(RESULT_SUCCESS); | 392 | rb.Push(RESULT_SUCCESS); |
| 392 | } | 393 | } |
| 393 | 394 | ||
| 394 | void Hid::ActivateMouse(Kernel::HLERequestContext& ctx) { | 395 | void Hid::ActivateXpad(Kernel::HLERequestContext& ctx) { |
| 395 | IPC::RequestParser rp{ctx}; | 396 | IPC::RequestParser rp{ctx}; |
| 396 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 397 | struct Parameters { |
| 398 | u32 basic_xpad_id{}; | ||
| 399 | INSERT_PADDING_WORDS(1); | ||
| 400 | u64 applet_resource_user_id{}; | ||
| 401 | }; | ||
| 397 | 402 | ||
| 398 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 403 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 404 | |||
| 405 | applet_resource->ActivateController(HidController::XPad); | ||
| 406 | |||
| 407 | LOG_DEBUG(Service_HID, "called, basic_xpad_id={}, applet_resource_user_id={}", | ||
| 408 | parameters.basic_xpad_id, parameters.applet_resource_user_id); | ||
| 399 | 409 | ||
| 400 | applet_resource->ActivateController(HidController::Mouse); | ||
| 401 | IPC::ResponseBuilder rb{ctx, 2}; | 410 | IPC::ResponseBuilder rb{ctx, 2}; |
| 402 | rb.Push(RESULT_SUCCESS); | 411 | rb.Push(RESULT_SUCCESS); |
| 403 | } | 412 | } |
| 404 | 413 | ||
| 405 | void Hid::ActivateKeyboard(Kernel::HLERequestContext& ctx) { | 414 | void Hid::GetXpadIDs(Kernel::HLERequestContext& ctx) { |
| 406 | IPC::RequestParser rp{ctx}; | 415 | IPC::RequestParser rp{ctx}; |
| 407 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 416 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 408 | 417 | ||
| 409 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 418 | LOG_DEBUG(Service_HID, "(STUBBED) called, applet_resource_user_id={}", applet_resource_user_id); |
| 410 | 419 | ||
| 411 | applet_resource->ActivateController(HidController::Keyboard); | 420 | IPC::ResponseBuilder rb{ctx, 3}; |
| 412 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 413 | rb.Push(RESULT_SUCCESS); | 421 | rb.Push(RESULT_SUCCESS); |
| 422 | rb.Push(0); | ||
| 414 | } | 423 | } |
| 415 | 424 | ||
| 416 | void Hid::SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx) { | 425 | void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| 417 | IPC::RequestParser rp{ctx}; | 426 | IPC::RequestParser rp{ctx}; |
| 418 | const auto flags{rp.Pop<u32>()}; | 427 | struct Parameters { |
| 419 | LOG_WARNING(Service_HID, "(STUBBED) called. flags={}", flags); | 428 | Controller_NPad::DeviceHandle sixaxis_handle{}; |
| 429 | INSERT_PADDING_WORDS(1); | ||
| 430 | u64 applet_resource_user_id{}; | ||
| 431 | }; | ||
| 420 | 432 | ||
| 421 | IPC::ResponseBuilder rb{ctx, 2}; | 433 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 422 | rb.Push(RESULT_SUCCESS); | ||
| 423 | } | ||
| 424 | 434 | ||
| 425 | void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) { | 435 | applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(true); |
| 426 | IPC::RequestParser rp{ctx}; | ||
| 427 | const auto unknown{rp.Pop<u32>()}; | ||
| 428 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 429 | 436 | ||
| 430 | LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", unknown, | 437 | LOG_DEBUG(Service_HID, |
| 431 | applet_resource_user_id); | 438 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", |
| 439 | parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||
| 440 | parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||
| 432 | 441 | ||
| 433 | applet_resource->ActivateController(HidController::Gesture); | ||
| 434 | IPC::ResponseBuilder rb{ctx, 2}; | 442 | IPC::ResponseBuilder rb{ctx, 2}; |
| 435 | rb.Push(RESULT_SUCCESS); | 443 | rb.Push(RESULT_SUCCESS); |
| 436 | } | 444 | } |
| 437 | 445 | ||
| 438 | void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) { | 446 | void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| 439 | // Should have no effect with how our npad sets up the data | ||
| 440 | IPC::RequestParser rp{ctx}; | 447 | IPC::RequestParser rp{ctx}; |
| 441 | const auto unknown{rp.Pop<u32>()}; | 448 | struct Parameters { |
| 442 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 449 | Controller_NPad::DeviceHandle sixaxis_handle{}; |
| 450 | INSERT_PADDING_WORDS(1); | ||
| 451 | u64 applet_resource_user_id{}; | ||
| 452 | }; | ||
| 443 | 453 | ||
| 444 | LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", unknown, | 454 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 445 | applet_resource_user_id); | 455 | |
| 456 | applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(false); | ||
| 457 | |||
| 458 | LOG_DEBUG(Service_HID, | ||
| 459 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | ||
| 460 | parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||
| 461 | parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||
| 446 | 462 | ||
| 447 | applet_resource->ActivateController(HidController::NPad); | ||
| 448 | IPC::ResponseBuilder rb{ctx, 2}; | 463 | IPC::ResponseBuilder rb{ctx, 2}; |
| 449 | rb.Push(RESULT_SUCCESS); | 464 | rb.Push(RESULT_SUCCESS); |
| 450 | } | 465 | } |
| 451 | 466 | ||
| 452 | void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) { | 467 | void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| 453 | IPC::RequestParser rp{ctx}; | 468 | IPC::RequestParser rp{ctx}; |
| 454 | const auto handle{rp.Pop<u32>()}; | 469 | struct Parameters { |
| 455 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 470 | Controller_NPad::DeviceHandle sixaxis_handle{}; |
| 471 | INSERT_PADDING_WORDS(1); | ||
| 472 | u64 applet_resource_user_id{}; | ||
| 473 | }; | ||
| 456 | 474 | ||
| 457 | LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle, | 475 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 458 | applet_resource_user_id); | 476 | |
| 477 | applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(true); | ||
| 478 | |||
| 479 | LOG_DEBUG(Service_HID, | ||
| 480 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | ||
| 481 | parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||
| 482 | parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||
| 459 | 483 | ||
| 460 | IPC::ResponseBuilder rb{ctx, 2}; | 484 | IPC::ResponseBuilder rb{ctx, 2}; |
| 461 | rb.Push(RESULT_SUCCESS); | 485 | rb.Push(RESULT_SUCCESS); |
| @@ -463,11 +487,20 @@ void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) { | |||
| 463 | 487 | ||
| 464 | void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) { | 488 | void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| 465 | IPC::RequestParser rp{ctx}; | 489 | IPC::RequestParser rp{ctx}; |
| 466 | const auto handle{rp.Pop<u32>()}; | 490 | struct Parameters { |
| 467 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 491 | Controller_NPad::DeviceHandle sixaxis_handle{}; |
| 492 | INSERT_PADDING_WORDS(1); | ||
| 493 | u64 applet_resource_user_id{}; | ||
| 494 | }; | ||
| 468 | 495 | ||
| 469 | LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle, | 496 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 470 | applet_resource_user_id); | 497 | |
| 498 | applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(false); | ||
| 499 | |||
| 500 | LOG_DEBUG(Service_HID, | ||
| 501 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | ||
| 502 | parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||
| 503 | parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||
| 471 | 504 | ||
| 472 | IPC::ResponseBuilder rb{ctx, 2}; | 505 | IPC::ResponseBuilder rb{ctx, 2}; |
| 473 | rb.Push(RESULT_SUCCESS); | 506 | rb.Push(RESULT_SUCCESS); |
| @@ -475,12 +508,21 @@ void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) { | |||
| 475 | 508 | ||
| 476 | void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) { | 509 | void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) { |
| 477 | IPC::RequestParser rp{ctx}; | 510 | IPC::RequestParser rp{ctx}; |
| 478 | [[maybe_unused]] const auto enable{rp.Pop<bool>()}; | 511 | struct Parameters { |
| 479 | const auto handle{rp.Pop<u32>()}; | 512 | bool enable_sixaxis_sensor_fusion{}; |
| 480 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 513 | INSERT_PADDING_BYTES(3); |
| 514 | Controller_NPad::DeviceHandle sixaxis_handle{}; | ||
| 515 | u64 applet_resource_user_id{}; | ||
| 516 | }; | ||
| 481 | 517 | ||
| 482 | LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle, | 518 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 483 | applet_resource_user_id); | 519 | |
| 520 | LOG_WARNING(Service_HID, | ||
| 521 | "(STUBBED) called, enable_sixaxis_sensor_fusion={}, npad_type={}, npad_id={}, " | ||
| 522 | "device_index={}, applet_resource_user_id={}", | ||
| 523 | parameters.enable_sixaxis_sensor_fusion, parameters.sixaxis_handle.npad_type, | ||
| 524 | parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index, | ||
| 525 | parameters.applet_resource_user_id); | ||
| 484 | 526 | ||
| 485 | IPC::ResponseBuilder rb{ctx, 2}; | 527 | IPC::ResponseBuilder rb{ctx, 2}; |
| 486 | rb.Push(RESULT_SUCCESS); | 528 | rb.Push(RESULT_SUCCESS); |
| @@ -488,14 +530,17 @@ void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) { | |||
| 488 | 530 | ||
| 489 | void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { | 531 | void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { |
| 490 | IPC::RequestParser rp{ctx}; | 532 | IPC::RequestParser rp{ctx}; |
| 491 | const auto handle{rp.Pop<u32>()}; | 533 | const auto sixaxis_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; |
| 492 | const auto drift_mode{rp.Pop<u32>()}; | 534 | const auto drift_mode{rp.PopEnum<Controller_NPad::GyroscopeZeroDriftMode>()}; |
| 493 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 535 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 494 | 536 | ||
| 495 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | 537 | applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 496 | .SetGyroscopeZeroDriftMode(Controller_NPad::GyroscopeZeroDriftMode{drift_mode}); | 538 | .SetGyroscopeZeroDriftMode(drift_mode); |
| 497 | 539 | ||
| 498 | LOG_DEBUG(Service_HID, "called, handle={}, drift_mode={}, applet_resource_user_id={}", handle, | 540 | LOG_DEBUG(Service_HID, |
| 541 | "called, npad_type={}, npad_id={}, device_index={}, drift_mode={}, " | ||
| 542 | "applet_resource_user_id={}", | ||
| 543 | sixaxis_handle.npad_type, sixaxis_handle.npad_id, sixaxis_handle.device_index, | ||
| 499 | drift_mode, applet_resource_user_id); | 544 | drift_mode, applet_resource_user_id); |
| 500 | 545 | ||
| 501 | IPC::ResponseBuilder rb{ctx, 2}; | 546 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -504,29 +549,42 @@ void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { | |||
| 504 | 549 | ||
| 505 | void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { | 550 | void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { |
| 506 | IPC::RequestParser rp{ctx}; | 551 | IPC::RequestParser rp{ctx}; |
| 507 | const auto handle{rp.Pop<u32>()}; | 552 | struct Parameters { |
| 508 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 553 | Controller_NPad::DeviceHandle sixaxis_handle{}; |
| 554 | INSERT_PADDING_WORDS(1); | ||
| 555 | u64 applet_resource_user_id{}; | ||
| 556 | }; | ||
| 557 | |||
| 558 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 509 | 559 | ||
| 510 | LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, | 560 | LOG_DEBUG(Service_HID, |
| 511 | applet_resource_user_id); | 561 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", |
| 562 | parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||
| 563 | parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||
| 512 | 564 | ||
| 513 | IPC::ResponseBuilder rb{ctx, 3}; | 565 | IPC::ResponseBuilder rb{ctx, 3}; |
| 514 | rb.Push(RESULT_SUCCESS); | 566 | rb.Push(RESULT_SUCCESS); |
| 515 | rb.Push<u32>( | 567 | rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 516 | static_cast<u32>(applet_resource->GetController<Controller_NPad>(HidController::NPad) | 568 | .GetGyroscopeZeroDriftMode()); |
| 517 | .GetGyroscopeZeroDriftMode())); | ||
| 518 | } | 569 | } |
| 519 | 570 | ||
| 520 | void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { | 571 | void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { |
| 521 | IPC::RequestParser rp{ctx}; | 572 | IPC::RequestParser rp{ctx}; |
| 522 | const auto handle{rp.Pop<u32>()}; | 573 | struct Parameters { |
| 523 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 574 | Controller_NPad::DeviceHandle sixaxis_handle{}; |
| 575 | INSERT_PADDING_WORDS(1); | ||
| 576 | u64 applet_resource_user_id{}; | ||
| 577 | }; | ||
| 578 | |||
| 579 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 524 | 580 | ||
| 525 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | 581 | applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 526 | .SetGyroscopeZeroDriftMode(Controller_NPad::GyroscopeZeroDriftMode::Standard); | 582 | .SetGyroscopeZeroDriftMode(Controller_NPad::GyroscopeZeroDriftMode::Standard); |
| 527 | 583 | ||
| 528 | LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, | 584 | LOG_DEBUG(Service_HID, |
| 529 | applet_resource_user_id); | 585 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", |
| 586 | parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||
| 587 | parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||
| 530 | 588 | ||
| 531 | IPC::ResponseBuilder rb{ctx, 2}; | 589 | IPC::ResponseBuilder rb{ctx, 2}; |
| 532 | rb.Push(RESULT_SUCCESS); | 590 | rb.Push(RESULT_SUCCESS); |
| @@ -534,11 +592,18 @@ void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { | |||
| 534 | 592 | ||
| 535 | void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) { | 593 | void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) { |
| 536 | IPC::RequestParser rp{ctx}; | 594 | IPC::RequestParser rp{ctx}; |
| 537 | const auto handle{rp.Pop<u32>()}; | 595 | struct Parameters { |
| 538 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 596 | Controller_NPad::DeviceHandle sixaxis_handle{}; |
| 597 | INSERT_PADDING_WORDS(1); | ||
| 598 | u64 applet_resource_user_id{}; | ||
| 599 | }; | ||
| 600 | |||
| 601 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 539 | 602 | ||
| 540 | LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, | 603 | LOG_DEBUG(Service_HID, |
| 541 | applet_resource_user_id); | 604 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", |
| 605 | parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||
| 606 | parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||
| 542 | 607 | ||
| 543 | IPC::ResponseBuilder rb{ctx, 3}; | 608 | IPC::ResponseBuilder rb{ctx, 3}; |
| 544 | rb.Push(RESULT_SUCCESS); | 609 | rb.Push(RESULT_SUCCESS); |
| @@ -546,15 +611,34 @@ void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) { | |||
| 546 | .IsSixAxisSensorAtRest()); | 611 | .IsSixAxisSensorAtRest()); |
| 547 | } | 612 | } |
| 548 | 613 | ||
| 614 | void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) { | ||
| 615 | IPC::RequestParser rp{ctx}; | ||
| 616 | struct Parameters { | ||
| 617 | u32 unknown{}; | ||
| 618 | INSERT_PADDING_WORDS(1); | ||
| 619 | u64 applet_resource_user_id{}; | ||
| 620 | }; | ||
| 621 | |||
| 622 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 623 | |||
| 624 | applet_resource->ActivateController(HidController::Gesture); | ||
| 625 | |||
| 626 | LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", parameters.unknown, | ||
| 627 | parameters.applet_resource_user_id); | ||
| 628 | |||
| 629 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 630 | rb.Push(RESULT_SUCCESS); | ||
| 631 | } | ||
| 632 | |||
| 549 | void Hid::SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { | 633 | void Hid::SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { |
| 550 | IPC::RequestParser rp{ctx}; | 634 | IPC::RequestParser rp{ctx}; |
| 551 | const auto supported_styleset{rp.Pop<u32>()}; | 635 | const auto supported_styleset{rp.Pop<u32>()}; |
| 552 | 636 | ||
| 553 | LOG_DEBUG(Service_HID, "called, supported_styleset={}", supported_styleset); | ||
| 554 | |||
| 555 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | 637 | applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 556 | .SetSupportedStyleSet({supported_styleset}); | 638 | .SetSupportedStyleSet({supported_styleset}); |
| 557 | 639 | ||
| 640 | LOG_DEBUG(Service_HID, "called, supported_styleset={}", supported_styleset); | ||
| 641 | |||
| 558 | IPC::ResponseBuilder rb{ctx, 2}; | 642 | IPC::ResponseBuilder rb{ctx, 2}; |
| 559 | rb.Push(RESULT_SUCCESS); | 643 | rb.Push(RESULT_SUCCESS); |
| 560 | } | 644 | } |
| @@ -565,21 +649,22 @@ void Hid::GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { | |||
| 565 | 649 | ||
| 566 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 650 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 567 | 651 | ||
| 568 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | ||
| 569 | |||
| 570 | IPC::ResponseBuilder rb{ctx, 3}; | 652 | IPC::ResponseBuilder rb{ctx, 3}; |
| 571 | rb.Push(RESULT_SUCCESS); | 653 | rb.Push(RESULT_SUCCESS); |
| 572 | rb.Push<u32>(controller.GetSupportedStyleSet().raw); | 654 | rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 655 | .GetSupportedStyleSet() | ||
| 656 | .raw); | ||
| 573 | } | 657 | } |
| 574 | 658 | ||
| 575 | void Hid::SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) { | 659 | void Hid::SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) { |
| 576 | IPC::RequestParser rp{ctx}; | 660 | IPC::RequestParser rp{ctx}; |
| 577 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 661 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 578 | 662 | ||
| 663 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 664 | .SetSupportedNpadIdTypes(ctx.ReadBuffer().data(), ctx.GetReadBufferSize()); | ||
| 665 | |||
| 579 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 666 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 580 | 667 | ||
| 581 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 582 | .SetSupportedNPadIdTypes(ctx.ReadBuffer().data(), ctx.GetReadBufferSize()); | ||
| 583 | IPC::ResponseBuilder rb{ctx, 2}; | 668 | IPC::ResponseBuilder rb{ctx, 2}; |
| 584 | rb.Push(RESULT_SUCCESS); | 669 | rb.Push(RESULT_SUCCESS); |
| 585 | } | 670 | } |
| @@ -588,48 +673,62 @@ void Hid::ActivateNpad(Kernel::HLERequestContext& ctx) { | |||
| 588 | IPC::RequestParser rp{ctx}; | 673 | IPC::RequestParser rp{ctx}; |
| 589 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 674 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 590 | 675 | ||
| 676 | applet_resource->ActivateController(HidController::NPad); | ||
| 677 | |||
| 591 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 678 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 592 | 679 | ||
| 593 | IPC::ResponseBuilder rb{ctx, 2}; | 680 | IPC::ResponseBuilder rb{ctx, 2}; |
| 594 | rb.Push(RESULT_SUCCESS); | 681 | rb.Push(RESULT_SUCCESS); |
| 595 | applet_resource->ActivateController(HidController::NPad); | ||
| 596 | } | 682 | } |
| 597 | 683 | ||
| 598 | void Hid::DeactivateNpad(Kernel::HLERequestContext& ctx) { | 684 | void Hid::DeactivateNpad(Kernel::HLERequestContext& ctx) { |
| 599 | IPC::RequestParser rp{ctx}; | 685 | IPC::RequestParser rp{ctx}; |
| 600 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 686 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 601 | 687 | ||
| 688 | applet_resource->DeactivateController(HidController::NPad); | ||
| 689 | |||
| 602 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 690 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 603 | 691 | ||
| 604 | IPC::ResponseBuilder rb{ctx, 2}; | 692 | IPC::ResponseBuilder rb{ctx, 2}; |
| 605 | rb.Push(RESULT_SUCCESS); | 693 | rb.Push(RESULT_SUCCESS); |
| 606 | applet_resource->DeactivateController(HidController::NPad); | ||
| 607 | } | 694 | } |
| 608 | 695 | ||
| 609 | void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) { | 696 | void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) { |
| 610 | IPC::RequestParser rp{ctx}; | 697 | IPC::RequestParser rp{ctx}; |
| 611 | const auto npad_id{rp.Pop<u32>()}; | 698 | struct Parameters { |
| 612 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 699 | u32 npad_id{}; |
| 613 | const auto unknown{rp.Pop<u64>()}; | 700 | INSERT_PADDING_WORDS(1); |
| 701 | u64 applet_resource_user_id{}; | ||
| 702 | u64 unknown{}; | ||
| 703 | }; | ||
| 614 | 704 | ||
| 615 | LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}, unknown={}", npad_id, | 705 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 616 | applet_resource_user_id, unknown); | 706 | |
| 707 | LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}, unknown={}", | ||
| 708 | parameters.npad_id, parameters.applet_resource_user_id, parameters.unknown); | ||
| 617 | 709 | ||
| 618 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 710 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 619 | rb.Push(RESULT_SUCCESS); | 711 | rb.Push(RESULT_SUCCESS); |
| 620 | rb.PushCopyObjects(applet_resource->GetController<Controller_NPad>(HidController::NPad) | 712 | rb.PushCopyObjects(applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 621 | .GetStyleSetChangedEvent(npad_id)); | 713 | .GetStyleSetChangedEvent(parameters.npad_id)); |
| 622 | } | 714 | } |
| 623 | 715 | ||
| 624 | void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) { | 716 | void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) { |
| 625 | IPC::RequestParser rp{ctx}; | 717 | IPC::RequestParser rp{ctx}; |
| 626 | const auto npad_id{rp.Pop<u32>()}; | 718 | struct Parameters { |
| 627 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 719 | u32 npad_id{}; |
| 720 | INSERT_PADDING_WORDS(1); | ||
| 721 | u64 applet_resource_user_id{}; | ||
| 722 | }; | ||
| 628 | 723 | ||
| 629 | LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, | 724 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 630 | applet_resource_user_id); | 725 | |
| 726 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 727 | .DisconnectNpad(parameters.npad_id); | ||
| 728 | |||
| 729 | LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id, | ||
| 730 | parameters.applet_resource_user_id); | ||
| 631 | 731 | ||
| 632 | applet_resource->GetController<Controller_NPad>(HidController::NPad).DisconnectNPad(npad_id); | ||
| 633 | IPC::ResponseBuilder rb{ctx, 2}; | 732 | IPC::ResponseBuilder rb{ctx, 2}; |
| 634 | rb.Push(RESULT_SUCCESS); | 733 | rb.Push(RESULT_SUCCESS); |
| 635 | } | 734 | } |
| @@ -642,22 +741,41 @@ void Hid::GetPlayerLedPattern(Kernel::HLERequestContext& ctx) { | |||
| 642 | 741 | ||
| 643 | IPC::ResponseBuilder rb{ctx, 4}; | 742 | IPC::ResponseBuilder rb{ctx, 4}; |
| 644 | rb.Push(RESULT_SUCCESS); | 743 | rb.Push(RESULT_SUCCESS); |
| 645 | rb.PushRaw<u64>(applet_resource->GetController<Controller_NPad>(HidController::NPad) | 744 | rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 646 | .GetLedPattern(npad_id) | 745 | .GetLedPattern(npad_id) |
| 647 | .raw); | 746 | .raw); |
| 747 | } | ||
| 748 | |||
| 749 | void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) { | ||
| 750 | // Should have no effect with how our npad sets up the data | ||
| 751 | IPC::RequestParser rp{ctx}; | ||
| 752 | struct Parameters { | ||
| 753 | u32 unknown{}; | ||
| 754 | INSERT_PADDING_WORDS(1); | ||
| 755 | u64 applet_resource_user_id{}; | ||
| 756 | }; | ||
| 757 | |||
| 758 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 759 | |||
| 760 | applet_resource->ActivateController(HidController::NPad); | ||
| 761 | |||
| 762 | LOG_DEBUG(Service_HID, "called, unknown={}, applet_resource_user_id={}", parameters.unknown, | ||
| 763 | parameters.applet_resource_user_id); | ||
| 764 | |||
| 765 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 766 | rb.Push(RESULT_SUCCESS); | ||
| 648 | } | 767 | } |
| 649 | 768 | ||
| 650 | void Hid::SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { | 769 | void Hid::SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { |
| 651 | IPC::RequestParser rp{ctx}; | 770 | IPC::RequestParser rp{ctx}; |
| 652 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 771 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 653 | const auto hold_type{rp.Pop<u64>()}; | 772 | const auto hold_type{rp.PopEnum<Controller_NPad::NpadHoldType>()}; |
| 773 | |||
| 774 | applet_resource->GetController<Controller_NPad>(HidController::NPad).SetHoldType(hold_type); | ||
| 654 | 775 | ||
| 655 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, hold_type={}", | 776 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, hold_type={}", |
| 656 | applet_resource_user_id, hold_type); | 777 | applet_resource_user_id, hold_type); |
| 657 | 778 | ||
| 658 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | ||
| 659 | controller.SetHoldType(Controller_NPad::NpadHoldType{hold_type}); | ||
| 660 | |||
| 661 | IPC::ResponseBuilder rb{ctx, 2}; | 779 | IPC::ResponseBuilder rb{ctx, 2}; |
| 662 | rb.Push(RESULT_SUCCESS); | 780 | rb.Push(RESULT_SUCCESS); |
| 663 | } | 781 | } |
| @@ -668,22 +786,26 @@ void Hid::GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { | |||
| 668 | 786 | ||
| 669 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 787 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 670 | 788 | ||
| 671 | const auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | ||
| 672 | IPC::ResponseBuilder rb{ctx, 4}; | 789 | IPC::ResponseBuilder rb{ctx, 4}; |
| 673 | rb.Push(RESULT_SUCCESS); | 790 | rb.Push(RESULT_SUCCESS); |
| 674 | rb.Push<u64>(static_cast<u64>(controller.GetHoldType())); | 791 | rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad).GetHoldType()); |
| 675 | } | 792 | } |
| 676 | 793 | ||
| 677 | void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) { | 794 | void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) { |
| 678 | IPC::RequestParser rp{ctx}; | 795 | IPC::RequestParser rp{ctx}; |
| 679 | const auto npad_id{rp.Pop<u32>()}; | 796 | struct Parameters { |
| 680 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 797 | u32 npad_id{}; |
| 798 | INSERT_PADDING_WORDS(1); | ||
| 799 | u64 applet_resource_user_id{}; | ||
| 800 | }; | ||
| 681 | 801 | ||
| 682 | LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", npad_id, | 802 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 683 | applet_resource_user_id); | 803 | |
| 804 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 805 | .SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Single); | ||
| 684 | 806 | ||
| 685 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | 807 | LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", |
| 686 | controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Single); | 808 | parameters.npad_id, parameters.applet_resource_user_id); |
| 687 | 809 | ||
| 688 | IPC::ResponseBuilder rb{ctx, 2}; | 810 | IPC::ResponseBuilder rb{ctx, 2}; |
| 689 | rb.Push(RESULT_SUCCESS); | 811 | rb.Push(RESULT_SUCCESS); |
| @@ -692,16 +814,22 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx | |||
| 692 | void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { | 814 | void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { |
| 693 | // TODO: Check the differences between this and SetNpadJoyAssignmentModeSingleByDefault | 815 | // TODO: Check the differences between this and SetNpadJoyAssignmentModeSingleByDefault |
| 694 | IPC::RequestParser rp{ctx}; | 816 | IPC::RequestParser rp{ctx}; |
| 695 | const auto npad_id{rp.Pop<u32>()}; | 817 | struct Parameters { |
| 696 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 818 | u32 npad_id{}; |
| 697 | const auto npad_joy_device_type{rp.Pop<u64>()}; | 819 | INSERT_PADDING_WORDS(1); |
| 820 | u64 applet_resource_user_id{}; | ||
| 821 | u64 npad_joy_device_type{}; | ||
| 822 | }; | ||
| 823 | |||
| 824 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 825 | |||
| 826 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 827 | .SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Single); | ||
| 698 | 828 | ||
| 699 | LOG_WARNING(Service_HID, | 829 | LOG_WARNING(Service_HID, |
| 700 | "(STUBBED) called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", | 830 | "(STUBBED) called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}", |
| 701 | npad_id, applet_resource_user_id, npad_joy_device_type); | 831 | parameters.npad_id, parameters.applet_resource_user_id, |
| 702 | 832 | parameters.npad_joy_device_type); | |
| 703 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | ||
| 704 | controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Single); | ||
| 705 | 833 | ||
| 706 | IPC::ResponseBuilder rb{ctx, 2}; | 834 | IPC::ResponseBuilder rb{ctx, 2}; |
| 707 | rb.Push(RESULT_SUCCESS); | 835 | rb.Push(RESULT_SUCCESS); |
| @@ -709,14 +837,19 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) { | |||
| 709 | 837 | ||
| 710 | void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { | 838 | void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { |
| 711 | IPC::RequestParser rp{ctx}; | 839 | IPC::RequestParser rp{ctx}; |
| 712 | const auto npad_id{rp.Pop<u32>()}; | 840 | struct Parameters { |
| 713 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 841 | u32 npad_id{}; |
| 842 | INSERT_PADDING_WORDS(1); | ||
| 843 | u64 applet_resource_user_id{}; | ||
| 844 | }; | ||
| 845 | |||
| 846 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 714 | 847 | ||
| 715 | LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id, | 848 | applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 716 | applet_resource_user_id); | 849 | .SetNpadMode(parameters.npad_id, Controller_NPad::NpadAssignments::Dual); |
| 717 | 850 | ||
| 718 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | 851 | LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", |
| 719 | controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Dual); | 852 | parameters.npad_id, parameters.applet_resource_user_id); |
| 720 | 853 | ||
| 721 | IPC::ResponseBuilder rb{ctx, 2}; | 854 | IPC::ResponseBuilder rb{ctx, 2}; |
| 722 | rb.Push(RESULT_SUCCESS); | 855 | rb.Push(RESULT_SUCCESS); |
| @@ -728,12 +861,12 @@ void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) { | |||
| 728 | const auto npad_id_2{rp.Pop<u32>()}; | 861 | const auto npad_id_2{rp.Pop<u32>()}; |
| 729 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 862 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 730 | 863 | ||
| 864 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 865 | .MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2); | ||
| 866 | |||
| 731 | LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", | 867 | LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", |
| 732 | npad_id_1, npad_id_2, applet_resource_user_id); | 868 | npad_id_1, npad_id_2, applet_resource_user_id); |
| 733 | 869 | ||
| 734 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | ||
| 735 | controller.MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2); | ||
| 736 | |||
| 737 | IPC::ResponseBuilder rb{ctx, 2}; | 870 | IPC::ResponseBuilder rb{ctx, 2}; |
| 738 | rb.Push(RESULT_SUCCESS); | 871 | rb.Push(RESULT_SUCCESS); |
| 739 | } | 872 | } |
| @@ -742,9 +875,9 @@ void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) { | |||
| 742 | IPC::RequestParser rp{ctx}; | 875 | IPC::RequestParser rp{ctx}; |
| 743 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 876 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 744 | 877 | ||
| 878 | applet_resource->GetController<Controller_NPad>(HidController::NPad).StartLRAssignmentMode(); | ||
| 879 | |||
| 745 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 880 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 746 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | ||
| 747 | controller.StartLRAssignmentMode(); | ||
| 748 | 881 | ||
| 749 | IPC::ResponseBuilder rb{ctx, 2}; | 882 | IPC::ResponseBuilder rb{ctx, 2}; |
| 750 | rb.Push(RESULT_SUCCESS); | 883 | rb.Push(RESULT_SUCCESS); |
| @@ -754,9 +887,9 @@ void Hid::StopLrAssignmentMode(Kernel::HLERequestContext& ctx) { | |||
| 754 | IPC::RequestParser rp{ctx}; | 887 | IPC::RequestParser rp{ctx}; |
| 755 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 888 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 756 | 889 | ||
| 890 | applet_resource->GetController<Controller_NPad>(HidController::NPad).StopLRAssignmentMode(); | ||
| 891 | |||
| 757 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 892 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 758 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | ||
| 759 | controller.StopLRAssignmentMode(); | ||
| 760 | 893 | ||
| 761 | IPC::ResponseBuilder rb{ctx, 2}; | 894 | IPC::ResponseBuilder rb{ctx, 2}; |
| 762 | rb.Push(RESULT_SUCCESS); | 895 | rb.Push(RESULT_SUCCESS); |
| @@ -765,13 +898,13 @@ void Hid::StopLrAssignmentMode(Kernel::HLERequestContext& ctx) { | |||
| 765 | void Hid::SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { | 898 | void Hid::SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { |
| 766 | IPC::RequestParser rp{ctx}; | 899 | IPC::RequestParser rp{ctx}; |
| 767 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 900 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 768 | const auto mode{rp.Pop<u64>()}; | 901 | const auto activation_mode{rp.PopEnum<Controller_NPad::NpadHandheldActivationMode>()}; |
| 769 | |||
| 770 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, mode={}", applet_resource_user_id, | ||
| 771 | mode); | ||
| 772 | 902 | ||
| 773 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | 903 | applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 774 | .SetNpadHandheldActivationMode(Controller_NPad::NpadHandheldActivationMode{mode}); | 904 | .SetNpadHandheldActivationMode(activation_mode); |
| 905 | |||
| 906 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, activation_mode={}", | ||
| 907 | applet_resource_user_id, activation_mode); | ||
| 775 | 908 | ||
| 776 | IPC::ResponseBuilder rb{ctx, 2}; | 909 | IPC::ResponseBuilder rb{ctx, 2}; |
| 777 | rb.Push(RESULT_SUCCESS); | 910 | rb.Push(RESULT_SUCCESS); |
| @@ -785,23 +918,24 @@ void Hid::GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { | |||
| 785 | 918 | ||
| 786 | IPC::ResponseBuilder rb{ctx, 4}; | 919 | IPC::ResponseBuilder rb{ctx, 4}; |
| 787 | rb.Push(RESULT_SUCCESS); | 920 | rb.Push(RESULT_SUCCESS); |
| 788 | rb.Push<u64>( | 921 | rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 789 | static_cast<u64>(applet_resource->GetController<Controller_NPad>(HidController::NPad) | 922 | .GetNpadHandheldActivationMode()); |
| 790 | .GetNpadHandheldActivationMode())); | ||
| 791 | } | 923 | } |
| 792 | 924 | ||
| 793 | void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) { | 925 | void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) { |
| 794 | IPC::RequestParser rp{ctx}; | 926 | IPC::RequestParser rp{ctx}; |
| 795 | const auto npad_1{rp.Pop<u32>()}; | 927 | const auto npad_id_1{rp.Pop<u32>()}; |
| 796 | const auto npad_2{rp.Pop<u32>()}; | 928 | const auto npad_id_2{rp.Pop<u32>()}; |
| 797 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 929 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 798 | 930 | ||
| 799 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, npad_1={}, npad_2={}", | 931 | const bool res = applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 800 | applet_resource_user_id, npad_1, npad_2); | 932 | .SwapNpadAssignment(npad_id_1, npad_id_2); |
| 933 | |||
| 934 | LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", | ||
| 935 | npad_id_1, npad_id_2, applet_resource_user_id); | ||
| 801 | 936 | ||
| 802 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | ||
| 803 | IPC::ResponseBuilder rb{ctx, 2}; | 937 | IPC::ResponseBuilder rb{ctx, 2}; |
| 804 | if (controller.SwapNpadAssignment(npad_1, npad_2)) { | 938 | if (res) { |
| 805 | rb.Push(RESULT_SUCCESS); | 939 | rb.Push(RESULT_SUCCESS); |
| 806 | } else { | 940 | } else { |
| 807 | LOG_ERROR(Service_HID, "Npads are not connected!"); | 941 | LOG_ERROR(Service_HID, "Npads are not connected!"); |
| @@ -811,144 +945,219 @@ void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) { | |||
| 811 | 945 | ||
| 812 | void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx) { | 946 | void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx) { |
| 813 | IPC::RequestParser rp{ctx}; | 947 | IPC::RequestParser rp{ctx}; |
| 814 | const auto npad_id{rp.Pop<u32>()}; | 948 | struct Parameters { |
| 815 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 949 | u32 npad_id{}; |
| 950 | INSERT_PADDING_WORDS(1); | ||
| 951 | u64 applet_resource_user_id{}; | ||
| 952 | }; | ||
| 816 | 953 | ||
| 817 | LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", npad_id, | 954 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 818 | applet_resource_user_id); | ||
| 819 | 955 | ||
| 820 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | 956 | LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", |
| 957 | parameters.npad_id, parameters.applet_resource_user_id); | ||
| 821 | 958 | ||
| 822 | IPC::ResponseBuilder rb{ctx, 3}; | 959 | IPC::ResponseBuilder rb{ctx, 3}; |
| 823 | rb.Push(RESULT_SUCCESS); | 960 | rb.Push(RESULT_SUCCESS); |
| 824 | rb.Push<bool>(controller.IsUnintendedHomeButtonInputProtectionEnabled(npad_id)); | 961 | rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 962 | .IsUnintendedHomeButtonInputProtectionEnabled(parameters.npad_id)); | ||
| 825 | } | 963 | } |
| 826 | 964 | ||
| 827 | void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx) { | 965 | void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx) { |
| 828 | IPC::RequestParser rp{ctx}; | 966 | IPC::RequestParser rp{ctx}; |
| 829 | const auto unintended_home_button_input_protection{rp.Pop<bool>()}; | 967 | struct Parameters { |
| 830 | const auto npad_id{rp.Pop<u32>()}; | 968 | bool unintended_home_button_input_protection{}; |
| 831 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 969 | INSERT_PADDING_BYTES(3); |
| 970 | u32 npad_id{}; | ||
| 971 | u64 applet_resource_user_id{}; | ||
| 972 | }; | ||
| 973 | |||
| 974 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 975 | |||
| 976 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 977 | .SetUnintendedHomeButtonInputProtectionEnabled( | ||
| 978 | parameters.unintended_home_button_input_protection, parameters.npad_id); | ||
| 832 | 979 | ||
| 833 | LOG_WARNING(Service_HID, | 980 | LOG_WARNING(Service_HID, |
| 834 | "(STUBBED) called, unintended_home_button_input_protection={}, npad_id={}," | 981 | "(STUBBED) called, unintended_home_button_input_protection={}, npad_id={}," |
| 835 | "applet_resource_user_id={}", | 982 | "applet_resource_user_id={}", |
| 836 | npad_id, unintended_home_button_input_protection, applet_resource_user_id); | 983 | parameters.unintended_home_button_input_protection, parameters.npad_id, |
| 837 | 984 | parameters.applet_resource_user_id); | |
| 838 | auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad); | ||
| 839 | controller.SetUnintendedHomeButtonInputProtectionEnabled( | ||
| 840 | unintended_home_button_input_protection, npad_id); | ||
| 841 | 985 | ||
| 842 | IPC::ResponseBuilder rb{ctx, 2}; | 986 | IPC::ResponseBuilder rb{ctx, 2}; |
| 843 | rb.Push(RESULT_SUCCESS); | 987 | rb.Push(RESULT_SUCCESS); |
| 844 | } | 988 | } |
| 845 | 989 | ||
| 846 | void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { | 990 | void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { |
| 847 | IPC::RequestParser rp{ctx}; | 991 | IPC::RequestParser rp{ctx}; |
| 848 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 992 | const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; |
| 993 | |||
| 994 | VibrationDeviceInfo vibration_device_info; | ||
| 995 | |||
| 996 | vibration_device_info.type = VibrationDeviceType::LinearResonantActuator; | ||
| 997 | |||
| 998 | switch (vibration_device_handle.device_index) { | ||
| 999 | case Controller_NPad::DeviceIndex::Left: | ||
| 1000 | vibration_device_info.position = VibrationDevicePosition::Left; | ||
| 1001 | break; | ||
| 1002 | case Controller_NPad::DeviceIndex::Right: | ||
| 1003 | vibration_device_info.position = VibrationDevicePosition::Right; | ||
| 1004 | break; | ||
| 1005 | case Controller_NPad::DeviceIndex::None: | ||
| 1006 | default: | ||
| 1007 | UNREACHABLE_MSG("DeviceIndex should never be None!"); | ||
| 1008 | vibration_device_info.position = VibrationDevicePosition::None; | ||
| 1009 | break; | ||
| 1010 | } | ||
| 849 | 1011 | ||
| 850 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 1012 | LOG_DEBUG(Service_HID, "called, vibration_device_type={}, vibration_device_position={}", |
| 1013 | vibration_device_info.type, vibration_device_info.position); | ||
| 1014 | |||
| 1015 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 1016 | rb.Push(RESULT_SUCCESS); | ||
| 1017 | rb.PushRaw(vibration_device_info); | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { | ||
| 1021 | IPC::RequestParser rp{ctx}; | ||
| 1022 | struct Parameters { | ||
| 1023 | Controller_NPad::DeviceHandle vibration_device_handle{}; | ||
| 1024 | Controller_NPad::VibrationValue vibration_value{}; | ||
| 1025 | INSERT_PADDING_WORDS(1); | ||
| 1026 | u64 applet_resource_user_id{}; | ||
| 1027 | }; | ||
| 1028 | |||
| 1029 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 1030 | |||
| 1031 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 1032 | .VibrateController(parameters.vibration_device_handle, parameters.vibration_value); | ||
| 1033 | |||
| 1034 | LOG_DEBUG(Service_HID, | ||
| 1035 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | ||
| 1036 | parameters.vibration_device_handle.npad_type, | ||
| 1037 | parameters.vibration_device_handle.npad_id, | ||
| 1038 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); | ||
| 851 | 1039 | ||
| 852 | applet_resource->GetController<Controller_NPad>(HidController::NPad).SetVibrationEnabled(true); | ||
| 853 | IPC::ResponseBuilder rb{ctx, 2}; | 1040 | IPC::ResponseBuilder rb{ctx, 2}; |
| 854 | rb.Push(RESULT_SUCCESS); | 1041 | rb.Push(RESULT_SUCCESS); |
| 855 | } | 1042 | } |
| 856 | 1043 | ||
| 857 | void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) { | 1044 | void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) { |
| 1045 | IPC::RequestParser rp{ctx}; | ||
| 1046 | struct Parameters { | ||
| 1047 | Controller_NPad::DeviceHandle vibration_device_handle{}; | ||
| 1048 | INSERT_PADDING_WORDS(1); | ||
| 1049 | u64 applet_resource_user_id{}; | ||
| 1050 | }; | ||
| 1051 | |||
| 1052 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 1053 | |||
| 1054 | LOG_DEBUG(Service_HID, | ||
| 1055 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | ||
| 1056 | parameters.vibration_device_handle.npad_type, | ||
| 1057 | parameters.vibration_device_handle.npad_id, | ||
| 1058 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); | ||
| 1059 | |||
| 1060 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 1061 | rb.Push(RESULT_SUCCESS); | ||
| 1062 | rb.PushRaw(applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 1063 | .GetLastVibration(parameters.vibration_device_handle)); | ||
| 1064 | } | ||
| 1065 | |||
| 1066 | void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { | ||
| 858 | LOG_DEBUG(Service_HID, "called"); | 1067 | LOG_DEBUG(Service_HID, "called"); |
| 859 | 1068 | ||
| 860 | applet_resource->GetController<Controller_NPad>(HidController::NPad).SetVibrationEnabled(false); | 1069 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 861 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 862 | rb.Push(RESULT_SUCCESS); | 1070 | rb.Push(RESULT_SUCCESS); |
| 1071 | rb.PushIpcInterface<IActiveVibrationDeviceList>(applet_resource); | ||
| 863 | } | 1072 | } |
| 864 | 1073 | ||
| 865 | void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { | 1074 | void Hid::PermitVibration(Kernel::HLERequestContext& ctx) { |
| 866 | IPC::RequestParser rp{ctx}; | 1075 | IPC::RequestParser rp{ctx}; |
| 867 | const auto controller{rp.Pop<u32>()}; | 1076 | const auto can_vibrate{rp.Pop<bool>()}; |
| 868 | const auto vibration_values{rp.PopRaw<Controller_NPad::Vibration>()}; | ||
| 869 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 870 | 1077 | ||
| 871 | LOG_DEBUG(Service_HID, "called, controller={}, applet_resource_user_id={}", controller, | 1078 | Settings::values.vibration_enabled.SetValue(can_vibrate); |
| 872 | applet_resource_user_id); | 1079 | |
| 1080 | LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); | ||
| 873 | 1081 | ||
| 874 | IPC::ResponseBuilder rb{ctx, 2}; | 1082 | IPC::ResponseBuilder rb{ctx, 2}; |
| 875 | rb.Push(RESULT_SUCCESS); | 1083 | rb.Push(RESULT_SUCCESS); |
| 1084 | } | ||
| 876 | 1085 | ||
| 877 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | 1086 | void Hid::IsVibrationPermitted(Kernel::HLERequestContext& ctx) { |
| 878 | .VibrateController({controller}, {vibration_values}); | 1087 | LOG_DEBUG(Service_HID, "called"); |
| 1088 | |||
| 1089 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 1090 | rb.Push(RESULT_SUCCESS); | ||
| 1091 | rb.Push(Settings::values.vibration_enabled.GetValue()); | ||
| 879 | } | 1092 | } |
| 880 | 1093 | ||
| 881 | void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { | 1094 | void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { |
| 882 | IPC::RequestParser rp{ctx}; | 1095 | IPC::RequestParser rp{ctx}; |
| 883 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 1096 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 884 | 1097 | ||
| 885 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 1098 | const auto handles = ctx.ReadBuffer(0); |
| 886 | |||
| 887 | const auto controllers = ctx.ReadBuffer(0); | ||
| 888 | const auto vibrations = ctx.ReadBuffer(1); | 1099 | const auto vibrations = ctx.ReadBuffer(1); |
| 889 | 1100 | ||
| 890 | std::vector<u32> controller_list(controllers.size() / sizeof(u32)); | 1101 | std::vector<Controller_NPad::DeviceHandle> vibration_device_handles( |
| 891 | std::vector<Controller_NPad::Vibration> vibration_list(vibrations.size() / | 1102 | handles.size() / sizeof(Controller_NPad::DeviceHandle)); |
| 892 | sizeof(Controller_NPad::Vibration)); | 1103 | std::vector<Controller_NPad::VibrationValue> vibration_values( |
| 1104 | vibrations.size() / sizeof(Controller_NPad::VibrationValue)); | ||
| 893 | 1105 | ||
| 894 | std::memcpy(controller_list.data(), controllers.data(), controllers.size()); | 1106 | std::memcpy(vibration_device_handles.data(), handles.data(), handles.size()); |
| 895 | std::memcpy(vibration_list.data(), vibrations.data(), vibrations.size()); | 1107 | std::memcpy(vibration_values.data(), vibrations.data(), vibrations.size()); |
| 896 | 1108 | ||
| 897 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | 1109 | applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 898 | .VibrateController(controller_list, vibration_list); | 1110 | .VibrateControllers(vibration_device_handles, vibration_values); |
| 1111 | |||
| 1112 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | ||
| 899 | 1113 | ||
| 900 | IPC::ResponseBuilder rb{ctx, 2}; | 1114 | IPC::ResponseBuilder rb{ctx, 2}; |
| 901 | rb.Push(RESULT_SUCCESS); | 1115 | rb.Push(RESULT_SUCCESS); |
| 902 | } | 1116 | } |
| 903 | 1117 | ||
| 904 | void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) { | 1118 | void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { |
| 905 | IPC::RequestParser rp{ctx}; | 1119 | IPC::RequestParser rp{ctx}; |
| 906 | const auto controller_id{rp.Pop<u32>()}; | ||
| 907 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 1120 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 908 | 1121 | ||
| 909 | LOG_DEBUG(Service_HID, "called, controller_id={}, applet_resource_user_id={}", controller_id, | 1122 | applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 910 | applet_resource_user_id); | 1123 | .SetPermitVibrationSession(true); |
| 911 | |||
| 912 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 913 | rb.Push(RESULT_SUCCESS); | ||
| 914 | rb.PushRaw<Controller_NPad::Vibration>( | ||
| 915 | applet_resource->GetController<Controller_NPad>(HidController::NPad).GetLastVibration()); | ||
| 916 | } | ||
| 917 | 1124 | ||
| 918 | void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { | 1125 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 919 | LOG_DEBUG(Service_HID, "called"); | ||
| 920 | 1126 | ||
| 921 | IPC::ResponseBuilder rb{ctx, 4}; | 1127 | IPC::ResponseBuilder rb{ctx, 2}; |
| 922 | rb.Push(RESULT_SUCCESS); | 1128 | rb.Push(RESULT_SUCCESS); |
| 923 | rb.Push<u32>(1); | ||
| 924 | rb.Push<u32>(0); | ||
| 925 | } | 1129 | } |
| 926 | 1130 | ||
| 927 | void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { | 1131 | void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) { |
| 1132 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 1133 | .SetPermitVibrationSession(false); | ||
| 1134 | |||
| 928 | LOG_DEBUG(Service_HID, "called"); | 1135 | LOG_DEBUG(Service_HID, "called"); |
| 929 | 1136 | ||
| 930 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 1137 | IPC::ResponseBuilder rb{ctx, 2}; |
| 931 | rb.Push(RESULT_SUCCESS); | 1138 | rb.Push(RESULT_SUCCESS); |
| 932 | rb.PushIpcInterface<IActiveVibrationDeviceList>(); | ||
| 933 | } | 1139 | } |
| 934 | 1140 | ||
| 935 | void Hid::PermitVibration(Kernel::HLERequestContext& ctx) { | 1141 | void Hid::IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx) { |
| 936 | IPC::RequestParser rp{ctx}; | 1142 | IPC::RequestParser rp{ctx}; |
| 937 | const auto can_vibrate{rp.Pop<bool>()}; | 1143 | struct Parameters { |
| 938 | Settings::values.vibration_enabled = can_vibrate; | 1144 | Controller_NPad::DeviceHandle vibration_device_handle{}; |
| 1145 | INSERT_PADDING_WORDS(1); | ||
| 1146 | u64 applet_resource_user_id{}; | ||
| 1147 | }; | ||
| 939 | 1148 | ||
| 940 | LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); | 1149 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 941 | 1150 | ||
| 942 | IPC::ResponseBuilder rb{ctx, 2}; | 1151 | LOG_DEBUG(Service_HID, |
| 943 | rb.Push(RESULT_SUCCESS); | 1152 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", |
| 944 | } | 1153 | parameters.vibration_device_handle.npad_type, |
| 945 | 1154 | parameters.vibration_device_handle.npad_id, | |
| 946 | void Hid::IsVibrationPermitted(Kernel::HLERequestContext& ctx) { | 1155 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); |
| 947 | LOG_DEBUG(Service_HID, "called"); | ||
| 948 | 1156 | ||
| 949 | IPC::ResponseBuilder rb{ctx, 3}; | 1157 | IPC::ResponseBuilder rb{ctx, 3}; |
| 950 | rb.Push(RESULT_SUCCESS); | 1158 | rb.Push(RESULT_SUCCESS); |
| 951 | rb.Push(Settings::values.vibration_enabled); | 1159 | rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 1160 | .IsVibrationDeviceMounted(parameters.vibration_device_handle)); | ||
| 952 | } | 1161 | } |
| 953 | 1162 | ||
| 954 | void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { | 1163 | void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| @@ -964,11 +1173,19 @@ void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { | |||
| 964 | 1173 | ||
| 965 | void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { | 1174 | void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| 966 | IPC::RequestParser rp{ctx}; | 1175 | IPC::RequestParser rp{ctx}; |
| 967 | const auto handle{rp.Pop<u32>()}; | 1176 | struct Parameters { |
| 968 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 1177 | Controller_NPad::DeviceHandle sixaxis_handle{}; |
| 1178 | INSERT_PADDING_WORDS(1); | ||
| 1179 | u64 applet_resource_user_id{}; | ||
| 1180 | }; | ||
| 969 | 1181 | ||
| 970 | LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle, | 1182 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 971 | applet_resource_user_id); | 1183 | |
| 1184 | LOG_WARNING( | ||
| 1185 | Service_HID, | ||
| 1186 | "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | ||
| 1187 | parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||
| 1188 | parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||
| 972 | 1189 | ||
| 973 | IPC::ResponseBuilder rb{ctx, 2}; | 1190 | IPC::ResponseBuilder rb{ctx, 2}; |
| 974 | rb.Push(RESULT_SUCCESS); | 1191 | rb.Push(RESULT_SUCCESS); |
| @@ -976,11 +1193,19 @@ void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { | |||
| 976 | 1193 | ||
| 977 | void Hid::StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { | 1194 | void Hid::StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| 978 | IPC::RequestParser rp{ctx}; | 1195 | IPC::RequestParser rp{ctx}; |
| 979 | const auto handle{rp.Pop<u32>()}; | 1196 | struct Parameters { |
| 980 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 1197 | Controller_NPad::DeviceHandle sixaxis_handle{}; |
| 1198 | INSERT_PADDING_WORDS(1); | ||
| 1199 | u64 applet_resource_user_id{}; | ||
| 1200 | }; | ||
| 981 | 1201 | ||
| 982 | LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle, | 1202 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 983 | applet_resource_user_id); | 1203 | |
| 1204 | LOG_WARNING( | ||
| 1205 | Service_HID, | ||
| 1206 | "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | ||
| 1207 | parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id, | ||
| 1208 | parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id); | ||
| 984 | 1209 | ||
| 985 | IPC::ResponseBuilder rb{ctx, 2}; | 1210 | IPC::ResponseBuilder rb{ctx, 2}; |
| 986 | rb.Push(RESULT_SUCCESS); | 1211 | rb.Push(RESULT_SUCCESS); |
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index fd0372b18..c8e4a4b55 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h | |||
| @@ -86,17 +86,15 @@ public: | |||
| 86 | 86 | ||
| 87 | private: | 87 | private: |
| 88 | void CreateAppletResource(Kernel::HLERequestContext& ctx); | 88 | void CreateAppletResource(Kernel::HLERequestContext& ctx); |
| 89 | void ActivateXpad(Kernel::HLERequestContext& ctx); | ||
| 90 | void GetXpadIDs(Kernel::HLERequestContext& ctx); | ||
| 91 | void ActivateSixAxisSensor(Kernel::HLERequestContext& ctx); | ||
| 92 | void DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx); | ||
| 93 | void ActivateDebugPad(Kernel::HLERequestContext& ctx); | 89 | void ActivateDebugPad(Kernel::HLERequestContext& ctx); |
| 94 | void ActivateTouchScreen(Kernel::HLERequestContext& ctx); | 90 | void ActivateTouchScreen(Kernel::HLERequestContext& ctx); |
| 95 | void ActivateMouse(Kernel::HLERequestContext& ctx); | 91 | void ActivateMouse(Kernel::HLERequestContext& ctx); |
| 96 | void ActivateKeyboard(Kernel::HLERequestContext& ctx); | 92 | void ActivateKeyboard(Kernel::HLERequestContext& ctx); |
| 97 | void SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx); | 93 | void SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx); |
| 98 | void ActivateGesture(Kernel::HLERequestContext& ctx); | 94 | void ActivateXpad(Kernel::HLERequestContext& ctx); |
| 99 | void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx); | 95 | void GetXpadIDs(Kernel::HLERequestContext& ctx); |
| 96 | void ActivateSixAxisSensor(Kernel::HLERequestContext& ctx); | ||
| 97 | void DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx); | ||
| 100 | void StartSixAxisSensor(Kernel::HLERequestContext& ctx); | 98 | void StartSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 101 | void StopSixAxisSensor(Kernel::HLERequestContext& ctx); | 99 | void StopSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 102 | void EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx); | 100 | void EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx); |
| @@ -104,6 +102,7 @@ private: | |||
| 104 | void GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); | 102 | void GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); |
| 105 | void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); | 103 | void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); |
| 106 | void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx); | 104 | void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx); |
| 105 | void ActivateGesture(Kernel::HLERequestContext& ctx); | ||
| 107 | void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); | 106 | void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); |
| 108 | void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); | 107 | void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); |
| 109 | void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx); | 108 | void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx); |
| @@ -112,6 +111,7 @@ private: | |||
| 112 | void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx); | 111 | void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx); |
| 113 | void DisconnectNpad(Kernel::HLERequestContext& ctx); | 112 | void DisconnectNpad(Kernel::HLERequestContext& ctx); |
| 114 | void GetPlayerLedPattern(Kernel::HLERequestContext& ctx); | 113 | void GetPlayerLedPattern(Kernel::HLERequestContext& ctx); |
| 114 | void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx); | ||
| 115 | void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx); | 115 | void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx); |
| 116 | void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx); | 116 | void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx); |
| 117 | void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx); | 117 | void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx); |
| @@ -125,15 +125,16 @@ private: | |||
| 125 | void SwapNpadAssignment(Kernel::HLERequestContext& ctx); | 125 | void SwapNpadAssignment(Kernel::HLERequestContext& ctx); |
| 126 | void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx); | 126 | void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx); |
| 127 | void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx); | 127 | void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx); |
| 128 | void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx); | 128 | void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx); |
| 129 | void EndPermitVibrationSession(Kernel::HLERequestContext& ctx); | ||
| 130 | void SendVibrationValue(Kernel::HLERequestContext& ctx); | 129 | void SendVibrationValue(Kernel::HLERequestContext& ctx); |
| 131 | void SendVibrationValues(Kernel::HLERequestContext& ctx); | ||
| 132 | void GetActualVibrationValue(Kernel::HLERequestContext& ctx); | 130 | void GetActualVibrationValue(Kernel::HLERequestContext& ctx); |
| 133 | void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx); | ||
| 134 | void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx); | 131 | void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx); |
| 135 | void PermitVibration(Kernel::HLERequestContext& ctx); | 132 | void PermitVibration(Kernel::HLERequestContext& ctx); |
| 136 | void IsVibrationPermitted(Kernel::HLERequestContext& ctx); | 133 | void IsVibrationPermitted(Kernel::HLERequestContext& ctx); |
| 134 | void SendVibrationValues(Kernel::HLERequestContext& ctx); | ||
| 135 | void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx); | ||
| 136 | void EndPermitVibrationSession(Kernel::HLERequestContext& ctx); | ||
| 137 | void IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx); | ||
| 137 | void ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); | 138 | void ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 138 | void StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); | 139 | void StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 139 | void StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); | 140 | void StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); |
| @@ -146,6 +147,22 @@ private: | |||
| 146 | void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx); | 147 | void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx); |
| 147 | void SetPalmaBoostMode(Kernel::HLERequestContext& ctx); | 148 | void SetPalmaBoostMode(Kernel::HLERequestContext& ctx); |
| 148 | 149 | ||
| 150 | enum class VibrationDeviceType : u32 { | ||
| 151 | LinearResonantActuator = 1, | ||
| 152 | }; | ||
| 153 | |||
| 154 | enum class VibrationDevicePosition : u32 { | ||
| 155 | None = 0, | ||
| 156 | Left = 1, | ||
| 157 | Right = 2, | ||
| 158 | }; | ||
| 159 | |||
| 160 | struct VibrationDeviceInfo { | ||
| 161 | VibrationDeviceType type{}; | ||
| 162 | VibrationDevicePosition position{}; | ||
| 163 | }; | ||
| 164 | static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incorrect size."); | ||
| 165 | |||
| 149 | std::shared_ptr<IAppletResource> applet_resource; | 166 | std::shared_ptr<IAppletResource> applet_resource; |
| 150 | Core::System& system; | 167 | Core::System& system; |
| 151 | }; | 168 | }; |
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 5b0e371fe..55e00dd93 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -771,7 +771,7 @@ private: | |||
| 771 | IPC::ResponseBuilder rb{ctx, 6}; | 771 | IPC::ResponseBuilder rb{ctx, 6}; |
| 772 | rb.Push(RESULT_SUCCESS); | 772 | rb.Push(RESULT_SUCCESS); |
| 773 | 773 | ||
| 774 | if (Settings::values.use_docked_mode) { | 774 | if (Settings::values.use_docked_mode.GetValue()) { |
| 775 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) * | 775 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) * |
| 776 | static_cast<u32>(Settings::values.resolution_factor.GetValue())); | 776 | static_cast<u32>(Settings::values.resolution_factor.GetValue())); |
| 777 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) * | 777 | rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) * |
diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 0587b9374..aadbc3932 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp | |||
| @@ -49,7 +49,7 @@ void LogSettings() { | |||
| 49 | }; | 49 | }; |
| 50 | 50 | ||
| 51 | LOG_INFO(Config, "yuzu Configuration:"); | 51 | LOG_INFO(Config, "yuzu Configuration:"); |
| 52 | log_setting("Controls_UseDockedMode", values.use_docked_mode); | 52 | log_setting("Controls_UseDockedMode", values.use_docked_mode.GetValue()); |
| 53 | log_setting("System_RngSeed", values.rng_seed.GetValue().value_or(0)); | 53 | log_setting("System_RngSeed", values.rng_seed.GetValue().value_or(0)); |
| 54 | log_setting("System_CurrentUser", values.current_user); | 54 | log_setting("System_CurrentUser", values.current_user); |
| 55 | log_setting("System_LanguageIndex", values.language_index.GetValue()); | 55 | log_setting("System_LanguageIndex", values.language_index.GetValue()); |
| @@ -145,6 +145,12 @@ void RestoreGlobalState() { | |||
| 145 | values.rng_seed.SetGlobal(true); | 145 | values.rng_seed.SetGlobal(true); |
| 146 | values.custom_rtc.SetGlobal(true); | 146 | values.custom_rtc.SetGlobal(true); |
| 147 | values.sound_index.SetGlobal(true); | 147 | values.sound_index.SetGlobal(true); |
| 148 | |||
| 149 | // Controls | ||
| 150 | values.players.SetGlobal(true); | ||
| 151 | values.use_docked_mode.SetGlobal(true); | ||
| 152 | values.vibration_enabled.SetGlobal(true); | ||
| 153 | values.motion_enabled.SetGlobal(true); | ||
| 148 | } | 154 | } |
| 149 | 155 | ||
| 150 | void Sanitize() { | 156 | void Sanitize() { |
diff --git a/src/core/settings.h b/src/core/settings.h index 28616a574..476c3fdf3 100644 --- a/src/core/settings.h +++ b/src/core/settings.h | |||
| @@ -65,6 +65,38 @@ private: | |||
| 65 | Type local{}; | 65 | Type local{}; |
| 66 | }; | 66 | }; |
| 67 | 67 | ||
| 68 | /** | ||
| 69 | * The InputSetting class allows for getting a reference to either the global or local members. | ||
| 70 | * This is required as we cannot easily modify the values of user-defined types within containers | ||
| 71 | * using the SetValue() member function found in the Setting class. The primary purpose of this | ||
| 72 | * class is to store an array of 10 PlayerInput structs for both the global and local (per-game) | ||
| 73 | * setting and allows for easily accessing and modifying both settings. | ||
| 74 | */ | ||
| 75 | template <typename Type> | ||
| 76 | class InputSetting final { | ||
| 77 | public: | ||
| 78 | InputSetting() = default; | ||
| 79 | explicit InputSetting(Type val) : global{val} {} | ||
| 80 | ~InputSetting() = default; | ||
| 81 | void SetGlobal(bool to_global) { | ||
| 82 | use_global = to_global; | ||
| 83 | } | ||
| 84 | bool UsingGlobal() const { | ||
| 85 | return use_global; | ||
| 86 | } | ||
| 87 | Type& GetValue(bool need_global = false) { | ||
| 88 | if (use_global || need_global) { | ||
| 89 | return global; | ||
| 90 | } | ||
| 91 | return local; | ||
| 92 | } | ||
| 93 | |||
| 94 | private: | ||
| 95 | bool use_global = true; | ||
| 96 | Type global{}; | ||
| 97 | Type local{}; | ||
| 98 | }; | ||
| 99 | |||
| 68 | struct TouchFromButtonMap { | 100 | struct TouchFromButtonMap { |
| 69 | std::string name; | 101 | std::string name; |
| 70 | std::vector<std::string> buttons; | 102 | std::vector<std::string> buttons; |
| @@ -133,9 +165,18 @@ struct Values { | |||
| 133 | Setting<s32> sound_index; | 165 | Setting<s32> sound_index; |
| 134 | 166 | ||
| 135 | // Controls | 167 | // Controls |
| 136 | std::array<PlayerInput, 10> players; | 168 | InputSetting<std::array<PlayerInput, 10>> players; |
| 169 | |||
| 170 | Setting<bool> use_docked_mode; | ||
| 137 | 171 | ||
| 138 | bool use_docked_mode; | 172 | Setting<bool> vibration_enabled; |
| 173 | Setting<bool> enable_accurate_vibrations; | ||
| 174 | |||
| 175 | Setting<bool> motion_enabled; | ||
| 176 | std::string motion_device; | ||
| 177 | std::string udp_input_address; | ||
| 178 | u16 udp_input_port; | ||
| 179 | u8 udp_pad_index; | ||
| 139 | 180 | ||
| 140 | bool mouse_enabled; | 181 | bool mouse_enabled; |
| 141 | std::string mouse_device; | 182 | std::string mouse_device; |
| @@ -149,20 +190,15 @@ struct Values { | |||
| 149 | ButtonsRaw debug_pad_buttons; | 190 | ButtonsRaw debug_pad_buttons; |
| 150 | AnalogsRaw debug_pad_analogs; | 191 | AnalogsRaw debug_pad_analogs; |
| 151 | 192 | ||
| 152 | bool vibration_enabled; | ||
| 153 | |||
| 154 | bool motion_enabled; | ||
| 155 | std::string motion_device; | ||
| 156 | std::string touch_device; | ||
| 157 | TouchscreenInput touchscreen; | 193 | TouchscreenInput touchscreen; |
| 158 | std::atomic_bool is_device_reload_pending{true}; | 194 | |
| 159 | bool use_touch_from_button; | 195 | bool use_touch_from_button; |
| 196 | std::string touch_device; | ||
| 160 | int touch_from_button_map_index; | 197 | int touch_from_button_map_index; |
| 161 | std::string udp_input_address; | ||
| 162 | u16 udp_input_port; | ||
| 163 | u8 udp_pad_index; | ||
| 164 | std::vector<TouchFromButtonMap> touch_from_button_maps; | 198 | std::vector<TouchFromButtonMap> touch_from_button_maps; |
| 165 | 199 | ||
| 200 | std::atomic_bool is_device_reload_pending{true}; | ||
| 201 | |||
| 166 | // Data Storage | 202 | // Data Storage |
| 167 | bool use_virtual_sd; | 203 | bool use_virtual_sd; |
| 168 | bool gamecard_inserted; | 204 | bool gamecard_inserted; |
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index ebc19e18a..e0908186b 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp | |||
| @@ -213,7 +213,7 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) { | |||
| 213 | Settings::values.use_assembly_shaders.GetValue()); | 213 | Settings::values.use_assembly_shaders.GetValue()); |
| 214 | AddField(field_type, "Renderer_UseAsynchronousShaders", | 214 | AddField(field_type, "Renderer_UseAsynchronousShaders", |
| 215 | Settings::values.use_asynchronous_shaders.GetValue()); | 215 | Settings::values.use_asynchronous_shaders.GetValue()); |
| 216 | AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode); | 216 | AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode.GetValue()); |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | bool TelemetrySession::SubmitTestcase() { | 219 | bool TelemetrySession::SubmitTestcase() { |
diff --git a/src/input_common/gcadapter/gc_adapter.cpp b/src/input_common/gcadapter/gc_adapter.cpp index b912188b6..d80195c82 100644 --- a/src/input_common/gcadapter/gc_adapter.cpp +++ b/src/input_common/gcadapter/gc_adapter.cpp | |||
| @@ -230,10 +230,8 @@ void Adapter::SendVibrations() { | |||
| 230 | vibration_changed = false; | 230 | vibration_changed = false; |
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | bool Adapter::RumblePlay(std::size_t port, f32 amplitude) { | 233 | bool Adapter::RumblePlay(std::size_t port, u8 amplitude) { |
| 234 | amplitude = std::clamp(amplitude, 0.0f, 1.0f); | 234 | pads[port].rumble_amplitude = amplitude; |
| 235 | const auto raw_amp = static_cast<u8>(amplitude * 0x8); | ||
| 236 | pads[port].rumble_amplitude = raw_amp; | ||
| 237 | 235 | ||
| 238 | return rumble_enabled; | 236 | return rumble_enabled; |
| 239 | } | 237 | } |
diff --git a/src/input_common/gcadapter/gc_adapter.h b/src/input_common/gcadapter/gc_adapter.h index d28dcfad3..f1256c9da 100644 --- a/src/input_common/gcadapter/gc_adapter.h +++ b/src/input_common/gcadapter/gc_adapter.h | |||
| @@ -77,8 +77,8 @@ public: | |||
| 77 | Adapter(); | 77 | Adapter(); |
| 78 | ~Adapter(); | 78 | ~Adapter(); |
| 79 | 79 | ||
| 80 | /// Request a vibration for a controlelr | 80 | /// Request a vibration for a controller |
| 81 | bool RumblePlay(std::size_t port, f32 amplitude); | 81 | bool RumblePlay(std::size_t port, u8 amplitude); |
| 82 | 82 | ||
| 83 | /// Used for polling | 83 | /// Used for polling |
| 84 | void BeginConfiguration(); | 84 | void BeginConfiguration(); |
diff --git a/src/input_common/gcadapter/gc_poller.cpp b/src/input_common/gcadapter/gc_poller.cpp index 6bd6f57fc..fe57c13a5 100644 --- a/src/input_common/gcadapter/gc_poller.cpp +++ b/src/input_common/gcadapter/gc_poller.cpp | |||
| @@ -15,7 +15,7 @@ namespace InputCommon { | |||
| 15 | 15 | ||
| 16 | class GCButton final : public Input::ButtonDevice { | 16 | class GCButton final : public Input::ButtonDevice { |
| 17 | public: | 17 | public: |
| 18 | explicit GCButton(u32 port_, s32 button_, GCAdapter::Adapter* adapter) | 18 | explicit GCButton(u32 port_, s32 button_, const GCAdapter::Adapter* adapter) |
| 19 | : port(port_), button(button_), gcadapter(adapter) {} | 19 | : port(port_), button(button_), gcadapter(adapter) {} |
| 20 | 20 | ||
| 21 | ~GCButton() override; | 21 | ~GCButton() override; |
| @@ -27,18 +27,10 @@ public: | |||
| 27 | return false; | 27 | return false; |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const override { | ||
| 31 | const float amplitude = amp_high + amp_low > 2.0f ? 1.0f : (amp_high + amp_low) * 0.5f; | ||
| 32 | const auto new_amp = | ||
| 33 | static_cast<f32>(pow(amplitude, 0.5f) * (3.0f - 2.0f * pow(amplitude, 0.15f))); | ||
| 34 | |||
| 35 | return gcadapter->RumblePlay(port, new_amp); | ||
| 36 | } | ||
| 37 | |||
| 38 | private: | 30 | private: |
| 39 | const u32 port; | 31 | const u32 port; |
| 40 | const s32 button; | 32 | const s32 button; |
| 41 | GCAdapter::Adapter* gcadapter; | 33 | const GCAdapter::Adapter* gcadapter; |
| 42 | }; | 34 | }; |
| 43 | 35 | ||
| 44 | class GCAxisButton final : public Input::ButtonDevice { | 36 | class GCAxisButton final : public Input::ButtonDevice { |
| @@ -299,4 +291,42 @@ Common::ParamPackage GCAnalogFactory::GetNextInput() { | |||
| 299 | return params; | 291 | return params; |
| 300 | } | 292 | } |
| 301 | 293 | ||
| 294 | class GCVibration final : public Input::VibrationDevice { | ||
| 295 | public: | ||
| 296 | explicit GCVibration(u32 port_, GCAdapter::Adapter* adapter) | ||
| 297 | : port(port_), gcadapter(adapter) {} | ||
| 298 | |||
| 299 | u8 GetStatus() const override { | ||
| 300 | return gcadapter->RumblePlay(port, 0); | ||
| 301 | } | ||
| 302 | |||
| 303 | bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const override { | ||
| 304 | const auto mean_amplitude = (amp_low + amp_high) * 0.5f; | ||
| 305 | const auto processed_amplitude = static_cast<u8>( | ||
| 306 | pow(mean_amplitude, 0.5f) * (3.0f - 2.0f * pow(mean_amplitude, 0.15f)) * 0x8); | ||
| 307 | |||
| 308 | return gcadapter->RumblePlay(port, processed_amplitude); | ||
| 309 | } | ||
| 310 | |||
| 311 | private: | ||
| 312 | const u32 port; | ||
| 313 | GCAdapter::Adapter* gcadapter; | ||
| 314 | }; | ||
| 315 | |||
| 316 | /// An vibration device factory that creates vibration devices from GC Adapter | ||
| 317 | GCVibrationFactory::GCVibrationFactory(std::shared_ptr<GCAdapter::Adapter> adapter_) | ||
| 318 | : adapter(std::move(adapter_)) {} | ||
| 319 | |||
| 320 | /** | ||
| 321 | * Creates a vibration device from a joystick | ||
| 322 | * @param params contains parameters for creating the device: | ||
| 323 | * - "port": the nth gcpad on the adapter | ||
| 324 | */ | ||
| 325 | std::unique_ptr<Input::VibrationDevice> GCVibrationFactory::Create( | ||
| 326 | const Common::ParamPackage& params) { | ||
| 327 | const auto port = static_cast<u32>(params.Get("port", 0)); | ||
| 328 | |||
| 329 | return std::make_unique<GCVibration>(port, adapter.get()); | ||
| 330 | } | ||
| 331 | |||
| 302 | } // namespace InputCommon | 332 | } // namespace InputCommon |
diff --git a/src/input_common/gcadapter/gc_poller.h b/src/input_common/gcadapter/gc_poller.h index 0527f328f..d1271e3ea 100644 --- a/src/input_common/gcadapter/gc_poller.h +++ b/src/input_common/gcadapter/gc_poller.h | |||
| @@ -64,4 +64,15 @@ private: | |||
| 64 | bool polling = false; | 64 | bool polling = false; |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | /// A vibration device factory creates vibration devices from GC Adapter | ||
| 68 | class GCVibrationFactory final : public Input::Factory<Input::VibrationDevice> { | ||
| 69 | public: | ||
| 70 | explicit GCVibrationFactory(std::shared_ptr<GCAdapter::Adapter> adapter_); | ||
| 71 | |||
| 72 | std::unique_ptr<Input::VibrationDevice> Create(const Common::ParamPackage& params) override; | ||
| 73 | |||
| 74 | private: | ||
| 75 | std::shared_ptr<GCAdapter::Adapter> adapter; | ||
| 76 | }; | ||
| 77 | |||
| 67 | } // namespace InputCommon | 78 | } // namespace InputCommon |
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index d32fd8b81..e59ad4ff5 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp | |||
| @@ -28,6 +28,8 @@ struct InputSubsystem::Impl { | |||
| 28 | Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons); | 28 | Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons); |
| 29 | gcanalog = std::make_shared<GCAnalogFactory>(gcadapter); | 29 | gcanalog = std::make_shared<GCAnalogFactory>(gcadapter); |
| 30 | Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog); | 30 | Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog); |
| 31 | gcvibration = std::make_shared<GCVibrationFactory>(gcadapter); | ||
| 32 | Input::RegisterFactory<Input::VibrationDevice>("gcpad", gcvibration); | ||
| 31 | 33 | ||
| 32 | keyboard = std::make_shared<Keyboard>(); | 34 | keyboard = std::make_shared<Keyboard>(); |
| 33 | Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard); | 35 | Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard); |
| @@ -64,9 +66,11 @@ struct InputSubsystem::Impl { | |||
| 64 | #endif | 66 | #endif |
| 65 | Input::UnregisterFactory<Input::ButtonDevice>("gcpad"); | 67 | Input::UnregisterFactory<Input::ButtonDevice>("gcpad"); |
| 66 | Input::UnregisterFactory<Input::AnalogDevice>("gcpad"); | 68 | Input::UnregisterFactory<Input::AnalogDevice>("gcpad"); |
| 69 | Input::UnregisterFactory<Input::VibrationDevice>("gcpad"); | ||
| 67 | 70 | ||
| 68 | gcbuttons.reset(); | 71 | gcbuttons.reset(); |
| 69 | gcanalog.reset(); | 72 | gcanalog.reset(); |
| 73 | gcvibration.reset(); | ||
| 70 | 74 | ||
| 71 | Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp"); | 75 | Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp"); |
| 72 | Input::UnregisterFactory<Input::TouchDevice>("cemuhookudp"); | 76 | Input::UnregisterFactory<Input::TouchDevice>("cemuhookudp"); |
| @@ -78,7 +82,7 @@ struct InputSubsystem::Impl { | |||
| 78 | [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const { | 82 | [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const { |
| 79 | std::vector<Common::ParamPackage> devices = { | 83 | std::vector<Common::ParamPackage> devices = { |
| 80 | Common::ParamPackage{{"display", "Any"}, {"class", "any"}}, | 84 | Common::ParamPackage{{"display", "Any"}, {"class", "any"}}, |
| 81 | Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "key"}}, | 85 | Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "keyboard"}}, |
| 82 | }; | 86 | }; |
| 83 | #ifdef HAVE_SDL2 | 87 | #ifdef HAVE_SDL2 |
| 84 | auto sdl_devices = sdl->GetInputDevices(); | 88 | auto sdl_devices = sdl->GetInputDevices(); |
| @@ -96,10 +100,6 @@ struct InputSubsystem::Impl { | |||
| 96 | if (!params.Has("class") || params.Get("class", "") == "any") { | 100 | if (!params.Has("class") || params.Get("class", "") == "any") { |
| 97 | return {}; | 101 | return {}; |
| 98 | } | 102 | } |
| 99 | if (params.Get("class", "") == "key") { | ||
| 100 | // TODO consider returning the SDL key codes for the default keybindings | ||
| 101 | return {}; | ||
| 102 | } | ||
| 103 | if (params.Get("class", "") == "gcpad") { | 103 | if (params.Get("class", "") == "gcpad") { |
| 104 | return gcadapter->GetAnalogMappingForDevice(params); | 104 | return gcadapter->GetAnalogMappingForDevice(params); |
| 105 | } | 105 | } |
| @@ -116,10 +116,6 @@ struct InputSubsystem::Impl { | |||
| 116 | if (!params.Has("class") || params.Get("class", "") == "any") { | 116 | if (!params.Has("class") || params.Get("class", "") == "any") { |
| 117 | return {}; | 117 | return {}; |
| 118 | } | 118 | } |
| 119 | if (params.Get("class", "") == "key") { | ||
| 120 | // TODO consider returning the SDL key codes for the default keybindings | ||
| 121 | return {}; | ||
| 122 | } | ||
| 123 | if (params.Get("class", "") == "gcpad") { | 119 | if (params.Get("class", "") == "gcpad") { |
| 124 | return gcadapter->GetButtonMappingForDevice(params); | 120 | return gcadapter->GetButtonMappingForDevice(params); |
| 125 | } | 121 | } |
| @@ -150,6 +146,7 @@ struct InputSubsystem::Impl { | |||
| 150 | #endif | 146 | #endif |
| 151 | std::shared_ptr<GCButtonFactory> gcbuttons; | 147 | std::shared_ptr<GCButtonFactory> gcbuttons; |
| 152 | std::shared_ptr<GCAnalogFactory> gcanalog; | 148 | std::shared_ptr<GCAnalogFactory> gcanalog; |
| 149 | std::shared_ptr<GCVibrationFactory> gcvibration; | ||
| 153 | std::shared_ptr<UDPMotionFactory> udpmotion; | 150 | std::shared_ptr<UDPMotionFactory> udpmotion; |
| 154 | std::shared_ptr<UDPTouchFactory> udptouch; | 151 | std::shared_ptr<UDPTouchFactory> udptouch; |
| 155 | std::shared_ptr<CemuhookUDP::Client> udp; | 152 | std::shared_ptr<CemuhookUDP::Client> udp; |
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index 10883e2d9..8c48bb861 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp | |||
| @@ -80,30 +80,13 @@ public: | |||
| 80 | return static_cast<float>(state.axes.at(axis)) / (32767.0f * range); | 80 | return static_cast<float>(state.axes.at(axis)) / (32767.0f * range); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | bool RumblePlay(f32 amp_low, f32 amp_high, u32 time) { | 83 | bool RumblePlay(u16 amp_low, u16 amp_high) { |
| 84 | const u16 raw_amp_low = static_cast<u16>(amp_low * 0xFFFF); | 84 | if (sdl_controller) { |
| 85 | const u16 raw_amp_high = static_cast<u16>(amp_high * 0xFFFF); | 85 | return SDL_GameControllerRumble(sdl_controller.get(), amp_low, amp_high, 0) == 0; |
| 86 | // Lower drastically the number of state changes | 86 | } else if (sdl_joystick) { |
| 87 | if (raw_amp_low >> 11 == last_state_rumble_low >> 11 && | 87 | return SDL_JoystickRumble(sdl_joystick.get(), amp_low, amp_high, 0) == 0; |
| 88 | raw_amp_high >> 11 == last_state_rumble_high >> 11) { | ||
| 89 | if (raw_amp_low + raw_amp_high != 0 || | ||
| 90 | last_state_rumble_low + last_state_rumble_high == 0) { | ||
| 91 | return false; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | // Don't change state if last vibration was < 20ms | ||
| 95 | const auto now = std::chrono::system_clock::now(); | ||
| 96 | if (std::chrono::duration_cast<std::chrono::milliseconds>(now - last_vibration) < | ||
| 97 | std::chrono::milliseconds(20)) { | ||
| 98 | return raw_amp_low + raw_amp_high == 0; | ||
| 99 | } | 88 | } |
| 100 | 89 | ||
| 101 | last_vibration = now; | ||
| 102 | last_state_rumble_low = raw_amp_low; | ||
| 103 | last_state_rumble_high = raw_amp_high; | ||
| 104 | if (sdl_joystick) { | ||
| 105 | SDL_JoystickRumble(sdl_joystick.get(), raw_amp_low, raw_amp_high, time); | ||
| 106 | } | ||
| 107 | return false; | 90 | return false; |
| 108 | } | 91 | } |
| 109 | 92 | ||
| @@ -172,9 +155,6 @@ private: | |||
| 172 | } state; | 155 | } state; |
| 173 | std::string guid; | 156 | std::string guid; |
| 174 | int port; | 157 | int port; |
| 175 | u16 last_state_rumble_high = 0; | ||
| 176 | u16 last_state_rumble_low = 0; | ||
| 177 | std::chrono::time_point<std::chrono::system_clock> last_vibration; | ||
| 178 | std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; | 158 | std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; |
| 179 | std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; | 159 | std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; |
| 180 | mutable std::mutex mutex; | 160 | mutable std::mutex mutex; |
| @@ -327,12 +307,6 @@ public: | |||
| 327 | return joystick->GetButton(button); | 307 | return joystick->GetButton(button); |
| 328 | } | 308 | } |
| 329 | 309 | ||
| 330 | bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const override { | ||
| 331 | const f32 new_amp_low = pow(amp_low, 0.5f) * (3.0f - 2.0f * pow(amp_low, 0.15f)); | ||
| 332 | const f32 new_amp_high = pow(amp_high, 0.5f) * (3.0f - 2.0f * pow(amp_high, 0.15f)); | ||
| 333 | return joystick->RumblePlay(new_amp_low, new_amp_high, 250); | ||
| 334 | } | ||
| 335 | |||
| 336 | private: | 310 | private: |
| 337 | std::shared_ptr<SDLJoystick> joystick; | 311 | std::shared_ptr<SDLJoystick> joystick; |
| 338 | int button; | 312 | int button; |
| @@ -416,6 +390,32 @@ private: | |||
| 416 | const float range; | 390 | const float range; |
| 417 | }; | 391 | }; |
| 418 | 392 | ||
| 393 | class SDLVibration final : public Input::VibrationDevice { | ||
| 394 | public: | ||
| 395 | explicit SDLVibration(std::shared_ptr<SDLJoystick> joystick_) | ||
| 396 | : joystick(std::move(joystick_)) {} | ||
| 397 | |||
| 398 | u8 GetStatus() const override { | ||
| 399 | joystick->RumblePlay(1, 1); | ||
| 400 | return joystick->RumblePlay(0, 0); | ||
| 401 | } | ||
| 402 | |||
| 403 | bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const override { | ||
| 404 | const auto process_amplitude = [](f32 amplitude) { | ||
| 405 | return static_cast<u16>(std::pow(amplitude, 0.5f) * | ||
| 406 | (3.0f - 2.0f * std::pow(amplitude, 0.15f)) * 0xFFFF); | ||
| 407 | }; | ||
| 408 | |||
| 409 | const auto processed_amp_low = process_amplitude(amp_low); | ||
| 410 | const auto processed_amp_high = process_amplitude(amp_high); | ||
| 411 | |||
| 412 | return joystick->RumblePlay(processed_amp_low, processed_amp_high); | ||
| 413 | } | ||
| 414 | |||
| 415 | private: | ||
| 416 | std::shared_ptr<SDLJoystick> joystick; | ||
| 417 | }; | ||
| 418 | |||
| 419 | class SDLDirectionMotion final : public Input::MotionDevice { | 419 | class SDLDirectionMotion final : public Input::MotionDevice { |
| 420 | public: | 420 | public: |
| 421 | explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_) | 421 | explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_) |
| @@ -558,7 +558,7 @@ class SDLAnalogFactory final : public Input::Factory<Input::AnalogDevice> { | |||
| 558 | public: | 558 | public: |
| 559 | explicit SDLAnalogFactory(SDLState& state_) : state(state_) {} | 559 | explicit SDLAnalogFactory(SDLState& state_) : state(state_) {} |
| 560 | /** | 560 | /** |
| 561 | * Creates analog device from joystick axes | 561 | * Creates an analog device from joystick axes |
| 562 | * @param params contains parameters for creating the device: | 562 | * @param params contains parameters for creating the device: |
| 563 | * - "guid": the guid of the joystick to bind | 563 | * - "guid": the guid of the joystick to bind |
| 564 | * - "port": the nth joystick of the same type | 564 | * - "port": the nth joystick of the same type |
| @@ -584,6 +584,26 @@ private: | |||
| 584 | SDLState& state; | 584 | SDLState& state; |
| 585 | }; | 585 | }; |
| 586 | 586 | ||
| 587 | /// An vibration device factory that creates vibration devices from SDL joystick | ||
| 588 | class SDLVibrationFactory final : public Input::Factory<Input::VibrationDevice> { | ||
| 589 | public: | ||
| 590 | explicit SDLVibrationFactory(SDLState& state_) : state(state_) {} | ||
| 591 | /** | ||
| 592 | * Creates a vibration device from a joystick | ||
| 593 | * @param params contains parameters for creating the device: | ||
| 594 | * - "guid": the guid of the joystick to bind | ||
| 595 | * - "port": the nth joystick of the same type | ||
| 596 | */ | ||
| 597 | std::unique_ptr<Input::VibrationDevice> Create(const Common::ParamPackage& params) override { | ||
| 598 | const std::string guid = params.Get("guid", "0"); | ||
| 599 | const int port = params.Get("port", 0); | ||
| 600 | return std::make_unique<SDLVibration>(state.GetSDLJoystickByGUID(guid, port)); | ||
| 601 | } | ||
| 602 | |||
| 603 | private: | ||
| 604 | SDLState& state; | ||
| 605 | }; | ||
| 606 | |||
| 587 | /// A motion device factory that creates motion devices from SDL joystick | 607 | /// A motion device factory that creates motion devices from SDL joystick |
| 588 | class SDLMotionFactory final : public Input::Factory<Input::MotionDevice> { | 608 | class SDLMotionFactory final : public Input::Factory<Input::MotionDevice> { |
| 589 | public: | 609 | public: |
| @@ -650,11 +670,13 @@ private: | |||
| 650 | 670 | ||
| 651 | SDLState::SDLState() { | 671 | SDLState::SDLState() { |
| 652 | using namespace Input; | 672 | using namespace Input; |
| 653 | analog_factory = std::make_shared<SDLAnalogFactory>(*this); | ||
| 654 | button_factory = std::make_shared<SDLButtonFactory>(*this); | 673 | button_factory = std::make_shared<SDLButtonFactory>(*this); |
| 674 | analog_factory = std::make_shared<SDLAnalogFactory>(*this); | ||
| 675 | vibration_factory = std::make_shared<SDLVibrationFactory>(*this); | ||
| 655 | motion_factory = std::make_shared<SDLMotionFactory>(*this); | 676 | motion_factory = std::make_shared<SDLMotionFactory>(*this); |
| 656 | RegisterFactory<AnalogDevice>("sdl", analog_factory); | ||
| 657 | RegisterFactory<ButtonDevice>("sdl", button_factory); | 677 | RegisterFactory<ButtonDevice>("sdl", button_factory); |
| 678 | RegisterFactory<AnalogDevice>("sdl", analog_factory); | ||
| 679 | RegisterFactory<VibrationDevice>("sdl", vibration_factory); | ||
| 658 | RegisterFactory<MotionDevice>("sdl", motion_factory); | 680 | RegisterFactory<MotionDevice>("sdl", motion_factory); |
| 659 | 681 | ||
| 660 | // If the frontend is going to manage the event loop, then we don't start one here | 682 | // If the frontend is going to manage the event loop, then we don't start one here |
| @@ -676,7 +698,7 @@ SDLState::SDLState() { | |||
| 676 | using namespace std::chrono_literals; | 698 | using namespace std::chrono_literals; |
| 677 | while (initialized) { | 699 | while (initialized) { |
| 678 | SDL_PumpEvents(); | 700 | SDL_PumpEvents(); |
| 679 | std::this_thread::sleep_for(5ms); | 701 | std::this_thread::sleep_for(1ms); |
| 680 | } | 702 | } |
| 681 | }); | 703 | }); |
| 682 | } | 704 | } |
| @@ -691,6 +713,7 @@ SDLState::~SDLState() { | |||
| 691 | using namespace Input; | 713 | using namespace Input; |
| 692 | UnregisterFactory<ButtonDevice>("sdl"); | 714 | UnregisterFactory<ButtonDevice>("sdl"); |
| 693 | UnregisterFactory<AnalogDevice>("sdl"); | 715 | UnregisterFactory<AnalogDevice>("sdl"); |
| 716 | UnregisterFactory<VibrationDevice>("sdl"); | ||
| 694 | UnregisterFactory<MotionDevice>("sdl"); | 717 | UnregisterFactory<MotionDevice>("sdl"); |
| 695 | 718 | ||
| 696 | CloseJoysticks(); | 719 | CloseJoysticks(); |
| @@ -1045,7 +1068,6 @@ public: | |||
| 1045 | 1068 | ||
| 1046 | void Start(const std::string& device_id) override { | 1069 | void Start(const std::string& device_id) override { |
| 1047 | SDLPoller::Start(device_id); | 1070 | SDLPoller::Start(device_id); |
| 1048 | // Load the game controller | ||
| 1049 | // Reset stored axes | 1071 | // Reset stored axes |
| 1050 | analog_x_axis = -1; | 1072 | analog_x_axis = -1; |
| 1051 | analog_y_axis = -1; | 1073 | analog_y_axis = -1; |
| @@ -1058,40 +1080,21 @@ public: | |||
| 1058 | if (event.type == SDL_JOYAXISMOTION && std::abs(event.jaxis.value / 32767.0) < 0.5) { | 1080 | if (event.type == SDL_JOYAXISMOTION && std::abs(event.jaxis.value / 32767.0) < 0.5) { |
| 1059 | continue; | 1081 | continue; |
| 1060 | } | 1082 | } |
| 1061 | // Simplify controller config by testing if game controller support is enabled. | ||
| 1062 | if (event.type == SDL_JOYAXISMOTION) { | 1083 | if (event.type == SDL_JOYAXISMOTION) { |
| 1063 | const auto axis = event.jaxis.axis; | 1084 | const auto axis = event.jaxis.axis; |
| 1064 | if (const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); | 1085 | // In order to return a complete analog param, we need inputs for both axes. |
| 1065 | auto* const controller = joystick->GetSDLGameController()) { | 1086 | // First we take the x-axis (horizontal) input, then the y-axis (vertical) input. |
| 1066 | const auto axis_left_x = | 1087 | if (analog_x_axis == -1) { |
| 1067 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX) | 1088 | analog_x_axis = axis; |
| 1068 | .value.axis; | 1089 | } else if (analog_y_axis == -1 && analog_x_axis != axis) { |
| 1069 | const auto axis_left_y = | 1090 | analog_y_axis = axis; |
| 1070 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY) | 1091 | } |
| 1071 | .value.axis; | 1092 | } else { |
| 1072 | const auto axis_right_x = | 1093 | // If the press wasn't accepted as a joy axis, check for a button press |
| 1073 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX) | 1094 | auto button_press = button_poller.FromEvent(event); |
| 1074 | .value.axis; | 1095 | if (button_press) { |
| 1075 | const auto axis_right_y = | 1096 | return *button_press; |
| 1076 | SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY) | ||
| 1077 | .value.axis; | ||
| 1078 | |||
| 1079 | if (axis == axis_left_x || axis == axis_left_y) { | ||
| 1080 | analog_x_axis = axis_left_x; | ||
| 1081 | analog_y_axis = axis_left_y; | ||
| 1082 | break; | ||
| 1083 | } else if (axis == axis_right_x || axis == axis_right_y) { | ||
| 1084 | analog_x_axis = axis_right_x; | ||
| 1085 | analog_y_axis = axis_right_y; | ||
| 1086 | break; | ||
| 1087 | } | ||
| 1088 | } | 1097 | } |
| 1089 | } | ||
| 1090 | |||
| 1091 | // If the press wasn't accepted as a joy axis, check for a button press | ||
| 1092 | auto button_press = button_poller.FromEvent(event); | ||
| 1093 | if (button_press) { | ||
| 1094 | return *button_press; | ||
| 1095 | } | 1098 | } |
| 1096 | } | 1099 | } |
| 1097 | 1100 | ||
| @@ -1104,6 +1107,7 @@ public: | |||
| 1104 | return params; | 1107 | return params; |
| 1105 | } | 1108 | } |
| 1106 | } | 1109 | } |
| 1110 | |||
| 1107 | return {}; | 1111 | return {}; |
| 1108 | } | 1112 | } |
| 1109 | 1113 | ||
diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h index b9bb4dc56..08044b00d 100644 --- a/src/input_common/sdl/sdl_impl.h +++ b/src/input_common/sdl/sdl_impl.h | |||
| @@ -22,6 +22,7 @@ namespace InputCommon::SDL { | |||
| 22 | class SDLAnalogFactory; | 22 | class SDLAnalogFactory; |
| 23 | class SDLButtonFactory; | 23 | class SDLButtonFactory; |
| 24 | class SDLMotionFactory; | 24 | class SDLMotionFactory; |
| 25 | class SDLVibrationFactory; | ||
| 25 | class SDLJoystick; | 26 | class SDLJoystick; |
| 26 | 27 | ||
| 27 | class SDLState : public State { | 28 | class SDLState : public State { |
| @@ -72,6 +73,7 @@ private: | |||
| 72 | 73 | ||
| 73 | std::shared_ptr<SDLButtonFactory> button_factory; | 74 | std::shared_ptr<SDLButtonFactory> button_factory; |
| 74 | std::shared_ptr<SDLAnalogFactory> analog_factory; | 75 | std::shared_ptr<SDLAnalogFactory> analog_factory; |
| 76 | std::shared_ptr<SDLVibrationFactory> vibration_factory; | ||
| 75 | std::shared_ptr<SDLMotionFactory> motion_factory; | 77 | std::shared_ptr<SDLMotionFactory> motion_factory; |
| 76 | 78 | ||
| 77 | bool start_thread = false; | 79 | bool start_thread = false; |
diff --git a/src/input_common/settings.cpp b/src/input_common/settings.cpp index b66c05856..557e7a9a0 100644 --- a/src/input_common/settings.cpp +++ b/src/input_common/settings.cpp | |||
| @@ -14,13 +14,6 @@ const std::array<const char*, NumButtons> mapping = {{ | |||
| 14 | }}; | 14 | }}; |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | namespace NativeMotion { | ||
| 18 | const std::array<const char*, NumMotions> mapping = {{ | ||
| 19 | "motionleft", | ||
| 20 | "motionright", | ||
| 21 | }}; | ||
| 22 | } | ||
| 23 | |||
| 24 | namespace NativeAnalog { | 17 | namespace NativeAnalog { |
| 25 | const std::array<const char*, NumAnalogs> mapping = {{ | 18 | const std::array<const char*, NumAnalogs> mapping = {{ |
| 26 | "lstick", | 19 | "lstick", |
| @@ -28,6 +21,20 @@ const std::array<const char*, NumAnalogs> mapping = {{ | |||
| 28 | }}; | 21 | }}; |
| 29 | } | 22 | } |
| 30 | 23 | ||
| 24 | namespace NativeVibration { | ||
| 25 | const std::array<const char*, NumVibrations> mapping = {{ | ||
| 26 | "left_vibration_device", | ||
| 27 | "right_vibration_device", | ||
| 28 | }}; | ||
| 29 | } | ||
| 30 | |||
| 31 | namespace NativeMotion { | ||
| 32 | const std::array<const char*, NumMotions> mapping = {{ | ||
| 33 | "motionleft", | ||
| 34 | "motionright", | ||
| 35 | }}; | ||
| 36 | } | ||
| 37 | |||
| 31 | namespace NativeMouseButton { | 38 | namespace NativeMouseButton { |
| 32 | const std::array<const char*, NumMouseButtons> mapping = {{ | 39 | const std::array<const char*, NumMouseButtons> mapping = {{ |
| 33 | "left", | 40 | "left", |
diff --git a/src/input_common/settings.h b/src/input_common/settings.h index f52d28540..75486554b 100644 --- a/src/input_common/settings.h +++ b/src/input_common/settings.h | |||
| @@ -66,17 +66,32 @@ constexpr int NUM_STICKS_HID = NumAnalogs; | |||
| 66 | extern const std::array<const char*, NumAnalogs> mapping; | 66 | extern const std::array<const char*, NumAnalogs> mapping; |
| 67 | } // namespace NativeAnalog | 67 | } // namespace NativeAnalog |
| 68 | 68 | ||
| 69 | namespace NativeVibration { | ||
| 70 | enum Values : int { | ||
| 71 | LeftVibrationDevice, | ||
| 72 | RightVibrationDevice, | ||
| 73 | |||
| 74 | NumVibrations, | ||
| 75 | }; | ||
| 76 | |||
| 77 | constexpr int VIBRATION_HID_BEGIN = LeftVibrationDevice; | ||
| 78 | constexpr int VIBRATION_HID_END = NumVibrations; | ||
| 79 | constexpr int NUM_VIBRATIONS_HID = NumVibrations; | ||
| 80 | |||
| 81 | extern const std::array<const char*, NumVibrations> mapping; | ||
| 82 | }; // namespace NativeVibration | ||
| 83 | |||
| 69 | namespace NativeMotion { | 84 | namespace NativeMotion { |
| 70 | enum Values : int { | 85 | enum Values : int { |
| 71 | MOTIONLEFT, | 86 | MotionLeft, |
| 72 | MOTIONRIGHT, | 87 | MotionRight, |
| 73 | 88 | ||
| 74 | NumMotions, | 89 | NumMotions, |
| 75 | }; | 90 | }; |
| 76 | 91 | ||
| 77 | constexpr int MOTION_HID_BEGIN = MOTIONLEFT; | 92 | constexpr int MOTION_HID_BEGIN = MotionLeft; |
| 78 | constexpr int MOTION_HID_END = NumMotions; | 93 | constexpr int MOTION_HID_END = NumMotions; |
| 79 | constexpr int NUM_MOTION_HID = NumMotions; | 94 | constexpr int NUM_MOTIONS_HID = NumMotions; |
| 80 | 95 | ||
| 81 | extern const std::array<const char*, NumMotions> mapping; | 96 | extern const std::array<const char*, NumMotions> mapping; |
| 82 | } // namespace NativeMotion | 97 | } // namespace NativeMotion |
| @@ -305,9 +320,11 @@ constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods; | |||
| 305 | 320 | ||
| 306 | } // namespace NativeKeyboard | 321 | } // namespace NativeKeyboard |
| 307 | 322 | ||
| 308 | using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>; | ||
| 309 | using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>; | 323 | using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>; |
| 310 | using MotionRaw = std::array<std::string, NativeMotion::NumMotions>; | 324 | using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>; |
| 325 | using MotionsRaw = std::array<std::string, NativeMotion::NumMotions>; | ||
| 326 | using VibrationsRaw = std::array<std::string, NativeVibration::NumVibrations>; | ||
| 327 | |||
| 311 | using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>; | 328 | using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>; |
| 312 | using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>; | 329 | using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>; |
| 313 | using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>; | 330 | using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>; |
| @@ -330,7 +347,11 @@ struct PlayerInput { | |||
| 330 | ControllerType controller_type; | 347 | ControllerType controller_type; |
| 331 | ButtonsRaw buttons; | 348 | ButtonsRaw buttons; |
| 332 | AnalogsRaw analogs; | 349 | AnalogsRaw analogs; |
| 333 | MotionRaw motions; | 350 | VibrationsRaw vibrations; |
| 351 | MotionsRaw motions; | ||
| 352 | |||
| 353 | bool vibration_enabled; | ||
| 354 | int vibration_strength; | ||
| 334 | 355 | ||
| 335 | u32 body_color_left; | 356 | u32 body_color_left; |
| 336 | u32 body_color_right; | 357 | u32 body_color_right; |
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp index 7039d6fc3..3677e79ca 100644 --- a/src/input_common/udp/client.cpp +++ b/src/input_common/udp/client.cpp | |||
| @@ -344,7 +344,7 @@ void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, | |||
| 344 | }; | 344 | }; |
| 345 | Socket socket{host, port, pad_index, client_id, std::move(callback)}; | 345 | Socket socket{host, port, pad_index, client_id, std::move(callback)}; |
| 346 | std::thread worker_thread{SocketLoop, &socket}; | 346 | std::thread worker_thread{SocketLoop, &socket}; |
| 347 | const bool result = success_event.WaitFor(std::chrono::seconds(8)); | 347 | const bool result = success_event.WaitFor(std::chrono::seconds(5)); |
| 348 | socket.Stop(); | 348 | socket.Stop(); |
| 349 | worker_thread.join(); | 349 | worker_thread.join(); |
| 350 | if (result) { | 350 | if (result) { |
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 8abb74d56..b16b54032 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt | |||
| @@ -68,12 +68,12 @@ add_executable(yuzu | |||
| 68 | configuration/configure_input_advanced.cpp | 68 | configuration/configure_input_advanced.cpp |
| 69 | configuration/configure_input_advanced.h | 69 | configuration/configure_input_advanced.h |
| 70 | configuration/configure_input_advanced.ui | 70 | configuration/configure_input_advanced.ui |
| 71 | configuration/configure_input_dialog.cpp | ||
| 72 | configuration/configure_input_dialog.h | ||
| 73 | configuration/configure_input_dialog.ui | ||
| 74 | configuration/configure_input_player.cpp | 71 | configuration/configure_input_player.cpp |
| 75 | configuration/configure_input_player.h | 72 | configuration/configure_input_player.h |
| 76 | configuration/configure_input_player.ui | 73 | configuration/configure_input_player.ui |
| 74 | configuration/configure_input_profile_dialog.cpp | ||
| 75 | configuration/configure_input_profile_dialog.h | ||
| 76 | configuration/configure_input_profile_dialog.ui | ||
| 77 | configuration/configure_motion_touch.cpp | 77 | configuration/configure_motion_touch.cpp |
| 78 | configuration/configure_motion_touch.h | 78 | configuration/configure_motion_touch.h |
| 79 | configuration/configure_motion_touch.ui | 79 | configuration/configure_motion_touch.ui |
| @@ -105,9 +105,14 @@ add_executable(yuzu | |||
| 105 | configuration/configure_ui.cpp | 105 | configuration/configure_ui.cpp |
| 106 | configuration/configure_ui.h | 106 | configuration/configure_ui.h |
| 107 | configuration/configure_ui.ui | 107 | configuration/configure_ui.ui |
| 108 | configuration/configure_vibration.cpp | ||
| 109 | configuration/configure_vibration.h | ||
| 110 | configuration/configure_vibration.ui | ||
| 108 | configuration/configure_web.cpp | 111 | configuration/configure_web.cpp |
| 109 | configuration/configure_web.h | 112 | configuration/configure_web.h |
| 110 | configuration/configure_web.ui | 113 | configuration/configure_web.ui |
| 114 | configuration/input_profiles.cpp | ||
| 115 | configuration/input_profiles.h | ||
| 111 | debugger/console.cpp | 116 | debugger/console.cpp |
| 112 | debugger/console.h | 117 | debugger/console.h |
| 113 | debugger/profiler.cpp | 118 | debugger/profiler.cpp |
diff --git a/src/yuzu/aboutdialog.ui b/src/yuzu/aboutdialog.ui index f122ba39d..1b320630c 100644 --- a/src/yuzu/aboutdialog.ui +++ b/src/yuzu/aboutdialog.ui | |||
| @@ -160,32 +160,12 @@ p, li { white-space: pre-wrap; } | |||
| 160 | <signal>accepted()</signal> | 160 | <signal>accepted()</signal> |
| 161 | <receiver>AboutDialog</receiver> | 161 | <receiver>AboutDialog</receiver> |
| 162 | <slot>accept()</slot> | 162 | <slot>accept()</slot> |
| 163 | <hints> | ||
| 164 | <hint type="sourcelabel"> | ||
| 165 | <x>248</x> | ||
| 166 | <y>254</y> | ||
| 167 | </hint> | ||
| 168 | <hint type="destinationlabel"> | ||
| 169 | <x>157</x> | ||
| 170 | <y>274</y> | ||
| 171 | </hint> | ||
| 172 | </hints> | ||
| 173 | </connection> | 163 | </connection> |
| 174 | <connection> | 164 | <connection> |
| 175 | <sender>buttonBox</sender> | 165 | <sender>buttonBox</sender> |
| 176 | <signal>rejected()</signal> | 166 | <signal>rejected()</signal> |
| 177 | <receiver>AboutDialog</receiver> | 167 | <receiver>AboutDialog</receiver> |
| 178 | <slot>reject()</slot> | 168 | <slot>reject()</slot> |
| 179 | <hints> | ||
| 180 | <hint type="sourcelabel"> | ||
| 181 | <x>316</x> | ||
| 182 | <y>260</y> | ||
| 183 | </hint> | ||
| 184 | <hint type="destinationlabel"> | ||
| 185 | <x>286</x> | ||
| 186 | <y>274</y> | ||
| 187 | </hint> | ||
| 188 | </hints> | ||
| 189 | </connection> | 169 | </connection> |
| 190 | </connections> | 170 | </connections> |
| 191 | </ui> | 171 | </ui> |
diff --git a/src/yuzu/applets/controller.cpp b/src/yuzu/applets/controller.cpp index c6fa3e4f6..8ecfec770 100644 --- a/src/yuzu/applets/controller.cpp +++ b/src/yuzu/applets/controller.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <thread> | ||
| 6 | 7 | ||
| 7 | #include "common/assert.h" | 8 | #include "common/assert.h" |
| 8 | #include "common/string_util.h" | 9 | #include "common/string_util.h" |
| @@ -13,11 +14,16 @@ | |||
| 13 | #include "core/hle/service/sm/sm.h" | 14 | #include "core/hle/service/sm/sm.h" |
| 14 | #include "ui_controller.h" | 15 | #include "ui_controller.h" |
| 15 | #include "yuzu/applets/controller.h" | 16 | #include "yuzu/applets/controller.h" |
| 16 | #include "yuzu/configuration/configure_input_dialog.h" | 17 | #include "yuzu/configuration/configure_input.h" |
| 18 | #include "yuzu/configuration/configure_input_profile_dialog.h" | ||
| 19 | #include "yuzu/configuration/configure_vibration.h" | ||
| 20 | #include "yuzu/configuration/input_profiles.h" | ||
| 17 | #include "yuzu/main.h" | 21 | #include "yuzu/main.h" |
| 18 | 22 | ||
| 19 | namespace { | 23 | namespace { |
| 20 | 24 | ||
| 25 | constexpr std::size_t HANDHELD_INDEX = 8; | ||
| 26 | |||
| 21 | constexpr std::array<std::array<bool, 4>, 8> led_patterns{{ | 27 | constexpr std::array<std::array<bool, 4>, 8> led_patterns{{ |
| 22 | {true, false, false, false}, | 28 | {true, false, false, false}, |
| 23 | {true, true, false, false}, | 29 | {true, true, false, false}, |
| @@ -106,7 +112,8 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( | |||
| 106 | QWidget* parent, Core::Frontend::ControllerParameters parameters_, | 112 | QWidget* parent, Core::Frontend::ControllerParameters parameters_, |
| 107 | InputCommon::InputSubsystem* input_subsystem_) | 113 | InputCommon::InputSubsystem* input_subsystem_) |
| 108 | : QDialog(parent), ui(std::make_unique<Ui::QtControllerSelectorDialog>()), | 114 | : QDialog(parent), ui(std::make_unique<Ui::QtControllerSelectorDialog>()), |
| 109 | parameters(std::move(parameters_)), input_subsystem(input_subsystem_) { | 115 | parameters(std::move(parameters_)), input_subsystem{input_subsystem_}, |
| 116 | input_profiles(std::make_unique<InputProfiles>()) { | ||
| 110 | ui->setupUi(this); | 117 | ui->setupUi(this); |
| 111 | 118 | ||
| 112 | player_widgets = { | 119 | player_widgets = { |
| @@ -223,12 +230,22 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( | |||
| 223 | } | 230 | } |
| 224 | } | 231 | } |
| 225 | 232 | ||
| 233 | connect(ui->vibrationButton, &QPushButton::clicked, this, | ||
| 234 | &QtControllerSelectorDialog::CallConfigureVibrationDialog); | ||
| 235 | |||
| 226 | connect(ui->inputConfigButton, &QPushButton::clicked, this, | 236 | connect(ui->inputConfigButton, &QPushButton::clicked, this, |
| 227 | &QtControllerSelectorDialog::CallConfigureInputDialog); | 237 | &QtControllerSelectorDialog::CallConfigureInputProfileDialog); |
| 228 | 238 | ||
| 229 | connect(ui->buttonBox, &QDialogButtonBox::accepted, this, | 239 | connect(ui->buttonBox, &QDialogButtonBox::accepted, this, |
| 230 | &QtControllerSelectorDialog::ApplyConfiguration); | 240 | &QtControllerSelectorDialog::ApplyConfiguration); |
| 231 | 241 | ||
| 242 | // Enhancement: Check if the parameters have already been met before disconnecting controllers. | ||
| 243 | // If all the parameters are met AND only allows a single player, | ||
| 244 | // stop the constructor here as we do not need to continue. | ||
| 245 | if (CheckIfParametersMet() && parameters.enable_single_mode) { | ||
| 246 | return; | ||
| 247 | } | ||
| 248 | |||
| 232 | // If keep_controllers_connected is false, forcefully disconnect all controllers | 249 | // If keep_controllers_connected is false, forcefully disconnect all controllers |
| 233 | if (!parameters.keep_controllers_connected) { | 250 | if (!parameters.keep_controllers_connected) { |
| 234 | for (auto player : player_groupboxes) { | 251 | for (auto player : player_groupboxes) { |
| @@ -236,58 +253,66 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( | |||
| 236 | } | 253 | } |
| 237 | } | 254 | } |
| 238 | 255 | ||
| 239 | CheckIfParametersMet(); | ||
| 240 | |||
| 241 | resize(0, 0); | 256 | resize(0, 0); |
| 242 | } | 257 | } |
| 243 | 258 | ||
| 244 | QtControllerSelectorDialog::~QtControllerSelectorDialog() = default; | 259 | QtControllerSelectorDialog::~QtControllerSelectorDialog() = default; |
| 245 | 260 | ||
| 246 | void QtControllerSelectorDialog::ApplyConfiguration() { | 261 | int QtControllerSelectorDialog::exec() { |
| 247 | // Update the controller state once more, just to be sure they are properly applied. | 262 | if (parameters_met && parameters.enable_single_mode) { |
| 248 | for (std::size_t index = 0; index < NUM_PLAYERS; ++index) { | 263 | return QDialog::Accepted; |
| 249 | UpdateControllerState(index); | ||
| 250 | } | 264 | } |
| 265 | return QDialog::exec(); | ||
| 266 | } | ||
| 251 | 267 | ||
| 252 | const bool pre_docked_mode = Settings::values.use_docked_mode; | 268 | void QtControllerSelectorDialog::ApplyConfiguration() { |
| 253 | Settings::values.use_docked_mode = ui->radioDocked->isChecked(); | 269 | const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue(); |
| 254 | OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode); | 270 | Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked()); |
| 271 | OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode.GetValue()); | ||
| 255 | 272 | ||
| 256 | Settings::values.vibration_enabled = ui->vibrationGroup->isChecked(); | 273 | Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked()); |
| 274 | Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked()); | ||
| 257 | } | 275 | } |
| 258 | 276 | ||
| 259 | void QtControllerSelectorDialog::LoadConfiguration() { | 277 | void QtControllerSelectorDialog::LoadConfiguration() { |
| 260 | for (std::size_t index = 0; index < NUM_PLAYERS; ++index) { | 278 | for (std::size_t index = 0; index < NUM_PLAYERS; ++index) { |
| 261 | const auto connected = Settings::values.players[index].connected || | 279 | const auto connected = |
| 262 | (index == 0 && Settings::values.players[8].connected); | 280 | Settings::values.players.GetValue()[index].connected || |
| 281 | (index == 0 && Settings::values.players.GetValue()[HANDHELD_INDEX].connected); | ||
| 263 | player_groupboxes[index]->setChecked(connected); | 282 | player_groupboxes[index]->setChecked(connected); |
| 264 | connected_controller_checkboxes[index]->setChecked(connected); | 283 | connected_controller_checkboxes[index]->setChecked(connected); |
| 265 | emulated_controllers[index]->setCurrentIndex( | 284 | emulated_controllers[index]->setCurrentIndex( |
| 266 | GetIndexFromControllerType(Settings::values.players[index].controller_type)); | 285 | GetIndexFromControllerType(Settings::values.players.GetValue()[index].controller_type)); |
| 267 | } | 286 | } |
| 268 | 287 | ||
| 269 | UpdateDockedState(Settings::values.players[8].connected); | 288 | UpdateDockedState(Settings::values.players.GetValue()[HANDHELD_INDEX].connected); |
| 270 | 289 | ||
| 271 | ui->vibrationGroup->setChecked(Settings::values.vibration_enabled); | 290 | ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue()); |
| 291 | ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue()); | ||
| 272 | } | 292 | } |
| 273 | 293 | ||
| 274 | void QtControllerSelectorDialog::CallConfigureInputDialog() { | 294 | void QtControllerSelectorDialog::CallConfigureVibrationDialog() { |
| 275 | const auto max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players; | 295 | ConfigureVibration dialog(this); |
| 276 | |||
| 277 | ConfigureInputDialog dialog(this, max_supported_players, input_subsystem); | ||
| 278 | 296 | ||
| 279 | dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | | 297 | dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | |
| 280 | Qt::WindowSystemMenuHint); | 298 | Qt::WindowSystemMenuHint); |
| 281 | dialog.setWindowModality(Qt::WindowModal); | 299 | dialog.setWindowModality(Qt::WindowModal); |
| 282 | dialog.exec(); | ||
| 283 | 300 | ||
| 284 | dialog.ApplyConfiguration(); | 301 | if (dialog.exec() == QDialog::Accepted) { |
| 302 | dialog.ApplyConfiguration(); | ||
| 303 | } | ||
| 304 | } | ||
| 285 | 305 | ||
| 286 | LoadConfiguration(); | 306 | void QtControllerSelectorDialog::CallConfigureInputProfileDialog() { |
| 287 | CheckIfParametersMet(); | 307 | ConfigureInputProfileDialog dialog(this, input_subsystem, input_profiles.get()); |
| 308 | |||
| 309 | dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | | ||
| 310 | Qt::WindowSystemMenuHint); | ||
| 311 | dialog.setWindowModality(Qt::WindowModal); | ||
| 312 | dialog.exec(); | ||
| 288 | } | 313 | } |
| 289 | 314 | ||
| 290 | void QtControllerSelectorDialog::CheckIfParametersMet() { | 315 | bool QtControllerSelectorDialog::CheckIfParametersMet() { |
| 291 | // Here, we check and validate the current configuration against all applicable parameters. | 316 | // Here, we check and validate the current configuration against all applicable parameters. |
| 292 | const auto num_connected_players = static_cast<int>( | 317 | const auto num_connected_players = static_cast<int>( |
| 293 | std::count_if(player_groupboxes.begin(), player_groupboxes.end(), | 318 | std::count_if(player_groupboxes.begin(), player_groupboxes.end(), |
| @@ -301,7 +326,7 @@ void QtControllerSelectorDialog::CheckIfParametersMet() { | |||
| 301 | num_connected_players > max_supported_players) { | 326 | num_connected_players > max_supported_players) { |
| 302 | parameters_met = false; | 327 | parameters_met = false; |
| 303 | ui->buttonBox->setEnabled(parameters_met); | 328 | ui->buttonBox->setEnabled(parameters_met); |
| 304 | return; | 329 | return parameters_met; |
| 305 | } | 330 | } |
| 306 | 331 | ||
| 307 | // Next, check against all connected controllers. | 332 | // Next, check against all connected controllers. |
| @@ -326,18 +351,13 @@ void QtControllerSelectorDialog::CheckIfParametersMet() { | |||
| 326 | return true; | 351 | return true; |
| 327 | }(); | 352 | }(); |
| 328 | 353 | ||
| 329 | if (!all_controllers_compatible) { | 354 | parameters_met = all_controllers_compatible; |
| 330 | parameters_met = false; | ||
| 331 | ui->buttonBox->setEnabled(parameters_met); | ||
| 332 | return; | ||
| 333 | } | ||
| 334 | |||
| 335 | parameters_met = true; | ||
| 336 | ui->buttonBox->setEnabled(parameters_met); | 355 | ui->buttonBox->setEnabled(parameters_met); |
| 356 | return parameters_met; | ||
| 337 | } | 357 | } |
| 338 | 358 | ||
| 339 | void QtControllerSelectorDialog::SetSupportedControllers() { | 359 | void QtControllerSelectorDialog::SetSupportedControllers() { |
| 340 | const QString theme = [this] { | 360 | const QString theme = [] { |
| 341 | if (QIcon::themeName().contains(QStringLiteral("dark"))) { | 361 | if (QIcon::themeName().contains(QStringLiteral("dark"))) { |
| 342 | return QStringLiteral("_dark"); | 362 | return QStringLiteral("_dark"); |
| 343 | } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { | 363 | } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { |
| @@ -426,7 +446,7 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index) | |||
| 426 | } | 446 | } |
| 427 | }(); | 447 | }(); |
| 428 | 448 | ||
| 429 | const QString theme = [this] { | 449 | const QString theme = [] { |
| 430 | if (QIcon::themeName().contains(QStringLiteral("dark"))) { | 450 | if (QIcon::themeName().contains(QStringLiteral("dark"))) { |
| 431 | return QStringLiteral("_dark"); | 451 | return QStringLiteral("_dark"); |
| 432 | } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { | 452 | } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { |
| @@ -441,32 +461,48 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index) | |||
| 441 | } | 461 | } |
| 442 | 462 | ||
| 443 | void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) { | 463 | void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) { |
| 444 | auto& player = Settings::values.players[player_index]; | 464 | auto& player = Settings::values.players.GetValue()[player_index]; |
| 445 | 465 | ||
| 446 | player.controller_type = | 466 | const auto controller_type = |
| 447 | GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex()); | 467 | GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex()); |
| 448 | player.connected = player_groupboxes[player_index]->isChecked(); | 468 | const auto player_connected = player_groupboxes[player_index]->isChecked() && |
| 469 | controller_type != Settings::ControllerType::Handheld; | ||
| 449 | 470 | ||
| 450 | // Player 2-8 | 471 | if (player.controller_type == controller_type && player.connected == player_connected) { |
| 451 | if (player_index != 0) { | 472 | // Set vibration devices in the event that the input device has changed. |
| 452 | UpdateController(player.controller_type, player_index, player.connected); | 473 | ConfigureVibration::SetVibrationDevices(player_index); |
| 453 | return; | 474 | return; |
| 454 | } | 475 | } |
| 455 | 476 | ||
| 456 | // Player 1 and Handheld | 477 | // Disconnect the controller first. |
| 457 | auto& handheld = Settings::values.players[8]; | 478 | UpdateController(controller_type, player_index, false); |
| 458 | // If Handheld is selected, copy all the settings from Player 1 to Handheld. | 479 | |
| 459 | if (player.controller_type == Settings::ControllerType::Handheld) { | 480 | player.controller_type = controller_type; |
| 460 | handheld = player; | 481 | player.connected = player_connected; |
| 461 | handheld.connected = player_groupboxes[player_index]->isChecked(); | 482 | |
| 462 | player.connected = false; // Disconnect Player 1 | 483 | ConfigureVibration::SetVibrationDevices(player_index); |
| 463 | } else { | 484 | |
| 464 | player.connected = player_groupboxes[player_index]->isChecked(); | 485 | // Handheld |
| 465 | handheld.connected = false; // Disconnect Handheld | 486 | if (player_index == 0) { |
| 487 | auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX]; | ||
| 488 | if (controller_type == Settings::ControllerType::Handheld) { | ||
| 489 | handheld = player; | ||
| 490 | } | ||
| 491 | handheld.connected = player_groupboxes[player_index]->isChecked() && | ||
| 492 | controller_type == Settings::ControllerType::Handheld; | ||
| 493 | UpdateController(Settings::ControllerType::Handheld, 8, handheld.connected); | ||
| 466 | } | 494 | } |
| 467 | 495 | ||
| 468 | UpdateController(player.controller_type, player_index, player.connected); | 496 | if (!player.connected) { |
| 469 | UpdateController(Settings::ControllerType::Handheld, 8, handheld.connected); | 497 | return; |
| 498 | } | ||
| 499 | |||
| 500 | // This emulates a delay between disconnecting and reconnecting controllers as some games | ||
| 501 | // do not respond to a change in controller type if it was instantaneous. | ||
| 502 | using namespace std::chrono_literals; | ||
| 503 | std::this_thread::sleep_for(20ms); | ||
| 504 | |||
| 505 | UpdateController(controller_type, player_index, player_connected); | ||
| 470 | } | 506 | } |
| 471 | 507 | ||
| 472 | void QtControllerSelectorDialog::UpdateLEDPattern(std::size_t player_index) { | 508 | void QtControllerSelectorDialog::UpdateLEDPattern(std::size_t player_index) { |
| @@ -520,8 +556,8 @@ void QtControllerSelectorDialog::UpdateDockedState(bool is_handheld) { | |||
| 520 | ui->radioDocked->setEnabled(!is_handheld); | 556 | ui->radioDocked->setEnabled(!is_handheld); |
| 521 | ui->radioUndocked->setEnabled(!is_handheld); | 557 | ui->radioUndocked->setEnabled(!is_handheld); |
| 522 | 558 | ||
| 523 | ui->radioDocked->setChecked(Settings::values.use_docked_mode); | 559 | ui->radioDocked->setChecked(Settings::values.use_docked_mode.GetValue()); |
| 524 | ui->radioUndocked->setChecked(!Settings::values.use_docked_mode); | 560 | ui->radioUndocked->setChecked(!Settings::values.use_docked_mode.GetValue()); |
| 525 | 561 | ||
| 526 | // Also force into undocked mode if the controller type is handheld. | 562 | // Also force into undocked mode if the controller type is handheld. |
| 527 | if (is_handheld) { | 563 | if (is_handheld) { |
| @@ -564,8 +600,8 @@ void QtControllerSelectorDialog::DisableUnsupportedPlayers() { | |||
| 564 | 600 | ||
| 565 | for (std::size_t index = max_supported_players; index < NUM_PLAYERS; ++index) { | 601 | for (std::size_t index = max_supported_players; index < NUM_PLAYERS; ++index) { |
| 566 | // Disconnect any unsupported players here and disable or hide them if applicable. | 602 | // Disconnect any unsupported players here and disable or hide them if applicable. |
| 567 | Settings::values.players[index].connected = false; | 603 | Settings::values.players.GetValue()[index].connected = false; |
| 568 | UpdateController(Settings::values.players[index].controller_type, index, false); | 604 | UpdateController(Settings::values.players.GetValue()[index].controller_type, index, false); |
| 569 | // Hide the player widgets when max_supported_controllers is less than or equal to 4. | 605 | // Hide the player widgets when max_supported_controllers is less than or equal to 4. |
| 570 | if (max_supported_players <= 4) { | 606 | if (max_supported_players <= 4) { |
| 571 | player_widgets[index]->hide(); | 607 | player_widgets[index]->hide(); |
diff --git a/src/yuzu/applets/controller.h b/src/yuzu/applets/controller.h index 729ecc831..4344e1dd0 100644 --- a/src/yuzu/applets/controller.h +++ b/src/yuzu/applets/controller.h | |||
| @@ -16,6 +16,8 @@ class QDialogButtonBox; | |||
| 16 | class QGroupBox; | 16 | class QGroupBox; |
| 17 | class QLabel; | 17 | class QLabel; |
| 18 | 18 | ||
| 19 | class InputProfiles; | ||
| 20 | |||
| 19 | namespace InputCommon { | 21 | namespace InputCommon { |
| 20 | class InputSubsystem; | 22 | class InputSubsystem; |
| 21 | } | 23 | } |
| @@ -33,6 +35,8 @@ public: | |||
| 33 | InputCommon::InputSubsystem* input_subsystem_); | 35 | InputCommon::InputSubsystem* input_subsystem_); |
| 34 | ~QtControllerSelectorDialog() override; | 36 | ~QtControllerSelectorDialog() override; |
| 35 | 37 | ||
| 38 | int exec() override; | ||
| 39 | |||
| 36 | private: | 40 | private: |
| 37 | // Applies the current configuration. | 41 | // Applies the current configuration. |
| 38 | void ApplyConfiguration(); | 42 | void ApplyConfiguration(); |
| @@ -40,12 +44,15 @@ private: | |||
| 40 | // Loads the current input configuration into the frontend applet. | 44 | // Loads the current input configuration into the frontend applet. |
| 41 | void LoadConfiguration(); | 45 | void LoadConfiguration(); |
| 42 | 46 | ||
| 43 | // Initializes the "Configure Input" Dialog. | 47 | // Initializes the "Configure Vibration" Dialog. |
| 44 | void CallConfigureInputDialog(); | 48 | void CallConfigureVibrationDialog(); |
| 45 | 49 | ||
| 46 | // Checks the current configuration against the given parameters and | 50 | // Initializes the "Create Input Profile" Dialog. |
| 47 | // sets the value of parameters_met. | 51 | void CallConfigureInputProfileDialog(); |
| 48 | void CheckIfParametersMet(); | 52 | |
| 53 | // Checks the current configuration against the given parameters. | ||
| 54 | // This sets and returns the value of parameters_met. | ||
| 55 | bool CheckIfParametersMet(); | ||
| 49 | 56 | ||
| 50 | // Sets the controller icons for "Supported Controller Types". | 57 | // Sets the controller icons for "Supported Controller Types". |
| 51 | void SetSupportedControllers(); | 58 | void SetSupportedControllers(); |
| @@ -78,6 +85,8 @@ private: | |||
| 78 | 85 | ||
| 79 | InputCommon::InputSubsystem* input_subsystem; | 86 | InputCommon::InputSubsystem* input_subsystem; |
| 80 | 87 | ||
| 88 | std::unique_ptr<InputProfiles> input_profiles; | ||
| 89 | |||
| 81 | // This is true if and only if all parameters are met. Otherwise, this is false. | 90 | // This is true if and only if all parameters are met. Otherwise, this is false. |
| 82 | // This determines whether the "OK" button can be clicked to exit the applet. | 91 | // This determines whether the "OK" button can be clicked to exit the applet. |
| 83 | bool parameters_met{false}; | 92 | bool parameters_met{false}; |
diff --git a/src/yuzu/applets/controller.ui b/src/yuzu/applets/controller.ui index c4108a979..c8cb6bcf3 100644 --- a/src/yuzu/applets/controller.ui +++ b/src/yuzu/applets/controller.ui | |||
| @@ -1217,9 +1217,6 @@ | |||
| 1217 | </item> | 1217 | </item> |
| 1218 | <item> | 1218 | <item> |
| 1219 | <widget class="QComboBox" name="comboPlayer3Emulated"> | 1219 | <widget class="QComboBox" name="comboPlayer3Emulated"> |
| 1220 | <property name="editable"> | ||
| 1221 | <bool>false</bool> | ||
| 1222 | </property> | ||
| 1223 | <item> | 1220 | <item> |
| 1224 | <property name="text"> | 1221 | <property name="text"> |
| 1225 | <string>Pro Controller</string> | 1222 | <string>Pro Controller</string> |
| @@ -2279,7 +2276,7 @@ | |||
| 2279 | <number>6</number> | 2276 | <number>6</number> |
| 2280 | </property> | 2277 | </property> |
| 2281 | <property name="leftMargin"> | 2278 | <property name="leftMargin"> |
| 2282 | <number>6</number> | 2279 | <number>8</number> |
| 2283 | </property> | 2280 | </property> |
| 2284 | <property name="topMargin"> | 2281 | <property name="topMargin"> |
| 2285 | <number>6</number> | 2282 | <number>6</number> |
| @@ -2332,30 +2329,24 @@ | |||
| 2332 | <number>3</number> | 2329 | <number>3</number> |
| 2333 | </property> | 2330 | </property> |
| 2334 | <item> | 2331 | <item> |
| 2335 | <widget class="QSpinBox" name="vibrationSpin"> | 2332 | <widget class="QPushButton" name="vibrationButton"> |
| 2336 | <property name="minimumSize"> | 2333 | <property name="minimumSize"> |
| 2337 | <size> | 2334 | <size> |
| 2338 | <width>65</width> | 2335 | <width>68</width> |
| 2339 | <height>0</height> | 2336 | <height>0</height> |
| 2340 | </size> | 2337 | </size> |
| 2341 | </property> | 2338 | </property> |
| 2342 | <property name="maximumSize"> | 2339 | <property name="maximumSize"> |
| 2343 | <size> | 2340 | <size> |
| 2344 | <width>65</width> | 2341 | <width>68</width> |
| 2345 | <height>16777215</height> | 2342 | <height>16777215</height> |
| 2346 | </size> | 2343 | </size> |
| 2347 | </property> | 2344 | </property> |
| 2348 | <property name="suffix"> | 2345 | <property name="styleSheet"> |
| 2349 | <string>%</string> | 2346 | <string notr="true">min-width: 68px;</string> |
| 2350 | </property> | ||
| 2351 | <property name="minimum"> | ||
| 2352 | <number>1</number> | ||
| 2353 | </property> | ||
| 2354 | <property name="maximum"> | ||
| 2355 | <number>200</number> | ||
| 2356 | </property> | 2347 | </property> |
| 2357 | <property name="value"> | 2348 | <property name="text"> |
| 2358 | <number>100</number> | 2349 | <string>Configure</string> |
| 2359 | </property> | 2350 | </property> |
| 2360 | </widget> | 2351 | </widget> |
| 2361 | </item> | 2352 | </item> |
| @@ -2387,18 +2378,18 @@ | |||
| 2387 | <widget class="QPushButton" name="motionButton"> | 2378 | <widget class="QPushButton" name="motionButton"> |
| 2388 | <property name="minimumSize"> | 2379 | <property name="minimumSize"> |
| 2389 | <size> | 2380 | <size> |
| 2390 | <width>57</width> | 2381 | <width>68</width> |
| 2391 | <height>0</height> | 2382 | <height>0</height> |
| 2392 | </size> | 2383 | </size> |
| 2393 | </property> | 2384 | </property> |
| 2394 | <property name="maximumSize"> | 2385 | <property name="maximumSize"> |
| 2395 | <size> | 2386 | <size> |
| 2396 | <width>55</width> | 2387 | <width>68</width> |
| 2397 | <height>16777215</height> | 2388 | <height>16777215</height> |
| 2398 | </size> | 2389 | </size> |
| 2399 | </property> | 2390 | </property> |
| 2400 | <property name="styleSheet"> | 2391 | <property name="styleSheet"> |
| 2401 | <string notr="true">min-width: 55px;</string> | 2392 | <string notr="true">min-width: 68px;</string> |
| 2402 | </property> | 2393 | </property> |
| 2403 | <property name="text"> | 2394 | <property name="text"> |
| 2404 | <string>Configure</string> | 2395 | <string>Configure</string> |
| @@ -2411,7 +2402,7 @@ | |||
| 2411 | <item> | 2402 | <item> |
| 2412 | <widget class="QGroupBox" name="inputConfigGroup"> | 2403 | <widget class="QGroupBox" name="inputConfigGroup"> |
| 2413 | <property name="title"> | 2404 | <property name="title"> |
| 2414 | <string>Input Config</string> | 2405 | <string>Profiles</string> |
| 2415 | </property> | 2406 | </property> |
| 2416 | <layout class="QHBoxLayout" name="horizontalLayout_7"> | 2407 | <layout class="QHBoxLayout" name="horizontalLayout_7"> |
| 2417 | <property name="leftMargin"> | 2408 | <property name="leftMargin"> |
| @@ -2430,15 +2421,15 @@ | |||
| 2430 | <widget class="QPushButton" name="inputConfigButton"> | 2421 | <widget class="QPushButton" name="inputConfigButton"> |
| 2431 | <property name="maximumSize"> | 2422 | <property name="maximumSize"> |
| 2432 | <size> | 2423 | <size> |
| 2433 | <width>65</width> | 2424 | <width>68</width> |
| 2434 | <height>16777215</height> | 2425 | <height>16777215</height> |
| 2435 | </size> | 2426 | </size> |
| 2436 | </property> | 2427 | </property> |
| 2437 | <property name="styleSheet"> | 2428 | <property name="styleSheet"> |
| 2438 | <string notr="true">min-width: 55px;</string> | 2429 | <string notr="true">min-width: 68px;</string> |
| 2439 | </property> | 2430 | </property> |
| 2440 | <property name="text"> | 2431 | <property name="text"> |
| 2441 | <string>Open</string> | 2432 | <string>Create</string> |
| 2442 | </property> | 2433 | </property> |
| 2443 | </widget> | 2434 | </widget> |
| 2444 | </item> | 2435 | </item> |
| @@ -2657,16 +2648,6 @@ | |||
| 2657 | <signal>accepted()</signal> | 2648 | <signal>accepted()</signal> |
| 2658 | <receiver>QtControllerSelectorDialog</receiver> | 2649 | <receiver>QtControllerSelectorDialog</receiver> |
| 2659 | <slot>accept()</slot> | 2650 | <slot>accept()</slot> |
| 2660 | <hints> | ||
| 2661 | <hint type="sourcelabel"> | ||
| 2662 | <x>20</x> | ||
| 2663 | <y>20</y> | ||
| 2664 | </hint> | ||
| 2665 | <hint type="destinationlabel"> | ||
| 2666 | <x>20</x> | ||
| 2667 | <y>20</y> | ||
| 2668 | </hint> | ||
| 2669 | </hints> | ||
| 2670 | </connection> | 2651 | </connection> |
| 2671 | </connections> | 2652 | </connections> |
| 2672 | </ui> | 2653 | </ui> |
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index e38bc7a9a..d62b0efc2 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp | |||
| @@ -382,7 +382,12 @@ void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { | |||
| 382 | } | 382 | } |
| 383 | 383 | ||
| 384 | void GRenderWindow::mousePressEvent(QMouseEvent* event) { | 384 | void GRenderWindow::mousePressEvent(QMouseEvent* event) { |
| 385 | // touch input is handled in TouchBeginEvent | 385 | if (!Settings::values.touchscreen.enabled) { |
| 386 | input_subsystem->GetKeyboard()->PressKey(event->button()); | ||
| 387 | return; | ||
| 388 | } | ||
| 389 | |||
| 390 | // Touch input is handled in TouchBeginEvent | ||
| 386 | if (event->source() == Qt::MouseEventSynthesizedBySystem) { | 391 | if (event->source() == Qt::MouseEventSynthesizedBySystem) { |
| 387 | return; | 392 | return; |
| 388 | } | 393 | } |
| @@ -398,7 +403,7 @@ void GRenderWindow::mousePressEvent(QMouseEvent* event) { | |||
| 398 | } | 403 | } |
| 399 | 404 | ||
| 400 | void GRenderWindow::mouseMoveEvent(QMouseEvent* event) { | 405 | void GRenderWindow::mouseMoveEvent(QMouseEvent* event) { |
| 401 | // touch input is handled in TouchUpdateEvent | 406 | // Touch input is handled in TouchUpdateEvent |
| 402 | if (event->source() == Qt::MouseEventSynthesizedBySystem) { | 407 | if (event->source() == Qt::MouseEventSynthesizedBySystem) { |
| 403 | return; | 408 | return; |
| 404 | } | 409 | } |
| @@ -411,7 +416,12 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) { | |||
| 411 | } | 416 | } |
| 412 | 417 | ||
| 413 | void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) { | 418 | void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) { |
| 414 | // touch input is handled in TouchEndEvent | 419 | if (!Settings::values.touchscreen.enabled) { |
| 420 | input_subsystem->GetKeyboard()->ReleaseKey(event->button()); | ||
| 421 | return; | ||
| 422 | } | ||
| 423 | |||
| 424 | // Touch input is handled in TouchEndEvent | ||
| 415 | if (event->source() == Qt::MouseEventSynthesizedBySystem) { | 425 | if (event->source() == Qt::MouseEventSynthesizedBySystem) { |
| 416 | return; | 426 | return; |
| 417 | } | 427 | } |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 1ce62e4a6..6fa842cd5 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <array> | 5 | #include <array> |
| 6 | #include <QKeySequence> | 6 | #include <QKeySequence> |
| 7 | #include <QSettings> | 7 | #include <QSettings> |
| 8 | #include "common/common_paths.h" | ||
| 8 | #include "common/file_util.h" | 9 | #include "common/file_util.h" |
| 9 | #include "core/hle/service/acc/profile_manager.h" | 10 | #include "core/hle/service/acc/profile_manager.h" |
| 10 | #include "core/hle/service/hid/controllers/npad.h" | 11 | #include "core/hle/service/hid/controllers/npad.h" |
| @@ -14,14 +15,10 @@ | |||
| 14 | 15 | ||
| 15 | namespace FS = Common::FS; | 16 | namespace FS = Common::FS; |
| 16 | 17 | ||
| 17 | Config::Config(const std::string& config_file, bool is_global) { | 18 | Config::Config(const std::string& config_name, ConfigType config_type) : type(config_type) { |
| 18 | // TODO: Don't hardcode the path; let the frontend decide where to put the config files. | 19 | global = config_type == ConfigType::GlobalConfig; |
| 19 | qt_config_loc = FS::GetUserPath(FS::UserPath::ConfigDir) + config_file; | 20 | |
| 20 | FS::CreateFullPath(qt_config_loc); | 21 | Initialize(config_name); |
| 21 | qt_config = | ||
| 22 | std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), QSettings::IniFormat); | ||
| 23 | global = is_global; | ||
| 24 | Reload(); | ||
| 25 | } | 22 | } |
| 26 | 23 | ||
| 27 | Config::~Config() { | 24 | Config::~Config() { |
| @@ -242,84 +239,152 @@ const std::array<UISettings::Shortcut, 16> Config::default_hotkeys{{ | |||
| 242 | }}; | 239 | }}; |
| 243 | // clang-format on | 240 | // clang-format on |
| 244 | 241 | ||
| 245 | void Config::ReadPlayerValues() { | 242 | void Config::Initialize(const std::string& config_name) { |
| 246 | for (std::size_t p = 0; p < Settings::values.players.size(); ++p) { | 243 | switch (type) { |
| 247 | auto& player = Settings::values.players[p]; | 244 | case ConfigType::GlobalConfig: |
| 245 | qt_config_loc = fmt::format("{}" DIR_SEP "{}.ini", FS::GetUserPath(FS::UserPath::ConfigDir), | ||
| 246 | config_name); | ||
| 247 | FS::CreateFullPath(qt_config_loc); | ||
| 248 | qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), | ||
| 249 | QSettings::IniFormat); | ||
| 250 | Reload(); | ||
| 251 | break; | ||
| 252 | case ConfigType::PerGameConfig: | ||
| 253 | qt_config_loc = fmt::format("{}custom" DIR_SEP "{}.ini", | ||
| 254 | FS::GetUserPath(FS::UserPath::ConfigDir), config_name); | ||
| 255 | FS::CreateFullPath(qt_config_loc); | ||
| 256 | qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), | ||
| 257 | QSettings::IniFormat); | ||
| 258 | Reload(); | ||
| 259 | break; | ||
| 260 | case ConfigType::InputProfile: | ||
| 261 | qt_config_loc = fmt::format("{}input" DIR_SEP "{}.ini", | ||
| 262 | FS::GetUserPath(FS::UserPath::ConfigDir), config_name); | ||
| 263 | FS::CreateFullPath(qt_config_loc); | ||
| 264 | qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), | ||
| 265 | QSettings::IniFormat); | ||
| 266 | break; | ||
| 267 | } | ||
| 268 | } | ||
| 269 | |||
| 270 | void Config::ReadPlayerValue(std::size_t player_index) { | ||
| 271 | const QString player_prefix = [this, player_index] { | ||
| 272 | if (type == ConfigType::InputProfile) { | ||
| 273 | return QString{}; | ||
| 274 | } else { | ||
| 275 | return QStringLiteral("player_%1_").arg(player_index); | ||
| 276 | } | ||
| 277 | }(); | ||
| 278 | |||
| 279 | auto& player = Settings::values.players.GetValue()[player_index]; | ||
| 280 | |||
| 281 | if (player_prefix.isEmpty()) { | ||
| 282 | const auto controller = static_cast<Settings::ControllerType>( | ||
| 283 | qt_config | ||
| 284 | ->value(QStringLiteral("%1type").arg(player_prefix), | ||
| 285 | static_cast<u8>(Settings::ControllerType::ProController)) | ||
| 286 | .toUInt()); | ||
| 248 | 287 | ||
| 288 | if (controller == Settings::ControllerType::LeftJoycon || | ||
| 289 | controller == Settings::ControllerType::RightJoycon) { | ||
| 290 | player.controller_type = controller; | ||
| 291 | } | ||
| 292 | } else { | ||
| 249 | player.connected = | 293 | player.connected = |
| 250 | ReadSetting(QStringLiteral("player_%1_connected").arg(p), false).toBool(); | 294 | ReadSetting(QStringLiteral("%1connected").arg(player_prefix), player_index == 0) |
| 295 | .toBool(); | ||
| 251 | 296 | ||
| 252 | player.controller_type = static_cast<Settings::ControllerType>( | 297 | player.controller_type = static_cast<Settings::ControllerType>( |
| 253 | qt_config | 298 | qt_config |
| 254 | ->value(QStringLiteral("player_%1_type").arg(p), | 299 | ->value(QStringLiteral("%1type").arg(player_prefix), |
| 255 | static_cast<u8>(Settings::ControllerType::ProController)) | 300 | static_cast<u8>(Settings::ControllerType::ProController)) |
| 256 | .toUInt()); | 301 | .toUInt()); |
| 257 | 302 | ||
| 303 | player.vibration_enabled = | ||
| 304 | qt_config->value(QStringLiteral("%1vibration_enabled").arg(player_prefix), true) | ||
| 305 | .toBool(); | ||
| 306 | |||
| 307 | player.vibration_strength = | ||
| 308 | qt_config->value(QStringLiteral("%1vibration_strength").arg(player_prefix), 100) | ||
| 309 | .toInt(); | ||
| 310 | |||
| 258 | player.body_color_left = qt_config | 311 | player.body_color_left = qt_config |
| 259 | ->value(QStringLiteral("player_%1_body_color_left").arg(p), | 312 | ->value(QStringLiteral("%1body_color_left").arg(player_prefix), |
| 260 | Settings::JOYCON_BODY_NEON_BLUE) | 313 | Settings::JOYCON_BODY_NEON_BLUE) |
| 261 | .toUInt(); | 314 | .toUInt(); |
| 262 | player.body_color_right = qt_config | 315 | player.body_color_right = |
| 263 | ->value(QStringLiteral("player_%1_body_color_right").arg(p), | 316 | qt_config |
| 264 | Settings::JOYCON_BODY_NEON_RED) | 317 | ->value(QStringLiteral("%1body_color_right").arg(player_prefix), |
| 265 | .toUInt(); | 318 | Settings::JOYCON_BODY_NEON_RED) |
| 266 | player.button_color_left = qt_config | 319 | .toUInt(); |
| 267 | ->value(QStringLiteral("player_%1_button_color_left").arg(p), | 320 | player.button_color_left = |
| 268 | Settings::JOYCON_BUTTONS_NEON_BLUE) | 321 | qt_config |
| 269 | .toUInt(); | 322 | ->value(QStringLiteral("%1button_color_left").arg(player_prefix), |
| 323 | Settings::JOYCON_BUTTONS_NEON_BLUE) | ||
| 324 | .toUInt(); | ||
| 270 | player.button_color_right = | 325 | player.button_color_right = |
| 271 | qt_config | 326 | qt_config |
| 272 | ->value(QStringLiteral("player_%1_button_color_right").arg(p), | 327 | ->value(QStringLiteral("%1button_color_right").arg(player_prefix), |
| 273 | Settings::JOYCON_BUTTONS_NEON_RED) | 328 | Settings::JOYCON_BUTTONS_NEON_RED) |
| 274 | .toUInt(); | 329 | .toUInt(); |
| 330 | } | ||
| 275 | 331 | ||
| 276 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | 332 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { |
| 277 | const std::string default_param = | 333 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); |
| 278 | InputCommon::GenerateKeyboardParam(default_buttons[i]); | 334 | auto& player_buttons = player.buttons[i]; |
| 279 | auto& player_buttons = player.buttons[i]; | 335 | |
| 280 | 336 | player_buttons = qt_config | |
| 281 | player_buttons = qt_config | 337 | ->value(QStringLiteral("%1").arg(player_prefix) + |
| 282 | ->value(QStringLiteral("player_%1_").arg(p) + | 338 | QString::fromUtf8(Settings::NativeButton::mapping[i]), |
| 283 | QString::fromUtf8(Settings::NativeButton::mapping[i]), | 339 | QString::fromStdString(default_param)) |
| 284 | QString::fromStdString(default_param)) | 340 | .toString() |
| 285 | .toString() | 341 | .toStdString(); |
| 286 | .toStdString(); | 342 | if (player_buttons.empty()) { |
| 287 | if (player_buttons.empty()) { | 343 | player_buttons = default_param; |
| 288 | player_buttons = default_param; | ||
| 289 | } | ||
| 290 | } | 344 | } |
| 345 | } | ||
| 291 | 346 | ||
| 292 | for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { | 347 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { |
| 293 | const std::string default_param = | 348 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( |
| 294 | InputCommon::GenerateKeyboardParam(default_motions[i]); | 349 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], |
| 295 | auto& player_motions = player.motions[i]; | 350 | default_analogs[i][3], default_stick_mod[i], 0.5f); |
| 296 | 351 | auto& player_analogs = player.analogs[i]; | |
| 297 | player_motions = qt_config | 352 | |
| 298 | ->value(QStringLiteral("player_%1_").arg(p) + | 353 | player_analogs = qt_config |
| 299 | QString::fromUtf8(Settings::NativeMotion::mapping[i]), | 354 | ->value(QStringLiteral("%1").arg(player_prefix) + |
| 300 | QString::fromStdString(default_param)) | 355 | QString::fromUtf8(Settings::NativeAnalog::mapping[i]), |
| 301 | .toString() | 356 | QString::fromStdString(default_param)) |
| 302 | .toStdString(); | 357 | .toString() |
| 303 | if (player_motions.empty()) { | 358 | .toStdString(); |
| 304 | player_motions = default_param; | 359 | if (player_analogs.empty()) { |
| 305 | } | 360 | player_analogs = default_param; |
| 306 | } | 361 | } |
| 362 | } | ||
| 307 | 363 | ||
| 308 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | 364 | for (int i = 0; i < Settings::NativeVibration::NumVibrations; ++i) { |
| 309 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | 365 | auto& player_vibrations = player.vibrations[i]; |
| 310 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | 366 | |
| 311 | default_analogs[i][3], default_stick_mod[i], 0.5f); | 367 | player_vibrations = |
| 312 | auto& player_analogs = player.analogs[i]; | 368 | qt_config |
| 313 | 369 | ->value(QStringLiteral("%1").arg(player_prefix) + | |
| 314 | player_analogs = qt_config | 370 | QString::fromUtf8(Settings::NativeVibration::mapping[i]), |
| 315 | ->value(QStringLiteral("player_%1_").arg(p) + | 371 | QString{}) |
| 316 | QString::fromUtf8(Settings::NativeAnalog::mapping[i]), | 372 | .toString() |
| 317 | QString::fromStdString(default_param)) | 373 | .toStdString(); |
| 318 | .toString() | 374 | } |
| 319 | .toStdString(); | 375 | |
| 320 | if (player_analogs.empty()) { | 376 | for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { |
| 321 | player_analogs = default_param; | 377 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); |
| 322 | } | 378 | auto& player_motions = player.motions[i]; |
| 379 | |||
| 380 | player_motions = qt_config | ||
| 381 | ->value(QStringLiteral("%1").arg(player_prefix) + | ||
| 382 | QString::fromUtf8(Settings::NativeMotion::mapping[i]), | ||
| 383 | QString::fromStdString(default_param)) | ||
| 384 | .toString() | ||
| 385 | .toStdString(); | ||
| 386 | if (player_motions.empty()) { | ||
| 387 | player_motions = default_param; | ||
| 323 | } | 388 | } |
| 324 | } | 389 | } |
| 325 | } | 390 | } |
| @@ -436,18 +501,21 @@ void Config::ReadAudioValues() { | |||
| 436 | void Config::ReadControlValues() { | 501 | void Config::ReadControlValues() { |
| 437 | qt_config->beginGroup(QStringLiteral("Controls")); | 502 | qt_config->beginGroup(QStringLiteral("Controls")); |
| 438 | 503 | ||
| 439 | ReadPlayerValues(); | 504 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { |
| 505 | ReadPlayerValue(p); | ||
| 506 | } | ||
| 440 | ReadDebugValues(); | 507 | ReadDebugValues(); |
| 441 | ReadKeyboardValues(); | 508 | ReadKeyboardValues(); |
| 442 | ReadMouseValues(); | 509 | ReadMouseValues(); |
| 443 | ReadTouchscreenValues(); | 510 | ReadTouchscreenValues(); |
| 444 | ReadMotionTouchValues(); | 511 | ReadMotionTouchValues(); |
| 445 | 512 | ||
| 446 | Settings::values.vibration_enabled = | 513 | ReadSettingGlobal(Settings::values.use_docked_mode, QStringLiteral("use_docked_mode"), false); |
| 447 | ReadSetting(QStringLiteral("vibration_enabled"), true).toBool(); | 514 | ReadSettingGlobal(Settings::values.vibration_enabled, QStringLiteral("vibration_enabled"), |
| 448 | Settings::values.motion_enabled = ReadSetting(QStringLiteral("motion_enabled"), true).toBool(); | 515 | true); |
| 449 | Settings::values.use_docked_mode = | 516 | ReadSettingGlobal(Settings::values.enable_accurate_vibrations, |
| 450 | ReadSetting(QStringLiteral("use_docked_mode"), false).toBool(); | 517 | QStringLiteral("enable_accurate_vibrations"), false); |
| 518 | ReadSettingGlobal(Settings::values.motion_enabled, QStringLiteral("motion_enabled"), true); | ||
| 451 | 519 | ||
| 452 | qt_config->endGroup(); | 520 | qt_config->endGroup(); |
| 453 | } | 521 | } |
| @@ -920,49 +988,64 @@ void Config::ReadValues() { | |||
| 920 | ReadSystemValues(); | 988 | ReadSystemValues(); |
| 921 | } | 989 | } |
| 922 | 990 | ||
| 923 | void Config::SavePlayerValues() { | 991 | void Config::SavePlayerValue(std::size_t player_index) { |
| 924 | for (std::size_t p = 0; p < Settings::values.players.size(); ++p) { | 992 | const QString player_prefix = [this, player_index] { |
| 925 | const auto& player = Settings::values.players[p]; | 993 | if (type == ConfigType::InputProfile) { |
| 994 | return QString{}; | ||
| 995 | } else { | ||
| 996 | return QStringLiteral("player_%1_").arg(player_index); | ||
| 997 | } | ||
| 998 | }(); | ||
| 926 | 999 | ||
| 927 | WriteSetting(QStringLiteral("player_%1_connected").arg(p), player.connected, false); | 1000 | const auto& player = Settings::values.players.GetValue()[player_index]; |
| 928 | WriteSetting(QStringLiteral("player_%1_type").arg(p), | ||
| 929 | static_cast<u8>(player.controller_type), | ||
| 930 | static_cast<u8>(Settings::ControllerType::ProController)); | ||
| 931 | 1001 | ||
| 932 | WriteSetting(QStringLiteral("player_%1_body_color_left").arg(p), player.body_color_left, | 1002 | WriteSetting(QStringLiteral("%1type").arg(player_prefix), |
| 1003 | static_cast<u8>(player.controller_type), | ||
| 1004 | static_cast<u8>(Settings::ControllerType::ProController)); | ||
| 1005 | |||
| 1006 | if (!player_prefix.isEmpty()) { | ||
| 1007 | WriteSetting(QStringLiteral("%1connected").arg(player_prefix), player.connected, false); | ||
| 1008 | WriteSetting(QStringLiteral("%1vibration_enabled").arg(player_prefix), | ||
| 1009 | player.vibration_enabled, true); | ||
| 1010 | WriteSetting(QStringLiteral("%1vibration_strength").arg(player_prefix), | ||
| 1011 | player.vibration_strength, 100); | ||
| 1012 | WriteSetting(QStringLiteral("%1body_color_left").arg(player_prefix), player.body_color_left, | ||
| 933 | Settings::JOYCON_BODY_NEON_BLUE); | 1013 | Settings::JOYCON_BODY_NEON_BLUE); |
| 934 | WriteSetting(QStringLiteral("player_%1_body_color_right").arg(p), player.body_color_right, | 1014 | WriteSetting(QStringLiteral("%1body_color_right").arg(player_prefix), |
| 935 | Settings::JOYCON_BODY_NEON_RED); | 1015 | player.body_color_right, Settings::JOYCON_BODY_NEON_RED); |
| 936 | WriteSetting(QStringLiteral("player_%1_button_color_left").arg(p), player.button_color_left, | 1016 | WriteSetting(QStringLiteral("%1button_color_left").arg(player_prefix), |
| 937 | Settings::JOYCON_BUTTONS_NEON_BLUE); | 1017 | player.button_color_left, Settings::JOYCON_BUTTONS_NEON_BLUE); |
| 938 | WriteSetting(QStringLiteral("player_%1_button_color_right").arg(p), | 1018 | WriteSetting(QStringLiteral("%1button_color_right").arg(player_prefix), |
| 939 | player.button_color_right, Settings::JOYCON_BUTTONS_NEON_RED); | 1019 | player.button_color_right, Settings::JOYCON_BUTTONS_NEON_RED); |
| 1020 | } | ||
| 940 | 1021 | ||
| 941 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | 1022 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { |
| 942 | const std::string default_param = | 1023 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); |
| 943 | InputCommon::GenerateKeyboardParam(default_buttons[i]); | 1024 | WriteSetting(QStringLiteral("%1").arg(player_prefix) + |
| 944 | WriteSetting(QStringLiteral("player_%1_").arg(p) + | 1025 | QString::fromStdString(Settings::NativeButton::mapping[i]), |
| 945 | QString::fromStdString(Settings::NativeButton::mapping[i]), | 1026 | QString::fromStdString(player.buttons[i]), |
| 946 | QString::fromStdString(player.buttons[i]), | 1027 | QString::fromStdString(default_param)); |
| 947 | QString::fromStdString(default_param)); | 1028 | } |
| 948 | } | 1029 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { |
| 949 | for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { | 1030 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( |
| 950 | const std::string default_param = | 1031 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], |
| 951 | InputCommon::GenerateKeyboardParam(default_motions[i]); | 1032 | default_analogs[i][3], default_stick_mod[i], 0.5f); |
| 952 | WriteSetting(QStringLiteral("player_%1_").arg(p) + | 1033 | WriteSetting(QStringLiteral("%1").arg(player_prefix) + |
| 953 | QString::fromStdString(Settings::NativeMotion::mapping[i]), | 1034 | QString::fromStdString(Settings::NativeAnalog::mapping[i]), |
| 954 | QString::fromStdString(player.motions[i]), | 1035 | QString::fromStdString(player.analogs[i]), |
| 955 | QString::fromStdString(default_param)); | 1036 | QString::fromStdString(default_param)); |
| 956 | } | 1037 | } |
| 957 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | 1038 | for (int i = 0; i < Settings::NativeVibration::NumVibrations; ++i) { |
| 958 | const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | 1039 | WriteSetting(QStringLiteral("%1").arg(player_prefix) + |
| 959 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | 1040 | QString::fromStdString(Settings::NativeVibration::mapping[i]), |
| 960 | default_analogs[i][3], default_stick_mod[i], 0.5f); | 1041 | QString::fromStdString(player.vibrations[i]), QString{}); |
| 961 | WriteSetting(QStringLiteral("player_%1_").arg(p) + | 1042 | } |
| 962 | QString::fromStdString(Settings::NativeAnalog::mapping[i]), | 1043 | for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) { |
| 963 | QString::fromStdString(player.analogs[i]), | 1044 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]); |
| 964 | QString::fromStdString(default_param)); | 1045 | WriteSetting(QStringLiteral("%1").arg(player_prefix) + |
| 965 | } | 1046 | QString::fromStdString(Settings::NativeMotion::mapping[i]), |
| 1047 | QString::fromStdString(player.motions[i]), | ||
| 1048 | QString::fromStdString(default_param)); | ||
| 966 | } | 1049 | } |
| 967 | } | 1050 | } |
| 968 | 1051 | ||
| @@ -1087,14 +1170,20 @@ void Config::SaveAudioValues() { | |||
| 1087 | void Config::SaveControlValues() { | 1170 | void Config::SaveControlValues() { |
| 1088 | qt_config->beginGroup(QStringLiteral("Controls")); | 1171 | qt_config->beginGroup(QStringLiteral("Controls")); |
| 1089 | 1172 | ||
| 1090 | SavePlayerValues(); | 1173 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { |
| 1174 | SavePlayerValue(p); | ||
| 1175 | } | ||
| 1091 | SaveDebugValues(); | 1176 | SaveDebugValues(); |
| 1092 | SaveMouseValues(); | 1177 | SaveMouseValues(); |
| 1093 | SaveTouchscreenValues(); | 1178 | SaveTouchscreenValues(); |
| 1094 | SaveMotionTouchValues(); | 1179 | SaveMotionTouchValues(); |
| 1095 | 1180 | ||
| 1096 | WriteSetting(QStringLiteral("vibration_enabled"), Settings::values.vibration_enabled, true); | 1181 | WriteSettingGlobal(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false); |
| 1097 | WriteSetting(QStringLiteral("motion_enabled"), Settings::values.motion_enabled, true); | 1182 | WriteSettingGlobal(QStringLiteral("vibration_enabled"), Settings::values.vibration_enabled, |
| 1183 | true); | ||
| 1184 | WriteSettingGlobal(QStringLiteral("enable_accurate_vibrations"), | ||
| 1185 | Settings::values.enable_accurate_vibrations, false); | ||
| 1186 | WriteSettingGlobal(QStringLiteral("motion_enabled"), Settings::values.motion_enabled, true); | ||
| 1098 | WriteSetting(QStringLiteral("motion_device"), | 1187 | WriteSetting(QStringLiteral("motion_device"), |
| 1099 | QString::fromStdString(Settings::values.motion_device), | 1188 | QString::fromStdString(Settings::values.motion_device), |
| 1100 | QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01")); | 1189 | QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01")); |
| @@ -1102,7 +1191,6 @@ void Config::SaveControlValues() { | |||
| 1102 | QString::fromStdString(Settings::values.touch_device), | 1191 | QString::fromStdString(Settings::values.touch_device), |
| 1103 | QStringLiteral("engine:emu_window")); | 1192 | QStringLiteral("engine:emu_window")); |
| 1104 | WriteSetting(QStringLiteral("keyboard_enabled"), Settings::values.keyboard_enabled, false); | 1193 | WriteSetting(QStringLiteral("keyboard_enabled"), Settings::values.keyboard_enabled, false); |
| 1105 | WriteSetting(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false); | ||
| 1106 | 1194 | ||
| 1107 | qt_config->endGroup(); | 1195 | qt_config->endGroup(); |
| 1108 | } | 1196 | } |
| @@ -1515,3 +1603,19 @@ void Config::Save() { | |||
| 1515 | Settings::Sanitize(); | 1603 | Settings::Sanitize(); |
| 1516 | SaveValues(); | 1604 | SaveValues(); |
| 1517 | } | 1605 | } |
| 1606 | |||
| 1607 | void Config::ReadControlPlayerValue(std::size_t player_index) { | ||
| 1608 | qt_config->beginGroup(QStringLiteral("Controls")); | ||
| 1609 | ReadPlayerValue(player_index); | ||
| 1610 | qt_config->endGroup(); | ||
| 1611 | } | ||
| 1612 | |||
| 1613 | void Config::SaveControlPlayerValue(std::size_t player_index) { | ||
| 1614 | qt_config->beginGroup(QStringLiteral("Controls")); | ||
| 1615 | SavePlayerValue(player_index); | ||
| 1616 | qt_config->endGroup(); | ||
| 1617 | } | ||
| 1618 | |||
| 1619 | const std::string& Config::GetConfigFilePath() const { | ||
| 1620 | return qt_config_loc; | ||
| 1621 | } | ||
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index 5d8e45d78..8a600e19d 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h | |||
| @@ -16,12 +16,24 @@ class QSettings; | |||
| 16 | 16 | ||
| 17 | class Config { | 17 | class Config { |
| 18 | public: | 18 | public: |
| 19 | explicit Config(const std::string& config_loc = "qt-config.ini", bool is_global = true); | 19 | enum class ConfigType { |
| 20 | GlobalConfig, | ||
| 21 | PerGameConfig, | ||
| 22 | InputProfile, | ||
| 23 | }; | ||
| 24 | |||
| 25 | explicit Config(const std::string& config_name = "qt-config", | ||
| 26 | ConfigType config_type = ConfigType::GlobalConfig); | ||
| 20 | ~Config(); | 27 | ~Config(); |
| 21 | 28 | ||
| 22 | void Reload(); | 29 | void Reload(); |
| 23 | void Save(); | 30 | void Save(); |
| 24 | 31 | ||
| 32 | void ReadControlPlayerValue(std::size_t player_index); | ||
| 33 | void SaveControlPlayerValue(std::size_t player_index); | ||
| 34 | |||
| 35 | const std::string& GetConfigFilePath() const; | ||
| 36 | |||
| 25 | static const std::array<int, Settings::NativeButton::NumButtons> default_buttons; | 37 | static const std::array<int, Settings::NativeButton::NumButtons> default_buttons; |
| 26 | static const std::array<int, Settings::NativeMotion::NumMotions> default_motions; | 38 | static const std::array<int, Settings::NativeMotion::NumMotions> default_motions; |
| 27 | static const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> default_analogs; | 39 | static const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> default_analogs; |
| @@ -33,8 +45,10 @@ public: | |||
| 33 | static const std::array<UISettings::Shortcut, 16> default_hotkeys; | 45 | static const std::array<UISettings::Shortcut, 16> default_hotkeys; |
| 34 | 46 | ||
| 35 | private: | 47 | private: |
| 48 | void Initialize(const std::string& config_name); | ||
| 49 | |||
| 36 | void ReadValues(); | 50 | void ReadValues(); |
| 37 | void ReadPlayerValues(); | 51 | void ReadPlayerValue(std::size_t player_index); |
| 38 | void ReadDebugValues(); | 52 | void ReadDebugValues(); |
| 39 | void ReadKeyboardValues(); | 53 | void ReadKeyboardValues(); |
| 40 | void ReadMouseValues(); | 54 | void ReadMouseValues(); |
| @@ -62,7 +76,7 @@ private: | |||
| 62 | void ReadWebServiceValues(); | 76 | void ReadWebServiceValues(); |
| 63 | 77 | ||
| 64 | void SaveValues(); | 78 | void SaveValues(); |
| 65 | void SavePlayerValues(); | 79 | void SavePlayerValue(std::size_t player_index); |
| 66 | void SaveDebugValues(); | 80 | void SaveDebugValues(); |
| 67 | void SaveMouseValues(); | 81 | void SaveMouseValues(); |
| 68 | void SaveTouchscreenValues(); | 82 | void SaveTouchscreenValues(); |
| @@ -111,9 +125,9 @@ private: | |||
| 111 | void WriteSettingGlobal(const QString& name, const QVariant& value, bool use_global, | 125 | void WriteSettingGlobal(const QString& name, const QVariant& value, bool use_global, |
| 112 | const QVariant& default_value); | 126 | const QVariant& default_value); |
| 113 | 127 | ||
| 128 | ConfigType type; | ||
| 114 | std::unique_ptr<QSettings> qt_config; | 129 | std::unique_ptr<QSettings> qt_config; |
| 115 | std::string qt_config_loc; | 130 | std::string qt_config_loc; |
| 116 | |||
| 117 | bool global; | 131 | bool global; |
| 118 | }; | 132 | }; |
| 119 | 133 | ||
diff --git a/src/yuzu/configuration/configure.ui b/src/yuzu/configuration/configure.ui index fcf42cdcb..f92c3aff3 100644 --- a/src/yuzu/configuration/configure.ui +++ b/src/yuzu/configuration/configure.ui | |||
| @@ -275,32 +275,12 @@ | |||
| 275 | <signal>accepted()</signal> | 275 | <signal>accepted()</signal> |
| 276 | <receiver>ConfigureDialog</receiver> | 276 | <receiver>ConfigureDialog</receiver> |
| 277 | <slot>accept()</slot> | 277 | <slot>accept()</slot> |
| 278 | <hints> | ||
| 279 | <hint type="sourcelabel"> | ||
| 280 | <x>220</x> | ||
| 281 | <y>380</y> | ||
| 282 | </hint> | ||
| 283 | <hint type="destinationlabel"> | ||
| 284 | <x>220</x> | ||
| 285 | <y>200</y> | ||
| 286 | </hint> | ||
| 287 | </hints> | ||
| 288 | </connection> | 278 | </connection> |
| 289 | <connection> | 279 | <connection> |
| 290 | <sender>buttonBox</sender> | 280 | <sender>buttonBox</sender> |
| 291 | <signal>rejected()</signal> | 281 | <signal>rejected()</signal> |
| 292 | <receiver>ConfigureDialog</receiver> | 282 | <receiver>ConfigureDialog</receiver> |
| 293 | <slot>reject()</slot> | 283 | <slot>reject()</slot> |
| 294 | <hints> | ||
| 295 | <hint type="sourcelabel"> | ||
| 296 | <x>220</x> | ||
| 297 | <y>380</y> | ||
| 298 | </hint> | ||
| 299 | <hint type="destinationlabel"> | ||
| 300 | <x>220</x> | ||
| 301 | <y>200</y> | ||
| 302 | </hint> | ||
| 303 | </hints> | ||
| 304 | </connection> | 284 | </connection> |
| 305 | </connections> | 285 | </connections> |
| 306 | </ui> | 286 | </ui> |
diff --git a/src/yuzu/configuration/configure_debug_controller.cpp b/src/yuzu/configuration/configure_debug_controller.cpp index 0097c9a29..a878ef9c6 100644 --- a/src/yuzu/configuration/configure_debug_controller.cpp +++ b/src/yuzu/configuration/configure_debug_controller.cpp | |||
| @@ -4,11 +4,14 @@ | |||
| 4 | 4 | ||
| 5 | #include "ui_configure_debug_controller.h" | 5 | #include "ui_configure_debug_controller.h" |
| 6 | #include "yuzu/configuration/configure_debug_controller.h" | 6 | #include "yuzu/configuration/configure_debug_controller.h" |
| 7 | #include "yuzu/configuration/configure_input_player.h" | ||
| 7 | 8 | ||
| 8 | ConfigureDebugController::ConfigureDebugController(QWidget* parent, | 9 | ConfigureDebugController::ConfigureDebugController(QWidget* parent, |
| 9 | InputCommon::InputSubsystem* input_subsystem) | 10 | InputCommon::InputSubsystem* input_subsystem, |
| 11 | InputProfiles* profiles) | ||
| 10 | : QDialog(parent), ui(std::make_unique<Ui::ConfigureDebugController>()), | 12 | : QDialog(parent), ui(std::make_unique<Ui::ConfigureDebugController>()), |
| 11 | debug_controller(new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, true)) { | 13 | debug_controller( |
| 14 | new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, profiles, true)) { | ||
| 12 | ui->setupUi(this); | 15 | ui->setupUi(this); |
| 13 | 16 | ||
| 14 | ui->controllerLayout->addWidget(debug_controller); | 17 | ui->controllerLayout->addWidget(debug_controller); |
diff --git a/src/yuzu/configuration/configure_debug_controller.h b/src/yuzu/configuration/configure_debug_controller.h index 34dcf705f..b4f53fad5 100644 --- a/src/yuzu/configuration/configure_debug_controller.h +++ b/src/yuzu/configuration/configure_debug_controller.h | |||
| @@ -6,10 +6,13 @@ | |||
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <QDialog> | 8 | #include <QDialog> |
| 9 | #include "yuzu/configuration/configure_input_player.h" | ||
| 10 | 9 | ||
| 11 | class QPushButton; | 10 | class QPushButton; |
| 12 | 11 | ||
| 12 | class ConfigureInputPlayer; | ||
| 13 | |||
| 14 | class InputProfiles; | ||
| 15 | |||
| 13 | namespace InputCommon { | 16 | namespace InputCommon { |
| 14 | class InputSubsystem; | 17 | class InputSubsystem; |
| 15 | } | 18 | } |
| @@ -22,8 +25,8 @@ class ConfigureDebugController : public QDialog { | |||
| 22 | Q_OBJECT | 25 | Q_OBJECT |
| 23 | 26 | ||
| 24 | public: | 27 | public: |
| 25 | explicit ConfigureDebugController(QWidget* parent, | 28 | explicit ConfigureDebugController(QWidget* parent, InputCommon::InputSubsystem* input_subsystem, |
| 26 | InputCommon::InputSubsystem* input_subsystem); | 29 | InputProfiles* profiles); |
| 27 | ~ConfigureDebugController() override; | 30 | ~ConfigureDebugController() override; |
| 28 | 31 | ||
| 29 | void ApplyConfiguration(); | 32 | void ApplyConfiguration(); |
diff --git a/src/yuzu/configuration/configure_debug_controller.ui b/src/yuzu/configuration/configure_debug_controller.ui index a95ed50ff..7b7e6582c 100644 --- a/src/yuzu/configuration/configure_debug_controller.ui +++ b/src/yuzu/configuration/configure_debug_controller.ui | |||
| @@ -66,32 +66,12 @@ | |||
| 66 | <signal>accepted()</signal> | 66 | <signal>accepted()</signal> |
| 67 | <receiver>ConfigureDebugController</receiver> | 67 | <receiver>ConfigureDebugController</receiver> |
| 68 | <slot>accept()</slot> | 68 | <slot>accept()</slot> |
| 69 | <hints> | ||
| 70 | <hint type="sourcelabel"> | ||
| 71 | <x>140</x> | ||
| 72 | <y>318</y> | ||
| 73 | </hint> | ||
| 74 | <hint type="destinationlabel"> | ||
| 75 | <x>140</x> | ||
| 76 | <y>169</y> | ||
| 77 | </hint> | ||
| 78 | </hints> | ||
| 79 | </connection> | 69 | </connection> |
| 80 | <connection> | 70 | <connection> |
| 81 | <sender>buttonBox</sender> | 71 | <sender>buttonBox</sender> |
| 82 | <signal>rejected()</signal> | 72 | <signal>rejected()</signal> |
| 83 | <receiver>ConfigureDebugController</receiver> | 73 | <receiver>ConfigureDebugController</receiver> |
| 84 | <slot>reject()</slot> | 74 | <slot>reject()</slot> |
| 85 | <hints> | ||
| 86 | <hint type="sourcelabel"> | ||
| 87 | <x>140</x> | ||
| 88 | <y>318</y> | ||
| 89 | </hint> | ||
| 90 | <hint type="destinationlabel"> | ||
| 91 | <x>140</x> | ||
| 92 | <y>169</y> | ||
| 93 | </hint> | ||
| 94 | </hints> | ||
| 95 | </connection> | 75 | </connection> |
| 96 | </connections> | 76 | </connections> |
| 97 | </ui> | 77 | </ui> |
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 2725fcb2b..d9009091b 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp | |||
| @@ -23,6 +23,8 @@ | |||
| 23 | #include "yuzu/configuration/configure_motion_touch.h" | 23 | #include "yuzu/configuration/configure_motion_touch.h" |
| 24 | #include "yuzu/configuration/configure_mouse_advanced.h" | 24 | #include "yuzu/configuration/configure_mouse_advanced.h" |
| 25 | #include "yuzu/configuration/configure_touchscreen_advanced.h" | 25 | #include "yuzu/configuration/configure_touchscreen_advanced.h" |
| 26 | #include "yuzu/configuration/configure_vibration.h" | ||
| 27 | #include "yuzu/configuration/input_profiles.h" | ||
| 26 | 28 | ||
| 27 | namespace { | 29 | namespace { |
| 28 | template <typename Dialog, typename... Args> | 30 | template <typename Dialog, typename... Args> |
| @@ -64,7 +66,8 @@ void OnDockedModeChanged(bool last_state, bool new_state) { | |||
| 64 | } | 66 | } |
| 65 | 67 | ||
| 66 | ConfigureInput::ConfigureInput(QWidget* parent) | 68 | ConfigureInput::ConfigureInput(QWidget* parent) |
| 67 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) { | 69 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()), |
| 70 | profiles(std::make_unique<InputProfiles>()) { | ||
| 68 | ui->setupUi(this); | 71 | ui->setupUi(this); |
| 69 | } | 72 | } |
| 70 | 73 | ||
| @@ -73,14 +76,22 @@ ConfigureInput::~ConfigureInput() = default; | |||
| 73 | void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, | 76 | void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, |
| 74 | std::size_t max_players) { | 77 | std::size_t max_players) { |
| 75 | player_controllers = { | 78 | player_controllers = { |
| 76 | new ConfigureInputPlayer(this, 0, ui->consoleInputSettings, input_subsystem), | 79 | new ConfigureInputPlayer(this, 0, ui->consoleInputSettings, input_subsystem, |
| 77 | new ConfigureInputPlayer(this, 1, ui->consoleInputSettings, input_subsystem), | 80 | profiles.get()), |
| 78 | new ConfigureInputPlayer(this, 2, ui->consoleInputSettings, input_subsystem), | 81 | new ConfigureInputPlayer(this, 1, ui->consoleInputSettings, input_subsystem, |
| 79 | new ConfigureInputPlayer(this, 3, ui->consoleInputSettings, input_subsystem), | 82 | profiles.get()), |
| 80 | new ConfigureInputPlayer(this, 4, ui->consoleInputSettings, input_subsystem), | 83 | new ConfigureInputPlayer(this, 2, ui->consoleInputSettings, input_subsystem, |
| 81 | new ConfigureInputPlayer(this, 5, ui->consoleInputSettings, input_subsystem), | 84 | profiles.get()), |
| 82 | new ConfigureInputPlayer(this, 6, ui->consoleInputSettings, input_subsystem), | 85 | new ConfigureInputPlayer(this, 3, ui->consoleInputSettings, input_subsystem, |
| 83 | new ConfigureInputPlayer(this, 7, ui->consoleInputSettings, input_subsystem), | 86 | profiles.get()), |
| 87 | new ConfigureInputPlayer(this, 4, ui->consoleInputSettings, input_subsystem, | ||
| 88 | profiles.get()), | ||
| 89 | new ConfigureInputPlayer(this, 5, ui->consoleInputSettings, input_subsystem, | ||
| 90 | profiles.get()), | ||
| 91 | new ConfigureInputPlayer(this, 6, ui->consoleInputSettings, input_subsystem, | ||
| 92 | profiles.get()), | ||
| 93 | new ConfigureInputPlayer(this, 7, ui->consoleInputSettings, input_subsystem, | ||
| 94 | profiles.get()), | ||
| 84 | }; | 95 | }; |
| 85 | 96 | ||
| 86 | player_tabs = { | 97 | player_tabs = { |
| @@ -113,8 +124,10 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, | |||
| 113 | } | 124 | } |
| 114 | } | 125 | } |
| 115 | }); | 126 | }); |
| 116 | connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputDevices, | 127 | connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputDevices, this, |
| 117 | [this] { UpdateAllInputDevices(); }); | 128 | &ConfigureInput::UpdateAllInputDevices); |
| 129 | connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputProfiles, this, | ||
| 130 | &ConfigureInput::UpdateAllInputProfiles, Qt::QueuedConnection); | ||
| 118 | connect(player_connected[i], &QCheckBox::stateChanged, [this, i](int state) { | 131 | connect(player_connected[i], &QCheckBox::stateChanged, [this, i](int state) { |
| 119 | player_controllers[i]->ConnectPlayer(state == Qt::Checked); | 132 | player_controllers[i]->ConnectPlayer(state == Qt::Checked); |
| 120 | }); | 133 | }); |
| @@ -134,7 +147,7 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, | |||
| 134 | ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced)); | 147 | ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced)); |
| 135 | ui->tabAdvanced->layout()->addWidget(advanced); | 148 | ui->tabAdvanced->layout()->addWidget(advanced); |
| 136 | connect(advanced, &ConfigureInputAdvanced::CallDebugControllerDialog, [this, input_subsystem] { | 149 | connect(advanced, &ConfigureInputAdvanced::CallDebugControllerDialog, [this, input_subsystem] { |
| 137 | CallConfigureDialog<ConfigureDebugController>(*this, input_subsystem); | 150 | CallConfigureDialog<ConfigureDebugController>(*this, input_subsystem, profiles.get()); |
| 138 | }); | 151 | }); |
| 139 | connect(advanced, &ConfigureInputAdvanced::CallMouseConfigDialog, [this, input_subsystem] { | 152 | connect(advanced, &ConfigureInputAdvanced::CallMouseConfigDialog, [this, input_subsystem] { |
| 140 | CallConfigureDialog<ConfigureMouseAdvanced>(*this, input_subsystem); | 153 | CallConfigureDialog<ConfigureMouseAdvanced>(*this, input_subsystem); |
| @@ -146,6 +159,9 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem, | |||
| 146 | CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem); | 159 | CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem); |
| 147 | }); | 160 | }); |
| 148 | 161 | ||
| 162 | connect(ui->vibrationButton, &QPushButton::clicked, | ||
| 163 | [this] { CallConfigureDialog<ConfigureVibration>(*this); }); | ||
| 164 | |||
| 149 | connect(ui->motionButton, &QPushButton::clicked, [this, input_subsystem] { | 165 | connect(ui->motionButton, &QPushButton::clicked, [this, input_subsystem] { |
| 150 | CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem); | 166 | CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem); |
| 151 | }); | 167 | }); |
| @@ -171,12 +187,12 @@ void ConfigureInput::ApplyConfiguration() { | |||
| 171 | 187 | ||
| 172 | advanced->ApplyConfiguration(); | 188 | advanced->ApplyConfiguration(); |
| 173 | 189 | ||
| 174 | const bool pre_docked_mode = Settings::values.use_docked_mode; | 190 | const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue(); |
| 175 | Settings::values.use_docked_mode = ui->radioDocked->isChecked(); | 191 | Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked()); |
| 176 | OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode); | 192 | OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode.GetValue()); |
| 177 | 193 | ||
| 178 | Settings::values.vibration_enabled = ui->vibrationGroup->isChecked(); | 194 | Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked()); |
| 179 | Settings::values.motion_enabled = ui->motionGroup->isChecked(); | 195 | Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked()); |
| 180 | } | 196 | } |
| 181 | 197 | ||
| 182 | void ConfigureInput::changeEvent(QEvent* event) { | 198 | void ConfigureInput::changeEvent(QEvent* event) { |
| @@ -193,16 +209,16 @@ void ConfigureInput::RetranslateUI() { | |||
| 193 | 209 | ||
| 194 | void ConfigureInput::LoadConfiguration() { | 210 | void ConfigureInput::LoadConfiguration() { |
| 195 | LoadPlayerControllerIndices(); | 211 | LoadPlayerControllerIndices(); |
| 196 | UpdateDockedState(Settings::values.players[8].connected); | 212 | UpdateDockedState(Settings::values.players.GetValue()[8].connected); |
| 197 | 213 | ||
| 198 | ui->vibrationGroup->setChecked(Settings::values.vibration_enabled); | 214 | ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue()); |
| 199 | ui->motionGroup->setChecked(Settings::values.motion_enabled); | 215 | ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue()); |
| 200 | } | 216 | } |
| 201 | 217 | ||
| 202 | void ConfigureInput::LoadPlayerControllerIndices() { | 218 | void ConfigureInput::LoadPlayerControllerIndices() { |
| 203 | for (std::size_t i = 0; i < player_connected.size(); ++i) { | 219 | for (std::size_t i = 0; i < player_connected.size(); ++i) { |
| 204 | const auto connected = Settings::values.players[i].connected || | 220 | const auto connected = Settings::values.players.GetValue()[i].connected || |
| 205 | (i == 0 && Settings::values.players[8].connected); | 221 | (i == 0 && Settings::values.players.GetValue()[8].connected); |
| 206 | player_connected[i]->setChecked(connected); | 222 | player_connected[i]->setChecked(connected); |
| 207 | } | 223 | } |
| 208 | } | 224 | } |
| @@ -231,8 +247,8 @@ void ConfigureInput::UpdateDockedState(bool is_handheld) { | |||
| 231 | ui->radioDocked->setEnabled(!is_handheld); | 247 | ui->radioDocked->setEnabled(!is_handheld); |
| 232 | ui->radioUndocked->setEnabled(!is_handheld); | 248 | ui->radioUndocked->setEnabled(!is_handheld); |
| 233 | 249 | ||
| 234 | ui->radioDocked->setChecked(Settings::values.use_docked_mode); | 250 | ui->radioDocked->setChecked(Settings::values.use_docked_mode.GetValue()); |
| 235 | ui->radioUndocked->setChecked(!Settings::values.use_docked_mode); | 251 | ui->radioUndocked->setChecked(!Settings::values.use_docked_mode.GetValue()); |
| 236 | 252 | ||
| 237 | // Also force into undocked mode if the controller type is handheld. | 253 | // Also force into undocked mode if the controller type is handheld. |
| 238 | if (is_handheld) { | 254 | if (is_handheld) { |
| @@ -242,6 +258,16 @@ void ConfigureInput::UpdateDockedState(bool is_handheld) { | |||
| 242 | 258 | ||
| 243 | void ConfigureInput::UpdateAllInputDevices() { | 259 | void ConfigureInput::UpdateAllInputDevices() { |
| 244 | for (const auto& player : player_controllers) { | 260 | for (const auto& player : player_controllers) { |
| 245 | player->UpdateInputDevices(); | 261 | player->UpdateInputDeviceCombobox(); |
| 262 | } | ||
| 263 | } | ||
| 264 | |||
| 265 | void ConfigureInput::UpdateAllInputProfiles(std::size_t player_index) { | ||
| 266 | for (std::size_t i = 0; i < player_controllers.size(); ++i) { | ||
| 267 | if (i == player_index) { | ||
| 268 | continue; | ||
| 269 | } | ||
| 270 | |||
| 271 | player_controllers[i]->UpdateInputProfiles(); | ||
| 246 | } | 272 | } |
| 247 | } | 273 | } |
diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h index 0e8b2fd4e..f4eb0d78b 100644 --- a/src/yuzu/configuration/configure_input.h +++ b/src/yuzu/configuration/configure_input.h | |||
| @@ -8,17 +8,18 @@ | |||
| 8 | #include <memory> | 8 | #include <memory> |
| 9 | 9 | ||
| 10 | #include <QKeyEvent> | 10 | #include <QKeyEvent> |
| 11 | #include <QList> | ||
| 11 | #include <QWidget> | 12 | #include <QWidget> |
| 12 | 13 | ||
| 13 | #include "yuzu/configuration/configure_input_advanced.h" | ||
| 14 | #include "yuzu/configuration/configure_input_player.h" | ||
| 15 | |||
| 16 | #include "ui_configure_input.h" | ||
| 17 | |||
| 18 | class QCheckBox; | 14 | class QCheckBox; |
| 19 | class QString; | 15 | class QString; |
| 20 | class QTimer; | 16 | class QTimer; |
| 21 | 17 | ||
| 18 | class ConfigureInputAdvanced; | ||
| 19 | class ConfigureInputPlayer; | ||
| 20 | |||
| 21 | class InputProfiles; | ||
| 22 | |||
| 22 | namespace InputCommon { | 23 | namespace InputCommon { |
| 23 | class InputSubsystem; | 24 | class InputSubsystem; |
| 24 | } | 25 | } |
| @@ -51,6 +52,7 @@ private: | |||
| 51 | 52 | ||
| 52 | void UpdateDockedState(bool is_handheld); | 53 | void UpdateDockedState(bool is_handheld); |
| 53 | void UpdateAllInputDevices(); | 54 | void UpdateAllInputDevices(); |
| 55 | void UpdateAllInputProfiles(std::size_t player_index); | ||
| 54 | 56 | ||
| 55 | /// Load configuration settings. | 57 | /// Load configuration settings. |
| 56 | void LoadConfiguration(); | 58 | void LoadConfiguration(); |
| @@ -61,6 +63,8 @@ private: | |||
| 61 | 63 | ||
| 62 | std::unique_ptr<Ui::ConfigureInput> ui; | 64 | std::unique_ptr<Ui::ConfigureInput> ui; |
| 63 | 65 | ||
| 66 | std::unique_ptr<InputProfiles> profiles; | ||
| 67 | |||
| 64 | std::array<ConfigureInputPlayer*, 8> player_controllers; | 68 | std::array<ConfigureInputPlayer*, 8> player_controllers; |
| 65 | std::array<QWidget*, 8> player_tabs; | 69 | std::array<QWidget*, 8> player_tabs; |
| 66 | std::array<QCheckBox*, 8> player_connected; | 70 | std::array<QCheckBox*, 8> player_connected; |
diff --git a/src/yuzu/configuration/configure_input.ui b/src/yuzu/configuration/configure_input.ui index 136955224..2707025e7 100644 --- a/src/yuzu/configuration/configure_input.ui +++ b/src/yuzu/configuration/configure_input.ui | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | <rect> | 6 | <rect> |
| 7 | <x>0</x> | 7 | <x>0</x> |
| 8 | <y>0</y> | 8 | <y>0</y> |
| 9 | <width>700</width> | 9 | <width>680</width> |
| 10 | <height>540</height> | 10 | <height>540</height> |
| 11 | </rect> | 11 | </rect> |
| 12 | </property> | 12 | </property> |
| @@ -142,7 +142,7 @@ | |||
| 142 | <number>6</number> | 142 | <number>6</number> |
| 143 | </property> | 143 | </property> |
| 144 | <property name="leftMargin"> | 144 | <property name="leftMargin"> |
| 145 | <number>3</number> | 145 | <number>8</number> |
| 146 | </property> | 146 | </property> |
| 147 | <property name="topMargin"> | 147 | <property name="topMargin"> |
| 148 | <number>6</number> | 148 | <number>6</number> |
| @@ -195,30 +195,24 @@ | |||
| 195 | <number>3</number> | 195 | <number>3</number> |
| 196 | </property> | 196 | </property> |
| 197 | <item> | 197 | <item> |
| 198 | <widget class="QSpinBox" name="vibrationSpin"> | 198 | <widget class="QPushButton" name="vibrationButton"> |
| 199 | <property name="minimumSize"> | 199 | <property name="minimumSize"> |
| 200 | <size> | 200 | <size> |
| 201 | <width>65</width> | 201 | <width>68</width> |
| 202 | <height>21</height> | 202 | <height>0</height> |
| 203 | </size> | 203 | </size> |
| 204 | </property> | 204 | </property> |
| 205 | <property name="maximumSize"> | 205 | <property name="maximumSize"> |
| 206 | <size> | 206 | <size> |
| 207 | <width>65</width> | 207 | <width>68</width> |
| 208 | <height>16777215</height> | 208 | <height>16777215</height> |
| 209 | </size> | 209 | </size> |
| 210 | </property> | 210 | </property> |
| 211 | <property name="suffix"> | 211 | <property name="styleSheet"> |
| 212 | <string>%</string> | 212 | <string notr="true">min-width: 68px;</string> |
| 213 | </property> | ||
| 214 | <property name="minimum"> | ||
| 215 | <number>1</number> | ||
| 216 | </property> | ||
| 217 | <property name="maximum"> | ||
| 218 | <number>200</number> | ||
| 219 | </property> | 213 | </property> |
| 220 | <property name="value"> | 214 | <property name="text"> |
| 221 | <number>100</number> | 215 | <string>Configure</string> |
| 222 | </property> | 216 | </property> |
| 223 | </widget> | 217 | </widget> |
| 224 | </item> | 218 | </item> |
| @@ -250,18 +244,18 @@ | |||
| 250 | <widget class="QPushButton" name="motionButton"> | 244 | <widget class="QPushButton" name="motionButton"> |
| 251 | <property name="minimumSize"> | 245 | <property name="minimumSize"> |
| 252 | <size> | 246 | <size> |
| 253 | <width>57</width> | 247 | <width>68</width> |
| 254 | <height>0</height> | 248 | <height>0</height> |
| 255 | </size> | 249 | </size> |
| 256 | </property> | 250 | </property> |
| 257 | <property name="maximumSize"> | 251 | <property name="maximumSize"> |
| 258 | <size> | 252 | <size> |
| 259 | <width>55</width> | 253 | <width>68</width> |
| 260 | <height>16777215</height> | 254 | <height>16777215</height> |
| 261 | </size> | 255 | </size> |
| 262 | </property> | 256 | </property> |
| 263 | <property name="styleSheet"> | 257 | <property name="styleSheet"> |
| 264 | <string notr="true">min-width: 55px;</string> | 258 | <string notr="true">min-width: 68px;</string> |
| 265 | </property> | 259 | </property> |
| 266 | <property name="text"> | 260 | <property name="text"> |
| 267 | <string>Configure</string> | 261 | <string>Configure</string> |
| @@ -272,7 +266,7 @@ | |||
| 272 | </widget> | 266 | </widget> |
| 273 | </item> | 267 | </item> |
| 274 | <item alignment="Qt::AlignVCenter"> | 268 | <item alignment="Qt::AlignVCenter"> |
| 275 | <widget class="QWidget" name="widget" native="true"> | 269 | <widget class="QWidget" name="connectedControllers" native="true"> |
| 276 | <layout class="QGridLayout" name="gridLayout_2"> | 270 | <layout class="QGridLayout" name="gridLayout_2"> |
| 277 | <property name="leftMargin"> | 271 | <property name="leftMargin"> |
| 278 | <number>5</number> | 272 | <number>5</number> |
| @@ -468,13 +462,13 @@ | |||
| 468 | </property> | 462 | </property> |
| 469 | <property name="minimumSize"> | 463 | <property name="minimumSize"> |
| 470 | <size> | 464 | <size> |
| 471 | <width>57</width> | 465 | <width>68</width> |
| 472 | <height>0</height> | 466 | <height>0</height> |
| 473 | </size> | 467 | </size> |
| 474 | </property> | 468 | </property> |
| 475 | <property name="maximumSize"> | 469 | <property name="maximumSize"> |
| 476 | <size> | 470 | <size> |
| 477 | <width>55</width> | 471 | <width>68</width> |
| 478 | <height>16777215</height> | 472 | <height>16777215</height> |
| 479 | </size> | 473 | </size> |
| 480 | </property> | 474 | </property> |
| @@ -494,7 +488,7 @@ | |||
| 494 | <enum>Qt::LeftToRight</enum> | 488 | <enum>Qt::LeftToRight</enum> |
| 495 | </property> | 489 | </property> |
| 496 | <property name="styleSheet"> | 490 | <property name="styleSheet"> |
| 497 | <string notr="true">min-width: 55px;</string> | 491 | <string notr="true">min-width: 68px;</string> |
| 498 | </property> | 492 | </property> |
| 499 | <property name="text"> | 493 | <property name="text"> |
| 500 | <string>Defaults</string> | 494 | <string>Defaults</string> |
| @@ -511,13 +505,13 @@ | |||
| 511 | </property> | 505 | </property> |
| 512 | <property name="minimumSize"> | 506 | <property name="minimumSize"> |
| 513 | <size> | 507 | <size> |
| 514 | <width>57</width> | 508 | <width>68</width> |
| 515 | <height>0</height> | 509 | <height>0</height> |
| 516 | </size> | 510 | </size> |
| 517 | </property> | 511 | </property> |
| 518 | <property name="maximumSize"> | 512 | <property name="maximumSize"> |
| 519 | <size> | 513 | <size> |
| 520 | <width>55</width> | 514 | <width>68</width> |
| 521 | <height>16777215</height> | 515 | <height>16777215</height> |
| 522 | </size> | 516 | </size> |
| 523 | </property> | 517 | </property> |
| @@ -537,7 +531,7 @@ | |||
| 537 | <enum>Qt::LeftToRight</enum> | 531 | <enum>Qt::LeftToRight</enum> |
| 538 | </property> | 532 | </property> |
| 539 | <property name="styleSheet"> | 533 | <property name="styleSheet"> |
| 540 | <string notr="true">min-width: 55px;</string> | 534 | <string notr="true">min-width: 68px;</string> |
| 541 | </property> | 535 | </property> |
| 542 | <property name="text"> | 536 | <property name="text"> |
| 543 | <string>Clear</string> | 537 | <string>Clear</string> |
diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp index 81f9dc16c..abaf03630 100644 --- a/src/yuzu/configuration/configure_input_advanced.cpp +++ b/src/yuzu/configuration/configure_input_advanced.cpp | |||
| @@ -68,8 +68,7 @@ ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent) | |||
| 68 | for (std::size_t button_idx = 0; button_idx < color_buttons.size(); ++button_idx) { | 68 | for (std::size_t button_idx = 0; button_idx < color_buttons.size(); ++button_idx) { |
| 69 | connect(color_buttons[button_idx], &QPushButton::clicked, this, | 69 | connect(color_buttons[button_idx], &QPushButton::clicked, this, |
| 70 | [this, player_idx, button_idx] { | 70 | [this, player_idx, button_idx] { |
| 71 | OnControllerButtonClick(static_cast<int>(player_idx), | 71 | OnControllerButtonClick(player_idx, button_idx); |
| 72 | static_cast<int>(button_idx)); | ||
| 73 | }); | 72 | }); |
| 74 | } | 73 | } |
| 75 | } | 74 | } |
| @@ -94,20 +93,21 @@ ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent) | |||
| 94 | 93 | ||
| 95 | ConfigureInputAdvanced::~ConfigureInputAdvanced() = default; | 94 | ConfigureInputAdvanced::~ConfigureInputAdvanced() = default; |
| 96 | 95 | ||
| 97 | void ConfigureInputAdvanced::OnControllerButtonClick(int player_idx, int button_idx) { | 96 | void ConfigureInputAdvanced::OnControllerButtonClick(std::size_t player_idx, |
| 97 | std::size_t button_idx) { | ||
| 98 | const QColor new_bg_color = QColorDialog::getColor(controllers_colors[player_idx][button_idx]); | 98 | const QColor new_bg_color = QColorDialog::getColor(controllers_colors[player_idx][button_idx]); |
| 99 | if (!new_bg_color.isValid()) { | 99 | if (!new_bg_color.isValid()) { |
| 100 | return; | 100 | return; |
| 101 | } | 101 | } |
| 102 | controllers_colors[player_idx][button_idx] = new_bg_color; | 102 | controllers_colors[player_idx][button_idx] = new_bg_color; |
| 103 | controllers_color_buttons[player_idx][button_idx]->setStyleSheet( | 103 | controllers_color_buttons[player_idx][button_idx]->setStyleSheet( |
| 104 | QStringLiteral("background-color: %1; min-width: 55px;") | 104 | QStringLiteral("background-color: %1; min-width: 60px;") |
| 105 | .arg(controllers_colors[player_idx][button_idx].name())); | 105 | .arg(controllers_colors[player_idx][button_idx].name())); |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | void ConfigureInputAdvanced::ApplyConfiguration() { | 108 | void ConfigureInputAdvanced::ApplyConfiguration() { |
| 109 | for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) { | 109 | for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) { |
| 110 | auto& player = Settings::values.players[player_idx]; | 110 | auto& player = Settings::values.players.GetValue()[player_idx]; |
| 111 | std::array<u32, 4> colors{}; | 111 | std::array<u32, 4> colors{}; |
| 112 | std::transform(controllers_colors[player_idx].begin(), controllers_colors[player_idx].end(), | 112 | std::transform(controllers_colors[player_idx].begin(), controllers_colors[player_idx].end(), |
| 113 | colors.begin(), [](QColor color) { return color.rgb(); }); | 113 | colors.begin(), [](QColor color) { return color.rgb(); }); |
| @@ -126,7 +126,7 @@ void ConfigureInputAdvanced::ApplyConfiguration() { | |||
| 126 | 126 | ||
| 127 | void ConfigureInputAdvanced::LoadConfiguration() { | 127 | void ConfigureInputAdvanced::LoadConfiguration() { |
| 128 | for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) { | 128 | for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) { |
| 129 | auto& player = Settings::values.players[player_idx]; | 129 | auto& player = Settings::values.players.GetValue()[player_idx]; |
| 130 | std::array<u32, 4> colors = { | 130 | std::array<u32, 4> colors = { |
| 131 | player.body_color_left, | 131 | player.body_color_left, |
| 132 | player.button_color_left, | 132 | player.button_color_left, |
| @@ -139,7 +139,7 @@ void ConfigureInputAdvanced::LoadConfiguration() { | |||
| 139 | 139 | ||
| 140 | for (std::size_t button_idx = 0; button_idx < colors.size(); ++button_idx) { | 140 | for (std::size_t button_idx = 0; button_idx < colors.size(); ++button_idx) { |
| 141 | controllers_color_buttons[player_idx][button_idx]->setStyleSheet( | 141 | controllers_color_buttons[player_idx][button_idx]->setStyleSheet( |
| 142 | QStringLiteral("background-color: %1; min-width: 55px;") | 142 | QStringLiteral("background-color: %1; min-width: 60px;") |
| 143 | .arg(controllers_colors[player_idx][button_idx].name())); | 143 | .arg(controllers_colors[player_idx][button_idx].name())); |
| 144 | } | 144 | } |
| 145 | } | 145 | } |
diff --git a/src/yuzu/configuration/configure_input_advanced.h b/src/yuzu/configuration/configure_input_advanced.h index 50bb87768..3083d55c1 100644 --- a/src/yuzu/configuration/configure_input_advanced.h +++ b/src/yuzu/configuration/configure_input_advanced.h | |||
| @@ -35,7 +35,7 @@ private: | |||
| 35 | void RetranslateUI(); | 35 | void RetranslateUI(); |
| 36 | void UpdateUIEnabled(); | 36 | void UpdateUIEnabled(); |
| 37 | 37 | ||
| 38 | void OnControllerButtonClick(int player_idx, int button_idx); | 38 | void OnControllerButtonClick(std::size_t player_idx, std::size_t button_idx); |
| 39 | 39 | ||
| 40 | void LoadConfiguration(); | 40 | void LoadConfiguration(); |
| 41 | 41 | ||
diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui index 5958435fc..a880a7c68 100644 --- a/src/yuzu/configuration/configure_input_advanced.ui +++ b/src/yuzu/configuration/configure_input_advanced.ui | |||
| @@ -192,18 +192,18 @@ | |||
| 192 | </property> | 192 | </property> |
| 193 | <property name="minimumSize"> | 193 | <property name="minimumSize"> |
| 194 | <size> | 194 | <size> |
| 195 | <width>57</width> | 195 | <width>68</width> |
| 196 | <height>0</height> | 196 | <height>0</height> |
| 197 | </size> | 197 | </size> |
| 198 | </property> | 198 | </property> |
| 199 | <property name="maximumSize"> | 199 | <property name="maximumSize"> |
| 200 | <size> | 200 | <size> |
| 201 | <width>55</width> | 201 | <width>68</width> |
| 202 | <height>16777215</height> | 202 | <height>16777215</height> |
| 203 | </size> | 203 | </size> |
| 204 | </property> | 204 | </property> |
| 205 | <property name="styleSheet"> | 205 | <property name="styleSheet"> |
| 206 | <string notr="true">min-width: 55px;</string> | 206 | <string notr="true">min-width: 68px;</string> |
| 207 | </property> | 207 | </property> |
| 208 | <property name="text"> | 208 | <property name="text"> |
| 209 | <string/> | 209 | <string/> |
| @@ -247,18 +247,18 @@ | |||
| 247 | </property> | 247 | </property> |
| 248 | <property name="minimumSize"> | 248 | <property name="minimumSize"> |
| 249 | <size> | 249 | <size> |
| 250 | <width>57</width> | 250 | <width>68</width> |
| 251 | <height>0</height> | 251 | <height>0</height> |
| 252 | </size> | 252 | </size> |
| 253 | </property> | 253 | </property> |
| 254 | <property name="maximumSize"> | 254 | <property name="maximumSize"> |
| 255 | <size> | 255 | <size> |
| 256 | <width>55</width> | 256 | <width>68</width> |
| 257 | <height>16777215</height> | 257 | <height>16777215</height> |
| 258 | </size> | 258 | </size> |
| 259 | </property> | 259 | </property> |
| 260 | <property name="styleSheet"> | 260 | <property name="styleSheet"> |
| 261 | <string notr="true">min-width: 55px;</string> | 261 | <string notr="true">min-width: 68px;</string> |
| 262 | </property> | 262 | </property> |
| 263 | <property name="text"> | 263 | <property name="text"> |
| 264 | <string/> | 264 | <string/> |
| @@ -323,18 +323,18 @@ | |||
| 323 | </property> | 323 | </property> |
| 324 | <property name="minimumSize"> | 324 | <property name="minimumSize"> |
| 325 | <size> | 325 | <size> |
| 326 | <width>57</width> | 326 | <width>68</width> |
| 327 | <height>0</height> | 327 | <height>0</height> |
| 328 | </size> | 328 | </size> |
| 329 | </property> | 329 | </property> |
| 330 | <property name="maximumSize"> | 330 | <property name="maximumSize"> |
| 331 | <size> | 331 | <size> |
| 332 | <width>55</width> | 332 | <width>68</width> |
| 333 | <height>16777215</height> | 333 | <height>16777215</height> |
| 334 | </size> | 334 | </size> |
| 335 | </property> | 335 | </property> |
| 336 | <property name="styleSheet"> | 336 | <property name="styleSheet"> |
| 337 | <string notr="true">min-width: 55px;</string> | 337 | <string notr="true">min-width: 68px;</string> |
| 338 | </property> | 338 | </property> |
| 339 | <property name="text"> | 339 | <property name="text"> |
| 340 | <string/> | 340 | <string/> |
| @@ -378,18 +378,18 @@ | |||
| 378 | </property> | 378 | </property> |
| 379 | <property name="minimumSize"> | 379 | <property name="minimumSize"> |
| 380 | <size> | 380 | <size> |
| 381 | <width>57</width> | 381 | <width>68</width> |
| 382 | <height>0</height> | 382 | <height>0</height> |
| 383 | </size> | 383 | </size> |
| 384 | </property> | 384 | </property> |
| 385 | <property name="maximumSize"> | 385 | <property name="maximumSize"> |
| 386 | <size> | 386 | <size> |
| 387 | <width>55</width> | 387 | <width>68</width> |
| 388 | <height>16777215</height> | 388 | <height>16777215</height> |
| 389 | </size> | 389 | </size> |
| 390 | </property> | 390 | </property> |
| 391 | <property name="styleSheet"> | 391 | <property name="styleSheet"> |
| 392 | <string notr="true">min-width: 55px;</string> | 392 | <string notr="true">min-width: 68px;</string> |
| 393 | </property> | 393 | </property> |
| 394 | <property name="text"> | 394 | <property name="text"> |
| 395 | <string/> | 395 | <string/> |
| @@ -478,18 +478,18 @@ | |||
| 478 | </property> | 478 | </property> |
| 479 | <property name="minimumSize"> | 479 | <property name="minimumSize"> |
| 480 | <size> | 480 | <size> |
| 481 | <width>57</width> | 481 | <width>68</width> |
| 482 | <height>0</height> | 482 | <height>0</height> |
| 483 | </size> | 483 | </size> |
| 484 | </property> | 484 | </property> |
| 485 | <property name="maximumSize"> | 485 | <property name="maximumSize"> |
| 486 | <size> | 486 | <size> |
| 487 | <width>55</width> | 487 | <width>68</width> |
| 488 | <height>16777215</height> | 488 | <height>16777215</height> |
| 489 | </size> | 489 | </size> |
| 490 | </property> | 490 | </property> |
| 491 | <property name="styleSheet"> | 491 | <property name="styleSheet"> |
| 492 | <string notr="true">min-width: 55px;</string> | 492 | <string notr="true">min-width: 68px;</string> |
| 493 | </property> | 493 | </property> |
| 494 | <property name="text"> | 494 | <property name="text"> |
| 495 | <string/> | 495 | <string/> |
| @@ -533,18 +533,18 @@ | |||
| 533 | </property> | 533 | </property> |
| 534 | <property name="minimumSize"> | 534 | <property name="minimumSize"> |
| 535 | <size> | 535 | <size> |
| 536 | <width>57</width> | 536 | <width>68</width> |
| 537 | <height>0</height> | 537 | <height>0</height> |
| 538 | </size> | 538 | </size> |
| 539 | </property> | 539 | </property> |
| 540 | <property name="maximumSize"> | 540 | <property name="maximumSize"> |
| 541 | <size> | 541 | <size> |
| 542 | <width>55</width> | 542 | <width>68</width> |
| 543 | <height>16777215</height> | 543 | <height>16777215</height> |
| 544 | </size> | 544 | </size> |
| 545 | </property> | 545 | </property> |
| 546 | <property name="styleSheet"> | 546 | <property name="styleSheet"> |
| 547 | <string notr="true">min-width: 55px;</string> | 547 | <string notr="true">min-width: 68px;</string> |
| 548 | </property> | 548 | </property> |
| 549 | <property name="text"> | 549 | <property name="text"> |
| 550 | <string/> | 550 | <string/> |
| @@ -609,18 +609,18 @@ | |||
| 609 | </property> | 609 | </property> |
| 610 | <property name="minimumSize"> | 610 | <property name="minimumSize"> |
| 611 | <size> | 611 | <size> |
| 612 | <width>57</width> | 612 | <width>68</width> |
| 613 | <height>0</height> | 613 | <height>0</height> |
| 614 | </size> | 614 | </size> |
| 615 | </property> | 615 | </property> |
| 616 | <property name="maximumSize"> | 616 | <property name="maximumSize"> |
| 617 | <size> | 617 | <size> |
| 618 | <width>55</width> | 618 | <width>68</width> |
| 619 | <height>16777215</height> | 619 | <height>16777215</height> |
| 620 | </size> | 620 | </size> |
| 621 | </property> | 621 | </property> |
| 622 | <property name="styleSheet"> | 622 | <property name="styleSheet"> |
| 623 | <string notr="true">min-width: 55px;</string> | 623 | <string notr="true">min-width: 68px;</string> |
| 624 | </property> | 624 | </property> |
| 625 | <property name="text"> | 625 | <property name="text"> |
| 626 | <string/> | 626 | <string/> |
| @@ -664,18 +664,18 @@ | |||
| 664 | </property> | 664 | </property> |
| 665 | <property name="minimumSize"> | 665 | <property name="minimumSize"> |
| 666 | <size> | 666 | <size> |
| 667 | <width>57</width> | 667 | <width>68</width> |
| 668 | <height>0</height> | 668 | <height>0</height> |
| 669 | </size> | 669 | </size> |
| 670 | </property> | 670 | </property> |
| 671 | <property name="maximumSize"> | 671 | <property name="maximumSize"> |
| 672 | <size> | 672 | <size> |
| 673 | <width>55</width> | 673 | <width>68</width> |
| 674 | <height>16777215</height> | 674 | <height>16777215</height> |
| 675 | </size> | 675 | </size> |
| 676 | </property> | 676 | </property> |
| 677 | <property name="styleSheet"> | 677 | <property name="styleSheet"> |
| 678 | <string notr="true">min-width: 55px;</string> | 678 | <string notr="true">min-width: 68px;</string> |
| 679 | </property> | 679 | </property> |
| 680 | <property name="text"> | 680 | <property name="text"> |
| 681 | <string/> | 681 | <string/> |
| @@ -782,18 +782,18 @@ | |||
| 782 | </property> | 782 | </property> |
| 783 | <property name="minimumSize"> | 783 | <property name="minimumSize"> |
| 784 | <size> | 784 | <size> |
| 785 | <width>57</width> | 785 | <width>68</width> |
| 786 | <height>0</height> | 786 | <height>0</height> |
| 787 | </size> | 787 | </size> |
| 788 | </property> | 788 | </property> |
| 789 | <property name="maximumSize"> | 789 | <property name="maximumSize"> |
| 790 | <size> | 790 | <size> |
| 791 | <width>55</width> | 791 | <width>68</width> |
| 792 | <height>16777215</height> | 792 | <height>16777215</height> |
| 793 | </size> | 793 | </size> |
| 794 | </property> | 794 | </property> |
| 795 | <property name="styleSheet"> | 795 | <property name="styleSheet"> |
| 796 | <string notr="true">min-width: 55px;</string> | 796 | <string notr="true">min-width: 68px;</string> |
| 797 | </property> | 797 | </property> |
| 798 | <property name="text"> | 798 | <property name="text"> |
| 799 | <string/> | 799 | <string/> |
| @@ -837,18 +837,18 @@ | |||
| 837 | </property> | 837 | </property> |
| 838 | <property name="minimumSize"> | 838 | <property name="minimumSize"> |
| 839 | <size> | 839 | <size> |
| 840 | <width>57</width> | 840 | <width>68</width> |
| 841 | <height>0</height> | 841 | <height>0</height> |
| 842 | </size> | 842 | </size> |
| 843 | </property> | 843 | </property> |
| 844 | <property name="maximumSize"> | 844 | <property name="maximumSize"> |
| 845 | <size> | 845 | <size> |
| 846 | <width>55</width> | 846 | <width>68</width> |
| 847 | <height>16777215</height> | 847 | <height>16777215</height> |
| 848 | </size> | 848 | </size> |
| 849 | </property> | 849 | </property> |
| 850 | <property name="styleSheet"> | 850 | <property name="styleSheet"> |
| 851 | <string notr="true">min-width: 55px;</string> | 851 | <string notr="true">min-width: 68px;</string> |
| 852 | </property> | 852 | </property> |
| 853 | <property name="text"> | 853 | <property name="text"> |
| 854 | <string/> | 854 | <string/> |
| @@ -913,18 +913,18 @@ | |||
| 913 | </property> | 913 | </property> |
| 914 | <property name="minimumSize"> | 914 | <property name="minimumSize"> |
| 915 | <size> | 915 | <size> |
| 916 | <width>57</width> | 916 | <width>68</width> |
| 917 | <height>0</height> | 917 | <height>0</height> |
| 918 | </size> | 918 | </size> |
| 919 | </property> | 919 | </property> |
| 920 | <property name="maximumSize"> | 920 | <property name="maximumSize"> |
| 921 | <size> | 921 | <size> |
| 922 | <width>55</width> | 922 | <width>68</width> |
| 923 | <height>16777215</height> | 923 | <height>16777215</height> |
| 924 | </size> | 924 | </size> |
| 925 | </property> | 925 | </property> |
| 926 | <property name="styleSheet"> | 926 | <property name="styleSheet"> |
| 927 | <string notr="true">min-width: 55px;</string> | 927 | <string notr="true">min-width: 68px;</string> |
| 928 | </property> | 928 | </property> |
| 929 | <property name="text"> | 929 | <property name="text"> |
| 930 | <string/> | 930 | <string/> |
| @@ -968,18 +968,18 @@ | |||
| 968 | </property> | 968 | </property> |
| 969 | <property name="minimumSize"> | 969 | <property name="minimumSize"> |
| 970 | <size> | 970 | <size> |
| 971 | <width>57</width> | 971 | <width>68</width> |
| 972 | <height>0</height> | 972 | <height>0</height> |
| 973 | </size> | 973 | </size> |
| 974 | </property> | 974 | </property> |
| 975 | <property name="maximumSize"> | 975 | <property name="maximumSize"> |
| 976 | <size> | 976 | <size> |
| 977 | <width>55</width> | 977 | <width>68</width> |
| 978 | <height>16777215</height> | 978 | <height>16777215</height> |
| 979 | </size> | 979 | </size> |
| 980 | </property> | 980 | </property> |
| 981 | <property name="styleSheet"> | 981 | <property name="styleSheet"> |
| 982 | <string notr="true">min-width: 55px;</string> | 982 | <string notr="true">min-width: 68px;</string> |
| 983 | </property> | 983 | </property> |
| 984 | <property name="text"> | 984 | <property name="text"> |
| 985 | <string/> | 985 | <string/> |
| @@ -1068,18 +1068,18 @@ | |||
| 1068 | </property> | 1068 | </property> |
| 1069 | <property name="minimumSize"> | 1069 | <property name="minimumSize"> |
| 1070 | <size> | 1070 | <size> |
| 1071 | <width>57</width> | 1071 | <width>68</width> |
| 1072 | <height>0</height> | 1072 | <height>0</height> |
| 1073 | </size> | 1073 | </size> |
| 1074 | </property> | 1074 | </property> |
| 1075 | <property name="maximumSize"> | 1075 | <property name="maximumSize"> |
| 1076 | <size> | 1076 | <size> |
| 1077 | <width>55</width> | 1077 | <width>68</width> |
| 1078 | <height>16777215</height> | 1078 | <height>16777215</height> |
| 1079 | </size> | 1079 | </size> |
| 1080 | </property> | 1080 | </property> |
| 1081 | <property name="styleSheet"> | 1081 | <property name="styleSheet"> |
| 1082 | <string notr="true">min-width: 55px;</string> | 1082 | <string notr="true">min-width: 68px;</string> |
| 1083 | </property> | 1083 | </property> |
| 1084 | <property name="text"> | 1084 | <property name="text"> |
| 1085 | <string/> | 1085 | <string/> |
| @@ -1123,18 +1123,18 @@ | |||
| 1123 | </property> | 1123 | </property> |
| 1124 | <property name="minimumSize"> | 1124 | <property name="minimumSize"> |
| 1125 | <size> | 1125 | <size> |
| 1126 | <width>57</width> | 1126 | <width>68</width> |
| 1127 | <height>0</height> | 1127 | <height>0</height> |
| 1128 | </size> | 1128 | </size> |
| 1129 | </property> | 1129 | </property> |
| 1130 | <property name="maximumSize"> | 1130 | <property name="maximumSize"> |
| 1131 | <size> | 1131 | <size> |
| 1132 | <width>55</width> | 1132 | <width>68</width> |
| 1133 | <height>16777215</height> | 1133 | <height>16777215</height> |
| 1134 | </size> | 1134 | </size> |
| 1135 | </property> | 1135 | </property> |
| 1136 | <property name="styleSheet"> | 1136 | <property name="styleSheet"> |
| 1137 | <string notr="true">min-width: 55px;</string> | 1137 | <string notr="true">min-width: 68px;</string> |
| 1138 | </property> | 1138 | </property> |
| 1139 | <property name="text"> | 1139 | <property name="text"> |
| 1140 | <string/> | 1140 | <string/> |
| @@ -1199,18 +1199,18 @@ | |||
| 1199 | </property> | 1199 | </property> |
| 1200 | <property name="minimumSize"> | 1200 | <property name="minimumSize"> |
| 1201 | <size> | 1201 | <size> |
| 1202 | <width>57</width> | 1202 | <width>68</width> |
| 1203 | <height>0</height> | 1203 | <height>0</height> |
| 1204 | </size> | 1204 | </size> |
| 1205 | </property> | 1205 | </property> |
| 1206 | <property name="maximumSize"> | 1206 | <property name="maximumSize"> |
| 1207 | <size> | 1207 | <size> |
| 1208 | <width>55</width> | 1208 | <width>68</width> |
| 1209 | <height>16777215</height> | 1209 | <height>16777215</height> |
| 1210 | </size> | 1210 | </size> |
| 1211 | </property> | 1211 | </property> |
| 1212 | <property name="styleSheet"> | 1212 | <property name="styleSheet"> |
| 1213 | <string notr="true">min-width: 55px;</string> | 1213 | <string notr="true">min-width: 68px;</string> |
| 1214 | </property> | 1214 | </property> |
| 1215 | <property name="text"> | 1215 | <property name="text"> |
| 1216 | <string/> | 1216 | <string/> |
| @@ -1254,18 +1254,18 @@ | |||
| 1254 | </property> | 1254 | </property> |
| 1255 | <property name="minimumSize"> | 1255 | <property name="minimumSize"> |
| 1256 | <size> | 1256 | <size> |
| 1257 | <width>57</width> | 1257 | <width>68</width> |
| 1258 | <height>0</height> | 1258 | <height>0</height> |
| 1259 | </size> | 1259 | </size> |
| 1260 | </property> | 1260 | </property> |
| 1261 | <property name="maximumSize"> | 1261 | <property name="maximumSize"> |
| 1262 | <size> | 1262 | <size> |
| 1263 | <width>55</width> | 1263 | <width>68</width> |
| 1264 | <height>16777215</height> | 1264 | <height>16777215</height> |
| 1265 | </size> | 1265 | </size> |
| 1266 | </property> | 1266 | </property> |
| 1267 | <property name="styleSheet"> | 1267 | <property name="styleSheet"> |
| 1268 | <string notr="true">min-width: 55px;</string> | 1268 | <string notr="true">min-width: 68px;</string> |
| 1269 | </property> | 1269 | </property> |
| 1270 | <property name="text"> | 1270 | <property name="text"> |
| 1271 | <string/> | 1271 | <string/> |
| @@ -1393,18 +1393,18 @@ | |||
| 1393 | </property> | 1393 | </property> |
| 1394 | <property name="minimumSize"> | 1394 | <property name="minimumSize"> |
| 1395 | <size> | 1395 | <size> |
| 1396 | <width>57</width> | 1396 | <width>68</width> |
| 1397 | <height>0</height> | 1397 | <height>0</height> |
| 1398 | </size> | 1398 | </size> |
| 1399 | </property> | 1399 | </property> |
| 1400 | <property name="maximumSize"> | 1400 | <property name="maximumSize"> |
| 1401 | <size> | 1401 | <size> |
| 1402 | <width>55</width> | 1402 | <width>68</width> |
| 1403 | <height>16777215</height> | 1403 | <height>16777215</height> |
| 1404 | </size> | 1404 | </size> |
| 1405 | </property> | 1405 | </property> |
| 1406 | <property name="styleSheet"> | 1406 | <property name="styleSheet"> |
| 1407 | <string notr="true">min-width: 55px;</string> | 1407 | <string notr="true">min-width: 68px;</string> |
| 1408 | </property> | 1408 | </property> |
| 1409 | <property name="text"> | 1409 | <property name="text"> |
| 1410 | <string/> | 1410 | <string/> |
| @@ -1448,18 +1448,18 @@ | |||
| 1448 | </property> | 1448 | </property> |
| 1449 | <property name="minimumSize"> | 1449 | <property name="minimumSize"> |
| 1450 | <size> | 1450 | <size> |
| 1451 | <width>57</width> | 1451 | <width>68</width> |
| 1452 | <height>0</height> | 1452 | <height>0</height> |
| 1453 | </size> | 1453 | </size> |
| 1454 | </property> | 1454 | </property> |
| 1455 | <property name="maximumSize"> | 1455 | <property name="maximumSize"> |
| 1456 | <size> | 1456 | <size> |
| 1457 | <width>55</width> | 1457 | <width>68</width> |
| 1458 | <height>16777215</height> | 1458 | <height>16777215</height> |
| 1459 | </size> | 1459 | </size> |
| 1460 | </property> | 1460 | </property> |
| 1461 | <property name="styleSheet"> | 1461 | <property name="styleSheet"> |
| 1462 | <string notr="true">min-width: 55px;</string> | 1462 | <string notr="true">min-width: 68px;</string> |
| 1463 | </property> | 1463 | </property> |
| 1464 | <property name="text"> | 1464 | <property name="text"> |
| 1465 | <string/> | 1465 | <string/> |
| @@ -1524,18 +1524,18 @@ | |||
| 1524 | </property> | 1524 | </property> |
| 1525 | <property name="minimumSize"> | 1525 | <property name="minimumSize"> |
| 1526 | <size> | 1526 | <size> |
| 1527 | <width>57</width> | 1527 | <width>68</width> |
| 1528 | <height>0</height> | 1528 | <height>0</height> |
| 1529 | </size> | 1529 | </size> |
| 1530 | </property> | 1530 | </property> |
| 1531 | <property name="maximumSize"> | 1531 | <property name="maximumSize"> |
| 1532 | <size> | 1532 | <size> |
| 1533 | <width>55</width> | 1533 | <width>68</width> |
| 1534 | <height>16777215</height> | 1534 | <height>16777215</height> |
| 1535 | </size> | 1535 | </size> |
| 1536 | </property> | 1536 | </property> |
| 1537 | <property name="styleSheet"> | 1537 | <property name="styleSheet"> |
| 1538 | <string notr="true">min-width: 55px;</string> | 1538 | <string notr="true">min-width: 68px;</string> |
| 1539 | </property> | 1539 | </property> |
| 1540 | <property name="text"> | 1540 | <property name="text"> |
| 1541 | <string/> | 1541 | <string/> |
| @@ -1579,18 +1579,18 @@ | |||
| 1579 | </property> | 1579 | </property> |
| 1580 | <property name="minimumSize"> | 1580 | <property name="minimumSize"> |
| 1581 | <size> | 1581 | <size> |
| 1582 | <width>57</width> | 1582 | <width>68</width> |
| 1583 | <height>0</height> | 1583 | <height>0</height> |
| 1584 | </size> | 1584 | </size> |
| 1585 | </property> | 1585 | </property> |
| 1586 | <property name="maximumSize"> | 1586 | <property name="maximumSize"> |
| 1587 | <size> | 1587 | <size> |
| 1588 | <width>55</width> | 1588 | <width>68</width> |
| 1589 | <height>16777215</height> | 1589 | <height>16777215</height> |
| 1590 | </size> | 1590 | </size> |
| 1591 | </property> | 1591 | </property> |
| 1592 | <property name="styleSheet"> | 1592 | <property name="styleSheet"> |
| 1593 | <string notr="true">min-width: 55px;</string> | 1593 | <string notr="true">min-width: 68px;</string> |
| 1594 | </property> | 1594 | </property> |
| 1595 | <property name="text"> | 1595 | <property name="text"> |
| 1596 | <string/> | 1596 | <string/> |
| @@ -1679,18 +1679,18 @@ | |||
| 1679 | </property> | 1679 | </property> |
| 1680 | <property name="minimumSize"> | 1680 | <property name="minimumSize"> |
| 1681 | <size> | 1681 | <size> |
| 1682 | <width>57</width> | 1682 | <width>68</width> |
| 1683 | <height>0</height> | 1683 | <height>0</height> |
| 1684 | </size> | 1684 | </size> |
| 1685 | </property> | 1685 | </property> |
| 1686 | <property name="maximumSize"> | 1686 | <property name="maximumSize"> |
| 1687 | <size> | 1687 | <size> |
| 1688 | <width>55</width> | 1688 | <width>68</width> |
| 1689 | <height>16777215</height> | 1689 | <height>16777215</height> |
| 1690 | </size> | 1690 | </size> |
| 1691 | </property> | 1691 | </property> |
| 1692 | <property name="styleSheet"> | 1692 | <property name="styleSheet"> |
| 1693 | <string notr="true">min-width: 55px;</string> | 1693 | <string notr="true">min-width: 68px;</string> |
| 1694 | </property> | 1694 | </property> |
| 1695 | <property name="text"> | 1695 | <property name="text"> |
| 1696 | <string/> | 1696 | <string/> |
| @@ -1734,18 +1734,18 @@ | |||
| 1734 | </property> | 1734 | </property> |
| 1735 | <property name="minimumSize"> | 1735 | <property name="minimumSize"> |
| 1736 | <size> | 1736 | <size> |
| 1737 | <width>57</width> | 1737 | <width>68</width> |
| 1738 | <height>0</height> | 1738 | <height>0</height> |
| 1739 | </size> | 1739 | </size> |
| 1740 | </property> | 1740 | </property> |
| 1741 | <property name="maximumSize"> | 1741 | <property name="maximumSize"> |
| 1742 | <size> | 1742 | <size> |
| 1743 | <width>55</width> | 1743 | <width>68</width> |
| 1744 | <height>16777215</height> | 1744 | <height>16777215</height> |
| 1745 | </size> | 1745 | </size> |
| 1746 | </property> | 1746 | </property> |
| 1747 | <property name="styleSheet"> | 1747 | <property name="styleSheet"> |
| 1748 | <string notr="true">min-width: 55px;</string> | 1748 | <string notr="true">min-width: 68px;</string> |
| 1749 | </property> | 1749 | </property> |
| 1750 | <property name="text"> | 1750 | <property name="text"> |
| 1751 | <string/> | 1751 | <string/> |
| @@ -1810,18 +1810,18 @@ | |||
| 1810 | </property> | 1810 | </property> |
| 1811 | <property name="minimumSize"> | 1811 | <property name="minimumSize"> |
| 1812 | <size> | 1812 | <size> |
| 1813 | <width>57</width> | 1813 | <width>68</width> |
| 1814 | <height>0</height> | 1814 | <height>0</height> |
| 1815 | </size> | 1815 | </size> |
| 1816 | </property> | 1816 | </property> |
| 1817 | <property name="maximumSize"> | 1817 | <property name="maximumSize"> |
| 1818 | <size> | 1818 | <size> |
| 1819 | <width>55</width> | 1819 | <width>68</width> |
| 1820 | <height>16777215</height> | 1820 | <height>16777215</height> |
| 1821 | </size> | 1821 | </size> |
| 1822 | </property> | 1822 | </property> |
| 1823 | <property name="styleSheet"> | 1823 | <property name="styleSheet"> |
| 1824 | <string notr="true">min-width: 55px;</string> | 1824 | <string notr="true">min-width: 68px;</string> |
| 1825 | </property> | 1825 | </property> |
| 1826 | <property name="text"> | 1826 | <property name="text"> |
| 1827 | <string/> | 1827 | <string/> |
| @@ -1865,18 +1865,18 @@ | |||
| 1865 | </property> | 1865 | </property> |
| 1866 | <property name="minimumSize"> | 1866 | <property name="minimumSize"> |
| 1867 | <size> | 1867 | <size> |
| 1868 | <width>57</width> | 1868 | <width>68</width> |
| 1869 | <height>0</height> | 1869 | <height>0</height> |
| 1870 | </size> | 1870 | </size> |
| 1871 | </property> | 1871 | </property> |
| 1872 | <property name="maximumSize"> | 1872 | <property name="maximumSize"> |
| 1873 | <size> | 1873 | <size> |
| 1874 | <width>55</width> | 1874 | <width>68</width> |
| 1875 | <height>16777215</height> | 1875 | <height>16777215</height> |
| 1876 | </size> | 1876 | </size> |
| 1877 | </property> | 1877 | </property> |
| 1878 | <property name="styleSheet"> | 1878 | <property name="styleSheet"> |
| 1879 | <string notr="true">min-width: 55px;</string> | 1879 | <string notr="true">min-width: 68px;</string> |
| 1880 | </property> | 1880 | </property> |
| 1881 | <property name="text"> | 1881 | <property name="text"> |
| 1882 | <string/> | 1882 | <string/> |
| @@ -1983,18 +1983,18 @@ | |||
| 1983 | </property> | 1983 | </property> |
| 1984 | <property name="minimumSize"> | 1984 | <property name="minimumSize"> |
| 1985 | <size> | 1985 | <size> |
| 1986 | <width>57</width> | 1986 | <width>68</width> |
| 1987 | <height>0</height> | 1987 | <height>0</height> |
| 1988 | </size> | 1988 | </size> |
| 1989 | </property> | 1989 | </property> |
| 1990 | <property name="maximumSize"> | 1990 | <property name="maximumSize"> |
| 1991 | <size> | 1991 | <size> |
| 1992 | <width>55</width> | 1992 | <width>68</width> |
| 1993 | <height>16777215</height> | 1993 | <height>16777215</height> |
| 1994 | </size> | 1994 | </size> |
| 1995 | </property> | 1995 | </property> |
| 1996 | <property name="styleSheet"> | 1996 | <property name="styleSheet"> |
| 1997 | <string notr="true">min-width: 55px;</string> | 1997 | <string notr="true">min-width: 68px;</string> |
| 1998 | </property> | 1998 | </property> |
| 1999 | <property name="text"> | 1999 | <property name="text"> |
| 2000 | <string/> | 2000 | <string/> |
| @@ -2038,18 +2038,18 @@ | |||
| 2038 | </property> | 2038 | </property> |
| 2039 | <property name="minimumSize"> | 2039 | <property name="minimumSize"> |
| 2040 | <size> | 2040 | <size> |
| 2041 | <width>57</width> | 2041 | <width>68</width> |
| 2042 | <height>0</height> | 2042 | <height>0</height> |
| 2043 | </size> | 2043 | </size> |
| 2044 | </property> | 2044 | </property> |
| 2045 | <property name="maximumSize"> | 2045 | <property name="maximumSize"> |
| 2046 | <size> | 2046 | <size> |
| 2047 | <width>55</width> | 2047 | <width>68</width> |
| 2048 | <height>16777215</height> | 2048 | <height>16777215</height> |
| 2049 | </size> | 2049 | </size> |
| 2050 | </property> | 2050 | </property> |
| 2051 | <property name="styleSheet"> | 2051 | <property name="styleSheet"> |
| 2052 | <string notr="true">min-width: 55px;</string> | 2052 | <string notr="true">min-width: 68px;</string> |
| 2053 | </property> | 2053 | </property> |
| 2054 | <property name="text"> | 2054 | <property name="text"> |
| 2055 | <string/> | 2055 | <string/> |
| @@ -2114,18 +2114,18 @@ | |||
| 2114 | </property> | 2114 | </property> |
| 2115 | <property name="minimumSize"> | 2115 | <property name="minimumSize"> |
| 2116 | <size> | 2116 | <size> |
| 2117 | <width>57</width> | 2117 | <width>68</width> |
| 2118 | <height>0</height> | 2118 | <height>0</height> |
| 2119 | </size> | 2119 | </size> |
| 2120 | </property> | 2120 | </property> |
| 2121 | <property name="maximumSize"> | 2121 | <property name="maximumSize"> |
| 2122 | <size> | 2122 | <size> |
| 2123 | <width>55</width> | 2123 | <width>68</width> |
| 2124 | <height>16777215</height> | 2124 | <height>16777215</height> |
| 2125 | </size> | 2125 | </size> |
| 2126 | </property> | 2126 | </property> |
| 2127 | <property name="styleSheet"> | 2127 | <property name="styleSheet"> |
| 2128 | <string notr="true">min-width: 55px;</string> | 2128 | <string notr="true">min-width: 68px;</string> |
| 2129 | </property> | 2129 | </property> |
| 2130 | <property name="text"> | 2130 | <property name="text"> |
| 2131 | <string/> | 2131 | <string/> |
| @@ -2169,18 +2169,18 @@ | |||
| 2169 | </property> | 2169 | </property> |
| 2170 | <property name="minimumSize"> | 2170 | <property name="minimumSize"> |
| 2171 | <size> | 2171 | <size> |
| 2172 | <width>57</width> | 2172 | <width>68</width> |
| 2173 | <height>0</height> | 2173 | <height>0</height> |
| 2174 | </size> | 2174 | </size> |
| 2175 | </property> | 2175 | </property> |
| 2176 | <property name="maximumSize"> | 2176 | <property name="maximumSize"> |
| 2177 | <size> | 2177 | <size> |
| 2178 | <width>55</width> | 2178 | <width>68</width> |
| 2179 | <height>16777215</height> | 2179 | <height>16777215</height> |
| 2180 | </size> | 2180 | </size> |
| 2181 | </property> | 2181 | </property> |
| 2182 | <property name="styleSheet"> | 2182 | <property name="styleSheet"> |
| 2183 | <string notr="true">min-width: 55px;</string> | 2183 | <string notr="true">min-width: 68px;</string> |
| 2184 | </property> | 2184 | </property> |
| 2185 | <property name="text"> | 2185 | <property name="text"> |
| 2186 | <string/> | 2186 | <string/> |
| @@ -2269,18 +2269,18 @@ | |||
| 2269 | </property> | 2269 | </property> |
| 2270 | <property name="minimumSize"> | 2270 | <property name="minimumSize"> |
| 2271 | <size> | 2271 | <size> |
| 2272 | <width>57</width> | 2272 | <width>68</width> |
| 2273 | <height>0</height> | 2273 | <height>0</height> |
| 2274 | </size> | 2274 | </size> |
| 2275 | </property> | 2275 | </property> |
| 2276 | <property name="maximumSize"> | 2276 | <property name="maximumSize"> |
| 2277 | <size> | 2277 | <size> |
| 2278 | <width>55</width> | 2278 | <width>68</width> |
| 2279 | <height>16777215</height> | 2279 | <height>16777215</height> |
| 2280 | </size> | 2280 | </size> |
| 2281 | </property> | 2281 | </property> |
| 2282 | <property name="styleSheet"> | 2282 | <property name="styleSheet"> |
| 2283 | <string notr="true">min-width: 55px;</string> | 2283 | <string notr="true">min-width: 68px;</string> |
| 2284 | </property> | 2284 | </property> |
| 2285 | <property name="text"> | 2285 | <property name="text"> |
| 2286 | <string/> | 2286 | <string/> |
| @@ -2324,18 +2324,18 @@ | |||
| 2324 | </property> | 2324 | </property> |
| 2325 | <property name="minimumSize"> | 2325 | <property name="minimumSize"> |
| 2326 | <size> | 2326 | <size> |
| 2327 | <width>57</width> | 2327 | <width>68</width> |
| 2328 | <height>0</height> | 2328 | <height>0</height> |
| 2329 | </size> | 2329 | </size> |
| 2330 | </property> | 2330 | </property> |
| 2331 | <property name="maximumSize"> | 2331 | <property name="maximumSize"> |
| 2332 | <size> | 2332 | <size> |
| 2333 | <width>55</width> | 2333 | <width>68</width> |
| 2334 | <height>16777215</height> | 2334 | <height>16777215</height> |
| 2335 | </size> | 2335 | </size> |
| 2336 | </property> | 2336 | </property> |
| 2337 | <property name="styleSheet"> | 2337 | <property name="styleSheet"> |
| 2338 | <string notr="true">min-width: 55px;</string> | 2338 | <string notr="true">min-width: 68px;</string> |
| 2339 | </property> | 2339 | </property> |
| 2340 | <property name="text"> | 2340 | <property name="text"> |
| 2341 | <string/> | 2341 | <string/> |
| @@ -2400,18 +2400,18 @@ | |||
| 2400 | </property> | 2400 | </property> |
| 2401 | <property name="minimumSize"> | 2401 | <property name="minimumSize"> |
| 2402 | <size> | 2402 | <size> |
| 2403 | <width>57</width> | 2403 | <width>68</width> |
| 2404 | <height>0</height> | 2404 | <height>0</height> |
| 2405 | </size> | 2405 | </size> |
| 2406 | </property> | 2406 | </property> |
| 2407 | <property name="maximumSize"> | 2407 | <property name="maximumSize"> |
| 2408 | <size> | 2408 | <size> |
| 2409 | <width>55</width> | 2409 | <width>68</width> |
| 2410 | <height>16777215</height> | 2410 | <height>16777215</height> |
| 2411 | </size> | 2411 | </size> |
| 2412 | </property> | 2412 | </property> |
| 2413 | <property name="styleSheet"> | 2413 | <property name="styleSheet"> |
| 2414 | <string notr="true">min-width: 55px;</string> | 2414 | <string notr="true">min-width: 68px;</string> |
| 2415 | </property> | 2415 | </property> |
| 2416 | <property name="text"> | 2416 | <property name="text"> |
| 2417 | <string/> | 2417 | <string/> |
| @@ -2455,18 +2455,18 @@ | |||
| 2455 | </property> | 2455 | </property> |
| 2456 | <property name="minimumSize"> | 2456 | <property name="minimumSize"> |
| 2457 | <size> | 2457 | <size> |
| 2458 | <width>57</width> | 2458 | <width>68</width> |
| 2459 | <height>0</height> | 2459 | <height>0</height> |
| 2460 | </size> | 2460 | </size> |
| 2461 | </property> | 2461 | </property> |
| 2462 | <property name="maximumSize"> | 2462 | <property name="maximumSize"> |
| 2463 | <size> | 2463 | <size> |
| 2464 | <width>55</width> | 2464 | <width>68</width> |
| 2465 | <height>16777215</height> | 2465 | <height>16777215</height> |
| 2466 | </size> | 2466 | </size> |
| 2467 | </property> | 2467 | </property> |
| 2468 | <property name="styleSheet"> | 2468 | <property name="styleSheet"> |
| 2469 | <string notr="true">min-width: 55px;</string> | 2469 | <string notr="true">min-width: 68px;</string> |
| 2470 | </property> | 2470 | </property> |
| 2471 | <property name="text"> | 2471 | <property name="text"> |
| 2472 | <string/> | 2472 | <string/> |
diff --git a/src/yuzu/configuration/configure_input_dialog.cpp b/src/yuzu/configuration/configure_input_dialog.cpp deleted file mode 100644 index 1866003c2..000000000 --- a/src/yuzu/configuration/configure_input_dialog.cpp +++ /dev/null | |||
| @@ -1,37 +0,0 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "ui_configure_input_dialog.h" | ||
| 6 | #include "yuzu/configuration/configure_input_dialog.h" | ||
| 7 | |||
| 8 | ConfigureInputDialog::ConfigureInputDialog(QWidget* parent, std::size_t max_players, | ||
| 9 | InputCommon::InputSubsystem* input_subsystem) | ||
| 10 | : QDialog(parent), ui(std::make_unique<Ui::ConfigureInputDialog>()), | ||
| 11 | input_widget(new ConfigureInput(this)) { | ||
| 12 | ui->setupUi(this); | ||
| 13 | |||
| 14 | input_widget->Initialize(input_subsystem, max_players); | ||
| 15 | |||
| 16 | ui->inputLayout->addWidget(input_widget); | ||
| 17 | |||
| 18 | RetranslateUI(); | ||
| 19 | } | ||
| 20 | |||
| 21 | ConfigureInputDialog::~ConfigureInputDialog() = default; | ||
| 22 | |||
| 23 | void ConfigureInputDialog::ApplyConfiguration() { | ||
| 24 | input_widget->ApplyConfiguration(); | ||
| 25 | } | ||
| 26 | |||
| 27 | void ConfigureInputDialog::changeEvent(QEvent* event) { | ||
| 28 | if (event->type() == QEvent::LanguageChange) { | ||
| 29 | RetranslateUI(); | ||
| 30 | } | ||
| 31 | |||
| 32 | QDialog::changeEvent(event); | ||
| 33 | } | ||
| 34 | |||
| 35 | void ConfigureInputDialog::RetranslateUI() { | ||
| 36 | ui->retranslateUi(this); | ||
| 37 | } | ||
diff --git a/src/yuzu/configuration/configure_input_dialog.h b/src/yuzu/configuration/configure_input_dialog.h deleted file mode 100644 index d1bd865f9..000000000 --- a/src/yuzu/configuration/configure_input_dialog.h +++ /dev/null | |||
| @@ -1,38 +0,0 @@ | |||
| 1 | // Copyright 2020 yuzu 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 <memory> | ||
| 8 | #include <QDialog> | ||
| 9 | #include "yuzu/configuration/configure_input.h" | ||
| 10 | |||
| 11 | class QPushButton; | ||
| 12 | |||
| 13 | namespace InputCommon { | ||
| 14 | class InputSubsystem; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace Ui { | ||
| 18 | class ConfigureInputDialog; | ||
| 19 | } | ||
| 20 | |||
| 21 | class ConfigureInputDialog : public QDialog { | ||
| 22 | Q_OBJECT | ||
| 23 | |||
| 24 | public: | ||
| 25 | explicit ConfigureInputDialog(QWidget* parent, std::size_t max_players, | ||
| 26 | InputCommon::InputSubsystem* input_subsystem); | ||
| 27 | ~ConfigureInputDialog() override; | ||
| 28 | |||
| 29 | void ApplyConfiguration(); | ||
| 30 | |||
| 31 | private: | ||
| 32 | void changeEvent(QEvent* event) override; | ||
| 33 | void RetranslateUI(); | ||
| 34 | |||
| 35 | std::unique_ptr<Ui::ConfigureInputDialog> ui; | ||
| 36 | |||
| 37 | ConfigureInput* input_widget; | ||
| 38 | }; | ||
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index f58ca29d7..72640f5e7 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <memory> | 6 | #include <memory> |
| 7 | #include <thread> | ||
| 7 | #include <utility> | 8 | #include <utility> |
| 8 | #include <QGridLayout> | 9 | #include <QGridLayout> |
| 9 | #include <QInputDialog> | 10 | #include <QInputDialog> |
| @@ -22,8 +23,9 @@ | |||
| 22 | #include "ui_configure_input_player.h" | 23 | #include "ui_configure_input_player.h" |
| 23 | #include "yuzu/configuration/config.h" | 24 | #include "yuzu/configuration/config.h" |
| 24 | #include "yuzu/configuration/configure_input_player.h" | 25 | #include "yuzu/configuration/configure_input_player.h" |
| 25 | 26 | #include "yuzu/configuration/configure_vibration.h" | |
| 26 | constexpr std::size_t HANDHELD_INDEX = 8; | 27 | #include "yuzu/configuration/input_profiles.h" |
| 28 | #include "yuzu/util/limitable_input_dialog.h" | ||
| 27 | 29 | ||
| 28 | const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM> | 30 | const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM> |
| 29 | ConfigureInputPlayer::analog_sub_buttons{{ | 31 | ConfigureInputPlayer::analog_sub_buttons{{ |
| @@ -35,6 +37,8 @@ const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM> | |||
| 35 | 37 | ||
| 36 | namespace { | 38 | namespace { |
| 37 | 39 | ||
| 40 | constexpr std::size_t HANDHELD_INDEX = 8; | ||
| 41 | |||
| 38 | void UpdateController(Settings::ControllerType controller_type, std::size_t npad_index, | 42 | void UpdateController(Settings::ControllerType controller_type, std::size_t npad_index, |
| 39 | bool connected) { | 43 | bool connected) { |
| 40 | Core::System& system{Core::System::GetInstance()}; | 44 | Core::System& system{Core::System::GetInstance()}; |
| @@ -240,10 +244,11 @@ QString AnalogToText(const Common::ParamPackage& param, const std::string& dir) | |||
| 240 | ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index, | 244 | ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index, |
| 241 | QWidget* bottom_row, | 245 | QWidget* bottom_row, |
| 242 | InputCommon::InputSubsystem* input_subsystem_, | 246 | InputCommon::InputSubsystem* input_subsystem_, |
| 243 | bool debug) | 247 | InputProfiles* profiles_, bool debug) |
| 244 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index), | 248 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index), |
| 245 | debug(debug), input_subsystem{input_subsystem_}, timeout_timer(std::make_unique<QTimer>()), | 249 | debug(debug), input_subsystem{input_subsystem_}, profiles(profiles_), |
| 246 | poll_timer(std::make_unique<QTimer>()), bottom_row(bottom_row) { | 250 | timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()), |
| 251 | bottom_row(bottom_row) { | ||
| 247 | ui->setupUi(this); | 252 | ui->setupUi(this); |
| 248 | 253 | ||
| 249 | setFocusPolicy(Qt::ClickFocus); | 254 | setFocusPolicy(Qt::ClickFocus); |
| @@ -366,6 +371,18 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 366 | } | 371 | } |
| 367 | 372 | ||
| 368 | connect(analog_button, &QPushButton::clicked, [=, this] { | 373 | connect(analog_button, &QPushButton::clicked, [=, this] { |
| 374 | if (!map_analog_stick_accepted) { | ||
| 375 | map_analog_stick_accepted = | ||
| 376 | QMessageBox::information( | ||
| 377 | this, tr("Map Analog Stick"), | ||
| 378 | tr("After pressing OK, first move your joystick horizontally, and then " | ||
| 379 | "vertically.\nTo invert the axes, first move your joystick " | ||
| 380 | "vertically, and then horizontally."), | ||
| 381 | QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok; | ||
| 382 | if (!map_analog_stick_accepted) { | ||
| 383 | return; | ||
| 384 | } | ||
| 385 | } | ||
| 369 | HandleClick( | 386 | HandleClick( |
| 370 | analog_map_buttons[analog_id][sub_button_id], | 387 | analog_map_buttons[analog_id][sub_button_id], |
| 371 | [=, this](const Common::ParamPackage& params) { | 388 | [=, this](const Common::ParamPackage& params) { |
| @@ -455,11 +472,14 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 455 | }); | 472 | }); |
| 456 | } | 473 | } |
| 457 | 474 | ||
| 475 | if (debug || player_index == 9) { | ||
| 476 | ui->groupConnectedController->setCheckable(false); | ||
| 477 | } | ||
| 478 | |||
| 458 | // The Debug Controller can only choose the Pro Controller. | 479 | // The Debug Controller can only choose the Pro Controller. |
| 459 | if (debug) { | 480 | if (debug) { |
| 460 | ui->buttonScreenshot->setEnabled(false); | 481 | ui->buttonScreenshot->setEnabled(false); |
| 461 | ui->buttonHome->setEnabled(false); | 482 | ui->buttonHome->setEnabled(false); |
| 462 | ui->groupConnectedController->setCheckable(false); | ||
| 463 | QStringList debug_controller_types = { | 483 | QStringList debug_controller_types = { |
| 464 | tr("Pro Controller"), | 484 | tr("Pro Controller"), |
| 465 | }; | 485 | }; |
| @@ -477,11 +497,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 477 | UpdateMotionButtons(); | 497 | UpdateMotionButtons(); |
| 478 | }); | 498 | }); |
| 479 | 499 | ||
| 480 | connect(ui->comboDevices, qOverload<int>(&QComboBox::currentIndexChanged), this, | 500 | connect(ui->comboDevices, qOverload<int>(&QComboBox::activated), this, |
| 481 | &ConfigureInputPlayer::UpdateMappingWithDefaults); | 501 | &ConfigureInputPlayer::UpdateMappingWithDefaults); |
| 482 | 502 | ||
| 503 | ui->comboDevices->setCurrentIndex(-1); | ||
| 504 | |||
| 483 | ui->buttonRefreshDevices->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); | 505 | ui->buttonRefreshDevices->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); |
| 484 | UpdateInputDevices(); | ||
| 485 | connect(ui->buttonRefreshDevices, &QPushButton::clicked, | 506 | connect(ui->buttonRefreshDevices, &QPushButton::clicked, |
| 486 | [this] { emit RefreshInputDevices(); }); | 507 | [this] { emit RefreshInputDevices(); }); |
| 487 | 508 | ||
| @@ -492,14 +513,14 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 492 | Common::ParamPackage params; | 513 | Common::ParamPackage params; |
| 493 | if (input_subsystem->GetGCButtons()->IsPolling()) { | 514 | if (input_subsystem->GetGCButtons()->IsPolling()) { |
| 494 | params = input_subsystem->GetGCButtons()->GetNextInput(); | 515 | params = input_subsystem->GetGCButtons()->GetNextInput(); |
| 495 | if (params.Has("engine")) { | 516 | if (params.Has("engine") && IsInputAcceptable(params)) { |
| 496 | SetPollingResult(params, false); | 517 | SetPollingResult(params, false); |
| 497 | return; | 518 | return; |
| 498 | } | 519 | } |
| 499 | } | 520 | } |
| 500 | if (input_subsystem->GetGCAnalogs()->IsPolling()) { | 521 | if (input_subsystem->GetGCAnalogs()->IsPolling()) { |
| 501 | params = input_subsystem->GetGCAnalogs()->GetNextInput(); | 522 | params = input_subsystem->GetGCAnalogs()->GetNextInput(); |
| 502 | if (params.Has("engine")) { | 523 | if (params.Has("engine") && IsInputAcceptable(params)) { |
| 503 | SetPollingResult(params, false); | 524 | SetPollingResult(params, false); |
| 504 | return; | 525 | return; |
| 505 | } | 526 | } |
| @@ -513,13 +534,24 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 513 | } | 534 | } |
| 514 | for (auto& poller : device_pollers) { | 535 | for (auto& poller : device_pollers) { |
| 515 | params = poller->GetNextInput(); | 536 | params = poller->GetNextInput(); |
| 516 | if (params.Has("engine")) { | 537 | if (params.Has("engine") && IsInputAcceptable(params)) { |
| 517 | SetPollingResult(params, false); | 538 | SetPollingResult(params, false); |
| 518 | return; | 539 | return; |
| 519 | } | 540 | } |
| 520 | } | 541 | } |
| 521 | }); | 542 | }); |
| 522 | 543 | ||
| 544 | UpdateInputProfiles(); | ||
| 545 | |||
| 546 | connect(ui->buttonProfilesNew, &QPushButton::clicked, this, | ||
| 547 | &ConfigureInputPlayer::CreateProfile); | ||
| 548 | connect(ui->buttonProfilesDelete, &QPushButton::clicked, this, | ||
| 549 | &ConfigureInputPlayer::DeleteProfile); | ||
| 550 | connect(ui->comboProfiles, qOverload<int>(&QComboBox::activated), this, | ||
| 551 | &ConfigureInputPlayer::LoadProfile); | ||
| 552 | connect(ui->buttonProfilesSave, &QPushButton::clicked, this, | ||
| 553 | &ConfigureInputPlayer::SaveProfile); | ||
| 554 | |||
| 523 | LoadConfiguration(); | 555 | LoadConfiguration(); |
| 524 | 556 | ||
| 525 | // TODO(wwylele): enable this when we actually emulate it | 557 | // TODO(wwylele): enable this when we actually emulate it |
| @@ -529,7 +561,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 529 | ConfigureInputPlayer::~ConfigureInputPlayer() = default; | 561 | ConfigureInputPlayer::~ConfigureInputPlayer() = default; |
| 530 | 562 | ||
| 531 | void ConfigureInputPlayer::ApplyConfiguration() { | 563 | void ConfigureInputPlayer::ApplyConfiguration() { |
| 532 | auto& player = Settings::values.players[player_index]; | 564 | auto& player = Settings::values.players.GetValue()[player_index]; |
| 533 | auto& buttons = debug ? Settings::values.debug_pad_buttons : player.buttons; | 565 | auto& buttons = debug ? Settings::values.debug_pad_buttons : player.buttons; |
| 534 | auto& analogs = debug ? Settings::values.debug_pad_analogs : player.analogs; | 566 | auto& analogs = debug ? Settings::values.debug_pad_analogs : player.analogs; |
| 535 | 567 | ||
| @@ -543,33 +575,58 @@ void ConfigureInputPlayer::ApplyConfiguration() { | |||
| 543 | } | 575 | } |
| 544 | 576 | ||
| 545 | auto& motions = player.motions; | 577 | auto& motions = player.motions; |
| 578 | |||
| 546 | std::transform(motions_param.begin(), motions_param.end(), motions.begin(), | 579 | std::transform(motions_param.begin(), motions_param.end(), motions.begin(), |
| 547 | [](const Common::ParamPackage& param) { return param.Serialize(); }); | 580 | [](const Common::ParamPackage& param) { return param.Serialize(); }); |
| 548 | 581 | ||
| 549 | player.controller_type = | 582 | const auto controller_type = |
| 550 | static_cast<Settings::ControllerType>(ui->comboControllerType->currentIndex()); | 583 | GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); |
| 551 | player.connected = ui->groupConnectedController->isChecked(); | 584 | const auto player_connected = ui->groupConnectedController->isChecked() && |
| 585 | controller_type != Settings::ControllerType::Handheld; | ||
| 552 | 586 | ||
| 553 | // Player 2-8 | 587 | if (player.controller_type == controller_type && player.connected == player_connected) { |
| 554 | if (player_index != 0) { | 588 | // Set vibration devices in the event that the input device has changed. |
| 555 | UpdateController(player.controller_type, player_index, player.connected); | 589 | ConfigureVibration::SetVibrationDevices(player_index); |
| 556 | return; | 590 | return; |
| 557 | } | 591 | } |
| 558 | 592 | ||
| 559 | // Player 1 and Handheld | 593 | // Disconnect the controller first. |
| 560 | auto& handheld = Settings::values.players[HANDHELD_INDEX]; | 594 | UpdateController(controller_type, player_index, false); |
| 561 | // If Handheld is selected, copy all the settings from Player 1 to Handheld. | 595 | |
| 562 | if (player.controller_type == Settings::ControllerType::Handheld) { | 596 | player.controller_type = controller_type; |
| 563 | handheld = player; | 597 | player.connected = player_connected; |
| 564 | handheld.connected = ui->groupConnectedController->isChecked(); | 598 | |
| 565 | player.connected = false; // Disconnect Player 1 | 599 | ConfigureVibration::SetVibrationDevices(player_index); |
| 566 | } else { | 600 | |
| 567 | player.connected = ui->groupConnectedController->isChecked(); | 601 | // Handheld |
| 568 | handheld.connected = false; // Disconnect Handheld | 602 | if (player_index == 0) { |
| 603 | auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX]; | ||
| 604 | if (controller_type == Settings::ControllerType::Handheld) { | ||
| 605 | handheld = player; | ||
| 606 | } | ||
| 607 | handheld.connected = ui->groupConnectedController->isChecked() && | ||
| 608 | controller_type == Settings::ControllerType::Handheld; | ||
| 609 | UpdateController(Settings::ControllerType::Handheld, HANDHELD_INDEX, handheld.connected); | ||
| 610 | } | ||
| 611 | |||
| 612 | if (!player.connected) { | ||
| 613 | return; | ||
| 569 | } | 614 | } |
| 570 | 615 | ||
| 571 | UpdateController(player.controller_type, player_index, player.connected); | 616 | // This emulates a delay between disconnecting and reconnecting controllers as some games |
| 572 | UpdateController(Settings::ControllerType::Handheld, HANDHELD_INDEX, handheld.connected); | 617 | // do not respond to a change in controller type if it was instantaneous. |
| 618 | using namespace std::chrono_literals; | ||
| 619 | std::this_thread::sleep_for(20ms); | ||
| 620 | |||
| 621 | UpdateController(controller_type, player_index, player_connected); | ||
| 622 | } | ||
| 623 | |||
| 624 | void ConfigureInputPlayer::showEvent(QShowEvent* event) { | ||
| 625 | if (bottom_row == nullptr) { | ||
| 626 | return; | ||
| 627 | } | ||
| 628 | QWidget::showEvent(event); | ||
| 629 | ui->main->addWidget(bottom_row); | ||
| 573 | } | 630 | } |
| 574 | 631 | ||
| 575 | void ConfigureInputPlayer::changeEvent(QEvent* event) { | 632 | void ConfigureInputPlayer::changeEvent(QEvent* event) { |
| @@ -586,7 +643,7 @@ void ConfigureInputPlayer::RetranslateUI() { | |||
| 586 | } | 643 | } |
| 587 | 644 | ||
| 588 | void ConfigureInputPlayer::LoadConfiguration() { | 645 | void ConfigureInputPlayer::LoadConfiguration() { |
| 589 | auto& player = Settings::values.players[player_index]; | 646 | auto& player = Settings::values.players.GetValue()[player_index]; |
| 590 | if (debug) { | 647 | if (debug) { |
| 591 | std::transform(Settings::values.debug_pad_buttons.begin(), | 648 | std::transform(Settings::values.debug_pad_buttons.begin(), |
| 592 | Settings::values.debug_pad_buttons.end(), buttons_param.begin(), | 649 | Settings::values.debug_pad_buttons.end(), buttons_param.begin(), |
| @@ -604,6 +661,7 @@ void ConfigureInputPlayer::LoadConfiguration() { | |||
| 604 | } | 661 | } |
| 605 | 662 | ||
| 606 | UpdateUI(); | 663 | UpdateUI(); |
| 664 | UpdateInputDeviceCombobox(); | ||
| 607 | 665 | ||
| 608 | if (debug) { | 666 | if (debug) { |
| 609 | return; | 667 | return; |
| @@ -612,44 +670,75 @@ void ConfigureInputPlayer::LoadConfiguration() { | |||
| 612 | ui->comboControllerType->setCurrentIndex(static_cast<int>(player.controller_type)); | 670 | ui->comboControllerType->setCurrentIndex(static_cast<int>(player.controller_type)); |
| 613 | ui->groupConnectedController->setChecked( | 671 | ui->groupConnectedController->setChecked( |
| 614 | player.connected || | 672 | player.connected || |
| 615 | (player_index == 0 && Settings::values.players[HANDHELD_INDEX].connected)); | 673 | (player_index == 0 && Settings::values.players.GetValue()[HANDHELD_INDEX].connected)); |
| 616 | } | 674 | } |
| 617 | 675 | ||
| 618 | void ConfigureInputPlayer::UpdateInputDevices() { | 676 | void ConfigureInputPlayer::ConnectPlayer(bool connected) { |
| 619 | input_devices = input_subsystem->GetInputDevices(); | 677 | ui->groupConnectedController->setChecked(connected); |
| 620 | ui->comboDevices->clear(); | ||
| 621 | for (auto device : input_devices) { | ||
| 622 | ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {}); | ||
| 623 | } | ||
| 624 | } | 678 | } |
| 625 | 679 | ||
| 626 | void ConfigureInputPlayer::RestoreDefaults() { | 680 | void ConfigureInputPlayer::UpdateInputDeviceCombobox() { |
| 627 | // Reset Buttons | 681 | // Skip input device persistence if "Input Devices" is set to "Any". |
| 628 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { | 682 | if (ui->comboDevices->currentIndex() == 0) { |
| 629 | buttons_param[button_id] = Common::ParamPackage{ | 683 | UpdateInputDevices(); |
| 630 | InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; | 684 | return; |
| 631 | } | 685 | } |
| 632 | 686 | ||
| 633 | // Reset Analogs and Modifier Buttons | 687 | // Find the first button that isn't empty. |
| 634 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { | 688 | const auto button_param = |
| 635 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { | 689 | std::find_if(buttons_param.begin(), buttons_param.end(), |
| 636 | Common::ParamPackage params{InputCommon::GenerateKeyboardParam( | 690 | [](const Common::ParamPackage param) { return param.Has("engine"); }); |
| 637 | Config::default_analogs[analog_id][sub_button_id])}; | 691 | const bool buttons_empty = button_param == buttons_param.end(); |
| 638 | SetAnalogParam(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]); | ||
| 639 | } | ||
| 640 | 692 | ||
| 641 | analogs_param[analog_id].Set( | 693 | const auto current_engine = button_param->Get("engine", ""); |
| 642 | "modifier", InputCommon::GenerateKeyboardParam(Config::default_stick_mod[analog_id])); | 694 | const auto current_guid = button_param->Get("guid", ""); |
| 695 | const auto current_port = button_param->Get("port", ""); | ||
| 696 | |||
| 697 | const bool is_keyboard_mouse = current_engine == "keyboard" || current_engine == "mouse"; | ||
| 698 | |||
| 699 | UpdateInputDevices(); | ||
| 700 | |||
| 701 | if (buttons_empty) { | ||
| 702 | return; | ||
| 643 | } | 703 | } |
| 644 | 704 | ||
| 645 | for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) { | 705 | const bool all_one_device = |
| 646 | motions_param[motion_id] = Common::ParamPackage{ | 706 | std::all_of(buttons_param.begin(), buttons_param.end(), |
| 647 | InputCommon::GenerateKeyboardParam(Config::default_motions[motion_id])}; | 707 | [current_engine, current_guid, current_port, |
| 708 | is_keyboard_mouse](const Common::ParamPackage param) { | ||
| 709 | if (is_keyboard_mouse) { | ||
| 710 | return !param.Has("engine") || param.Get("engine", "") == "keyboard" || | ||
| 711 | param.Get("engine", "") == "mouse"; | ||
| 712 | } | ||
| 713 | return !param.Has("engine") || (param.Get("engine", "") == current_engine && | ||
| 714 | param.Get("guid", "") == current_guid && | ||
| 715 | param.Get("port", "") == current_port); | ||
| 716 | }); | ||
| 717 | |||
| 718 | if (all_one_device) { | ||
| 719 | if (is_keyboard_mouse) { | ||
| 720 | ui->comboDevices->setCurrentIndex(1); | ||
| 721 | return; | ||
| 722 | } | ||
| 723 | const auto devices_it = std::find_if( | ||
| 724 | input_devices.begin(), input_devices.end(), | ||
| 725 | [current_engine, current_guid, current_port](const Common::ParamPackage param) { | ||
| 726 | return param.Get("class", "") == current_engine && | ||
| 727 | param.Get("guid", "") == current_guid && | ||
| 728 | param.Get("port", "") == current_port; | ||
| 729 | }); | ||
| 730 | const int device_index = | ||
| 731 | devices_it != input_devices.end() | ||
| 732 | ? static_cast<int>(std::distance(input_devices.begin(), devices_it)) | ||
| 733 | : 0; | ||
| 734 | ui->comboDevices->setCurrentIndex(device_index); | ||
| 735 | } else { | ||
| 736 | ui->comboDevices->setCurrentIndex(0); | ||
| 648 | } | 737 | } |
| 738 | } | ||
| 649 | 739 | ||
| 650 | UpdateUI(); | 740 | void ConfigureInputPlayer::RestoreDefaults() { |
| 651 | UpdateInputDevices(); | 741 | UpdateMappingWithDefaults(); |
| 652 | ui->comboControllerType->setCurrentIndex(0); | ||
| 653 | } | 742 | } |
| 654 | 743 | ||
| 655 | void ConfigureInputPlayer::ClearAll() { | 744 | void ConfigureInputPlayer::ClearAll() { |
| @@ -752,10 +841,167 @@ void ConfigureInputPlayer::UpdateUI() { | |||
| 752 | } | 841 | } |
| 753 | } | 842 | } |
| 754 | 843 | ||
| 844 | void ConfigureInputPlayer::UpdateInputDevices() { | ||
| 845 | input_devices = input_subsystem->GetInputDevices(); | ||
| 846 | ui->comboDevices->clear(); | ||
| 847 | for (auto device : input_devices) { | ||
| 848 | ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {}); | ||
| 849 | } | ||
| 850 | } | ||
| 851 | |||
| 852 | void ConfigureInputPlayer::UpdateControllerIcon() { | ||
| 853 | // We aren't using Qt's built in theme support here since we aren't drawing an icon (and its | ||
| 854 | // "nonstandard" to use an image through the icon support) | ||
| 855 | const QString stylesheet = [this] { | ||
| 856 | switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) { | ||
| 857 | case Settings::ControllerType::ProController: | ||
| 858 | return QStringLiteral("image: url(:/controller/pro_controller%0)"); | ||
| 859 | case Settings::ControllerType::DualJoyconDetached: | ||
| 860 | return QStringLiteral("image: url(:/controller/dual_joycon%0)"); | ||
| 861 | case Settings::ControllerType::LeftJoycon: | ||
| 862 | return QStringLiteral("image: url(:/controller/single_joycon_left_vertical%0)"); | ||
| 863 | case Settings::ControllerType::RightJoycon: | ||
| 864 | return QStringLiteral("image: url(:/controller/single_joycon_right_vertical%0)"); | ||
| 865 | case Settings::ControllerType::Handheld: | ||
| 866 | return QStringLiteral("image: url(:/controller/handheld%0)"); | ||
| 867 | default: | ||
| 868 | return QString{}; | ||
| 869 | } | ||
| 870 | }(); | ||
| 871 | |||
| 872 | const QString theme = [] { | ||
| 873 | if (QIcon::themeName().contains(QStringLiteral("dark"))) { | ||
| 874 | return QStringLiteral("_dark"); | ||
| 875 | } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { | ||
| 876 | return QStringLiteral("_midnight"); | ||
| 877 | } else { | ||
| 878 | return QString{}; | ||
| 879 | } | ||
| 880 | }(); | ||
| 881 | |||
| 882 | ui->controllerFrame->setStyleSheet(stylesheet.arg(theme)); | ||
| 883 | } | ||
| 884 | |||
| 885 | void ConfigureInputPlayer::UpdateControllerAvailableButtons() { | ||
| 886 | auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); | ||
| 887 | if (debug) { | ||
| 888 | layout = Settings::ControllerType::ProController; | ||
| 889 | } | ||
| 890 | |||
| 891 | // List of all the widgets that will be hidden by any of the following layouts that need | ||
| 892 | // "unhidden" after the controller type changes | ||
| 893 | const std::array<QWidget*, 9> layout_show = { | ||
| 894 | ui->buttonShoulderButtonsSLSR, | ||
| 895 | ui->horizontalSpacerShoulderButtonsWidget, | ||
| 896 | ui->horizontalSpacerShoulderButtonsWidget2, | ||
| 897 | ui->buttonShoulderButtonsLeft, | ||
| 898 | ui->buttonMiscButtonsMinusScreenshot, | ||
| 899 | ui->bottomLeft, | ||
| 900 | ui->buttonShoulderButtonsRight, | ||
| 901 | ui->buttonMiscButtonsPlusHome, | ||
| 902 | ui->bottomRight, | ||
| 903 | }; | ||
| 904 | |||
| 905 | for (auto* widget : layout_show) { | ||
| 906 | widget->show(); | ||
| 907 | } | ||
| 908 | |||
| 909 | std::vector<QWidget*> layout_hidden; | ||
| 910 | switch (layout) { | ||
| 911 | case Settings::ControllerType::ProController: | ||
| 912 | case Settings::ControllerType::DualJoyconDetached: | ||
| 913 | case Settings::ControllerType::Handheld: | ||
| 914 | layout_hidden = { | ||
| 915 | ui->buttonShoulderButtonsSLSR, | ||
| 916 | ui->horizontalSpacerShoulderButtonsWidget2, | ||
| 917 | }; | ||
| 918 | break; | ||
| 919 | case Settings::ControllerType::LeftJoycon: | ||
| 920 | layout_hidden = { | ||
| 921 | ui->horizontalSpacerShoulderButtonsWidget2, | ||
| 922 | ui->buttonShoulderButtonsRight, | ||
| 923 | ui->buttonMiscButtonsPlusHome, | ||
| 924 | ui->bottomRight, | ||
| 925 | }; | ||
| 926 | break; | ||
| 927 | case Settings::ControllerType::RightJoycon: | ||
| 928 | layout_hidden = { | ||
| 929 | ui->horizontalSpacerShoulderButtonsWidget, | ||
| 930 | ui->buttonShoulderButtonsLeft, | ||
| 931 | ui->buttonMiscButtonsMinusScreenshot, | ||
| 932 | ui->bottomLeft, | ||
| 933 | }; | ||
| 934 | break; | ||
| 935 | } | ||
| 936 | |||
| 937 | for (auto* widget : layout_hidden) { | ||
| 938 | widget->hide(); | ||
| 939 | } | ||
| 940 | } | ||
| 941 | |||
| 942 | void ConfigureInputPlayer::UpdateMotionButtons() { | ||
| 943 | if (debug) { | ||
| 944 | // Motion isn't used with the debug controller, hide both groupboxes. | ||
| 945 | ui->buttonMotionLeftGroup->hide(); | ||
| 946 | ui->buttonMotionRightGroup->hide(); | ||
| 947 | return; | ||
| 948 | } | ||
| 949 | |||
| 950 | // Show/hide the "Motion 1/2" groupboxes depending on the currently selected controller. | ||
| 951 | switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) { | ||
| 952 | case Settings::ControllerType::ProController: | ||
| 953 | case Settings::ControllerType::LeftJoycon: | ||
| 954 | case Settings::ControllerType::Handheld: | ||
| 955 | // Show "Motion 1" and hide "Motion 2". | ||
| 956 | ui->buttonMotionLeftGroup->show(); | ||
| 957 | ui->buttonMotionRightGroup->hide(); | ||
| 958 | break; | ||
| 959 | case Settings::ControllerType::RightJoycon: | ||
| 960 | // Show "Motion 2" and hide "Motion 1". | ||
| 961 | ui->buttonMotionLeftGroup->hide(); | ||
| 962 | ui->buttonMotionRightGroup->show(); | ||
| 963 | break; | ||
| 964 | case Settings::ControllerType::DualJoyconDetached: | ||
| 965 | default: | ||
| 966 | // Show both "Motion 1/2". | ||
| 967 | ui->buttonMotionLeftGroup->show(); | ||
| 968 | ui->buttonMotionRightGroup->show(); | ||
| 969 | break; | ||
| 970 | } | ||
| 971 | } | ||
| 972 | |||
| 755 | void ConfigureInputPlayer::UpdateMappingWithDefaults() { | 973 | void ConfigureInputPlayer::UpdateMappingWithDefaults() { |
| 756 | if (ui->comboDevices->currentIndex() < 2) { | 974 | if (ui->comboDevices->currentIndex() == 0) { |
| 757 | return; | 975 | return; |
| 758 | } | 976 | } |
| 977 | |||
| 978 | if (ui->comboDevices->currentIndex() == 1) { | ||
| 979 | // Reset keyboard bindings | ||
| 980 | for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; ++button_id) { | ||
| 981 | buttons_param[button_id] = Common::ParamPackage{ | ||
| 982 | InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; | ||
| 983 | } | ||
| 984 | for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; ++analog_id) { | ||
| 985 | for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) { | ||
| 986 | Common::ParamPackage params{InputCommon::GenerateKeyboardParam( | ||
| 987 | Config::default_analogs[analog_id][sub_button_id])}; | ||
| 988 | SetAnalogParam(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]); | ||
| 989 | } | ||
| 990 | |||
| 991 | analogs_param[analog_id].Set("modifier", InputCommon::GenerateKeyboardParam( | ||
| 992 | Config::default_stick_mod[analog_id])); | ||
| 993 | } | ||
| 994 | |||
| 995 | for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) { | ||
| 996 | motions_param[motion_id] = Common::ParamPackage{ | ||
| 997 | InputCommon::GenerateKeyboardParam(Config::default_motions[motion_id])}; | ||
| 998 | } | ||
| 999 | |||
| 1000 | UpdateUI(); | ||
| 1001 | return; | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | // Reset controller bindings | ||
| 759 | const auto& device = input_devices[ui->comboDevices->currentIndex()]; | 1005 | const auto& device = input_devices[ui->comboDevices->currentIndex()]; |
| 760 | auto button_mapping = input_subsystem->GetButtonMappingForDevice(device); | 1006 | auto button_mapping = input_subsystem->GetButtonMappingForDevice(device); |
| 761 | auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device); | 1007 | auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device); |
| @@ -828,9 +1074,27 @@ void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, | |||
| 828 | } | 1074 | } |
| 829 | 1075 | ||
| 830 | UpdateUI(); | 1076 | UpdateUI(); |
| 1077 | UpdateInputDeviceCombobox(); | ||
| 1078 | |||
| 831 | input_setter = std::nullopt; | 1079 | input_setter = std::nullopt; |
| 832 | } | 1080 | } |
| 833 | 1081 | ||
| 1082 | bool ConfigureInputPlayer::IsInputAcceptable(const Common::ParamPackage& params) const { | ||
| 1083 | if (ui->comboDevices->currentIndex() == 0) { | ||
| 1084 | return true; | ||
| 1085 | } | ||
| 1086 | |||
| 1087 | // Keyboard/Mouse | ||
| 1088 | if (ui->comboDevices->currentIndex() == 1) { | ||
| 1089 | return params.Get("engine", "") == "keyboard" || params.Get("engine", "") == "mouse"; | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | const auto current_input_device = input_devices[ui->comboDevices->currentIndex()]; | ||
| 1093 | return params.Get("engine", "") == current_input_device.Get("class", "") && | ||
| 1094 | params.Get("guid", "") == current_input_device.Get("guid", "") && | ||
| 1095 | params.Get("port", "") == current_input_device.Get("port", ""); | ||
| 1096 | } | ||
| 1097 | |||
| 834 | void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) { | 1098 | void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) { |
| 835 | if (!input_setter || !event) { | 1099 | if (!input_setter || !event) { |
| 836 | return; | 1100 | return; |
| @@ -865,135 +1129,101 @@ void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) { | |||
| 865 | SetPollingResult({}, true); | 1129 | SetPollingResult({}, true); |
| 866 | } | 1130 | } |
| 867 | 1131 | ||
| 868 | void ConfigureInputPlayer::UpdateControllerIcon() { | 1132 | void ConfigureInputPlayer::CreateProfile() { |
| 869 | // We aren't using Qt's built in theme support here since we aren't drawing an icon (and its | 1133 | const auto profile_name = |
| 870 | // "nonstandard" to use an image through the icon support) | 1134 | LimitableInputDialog::GetText(this, tr("New Profile"), tr("Enter a profile name:"), 1, 20); |
| 871 | const QString stylesheet = [this] { | ||
| 872 | switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) { | ||
| 873 | case Settings::ControllerType::ProController: | ||
| 874 | return QStringLiteral("image: url(:/controller/pro_controller%0)"); | ||
| 875 | case Settings::ControllerType::DualJoyconDetached: | ||
| 876 | return QStringLiteral("image: url(:/controller/dual_joycon%0)"); | ||
| 877 | case Settings::ControllerType::LeftJoycon: | ||
| 878 | return QStringLiteral("image: url(:/controller/single_joycon_left_vertical%0)"); | ||
| 879 | case Settings::ControllerType::RightJoycon: | ||
| 880 | return QStringLiteral("image: url(:/controller/single_joycon_right_vertical%0)"); | ||
| 881 | case Settings::ControllerType::Handheld: | ||
| 882 | return QStringLiteral("image: url(:/controller/handheld%0)"); | ||
| 883 | default: | ||
| 884 | return QString{}; | ||
| 885 | } | ||
| 886 | }(); | ||
| 887 | |||
| 888 | const QString theme = [this] { | ||
| 889 | if (QIcon::themeName().contains(QStringLiteral("dark"))) { | ||
| 890 | return QStringLiteral("_dark"); | ||
| 891 | } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { | ||
| 892 | return QStringLiteral("_midnight"); | ||
| 893 | } else { | ||
| 894 | return QString{}; | ||
| 895 | } | ||
| 896 | }(); | ||
| 897 | 1135 | ||
| 898 | ui->controllerFrame->setStyleSheet(stylesheet.arg(theme)); | 1136 | if (profile_name.isEmpty()) { |
| 899 | } | 1137 | return; |
| 1138 | } | ||
| 900 | 1139 | ||
| 901 | void ConfigureInputPlayer::UpdateControllerAvailableButtons() { | 1140 | if (!profiles->IsProfileNameValid(profile_name.toStdString())) { |
| 902 | auto layout = GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); | 1141 | QMessageBox::critical(this, tr("Create Input Profile"), |
| 903 | if (debug) { | 1142 | tr("The given profile name is not valid!")); |
| 904 | layout = Settings::ControllerType::ProController; | 1143 | return; |
| 905 | } | 1144 | } |
| 906 | 1145 | ||
| 907 | // List of all the widgets that will be hidden by any of the following layouts that need | 1146 | ApplyConfiguration(); |
| 908 | // "unhidden" after the controller type changes | ||
| 909 | const std::array<QWidget*, 9> layout_show = { | ||
| 910 | ui->buttonShoulderButtonsSLSR, | ||
| 911 | ui->horizontalSpacerShoulderButtonsWidget, | ||
| 912 | ui->horizontalSpacerShoulderButtonsWidget2, | ||
| 913 | ui->buttonShoulderButtonsLeft, | ||
| 914 | ui->buttonMiscButtonsMinusScreenshot, | ||
| 915 | ui->bottomLeft, | ||
| 916 | ui->buttonShoulderButtonsRight, | ||
| 917 | ui->buttonMiscButtonsPlusHome, | ||
| 918 | ui->bottomRight, | ||
| 919 | }; | ||
| 920 | 1147 | ||
| 921 | for (auto* widget : layout_show) { | 1148 | if (!profiles->CreateProfile(profile_name.toStdString(), player_index)) { |
| 922 | widget->show(); | 1149 | QMessageBox::critical(this, tr("Create Input Profile"), |
| 1150 | tr("Failed to create the input profile \"%1\"").arg(profile_name)); | ||
| 1151 | UpdateInputProfiles(); | ||
| 1152 | emit RefreshInputProfiles(player_index); | ||
| 1153 | return; | ||
| 923 | } | 1154 | } |
| 924 | 1155 | ||
| 925 | std::vector<QWidget*> layout_hidden; | 1156 | emit RefreshInputProfiles(player_index); |
| 926 | switch (layout) { | 1157 | |
| 927 | case Settings::ControllerType::ProController: | 1158 | ui->comboProfiles->addItem(profile_name); |
| 928 | case Settings::ControllerType::DualJoyconDetached: | 1159 | ui->comboProfiles->setCurrentIndex(ui->comboProfiles->count() - 1); |
| 929 | case Settings::ControllerType::Handheld: | 1160 | } |
| 930 | layout_hidden = { | 1161 | |
| 931 | ui->buttonShoulderButtonsSLSR, | 1162 | void ConfigureInputPlayer::DeleteProfile() { |
| 932 | ui->horizontalSpacerShoulderButtonsWidget2, | 1163 | const QString profile_name = ui->comboProfiles->itemText(ui->comboProfiles->currentIndex()); |
| 933 | }; | 1164 | |
| 934 | break; | 1165 | if (profile_name.isEmpty()) { |
| 935 | case Settings::ControllerType::LeftJoycon: | 1166 | return; |
| 936 | layout_hidden = { | ||
| 937 | ui->horizontalSpacerShoulderButtonsWidget2, | ||
| 938 | ui->buttonShoulderButtonsRight, | ||
| 939 | ui->buttonMiscButtonsPlusHome, | ||
| 940 | ui->bottomRight, | ||
| 941 | }; | ||
| 942 | break; | ||
| 943 | case Settings::ControllerType::RightJoycon: | ||
| 944 | layout_hidden = { | ||
| 945 | ui->horizontalSpacerShoulderButtonsWidget, | ||
| 946 | ui->buttonShoulderButtonsLeft, | ||
| 947 | ui->buttonMiscButtonsMinusScreenshot, | ||
| 948 | ui->bottomLeft, | ||
| 949 | }; | ||
| 950 | break; | ||
| 951 | } | 1167 | } |
| 952 | 1168 | ||
| 953 | for (auto* widget : layout_hidden) { | 1169 | if (!profiles->DeleteProfile(profile_name.toStdString())) { |
| 954 | widget->hide(); | 1170 | QMessageBox::critical(this, tr("Delete Input Profile"), |
| 1171 | tr("Failed to delete the input profile \"%1\"").arg(profile_name)); | ||
| 1172 | UpdateInputProfiles(); | ||
| 1173 | emit RefreshInputProfiles(player_index); | ||
| 1174 | return; | ||
| 955 | } | 1175 | } |
| 1176 | |||
| 1177 | emit RefreshInputProfiles(player_index); | ||
| 1178 | |||
| 1179 | ui->comboProfiles->removeItem(ui->comboProfiles->currentIndex()); | ||
| 1180 | ui->comboProfiles->setCurrentIndex(-1); | ||
| 956 | } | 1181 | } |
| 957 | 1182 | ||
| 958 | void ConfigureInputPlayer::UpdateMotionButtons() { | 1183 | void ConfigureInputPlayer::LoadProfile() { |
| 959 | if (debug) { | 1184 | const QString profile_name = ui->comboProfiles->itemText(ui->comboProfiles->currentIndex()); |
| 960 | // Motion isn't used with the debug controller, hide both groupboxes. | 1185 | |
| 961 | ui->buttonMotionLeftGroup->hide(); | 1186 | if (profile_name.isEmpty()) { |
| 962 | ui->buttonMotionRightGroup->hide(); | ||
| 963 | return; | 1187 | return; |
| 964 | } | 1188 | } |
| 965 | 1189 | ||
| 966 | // Show/hide the "Motion 1/2" groupboxes depending on the currently selected controller. | 1190 | ApplyConfiguration(); |
| 967 | switch (GetControllerTypeFromIndex(ui->comboControllerType->currentIndex())) { | 1191 | |
| 968 | case Settings::ControllerType::ProController: | 1192 | if (!profiles->LoadProfile(profile_name.toStdString(), player_index)) { |
| 969 | case Settings::ControllerType::LeftJoycon: | 1193 | QMessageBox::critical(this, tr("Load Input Profile"), |
| 970 | case Settings::ControllerType::Handheld: | 1194 | tr("Failed to load the input profile \"%1\"").arg(profile_name)); |
| 971 | // Show "Motion 1" and hide "Motion 2". | 1195 | UpdateInputProfiles(); |
| 972 | ui->buttonMotionLeftGroup->show(); | 1196 | emit RefreshInputProfiles(player_index); |
| 973 | ui->buttonMotionRightGroup->hide(); | 1197 | return; |
| 974 | break; | ||
| 975 | case Settings::ControllerType::RightJoycon: | ||
| 976 | // Show "Motion 2" and hide "Motion 1". | ||
| 977 | ui->buttonMotionLeftGroup->hide(); | ||
| 978 | ui->buttonMotionRightGroup->show(); | ||
| 979 | break; | ||
| 980 | case Settings::ControllerType::DualJoyconDetached: | ||
| 981 | default: | ||
| 982 | // Show both "Motion 1/2". | ||
| 983 | ui->buttonMotionLeftGroup->show(); | ||
| 984 | ui->buttonMotionRightGroup->show(); | ||
| 985 | break; | ||
| 986 | } | 1198 | } |
| 1199 | |||
| 1200 | LoadConfiguration(); | ||
| 987 | } | 1201 | } |
| 988 | 1202 | ||
| 989 | void ConfigureInputPlayer::showEvent(QShowEvent* event) { | 1203 | void ConfigureInputPlayer::SaveProfile() { |
| 990 | if (bottom_row == nullptr) { | 1204 | const QString profile_name = ui->comboProfiles->itemText(ui->comboProfiles->currentIndex()); |
| 1205 | |||
| 1206 | if (profile_name.isEmpty()) { | ||
| 1207 | return; | ||
| 1208 | } | ||
| 1209 | |||
| 1210 | ApplyConfiguration(); | ||
| 1211 | |||
| 1212 | if (!profiles->SaveProfile(profile_name.toStdString(), player_index)) { | ||
| 1213 | QMessageBox::critical(this, tr("Save Input Profile"), | ||
| 1214 | tr("Failed to save the input profile \"%1\"").arg(profile_name)); | ||
| 1215 | UpdateInputProfiles(); | ||
| 1216 | emit RefreshInputProfiles(player_index); | ||
| 991 | return; | 1217 | return; |
| 992 | } | 1218 | } |
| 993 | QWidget::showEvent(event); | ||
| 994 | ui->main->addWidget(bottom_row); | ||
| 995 | } | 1219 | } |
| 996 | 1220 | ||
| 997 | void ConfigureInputPlayer::ConnectPlayer(bool connected) { | 1221 | void ConfigureInputPlayer::UpdateInputProfiles() { |
| 998 | ui->groupConnectedController->setChecked(connected); | 1222 | ui->comboProfiles->clear(); |
| 1223 | |||
| 1224 | for (const auto& profile_name : profiles->GetInputProfileNames()) { | ||
| 1225 | ui->comboProfiles->addItem(QString::fromStdString(profile_name)); | ||
| 1226 | } | ||
| 1227 | |||
| 1228 | ui->comboProfiles->setCurrentIndex(-1); | ||
| 999 | } | 1229 | } |
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h index c19aefffa..23cf6f958 100644 --- a/src/yuzu/configuration/configure_input_player.h +++ b/src/yuzu/configuration/configure_input_player.h | |||
| @@ -26,6 +26,8 @@ class QString; | |||
| 26 | class QTimer; | 26 | class QTimer; |
| 27 | class QWidget; | 27 | class QWidget; |
| 28 | 28 | ||
| 29 | class InputProfiles; | ||
| 30 | |||
| 29 | namespace InputCommon { | 31 | namespace InputCommon { |
| 30 | class InputSubsystem; | 32 | class InputSubsystem; |
| 31 | } | 33 | } |
| @@ -45,14 +47,20 @@ class ConfigureInputPlayer : public QWidget { | |||
| 45 | public: | 47 | public: |
| 46 | explicit ConfigureInputPlayer(QWidget* parent, std::size_t player_index, QWidget* bottom_row, | 48 | explicit ConfigureInputPlayer(QWidget* parent, std::size_t player_index, QWidget* bottom_row, |
| 47 | InputCommon::InputSubsystem* input_subsystem_, | 49 | InputCommon::InputSubsystem* input_subsystem_, |
| 48 | bool debug = false); | 50 | InputProfiles* profiles_, bool debug = false); |
| 49 | ~ConfigureInputPlayer() override; | 51 | ~ConfigureInputPlayer() override; |
| 50 | 52 | ||
| 51 | /// Save all button configurations to settings file. | 53 | /// Save all button configurations to settings file. |
| 52 | void ApplyConfiguration(); | 54 | void ApplyConfiguration(); |
| 53 | 55 | ||
| 56 | /// Set the connection state checkbox (used to sync state). | ||
| 57 | void ConnectPlayer(bool connected); | ||
| 58 | |||
| 54 | /// Update the input devices combobox. | 59 | /// Update the input devices combobox. |
| 55 | void UpdateInputDevices(); | 60 | void UpdateInputDeviceCombobox(); |
| 61 | |||
| 62 | /// Updates the list of controller profiles. | ||
| 63 | void UpdateInputProfiles(); | ||
| 56 | 64 | ||
| 57 | /// Restore all buttons to their default values. | 65 | /// Restore all buttons to their default values. |
| 58 | void RestoreDefaults(); | 66 | void RestoreDefaults(); |
| @@ -60,9 +68,6 @@ public: | |||
| 60 | /// Clear all input configuration. | 68 | /// Clear all input configuration. |
| 61 | void ClearAll(); | 69 | void ClearAll(); |
| 62 | 70 | ||
| 63 | /// Set the connection state checkbox (used to sync state). | ||
| 64 | void ConnectPlayer(bool connected); | ||
| 65 | |||
| 66 | signals: | 71 | signals: |
| 67 | /// Emitted when this controller is connected by the user. | 72 | /// Emitted when this controller is connected by the user. |
| 68 | void Connected(bool connected); | 73 | void Connected(bool connected); |
| @@ -70,6 +75,12 @@ signals: | |||
| 70 | void HandheldStateChanged(bool is_handheld); | 75 | void HandheldStateChanged(bool is_handheld); |
| 71 | /// Emitted when the input devices combobox is being refreshed. | 76 | /// Emitted when the input devices combobox is being refreshed. |
| 72 | void RefreshInputDevices(); | 77 | void RefreshInputDevices(); |
| 78 | /** | ||
| 79 | * Emitted when the input profiles combobox is being refreshed. | ||
| 80 | * The player_index represents the current player's index, and the profile combobox | ||
| 81 | * will not be updated for this index as they are already updated by other mechanisms. | ||
| 82 | */ | ||
| 83 | void RefreshInputProfiles(std::size_t player_index); | ||
| 73 | 84 | ||
| 74 | protected: | 85 | protected: |
| 75 | void showEvent(QShowEvent* event) override; | 86 | void showEvent(QShowEvent* event) override; |
| @@ -89,6 +100,9 @@ private: | |||
| 89 | /// Finish polling and configure input using the input_setter. | 100 | /// Finish polling and configure input using the input_setter. |
| 90 | void SetPollingResult(const Common::ParamPackage& params, bool abort); | 101 | void SetPollingResult(const Common::ParamPackage& params, bool abort); |
| 91 | 102 | ||
| 103 | /// Checks whether a given input can be accepted. | ||
| 104 | bool IsInputAcceptable(const Common::ParamPackage& params) const; | ||
| 105 | |||
| 92 | /// Handle mouse button press events. | 106 | /// Handle mouse button press events. |
| 93 | void mousePressEvent(QMouseEvent* event) override; | 107 | void mousePressEvent(QMouseEvent* event) override; |
| 94 | 108 | ||
| @@ -98,8 +112,8 @@ private: | |||
| 98 | /// Update UI to reflect current configuration. | 112 | /// Update UI to reflect current configuration. |
| 99 | void UpdateUI(); | 113 | void UpdateUI(); |
| 100 | 114 | ||
| 101 | /// Update the controller selection combobox | 115 | /// Update the available input devices. |
| 102 | void UpdateControllerCombobox(); | 116 | void UpdateInputDevices(); |
| 103 | 117 | ||
| 104 | /// Update the current controller icon. | 118 | /// Update the current controller icon. |
| 105 | void UpdateControllerIcon(); | 119 | void UpdateControllerIcon(); |
| @@ -113,6 +127,18 @@ private: | |||
| 113 | /// Gets the default controller mapping for this device and auto configures the input to match. | 127 | /// Gets the default controller mapping for this device and auto configures the input to match. |
| 114 | void UpdateMappingWithDefaults(); | 128 | void UpdateMappingWithDefaults(); |
| 115 | 129 | ||
| 130 | /// Creates a controller profile. | ||
| 131 | void CreateProfile(); | ||
| 132 | |||
| 133 | /// Deletes the selected controller profile. | ||
| 134 | void DeleteProfile(); | ||
| 135 | |||
| 136 | /// Loads the selected controller profile. | ||
| 137 | void LoadProfile(); | ||
| 138 | |||
| 139 | /// Saves the current controller configuration into a selected controller profile. | ||
| 140 | void SaveProfile(); | ||
| 141 | |||
| 116 | std::unique_ptr<Ui::ConfigureInputPlayer> ui; | 142 | std::unique_ptr<Ui::ConfigureInputPlayer> ui; |
| 117 | 143 | ||
| 118 | std::size_t player_index; | 144 | std::size_t player_index; |
| @@ -120,6 +146,8 @@ private: | |||
| 120 | 146 | ||
| 121 | InputCommon::InputSubsystem* input_subsystem; | 147 | InputCommon::InputSubsystem* input_subsystem; |
| 122 | 148 | ||
| 149 | InputProfiles* profiles; | ||
| 150 | |||
| 123 | std::unique_ptr<QTimer> timeout_timer; | 151 | std::unique_ptr<QTimer> timeout_timer; |
| 124 | std::unique_ptr<QTimer> poll_timer; | 152 | std::unique_ptr<QTimer> poll_timer; |
| 125 | 153 | ||
| @@ -159,12 +187,15 @@ private: | |||
| 159 | 187 | ||
| 160 | std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers; | 188 | std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers; |
| 161 | 189 | ||
| 190 | /// A flag to indicate that the "Map Analog Stick" pop-up has been shown and accepted once. | ||
| 191 | bool map_analog_stick_accepted{}; | ||
| 192 | |||
| 162 | /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false, | 193 | /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false, |
| 163 | /// keyboard events are ignored. | 194 | /// keyboard events are ignored. |
| 164 | bool want_keyboard_mouse = false; | 195 | bool want_keyboard_mouse{}; |
| 165 | 196 | ||
| 166 | /// List of physical devices users can map with. If a SDL backed device is selected, then you | 197 | /// List of physical devices users can map with. If a SDL backed device is selected, then you |
| 167 | /// can usue this device to get a default mapping. | 198 | /// can use this device to get a default mapping. |
| 168 | std::vector<Common::ParamPackage> input_devices; | 199 | std::vector<Common::ParamPackage> input_devices; |
| 169 | 200 | ||
| 170 | /// Bottom row is where console wide settings are held, and its "owned" by the parent | 201 | /// Bottom row is where console wide settings are held, and its "owned" by the parent |
diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui index e03461d9d..1e78b4c10 100644 --- a/src/yuzu/configuration/configure_input_player.ui +++ b/src/yuzu/configuration/configure_input_player.ui | |||
| @@ -83,6 +83,12 @@ | |||
| 83 | </property> | 83 | </property> |
| 84 | <item> | 84 | <item> |
| 85 | <widget class="QComboBox" name="comboControllerType"> | 85 | <widget class="QComboBox" name="comboControllerType"> |
| 86 | <property name="minimumSize"> | ||
| 87 | <size> | ||
| 88 | <width>0</width> | ||
| 89 | <height>21</height> | ||
| 90 | </size> | ||
| 91 | </property> | ||
| 86 | <item> | 92 | <item> |
| 87 | <property name="text"> | 93 | <property name="text"> |
| 88 | <string>Pro Controller</string> | 94 | <string>Pro Controller</string> |
| @@ -136,6 +142,12 @@ | |||
| 136 | </property> | 142 | </property> |
| 137 | <item> | 143 | <item> |
| 138 | <widget class="QComboBox" name="comboDevices"> | 144 | <widget class="QComboBox" name="comboDevices"> |
| 145 | <property name="minimumSize"> | ||
| 146 | <size> | ||
| 147 | <width>0</width> | ||
| 148 | <height>21</height> | ||
| 149 | </size> | ||
| 150 | </property> | ||
| 139 | <item> | 151 | <item> |
| 140 | <property name="text"> | 152 | <property name="text"> |
| 141 | <string>Any</string> | 153 | <string>Any</string> |
| @@ -152,14 +164,14 @@ | |||
| 152 | <widget class="QPushButton" name="buttonRefreshDevices"> | 164 | <widget class="QPushButton" name="buttonRefreshDevices"> |
| 153 | <property name="minimumSize"> | 165 | <property name="minimumSize"> |
| 154 | <size> | 166 | <size> |
| 155 | <width>24</width> | 167 | <width>21</width> |
| 156 | <height>22</height> | 168 | <height>21</height> |
| 157 | </size> | 169 | </size> |
| 158 | </property> | 170 | </property> |
| 159 | <property name="maximumSize"> | 171 | <property name="maximumSize"> |
| 160 | <size> | 172 | <size> |
| 161 | <width>24</width> | 173 | <width>21</width> |
| 162 | <height>22</height> | 174 | <height>21</height> |
| 163 | </size> | 175 | </size> |
| 164 | </property> | 176 | </property> |
| 165 | <property name="styleSheet"> | 177 | <property name="styleSheet"> |
| @@ -198,18 +210,25 @@ | |||
| 198 | <number>5</number> | 210 | <number>5</number> |
| 199 | </property> | 211 | </property> |
| 200 | <item> | 212 | <item> |
| 201 | <widget class="QComboBox" name="comboProfiles"/> | 213 | <widget class="QComboBox" name="comboProfiles"> |
| 214 | <property name="minimumSize"> | ||
| 215 | <size> | ||
| 216 | <width>0</width> | ||
| 217 | <height>21</height> | ||
| 218 | </size> | ||
| 219 | </property> | ||
| 220 | </widget> | ||
| 202 | </item> | 221 | </item> |
| 203 | <item> | 222 | <item> |
| 204 | <widget class="QPushButton" name="buttonProfilesSave"> | 223 | <widget class="QPushButton" name="buttonProfilesSave"> |
| 205 | <property name="maximumSize"> | 224 | <property name="maximumSize"> |
| 206 | <size> | 225 | <size> |
| 207 | <width>55</width> | 226 | <width>68</width> |
| 208 | <height>16777215</height> | 227 | <height>16777215</height> |
| 209 | </size> | 228 | </size> |
| 210 | </property> | 229 | </property> |
| 211 | <property name="styleSheet"> | 230 | <property name="styleSheet"> |
| 212 | <string notr="true">min-width: 55px;</string> | 231 | <string notr="true">min-width: 68px;</string> |
| 213 | </property> | 232 | </property> |
| 214 | <property name="text"> | 233 | <property name="text"> |
| 215 | <string>Save</string> | 234 | <string>Save</string> |
| @@ -220,12 +239,12 @@ | |||
| 220 | <widget class="QPushButton" name="buttonProfilesNew"> | 239 | <widget class="QPushButton" name="buttonProfilesNew"> |
| 221 | <property name="maximumSize"> | 240 | <property name="maximumSize"> |
| 222 | <size> | 241 | <size> |
| 223 | <width>55</width> | 242 | <width>68</width> |
| 224 | <height>16777215</height> | 243 | <height>16777215</height> |
| 225 | </size> | 244 | </size> |
| 226 | </property> | 245 | </property> |
| 227 | <property name="styleSheet"> | 246 | <property name="styleSheet"> |
| 228 | <string notr="true">min-width: 55px;</string> | 247 | <string notr="true">min-width: 68px;</string> |
| 229 | </property> | 248 | </property> |
| 230 | <property name="text"> | 249 | <property name="text"> |
| 231 | <string>New</string> | 250 | <string>New</string> |
| @@ -236,12 +255,12 @@ | |||
| 236 | <widget class="QPushButton" name="buttonProfilesDelete"> | 255 | <widget class="QPushButton" name="buttonProfilesDelete"> |
| 237 | <property name="maximumSize"> | 256 | <property name="maximumSize"> |
| 238 | <size> | 257 | <size> |
| 239 | <width>55</width> | 258 | <width>68</width> |
| 240 | <height>16777215</height> | 259 | <height>16777215</height> |
| 241 | </size> | 260 | </size> |
| 242 | </property> | 261 | </property> |
| 243 | <property name="styleSheet"> | 262 | <property name="styleSheet"> |
| 244 | <string notr="true">min-width: 55px;</string> | 263 | <string notr="true">min-width: 68px;</string> |
| 245 | </property> | 264 | </property> |
| 246 | <property name="text"> | 265 | <property name="text"> |
| 247 | <string>Delete</string> | 266 | <string>Delete</string> |
| @@ -393,18 +412,18 @@ | |||
| 393 | <widget class="QPushButton" name="buttonLStickUp"> | 412 | <widget class="QPushButton" name="buttonLStickUp"> |
| 394 | <property name="minimumSize"> | 413 | <property name="minimumSize"> |
| 395 | <size> | 414 | <size> |
| 396 | <width>57</width> | 415 | <width>68</width> |
| 397 | <height>0</height> | 416 | <height>0</height> |
| 398 | </size> | 417 | </size> |
| 399 | </property> | 418 | </property> |
| 400 | <property name="maximumSize"> | 419 | <property name="maximumSize"> |
| 401 | <size> | 420 | <size> |
| 402 | <width>55</width> | 421 | <width>68</width> |
| 403 | <height>16777215</height> | 422 | <height>16777215</height> |
| 404 | </size> | 423 | </size> |
| 405 | </property> | 424 | </property> |
| 406 | <property name="styleSheet"> | 425 | <property name="styleSheet"> |
| 407 | <string notr="true">min-width: 55px;</string> | 426 | <string notr="true">min-width: 68px;</string> |
| 408 | </property> | 427 | </property> |
| 409 | <property name="text"> | 428 | <property name="text"> |
| 410 | <string>Up</string> | 429 | <string>Up</string> |
| @@ -463,18 +482,18 @@ | |||
| 463 | <widget class="QPushButton" name="buttonLStickLeft"> | 482 | <widget class="QPushButton" name="buttonLStickLeft"> |
| 464 | <property name="minimumSize"> | 483 | <property name="minimumSize"> |
| 465 | <size> | 484 | <size> |
| 466 | <width>57</width> | 485 | <width>68</width> |
| 467 | <height>0</height> | 486 | <height>0</height> |
| 468 | </size> | 487 | </size> |
| 469 | </property> | 488 | </property> |
| 470 | <property name="maximumSize"> | 489 | <property name="maximumSize"> |
| 471 | <size> | 490 | <size> |
| 472 | <width>55</width> | 491 | <width>68</width> |
| 473 | <height>16777215</height> | 492 | <height>16777215</height> |
| 474 | </size> | 493 | </size> |
| 475 | </property> | 494 | </property> |
| 476 | <property name="styleSheet"> | 495 | <property name="styleSheet"> |
| 477 | <string notr="true">min-width: 55px;</string> | 496 | <string notr="true">min-width: 68px;</string> |
| 478 | </property> | 497 | </property> |
| 479 | <property name="text"> | 498 | <property name="text"> |
| 480 | <string>Left</string> | 499 | <string>Left</string> |
| @@ -512,18 +531,18 @@ | |||
| 512 | <widget class="QPushButton" name="buttonLStickRight"> | 531 | <widget class="QPushButton" name="buttonLStickRight"> |
| 513 | <property name="minimumSize"> | 532 | <property name="minimumSize"> |
| 514 | <size> | 533 | <size> |
| 515 | <width>57</width> | 534 | <width>68</width> |
| 516 | <height>0</height> | 535 | <height>0</height> |
| 517 | </size> | 536 | </size> |
| 518 | </property> | 537 | </property> |
| 519 | <property name="maximumSize"> | 538 | <property name="maximumSize"> |
| 520 | <size> | 539 | <size> |
| 521 | <width>55</width> | 540 | <width>68</width> |
| 522 | <height>16777215</height> | 541 | <height>16777215</height> |
| 523 | </size> | 542 | </size> |
| 524 | </property> | 543 | </property> |
| 525 | <property name="styleSheet"> | 544 | <property name="styleSheet"> |
| 526 | <string notr="true">min-width: 55px;</string> | 545 | <string notr="true">min-width: 68px;</string> |
| 527 | </property> | 546 | </property> |
| 528 | <property name="text"> | 547 | <property name="text"> |
| 529 | <string>Right</string> | 548 | <string>Right</string> |
| @@ -594,18 +613,18 @@ | |||
| 594 | <widget class="QPushButton" name="buttonLStickDown"> | 613 | <widget class="QPushButton" name="buttonLStickDown"> |
| 595 | <property name="minimumSize"> | 614 | <property name="minimumSize"> |
| 596 | <size> | 615 | <size> |
| 597 | <width>57</width> | 616 | <width>68</width> |
| 598 | <height>0</height> | 617 | <height>0</height> |
| 599 | </size> | 618 | </size> |
| 600 | </property> | 619 | </property> |
| 601 | <property name="maximumSize"> | 620 | <property name="maximumSize"> |
| 602 | <size> | 621 | <size> |
| 603 | <width>55</width> | 622 | <width>68</width> |
| 604 | <height>16777215</height> | 623 | <height>16777215</height> |
| 605 | </size> | 624 | </size> |
| 606 | </property> | 625 | </property> |
| 607 | <property name="styleSheet"> | 626 | <property name="styleSheet"> |
| 608 | <string notr="true">min-width: 55px;</string> | 627 | <string notr="true">min-width: 68px;</string> |
| 609 | </property> | 628 | </property> |
| 610 | <property name="text"> | 629 | <property name="text"> |
| 611 | <string>Down</string> | 630 | <string>Down</string> |
| @@ -664,18 +683,18 @@ | |||
| 664 | <widget class="QPushButton" name="buttonLStick"> | 683 | <widget class="QPushButton" name="buttonLStick"> |
| 665 | <property name="minimumSize"> | 684 | <property name="minimumSize"> |
| 666 | <size> | 685 | <size> |
| 667 | <width>57</width> | 686 | <width>68</width> |
| 668 | <height>0</height> | 687 | <height>0</height> |
| 669 | </size> | 688 | </size> |
| 670 | </property> | 689 | </property> |
| 671 | <property name="maximumSize"> | 690 | <property name="maximumSize"> |
| 672 | <size> | 691 | <size> |
| 673 | <width>55</width> | 692 | <width>68</width> |
| 674 | <height>16777215</height> | 693 | <height>16777215</height> |
| 675 | </size> | 694 | </size> |
| 676 | </property> | 695 | </property> |
| 677 | <property name="styleSheet"> | 696 | <property name="styleSheet"> |
| 678 | <string notr="true">min-width: 55px;</string> | 697 | <string notr="true">min-width: 68px;</string> |
| 679 | </property> | 698 | </property> |
| 680 | <property name="text"> | 699 | <property name="text"> |
| 681 | <string>Pressed</string> | 700 | <string>Pressed</string> |
| @@ -713,18 +732,18 @@ | |||
| 713 | <widget class="QPushButton" name="buttonLStickMod"> | 732 | <widget class="QPushButton" name="buttonLStickMod"> |
| 714 | <property name="minimumSize"> | 733 | <property name="minimumSize"> |
| 715 | <size> | 734 | <size> |
| 716 | <width>57</width> | 735 | <width>68</width> |
| 717 | <height>0</height> | 736 | <height>0</height> |
| 718 | </size> | 737 | </size> |
| 719 | </property> | 738 | </property> |
| 720 | <property name="maximumSize"> | 739 | <property name="maximumSize"> |
| 721 | <size> | 740 | <size> |
| 722 | <width>55</width> | 741 | <width>68</width> |
| 723 | <height>16777215</height> | 742 | <height>16777215</height> |
| 724 | </size> | 743 | </size> |
| 725 | </property> | 744 | </property> |
| 726 | <property name="styleSheet"> | 745 | <property name="styleSheet"> |
| 727 | <string notr="true">min-width: 55px;</string> | 746 | <string notr="true">min-width: 68px;</string> |
| 728 | </property> | 747 | </property> |
| 729 | <property name="text"> | 748 | <property name="text"> |
| 730 | <string>Modifier</string> | 749 | <string>Modifier</string> |
| @@ -759,13 +778,13 @@ | |||
| 759 | <widget class="QSpinBox" name="spinboxLStickRange"> | 778 | <widget class="QSpinBox" name="spinboxLStickRange"> |
| 760 | <property name="minimumSize"> | 779 | <property name="minimumSize"> |
| 761 | <size> | 780 | <size> |
| 762 | <width>55</width> | 781 | <width>68</width> |
| 763 | <height>21</height> | 782 | <height>21</height> |
| 764 | </size> | 783 | </size> |
| 765 | </property> | 784 | </property> |
| 766 | <property name="maximumSize"> | 785 | <property name="maximumSize"> |
| 767 | <size> | 786 | <size> |
| 768 | <width>55</width> | 787 | <width>68</width> |
| 769 | <height>16777215</height> | 788 | <height>16777215</height> |
| 770 | </size> | 789 | </size> |
| 771 | </property> | 790 | </property> |
| @@ -966,18 +985,18 @@ | |||
| 966 | <widget class="QPushButton" name="buttonDpadUp"> | 985 | <widget class="QPushButton" name="buttonDpadUp"> |
| 967 | <property name="minimumSize"> | 986 | <property name="minimumSize"> |
| 968 | <size> | 987 | <size> |
| 969 | <width>57</width> | 988 | <width>68</width> |
| 970 | <height>0</height> | 989 | <height>0</height> |
| 971 | </size> | 990 | </size> |
| 972 | </property> | 991 | </property> |
| 973 | <property name="maximumSize"> | 992 | <property name="maximumSize"> |
| 974 | <size> | 993 | <size> |
| 975 | <width>55</width> | 994 | <width>68</width> |
| 976 | <height>16777215</height> | 995 | <height>16777215</height> |
| 977 | </size> | 996 | </size> |
| 978 | </property> | 997 | </property> |
| 979 | <property name="styleSheet"> | 998 | <property name="styleSheet"> |
| 980 | <string notr="true">min-width: 55px;</string> | 999 | <string notr="true">min-width: 68px;</string> |
| 981 | </property> | 1000 | </property> |
| 982 | <property name="text"> | 1001 | <property name="text"> |
| 983 | <string>Up</string> | 1002 | <string>Up</string> |
| @@ -1036,18 +1055,18 @@ | |||
| 1036 | <widget class="QPushButton" name="buttonDpadLeft"> | 1055 | <widget class="QPushButton" name="buttonDpadLeft"> |
| 1037 | <property name="minimumSize"> | 1056 | <property name="minimumSize"> |
| 1038 | <size> | 1057 | <size> |
| 1039 | <width>57</width> | 1058 | <width>68</width> |
| 1040 | <height>0</height> | 1059 | <height>0</height> |
| 1041 | </size> | 1060 | </size> |
| 1042 | </property> | 1061 | </property> |
| 1043 | <property name="maximumSize"> | 1062 | <property name="maximumSize"> |
| 1044 | <size> | 1063 | <size> |
| 1045 | <width>55</width> | 1064 | <width>68</width> |
| 1046 | <height>16777215</height> | 1065 | <height>16777215</height> |
| 1047 | </size> | 1066 | </size> |
| 1048 | </property> | 1067 | </property> |
| 1049 | <property name="styleSheet"> | 1068 | <property name="styleSheet"> |
| 1050 | <string notr="true">min-width: 55px;</string> | 1069 | <string notr="true">min-width: 68px;</string> |
| 1051 | </property> | 1070 | </property> |
| 1052 | <property name="text"> | 1071 | <property name="text"> |
| 1053 | <string>Left</string> | 1072 | <string>Left</string> |
| @@ -1085,18 +1104,18 @@ | |||
| 1085 | <widget class="QPushButton" name="buttonDpadRight"> | 1104 | <widget class="QPushButton" name="buttonDpadRight"> |
| 1086 | <property name="minimumSize"> | 1105 | <property name="minimumSize"> |
| 1087 | <size> | 1106 | <size> |
| 1088 | <width>57</width> | 1107 | <width>68</width> |
| 1089 | <height>0</height> | 1108 | <height>0</height> |
| 1090 | </size> | 1109 | </size> |
| 1091 | </property> | 1110 | </property> |
| 1092 | <property name="maximumSize"> | 1111 | <property name="maximumSize"> |
| 1093 | <size> | 1112 | <size> |
| 1094 | <width>55</width> | 1113 | <width>68</width> |
| 1095 | <height>16777215</height> | 1114 | <height>16777215</height> |
| 1096 | </size> | 1115 | </size> |
| 1097 | </property> | 1116 | </property> |
| 1098 | <property name="styleSheet"> | 1117 | <property name="styleSheet"> |
| 1099 | <string notr="true">min-width: 55px;</string> | 1118 | <string notr="true">min-width: 68px;</string> |
| 1100 | </property> | 1119 | </property> |
| 1101 | <property name="text"> | 1120 | <property name="text"> |
| 1102 | <string>Right</string> | 1121 | <string>Right</string> |
| @@ -1167,18 +1186,18 @@ | |||
| 1167 | <widget class="QPushButton" name="buttonDpadDown"> | 1186 | <widget class="QPushButton" name="buttonDpadDown"> |
| 1168 | <property name="minimumSize"> | 1187 | <property name="minimumSize"> |
| 1169 | <size> | 1188 | <size> |
| 1170 | <width>57</width> | 1189 | <width>68</width> |
| 1171 | <height>0</height> | 1190 | <height>0</height> |
| 1172 | </size> | 1191 | </size> |
| 1173 | </property> | 1192 | </property> |
| 1174 | <property name="maximumSize"> | 1193 | <property name="maximumSize"> |
| 1175 | <size> | 1194 | <size> |
| 1176 | <width>55</width> | 1195 | <width>68</width> |
| 1177 | <height>16777215</height> | 1196 | <height>16777215</height> |
| 1178 | </size> | 1197 | </size> |
| 1179 | </property> | 1198 | </property> |
| 1180 | <property name="styleSheet"> | 1199 | <property name="styleSheet"> |
| 1181 | <string notr="true">min-width: 55px;</string> | 1200 | <string notr="true">min-width: 68px;</string> |
| 1182 | </property> | 1201 | </property> |
| 1183 | <property name="text"> | 1202 | <property name="text"> |
| 1184 | <string>Down</string> | 1203 | <string>Down</string> |
| @@ -1292,18 +1311,18 @@ | |||
| 1292 | <widget class="QPushButton" name="buttonL"> | 1311 | <widget class="QPushButton" name="buttonL"> |
| 1293 | <property name="minimumSize"> | 1312 | <property name="minimumSize"> |
| 1294 | <size> | 1313 | <size> |
| 1295 | <width>57</width> | 1314 | <width>68</width> |
| 1296 | <height>0</height> | 1315 | <height>0</height> |
| 1297 | </size> | 1316 | </size> |
| 1298 | </property> | 1317 | </property> |
| 1299 | <property name="maximumSize"> | 1318 | <property name="maximumSize"> |
| 1300 | <size> | 1319 | <size> |
| 1301 | <width>55</width> | 1320 | <width>68</width> |
| 1302 | <height>16777215</height> | 1321 | <height>16777215</height> |
| 1303 | </size> | 1322 | </size> |
| 1304 | </property> | 1323 | </property> |
| 1305 | <property name="styleSheet"> | 1324 | <property name="styleSheet"> |
| 1306 | <string notr="true">min-width: 55px;</string> | 1325 | <string notr="true">min-width: 68px;</string> |
| 1307 | </property> | 1326 | </property> |
| 1308 | <property name="text"> | 1327 | <property name="text"> |
| 1309 | <string>L</string> | 1328 | <string>L</string> |
| @@ -1341,18 +1360,18 @@ | |||
| 1341 | <widget class="QPushButton" name="buttonZL"> | 1360 | <widget class="QPushButton" name="buttonZL"> |
| 1342 | <property name="minimumSize"> | 1361 | <property name="minimumSize"> |
| 1343 | <size> | 1362 | <size> |
| 1344 | <width>57</width> | 1363 | <width>68</width> |
| 1345 | <height>0</height> | 1364 | <height>0</height> |
| 1346 | </size> | 1365 | </size> |
| 1347 | </property> | 1366 | </property> |
| 1348 | <property name="maximumSize"> | 1367 | <property name="maximumSize"> |
| 1349 | <size> | 1368 | <size> |
| 1350 | <width>55</width> | 1369 | <width>68</width> |
| 1351 | <height>16777215</height> | 1370 | <height>16777215</height> |
| 1352 | </size> | 1371 | </size> |
| 1353 | </property> | 1372 | </property> |
| 1354 | <property name="styleSheet"> | 1373 | <property name="styleSheet"> |
| 1355 | <string notr="true">min-width: 55px;</string> | 1374 | <string notr="true">min-width: 68px;</string> |
| 1356 | </property> | 1375 | </property> |
| 1357 | <property name="text"> | 1376 | <property name="text"> |
| 1358 | <string>ZL</string> | 1377 | <string>ZL</string> |
| @@ -1445,18 +1464,18 @@ | |||
| 1445 | <widget class="QPushButton" name="buttonMinus"> | 1464 | <widget class="QPushButton" name="buttonMinus"> |
| 1446 | <property name="minimumSize"> | 1465 | <property name="minimumSize"> |
| 1447 | <size> | 1466 | <size> |
| 1448 | <width>57</width> | 1467 | <width>68</width> |
| 1449 | <height>0</height> | 1468 | <height>0</height> |
| 1450 | </size> | 1469 | </size> |
| 1451 | </property> | 1470 | </property> |
| 1452 | <property name="maximumSize"> | 1471 | <property name="maximumSize"> |
| 1453 | <size> | 1472 | <size> |
| 1454 | <width>55</width> | 1473 | <width>68</width> |
| 1455 | <height>16777215</height> | 1474 | <height>16777215</height> |
| 1456 | </size> | 1475 | </size> |
| 1457 | </property> | 1476 | </property> |
| 1458 | <property name="styleSheet"> | 1477 | <property name="styleSheet"> |
| 1459 | <string notr="true">min-width: 55px;</string> | 1478 | <string notr="true">min-width: 68px;</string> |
| 1460 | </property> | 1479 | </property> |
| 1461 | <property name="text"> | 1480 | <property name="text"> |
| 1462 | <string>Minus</string> | 1481 | <string>Minus</string> |
| @@ -1494,18 +1513,18 @@ | |||
| 1494 | <widget class="QPushButton" name="buttonScreenshot"> | 1513 | <widget class="QPushButton" name="buttonScreenshot"> |
| 1495 | <property name="minimumSize"> | 1514 | <property name="minimumSize"> |
| 1496 | <size> | 1515 | <size> |
| 1497 | <width>57</width> | 1516 | <width>68</width> |
| 1498 | <height>0</height> | 1517 | <height>0</height> |
| 1499 | </size> | 1518 | </size> |
| 1500 | </property> | 1519 | </property> |
| 1501 | <property name="maximumSize"> | 1520 | <property name="maximumSize"> |
| 1502 | <size> | 1521 | <size> |
| 1503 | <width>55</width> | 1522 | <width>68</width> |
| 1504 | <height>16777215</height> | 1523 | <height>16777215</height> |
| 1505 | </size> | 1524 | </size> |
| 1506 | </property> | 1525 | </property> |
| 1507 | <property name="styleSheet"> | 1526 | <property name="styleSheet"> |
| 1508 | <string notr="true">min-width: 55px;</string> | 1527 | <string notr="true">min-width: 68px;</string> |
| 1509 | </property> | 1528 | </property> |
| 1510 | <property name="text"> | 1529 | <property name="text"> |
| 1511 | <string>Capture</string> | 1530 | <string>Capture</string> |
| @@ -1564,18 +1583,18 @@ | |||
| 1564 | <widget class="QPushButton" name="buttonPlus"> | 1583 | <widget class="QPushButton" name="buttonPlus"> |
| 1565 | <property name="minimumSize"> | 1584 | <property name="minimumSize"> |
| 1566 | <size> | 1585 | <size> |
| 1567 | <width>57</width> | 1586 | <width>68</width> |
| 1568 | <height>0</height> | 1587 | <height>0</height> |
| 1569 | </size> | 1588 | </size> |
| 1570 | </property> | 1589 | </property> |
| 1571 | <property name="maximumSize"> | 1590 | <property name="maximumSize"> |
| 1572 | <size> | 1591 | <size> |
| 1573 | <width>55</width> | 1592 | <width>68</width> |
| 1574 | <height>16777215</height> | 1593 | <height>16777215</height> |
| 1575 | </size> | 1594 | </size> |
| 1576 | </property> | 1595 | </property> |
| 1577 | <property name="styleSheet"> | 1596 | <property name="styleSheet"> |
| 1578 | <string notr="true">min-width: 55px;</string> | 1597 | <string notr="true">min-width: 68px;</string> |
| 1579 | </property> | 1598 | </property> |
| 1580 | <property name="text"> | 1599 | <property name="text"> |
| 1581 | <string>Plus</string> | 1600 | <string>Plus</string> |
| @@ -1613,18 +1632,18 @@ | |||
| 1613 | <widget class="QPushButton" name="buttonHome"> | 1632 | <widget class="QPushButton" name="buttonHome"> |
| 1614 | <property name="minimumSize"> | 1633 | <property name="minimumSize"> |
| 1615 | <size> | 1634 | <size> |
| 1616 | <width>57</width> | 1635 | <width>68</width> |
| 1617 | <height>0</height> | 1636 | <height>0</height> |
| 1618 | </size> | 1637 | </size> |
| 1619 | </property> | 1638 | </property> |
| 1620 | <property name="maximumSize"> | 1639 | <property name="maximumSize"> |
| 1621 | <size> | 1640 | <size> |
| 1622 | <width>55</width> | 1641 | <width>68</width> |
| 1623 | <height>16777215</height> | 1642 | <height>16777215</height> |
| 1624 | </size> | 1643 | </size> |
| 1625 | </property> | 1644 | </property> |
| 1626 | <property name="styleSheet"> | 1645 | <property name="styleSheet"> |
| 1627 | <string notr="true">min-width: 55px;</string> | 1646 | <string notr="true">min-width: 68px;</string> |
| 1628 | </property> | 1647 | </property> |
| 1629 | <property name="text"> | 1648 | <property name="text"> |
| 1630 | <string>Home</string> | 1649 | <string>Home</string> |
| @@ -1717,18 +1736,18 @@ | |||
| 1717 | <widget class="QPushButton" name="buttonR"> | 1736 | <widget class="QPushButton" name="buttonR"> |
| 1718 | <property name="minimumSize"> | 1737 | <property name="minimumSize"> |
| 1719 | <size> | 1738 | <size> |
| 1720 | <width>57</width> | 1739 | <width>68</width> |
| 1721 | <height>0</height> | 1740 | <height>0</height> |
| 1722 | </size> | 1741 | </size> |
| 1723 | </property> | 1742 | </property> |
| 1724 | <property name="maximumSize"> | 1743 | <property name="maximumSize"> |
| 1725 | <size> | 1744 | <size> |
| 1726 | <width>55</width> | 1745 | <width>68</width> |
| 1727 | <height>16777215</height> | 1746 | <height>16777215</height> |
| 1728 | </size> | 1747 | </size> |
| 1729 | </property> | 1748 | </property> |
| 1730 | <property name="styleSheet"> | 1749 | <property name="styleSheet"> |
| 1731 | <string notr="true">min-width: 55px;</string> | 1750 | <string notr="true">min-width: 68px;</string> |
| 1732 | </property> | 1751 | </property> |
| 1733 | <property name="text"> | 1752 | <property name="text"> |
| 1734 | <string>R</string> | 1753 | <string>R</string> |
| @@ -1766,18 +1785,18 @@ | |||
| 1766 | <widget class="QPushButton" name="buttonZR"> | 1785 | <widget class="QPushButton" name="buttonZR"> |
| 1767 | <property name="minimumSize"> | 1786 | <property name="minimumSize"> |
| 1768 | <size> | 1787 | <size> |
| 1769 | <width>57</width> | 1788 | <width>68</width> |
| 1770 | <height>0</height> | 1789 | <height>0</height> |
| 1771 | </size> | 1790 | </size> |
| 1772 | </property> | 1791 | </property> |
| 1773 | <property name="maximumSize"> | 1792 | <property name="maximumSize"> |
| 1774 | <size> | 1793 | <size> |
| 1775 | <width>55</width> | 1794 | <width>68</width> |
| 1776 | <height>16777215</height> | 1795 | <height>16777215</height> |
| 1777 | </size> | 1796 | </size> |
| 1778 | </property> | 1797 | </property> |
| 1779 | <property name="styleSheet"> | 1798 | <property name="styleSheet"> |
| 1780 | <string notr="true">min-width: 55px;</string> | 1799 | <string notr="true">min-width: 68px;</string> |
| 1781 | </property> | 1800 | </property> |
| 1782 | <property name="text"> | 1801 | <property name="text"> |
| 1783 | <string>ZR</string> | 1802 | <string>ZR</string> |
| @@ -1870,18 +1889,18 @@ | |||
| 1870 | <widget class="QPushButton" name="buttonSL"> | 1889 | <widget class="QPushButton" name="buttonSL"> |
| 1871 | <property name="minimumSize"> | 1890 | <property name="minimumSize"> |
| 1872 | <size> | 1891 | <size> |
| 1873 | <width>57</width> | 1892 | <width>68</width> |
| 1874 | <height>0</height> | 1893 | <height>0</height> |
| 1875 | </size> | 1894 | </size> |
| 1876 | </property> | 1895 | </property> |
| 1877 | <property name="maximumSize"> | 1896 | <property name="maximumSize"> |
| 1878 | <size> | 1897 | <size> |
| 1879 | <width>55</width> | 1898 | <width>68</width> |
| 1880 | <height>16777215</height> | 1899 | <height>16777215</height> |
| 1881 | </size> | 1900 | </size> |
| 1882 | </property> | 1901 | </property> |
| 1883 | <property name="styleSheet"> | 1902 | <property name="styleSheet"> |
| 1884 | <string notr="true">min-width: 55px;</string> | 1903 | <string notr="true">min-width: 68px;</string> |
| 1885 | </property> | 1904 | </property> |
| 1886 | <property name="text"> | 1905 | <property name="text"> |
| 1887 | <string>SL</string> | 1906 | <string>SL</string> |
| @@ -1919,18 +1938,18 @@ | |||
| 1919 | <widget class="QPushButton" name="buttonSR"> | 1938 | <widget class="QPushButton" name="buttonSR"> |
| 1920 | <property name="minimumSize"> | 1939 | <property name="minimumSize"> |
| 1921 | <size> | 1940 | <size> |
| 1922 | <width>57</width> | 1941 | <width>68</width> |
| 1923 | <height>0</height> | 1942 | <height>0</height> |
| 1924 | </size> | 1943 | </size> |
| 1925 | </property> | 1944 | </property> |
| 1926 | <property name="maximumSize"> | 1945 | <property name="maximumSize"> |
| 1927 | <size> | 1946 | <size> |
| 1928 | <width>55</width> | 1947 | <width>68</width> |
| 1929 | <height>16777215</height> | 1948 | <height>16777215</height> |
| 1930 | </size> | 1949 | </size> |
| 1931 | </property> | 1950 | </property> |
| 1932 | <property name="styleSheet"> | 1951 | <property name="styleSheet"> |
| 1933 | <string notr="true">min-width: 55px;</string> | 1952 | <string notr="true">min-width: 68px;</string> |
| 1934 | </property> | 1953 | </property> |
| 1935 | <property name="text"> | 1954 | <property name="text"> |
| 1936 | <string>SR</string> | 1955 | <string>SR</string> |
| @@ -2027,18 +2046,18 @@ | |||
| 2027 | <widget class="QPushButton" name="buttonMotionLeft"> | 2046 | <widget class="QPushButton" name="buttonMotionLeft"> |
| 2028 | <property name="minimumSize"> | 2047 | <property name="minimumSize"> |
| 2029 | <size> | 2048 | <size> |
| 2030 | <width>57</width> | 2049 | <width>68</width> |
| 2031 | <height>0</height> | 2050 | <height>0</height> |
| 2032 | </size> | 2051 | </size> |
| 2033 | </property> | 2052 | </property> |
| 2034 | <property name="maximumSize"> | 2053 | <property name="maximumSize"> |
| 2035 | <size> | 2054 | <size> |
| 2036 | <width>55</width> | 2055 | <width>68</width> |
| 2037 | <height>16777215</height> | 2056 | <height>16777215</height> |
| 2038 | </size> | 2057 | </size> |
| 2039 | </property> | 2058 | </property> |
| 2040 | <property name="styleSheet"> | 2059 | <property name="styleSheet"> |
| 2041 | <string notr="true">min-width: 55px;</string> | 2060 | <string notr="true">min-width: 68px;</string> |
| 2042 | </property> | 2061 | </property> |
| 2043 | <property name="text"> | 2062 | <property name="text"> |
| 2044 | <string>Left</string> | 2063 | <string>Left</string> |
| @@ -2076,18 +2095,18 @@ | |||
| 2076 | <widget class="QPushButton" name="buttonMotionRight"> | 2095 | <widget class="QPushButton" name="buttonMotionRight"> |
| 2077 | <property name="minimumSize"> | 2096 | <property name="minimumSize"> |
| 2078 | <size> | 2097 | <size> |
| 2079 | <width>57</width> | 2098 | <width>68</width> |
| 2080 | <height>0</height> | 2099 | <height>0</height> |
| 2081 | </size> | 2100 | </size> |
| 2082 | </property> | 2101 | </property> |
| 2083 | <property name="maximumSize"> | 2102 | <property name="maximumSize"> |
| 2084 | <size> | 2103 | <size> |
| 2085 | <width>55</width> | 2104 | <width>68</width> |
| 2086 | <height>16777215</height> | 2105 | <height>16777215</height> |
| 2087 | </size> | 2106 | </size> |
| 2088 | </property> | 2107 | </property> |
| 2089 | <property name="styleSheet"> | 2108 | <property name="styleSheet"> |
| 2090 | <string notr="true">min-width: 55px;</string> | 2109 | <string notr="true">min-width: 68px;</string> |
| 2091 | </property> | 2110 | </property> |
| 2092 | <property name="text"> | 2111 | <property name="text"> |
| 2093 | <string>Right</string> | 2112 | <string>Right</string> |
| @@ -2225,18 +2244,18 @@ | |||
| 2225 | <widget class="QPushButton" name="buttonX"> | 2244 | <widget class="QPushButton" name="buttonX"> |
| 2226 | <property name="minimumSize"> | 2245 | <property name="minimumSize"> |
| 2227 | <size> | 2246 | <size> |
| 2228 | <width>57</width> | 2247 | <width>68</width> |
| 2229 | <height>0</height> | 2248 | <height>0</height> |
| 2230 | </size> | 2249 | </size> |
| 2231 | </property> | 2250 | </property> |
| 2232 | <property name="maximumSize"> | 2251 | <property name="maximumSize"> |
| 2233 | <size> | 2252 | <size> |
| 2234 | <width>55</width> | 2253 | <width>68</width> |
| 2235 | <height>16777215</height> | 2254 | <height>16777215</height> |
| 2236 | </size> | 2255 | </size> |
| 2237 | </property> | 2256 | </property> |
| 2238 | <property name="styleSheet"> | 2257 | <property name="styleSheet"> |
| 2239 | <string notr="true">min-width: 55px;</string> | 2258 | <string notr="true">min-width: 68px;</string> |
| 2240 | </property> | 2259 | </property> |
| 2241 | <property name="text"> | 2260 | <property name="text"> |
| 2242 | <string>X</string> | 2261 | <string>X</string> |
| @@ -2295,18 +2314,18 @@ | |||
| 2295 | <widget class="QPushButton" name="buttonY"> | 2314 | <widget class="QPushButton" name="buttonY"> |
| 2296 | <property name="minimumSize"> | 2315 | <property name="minimumSize"> |
| 2297 | <size> | 2316 | <size> |
| 2298 | <width>57</width> | 2317 | <width>68</width> |
| 2299 | <height>0</height> | 2318 | <height>0</height> |
| 2300 | </size> | 2319 | </size> |
| 2301 | </property> | 2320 | </property> |
| 2302 | <property name="maximumSize"> | 2321 | <property name="maximumSize"> |
| 2303 | <size> | 2322 | <size> |
| 2304 | <width>55</width> | 2323 | <width>68</width> |
| 2305 | <height>16777215</height> | 2324 | <height>16777215</height> |
| 2306 | </size> | 2325 | </size> |
| 2307 | </property> | 2326 | </property> |
| 2308 | <property name="styleSheet"> | 2327 | <property name="styleSheet"> |
| 2309 | <string notr="true">min-width: 55px;</string> | 2328 | <string notr="true">min-width: 68px;</string> |
| 2310 | </property> | 2329 | </property> |
| 2311 | <property name="text"> | 2330 | <property name="text"> |
| 2312 | <string>Y</string> | 2331 | <string>Y</string> |
| @@ -2344,18 +2363,18 @@ | |||
| 2344 | <widget class="QPushButton" name="buttonA"> | 2363 | <widget class="QPushButton" name="buttonA"> |
| 2345 | <property name="minimumSize"> | 2364 | <property name="minimumSize"> |
| 2346 | <size> | 2365 | <size> |
| 2347 | <width>57</width> | 2366 | <width>68</width> |
| 2348 | <height>0</height> | 2367 | <height>0</height> |
| 2349 | </size> | 2368 | </size> |
| 2350 | </property> | 2369 | </property> |
| 2351 | <property name="maximumSize"> | 2370 | <property name="maximumSize"> |
| 2352 | <size> | 2371 | <size> |
| 2353 | <width>55</width> | 2372 | <width>68</width> |
| 2354 | <height>16777215</height> | 2373 | <height>16777215</height> |
| 2355 | </size> | 2374 | </size> |
| 2356 | </property> | 2375 | </property> |
| 2357 | <property name="styleSheet"> | 2376 | <property name="styleSheet"> |
| 2358 | <string notr="true">min-width: 55px;</string> | 2377 | <string notr="true">min-width: 68px;</string> |
| 2359 | </property> | 2378 | </property> |
| 2360 | <property name="text"> | 2379 | <property name="text"> |
| 2361 | <string>A</string> | 2380 | <string>A</string> |
| @@ -2426,18 +2445,18 @@ | |||
| 2426 | <widget class="QPushButton" name="buttonB"> | 2445 | <widget class="QPushButton" name="buttonB"> |
| 2427 | <property name="minimumSize"> | 2446 | <property name="minimumSize"> |
| 2428 | <size> | 2447 | <size> |
| 2429 | <width>57</width> | 2448 | <width>68</width> |
| 2430 | <height>0</height> | 2449 | <height>0</height> |
| 2431 | </size> | 2450 | </size> |
| 2432 | </property> | 2451 | </property> |
| 2433 | <property name="maximumSize"> | 2452 | <property name="maximumSize"> |
| 2434 | <size> | 2453 | <size> |
| 2435 | <width>55</width> | 2454 | <width>68</width> |
| 2436 | <height>16777215</height> | 2455 | <height>16777215</height> |
| 2437 | </size> | 2456 | </size> |
| 2438 | </property> | 2457 | </property> |
| 2439 | <property name="styleSheet"> | 2458 | <property name="styleSheet"> |
| 2440 | <string notr="true">min-width: 55px;</string> | 2459 | <string notr="true">min-width: 68px;</string> |
| 2441 | </property> | 2460 | </property> |
| 2442 | <property name="text"> | 2461 | <property name="text"> |
| 2443 | <string>B</string> | 2462 | <string>B</string> |
| @@ -2580,18 +2599,18 @@ | |||
| 2580 | <widget class="QPushButton" name="buttonRStickUp"> | 2599 | <widget class="QPushButton" name="buttonRStickUp"> |
| 2581 | <property name="minimumSize"> | 2600 | <property name="minimumSize"> |
| 2582 | <size> | 2601 | <size> |
| 2583 | <width>57</width> | 2602 | <width>68</width> |
| 2584 | <height>0</height> | 2603 | <height>0</height> |
| 2585 | </size> | 2604 | </size> |
| 2586 | </property> | 2605 | </property> |
| 2587 | <property name="maximumSize"> | 2606 | <property name="maximumSize"> |
| 2588 | <size> | 2607 | <size> |
| 2589 | <width>55</width> | 2608 | <width>68</width> |
| 2590 | <height>16777215</height> | 2609 | <height>16777215</height> |
| 2591 | </size> | 2610 | </size> |
| 2592 | </property> | 2611 | </property> |
| 2593 | <property name="styleSheet"> | 2612 | <property name="styleSheet"> |
| 2594 | <string notr="true">min-width: 55px;</string> | 2613 | <string notr="true">min-width: 68px;</string> |
| 2595 | </property> | 2614 | </property> |
| 2596 | <property name="text"> | 2615 | <property name="text"> |
| 2597 | <string>Up</string> | 2616 | <string>Up</string> |
| @@ -2650,18 +2669,18 @@ | |||
| 2650 | <widget class="QPushButton" name="buttonRStickLeft"> | 2669 | <widget class="QPushButton" name="buttonRStickLeft"> |
| 2651 | <property name="minimumSize"> | 2670 | <property name="minimumSize"> |
| 2652 | <size> | 2671 | <size> |
| 2653 | <width>57</width> | 2672 | <width>68</width> |
| 2654 | <height>0</height> | 2673 | <height>0</height> |
| 2655 | </size> | 2674 | </size> |
| 2656 | </property> | 2675 | </property> |
| 2657 | <property name="maximumSize"> | 2676 | <property name="maximumSize"> |
| 2658 | <size> | 2677 | <size> |
| 2659 | <width>55</width> | 2678 | <width>68</width> |
| 2660 | <height>16777215</height> | 2679 | <height>16777215</height> |
| 2661 | </size> | 2680 | </size> |
| 2662 | </property> | 2681 | </property> |
| 2663 | <property name="styleSheet"> | 2682 | <property name="styleSheet"> |
| 2664 | <string notr="true">min-width: 55px;</string> | 2683 | <string notr="true">min-width: 68px;</string> |
| 2665 | </property> | 2684 | </property> |
| 2666 | <property name="text"> | 2685 | <property name="text"> |
| 2667 | <string>Left</string> | 2686 | <string>Left</string> |
| @@ -2699,18 +2718,18 @@ | |||
| 2699 | <widget class="QPushButton" name="buttonRStickRight"> | 2718 | <widget class="QPushButton" name="buttonRStickRight"> |
| 2700 | <property name="minimumSize"> | 2719 | <property name="minimumSize"> |
| 2701 | <size> | 2720 | <size> |
| 2702 | <width>57</width> | 2721 | <width>68</width> |
| 2703 | <height>0</height> | 2722 | <height>0</height> |
| 2704 | </size> | 2723 | </size> |
| 2705 | </property> | 2724 | </property> |
| 2706 | <property name="maximumSize"> | 2725 | <property name="maximumSize"> |
| 2707 | <size> | 2726 | <size> |
| 2708 | <width>55</width> | 2727 | <width>68</width> |
| 2709 | <height>16777215</height> | 2728 | <height>16777215</height> |
| 2710 | </size> | 2729 | </size> |
| 2711 | </property> | 2730 | </property> |
| 2712 | <property name="styleSheet"> | 2731 | <property name="styleSheet"> |
| 2713 | <string notr="true">min-width: 55px;</string> | 2732 | <string notr="true">min-width: 68px;</string> |
| 2714 | </property> | 2733 | </property> |
| 2715 | <property name="text"> | 2734 | <property name="text"> |
| 2716 | <string>Right</string> | 2735 | <string>Right</string> |
| @@ -2781,18 +2800,18 @@ | |||
| 2781 | <widget class="QPushButton" name="buttonRStickDown"> | 2800 | <widget class="QPushButton" name="buttonRStickDown"> |
| 2782 | <property name="minimumSize"> | 2801 | <property name="minimumSize"> |
| 2783 | <size> | 2802 | <size> |
| 2784 | <width>57</width> | 2803 | <width>68</width> |
| 2785 | <height>0</height> | 2804 | <height>0</height> |
| 2786 | </size> | 2805 | </size> |
| 2787 | </property> | 2806 | </property> |
| 2788 | <property name="maximumSize"> | 2807 | <property name="maximumSize"> |
| 2789 | <size> | 2808 | <size> |
| 2790 | <width>55</width> | 2809 | <width>68</width> |
| 2791 | <height>16777215</height> | 2810 | <height>16777215</height> |
| 2792 | </size> | 2811 | </size> |
| 2793 | </property> | 2812 | </property> |
| 2794 | <property name="styleSheet"> | 2813 | <property name="styleSheet"> |
| 2795 | <string notr="true">min-width: 55px;</string> | 2814 | <string notr="true">min-width: 68px;</string> |
| 2796 | </property> | 2815 | </property> |
| 2797 | <property name="text"> | 2816 | <property name="text"> |
| 2798 | <string>Down</string> | 2817 | <string>Down</string> |
| @@ -2851,18 +2870,18 @@ | |||
| 2851 | <widget class="QPushButton" name="buttonRStick"> | 2870 | <widget class="QPushButton" name="buttonRStick"> |
| 2852 | <property name="minimumSize"> | 2871 | <property name="minimumSize"> |
| 2853 | <size> | 2872 | <size> |
| 2854 | <width>57</width> | 2873 | <width>68</width> |
| 2855 | <height>0</height> | 2874 | <height>0</height> |
| 2856 | </size> | 2875 | </size> |
| 2857 | </property> | 2876 | </property> |
| 2858 | <property name="maximumSize"> | 2877 | <property name="maximumSize"> |
| 2859 | <size> | 2878 | <size> |
| 2860 | <width>55</width> | 2879 | <width>68</width> |
| 2861 | <height>16777215</height> | 2880 | <height>16777215</height> |
| 2862 | </size> | 2881 | </size> |
| 2863 | </property> | 2882 | </property> |
| 2864 | <property name="styleSheet"> | 2883 | <property name="styleSheet"> |
| 2865 | <string notr="true">min-width: 55px;</string> | 2884 | <string notr="true">min-width: 68px;</string> |
| 2866 | </property> | 2885 | </property> |
| 2867 | <property name="text"> | 2886 | <property name="text"> |
| 2868 | <string>Pressed</string> | 2887 | <string>Pressed</string> |
| @@ -2900,18 +2919,18 @@ | |||
| 2900 | <widget class="QPushButton" name="buttonRStickMod"> | 2919 | <widget class="QPushButton" name="buttonRStickMod"> |
| 2901 | <property name="minimumSize"> | 2920 | <property name="minimumSize"> |
| 2902 | <size> | 2921 | <size> |
| 2903 | <width>57</width> | 2922 | <width>68</width> |
| 2904 | <height>0</height> | 2923 | <height>0</height> |
| 2905 | </size> | 2924 | </size> |
| 2906 | </property> | 2925 | </property> |
| 2907 | <property name="maximumSize"> | 2926 | <property name="maximumSize"> |
| 2908 | <size> | 2927 | <size> |
| 2909 | <width>55</width> | 2928 | <width>68</width> |
| 2910 | <height>16777215</height> | 2929 | <height>16777215</height> |
| 2911 | </size> | 2930 | </size> |
| 2912 | </property> | 2931 | </property> |
| 2913 | <property name="styleSheet"> | 2932 | <property name="styleSheet"> |
| 2914 | <string notr="true">min-width: 55px;</string> | 2933 | <string notr="true">min-width: 68px;</string> |
| 2915 | </property> | 2934 | </property> |
| 2916 | <property name="text"> | 2935 | <property name="text"> |
| 2917 | <string>Modifier</string> | 2936 | <string>Modifier</string> |
| @@ -2946,13 +2965,13 @@ | |||
| 2946 | <widget class="QSpinBox" name="spinboxRStickRange"> | 2965 | <widget class="QSpinBox" name="spinboxRStickRange"> |
| 2947 | <property name="minimumSize"> | 2966 | <property name="minimumSize"> |
| 2948 | <size> | 2967 | <size> |
| 2949 | <width>55</width> | 2968 | <width>68</width> |
| 2950 | <height>21</height> | 2969 | <height>21</height> |
| 2951 | </size> | 2970 | </size> |
| 2952 | </property> | 2971 | </property> |
| 2953 | <property name="maximumSize"> | 2972 | <property name="maximumSize"> |
| 2954 | <size> | 2973 | <size> |
| 2955 | <width>55</width> | 2974 | <width>68</width> |
| 2956 | <height>16777215</height> | 2975 | <height>16777215</height> |
| 2957 | </size> | 2976 | </size> |
| 2958 | </property> | 2977 | </property> |
diff --git a/src/yuzu/configuration/configure_input_profile_dialog.cpp b/src/yuzu/configuration/configure_input_profile_dialog.cpp new file mode 100644 index 000000000..1f5cfa75b --- /dev/null +++ b/src/yuzu/configuration/configure_input_profile_dialog.cpp | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "ui_configure_input_profile_dialog.h" | ||
| 6 | #include "yuzu/configuration/configure_input_player.h" | ||
| 7 | #include "yuzu/configuration/configure_input_profile_dialog.h" | ||
| 8 | |||
| 9 | ConfigureInputProfileDialog::ConfigureInputProfileDialog( | ||
| 10 | QWidget* parent, InputCommon::InputSubsystem* input_subsystem, InputProfiles* profiles) | ||
| 11 | : QDialog(parent), ui(std::make_unique<Ui::ConfigureInputProfileDialog>()), | ||
| 12 | profile_widget(new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, profiles, false)) { | ||
| 13 | ui->setupUi(this); | ||
| 14 | |||
| 15 | ui->controllerLayout->addWidget(profile_widget); | ||
| 16 | |||
| 17 | connect(ui->clear_all_button, &QPushButton::clicked, this, | ||
| 18 | [this] { profile_widget->ClearAll(); }); | ||
| 19 | connect(ui->restore_defaults_button, &QPushButton::clicked, this, | ||
| 20 | [this] { profile_widget->RestoreDefaults(); }); | ||
| 21 | |||
| 22 | RetranslateUI(); | ||
| 23 | } | ||
| 24 | |||
| 25 | ConfigureInputProfileDialog::~ConfigureInputProfileDialog() = default; | ||
| 26 | |||
| 27 | void ConfigureInputProfileDialog::changeEvent(QEvent* event) { | ||
| 28 | if (event->type() == QEvent::LanguageChange) { | ||
| 29 | RetranslateUI(); | ||
| 30 | } | ||
| 31 | |||
| 32 | QDialog::changeEvent(event); | ||
| 33 | } | ||
| 34 | |||
| 35 | void ConfigureInputProfileDialog::RetranslateUI() { | ||
| 36 | ui->retranslateUi(this); | ||
| 37 | } | ||
diff --git a/src/yuzu/configuration/configure_input_profile_dialog.h b/src/yuzu/configuration/configure_input_profile_dialog.h new file mode 100644 index 000000000..e6386bdbb --- /dev/null +++ b/src/yuzu/configuration/configure_input_profile_dialog.h | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | // Copyright 2020 yuzu 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 <memory> | ||
| 8 | #include <QDialog> | ||
| 9 | |||
| 10 | class QPushButton; | ||
| 11 | |||
| 12 | class ConfigureInputPlayer; | ||
| 13 | |||
| 14 | class InputProfiles; | ||
| 15 | |||
| 16 | namespace InputCommon { | ||
| 17 | class InputSubsystem; | ||
| 18 | } | ||
| 19 | |||
| 20 | namespace Ui { | ||
| 21 | class ConfigureInputProfileDialog; | ||
| 22 | } | ||
| 23 | |||
| 24 | class ConfigureInputProfileDialog : public QDialog { | ||
| 25 | Q_OBJECT | ||
| 26 | |||
| 27 | public: | ||
| 28 | explicit ConfigureInputProfileDialog(QWidget* parent, | ||
| 29 | InputCommon::InputSubsystem* input_subsystem, | ||
| 30 | InputProfiles* profiles); | ||
| 31 | ~ConfigureInputProfileDialog() override; | ||
| 32 | |||
| 33 | private: | ||
| 34 | void changeEvent(QEvent* event) override; | ||
| 35 | void RetranslateUI(); | ||
| 36 | |||
| 37 | std::unique_ptr<Ui::ConfigureInputProfileDialog> ui; | ||
| 38 | |||
| 39 | ConfigureInputPlayer* profile_widget; | ||
| 40 | }; | ||
diff --git a/src/yuzu/configuration/configure_input_dialog.ui b/src/yuzu/configuration/configure_input_profile_dialog.ui index b92ddb200..726cf6905 100644 --- a/src/yuzu/configuration/configure_input_dialog.ui +++ b/src/yuzu/configuration/configure_input_profile_dialog.ui | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | 1 | <?xml version="1.0" encoding="UTF-8"?> |
| 2 | <ui version="4.0"> | 2 | <ui version="4.0"> |
| 3 | <class>ConfigureInputDialog</class> | 3 | <class>ConfigureInputProfileDialog</class> |
| 4 | <widget class="QDialog" name="ConfigureInputDialog"> | 4 | <widget class="QDialog" name="ConfigureInputProfileDialog"> |
| 5 | <property name="geometry"> | 5 | <property name="geometry"> |
| 6 | <rect> | 6 | <rect> |
| 7 | <x>0</x> | 7 | <x>0</x> |
| @@ -11,7 +11,7 @@ | |||
| 11 | </rect> | 11 | </rect> |
| 12 | </property> | 12 | </property> |
| 13 | <property name="windowTitle"> | 13 | <property name="windowTitle"> |
| 14 | <string>Configure Input</string> | 14 | <string>Create Input Profile</string> |
| 15 | </property> | 15 | </property> |
| 16 | <layout class="QVBoxLayout" name="verticalLayout"> | 16 | <layout class="QVBoxLayout" name="verticalLayout"> |
| 17 | <property name="spacing"> | 17 | <property name="spacing"> |
| @@ -30,11 +30,25 @@ | |||
| 30 | <number>9</number> | 30 | <number>9</number> |
| 31 | </property> | 31 | </property> |
| 32 | <item> | 32 | <item> |
| 33 | <layout class="QHBoxLayout" name="inputLayout"/> | 33 | <layout class="QHBoxLayout" name="controllerLayout"/> |
| 34 | </item> | 34 | </item> |
| 35 | <item> | 35 | <item> |
| 36 | <layout class="QHBoxLayout" name="horizontalLayout"> | 36 | <layout class="QHBoxLayout" name="horizontalLayout"> |
| 37 | <item> | 37 | <item> |
| 38 | <widget class="QPushButton" name="clear_all_button"> | ||
| 39 | <property name="text"> | ||
| 40 | <string>Clear</string> | ||
| 41 | </property> | ||
| 42 | </widget> | ||
| 43 | </item> | ||
| 44 | <item> | ||
| 45 | <widget class="QPushButton" name="restore_defaults_button"> | ||
| 46 | <property name="text"> | ||
| 47 | <string>Defaults</string> | ||
| 48 | </property> | ||
| 49 | </widget> | ||
| 50 | </item> | ||
| 51 | <item> | ||
| 38 | <widget class="QDialogButtonBox" name="buttonBox"> | 52 | <widget class="QDialogButtonBox" name="buttonBox"> |
| 39 | <property name="standardButtons"> | 53 | <property name="standardButtons"> |
| 40 | <set>QDialogButtonBox::Ok</set> | 54 | <set>QDialogButtonBox::Ok</set> |
| @@ -50,7 +64,7 @@ | |||
| 50 | <connection> | 64 | <connection> |
| 51 | <sender>buttonBox</sender> | 65 | <sender>buttonBox</sender> |
| 52 | <signal>accepted()</signal> | 66 | <signal>accepted()</signal> |
| 53 | <receiver>ConfigureInputDialog</receiver> | 67 | <receiver>ConfigureInputProfileDialog</receiver> |
| 54 | <slot>accept()</slot> | 68 | <slot>accept()</slot> |
| 55 | </connection> | 69 | </connection> |
| 56 | </connections> | 70 | </connections> |
diff --git a/src/yuzu/configuration/configure_motion_touch.ui b/src/yuzu/configuration/configure_motion_touch.ui index 602cf8cd8..5b78c5a4b 100644 --- a/src/yuzu/configuration/configure_motion_touch.ui +++ b/src/yuzu/configuration/configure_motion_touch.ui | |||
| @@ -312,16 +312,6 @@ | |||
| 312 | <signal>accepted()</signal> | 312 | <signal>accepted()</signal> |
| 313 | <receiver>ConfigureMotionTouch</receiver> | 313 | <receiver>ConfigureMotionTouch</receiver> |
| 314 | <slot>ApplyConfiguration()</slot> | 314 | <slot>ApplyConfiguration()</slot> |
| 315 | <hints> | ||
| 316 | <hint type="sourcelabel"> | ||
| 317 | <x>220</x> | ||
| 318 | <y>380</y> | ||
| 319 | </hint> | ||
| 320 | <hint type="destinationlabel"> | ||
| 321 | <x>220</x> | ||
| 322 | <y>200</y> | ||
| 323 | </hint> | ||
| 324 | </hints> | ||
| 325 | </connection> | 315 | </connection> |
| 326 | </connections> | 316 | </connections> |
| 327 | </ui> | 317 | </ui> |
diff --git a/src/yuzu/configuration/configure_mouse_advanced.ui b/src/yuzu/configuration/configure_mouse_advanced.ui index 74552fdbd..5b99e1c37 100644 --- a/src/yuzu/configuration/configure_mouse_advanced.ui +++ b/src/yuzu/configuration/configure_mouse_advanced.ui | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | </property> | 15 | </property> |
| 16 | <property name="styleSheet"> | 16 | <property name="styleSheet"> |
| 17 | <string notr="true">QPushButton { | 17 | <string notr="true">QPushButton { |
| 18 | min-width: 55px; | 18 | min-width: 60px; |
| 19 | }</string> | 19 | }</string> |
| 20 | </property> | 20 | </property> |
| 21 | <layout class="QVBoxLayout" name="verticalLayout"> | 21 | <layout class="QVBoxLayout" name="verticalLayout"> |
| @@ -42,13 +42,13 @@ | |||
| 42 | <widget class="QPushButton" name="forward_button"> | 42 | <widget class="QPushButton" name="forward_button"> |
| 43 | <property name="minimumSize"> | 43 | <property name="minimumSize"> |
| 44 | <size> | 44 | <size> |
| 45 | <width>57</width> | 45 | <width>68</width> |
| 46 | <height>0</height> | 46 | <height>0</height> |
| 47 | </size> | 47 | </size> |
| 48 | </property> | 48 | </property> |
| 49 | <property name="maximumSize"> | 49 | <property name="maximumSize"> |
| 50 | <size> | 50 | <size> |
| 51 | <width>16777215</width> | 51 | <width>68</width> |
| 52 | <height>16777215</height> | 52 | <height>16777215</height> |
| 53 | </size> | 53 | </size> |
| 54 | </property> | 54 | </property> |
| @@ -82,7 +82,7 @@ | |||
| 82 | <widget class="QPushButton" name="back_button"> | 82 | <widget class="QPushButton" name="back_button"> |
| 83 | <property name="minimumSize"> | 83 | <property name="minimumSize"> |
| 84 | <size> | 84 | <size> |
| 85 | <width>57</width> | 85 | <width>68</width> |
| 86 | <height>0</height> | 86 | <height>0</height> |
| 87 | </size> | 87 | </size> |
| 88 | </property> | 88 | </property> |
| @@ -110,7 +110,7 @@ | |||
| 110 | <widget class="QPushButton" name="left_button"> | 110 | <widget class="QPushButton" name="left_button"> |
| 111 | <property name="minimumSize"> | 111 | <property name="minimumSize"> |
| 112 | <size> | 112 | <size> |
| 113 | <width>57</width> | 113 | <width>68</width> |
| 114 | <height>0</height> | 114 | <height>0</height> |
| 115 | </size> | 115 | </size> |
| 116 | </property> | 116 | </property> |
| @@ -138,13 +138,13 @@ | |||
| 138 | <widget class="QPushButton" name="middle_button"> | 138 | <widget class="QPushButton" name="middle_button"> |
| 139 | <property name="minimumSize"> | 139 | <property name="minimumSize"> |
| 140 | <size> | 140 | <size> |
| 141 | <width>57</width> | 141 | <width>68</width> |
| 142 | <height>0</height> | 142 | <height>0</height> |
| 143 | </size> | 143 | </size> |
| 144 | </property> | 144 | </property> |
| 145 | <property name="maximumSize"> | 145 | <property name="maximumSize"> |
| 146 | <size> | 146 | <size> |
| 147 | <width>16777215</width> | 147 | <width>68</width> |
| 148 | <height>16777215</height> | 148 | <height>16777215</height> |
| 149 | </size> | 149 | </size> |
| 150 | </property> | 150 | </property> |
| @@ -204,13 +204,13 @@ | |||
| 204 | <widget class="QPushButton" name="right_button"> | 204 | <widget class="QPushButton" name="right_button"> |
| 205 | <property name="minimumSize"> | 205 | <property name="minimumSize"> |
| 206 | <size> | 206 | <size> |
| 207 | <width>57</width> | 207 | <width>68</width> |
| 208 | <height>0</height> | 208 | <height>0</height> |
| 209 | </size> | 209 | </size> |
| 210 | </property> | 210 | </property> |
| 211 | <property name="maximumSize"> | 211 | <property name="maximumSize"> |
| 212 | <size> | 212 | <size> |
| 213 | <width>16777215</width> | 213 | <width>68</width> |
| 214 | <height>16777215</height> | 214 | <height>16777215</height> |
| 215 | </size> | 215 | </size> |
| 216 | </property> | 216 | </property> |
| @@ -256,13 +256,13 @@ | |||
| 256 | <widget class="QPushButton" name="buttonClearAll"> | 256 | <widget class="QPushButton" name="buttonClearAll"> |
| 257 | <property name="minimumSize"> | 257 | <property name="minimumSize"> |
| 258 | <size> | 258 | <size> |
| 259 | <width>57</width> | 259 | <width>68</width> |
| 260 | <height>0</height> | 260 | <height>0</height> |
| 261 | </size> | 261 | </size> |
| 262 | </property> | 262 | </property> |
| 263 | <property name="maximumSize"> | 263 | <property name="maximumSize"> |
| 264 | <size> | 264 | <size> |
| 265 | <width>16777215</width> | 265 | <width>68</width> |
| 266 | <height>16777215</height> | 266 | <height>16777215</height> |
| 267 | </size> | 267 | </size> |
| 268 | </property> | 268 | </property> |
| @@ -275,13 +275,13 @@ | |||
| 275 | <widget class="QPushButton" name="buttonRestoreDefaults"> | 275 | <widget class="QPushButton" name="buttonRestoreDefaults"> |
| 276 | <property name="minimumSize"> | 276 | <property name="minimumSize"> |
| 277 | <size> | 277 | <size> |
| 278 | <width>57</width> | 278 | <width>68</width> |
| 279 | <height>0</height> | 279 | <height>0</height> |
| 280 | </size> | 280 | </size> |
| 281 | </property> | 281 | </property> |
| 282 | <property name="maximumSize"> | 282 | <property name="maximumSize"> |
| 283 | <size> | 283 | <size> |
| 284 | <width>16777215</width> | 284 | <width>68</width> |
| 285 | <height>16777215</height> | 285 | <height>16777215</height> |
| 286 | </size> | 286 | </size> |
| 287 | </property> | 287 | </property> |
| @@ -324,32 +324,12 @@ | |||
| 324 | <signal>accepted()</signal> | 324 | <signal>accepted()</signal> |
| 325 | <receiver>ConfigureMouseAdvanced</receiver> | 325 | <receiver>ConfigureMouseAdvanced</receiver> |
| 326 | <slot>accept()</slot> | 326 | <slot>accept()</slot> |
| 327 | <hints> | ||
| 328 | <hint type="sourcelabel"> | ||
| 329 | <x>124</x> | ||
| 330 | <y>266</y> | ||
| 331 | </hint> | ||
| 332 | <hint type="destinationlabel"> | ||
| 333 | <x>124</x> | ||
| 334 | <y>143</y> | ||
| 335 | </hint> | ||
| 336 | </hints> | ||
| 337 | </connection> | 327 | </connection> |
| 338 | <connection> | 328 | <connection> |
| 339 | <sender>buttonBox</sender> | 329 | <sender>buttonBox</sender> |
| 340 | <signal>rejected()</signal> | 330 | <signal>rejected()</signal> |
| 341 | <receiver>ConfigureMouseAdvanced</receiver> | 331 | <receiver>ConfigureMouseAdvanced</receiver> |
| 342 | <slot>reject()</slot> | 332 | <slot>reject()</slot> |
| 343 | <hints> | ||
| 344 | <hint type="sourcelabel"> | ||
| 345 | <x>124</x> | ||
| 346 | <y>266</y> | ||
| 347 | </hint> | ||
| 348 | <hint type="destinationlabel"> | ||
| 349 | <x>124</x> | ||
| 350 | <y>143</y> | ||
| 351 | </hint> | ||
| 352 | </hints> | ||
| 353 | </connection> | 333 | </connection> |
| 354 | </connections> | 334 | </connections> |
| 355 | </ui> | 335 | </ui> |
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp index 002db3f93..81464dd37 100644 --- a/src/yuzu/configuration/configure_per_game.cpp +++ b/src/yuzu/configuration/configure_per_game.cpp | |||
| @@ -29,7 +29,8 @@ | |||
| 29 | 29 | ||
| 30 | ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id) | 30 | ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id) |
| 31 | : QDialog(parent), ui(std::make_unique<Ui::ConfigurePerGame>()), title_id(title_id) { | 31 | : QDialog(parent), ui(std::make_unique<Ui::ConfigurePerGame>()), title_id(title_id) { |
| 32 | game_config = std::make_unique<Config>(fmt::format("{:016X}.ini", title_id), false); | 32 | game_config = std::make_unique<Config>(fmt::format("{:016X}", title_id), |
| 33 | Config::ConfigType::PerGameConfig); | ||
| 33 | 34 | ||
| 34 | Settings::SetConfiguringGlobal(false); | 35 | Settings::SetConfiguringGlobal(false); |
| 35 | 36 | ||
diff --git a/src/yuzu/configuration/configure_per_game.ui b/src/yuzu/configuration/configure_per_game.ui index d2057c4ab..25975b3b9 100644 --- a/src/yuzu/configuration/configure_per_game.ui +++ b/src/yuzu/configuration/configure_per_game.ui | |||
| @@ -319,32 +319,12 @@ | |||
| 319 | <signal>accepted()</signal> | 319 | <signal>accepted()</signal> |
| 320 | <receiver>ConfigurePerGame</receiver> | 320 | <receiver>ConfigurePerGame</receiver> |
| 321 | <slot>accept()</slot> | 321 | <slot>accept()</slot> |
| 322 | <hints> | ||
| 323 | <hint type="sourcelabel"> | ||
| 324 | <x>248</x> | ||
| 325 | <y>254</y> | ||
| 326 | </hint> | ||
| 327 | <hint type="destinationlabel"> | ||
| 328 | <x>157</x> | ||
| 329 | <y>274</y> | ||
| 330 | </hint> | ||
| 331 | </hints> | ||
| 332 | </connection> | 322 | </connection> |
| 333 | <connection> | 323 | <connection> |
| 334 | <sender>buttonBox</sender> | 324 | <sender>buttonBox</sender> |
| 335 | <signal>rejected()</signal> | 325 | <signal>rejected()</signal> |
| 336 | <receiver>ConfigurePerGame</receiver> | 326 | <receiver>ConfigurePerGame</receiver> |
| 337 | <slot>reject()</slot> | 327 | <slot>reject()</slot> |
| 338 | <hints> | ||
| 339 | <hint type="sourcelabel"> | ||
| 340 | <x>316</x> | ||
| 341 | <y>260</y> | ||
| 342 | </hint> | ||
| 343 | <hint type="destinationlabel"> | ||
| 344 | <x>286</x> | ||
| 345 | <y>274</y> | ||
| 346 | </hint> | ||
| 347 | </hints> | ||
| 348 | </connection> | 328 | </connection> |
| 349 | </connections> | 329 | </connections> |
| 350 | </ui> | 330 | </ui> |
diff --git a/src/yuzu/configuration/configure_touch_from_button.ui b/src/yuzu/configuration/configure_touch_from_button.ui index f581e27e0..757219d54 100644 --- a/src/yuzu/configuration/configure_touch_from_button.ui +++ b/src/yuzu/configuration/configure_touch_from_button.ui | |||
| @@ -216,16 +216,6 @@ Drag points to change position, or double-click table cells to edit values.</str | |||
| 216 | <signal>rejected()</signal> | 216 | <signal>rejected()</signal> |
| 217 | <receiver>ConfigureTouchFromButton</receiver> | 217 | <receiver>ConfigureTouchFromButton</receiver> |
| 218 | <slot>reject()</slot> | 218 | <slot>reject()</slot> |
| 219 | <hints> | ||
| 220 | <hint type="sourcelabel"> | ||
| 221 | <x>249</x> | ||
| 222 | <y>428</y> | ||
| 223 | </hint> | ||
| 224 | <hint type="destinationlabel"> | ||
| 225 | <x>249</x> | ||
| 226 | <y>224</y> | ||
| 227 | </hint> | ||
| 228 | </hints> | ||
| 229 | </connection> | 219 | </connection> |
| 230 | </connections> | 220 | </connections> |
| 231 | </ui> | 221 | </ui> |
diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.ui b/src/yuzu/configuration/configure_touchscreen_advanced.ui index 1171c2dd1..30ceccddb 100644 --- a/src/yuzu/configuration/configure_touchscreen_advanced.ui +++ b/src/yuzu/configuration/configure_touchscreen_advanced.ui | |||
| @@ -168,32 +168,12 @@ | |||
| 168 | <signal>accepted()</signal> | 168 | <signal>accepted()</signal> |
| 169 | <receiver>ConfigureTouchscreenAdvanced</receiver> | 169 | <receiver>ConfigureTouchscreenAdvanced</receiver> |
| 170 | <slot>accept()</slot> | 170 | <slot>accept()</slot> |
| 171 | <hints> | ||
| 172 | <hint type="sourcelabel"> | ||
| 173 | <x>140</x> | ||
| 174 | <y>318</y> | ||
| 175 | </hint> | ||
| 176 | <hint type="destinationlabel"> | ||
| 177 | <x>140</x> | ||
| 178 | <y>169</y> | ||
| 179 | </hint> | ||
| 180 | </hints> | ||
| 181 | </connection> | 171 | </connection> |
| 182 | <connection> | 172 | <connection> |
| 183 | <sender>buttonBox</sender> | 173 | <sender>buttonBox</sender> |
| 184 | <signal>rejected()</signal> | 174 | <signal>rejected()</signal> |
| 185 | <receiver>ConfigureTouchscreenAdvanced</receiver> | 175 | <receiver>ConfigureTouchscreenAdvanced</receiver> |
| 186 | <slot>reject()</slot> | 176 | <slot>reject()</slot> |
| 187 | <hints> | 177 | </connection> |
| 188 | <hint type="sourcelabel"> | ||
| 189 | <x>140</x> | ||
| 190 | <y>318</y> | ||
| 191 | </hint> | ||
| 192 | <hint type="destinationlabel"> | ||
| 193 | <x>140</x> | ||
| 194 | <y>169</y> | ||
| 195 | </hint> | ||
| 196 | </hints> | ||
| 197 | </connection> | ||
| 198 | </connections> | 178 | </connections> |
| 199 | </ui> | 179 | </ui> |
diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp new file mode 100644 index 000000000..7dcb2c5b9 --- /dev/null +++ b/src/yuzu/configuration/configure_vibration.cpp | |||
| @@ -0,0 +1,146 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <unordered_map> | ||
| 7 | |||
| 8 | #include <fmt/format.h> | ||
| 9 | |||
| 10 | #include "common/param_package.h" | ||
| 11 | #include "core/settings.h" | ||
| 12 | #include "ui_configure_vibration.h" | ||
| 13 | #include "yuzu/configuration/configure_vibration.h" | ||
| 14 | |||
| 15 | ConfigureVibration::ConfigureVibration(QWidget* parent) | ||
| 16 | : QDialog(parent), ui(std::make_unique<Ui::ConfigureVibration>()) { | ||
| 17 | ui->setupUi(this); | ||
| 18 | |||
| 19 | vibration_groupboxes = { | ||
| 20 | ui->vibrationGroupPlayer1, ui->vibrationGroupPlayer2, ui->vibrationGroupPlayer3, | ||
| 21 | ui->vibrationGroupPlayer4, ui->vibrationGroupPlayer5, ui->vibrationGroupPlayer6, | ||
| 22 | ui->vibrationGroupPlayer7, ui->vibrationGroupPlayer8, | ||
| 23 | }; | ||
| 24 | |||
| 25 | vibration_spinboxes = { | ||
| 26 | ui->vibrationSpinPlayer1, ui->vibrationSpinPlayer2, ui->vibrationSpinPlayer3, | ||
| 27 | ui->vibrationSpinPlayer4, ui->vibrationSpinPlayer5, ui->vibrationSpinPlayer6, | ||
| 28 | ui->vibrationSpinPlayer7, ui->vibrationSpinPlayer8, | ||
| 29 | }; | ||
| 30 | |||
| 31 | const auto& players = Settings::values.players.GetValue(); | ||
| 32 | |||
| 33 | for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { | ||
| 34 | vibration_groupboxes[i]->setChecked(players[i].vibration_enabled); | ||
| 35 | vibration_spinboxes[i]->setValue(players[i].vibration_strength); | ||
| 36 | } | ||
| 37 | |||
| 38 | ui->checkBoxAccurateVibration->setChecked( | ||
| 39 | Settings::values.enable_accurate_vibrations.GetValue()); | ||
| 40 | |||
| 41 | if (!Settings::IsConfiguringGlobal()) { | ||
| 42 | ui->checkBoxAccurateVibration->setDisabled(true); | ||
| 43 | } | ||
| 44 | |||
| 45 | RetranslateUI(); | ||
| 46 | } | ||
| 47 | |||
| 48 | ConfigureVibration::~ConfigureVibration() = default; | ||
| 49 | |||
| 50 | void ConfigureVibration::ApplyConfiguration() { | ||
| 51 | auto& players = Settings::values.players.GetValue(); | ||
| 52 | |||
| 53 | for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { | ||
| 54 | players[i].vibration_enabled = vibration_groupboxes[i]->isChecked(); | ||
| 55 | players[i].vibration_strength = vibration_spinboxes[i]->value(); | ||
| 56 | } | ||
| 57 | |||
| 58 | Settings::values.enable_accurate_vibrations.SetValue( | ||
| 59 | ui->checkBoxAccurateVibration->isChecked()); | ||
| 60 | } | ||
| 61 | |||
| 62 | void ConfigureVibration::SetVibrationDevices(std::size_t player_index) { | ||
| 63 | using namespace Settings::NativeButton; | ||
| 64 | static constexpr std::array<std::array<Settings::NativeButton::Values, 6>, 2> buttons{{ | ||
| 65 | {DLeft, DUp, DRight, DDown, L, ZL}, // Left Buttons | ||
| 66 | {A, B, X, Y, R, ZR}, // Right Buttons | ||
| 67 | }}; | ||
| 68 | |||
| 69 | auto& player = Settings::values.players.GetValue()[player_index]; | ||
| 70 | |||
| 71 | for (std::size_t device_idx = 0; device_idx < buttons.size(); ++device_idx) { | ||
| 72 | std::unordered_map<std::string, int> params_count; | ||
| 73 | |||
| 74 | for (const auto button_index : buttons[device_idx]) { | ||
| 75 | const auto& player_button = player.buttons[button_index]; | ||
| 76 | |||
| 77 | if (params_count.find(player_button) != params_count.end()) { | ||
| 78 | ++params_count[player_button]; | ||
| 79 | continue; | ||
| 80 | } | ||
| 81 | |||
| 82 | params_count.insert_or_assign(player_button, 1); | ||
| 83 | } | ||
| 84 | |||
| 85 | const auto it = std::max_element( | ||
| 86 | params_count.begin(), params_count.end(), | ||
| 87 | [](const auto& lhs, const auto& rhs) { return lhs.second < rhs.second; }); | ||
| 88 | |||
| 89 | auto& vibration_param_str = player.vibrations[device_idx]; | ||
| 90 | vibration_param_str.clear(); | ||
| 91 | |||
| 92 | if (it->first.empty()) { | ||
| 93 | continue; | ||
| 94 | } | ||
| 95 | |||
| 96 | const auto param = Common::ParamPackage(it->first); | ||
| 97 | |||
| 98 | const auto engine = param.Get("engine", ""); | ||
| 99 | const auto guid = param.Get("guid", ""); | ||
| 100 | const auto port = param.Get("port", ""); | ||
| 101 | |||
| 102 | if (engine.empty() || engine == "keyboard" || engine == "mouse") { | ||
| 103 | continue; | ||
| 104 | } | ||
| 105 | |||
| 106 | vibration_param_str += fmt::format("engine:{}", engine); | ||
| 107 | |||
| 108 | if (!port.empty()) { | ||
| 109 | vibration_param_str += fmt::format(",port:{}", port); | ||
| 110 | } | ||
| 111 | if (!guid.empty()) { | ||
| 112 | vibration_param_str += fmt::format(",guid:{}", guid); | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | if (player.vibrations[0] != player.vibrations[1]) { | ||
| 117 | return; | ||
| 118 | } | ||
| 119 | |||
| 120 | if (!player.vibrations[0].empty() && | ||
| 121 | player.controller_type != Settings::ControllerType::RightJoycon) { | ||
| 122 | player.vibrations[1].clear(); | ||
| 123 | } else if (!player.vibrations[1].empty() && | ||
| 124 | player.controller_type == Settings::ControllerType::RightJoycon) { | ||
| 125 | player.vibrations[0].clear(); | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | void ConfigureVibration::SetAllVibrationDevices() { | ||
| 130 | // Set vibration devices for all player indices including handheld | ||
| 131 | for (std::size_t player_idx = 0; player_idx < NUM_PLAYERS + 1; ++player_idx) { | ||
| 132 | SetVibrationDevices(player_idx); | ||
| 133 | } | ||
| 134 | } | ||
| 135 | |||
| 136 | void ConfigureVibration::changeEvent(QEvent* event) { | ||
| 137 | if (event->type() == QEvent::LanguageChange) { | ||
| 138 | RetranslateUI(); | ||
| 139 | } | ||
| 140 | |||
| 141 | QDialog::changeEvent(event); | ||
| 142 | } | ||
| 143 | |||
| 144 | void ConfigureVibration::RetranslateUI() { | ||
| 145 | ui->retranslateUi(this); | ||
| 146 | } | ||
diff --git a/src/yuzu/configuration/configure_vibration.h b/src/yuzu/configuration/configure_vibration.h new file mode 100644 index 000000000..07411a86f --- /dev/null +++ b/src/yuzu/configuration/configure_vibration.h | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | // Copyright 2020 yuzu 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 <memory> | ||
| 9 | #include <QDialog> | ||
| 10 | |||
| 11 | class QGroupBox; | ||
| 12 | class QSpinBox; | ||
| 13 | |||
| 14 | namespace Ui { | ||
| 15 | class ConfigureVibration; | ||
| 16 | } | ||
| 17 | |||
| 18 | class ConfigureVibration : public QDialog { | ||
| 19 | Q_OBJECT | ||
| 20 | |||
| 21 | public: | ||
| 22 | explicit ConfigureVibration(QWidget* parent); | ||
| 23 | ~ConfigureVibration() override; | ||
| 24 | |||
| 25 | void ApplyConfiguration(); | ||
| 26 | |||
| 27 | static void SetVibrationDevices(std::size_t player_index); | ||
| 28 | static void SetAllVibrationDevices(); | ||
| 29 | |||
| 30 | private: | ||
| 31 | void changeEvent(QEvent* event) override; | ||
| 32 | void RetranslateUI(); | ||
| 33 | |||
| 34 | std::unique_ptr<Ui::ConfigureVibration> ui; | ||
| 35 | |||
| 36 | static constexpr std::size_t NUM_PLAYERS = 8; | ||
| 37 | |||
| 38 | // Groupboxes encapsulating the vibration strength spinbox. | ||
| 39 | std::array<QGroupBox*, NUM_PLAYERS> vibration_groupboxes; | ||
| 40 | |||
| 41 | // Spinboxes representing the vibration strength percentage. | ||
| 42 | std::array<QSpinBox*, NUM_PLAYERS> vibration_spinboxes; | ||
| 43 | }; | ||
diff --git a/src/yuzu/configuration/configure_vibration.ui b/src/yuzu/configuration/configure_vibration.ui new file mode 100644 index 000000000..efdf317a9 --- /dev/null +++ b/src/yuzu/configuration/configure_vibration.ui | |||
| @@ -0,0 +1,546 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <ui version="4.0"> | ||
| 3 | <class>ConfigureVibration</class> | ||
| 4 | <widget class="QDialog" name="ConfigureVibration"> | ||
| 5 | <property name="geometry"> | ||
| 6 | <rect> | ||
| 7 | <x>0</x> | ||
| 8 | <y>0</y> | ||
| 9 | <width>364</width> | ||
| 10 | <height>242</height> | ||
| 11 | </rect> | ||
| 12 | </property> | ||
| 13 | <property name="windowTitle"> | ||
| 14 | <string>Configure Vibration</string> | ||
| 15 | </property> | ||
| 16 | <property name="styleSheet"> | ||
| 17 | <string notr="true"/> | ||
| 18 | </property> | ||
| 19 | <layout class="QVBoxLayout"> | ||
| 20 | <item> | ||
| 21 | <widget class="QGroupBox" name="vibrationStrengthGroup"> | ||
| 22 | <property name="title"> | ||
| 23 | <string>Vibration</string> | ||
| 24 | </property> | ||
| 25 | <layout class="QVBoxLayout" name="verticalLayout_3" stretch="0,0"> | ||
| 26 | <property name="leftMargin"> | ||
| 27 | <number>9</number> | ||
| 28 | </property> | ||
| 29 | <property name="topMargin"> | ||
| 30 | <number>9</number> | ||
| 31 | </property> | ||
| 32 | <property name="rightMargin"> | ||
| 33 | <number>9</number> | ||
| 34 | </property> | ||
| 35 | <property name="bottomMargin"> | ||
| 36 | <number>9</number> | ||
| 37 | </property> | ||
| 38 | <item> | ||
| 39 | <widget class="QWidget" name="player14Widget" native="true"> | ||
| 40 | <layout class="QHBoxLayout" name="horizontalLayout_4"> | ||
| 41 | <property name="leftMargin"> | ||
| 42 | <number>0</number> | ||
| 43 | </property> | ||
| 44 | <property name="topMargin"> | ||
| 45 | <number>0</number> | ||
| 46 | </property> | ||
| 47 | <property name="rightMargin"> | ||
| 48 | <number>0</number> | ||
| 49 | </property> | ||
| 50 | <property name="bottomMargin"> | ||
| 51 | <number>0</number> | ||
| 52 | </property> | ||
| 53 | <item> | ||
| 54 | <widget class="QGroupBox" name="vibrationGroupPlayer1"> | ||
| 55 | <property name="title"> | ||
| 56 | <string>Player 1</string> | ||
| 57 | </property> | ||
| 58 | <property name="checkable"> | ||
| 59 | <bool>true</bool> | ||
| 60 | </property> | ||
| 61 | <layout class="QHBoxLayout" name="horizontalLayout_8"> | ||
| 62 | <property name="leftMargin"> | ||
| 63 | <number>3</number> | ||
| 64 | </property> | ||
| 65 | <property name="topMargin"> | ||
| 66 | <number>3</number> | ||
| 67 | </property> | ||
| 68 | <property name="rightMargin"> | ||
| 69 | <number>3</number> | ||
| 70 | </property> | ||
| 71 | <property name="bottomMargin"> | ||
| 72 | <number>3</number> | ||
| 73 | </property> | ||
| 74 | <item> | ||
| 75 | <widget class="QSpinBox" name="vibrationSpinPlayer1"> | ||
| 76 | <property name="minimumSize"> | ||
| 77 | <size> | ||
| 78 | <width>68</width> | ||
| 79 | <height>21</height> | ||
| 80 | </size> | ||
| 81 | </property> | ||
| 82 | <property name="maximumSize"> | ||
| 83 | <size> | ||
| 84 | <width>68</width> | ||
| 85 | <height>16777215</height> | ||
| 86 | </size> | ||
| 87 | </property> | ||
| 88 | <property name="suffix"> | ||
| 89 | <string>%</string> | ||
| 90 | </property> | ||
| 91 | <property name="minimum"> | ||
| 92 | <number>1</number> | ||
| 93 | </property> | ||
| 94 | <property name="maximum"> | ||
| 95 | <number>150</number> | ||
| 96 | </property> | ||
| 97 | <property name="value"> | ||
| 98 | <number>100</number> | ||
| 99 | </property> | ||
| 100 | </widget> | ||
| 101 | </item> | ||
| 102 | </layout> | ||
| 103 | </widget> | ||
| 104 | </item> | ||
| 105 | <item> | ||
| 106 | <widget class="QGroupBox" name="vibrationGroupPlayer2"> | ||
| 107 | <property name="title"> | ||
| 108 | <string>Player 2</string> | ||
| 109 | </property> | ||
| 110 | <property name="checkable"> | ||
| 111 | <bool>true</bool> | ||
| 112 | </property> | ||
| 113 | <layout class="QHBoxLayout" name="horizontalLayout_9"> | ||
| 114 | <property name="leftMargin"> | ||
| 115 | <number>3</number> | ||
| 116 | </property> | ||
| 117 | <property name="topMargin"> | ||
| 118 | <number>3</number> | ||
| 119 | </property> | ||
| 120 | <property name="rightMargin"> | ||
| 121 | <number>3</number> | ||
| 122 | </property> | ||
| 123 | <property name="bottomMargin"> | ||
| 124 | <number>3</number> | ||
| 125 | </property> | ||
| 126 | <item> | ||
| 127 | <widget class="QSpinBox" name="vibrationSpinPlayer2"> | ||
| 128 | <property name="minimumSize"> | ||
| 129 | <size> | ||
| 130 | <width>68</width> | ||
| 131 | <height>21</height> | ||
| 132 | </size> | ||
| 133 | </property> | ||
| 134 | <property name="maximumSize"> | ||
| 135 | <size> | ||
| 136 | <width>68</width> | ||
| 137 | <height>16777215</height> | ||
| 138 | </size> | ||
| 139 | </property> | ||
| 140 | <property name="suffix"> | ||
| 141 | <string>%</string> | ||
| 142 | </property> | ||
| 143 | <property name="minimum"> | ||
| 144 | <number>1</number> | ||
| 145 | </property> | ||
| 146 | <property name="maximum"> | ||
| 147 | <number>150</number> | ||
| 148 | </property> | ||
| 149 | <property name="value"> | ||
| 150 | <number>100</number> | ||
| 151 | </property> | ||
| 152 | </widget> | ||
| 153 | </item> | ||
| 154 | </layout> | ||
| 155 | </widget> | ||
| 156 | </item> | ||
| 157 | <item> | ||
| 158 | <widget class="QGroupBox" name="vibrationGroupPlayer3"> | ||
| 159 | <property name="title"> | ||
| 160 | <string>Player 3</string> | ||
| 161 | </property> | ||
| 162 | <property name="checkable"> | ||
| 163 | <bool>true</bool> | ||
| 164 | </property> | ||
| 165 | <layout class="QHBoxLayout" name="horizontalLayout_10"> | ||
| 166 | <property name="leftMargin"> | ||
| 167 | <number>3</number> | ||
| 168 | </property> | ||
| 169 | <property name="topMargin"> | ||
| 170 | <number>3</number> | ||
| 171 | </property> | ||
| 172 | <property name="rightMargin"> | ||
| 173 | <number>3</number> | ||
| 174 | </property> | ||
| 175 | <property name="bottomMargin"> | ||
| 176 | <number>3</number> | ||
| 177 | </property> | ||
| 178 | <item> | ||
| 179 | <widget class="QSpinBox" name="vibrationSpinPlayer3"> | ||
| 180 | <property name="minimumSize"> | ||
| 181 | <size> | ||
| 182 | <width>68</width> | ||
| 183 | <height>21</height> | ||
| 184 | </size> | ||
| 185 | </property> | ||
| 186 | <property name="maximumSize"> | ||
| 187 | <size> | ||
| 188 | <width>68</width> | ||
| 189 | <height>16777215</height> | ||
| 190 | </size> | ||
| 191 | </property> | ||
| 192 | <property name="suffix"> | ||
| 193 | <string>%</string> | ||
| 194 | </property> | ||
| 195 | <property name="minimum"> | ||
| 196 | <number>1</number> | ||
| 197 | </property> | ||
| 198 | <property name="maximum"> | ||
| 199 | <number>150</number> | ||
| 200 | </property> | ||
| 201 | <property name="value"> | ||
| 202 | <number>100</number> | ||
| 203 | </property> | ||
| 204 | </widget> | ||
| 205 | </item> | ||
| 206 | </layout> | ||
| 207 | </widget> | ||
| 208 | </item> | ||
| 209 | <item> | ||
| 210 | <widget class="QGroupBox" name="vibrationGroupPlayer4"> | ||
| 211 | <property name="title"> | ||
| 212 | <string>Player 4</string> | ||
| 213 | </property> | ||
| 214 | <property name="checkable"> | ||
| 215 | <bool>true</bool> | ||
| 216 | </property> | ||
| 217 | <layout class="QHBoxLayout" name="horizontalLayout_11"> | ||
| 218 | <property name="leftMargin"> | ||
| 219 | <number>3</number> | ||
| 220 | </property> | ||
| 221 | <property name="topMargin"> | ||
| 222 | <number>3</number> | ||
| 223 | </property> | ||
| 224 | <property name="rightMargin"> | ||
| 225 | <number>3</number> | ||
| 226 | </property> | ||
| 227 | <property name="bottomMargin"> | ||
| 228 | <number>3</number> | ||
| 229 | </property> | ||
| 230 | <item> | ||
| 231 | <widget class="QSpinBox" name="vibrationSpinPlayer4"> | ||
| 232 | <property name="minimumSize"> | ||
| 233 | <size> | ||
| 234 | <width>68</width> | ||
| 235 | <height>21</height> | ||
| 236 | </size> | ||
| 237 | </property> | ||
| 238 | <property name="maximumSize"> | ||
| 239 | <size> | ||
| 240 | <width>68</width> | ||
| 241 | <height>16777215</height> | ||
| 242 | </size> | ||
| 243 | </property> | ||
| 244 | <property name="suffix"> | ||
| 245 | <string>%</string> | ||
| 246 | </property> | ||
| 247 | <property name="minimum"> | ||
| 248 | <number>1</number> | ||
| 249 | </property> | ||
| 250 | <property name="maximum"> | ||
| 251 | <number>150</number> | ||
| 252 | </property> | ||
| 253 | <property name="value"> | ||
| 254 | <number>100</number> | ||
| 255 | </property> | ||
| 256 | </widget> | ||
| 257 | </item> | ||
| 258 | </layout> | ||
| 259 | </widget> | ||
| 260 | </item> | ||
| 261 | </layout> | ||
| 262 | </widget> | ||
| 263 | </item> | ||
| 264 | <item> | ||
| 265 | <widget class="QWidget" name="player58Widget" native="true"> | ||
| 266 | <layout class="QHBoxLayout" name="horizontalLayout_6"> | ||
| 267 | <property name="leftMargin"> | ||
| 268 | <number>0</number> | ||
| 269 | </property> | ||
| 270 | <property name="topMargin"> | ||
| 271 | <number>0</number> | ||
| 272 | </property> | ||
| 273 | <property name="rightMargin"> | ||
| 274 | <number>0</number> | ||
| 275 | </property> | ||
| 276 | <property name="bottomMargin"> | ||
| 277 | <number>0</number> | ||
| 278 | </property> | ||
| 279 | <item> | ||
| 280 | <widget class="QGroupBox" name="vibrationGroupPlayer7"> | ||
| 281 | <property name="title"> | ||
| 282 | <string>Player 5</string> | ||
| 283 | </property> | ||
| 284 | <property name="checkable"> | ||
| 285 | <bool>true</bool> | ||
| 286 | </property> | ||
| 287 | <layout class="QHBoxLayout" name="horizontalLayout_14"> | ||
| 288 | <property name="leftMargin"> | ||
| 289 | <number>3</number> | ||
| 290 | </property> | ||
| 291 | <property name="topMargin"> | ||
| 292 | <number>3</number> | ||
| 293 | </property> | ||
| 294 | <property name="rightMargin"> | ||
| 295 | <number>3</number> | ||
| 296 | </property> | ||
| 297 | <property name="bottomMargin"> | ||
| 298 | <number>3</number> | ||
| 299 | </property> | ||
| 300 | <item> | ||
| 301 | <widget class="QSpinBox" name="vibrationSpinPlayer7"> | ||
| 302 | <property name="minimumSize"> | ||
| 303 | <size> | ||
| 304 | <width>68</width> | ||
| 305 | <height>21</height> | ||
| 306 | </size> | ||
| 307 | </property> | ||
| 308 | <property name="maximumSize"> | ||
| 309 | <size> | ||
| 310 | <width>68</width> | ||
| 311 | <height>16777215</height> | ||
| 312 | </size> | ||
| 313 | </property> | ||
| 314 | <property name="suffix"> | ||
| 315 | <string>%</string> | ||
| 316 | </property> | ||
| 317 | <property name="minimum"> | ||
| 318 | <number>1</number> | ||
| 319 | </property> | ||
| 320 | <property name="maximum"> | ||
| 321 | <number>150</number> | ||
| 322 | </property> | ||
| 323 | <property name="value"> | ||
| 324 | <number>100</number> | ||
| 325 | </property> | ||
| 326 | </widget> | ||
| 327 | </item> | ||
| 328 | </layout> | ||
| 329 | </widget> | ||
| 330 | </item> | ||
| 331 | <item> | ||
| 332 | <widget class="QGroupBox" name="vibrationGroupPlayer8"> | ||
| 333 | <property name="title"> | ||
| 334 | <string>Player 6</string> | ||
| 335 | </property> | ||
| 336 | <property name="checkable"> | ||
| 337 | <bool>true</bool> | ||
| 338 | </property> | ||
| 339 | <layout class="QHBoxLayout" name="horizontalLayout_15"> | ||
| 340 | <property name="leftMargin"> | ||
| 341 | <number>3</number> | ||
| 342 | </property> | ||
| 343 | <property name="topMargin"> | ||
| 344 | <number>3</number> | ||
| 345 | </property> | ||
| 346 | <property name="rightMargin"> | ||
| 347 | <number>3</number> | ||
| 348 | </property> | ||
| 349 | <property name="bottomMargin"> | ||
| 350 | <number>3</number> | ||
| 351 | </property> | ||
| 352 | <item> | ||
| 353 | <widget class="QSpinBox" name="vibrationSpinPlayer8"> | ||
| 354 | <property name="minimumSize"> | ||
| 355 | <size> | ||
| 356 | <width>68</width> | ||
| 357 | <height>21</height> | ||
| 358 | </size> | ||
| 359 | </property> | ||
| 360 | <property name="maximumSize"> | ||
| 361 | <size> | ||
| 362 | <width>68</width> | ||
| 363 | <height>16777215</height> | ||
| 364 | </size> | ||
| 365 | </property> | ||
| 366 | <property name="suffix"> | ||
| 367 | <string>%</string> | ||
| 368 | </property> | ||
| 369 | <property name="minimum"> | ||
| 370 | <number>1</number> | ||
| 371 | </property> | ||
| 372 | <property name="maximum"> | ||
| 373 | <number>150</number> | ||
| 374 | </property> | ||
| 375 | <property name="value"> | ||
| 376 | <number>100</number> | ||
| 377 | </property> | ||
| 378 | </widget> | ||
| 379 | </item> | ||
| 380 | </layout> | ||
| 381 | </widget> | ||
| 382 | </item> | ||
| 383 | <item> | ||
| 384 | <widget class="QGroupBox" name="vibrationGroupPlayer5"> | ||
| 385 | <property name="title"> | ||
| 386 | <string>Player 7</string> | ||
| 387 | </property> | ||
| 388 | <property name="checkable"> | ||
| 389 | <bool>true</bool> | ||
| 390 | </property> | ||
| 391 | <layout class="QHBoxLayout" name="horizontalLayout_12"> | ||
| 392 | <property name="leftMargin"> | ||
| 393 | <number>3</number> | ||
| 394 | </property> | ||
| 395 | <property name="topMargin"> | ||
| 396 | <number>3</number> | ||
| 397 | </property> | ||
| 398 | <property name="rightMargin"> | ||
| 399 | <number>3</number> | ||
| 400 | </property> | ||
| 401 | <property name="bottomMargin"> | ||
| 402 | <number>3</number> | ||
| 403 | </property> | ||
| 404 | <item> | ||
| 405 | <widget class="QSpinBox" name="vibrationSpinPlayer5"> | ||
| 406 | <property name="minimumSize"> | ||
| 407 | <size> | ||
| 408 | <width>68</width> | ||
| 409 | <height>21</height> | ||
| 410 | </size> | ||
| 411 | </property> | ||
| 412 | <property name="maximumSize"> | ||
| 413 | <size> | ||
| 414 | <width>68</width> | ||
| 415 | <height>16777215</height> | ||
| 416 | </size> | ||
| 417 | </property> | ||
| 418 | <property name="suffix"> | ||
| 419 | <string>%</string> | ||
| 420 | </property> | ||
| 421 | <property name="minimum"> | ||
| 422 | <number>1</number> | ||
| 423 | </property> | ||
| 424 | <property name="maximum"> | ||
| 425 | <number>150</number> | ||
| 426 | </property> | ||
| 427 | <property name="value"> | ||
| 428 | <number>100</number> | ||
| 429 | </property> | ||
| 430 | </widget> | ||
| 431 | </item> | ||
| 432 | </layout> | ||
| 433 | </widget> | ||
| 434 | </item> | ||
| 435 | <item> | ||
| 436 | <widget class="QGroupBox" name="vibrationGroupPlayer6"> | ||
| 437 | <property name="title"> | ||
| 438 | <string>Player 8</string> | ||
| 439 | </property> | ||
| 440 | <property name="checkable"> | ||
| 441 | <bool>true</bool> | ||
| 442 | </property> | ||
| 443 | <layout class="QHBoxLayout" name="horizontalLayout_13"> | ||
| 444 | <property name="leftMargin"> | ||
| 445 | <number>3</number> | ||
| 446 | </property> | ||
| 447 | <property name="topMargin"> | ||
| 448 | <number>3</number> | ||
| 449 | </property> | ||
| 450 | <property name="rightMargin"> | ||
| 451 | <number>3</number> | ||
| 452 | </property> | ||
| 453 | <property name="bottomMargin"> | ||
| 454 | <number>3</number> | ||
| 455 | </property> | ||
| 456 | <item> | ||
| 457 | <widget class="QSpinBox" name="vibrationSpinPlayer6"> | ||
| 458 | <property name="minimumSize"> | ||
| 459 | <size> | ||
| 460 | <width>68</width> | ||
| 461 | <height>21</height> | ||
| 462 | </size> | ||
| 463 | </property> | ||
| 464 | <property name="maximumSize"> | ||
| 465 | <size> | ||
| 466 | <width>68</width> | ||
| 467 | <height>16777215</height> | ||
| 468 | </size> | ||
| 469 | </property> | ||
| 470 | <property name="suffix"> | ||
| 471 | <string>%</string> | ||
| 472 | </property> | ||
| 473 | <property name="minimum"> | ||
| 474 | <number>1</number> | ||
| 475 | </property> | ||
| 476 | <property name="maximum"> | ||
| 477 | <number>150</number> | ||
| 478 | </property> | ||
| 479 | <property name="value"> | ||
| 480 | <number>100</number> | ||
| 481 | </property> | ||
| 482 | </widget> | ||
| 483 | </item> | ||
| 484 | </layout> | ||
| 485 | </widget> | ||
| 486 | </item> | ||
| 487 | </layout> | ||
| 488 | </widget> | ||
| 489 | </item> | ||
| 490 | </layout> | ||
| 491 | </widget> | ||
| 492 | </item> | ||
| 493 | <item> | ||
| 494 | <widget class="QGroupBox" name="vibrationSettingsGroup"> | ||
| 495 | <property name="title"> | ||
| 496 | <string>Settings</string> | ||
| 497 | </property> | ||
| 498 | <layout class="QVBoxLayout" name="verticalLayout"> | ||
| 499 | <item> | ||
| 500 | <widget class="QCheckBox" name="checkBoxAccurateVibration"> | ||
| 501 | <property name="text"> | ||
| 502 | <string>Enable Accurate Vibration</string> | ||
| 503 | </property> | ||
| 504 | </widget> | ||
| 505 | </item> | ||
| 506 | </layout> | ||
| 507 | </widget> | ||
| 508 | </item> | ||
| 509 | <item> | ||
| 510 | <spacer name="spacerVibration"> | ||
| 511 | <property name="orientation"> | ||
| 512 | <enum>Qt::Vertical</enum> | ||
| 513 | </property> | ||
| 514 | <property name="sizeHint" stdset="0"> | ||
| 515 | <size> | ||
| 516 | <width>167</width> | ||
| 517 | <height>55</height> | ||
| 518 | </size> | ||
| 519 | </property> | ||
| 520 | </spacer> | ||
| 521 | </item> | ||
| 522 | <item> | ||
| 523 | <widget class="QDialogButtonBox" name="buttonBoxVibration"> | ||
| 524 | <property name="standardButtons"> | ||
| 525 | <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||
| 526 | </property> | ||
| 527 | </widget> | ||
| 528 | </item> | ||
| 529 | </layout> | ||
| 530 | </widget> | ||
| 531 | <resources/> | ||
| 532 | <connections> | ||
| 533 | <connection> | ||
| 534 | <sender>buttonBoxVibration</sender> | ||
| 535 | <signal>accepted()</signal> | ||
| 536 | <receiver>ConfigureVibration</receiver> | ||
| 537 | <slot>accept()</slot> | ||
| 538 | </connection> | ||
| 539 | <connection> | ||
| 540 | <sender>buttonBoxVibration</sender> | ||
| 541 | <signal>rejected()</signal> | ||
| 542 | <receiver>ConfigureVibration</receiver> | ||
| 543 | <slot>reject()</slot> | ||
| 544 | </connection> | ||
| 545 | </connections> | ||
| 546 | </ui> | ||
diff --git a/src/yuzu/configuration/input_profiles.cpp b/src/yuzu/configuration/input_profiles.cpp new file mode 100644 index 000000000..e87aededb --- /dev/null +++ b/src/yuzu/configuration/input_profiles.cpp | |||
| @@ -0,0 +1,131 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <fmt/format.h> | ||
| 6 | |||
| 7 | #include "common/common_paths.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | #include "yuzu/configuration/config.h" | ||
| 10 | #include "yuzu/configuration/input_profiles.h" | ||
| 11 | |||
| 12 | namespace FS = Common::FS; | ||
| 13 | |||
| 14 | namespace { | ||
| 15 | |||
| 16 | bool ProfileExistsInFilesystem(std::string_view profile_name) { | ||
| 17 | return FS::Exists(fmt::format("{}input" DIR_SEP "{}.ini", | ||
| 18 | FS::GetUserPath(FS::UserPath::ConfigDir), profile_name)); | ||
| 19 | } | ||
| 20 | |||
| 21 | bool IsINI(std::string_view filename) { | ||
| 22 | const std::size_t index = filename.rfind('.'); | ||
| 23 | |||
| 24 | if (index == std::string::npos) { | ||
| 25 | return false; | ||
| 26 | } | ||
| 27 | |||
| 28 | return filename.substr(index) == ".ini"; | ||
| 29 | } | ||
| 30 | |||
| 31 | std::string GetNameWithoutExtension(const std::string& filename) { | ||
| 32 | const std::size_t index = filename.rfind('.'); | ||
| 33 | |||
| 34 | if (index == std::string::npos) { | ||
| 35 | return filename; | ||
| 36 | } | ||
| 37 | |||
| 38 | return filename.substr(0, index); | ||
| 39 | } | ||
| 40 | |||
| 41 | } // namespace | ||
| 42 | |||
| 43 | InputProfiles::InputProfiles() { | ||
| 44 | const std::string input_profile_loc = | ||
| 45 | fmt::format("{}input", FS::GetUserPath(FS::UserPath::ConfigDir)); | ||
| 46 | |||
| 47 | FS::ForeachDirectoryEntry( | ||
| 48 | nullptr, input_profile_loc, | ||
| 49 | [this](u64* entries_out, const std::string& directory, const std::string& filename) { | ||
| 50 | if (IsINI(filename) && IsProfileNameValid(GetNameWithoutExtension(filename))) { | ||
| 51 | map_profiles.insert_or_assign( | ||
| 52 | GetNameWithoutExtension(filename), | ||
| 53 | std::make_unique<Config>(GetNameWithoutExtension(filename), | ||
| 54 | Config::ConfigType::InputProfile)); | ||
| 55 | } | ||
| 56 | return true; | ||
| 57 | }); | ||
| 58 | } | ||
| 59 | |||
| 60 | InputProfiles::~InputProfiles() = default; | ||
| 61 | |||
| 62 | std::vector<std::string> InputProfiles::GetInputProfileNames() { | ||
| 63 | std::vector<std::string> profile_names; | ||
| 64 | profile_names.reserve(map_profiles.size()); | ||
| 65 | |||
| 66 | for (const auto& [profile_name, config] : map_profiles) { | ||
| 67 | if (!ProfileExistsInFilesystem(profile_name)) { | ||
| 68 | DeleteProfile(profile_name); | ||
| 69 | continue; | ||
| 70 | } | ||
| 71 | |||
| 72 | profile_names.push_back(profile_name); | ||
| 73 | } | ||
| 74 | |||
| 75 | return profile_names; | ||
| 76 | } | ||
| 77 | |||
| 78 | bool InputProfiles::IsProfileNameValid(std::string_view profile_name) { | ||
| 79 | return profile_name.find_first_of("<>:;\"/\\|,.!?*") == std::string::npos; | ||
| 80 | } | ||
| 81 | |||
| 82 | bool InputProfiles::CreateProfile(const std::string& profile_name, std::size_t player_index) { | ||
| 83 | if (ProfileExistsInMap(profile_name)) { | ||
| 84 | return false; | ||
| 85 | } | ||
| 86 | |||
| 87 | map_profiles.insert_or_assign( | ||
| 88 | profile_name, std::make_unique<Config>(profile_name, Config::ConfigType::InputProfile)); | ||
| 89 | |||
| 90 | return SaveProfile(profile_name, player_index); | ||
| 91 | } | ||
| 92 | |||
| 93 | bool InputProfiles::DeleteProfile(const std::string& profile_name) { | ||
| 94 | if (!ProfileExistsInMap(profile_name)) { | ||
| 95 | return false; | ||
| 96 | } | ||
| 97 | |||
| 98 | if (!ProfileExistsInFilesystem(profile_name) || | ||
| 99 | FS::Delete(map_profiles[profile_name]->GetConfigFilePath())) { | ||
| 100 | map_profiles.erase(profile_name); | ||
| 101 | } | ||
| 102 | |||
| 103 | return !ProfileExistsInMap(profile_name) && !ProfileExistsInFilesystem(profile_name); | ||
| 104 | } | ||
| 105 | |||
| 106 | bool InputProfiles::LoadProfile(const std::string& profile_name, std::size_t player_index) { | ||
| 107 | if (!ProfileExistsInMap(profile_name)) { | ||
| 108 | return false; | ||
| 109 | } | ||
| 110 | |||
| 111 | if (!ProfileExistsInFilesystem(profile_name)) { | ||
| 112 | map_profiles.erase(profile_name); | ||
| 113 | return false; | ||
| 114 | } | ||
| 115 | |||
| 116 | map_profiles[profile_name]->ReadControlPlayerValue(player_index); | ||
| 117 | return true; | ||
| 118 | } | ||
| 119 | |||
| 120 | bool InputProfiles::SaveProfile(const std::string& profile_name, std::size_t player_index) { | ||
| 121 | if (!ProfileExistsInMap(profile_name)) { | ||
| 122 | return false; | ||
| 123 | } | ||
| 124 | |||
| 125 | map_profiles[profile_name]->SaveControlPlayerValue(player_index); | ||
| 126 | return true; | ||
| 127 | } | ||
| 128 | |||
| 129 | bool InputProfiles::ProfileExistsInMap(const std::string& profile_name) const { | ||
| 130 | return map_profiles.find(profile_name) != map_profiles.end(); | ||
| 131 | } | ||
diff --git a/src/yuzu/configuration/input_profiles.h b/src/yuzu/configuration/input_profiles.h new file mode 100644 index 000000000..cb41fd9be --- /dev/null +++ b/src/yuzu/configuration/input_profiles.h | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | // Copyright 2020 yuzu 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 <string> | ||
| 8 | #include <string_view> | ||
| 9 | #include <unordered_map> | ||
| 10 | |||
| 11 | class Config; | ||
| 12 | |||
| 13 | class InputProfiles { | ||
| 14 | |||
| 15 | public: | ||
| 16 | explicit InputProfiles(); | ||
| 17 | virtual ~InputProfiles(); | ||
| 18 | |||
| 19 | std::vector<std::string> GetInputProfileNames(); | ||
| 20 | |||
| 21 | static bool IsProfileNameValid(std::string_view profile_name); | ||
| 22 | |||
| 23 | bool CreateProfile(const std::string& profile_name, std::size_t player_index); | ||
| 24 | bool DeleteProfile(const std::string& profile_name); | ||
| 25 | bool LoadProfile(const std::string& profile_name, std::size_t player_index); | ||
| 26 | bool SaveProfile(const std::string& profile_name, std::size_t player_index); | ||
| 27 | |||
| 28 | private: | ||
| 29 | bool ProfileExistsInMap(const std::string& profile_name) const; | ||
| 30 | |||
| 31 | std::unordered_map<std::string, std::unique_ptr<Config>> map_profiles; | ||
| 32 | }; | ||
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 18e68e590..9dabd8889 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include "applets/web_browser.h" | 18 | #include "applets/web_browser.h" |
| 19 | #include "configuration/configure_input.h" | 19 | #include "configuration/configure_input.h" |
| 20 | #include "configuration/configure_per_game.h" | 20 | #include "configuration/configure_per_game.h" |
| 21 | #include "configuration/configure_vibration.h" | ||
| 21 | #include "core/file_sys/vfs.h" | 22 | #include "core/file_sys/vfs.h" |
| 22 | #include "core/file_sys/vfs_real.h" | 23 | #include "core/file_sys/vfs_real.h" |
| 23 | #include "core/frontend/applets/controller.h" | 24 | #include "core/frontend/applets/controller.h" |
| @@ -50,12 +51,14 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual | |||
| 50 | #include <QDesktopServices> | 51 | #include <QDesktopServices> |
| 51 | #include <QDesktopWidget> | 52 | #include <QDesktopWidget> |
| 52 | #include <QDialogButtonBox> | 53 | #include <QDialogButtonBox> |
| 54 | #include <QDir> | ||
| 53 | #include <QFile> | 55 | #include <QFile> |
| 54 | #include <QFileDialog> | 56 | #include <QFileDialog> |
| 55 | #include <QInputDialog> | 57 | #include <QInputDialog> |
| 56 | #include <QMessageBox> | 58 | #include <QMessageBox> |
| 57 | #include <QProgressBar> | 59 | #include <QProgressBar> |
| 58 | #include <QProgressDialog> | 60 | #include <QProgressDialog> |
| 61 | #include <QPushButton> | ||
| 59 | #include <QShortcut> | 62 | #include <QShortcut> |
| 60 | #include <QStatusBar> | 63 | #include <QStatusBar> |
| 61 | #include <QSysInfo> | 64 | #include <QSysInfo> |
| @@ -277,6 +280,8 @@ GMainWindow::GMainWindow() | |||
| 277 | if (args.length() >= 2) { | 280 | if (args.length() >= 2) { |
| 278 | BootGame(args[1]); | 281 | BootGame(args[1]); |
| 279 | } | 282 | } |
| 283 | |||
| 284 | MigrateConfigFiles(); | ||
| 280 | } | 285 | } |
| 281 | 286 | ||
| 282 | GMainWindow::~GMainWindow() { | 287 | GMainWindow::~GMainWindow() { |
| @@ -288,6 +293,7 @@ GMainWindow::~GMainWindow() { | |||
| 288 | void GMainWindow::ControllerSelectorReconfigureControllers( | 293 | void GMainWindow::ControllerSelectorReconfigureControllers( |
| 289 | const Core::Frontend::ControllerParameters& parameters) { | 294 | const Core::Frontend::ControllerParameters& parameters) { |
| 290 | QtControllerSelectorDialog dialog(this, parameters, input_subsystem.get()); | 295 | QtControllerSelectorDialog dialog(this, parameters, input_subsystem.get()); |
| 296 | |||
| 291 | dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint | | 297 | dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint | |
| 292 | Qt::WindowTitleHint | Qt::WindowSystemMenuHint); | 298 | Qt::WindowTitleHint | Qt::WindowSystemMenuHint); |
| 293 | dialog.setWindowModality(Qt::WindowModal); | 299 | dialog.setWindowModality(Qt::WindowModal); |
| @@ -547,13 +553,14 @@ void GMainWindow::InitializeWidgets() { | |||
| 547 | dock_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton")); | 553 | dock_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton")); |
| 548 | dock_status_button->setFocusPolicy(Qt::NoFocus); | 554 | dock_status_button->setFocusPolicy(Qt::NoFocus); |
| 549 | connect(dock_status_button, &QPushButton::clicked, [&] { | 555 | connect(dock_status_button, &QPushButton::clicked, [&] { |
| 550 | Settings::values.use_docked_mode = !Settings::values.use_docked_mode; | 556 | Settings::values.use_docked_mode.SetValue(!Settings::values.use_docked_mode.GetValue()); |
| 551 | dock_status_button->setChecked(Settings::values.use_docked_mode); | 557 | dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue()); |
| 552 | OnDockedModeChanged(!Settings::values.use_docked_mode, Settings::values.use_docked_mode); | 558 | OnDockedModeChanged(!Settings::values.use_docked_mode.GetValue(), |
| 559 | Settings::values.use_docked_mode.GetValue()); | ||
| 553 | }); | 560 | }); |
| 554 | dock_status_button->setText(tr("DOCK")); | 561 | dock_status_button->setText(tr("DOCK")); |
| 555 | dock_status_button->setCheckable(true); | 562 | dock_status_button->setCheckable(true); |
| 556 | dock_status_button->setChecked(Settings::values.use_docked_mode); | 563 | dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue()); |
| 557 | statusBar()->insertPermanentWidget(0, dock_status_button); | 564 | statusBar()->insertPermanentWidget(0, dock_status_button); |
| 558 | 565 | ||
| 559 | // Setup ASync button | 566 | // Setup ASync button |
| @@ -792,10 +799,11 @@ void GMainWindow::InitializeHotkeys() { | |||
| 792 | }); | 799 | }); |
| 793 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Change Docked Mode"), this), | 800 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Change Docked Mode"), this), |
| 794 | &QShortcut::activated, this, [&] { | 801 | &QShortcut::activated, this, [&] { |
| 795 | Settings::values.use_docked_mode = !Settings::values.use_docked_mode; | 802 | Settings::values.use_docked_mode.SetValue( |
| 796 | OnDockedModeChanged(!Settings::values.use_docked_mode, | 803 | !Settings::values.use_docked_mode.GetValue()); |
| 797 | Settings::values.use_docked_mode); | 804 | OnDockedModeChanged(!Settings::values.use_docked_mode.GetValue(), |
| 798 | dock_status_button->setChecked(Settings::values.use_docked_mode); | 805 | Settings::values.use_docked_mode.GetValue()); |
| 806 | dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue()); | ||
| 799 | }); | 807 | }); |
| 800 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Mute Audio"), this), | 808 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Mute Audio"), this), |
| 801 | &QShortcut::activated, this, | 809 | &QShortcut::activated, this, |
| @@ -1087,9 +1095,11 @@ void GMainWindow::BootGame(const QString& filename) { | |||
| 1087 | const auto loader = Loader::GetLoader(v_file); | 1095 | const auto loader = Loader::GetLoader(v_file); |
| 1088 | if (!(loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success)) { | 1096 | if (!(loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success)) { |
| 1089 | // Load per game settings | 1097 | // Load per game settings |
| 1090 | Config per_game_config(fmt::format("{:016X}.ini", title_id), false); | 1098 | Config per_game_config(fmt::format("{:016X}", title_id), Config::ConfigType::PerGameConfig); |
| 1091 | } | 1099 | } |
| 1092 | 1100 | ||
| 1101 | ConfigureVibration::SetAllVibrationDevices(); | ||
| 1102 | |||
| 1093 | Settings::LogSettings(); | 1103 | Settings::LogSettings(); |
| 1094 | 1104 | ||
| 1095 | if (UISettings::values.select_user_on_boot) { | 1105 | if (UISettings::values.select_user_on_boot) { |
| @@ -1577,7 +1587,8 @@ void GMainWindow::RemoveCustomConfiguration(u64 program_id) { | |||
| 1577 | const QString config_dir = | 1587 | const QString config_dir = |
| 1578 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir)); | 1588 | QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir)); |
| 1579 | const QString custom_config_file_path = | 1589 | const QString custom_config_file_path = |
| 1580 | config_dir + QString::fromStdString(fmt::format("{:016X}.ini", program_id)); | 1590 | config_dir + QStringLiteral("custom") + QDir::separator() + |
| 1591 | QString::fromStdString(fmt::format("{:016X}.ini", program_id)); | ||
| 1581 | 1592 | ||
| 1582 | if (!QFile::exists(custom_config_file_path)) { | 1593 | if (!QFile::exists(custom_config_file_path)) { |
| 1583 | QMessageBox::warning(this, tr("Error Removing Custom Configuration"), | 1594 | QMessageBox::warning(this, tr("Error Removing Custom Configuration"), |
| @@ -2393,6 +2404,29 @@ void GMainWindow::OnCaptureScreenshot() { | |||
| 2393 | OnStartGame(); | 2404 | OnStartGame(); |
| 2394 | } | 2405 | } |
| 2395 | 2406 | ||
| 2407 | // TODO: Written 2020-10-01: Remove per-game config migration code when it is irrelevant | ||
| 2408 | void GMainWindow::MigrateConfigFiles() { | ||
| 2409 | const std::string& config_dir_str = Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir); | ||
| 2410 | const QDir config_dir = QDir(QString::fromStdString(config_dir_str)); | ||
| 2411 | const QStringList config_dir_list = config_dir.entryList(QStringList(QStringLiteral("*.ini"))); | ||
| 2412 | |||
| 2413 | Common::FS::CreateFullPath(fmt::format("{}custom" DIR_SEP, config_dir_str)); | ||
| 2414 | for (QStringList::const_iterator it = config_dir_list.constBegin(); | ||
| 2415 | it != config_dir_list.constEnd(); ++it) { | ||
| 2416 | const auto filename = it->toStdString(); | ||
| 2417 | if (filename.find_first_not_of("0123456789abcdefACBDEF", 0) < 16) { | ||
| 2418 | continue; | ||
| 2419 | } | ||
| 2420 | const auto origin = fmt::format("{}{}", config_dir_str, filename); | ||
| 2421 | const auto destination = fmt::format("{}custom" DIR_SEP "{}", config_dir_str, filename); | ||
| 2422 | LOG_INFO(Frontend, "Migrating config file from {} to {}", origin, destination); | ||
| 2423 | if (!Common::FS::Rename(origin, destination)) { | ||
| 2424 | // Delete the old config file if one already exists in the new location. | ||
| 2425 | Common::FS::Delete(origin); | ||
| 2426 | } | ||
| 2427 | } | ||
| 2428 | } | ||
| 2429 | |||
| 2396 | void GMainWindow::UpdateWindowTitle(const std::string& title_name, | 2430 | void GMainWindow::UpdateWindowTitle(const std::string& title_name, |
| 2397 | const std::string& title_version) { | 2431 | const std::string& title_version) { |
| 2398 | const auto full_name = std::string(Common::g_build_fullname); | 2432 | const auto full_name = std::string(Common::g_build_fullname); |
| @@ -2450,7 +2484,7 @@ void GMainWindow::UpdateStatusBar() { | |||
| 2450 | } | 2484 | } |
| 2451 | 2485 | ||
| 2452 | void GMainWindow::UpdateStatusButtons() { | 2486 | void GMainWindow::UpdateStatusButtons() { |
| 2453 | dock_status_button->setChecked(Settings::values.use_docked_mode); | 2487 | dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue()); |
| 2454 | multicore_status_button->setChecked(Settings::values.use_multi_core.GetValue()); | 2488 | multicore_status_button->setChecked(Settings::values.use_multi_core.GetValue()); |
| 2455 | Settings::values.use_asynchronous_gpu_emulation.SetValue( | 2489 | Settings::values.use_asynchronous_gpu_emulation.SetValue( |
| 2456 | Settings::values.use_asynchronous_gpu_emulation.GetValue() || | 2490 | Settings::values.use_asynchronous_gpu_emulation.GetValue() || |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index afcfa68a9..b380a66f3 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -251,6 +251,7 @@ private: | |||
| 251 | std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id); | 251 | std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id); |
| 252 | InstallResult InstallNSPXCI(const QString& filename); | 252 | InstallResult InstallNSPXCI(const QString& filename); |
| 253 | InstallResult InstallNCA(const QString& filename); | 253 | InstallResult InstallNCA(const QString& filename); |
| 254 | void MigrateConfigFiles(); | ||
| 254 | void UpdateWindowTitle(const std::string& title_name = {}, | 255 | void UpdateWindowTitle(const std::string& title_name = {}, |
| 255 | const std::string& title_version = {}); | 256 | const std::string& title_version = {}); |
| 256 | void UpdateStatusBar(); | 257 | void UpdateStatusBar(); |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 334038ef9..e1adbbf2b 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -228,24 +228,24 @@ static const std::array<int, 8> keyboard_mods{ | |||
| 228 | 228 | ||
| 229 | void Config::ReadValues() { | 229 | void Config::ReadValues() { |
| 230 | // Controls | 230 | // Controls |
| 231 | for (std::size_t p = 0; p < Settings::values.players.size(); ++p) { | 231 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { |
| 232 | const auto group = fmt::format("ControlsP{}", p); | 232 | const auto group = fmt::format("ControlsP{}", p); |
| 233 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | 233 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { |
| 234 | std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | 234 | std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); |
| 235 | Settings::values.players[p].buttons[i] = | 235 | Settings::values.players.GetValue()[p].buttons[i] = |
| 236 | sdl2_config->Get(group, Settings::NativeButton::mapping[i], default_param); | 236 | sdl2_config->Get(group, Settings::NativeButton::mapping[i], default_param); |
| 237 | if (Settings::values.players[p].buttons[i].empty()) | 237 | if (Settings::values.players.GetValue()[p].buttons[i].empty()) |
| 238 | Settings::values.players[p].buttons[i] = default_param; | 238 | Settings::values.players.GetValue()[p].buttons[i] = default_param; |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | 241 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { |
| 242 | std::string default_param = InputCommon::GenerateAnalogParamFromKeys( | 242 | std::string default_param = InputCommon::GenerateAnalogParamFromKeys( |
| 243 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], | 243 | default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], |
| 244 | default_analogs[i][3], default_analogs[i][4], 0.5f); | 244 | default_analogs[i][3], default_analogs[i][4], 0.5f); |
| 245 | Settings::values.players[p].analogs[i] = | 245 | Settings::values.players.GetValue()[p].analogs[i] = |
| 246 | sdl2_config->Get(group, Settings::NativeAnalog::mapping[i], default_param); | 246 | sdl2_config->Get(group, Settings::NativeAnalog::mapping[i], default_param); |
| 247 | if (Settings::values.players[p].analogs[i].empty()) | 247 | if (Settings::values.players.GetValue()[p].analogs[i].empty()) |
| 248 | Settings::values.players[p].analogs[i] = default_param; | 248 | Settings::values.players.GetValue()[p].analogs[i] = default_param; |
| 249 | } | 249 | } |
| 250 | } | 250 | } |
| 251 | 251 | ||
| @@ -288,10 +288,12 @@ void Config::ReadValues() { | |||
| 288 | Settings::values.debug_pad_analogs[i] = default_param; | 288 | Settings::values.debug_pad_analogs[i] = default_param; |
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | Settings::values.vibration_enabled = | 291 | Settings::values.vibration_enabled.SetValue( |
| 292 | sdl2_config->GetBoolean("ControlsGeneral", "vibration_enabled", true); | 292 | sdl2_config->GetBoolean("ControlsGeneral", "vibration_enabled", true)); |
| 293 | Settings::values.motion_enabled = | 293 | Settings::values.enable_accurate_vibrations.SetValue( |
| 294 | sdl2_config->GetBoolean("ControlsGeneral", "motion_enabled", true); | 294 | sdl2_config->GetBoolean("ControlsGeneral", "enable_accurate_vibrations", false)); |
| 295 | Settings::values.motion_enabled.SetValue( | ||
| 296 | sdl2_config->GetBoolean("ControlsGeneral", "motion_enabled", true)); | ||
| 295 | Settings::values.touchscreen.enabled = | 297 | Settings::values.touchscreen.enabled = |
| 296 | sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true); | 298 | sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true); |
| 297 | Settings::values.touchscreen.device = | 299 | Settings::values.touchscreen.device = |
| @@ -343,7 +345,8 @@ void Config::ReadValues() { | |||
| 343 | Settings::values.gamecard_path = sdl2_config->Get("Data Storage", "gamecard_path", ""); | 345 | Settings::values.gamecard_path = sdl2_config->Get("Data Storage", "gamecard_path", ""); |
| 344 | 346 | ||
| 345 | // System | 347 | // System |
| 346 | Settings::values.use_docked_mode = sdl2_config->GetBoolean("System", "use_docked_mode", false); | 348 | Settings::values.use_docked_mode.SetValue( |
| 349 | sdl2_config->GetBoolean("System", "use_docked_mode", false)); | ||
| 347 | const auto size = sdl2_config->GetInteger("System", "users_size", 0); | 350 | const auto size = sdl2_config->GetInteger("System", "users_size", 0); |
| 348 | 351 | ||
| 349 | Settings::values.current_user = std::clamp<int>( | 352 | Settings::values.current_user = std::clamp<int>( |
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index 796e27df4..bcbbcd4ca 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h | |||
| @@ -65,6 +65,14 @@ button_screenshot= | |||
| 65 | lstick= | 65 | lstick= |
| 66 | rstick= | 66 | rstick= |
| 67 | 67 | ||
| 68 | # Whether to enable or disable vibration | ||
| 69 | # 0: Disabled, 1 (default): Enabled | ||
| 70 | vibration_enabled= | ||
| 71 | |||
| 72 | # Whether to enable or disable accurate vibrations | ||
| 73 | # 0 (default): Disabled, 1: Enabled | ||
| 74 | enable_accurate_vibrations= | ||
| 75 | |||
| 68 | # for motion input, the following devices are available: | 76 | # for motion input, the following devices are available: |
| 69 | # - "motion_emu" (default) for emulating motion input from mouse input. Required parameters: | 77 | # - "motion_emu" (default) for emulating motion input from mouse input. Required parameters: |
| 70 | # - "update_period": update period in milliseconds (default to 100) | 78 | # - "update_period": update period in milliseconds (default to 100) |
diff --git a/src/yuzu_tester/config.cpp b/src/yuzu_tester/config.cpp index bc273fb51..b6cdc7c1c 100644 --- a/src/yuzu_tester/config.cpp +++ b/src/yuzu_tester/config.cpp | |||
| @@ -47,13 +47,13 @@ bool Config::LoadINI(const std::string& default_contents, bool retry) { | |||
| 47 | 47 | ||
| 48 | void Config::ReadValues() { | 48 | void Config::ReadValues() { |
| 49 | // Controls | 49 | // Controls |
| 50 | for (std::size_t p = 0; p < Settings::values.players.size(); ++p) { | 50 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { |
| 51 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | 51 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { |
| 52 | Settings::values.players[p].buttons[i] = ""; | 52 | Settings::values.players.GetValue()[p].buttons[i] = ""; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { | 55 | for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { |
| 56 | Settings::values.players[p].analogs[i] = ""; | 56 | Settings::values.players.GetValue()[p].analogs[i] = ""; |
| 57 | } | 57 | } |
| 58 | } | 58 | } |
| 59 | 59 | ||
| @@ -75,8 +75,9 @@ void Config::ReadValues() { | |||
| 75 | Settings::values.debug_pad_analogs[i] = ""; | 75 | Settings::values.debug_pad_analogs[i] = ""; |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | Settings::values.vibration_enabled = true; | 78 | Settings::values.vibration_enabled.SetValue(true); |
| 79 | Settings::values.motion_enabled = true; | 79 | Settings::values.enable_accurate_vibrations.SetValue(false); |
| 80 | Settings::values.motion_enabled.SetValue(true); | ||
| 80 | Settings::values.touchscreen.enabled = ""; | 81 | Settings::values.touchscreen.enabled = ""; |
| 81 | Settings::values.touchscreen.device = ""; | 82 | Settings::values.touchscreen.device = ""; |
| 82 | Settings::values.touchscreen.finger = 0; | 83 | Settings::values.touchscreen.finger = 0; |
| @@ -84,8 +85,8 @@ void Config::ReadValues() { | |||
| 84 | Settings::values.touchscreen.diameter_x = 15; | 85 | Settings::values.touchscreen.diameter_x = 15; |
| 85 | Settings::values.touchscreen.diameter_y = 15; | 86 | Settings::values.touchscreen.diameter_y = 15; |
| 86 | 87 | ||
| 87 | Settings::values.use_docked_mode = | 88 | Settings::values.use_docked_mode.SetValue( |
| 88 | sdl2_config->GetBoolean("Controls", "use_docked_mode", false); | 89 | sdl2_config->GetBoolean("Controls", "use_docked_mode", false)); |
| 89 | 90 | ||
| 90 | // Data Storage | 91 | // Data Storage |
| 91 | Settings::values.use_virtual_sd = | 92 | Settings::values.use_virtual_sd = |