From beab38601badd54930881858b4a021fe76a92b39 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Thu, 18 Oct 2018 14:11:15 +1100 Subject: [PATCH 01/26] Added multi-input support and controller assignment at any port --- src/core/hle/service/hid/controllers/npad.cpp | 287 ++++++++++-------- src/core/hle/service/hid/controllers/npad.h | 16 +- 2 files changed, 181 insertions(+), 122 deletions(-) diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 205e4fd14..5b0ca57f8 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -164,6 +164,57 @@ void Controller_NPad::OnLoadInputDevices() { void Controller_NPad::OnRelease() {} +void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { + const auto controller_idx = NPadIdToIndex(npad_id); + const auto controller_type = connected_controllers[controller_idx].type; + if (!connected_controllers[controller_idx].is_connected) { + return; + } + auto& pad_state = npad_pad_states[controller_idx].pad_states; + auto& lstick_entry = npad_pad_states[controller_idx].l_stick; + auto& rstick_entry = npad_pad_states[controller_idx].r_stick; + using namespace Settings::NativeButton; + pad_state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l_stick.Assign(buttons[LStick - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r_stick.Assign(buttons[RStick - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus()); + + pad_state.d_left.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.d_up.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.d_right.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.d_down.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus()); + + pad_state.l_stick_left.Assign(buttons[LStick_Left - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l_stick_up.Assign(buttons[LStick_Up - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l_stick_right.Assign(buttons[LStick_Right - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l_stick_down.Assign(buttons[LStick_Down - BUTTON_HID_BEGIN]->GetStatus()); + + pad_state.r_stick_left.Assign(buttons[RStick_Left - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r_stick_up.Assign(buttons[RStick_Up - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r_stick_right.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r_stick_down.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus()); + + pad_state.sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.sr.Assign(buttons[SR - BUTTON_HID_BEGIN]->GetStatus()); + + const auto [stick_l_x_f, stick_l_y_f] = + sticks[static_cast(JoystickId::Joystick_Left)]->GetStatus(); + const auto [stick_r_x_f, stick_r_y_f] = + sticks[static_cast(JoystickId::Joystick_Right)]->GetStatus(); + lstick_entry.x = static_cast(stick_l_x_f * HID_JOYSTICK_MAX); + lstick_entry.y = static_cast(stick_l_y_f * HID_JOYSTICK_MAX); + rstick_entry.x = static_cast(stick_r_x_f * HID_JOYSTICK_MAX); + rstick_entry.y = static_cast(stick_r_y_f * HID_JOYSTICK_MAX); +} + void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { if (!IsControllerActivated()) return; @@ -199,97 +250,9 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) { continue; } - - // Pad states - ControllerPadState pad_state{}; - using namespace Settings::NativeButton; - pad_state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.l_stick.Assign(buttons[LStick - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.r_stick.Assign(buttons[RStick - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus()); - - pad_state.d_left.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.d_up.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.d_right.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.d_down.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus()); - - pad_state.l_stick_left.Assign(buttons[LStick_Left - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.l_stick_up.Assign(buttons[LStick_Up - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.l_stick_right.Assign(buttons[LStick_Right - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.l_stick_down.Assign(buttons[LStick_Down - BUTTON_HID_BEGIN]->GetStatus()); - - pad_state.r_stick_left.Assign(buttons[RStick_Left - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.r_stick_up.Assign(buttons[RStick_Up - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.r_stick_right.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.r_stick_down.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus()); - - pad_state.sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.sr.Assign(buttons[SR - BUTTON_HID_BEGIN]->GetStatus()); - - AnalogPosition lstick_entry{}; - AnalogPosition rstick_entry{}; - - const auto [stick_l_x_f, stick_l_y_f] = - sticks[static_cast(JoystickId::Joystick_Left)]->GetStatus(); - const auto [stick_r_x_f, stick_r_y_f] = - sticks[static_cast(JoystickId::Joystick_Right)]->GetStatus(); - lstick_entry.x = static_cast(stick_l_x_f * HID_JOYSTICK_MAX); - lstick_entry.y = static_cast(stick_l_y_f * HID_JOYSTICK_MAX); - rstick_entry.x = static_cast(stick_r_x_f * HID_JOYSTICK_MAX); - rstick_entry.y = static_cast(stick_r_y_f * HID_JOYSTICK_MAX); - - if (controller_type == NPadControllerType::JoyLeft || - controller_type == NPadControllerType::JoyRight) { - if (npad.properties.is_horizontal) { - ControllerPadState state{}; - AnalogPosition temp_lstick_entry{}; - AnalogPosition temp_rstick_entry{}; - if (controller_type == NPadControllerType::JoyLeft) { - state.d_down.Assign(pad_state.d_left.Value()); - state.d_left.Assign(pad_state.d_up.Value()); - state.d_right.Assign(pad_state.d_down.Value()); - state.d_up.Assign(pad_state.d_right.Value()); - state.l.Assign(pad_state.l.Value() | pad_state.sl.Value()); - state.r.Assign(pad_state.r.Value() | pad_state.sr.Value()); - - state.zl.Assign(pad_state.zl.Value()); - state.plus.Assign(pad_state.minus.Value()); - - temp_lstick_entry = lstick_entry; - temp_rstick_entry = rstick_entry; - std::swap(temp_lstick_entry.x, temp_lstick_entry.y); - std::swap(temp_rstick_entry.x, temp_rstick_entry.y); - temp_lstick_entry.y *= -1; - } else if (controller_type == NPadControllerType::JoyRight) { - state.x.Assign(pad_state.a.Value()); - state.a.Assign(pad_state.b.Value()); - state.b.Assign(pad_state.y.Value()); - state.y.Assign(pad_state.b.Value()); - - state.l.Assign(pad_state.l.Value() | pad_state.sl.Value()); - state.r.Assign(pad_state.r.Value() | pad_state.sr.Value()); - state.zr.Assign(pad_state.zr.Value()); - state.plus.Assign(pad_state.plus.Value()); - - temp_lstick_entry = lstick_entry; - temp_rstick_entry = rstick_entry; - std::swap(temp_lstick_entry.x, temp_lstick_entry.y); - std::swap(temp_rstick_entry.x, temp_rstick_entry.y); - temp_rstick_entry.x *= -1; - } - pad_state.raw = state.raw; - lstick_entry = temp_lstick_entry; - rstick_entry = temp_rstick_entry; - } - } + const u32 npad_index = static_cast(i); + RequestPadStateUpdate(npad_index); + auto& pad_state = npad_pad_states[npad_index]; auto& main_controller = npad.main_controller_states.npad[npad.main_controller_states.common.last_entry_index]; @@ -304,7 +267,45 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index]; if (hold_type == NpadHoldType::Horizontal) { - // TODO(ogniK): Remap buttons for different orientations + ControllerPadState state{}; + AnalogPosition temp_lstick_entry{}; + AnalogPosition temp_rstick_entry{}; + if (controller_type == NPadControllerType::JoyLeft) { + state.d_down.Assign(pad_state.pad_states.d_left.Value()); + state.d_left.Assign(pad_state.pad_states.d_up.Value()); + state.d_right.Assign(pad_state.pad_states.d_down.Value()); + state.d_up.Assign(pad_state.pad_states.d_right.Value()); + state.l.Assign(pad_state.pad_states.l.Value() | pad_state.pad_states.sl.Value()); + state.r.Assign(pad_state.pad_states.r.Value() | pad_state.pad_states.sr.Value()); + + state.zl.Assign(pad_state.pad_states.zl.Value()); + state.plus.Assign(pad_state.pad_states.minus.Value()); + + temp_lstick_entry = pad_state.l_stick; + temp_rstick_entry = pad_state.r_stick; + std::swap(temp_lstick_entry.x, temp_lstick_entry.y); + std::swap(temp_rstick_entry.x, temp_rstick_entry.y); + temp_lstick_entry.y *= -1; + } else if (controller_type == NPadControllerType::JoyRight) { + state.x.Assign(pad_state.pad_states.a.Value()); + state.a.Assign(pad_state.pad_states.b.Value()); + state.b.Assign(pad_state.pad_states.y.Value()); + state.y.Assign(pad_state.pad_states.b.Value()); + + state.l.Assign(pad_state.pad_states.l.Value() | pad_state.pad_states.sl.Value()); + state.r.Assign(pad_state.pad_states.r.Value() | pad_state.pad_states.sr.Value()); + state.zr.Assign(pad_state.pad_states.zr.Value()); + state.plus.Assign(pad_state.pad_states.plus.Value()); + + temp_lstick_entry = pad_state.l_stick; + temp_rstick_entry = pad_state.r_stick; + std::swap(temp_lstick_entry.x, temp_lstick_entry.y); + std::swap(temp_rstick_entry.x, temp_rstick_entry.y); + temp_rstick_entry.x *= -1; + } + pad_state.pad_states.raw = state.raw; + pad_state.l_stick = temp_lstick_entry; + pad_state.r_stick = temp_rstick_entry; } libnx_entry.connection_status.raw = 0; @@ -316,9 +317,9 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { handheld_entry.connection_status.IsRightJoyConnected.Assign(1); handheld_entry.connection_status.IsLeftJoyWired.Assign(1); handheld_entry.connection_status.IsRightJoyWired.Assign(1); - handheld_entry.pad_states.raw = pad_state.raw; - handheld_entry.l_stick = lstick_entry; - handheld_entry.r_stick = rstick_entry; + handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw; + handheld_entry.pad.l_stick = pad_state.l_stick; + handheld_entry.pad.r_stick = pad_state.r_stick; break; case NPadControllerType::JoyDual: dual_entry.connection_status.raw = 0; @@ -339,17 +340,17 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { left_entry.connection_status.raw = 0; left_entry.connection_status.IsConnected.Assign(1); - left_entry.pad_states.raw = pad_state.raw; - left_entry.l_stick = lstick_entry; - left_entry.r_stick = rstick_entry; + left_entry.pad.pad_states.raw = pad_state.pad_states.raw; + left_entry.pad.l_stick = pad_state.l_stick; + left_entry.pad.r_stick = pad_state.r_stick; break; case NPadControllerType::JoyRight: right_entry.connection_status.raw = 0; right_entry.connection_status.IsConnected.Assign(1); - right_entry.pad_states.raw = pad_state.raw; - right_entry.l_stick = lstick_entry; - right_entry.r_stick = rstick_entry; + right_entry.pad.pad_states.raw = pad_state.pad_states.raw; + right_entry.pad.l_stick = pad_state.l_stick; + right_entry.pad.r_stick = pad_state.r_stick; break; case NPadControllerType::Pokeball: pokeball_entry.connection_status.raw = 0; @@ -357,26 +358,26 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { pokeball_entry.connection_status.IsConnected.Assign(1); pokeball_entry.connection_status.IsWired.Assign(1); - pokeball_entry.pad_states.raw = pad_state.raw; - pokeball_entry.l_stick = lstick_entry; - pokeball_entry.r_stick = rstick_entry; + pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw; + pokeball_entry.pad.l_stick = pad_state.l_stick; + pokeball_entry.pad.r_stick = pad_state.r_stick; break; case NPadControllerType::ProController: main_controller.connection_status.raw = 0; main_controller.connection_status.IsConnected.Assign(1); main_controller.connection_status.IsWired.Assign(1); - main_controller.pad_states.raw = pad_state.raw; - main_controller.l_stick = lstick_entry; - main_controller.r_stick = rstick_entry; + main_controller.pad.pad_states.raw = pad_state.pad_states.raw; + main_controller.pad.l_stick = pad_state.l_stick; + main_controller.pad.r_stick = pad_state.r_stick; break; } // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate // any controllers. - libnx_entry.pad_states.raw = pad_state.raw; - libnx_entry.l_stick = lstick_entry; - libnx_entry.r_stick = rstick_entry; + libnx_entry.pad.pad_states.raw = pad_state.pad_states.raw; + libnx_entry.pad.l_stick = pad_state.l_stick; + libnx_entry.pad.r_stick = pad_state.r_stick; } std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(), shared_memory_entries.size() * sizeof(NPadEntry)); @@ -450,15 +451,7 @@ void Controller_NPad::VibrateController(const std::vector& controller_ids, return; } for (std::size_t i = 0; i < controller_ids.size(); i++) { - std::size_t controller_pos = i; - // Handheld controller conversion - if (controller_pos == NPAD_HANDHELD) { - controller_pos = 8; - } - // Unknown controller conversion - if (controller_pos == NPAD_UNKNOWN) { - controller_pos = 9; - } + std::size_t controller_pos = NPadIdToIndex(static_cast(i)); if (connected_controllers[controller_pos].is_connected) { // TODO(ogniK): Vibrate the physical controller } @@ -477,6 +470,51 @@ Kernel::SharedPtr Controller_NPad::GetStyleSetChangedEvent() cons Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { return last_processed_vibration; } + +std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) { + switch (npad_id) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + return static_cast(npad_id); + case 8: + case 32: + return 8; + case 9: + case 16: + return 9; + default: + UNIMPLEMENTED_MSG("Unknown npad id {}", npad_id); + return 0; + } +} + +u32 Controller_NPad::IndexToNPad(std::size_t index) { + switch (index) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + return static_cast(index); + case 8: + return 32; + case 9: + return 16; + default: + UNIMPLEMENTED_MSG("Unknown npad index {}", index); + return 0; + }; +} + void Controller_NPad::AddNewController(NPadControllerType controller) { if (controller == NPadControllerType::Handheld) { connected_controllers[8] = {controller, true}; @@ -495,6 +533,17 @@ void Controller_NPad::AddNewController(NPadControllerType controller) { InitNewlyAddedControler(controller_id); } +void Controller_NPad::AddNewControllerAt(NPadControllerType controller, u32 npad_id) { + if (controller == NPadControllerType::Handheld) { + connected_controllers[8] = {controller, true}; + InitNewlyAddedControler(8); + return; + } + const size_t controller_id = static_cast(npad_id); + connected_controllers[controller_id] = {controller, true}; + InitNewlyAddedControler(controller_id); +} + void Controller_NPad::ConnectNPad(u32 npad_id) { connected_controllers[NPadIdToIndex(npad_id)].is_connected = true; } diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index ac86985ff..1192cfcd9 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -107,6 +107,7 @@ public: Vibration GetLastVibration() const; void AddNewController(NPadControllerType controller); + void AddNewControllerAt(NPadControllerType controller, u32 npad_id); void ConnectNPad(u32 npad_id); void DisconnectNPad(u32 npad_id); @@ -189,12 +190,17 @@ private: }; static_assert(sizeof(ConnectionState) == 4, "ConnectionState is an invalid size"); - struct GenericStates { - s64_le timestamp; - s64_le timestamp2; + struct ControllerPad { ControllerPadState pad_states; AnalogPosition l_stick; AnalogPosition r_stick; + }; + static_assert(sizeof(ControllerPad) == 0x18, "ControllerPad is an invalid size"); + + struct GenericStates { + s64_le timestamp; + s64_le timestamp2; + ControllerPad pad; ConnectionState connection_status; }; static_assert(sizeof(GenericStates) == 0x30, "NPadGenericStates is an invalid size"); @@ -285,5 +291,9 @@ private: void InitNewlyAddedControler(std::size_t controller_idx); bool IsControllerSupported(NPadControllerType controller) const; NPadControllerType DecideBestController(NPadControllerType priority) const; + void RequestPadStateUpdate(u32 npad_id); + std::size_t NPadIdToIndex(u32 npad_id); + u32 IndexToNPad(std::size_t index); + std::array npad_pad_states{}; }; } // namespace Service::HID From b9c1e4b0e75f13cde0508bc3d0bd252add03ae85 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Thu, 18 Oct 2018 15:09:55 +1100 Subject: [PATCH 02/26] Added automatic npad switch based on supported stylesets --- src/core/hle/service/hid/controllers/npad.cpp | 124 +++++++++++++++++- src/core/hle/service/hid/controllers/npad.h | 4 +- 2 files changed, 124 insertions(+), 4 deletions(-) diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 5b0ca57f8..a9060fa2c 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -89,12 +89,12 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { case NPadControllerType::JoyLeft: controller.joy_styles.joycon_left.Assign(1); controller.device_type.joycon_left.Assign(1); - controller.pad_assignment = NPadAssignments::Dual; + controller.pad_assignment = NPadAssignments::Single; break; case NPadControllerType::JoyRight: controller.joy_styles.joycon_right.Assign(1); controller.device_type.joycon_right.Assign(1); - controller.pad_assignment = NPadAssignments::Dual; + controller.pad_assignment = NPadAssignments::Single; break; case NPadControllerType::Pokeball: controller.joy_styles.pokeball.Assign(1); @@ -381,7 +381,7 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { } std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(), shared_memory_entries.size() * sizeof(NPadEntry)); -} // namespace Service::HID +} void Controller_NPad::SetSupportedStyleSet(NPadType style_set) { style.raw = style_set.raw; @@ -516,6 +516,7 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) { } void Controller_NPad::AddNewController(NPadControllerType controller) { + controller = DecideBestController(controller); if (controller == NPadControllerType::Handheld) { connected_controllers[8] = {controller, true}; InitNewlyAddedControler(8); @@ -534,6 +535,7 @@ void Controller_NPad::AddNewController(NPadControllerType controller) { } void Controller_NPad::AddNewControllerAt(NPadControllerType controller, u32 npad_id) { + controller = DecideBestController(controller); if (controller == NPadControllerType::Handheld) { connected_controllers[8] = {controller, true}; InitNewlyAddedControler(8); @@ -552,6 +554,122 @@ void Controller_NPad::DisconnectNPad(u32 npad_id) { connected_controllers[NPadIdToIndex(npad_id)].is_connected = false; } +Controller_NPad::NPadControllerType Controller_NPad::DecideBestController( + NPadControllerType priority) { + if (IsControllerSupported(priority)) { + return priority; + } + const auto is_docked = Settings::values->use_docked_mode; + if (is_docked && priority == NPadControllerType::Handheld) { + priority = NPadControllerType::JoyDual; + if (IsControllerSupported(priority)) { + return priority; + } + } + std::vector priority_list{}; + switch (priority) { + case NPadControllerType::ProController: + priority_list.push_back(NPadControllerType::JoyDual); + if (!is_docked) { + priority_list.push_back(NPadControllerType::Handheld); + } + priority_list.push_back(NPadControllerType::JoyLeft); + priority_list.push_back(NPadControllerType::JoyRight); + priority_list.push_back(NPadControllerType::Pokeball); + break; + case NPadControllerType::Handheld: + priority_list.push_back(NPadControllerType::JoyDual); + priority_list.push_back(NPadControllerType::ProController); + priority_list.push_back(NPadControllerType::JoyLeft); + priority_list.push_back(NPadControllerType::JoyRight); + priority_list.push_back(NPadControllerType::Pokeball); + break; + case NPadControllerType::JoyDual: + if (!is_docked) { + priority_list.push_back(NPadControllerType::Handheld); + } + priority_list.push_back(NPadControllerType::ProController); + priority_list.push_back(NPadControllerType::JoyLeft); + priority_list.push_back(NPadControllerType::JoyRight); + priority_list.push_back(NPadControllerType::Pokeball); + break; + case NPadControllerType::JoyLeft: + priority_list.push_back(NPadControllerType::JoyRight); + priority_list.push_back(NPadControllerType::JoyDual); + if (!is_docked) { + priority_list.push_back(NPadControllerType::Handheld); + } + priority_list.push_back(NPadControllerType::ProController); + priority_list.push_back(NPadControllerType::Pokeball); + break; + case NPadControllerType::JoyRight: + priority_list.push_back(NPadControllerType::JoyLeft); + priority_list.push_back(NPadControllerType::JoyDual); + if (!is_docked) { + priority_list.push_back(NPadControllerType::Handheld); + } + priority_list.push_back(NPadControllerType::ProController); + priority_list.push_back(NPadControllerType::Pokeball); + break; + case NPadControllerType::Pokeball: + priority_list.push_back(NPadControllerType::JoyLeft); + priority_list.push_back(NPadControllerType::JoyRight); + priority_list.push_back(NPadControllerType::JoyDual); + if (!is_docked) { + priority_list.push_back(NPadControllerType::Handheld); + } + priority_list.push_back(NPadControllerType::ProController); + break; + default: + priority_list.push_back(NPadControllerType::JoyDual); + if (!is_docked) { + priority_list.push_back(NPadControllerType::Handheld); + } + priority_list.push_back(NPadControllerType::ProController); + priority_list.push_back(NPadControllerType::JoyLeft); + priority_list.push_back(NPadControllerType::JoyRight); + priority_list.push_back(NPadControllerType::JoyDual); + } + + for (const auto controller_type : priority_list) { + if (IsControllerSupported(controller_type)) { + return controller_type; + } + } + UNIMPLEMENTED_MSG("Could not find supported controller!"); + return priority; +} + +bool Controller_NPad::IsControllerSupported(NPadControllerType controller) { + if (controller == NPadControllerType::Handheld) { + // Handheld is not even a supported type, lets stop here + if (std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), 32) == + supported_npad_id_types.end()) { + return false; + } + // Handheld should not be supported in docked mode + if (Settings::values->use_docked_mode) { + return false; + } + } + switch (controller) { + case NPadControllerType::ProController: + return style.pro_controller; + case NPadControllerType::Handheld: + return style.handheld; + case NPadControllerType::JoyDual: + return style.joycon_dual; + case NPadControllerType::JoyLeft: + return style.joycon_left; + case NPadControllerType::JoyRight: + return style.joycon_right; + case NPadControllerType::Pokeball: + return style.pokeball; + default: + return false; + } +} + Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) { // These are controllers without led patterns diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 1192cfcd9..ea12646f8 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -272,7 +272,7 @@ private: static_assert(sizeof(NPadEntry) == 0x5000, "NPadEntry is an invalid size"); struct ControllerHolder { - Controller_NPad::NPadControllerType type; + NPadControllerType type; bool is_connected; }; @@ -295,5 +295,7 @@ private: std::size_t NPadIdToIndex(u32 npad_id); u32 IndexToNPad(std::size_t index); std::array npad_pad_states{}; + NPadControllerType DecideBestController(NPadControllerType priority); + bool IsControllerSupported(NPadControllerType controller); }; } // namespace Service::HID From 7fbe2c83a7e3de06624f0ab2f14f760fbccc89e3 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Thu, 18 Oct 2018 19:00:16 +1100 Subject: [PATCH 03/26] Left joycon rotation button remapping --- src/core/hle/service/hid/controllers/npad.cpp | 21 ++++++++++++++----- src/core/hle/service/hid/controllers/npad.h | 7 +++++-- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index a9060fa2c..fd677d281 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -79,21 +79,31 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { controller.joy_styles.handheld.Assign(1); controller.device_type.handheld.Assign(1); controller.pad_assignment = NPadAssignments::Dual; + controller.properties.is_vertical.Assign(1); + controller.properties.use_plus.Assign(1); + controller.properties.use_minus.Assign(1); break; case NPadControllerType::JoyDual: controller.joy_styles.joycon_dual.Assign(1); controller.device_type.joycon_left.Assign(1); controller.device_type.joycon_right.Assign(1); + controller.properties.is_vertical.Assign(1); + controller.properties.use_plus.Assign(1); + controller.properties.use_minus.Assign(1); controller.pad_assignment = NPadAssignments::Dual; break; case NPadControllerType::JoyLeft: controller.joy_styles.joycon_left.Assign(1); controller.device_type.joycon_left.Assign(1); + controller.properties.is_horizontal.Assign(1); + controller.properties.use_minus.Assign(1); controller.pad_assignment = NPadAssignments::Single; break; case NPadControllerType::JoyRight: controller.joy_styles.joycon_right.Assign(1); controller.device_type.joycon_right.Assign(1); + controller.properties.is_horizontal.Assign(1); + controller.properties.use_plus.Assign(1); controller.pad_assignment = NPadAssignments::Single; break; case NPadControllerType::Pokeball: @@ -104,6 +114,9 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { case NPadControllerType::ProController: controller.joy_styles.pro_controller.Assign(1); controller.device_type.pro_controller.Assign(1); + controller.properties.is_vertical.Assign(1); + controller.properties.use_plus.Assign(1); + controller.properties.use_minus.Assign(1); controller.pad_assignment = NPadAssignments::Single; break; } @@ -118,9 +131,6 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { controller.right_color.body_color = JOYCON_BODY_NEON_RED; controller.right_color.button_color = JOYCON_BUTTONS_NEON_RED; - controller.properties.is_vertical.Assign(1); // TODO(ogniK): Swap joycons orientations - controller.properties.use_plus.Assign(1); - controller.properties.use_minus.Assign(1); controller.battery_level[0] = BATTERY_FULL; controller.battery_level[1] = BATTERY_FULL; controller.battery_level[2] = BATTERY_FULL; @@ -202,8 +212,8 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { pad_state.r_stick_right.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus()); pad_state.r_stick_down.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.sr.Assign(buttons[SR - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.left_sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.left_sr.Assign(buttons[SR - BUTTON_HID_BEGIN]->GetStatus()); const auto [stick_l_x_f, stick_l_y_f] = sticks[static_cast(JoystickId::Joystick_Left)]->GetStatus(); @@ -307,6 +317,7 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { pad_state.l_stick = temp_lstick_entry; pad_state.r_stick = temp_rstick_entry; } + libnx_entry.connection_status.raw = 0; switch (controller_type) { diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index ea12646f8..f702990c7 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -165,8 +165,11 @@ private: BitField<23, 1, u64_le> r_stick_down; // Not always active? - BitField<24, 1, u64_le> sl; - BitField<25, 1, u64_le> sr; + BitField<24, 1, u64_le> left_sl; + BitField<25, 1, u64_le> left_sr; + + BitField<26, 1, u64_le> right_sl; + BitField<27, 1, u64_le> right_sr; }; }; static_assert(sizeof(ControllerPadState) == 8, "ControllerPadState is an invalid size"); From a69b9d73f501395a0522f9e8227402c251281bbe Mon Sep 17 00:00:00 2001 From: David Marcec Date: Thu, 18 Oct 2018 21:04:45 +1100 Subject: [PATCH 04/26] Changed polling rate of hid and Right joycon rotation --- src/core/hle/service/hid/hid.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 39631b14f..7c0dac5dc 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -34,8 +34,8 @@ namespace Service::HID { // Updating period for each HID device. -// TODO(shinyquagsire23): These need better values. -constexpr u64 pad_update_ticks = CoreTiming::BASE_CLOCK_RATE / 100; +// TODO(ogniK): Find actual polling rate of hid +constexpr u64 pad_update_ticks = CoreTiming::BASE_CLOCK_RATE / 66; constexpr u64 accelerometer_update_ticks = CoreTiming::BASE_CLOCK_RATE / 100; constexpr u64 gyroscope_update_ticks = CoreTiming::BASE_CLOCK_RATE / 100; constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; From 362b28d0529eeb815f428594200c611d525a0d6f Mon Sep 17 00:00:00 2001 From: David Marcec Date: Thu, 18 Oct 2018 21:45:10 +1100 Subject: [PATCH 05/26] Added controller helper funcs --- src/core/hle/service/hid/controllers/npad.cpp | 31 +++++++++++++++++++ src/core/hle/service/hid/controllers/npad.h | 4 +++ 2 files changed, 35 insertions(+) diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index fd677d281..3eb59599f 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -712,6 +712,37 @@ void Controller_NPad::SetVibrationEnabled(bool can_vibrate) { can_controllers_vibrate = can_vibrate; } +void Controller_NPad::ClearAllConnectedControllers() { + std::for_each(connected_controllers.begin(), connected_controllers.end(), + [](ControllerHolder& controller) { + if (controller.is_connected && controller.type != NPadControllerType::None) { + controller.type = NPadControllerType::None; + controller.is_connected = false; + } + }); +} +void Controller_NPad::DisconnectAllConnectedControllers() { + std::for_each(connected_controllers.begin(), connected_controllers.end(), + [](ControllerHolder& controller) { controller.is_connected = false; }); +} + +void Controller_NPad::ConnectAllDisconnectedControllers() { + std::for_each(connected_controllers.begin(), connected_controllers.end(), + [](ControllerHolder& controller) { + if (controller.type != NPadControllerType::None && !controller.is_connected) { + controller.is_connected = false; + } + }); +} + +void Controller_NPad::ClearAllControllers() { + std::for_each(connected_controllers.begin(), connected_controllers.end(), + [](ControllerHolder& controller) { + controller.type = NPadControllerType::None; + controller.is_connected = false; + }); +} + bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const { const bool support_handheld = std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), NPAD_HANDHELD) != diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index f702990c7..7222bca72 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -113,6 +113,10 @@ public: void DisconnectNPad(u32 npad_id); LedPattern GetLedPattern(u32 npad_id); void SetVibrationEnabled(bool can_vibrate); + void ClearAllConnectedControllers(); + void DisconnectAllConnectedControllers(); + void ConnectAllDisconnectedControllers(); + void ClearAllControllers(); private: struct CommonHeader { From f66c6fe55424c229728c5dc2e36efe51386a0dd0 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Thu, 18 Oct 2018 22:01:55 +1100 Subject: [PATCH 06/26] Added debugpad skeleton --- .../hle/service/hid/controllers/debug_pad.cpp | 23 +++++++++++++ .../hle/service/hid/controllers/debug_pad.h | 34 +++++++++++++++++-- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp index 3d100763f..ac9b23bb8 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.cpp +++ b/src/core/hle/service/hid/controllers/debug_pad.cpp @@ -34,6 +34,29 @@ void Controller_DebugPad::OnUpdate(u8* data, std::size_t size) { cur_entry.sampling_number = last_entry.sampling_number + 1; cur_entry.sampling_number2 = cur_entry.sampling_number; // TODO(ogniK): Update debug pad states + cur_entry.attribute.connected.Assign(1); + auto& pad = cur_entry.pad_state; + + pad.a.Assign(0); + pad.b.Assign(0); + pad.x.Assign(0); + pad.y.Assign(0); + pad.l.Assign(0); + pad.r.Assign(0); + pad.zl.Assign(0); + pad.zr.Assign(0); + pad.plus.Assign(0); + pad.minus.Assign(0); + pad.d_left.Assign(0); + pad.d_up.Assign(0); + pad.d_right.Assign(0); + pad.d_down.Assign(0); + + cur_entry.l_stick.x = 0; + cur_entry.l_stick.y = 0; + + cur_entry.r_stick.x = 0; + cur_entry.r_stick.y = 0; std::memcpy(data, &shared_memory, sizeof(SharedMemory)); } diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h index 62b4f2682..a41564b4d 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.h +++ b/src/core/hle/service/hid/controllers/debug_pad.h @@ -5,6 +5,7 @@ #pragma once #include +#include "common/bit_field.h" #include "common/common_funcs.h" #include "common/common_types.h" #include "common/swap.h" @@ -35,11 +36,40 @@ private: }; static_assert(sizeof(AnalogStick) == 0x8); + struct PadState { + union { + u32_le raw{}; + BitField<0, 1, u32_le> a; + BitField<1, 1, u32_le> b; + BitField<2, 1, u32_le> x; + BitField<3, 1, u32_le> y; + BitField<4, 1, u32_le> l; + BitField<5, 1, u32_le> r; + BitField<6, 1, u32_le> zl; + BitField<7, 1, u32_le> zr; + BitField<8, 1, u32_le> plus; + BitField<9, 1, u32_le> minus; + BitField<10, 1, u32_le> d_left; + BitField<11, 1, u32_le> d_up; + BitField<12, 1, u32_le> d_right; + BitField<13, 1, u32_le> d_down; + }; + }; + static_assert(sizeof(PadState) == 0x4, "PadState is an invalid size"); + + struct Attributes { + union { + u32_le raw{}; + BitField<0, 1, u32_le> connected; + }; + }; + static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size"); + struct PadStates { s64_le sampling_number; s64_le sampling_number2; - u32_le attribute; - u32_le button_state; + Attributes attribute; + PadState pad_state; AnalogStick r_stick; AnalogStick l_stick; }; From 0c3e7b708684fb17cb29c491fca46125d7d716b9 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Thu, 18 Oct 2018 22:34:30 +1100 Subject: [PATCH 07/26] Added missing start/end touch attributes to touchscreen --- src/core/hle/service/hid/controllers/touchscreen.cpp | 7 +++++++ src/core/hle/service/hid/controllers/touchscreen.h | 12 +++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index 43efef803..07244fe4e 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp @@ -41,7 +41,11 @@ void Controller_Touchscreen::OnUpdate(u8* data, std::size_t size) { const auto [x, y, pressed] = touch_device->GetStatus(); auto& touch_entry = cur_entry.states[0]; + touch_entry.attribute.raw = 0; if (pressed) { + if (cur_entry.entry_count == 0) { + touch_entry.attribute.start_touch.Assign(1); + } touch_entry.x = static_cast(x * Layout::ScreenUndocked::Width); touch_entry.y = static_cast(y * Layout::ScreenUndocked::Height); touch_entry.diameter_x = 15; @@ -53,6 +57,9 @@ void Controller_Touchscreen::OnUpdate(u8* data, std::size_t size) { touch_entry.finger = 0; cur_entry.entry_count = 1; } else { + if (cur_entry.entry_count == 1) { + touch_entry.attribute.end_touch.Assign(1); + } cur_entry.entry_count = 0; } diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index e5db6e6ba..94cd0eba9 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h @@ -4,6 +4,7 @@ #pragma once +#include "common/bit_field.h" #include "common/common_funcs.h" #include "common/common_types.h" #include "common/swap.h" @@ -29,9 +30,18 @@ public: void OnLoadInputDevices() override; private: + struct Attributes { + union { + u32 raw{}; + BitField<0, 1, u32_le> start_touch; + BitField<1, 1, u32_le> end_touch; + }; + }; + static_assert(sizeof(Attributes) == 0x4, "Attributes is an invalid size"); + struct TouchState { u64_le delta_time; - u32_le attribute; + Attributes attribute; u32_le finger; u32_le x; u32_le y; From 152422bab1382575e951c1c11b5de3013b8b402a Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 1 Nov 2018 21:52:51 -0400 Subject: [PATCH 08/26] settings: Add Native type for mouse buttons --- src/core/frontend/input.h | 7 +++++++ src/core/settings.h | 27 +++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/core/frontend/input.h b/src/core/frontend/input.h index 39bdf4e21..16fdcd376 100644 --- a/src/core/frontend/input.h +++ b/src/core/frontend/input.h @@ -132,4 +132,11 @@ using MotionDevice = InputDevice, Math::Vec3 */ using TouchDevice = InputDevice>; +/** + * A mouse device is an input device that returns a tuple of two floats and four ints. + * The first two floats are X and Y device coordinates of the mouse (from 0-1). + * The s32s are the mouse wheel. + */ +using MouseDevice = InputDevice>; + } // namespace Input diff --git a/src/core/settings.h b/src/core/settings.h index e424479f2..d9aa14cd2 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -111,6 +111,30 @@ static const std::array mapping = {{ }}; } // namespace NativeAnalog +namespace NativeMouseButton { +enum Values { + Left, + Right, + Middle, + Forward, + Back, + + NumMouseButtons, +}; + +constexpr int MOUSE_HID_BEGIN = Left; +constexpr int MOUSE_HID_END = NumMouseButtons; +constexpr int NUM_MOUSE_HID = NumMouseButtons; + +static const std::array mapping = {{ + "left", + "right", + "middle", + "forward", + "back", +}}; +} // namespace NativeMouseButton + struct Values { // System bool use_docked_mode; @@ -122,6 +146,9 @@ struct Values { // Controls std::array buttons; std::array analogs; + bool mouse_enabled; + std::string mouse_device; + MouseButtonsRaw mouse_buttons; std::string motion_device; std::string touch_device; std::atomic_bool is_device_reload_pending{true}; From fd5fa48674d85be2c7d8c2d9ab84b410bb47341b Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 1 Nov 2018 21:53:31 -0400 Subject: [PATCH 09/26] settings: Add Native type for keyboard --- src/core/settings.h | 210 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) diff --git a/src/core/settings.h b/src/core/settings.h index d9aa14cd2..54a4859b9 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -135,6 +135,212 @@ static const std::array mapping = {{ }}; } // namespace NativeMouseButton +namespace NativeKeyboard { +enum Keys { + None, + Error, + + A = 4, + B, + C, + D, + E, + F, + G, + H, + I, + J, + K, + L, + M, + N, + O, + P, + Q, + R, + S, + T, + U, + V, + W, + X, + Y, + Z, + N1, + N2, + N3, + N4, + N5, + N6, + N7, + N8, + N9, + N0, + Enter, + Escape, + Backspace, + Tab, + Space, + Minus, + Equal, + LeftBrace, + RightBrace, + Backslash, + Tilde, + Semicolon, + Apostrophe, + Grave, + Comma, + Dot, + Slash, + CapsLockKey, + + F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + + SystemRequest, + ScrollLockKey, + Pause, + Insert, + Home, + PageUp, + Delete, + End, + PageDown, + Right, + Left, + Down, + Up, + + NumLockKey, + KPSlash, + KPAsterisk, + KPMinus, + KPPlus, + KPEnter, + KP1, + KP2, + KP3, + KP4, + KP5, + KP6, + KP7, + KP8, + KP9, + KP0, + KPDot, + + Key102, + Compose, + Power, + KPEqual, + + F13, + F14, + F15, + F16, + F17, + F18, + F19, + F20, + F21, + F22, + F23, + F24, + + Open, + Help, + Properties, + Front, + Stop, + Repeat, + Undo, + Cut, + Copy, + Paste, + Find, + Mute, + VolumeUp, + VolumeDown, + CapsLockActive, + NumLockActive, + ScrollLockActive, + KPComma, + + KPLeftParenthesis, + KPRightParenthesis, + + LeftControlKey = 0xE0, + LeftShiftKey, + LeftAltKey, + LeftMetaKey, + RightControlKey, + RightShiftKey, + RightAltKey, + RightMetaKey, + + MediaPlayPause, + MediaStopCD, + MediaPrevious, + MediaNext, + MediaEject, + MediaVolumeUp, + MediaVolumeDown, + MediaMute, + MediaWebsite, + MediaBack, + MediaForward, + MediaStop, + MediaFind, + MediaScrollUp, + MediaScrollDown, + MediaEdit, + MediaSleep, + MediaCoffee, + MediaRefresh, + MediaCalculator, + + NumKeyboardKeys, +}; + +static_assert(NumKeyboardKeys == 0xFC, "Incorrect number of keyboard keys."); + +enum Modifiers { + LeftControl, + LeftShift, + LeftAlt, + LeftMeta, + RightControl, + RightShift, + RightAlt, + RightMeta, + CapsLock, + ScrollLock, + NumLock, + + NumKeyboardMods, +}; + +constexpr int KEYBOARD_KEYS_HID_BEGIN = None; +constexpr int KEYBOARD_KEYS_HID_END = NumKeyboardKeys; +constexpr int NUM_KEYBOARD_KEYS_HID = NumKeyboardKeys; + +constexpr int KEYBOARD_MODS_HID_BEGIN = LeftControl; +constexpr int KEYBOARD_MODS_HID_END = NumKeyboardMods; +constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods; + +} // namespace NativeKeyboard + struct Values { // System bool use_docked_mode; @@ -149,6 +355,10 @@ struct Values { bool mouse_enabled; std::string mouse_device; MouseButtonsRaw mouse_buttons; + + bool keyboard_enabled; + KeyboardKeysRaw keyboard_keys; + KeyboardModsRaw keyboard_mods; std::string motion_device; std::string touch_device; std::atomic_bool is_device_reload_pending{true}; From c77454b9d009e3e45b1b140743338f3063fc1656 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 1 Nov 2018 21:54:16 -0400 Subject: [PATCH 10/26] settings: Add settings for multiple players and controllers Uses the PlayerInput struct to represent all of the data that constitutes a player. --- src/core/settings.h | 51 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/src/core/settings.h b/src/core/settings.h index 54a4859b9..9cc3c1dc8 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -341,6 +341,46 @@ constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods; } // namespace NativeKeyboard +using ButtonsRaw = std::array; +using AnalogsRaw = std::array; +using MouseButtonsRaw = std::array; +using KeyboardKeysRaw = std::array; +using KeyboardModsRaw = std::array; + +constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28; +constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A; +constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6; +constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E; + +enum class ControllerType { + ProController, + DualJoycon, + RightJoycon, + LeftJoycon, +}; + +struct PlayerInput { + bool connected; + ControllerType type; + ButtonsRaw buttons; + AnalogsRaw analogs; + + u32 body_color_right; + u32 button_color_right; + u32 body_color_left; + u32 button_color_left; +}; + +struct TouchscreenInput { + bool enabled; + std::string device; + + u32 finger; + u32 diameter_x; + u32 diameter_y; + u32 rotation_angle; +}; + struct Values { // System bool use_docked_mode; @@ -350,8 +390,8 @@ struct Values { s32 language_index; // Controls - std::array buttons; - std::array analogs; + std::array players; + bool mouse_enabled; std::string mouse_device; MouseButtonsRaw mouse_buttons; @@ -359,8 +399,13 @@ struct Values { bool keyboard_enabled; KeyboardKeysRaw keyboard_keys; KeyboardModsRaw keyboard_mods; + + bool debug_pad_enabled; + ButtonsRaw debug_pad_buttons; + AnalogsRaw debug_pad_analogs; + std::string motion_device; - std::string touch_device; + TouchscreenInput touchscreen; std::atomic_bool is_device_reload_pending{true}; // Core From b8f7f9651e1887c8ebeb23021d3b1466b25f6644 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 1 Nov 2018 21:55:35 -0400 Subject: [PATCH 11/26] yuzu_cmd/config: Add config deserialization for multiplayer --- src/yuzu_cmd/config.cpp | 291 +++++++++++++++++++++++++++++++++++----- 1 file changed, 254 insertions(+), 37 deletions(-) diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 96f1ef636..0d5df8fd0 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp @@ -65,30 +65,272 @@ static const std::array, Settings::NativeAnalog::NumAnalogs> }, }}; +static const std::array default_mouse_buttons = { + SDL_SCANCODE_LEFTBRACKET, SDL_SCANCODE_RIGHTBRACKET, SDL_SCANCODE_APOSTROPHE, + SDL_SCANCODE_MINUS, SDL_SCANCODE_EQUALS, +}; + +static const std::array keyboard_keys = { + 0, + 0, + 0, + 0, + SDL_SCANCODE_A, + SDL_SCANCODE_B, + SDL_SCANCODE_C, + SDL_SCANCODE_D, + SDL_SCANCODE_E, + SDL_SCANCODE_F, + SDL_SCANCODE_G, + SDL_SCANCODE_H, + SDL_SCANCODE_I, + SDL_SCANCODE_J, + SDL_SCANCODE_K, + SDL_SCANCODE_L, + SDL_SCANCODE_M, + SDL_SCANCODE_N, + SDL_SCANCODE_O, + SDL_SCANCODE_P, + SDL_SCANCODE_Q, + SDL_SCANCODE_R, + SDL_SCANCODE_S, + SDL_SCANCODE_T, + SDL_SCANCODE_U, + SDL_SCANCODE_V, + SDL_SCANCODE_W, + SDL_SCANCODE_X, + SDL_SCANCODE_Y, + SDL_SCANCODE_Z, + SDL_SCANCODE_1, + SDL_SCANCODE_2, + SDL_SCANCODE_3, + SDL_SCANCODE_4, + SDL_SCANCODE_5, + SDL_SCANCODE_6, + SDL_SCANCODE_7, + SDL_SCANCODE_8, + SDL_SCANCODE_9, + SDL_SCANCODE_0, + SDL_SCANCODE_RETURN, + SDL_SCANCODE_ESCAPE, + SDL_SCANCODE_BACKSPACE, + SDL_SCANCODE_TAB, + SDL_SCANCODE_SPACE, + SDL_SCANCODE_MINUS, + SDL_SCANCODE_EQUALS, + SDL_SCANCODE_LEFTBRACKET, + SDL_SCANCODE_RIGHTBRACKET, + SDL_SCANCODE_BACKSLASH, + 0, + SDL_SCANCODE_SEMICOLON, + SDL_SCANCODE_APOSTROPHE, + SDL_SCANCODE_GRAVE, + SDL_SCANCODE_COMMA, + SDL_SCANCODE_PERIOD, + SDL_SCANCODE_SLASH, + SDL_SCANCODE_CAPSLOCK, + + SDL_SCANCODE_F1, + SDL_SCANCODE_F2, + SDL_SCANCODE_F3, + SDL_SCANCODE_F4, + SDL_SCANCODE_F5, + SDL_SCANCODE_F6, + SDL_SCANCODE_F7, + SDL_SCANCODE_F8, + SDL_SCANCODE_F9, + SDL_SCANCODE_F10, + SDL_SCANCODE_F11, + SDL_SCANCODE_F12, + + 0, + SDL_SCANCODE_SCROLLLOCK, + SDL_SCANCODE_PAUSE, + SDL_SCANCODE_INSERT, + SDL_SCANCODE_HOME, + SDL_SCANCODE_PAGEUP, + SDL_SCANCODE_DELETE, + SDL_SCANCODE_END, + SDL_SCANCODE_PAGEDOWN, + SDL_SCANCODE_RIGHT, + SDL_SCANCODE_LEFT, + SDL_SCANCODE_DOWN, + SDL_SCANCODE_UP, + + SDL_SCANCODE_NUMLOCKCLEAR, + SDL_SCANCODE_KP_DIVIDE, + SDL_SCANCODE_KP_MULTIPLY, + SDL_SCANCODE_KP_MINUS, + SDL_SCANCODE_KP_PLUS, + SDL_SCANCODE_KP_ENTER, + SDL_SCANCODE_KP_1, + SDL_SCANCODE_KP_2, + SDL_SCANCODE_KP_3, + SDL_SCANCODE_KP_4, + SDL_SCANCODE_KP_5, + SDL_SCANCODE_KP_6, + SDL_SCANCODE_KP_7, + SDL_SCANCODE_KP_8, + SDL_SCANCODE_KP_9, + SDL_SCANCODE_KP_0, + SDL_SCANCODE_KP_PERIOD, + + 0, + 0, + SDL_SCANCODE_POWER, + SDL_SCANCODE_KP_EQUALS, + + SDL_SCANCODE_F13, + SDL_SCANCODE_F14, + SDL_SCANCODE_F15, + SDL_SCANCODE_F16, + SDL_SCANCODE_F17, + SDL_SCANCODE_F18, + SDL_SCANCODE_F19, + SDL_SCANCODE_F20, + SDL_SCANCODE_F21, + SDL_SCANCODE_F22, + SDL_SCANCODE_F23, + SDL_SCANCODE_F24, + + 0, + SDL_SCANCODE_HELP, + SDL_SCANCODE_MENU, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + SDL_SCANCODE_KP_COMMA, + SDL_SCANCODE_KP_LEFTPAREN, + SDL_SCANCODE_KP_RIGHTPAREN, + 0, + 0, + 0, + 0, +}; + +static const std::array keyboard_mods{ + SDL_SCANCODE_LCTRL, SDL_SCANCODE_LSHIFT, SDL_SCANCODE_LALT, SDL_SCANCODE_LGUI, + SDL_SCANCODE_RCTRL, SDL_SCANCODE_RSHIFT, SDL_SCANCODE_RALT, SDL_SCANCODE_RGUI, +}; + void Config::ReadValues() { // Controls + for (std::size_t p = 0; p < Settings::values.players.size(); ++p) { + const auto group = fmt::format("ControlsP{}", p); + for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { + std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); + Settings::values.players[p].buttons[i] = + sdl2_config->Get(group, Settings::NativeButton::mapping[i], default_param); + if (Settings::values.players[p].buttons[i].empty()) + Settings::values.players[p].buttons[i] = default_param; + } + + for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { + std::string default_param = InputCommon::GenerateAnalogParamFromKeys( + default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], + default_analogs[i][3], default_analogs[i][4], 0.5f); + Settings::values.players[p].analogs[i] = + sdl2_config->Get(group, Settings::NativeAnalog::mapping[i], default_param); + if (Settings::values.players[p].analogs[i].empty()) + Settings::values.players[p].analogs[i] = default_param; + } + } + + Settings::values.mouse_enabled = + sdl2_config->GetBoolean("ControlsGeneral", "mouse_enabled", false); + for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { + std::string default_param = InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]); + Settings::values.mouse_buttons[i] = sdl2_config->Get( + "ControlsGeneral", std::string("mouse_") + Settings::NativeMouseButton::mapping[i], + default_param); + if (Settings::values.mouse_buttons[i].empty()) + Settings::values.mouse_buttons[i] = default_param; + } + + Settings::values.motion_device = sdl2_config->Get( + "ControlsGeneral", "motion_device", "engine:motion_emu,update_period:100,sensitivity:0.01"); + + Settings::values.keyboard_enabled = + sdl2_config->GetBoolean("ControlsGeneral", "keyboard_enabled", false); + + Settings::values.debug_pad_enabled = + sdl2_config->GetBoolean("ControlsGeneral", "debug_pad_enabled", false); for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); - Settings::values.buttons[i] = - sdl2_config->Get("Controls", Settings::NativeButton::mapping[i], default_param); - if (Settings::values.buttons[i].empty()) - Settings::values.buttons[i] = default_param; + Settings::values.debug_pad_buttons[i] = sdl2_config->Get( + "ControlsGeneral", std::string("debug_pad_") + Settings::NativeButton::mapping[i], + default_param); + if (Settings::values.debug_pad_buttons[i].empty()) + Settings::values.debug_pad_buttons[i] = default_param; } for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { std::string default_param = InputCommon::GenerateAnalogParamFromKeys( default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], default_analogs[i][3], default_analogs[i][4], 0.5f); - Settings::values.analogs[i] = - sdl2_config->Get("Controls", Settings::NativeAnalog::mapping[i], default_param); - if (Settings::values.analogs[i].empty()) - Settings::values.analogs[i] = default_param; + Settings::values.debug_pad_analogs[i] = sdl2_config->Get( + "ControlsGeneral", std::string("debug_pad_") + Settings::NativeAnalog::mapping[i], + default_param); + if (Settings::values.debug_pad_analogs[i].empty()) + Settings::values.debug_pad_analogs[i] = default_param; } - Settings::values.motion_device = sdl2_config->Get( - "Controls", "motion_device", "engine:motion_emu,update_period:100,sensitivity:0.01"); - Settings::values.touch_device = - sdl2_config->Get("Controls", "touch_device", "engine:emu_window"); + Settings::values.touchscreen.enabled = + sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true); + Settings::values.touchscreen.device = + sdl2_config->Get("ControlsGeneral", "touch_device", "engine:emu_window"); + Settings::values.touchscreen.finger = + sdl2_config->GetInteger("ControlsGeneral", "touch_finger", 0); + Settings::values.touchscreen.rotation_angle = + sdl2_config->GetInteger("ControlsGeneral", "touch_angle", 0); + Settings::values.touchscreen.diameter_x = + sdl2_config->GetInteger("ControlsGeneral", "touch_diameter_x", 15); + Settings::values.touchscreen.diameter_y = + sdl2_config->GetInteger("ControlsGeneral", "touch_diameter_y", 15); + + std::transform(keyboard_keys.begin(), keyboard_keys.end(), + Settings::values.keyboard_keys.begin(), InputCommon::GenerateKeyboardParam); + std::transform(keyboard_mods.begin(), keyboard_mods.end(), + Settings::values.keyboard_keys.begin() + + Settings::NativeKeyboard::LeftControlKey, + InputCommon::GenerateKeyboardParam); + std::transform(keyboard_mods.begin(), keyboard_mods.end(), + Settings::values.keyboard_mods.begin(), InputCommon::GenerateKeyboardParam); + + // Data Storage + Settings::values.use_virtual_sd = + sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true); + FileUtil::GetUserPath(FileUtil::UserPath::NANDDir, + sdl2_config->Get("Data Storage", "nand_directory", + FileUtil::GetUserPath(FileUtil::UserPath::NANDDir))); + FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir, + sdl2_config->Get("Data Storage", "sdmc_directory", + FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir))); + + // System + Settings::values.use_docked_mode = sdl2_config->GetBoolean("System", "use_docked_mode", false); + Settings::values.enable_nfc = sdl2_config->GetBoolean("System", "enable_nfc", true); + const auto size = sdl2_config->GetInteger("System", "users_size", 0); + + Settings::values.current_user = std::clamp( + sdl2_config->GetInteger("System", "current_user", 0), 0, Service::Account::MAX_USERS - 1); + + const auto enabled = sdl2_config->GetBoolean("System", "rng_seed_enabled", false); + if (enabled) { + Settings::values.rng_seed = sdl2_config->GetInteger("System", "rng_seed", 0); + } + else { + Settings::values.rng_seed = std::nullopt; + } // Core Settings::values.use_cpu_jit = sdl2_config->GetBoolean("Core", "use_cpu_jit", true); @@ -114,31 +356,6 @@ void Config::ReadValues() { Settings::values.audio_device_id = sdl2_config->Get("Audio", "output_device", "auto"); Settings::values.volume = sdl2_config->GetReal("Audio", "volume", 1); - // Data Storage - Settings::values.use_virtual_sd = - sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true); - FileUtil::GetUserPath(FileUtil::UserPath::NANDDir, - sdl2_config->Get("Data Storage", "nand_directory", - FileUtil::GetUserPath(FileUtil::UserPath::NANDDir))); - FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir, - sdl2_config->Get("Data Storage", "sdmc_directory", - FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir))); - - // System - Settings::values.use_docked_mode = sdl2_config->GetBoolean("System", "use_docked_mode", false); - Settings::values.enable_nfc = sdl2_config->GetBoolean("System", "enable_nfc", true); - const auto size = sdl2_config->GetInteger("System", "users_size", 0); - - Settings::values.current_user = std::clamp( - sdl2_config->GetInteger("System", "current_user", 0), 0, Service::Account::MAX_USERS - 1); - - const auto enabled = sdl2_config->GetBoolean("System", "rng_seed_enabled", false); - if (enabled) { - Settings::values.rng_seed = sdl2_config->GetInteger("System", "rng_seed", 0); - } else { - Settings::values.rng_seed = std::nullopt; - } - Settings::values.language_index = sdl2_config->GetInteger("System", "language_index", 1); // Miscellaneous From d1b7c65b9ec9e76e299ef96710a86311e3cecd2f Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 1 Nov 2018 21:57:13 -0400 Subject: [PATCH 12/26] yuzu/config: Add (de-)serialization for multiplayer Defaults to full keyboard for keyboard -- It did not seem to be necessary to make the keyboard configurable (besides enabled/disabled). --- src/yuzu/configuration/config.cpp | 352 ++++++++++++++++++++++++++++-- src/yuzu/configuration/config.h | 4 + 2 files changed, 333 insertions(+), 23 deletions(-) diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index be69fb831..c931c7cd6 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -47,39 +47,283 @@ const std::array, Settings::NativeAnalog::NumAnalogs> Config: }, }}; +const std::array Config::default_mouse_buttons = + { + Qt::Key_BracketLeft, Qt::Key_BracketRight, Qt::Key_Apostrophe, Qt::Key_Minus, Qt::Key_Equal, +}; + +const std::array Config::default_keyboard_keys = { + 0, + 0, + 0, + 0, + Qt::Key_A, + Qt::Key_B, + Qt::Key_C, + Qt::Key_D, + Qt::Key_E, + Qt::Key_F, + Qt::Key_G, + Qt::Key_H, + Qt::Key_I, + Qt::Key_J, + Qt::Key_K, + Qt::Key_L, + Qt::Key_M, + Qt::Key_N, + Qt::Key_O, + Qt::Key_P, + Qt::Key_Q, + Qt::Key_R, + Qt::Key_S, + Qt::Key_T, + Qt::Key_U, + Qt::Key_V, + Qt::Key_W, + Qt::Key_X, + Qt::Key_Y, + Qt::Key_Z, + Qt::Key_1, + Qt::Key_2, + Qt::Key_3, + Qt::Key_4, + Qt::Key_5, + Qt::Key_6, + Qt::Key_7, + Qt::Key_8, + Qt::Key_9, + Qt::Key_0, + Qt::Key_Enter, + Qt::Key_Escape, + Qt::Key_Backspace, + Qt::Key_Tab, + Qt::Key_Space, + Qt::Key_Minus, + Qt::Key_Equal, + Qt::Key_BracketLeft, + Qt::Key_BracketRight, + Qt::Key_Backslash, + Qt::Key_Dead_Tilde, + Qt::Key_Semicolon, + Qt::Key_Apostrophe, + Qt::Key_Dead_Grave, + Qt::Key_Comma, + Qt::Key_Period, + Qt::Key_Slash, + Qt::Key_CapsLock, + + Qt::Key_F1, + Qt::Key_F2, + Qt::Key_F3, + Qt::Key_F4, + Qt::Key_F5, + Qt::Key_F6, + Qt::Key_F7, + Qt::Key_F8, + Qt::Key_F9, + Qt::Key_F10, + Qt::Key_F11, + Qt::Key_F12, + + Qt::Key_SysReq, + Qt::Key_ScrollLock, + Qt::Key_Pause, + Qt::Key_Insert, + Qt::Key_Home, + Qt::Key_PageUp, + Qt::Key_Delete, + Qt::Key_End, + Qt::Key_PageDown, + Qt::Key_Right, + Qt::Key_Left, + Qt::Key_Down, + Qt::Key_Up, + + Qt::Key_NumLock, + Qt::Key_Slash, + Qt::Key_Asterisk, + Qt::Key_Minus, + Qt::Key_Plus, + Qt::Key_Enter, + Qt::Key_1, + Qt::Key_2, + Qt::Key_3, + Qt::Key_4, + Qt::Key_5, + Qt::Key_6, + Qt::Key_7, + Qt::Key_8, + Qt::Key_9, + Qt::Key_0, + Qt::Key_Period, + + 0, + 0, + Qt::Key_PowerOff, + Qt::Key_Equal, + + Qt::Key_F13, + Qt::Key_F14, + Qt::Key_F15, + Qt::Key_F16, + Qt::Key_F17, + Qt::Key_F18, + Qt::Key_F19, + Qt::Key_F20, + Qt::Key_F21, + Qt::Key_F22, + Qt::Key_F23, + Qt::Key_F24, + + Qt::Key_Open, + Qt::Key_Help, + Qt::Key_Menu, + 0, + Qt::Key_Stop, + Qt::Key_AudioRepeat, + Qt::Key_Undo, + Qt::Key_Cut, + Qt::Key_Copy, + Qt::Key_Paste, + Qt::Key_Find, + Qt::Key_VolumeMute, + Qt::Key_VolumeUp, + Qt::Key_VolumeDown, + Qt::Key_CapsLock, + Qt::Key_NumLock, + Qt::Key_ScrollLock, + Qt::Key_Comma, + + Qt::Key_ParenLeft, + Qt::Key_ParenRight, +}; + +const std::array Config::default_keyboard_mods = { + Qt::Key_Control, Qt::Key_Shift, Qt::Key_Alt, Qt::Key_ApplicationLeft, + Qt::Key_Control, Qt::Key_Shift, Qt::Key_AltGr, Qt::Key_ApplicationRight, +}; + void Config::ReadValues() { qt_config->beginGroup("Controls"); - for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { - std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); - Settings::values.buttons[i] = + for (std::size_t p = 0; p < 10; ++p) { + Settings::values.players[p].connected = + qt_config->value(QString("player_%1_connected").arg(p), false).toBool(); + + Settings::values.players[p].type = static_cast( qt_config - ->value(Settings::NativeButton::mapping[i], QString::fromStdString(default_param)) + ->value(QString("player_%1_type").arg(p), + static_cast(Settings::ControllerType::DualJoycon)) + .toUInt()); + + Settings::values.players[p].body_color_left = + qt_config + ->value(QString("player_%1_body_color_left").arg(p), + Settings::JOYCON_BODY_NEON_BLUE) + .toUInt(); + Settings::values.players[p].body_color_right = + qt_config + ->value(QString("player_%1_body_color_right").arg(p), + Settings::JOYCON_BODY_NEON_RED) + .toUInt(); + Settings::values.players[p].button_color_left = + qt_config + ->value(QString("player_%1_button_color_left").arg(p), + Settings::JOYCON_BUTTONS_NEON_BLUE) + .toUInt(); + Settings::values.players[p].button_color_right = + qt_config + ->value(QString("player_%1_button_color_right").arg(p), + Settings::JOYCON_BUTTONS_NEON_RED) + .toUInt(); + + for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { + std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); + Settings::values.players[p].buttons[i] = + qt_config + ->value(QString("player_%1_").arg(p) + Settings::NativeButton::mapping[i], + QString::fromStdString(default_param)) + .toString() + .toStdString(); + if (Settings::values.players[p].buttons[i].empty()) + Settings::values.players[p].buttons[i] = default_param; + } + + for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { + std::string default_param = InputCommon::GenerateAnalogParamFromKeys( + default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], + default_analogs[i][3], default_analogs[i][4], 0.5f); + Settings::values.players[p].analogs[i] = + qt_config + ->value(QString("player_%1_").arg(p) + Settings::NativeAnalog::mapping[i], + QString::fromStdString(default_param)) + .toString() + .toStdString(); + if (Settings::values.players[p].analogs[i].empty()) + Settings::values.players[p].analogs[i] = default_param; + } + } + + std::stable_partition(Settings::values.players.begin(), Settings::values.players.end(), + [](const auto& player) { return player.connected; }); + + Settings::values.motion_device = + qt_config->value("motion_device", "engine:motion_emu,update_period:100,sensitivity:0.01") + .toString() + .toStdString(); + + Settings::values.mouse_enabled = qt_config->value("mouse_enabled", false).toBool(); + + for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { + std::string default_param = InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]); + Settings::values.mouse_buttons[i] = + qt_config + ->value(QString("mouse_") + Settings::NativeMouseButton::mapping[i], + QString::fromStdString(default_param)) .toString() .toStdString(); - if (Settings::values.buttons[i].empty()) - Settings::values.buttons[i] = default_param; + if (Settings::values.mouse_buttons[i].empty()) + Settings::values.mouse_buttons[i] = default_param; + } + + Settings::values.keyboard_enabled = qt_config->value("keyboard_enabled", false).toBool(); + + Settings::values.debug_pad_enabled = qt_config->value("debug_pad_enabled", false).toBool(); + for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { + std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); + Settings::values.debug_pad_buttons[i] = + qt_config + ->value(QString("debug_pad_") + Settings::NativeButton::mapping[i], + QString::fromStdString(default_param)) + .toString() + .toStdString(); + if (Settings::values.debug_pad_buttons[i].empty()) + Settings::values.debug_pad_buttons[i] = default_param; } for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { std::string default_param = InputCommon::GenerateAnalogParamFromKeys( default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], default_analogs[i][3], default_analogs[i][4], 0.5f); - Settings::values.analogs[i] = + Settings::values.debug_pad_analogs[i] = qt_config - ->value(Settings::NativeAnalog::mapping[i], QString::fromStdString(default_param)) + ->value(QString("debug_pad_") + Settings::NativeAnalog::mapping[i], + QString::fromStdString(default_param)) .toString() .toStdString(); - if (Settings::values.analogs[i].empty()) - Settings::values.analogs[i] = default_param; + if (Settings::values.debug_pad_analogs[i].empty()) + Settings::values.debug_pad_analogs[i] = default_param; } - Settings::values.motion_device = - qt_config->value("motion_device", "engine:motion_emu,update_period:100,sensitivity:0.01") - .toString() - .toStdString(); - Settings::values.touch_device = - qt_config->value("touch_device", "engine:emu_window").toString().toStdString(); + Settings::values.touchscreen.enabled = qt_config->value("touchscreen_enabled", true).toBool(); + Settings::values.touchscreen.device = + qt_config->value("touchscreen_device", "engine:emu_window").toString().toStdString(); + Settings::values.touchscreen.finger = qt_config->value("touchscreen_finger", 0).toUInt(); + Settings::values.touchscreen.rotation_angle = qt_config->value("touchscreen_angle", 0).toUInt(); + Settings::values.touchscreen.diameter_x = + qt_config->value("touchscreen_diameter_x", 15).toUInt(); + Settings::values.touchscreen.diameter_y = + qt_config->value("touchscreen_diameter_y", 15).toUInt(); qt_config->endGroup(); qt_config->beginGroup("Core"); @@ -126,6 +370,20 @@ void Config::ReadValues() { .toStdString()); qt_config->endGroup(); + std::transform(default_keyboard_keys.begin(), default_keyboard_keys.end(), + Settings::values.keyboard_keys.begin(), InputCommon::GenerateKeyboardParam); + std::transform(default_keyboard_mods.begin(), default_keyboard_mods.end(), + Settings::values.keyboard_keys.begin() + + Settings::NativeKeyboard::LeftControlKey, + InputCommon::GenerateKeyboardParam); + std::transform(default_keyboard_mods.begin(), default_keyboard_mods.end(), + Settings::values.keyboard_mods.begin(), InputCommon::GenerateKeyboardParam); + + qt_config->beginGroup("Core"); + Settings::values.use_cpu_jit = qt_config->value("use_cpu_jit", true).toBool(); + Settings::values.use_multi_core = qt_config->value("use_multi_core", false).toBool(); + qt_config->endGroup(); + qt_config->beginGroup("System"); Settings::values.use_docked_mode = qt_config->value("use_docked_mode", false).toBool(); Settings::values.enable_nfc = qt_config->value("enable_nfc", true).toBool(); @@ -232,16 +490,65 @@ void Config::ReadValues() { void Config::SaveValues() { qt_config->beginGroup("Controls"); + for (int p = 0; p < 10; ++p) { + qt_config->setValue(QString("player_%1_connected").arg(p), + Settings::values.players[p].connected); + qt_config->setValue(QString("player_%1_type").arg(p), + static_cast(Settings::values.players[p].type)); + + qt_config->setValue(QString("player_%1_body_color_left").arg(p), + Settings::values.players[p].body_color_left); + qt_config->setValue(QString("player_%1_body_color_right").arg(p), + Settings::values.players[p].body_color_right); + qt_config->setValue(QString("player_%1_button_color_left").arg(p), + Settings::values.players[p].button_color_left); + qt_config->setValue(QString("player_%1_button_color_right").arg(p), + Settings::values.players[p].button_color_right); + + for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { + qt_config->setValue(QString("player_%1_").arg(p) + + QString::fromStdString(Settings::NativeButton::mapping[i]), + QString::fromStdString(Settings::values.players[p].buttons[i])); + } + for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { + qt_config->setValue(QString("player_%1_").arg(p) + + QString::fromStdString(Settings::NativeAnalog::mapping[i]), + QString::fromStdString(Settings::values.players[p].analogs[i])); + } + } + + qt_config->setValue("motion_device", QString::fromStdString(Settings::values.motion_device)); + + qt_config->setValue("mouse_enabled", Settings::values.mouse_enabled); + + for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { + qt_config->setValue(QString("mouse_") + + QString::fromStdString(Settings::NativeMouseButton::mapping[i]), + QString::fromStdString(Settings::values.mouse_buttons[i])); + } + + qt_config->setValue("keyboard_enabled", Settings::values.keyboard_enabled); + + qt_config->setValue("debug_pad_enabled", Settings::values.debug_pad_enabled); for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { - qt_config->setValue(QString::fromStdString(Settings::NativeButton::mapping[i]), - QString::fromStdString(Settings::values.buttons[i])); + qt_config->setValue(QString("debug_pad_") + + QString::fromStdString(Settings::NativeButton::mapping[i]), + QString::fromStdString(Settings::values.debug_pad_buttons[i])); } for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { - qt_config->setValue(QString::fromStdString(Settings::NativeAnalog::mapping[i]), - QString::fromStdString(Settings::values.analogs[i])); + qt_config->setValue(QString("debug_pad_") + + QString::fromStdString(Settings::NativeAnalog::mapping[i]), + QString::fromStdString(Settings::values.debug_pad_analogs[i])); } - qt_config->setValue("motion_device", QString::fromStdString(Settings::values.motion_device)); - qt_config->setValue("touch_device", QString::fromStdString(Settings::values.touch_device)); + + qt_config->setValue("touchscreen_enabled", Settings::values.touchscreen.enabled); + qt_config->setValue("touchscreen_device", + QString::fromStdString(Settings::values.touchscreen.device)); + + qt_config->setValue("touchscreen_finger", Settings::values.touchscreen.finger); + qt_config->setValue("touchscreen_angle", Settings::values.touchscreen.rotation_angle); + qt_config->setValue("touchscreen_diameter_x", Settings::values.touchscreen.diameter_x); + qt_config->setValue("touchscreen_diameter_y", Settings::values.touchscreen.diameter_y); qt_config->endGroup(); qt_config->beginGroup("Core"); @@ -280,7 +587,6 @@ void Config::SaveValues() { qt_config->setValue("use_docked_mode", Settings::values.use_docked_mode); qt_config->setValue("enable_nfc", Settings::values.enable_nfc); qt_config->setValue("current_user", Settings::values.current_user); - qt_config->setValue("language_index", Settings::values.language_index); qt_config->setValue("rng_seed_enabled", Settings::values.rng_seed.has_value()); diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index 9c99c1b75..1facd6b55 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h @@ -22,6 +22,10 @@ public: static const std::array default_buttons; static const std::array, Settings::NativeAnalog::NumAnalogs> default_analogs; + static const std::array + default_mouse_buttons; + static const std::array default_keyboard_keys; + static const std::array default_keyboard_mods; private: void ReadValues(); From 06cf050c0a541bc0bf9b4ca41fdec75f133c91d3 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 1 Nov 2018 22:01:11 -0400 Subject: [PATCH 13/26] hid: Add controller bindings for DebugPad controller Used by developers to test games, not present on retail systems. Some games are known to respond to DebugPad input though, for example Kirby Star Allies. --- .../hle/service/hid/controllers/debug_pad.cpp | 57 ++++++++++++------- .../hle/service/hid/controllers/debug_pad.h | 7 +++ 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp index ac9b23bb8..e76c83aee 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.cpp +++ b/src/core/hle/service/hid/controllers/debug_pad.cpp @@ -6,9 +6,14 @@ #include "common/common_types.h" #include "core/core_timing.h" #include "core/hle/service/hid/controllers/debug_pad.h" +#include "core/settings.h" namespace Service::HID { +constexpr s32 HID_JOYSTICK_MAX = 0x7fff; +constexpr s32 HID_JOYSTICK_MIN = -0x7fff; +enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right }; + Controller_DebugPad::Controller_DebugPad() = default; Controller_DebugPad::~Controller_DebugPad() = default; @@ -33,33 +38,43 @@ void Controller_DebugPad::OnUpdate(u8* data, std::size_t size) { cur_entry.sampling_number = last_entry.sampling_number + 1; cur_entry.sampling_number2 = cur_entry.sampling_number; - // TODO(ogniK): Update debug pad states cur_entry.attribute.connected.Assign(1); auto& pad = cur_entry.pad_state; - pad.a.Assign(0); - pad.b.Assign(0); - pad.x.Assign(0); - pad.y.Assign(0); - pad.l.Assign(0); - pad.r.Assign(0); - pad.zl.Assign(0); - pad.zr.Assign(0); - pad.plus.Assign(0); - pad.minus.Assign(0); - pad.d_left.Assign(0); - pad.d_up.Assign(0); - pad.d_right.Assign(0); - pad.d_down.Assign(0); + using namespace Settings::NativeButton; + pad.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus()); + pad.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus()); + pad.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus()); + pad.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus()); + pad.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus()); + pad.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus()); + pad.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus()); + pad.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus()); + pad.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus()); + pad.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus()); + pad.d_left.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus()); + pad.d_up.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus()); + pad.d_right.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus()); + pad.d_down.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus()); - cur_entry.l_stick.x = 0; - cur_entry.l_stick.y = 0; - - cur_entry.r_stick.x = 0; - cur_entry.r_stick.y = 0; + const auto [stick_l_x_f, stick_l_y_f] = + analogs[static_cast(JoystickId::Joystick_Left)]->GetStatus(); + const auto [stick_r_x_f, stick_r_y_f] = + analogs[static_cast(JoystickId::Joystick_Right)]->GetStatus(); + cur_entry.l_stick.x = static_cast(stick_l_x_f * HID_JOYSTICK_MAX); + cur_entry.l_stick.y = static_cast(stick_l_y_f * HID_JOYSTICK_MAX); + cur_entry.r_stick.x = static_cast(stick_r_x_f * HID_JOYSTICK_MAX); + cur_entry.r_stick.y = static_cast(stick_r_y_f * HID_JOYSTICK_MAX); std::memcpy(data, &shared_memory, sizeof(SharedMemory)); } -void Controller_DebugPad::OnLoadInputDevices() {} +void Controller_DebugPad::OnLoadInputDevices() { + std::transform(Settings::values.debug_pad_buttons.begin(), + Settings::values.debug_pad_buttons.end(), buttons.begin(), + Input::CreateDevice); + std::transform(Settings::values.debug_pad_analogs.begin(), + Settings::values.debug_pad_analogs.end(), analogs.begin(), + Input::CreateDevice); +} } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h index a41564b4d..68b734248 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.h +++ b/src/core/hle/service/hid/controllers/debug_pad.h @@ -9,7 +9,9 @@ #include "common/common_funcs.h" #include "common/common_types.h" #include "common/swap.h" +#include "core/frontend/input.h" #include "core/hle/service/hid/controllers/controller_base.h" +#include "core/settings.h" namespace Service::HID { class Controller_DebugPad final : public ControllerBase { @@ -82,5 +84,10 @@ private: }; static_assert(sizeof(SharedMemory) == 0x400, "SharedMemory is an invalid size"); SharedMemory shared_memory{}; + + std::array, Settings::NativeButton::NUM_BUTTONS_HID> + buttons; + std::array, Settings::NativeAnalog::NUM_STICKS_HID> + analogs; }; } // namespace Service::HID From 0fd45e78f453c2afad4fe508c2fe181604ff821e Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 1 Nov 2018 22:01:36 -0400 Subject: [PATCH 14/26] hid: Add keyboard bindings for Keyboard controller --- .../hle/service/hid/controllers/keyboard.cpp | 19 +++++++++++++++++-- .../hle/service/hid/controllers/keyboard.h | 7 +++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp index ccfbce9ac..088f00b43 100644 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ b/src/core/hle/service/hid/controllers/keyboard.cpp @@ -6,6 +6,7 @@ #include "common/common_types.h" #include "core/core_timing.h" #include "core/hle/service/hid/controllers/keyboard.h" +#include "core/settings.h" namespace Service::HID { constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800; @@ -34,10 +35,24 @@ void Controller_Keyboard::OnUpdate(u8* data, std::size_t size) { cur_entry.sampling_number = last_entry.sampling_number + 1; cur_entry.sampling_number2 = cur_entry.sampling_number; - // TODO(ogniK): Update keyboard states + + for (std::size_t i = 0; i < keyboard_keys.size(); ++i) { + for (std::size_t k = 0; k < 8; ++k) { + cur_entry.key[i / 8] |= (keyboard_keys[i]->GetStatus() << k); + } + } + + for (std::size_t i = 0; i < keyboard_mods.size(); ++i) { + cur_entry.modifier |= (keyboard_mods[i]->GetStatus() << i); + } std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); } -void Controller_Keyboard::OnLoadInputDevices() {} +void Controller_Keyboard::OnLoadInputDevices() { + std::transform(Settings::values.keyboard_keys.begin(), Settings::values.keyboard_keys.end(), + keyboard_keys.begin(), Input::CreateDevice); + std::transform(Settings::values.keyboard_mods.begin(), Settings::values.keyboard_mods.end(), + keyboard_mods.begin(), Input::CreateDevice); +} } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h index 493e68fce..f52775456 100644 --- a/src/core/hle/service/hid/controllers/keyboard.h +++ b/src/core/hle/service/hid/controllers/keyboard.h @@ -8,7 +8,9 @@ #include "common/common_funcs.h" #include "common/common_types.h" #include "common/swap.h" +#include "core/frontend/input.h" #include "core/hle/service/hid/controllers/controller_base.h" +#include "core/settings.h" namespace Service::HID { class Controller_Keyboard final : public ControllerBase { @@ -46,5 +48,10 @@ private: }; static_assert(sizeof(SharedMemory) == 0x400, "SharedMemory is an invalid size"); SharedMemory shared_memory{}; + + std::array, Settings::NativeKeyboard::NumKeyboardKeys> + keyboard_keys; + std::array, Settings::NativeKeyboard::NumKeyboardMods> + keyboard_mods; }; } // namespace Service::HID From 3b25426bd95423f74bca25145c67e350d3745d5a Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 1 Nov 2018 22:01:59 -0400 Subject: [PATCH 15/26] hid: Add controller bindings for Mouse controller --- .../hle/service/hid/controllers/mouse.cpp | 25 ++++++++++++++++--- src/core/hle/service/hid/controllers/mouse.h | 9 ++++++- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp index 4e246a57d..63391dbe9 100644 --- a/src/core/hle/service/hid/controllers/mouse.cpp +++ b/src/core/hle/service/hid/controllers/mouse.cpp @@ -5,6 +5,7 @@ #include #include "common/common_types.h" #include "core/core_timing.h" +#include "core/frontend/emu_window.h" #include "core/hle/service/hid/controllers/mouse.h" namespace Service::HID { @@ -14,7 +15,6 @@ Controller_Mouse::Controller_Mouse() = default; Controller_Mouse::~Controller_Mouse() = default; void Controller_Mouse::OnInit() {} - void Controller_Mouse::OnRelease() {} void Controller_Mouse::OnUpdate(u8* data, std::size_t size) { @@ -34,10 +34,29 @@ void Controller_Mouse::OnUpdate(u8* data, std::size_t size) { cur_entry.sampling_number = last_entry.sampling_number + 1; cur_entry.sampling_number2 = cur_entry.sampling_number; - // TODO(ogniK): Update mouse states + + if (Settings::values.mouse_enabled) { + const auto [px, py, sx, sy] = mouse_device->GetStatus(); + const auto x = static_cast(px * Layout::ScreenUndocked::Width); + const auto y = static_cast(py * Layout::ScreenUndocked::Height); + cur_entry.x = x; + cur_entry.y = y; + cur_entry.delta_x = x - last_entry.x; + cur_entry.delta_y = y - last_entry.y; + cur_entry.mouse_wheel_x = sx; + cur_entry.mouse_wheel_y = sy; + + for (std::size_t i = 0; i < mouse_button_devices.size(); ++i) { + cur_entry.button |= (mouse_button_devices[i]->GetStatus() << i); + } + } std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); } -void Controller_Mouse::OnLoadInputDevices() {} +void Controller_Mouse::OnLoadInputDevices() { + mouse_device = Input::CreateDevice(Settings::values.mouse_device); + std::transform(Settings::values.mouse_buttons.begin(), Settings::values.mouse_buttons.end(), + mouse_button_devices.begin(), Input::CreateDevice); +} } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h index 543b0b71f..70b654d07 100644 --- a/src/core/hle/service/hid/controllers/mouse.h +++ b/src/core/hle/service/hid/controllers/mouse.h @@ -7,7 +7,9 @@ #include #include "common/common_types.h" #include "common/swap.h" +#include "core/frontend/input.h" #include "core/hle/service/hid/controllers/controller_base.h" +#include "core/settings.h" namespace Service::HID { class Controller_Mouse final : public ControllerBase { @@ -35,7 +37,8 @@ private: s32_le y; s32_le delta_x; s32_le delta_y; - s32_le mouse_wheel; + s32_le mouse_wheel_x; + s32_le mouse_wheel_y; s32_le button; s32_le attribute; }; @@ -46,5 +49,9 @@ private: std::array mouse_states; }; SharedMemory shared_memory{}; + + std::unique_ptr mouse_device; + std::array, Settings::NativeMouseButton::NumMouseButtons> + mouse_button_devices; }; } // namespace Service::HID From e9145c3e1671d0a3d2293e5b11f70649918a3d45 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 1 Nov 2018 22:02:44 -0400 Subject: [PATCH 16/26] hid/touchscreen: Update Touchscreen to use advanced parameters Including finger ID, diamater x/y, and angle. Additionally, checks if the touchscreen is enabled. --- src/core/hle/service/hid/controllers/touchscreen.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index 07244fe4e..8b9763de6 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp @@ -42,19 +42,19 @@ void Controller_Touchscreen::OnUpdate(u8* data, std::size_t size) { const auto [x, y, pressed] = touch_device->GetStatus(); auto& touch_entry = cur_entry.states[0]; touch_entry.attribute.raw = 0; - if (pressed) { + if (pressed && Settings::values.touchscreen.enabled) { if (cur_entry.entry_count == 0) { touch_entry.attribute.start_touch.Assign(1); } touch_entry.x = static_cast(x * Layout::ScreenUndocked::Width); touch_entry.y = static_cast(y * Layout::ScreenUndocked::Height); - touch_entry.diameter_x = 15; - touch_entry.diameter_y = 15; - touch_entry.rotation_angle = 0; + touch_entry.diameter_x = Settings::values.touchscreen.diameter_x; + touch_entry.diameter_y = Settings::values.touchscreen.diameter_y; + touch_entry.rotation_angle = Settings::values.touchscreen.rotation_angle; const u64 tick = CoreTiming::GetTicks(); touch_entry.delta_time = tick - last_touch; last_touch = tick; - touch_entry.finger = 0; + touch_entry.finger = Settings::values.touchscreen.finger; cur_entry.entry_count = 1; } else { if (cur_entry.entry_count == 1) { @@ -67,6 +67,6 @@ void Controller_Touchscreen::OnUpdate(u8* data, std::size_t size) { } void Controller_Touchscreen::OnLoadInputDevices() { - touch_device = Input::CreateDevice(Settings::values.touch_device); + touch_device = Input::CreateDevice(Settings::values.touchscreen.device); } } // namespace Service::HID From 55ded706d67a6f2dd6e01d0abf7351e69588ac3a Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 1 Nov 2018 22:03:17 -0400 Subject: [PATCH 17/26] hid/npad: Update NPad to use player controller bindings and type --- src/core/hle/service/hid/controllers/npad.cpp | 146 ++++++++++++------ src/core/hle/service/hid/controllers/npad.h | 9 +- 2 files changed, 104 insertions(+), 51 deletions(-) diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 3eb59599f..911ba3574 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -17,11 +17,6 @@ #include "core/settings.h" namespace Service::HID { - -constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28; -constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A; -constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6; -constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E; constexpr s32 HID_JOYSTICK_MAX = 0x7fff; constexpr s32 HID_JOYSTICK_MIN = -0x7fff; constexpr std::size_t NPAD_OFFSET = 0x9A00; @@ -40,6 +35,22 @@ enum class JoystickId : std::size_t { Joystick_Right, }; +static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::ControllerType type) { + switch (type) { + case Settings::ControllerType::ProController: + return Controller_NPad::NPadControllerType::ProController; + case Settings::ControllerType::DualJoycon: + return Controller_NPad::NPadControllerType::JoyDual; + case Settings::ControllerType::LeftJoycon: + return Controller_NPad::NPadControllerType::JoyLeft; + case Settings::ControllerType::RightJoycon: + return Controller_NPad::NPadControllerType::JoyRight; + default: + UNREACHABLE(); + return Controller_NPad::NPadControllerType::JoyDual; + } +} + static std::size_t NPadIdToIndex(u32 npad_id) { switch (npad_id) { case 0: @@ -126,10 +137,11 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { controller.single_color.button_color = 0; controller.dual_color_error = ColorReadError::ReadOk; - controller.left_color.body_color = JOYCON_BODY_NEON_BLUE; - controller.left_color.button_color = JOYCON_BUTTONS_NEON_BLUE; - controller.right_color.body_color = JOYCON_BODY_NEON_RED; - controller.right_color.button_color = JOYCON_BUTTONS_NEON_RED; + controller.left_color.body_color = Settings::values.players[controller_idx].body_color_left; + controller.left_color.button_color = Settings::values.players[controller_idx].button_color_left; + controller.right_color.body_color = Settings::values.players[controller_idx].body_color_right; + controller.right_color.button_color = + Settings::values.players[controller_idx].button_color_right; controller.battery_level[0] = BATTERY_FULL; controller.battery_level[1] = BATTERY_FULL; @@ -154,6 +166,25 @@ void Controller_NPad::OnInit() { style.pro_controller.Assign(1); style.pokeball.Assign(1); } + + std::transform( + Settings::values.players.begin(), Settings::values.players.end(), + connected_controllers.begin(), [](const Settings::PlayerInput& player) { + return ControllerHolder{MapSettingsTypeToNPad(player.type), player.connected}; + }); + + std::stable_partition(connected_controllers.begin(), connected_controllers.begin() + 8, + [](const ControllerHolder& holder) { return holder.is_connected; }); + + // Account for handheld + if (connected_controllers[8].is_connected) + connected_controllers[8].type = NPadControllerType::Handheld; + + supported_npad_id_types.resize(npad_id_list.size()); + std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), + npad_id_list.size() * sizeof(u32)); + + // Add a default dual joycon controller if none are present. if (std::none_of(connected_controllers.begin(), connected_controllers.end(), [](const ControllerHolder& controller) { return controller.is_connected; })) { supported_npad_id_types.resize(npad_id_list.size()); @@ -161,15 +192,25 @@ void Controller_NPad::OnInit() { npad_id_list.size() * sizeof(u32)); AddNewController(PREFERRED_CONTROLLER); } + + for (std::size_t i = 0; i < connected_controllers.size(); ++i) { + const auto& controller = connected_controllers[i]; + if (controller.is_connected) { + AddNewControllerAt(controller.type, IndexToNPad(i)); + } + } } void Controller_NPad::OnLoadInputDevices() { - std::transform(Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, - Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_END, - buttons.begin(), Input::CreateDevice); - std::transform(Settings::values.analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, - Settings::values.analogs.begin() + Settings::NativeAnalog::STICK_HID_END, - sticks.begin(), Input::CreateDevice); + const auto& players = Settings::values.players; + for (std::size_t i = 0; i < players.size(); ++i) { + std::transform(players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, + players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_END, + buttons[i].begin(), Input::CreateDevice); + std::transform(players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, + players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_END, + sticks[i].begin(), Input::CreateDevice); + } } void Controller_NPad::OnRelease() {} @@ -183,42 +224,45 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { auto& pad_state = npad_pad_states[controller_idx].pad_states; auto& lstick_entry = npad_pad_states[controller_idx].l_stick; auto& rstick_entry = npad_pad_states[controller_idx].r_stick; + const auto& button_state = buttons[controller_idx]; + const auto& analog_state = sticks[controller_idx]; + using namespace Settings::NativeButton; - pad_state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.l_stick.Assign(buttons[LStick - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.r_stick.Assign(buttons[RStick - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.a.Assign(button_state[A - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.b.Assign(button_state[B - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.x.Assign(button_state[X - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.y.Assign(button_state[Y - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l_stick.Assign(button_state[LStick - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r_stick.Assign(button_state[RStick - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l.Assign(button_state[L - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.zl.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.zr.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.plus.Assign(button_state[Plus - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.minus.Assign(button_state[Minus - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.d_left.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.d_up.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.d_right.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.d_down.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.d_left.Assign(button_state[DLeft - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.d_up.Assign(button_state[DUp - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.d_right.Assign(button_state[DRight - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.d_down.Assign(button_state[DDown - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.l_stick_left.Assign(buttons[LStick_Left - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.l_stick_up.Assign(buttons[LStick_Up - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.l_stick_right.Assign(buttons[LStick_Right - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.l_stick_down.Assign(buttons[LStick_Down - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l_stick_left.Assign(button_state[LStick_Left - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l_stick_up.Assign(button_state[LStick_Up - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l_stick_right.Assign(button_state[LStick_Right - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.l_stick_down.Assign(button_state[LStick_Down - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.r_stick_left.Assign(buttons[RStick_Left - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.r_stick_up.Assign(buttons[RStick_Up - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.r_stick_right.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.r_stick_down.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r_stick_left.Assign(button_state[RStick_Left - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r_stick_up.Assign(button_state[RStick_Up - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r_stick_right.Assign(button_state[RStick_Right - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.r_stick_down.Assign(button_state[RStick_Down - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.left_sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus()); - pad_state.left_sr.Assign(buttons[SR - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus()); + pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus()); const auto [stick_l_x_f, stick_l_y_f] = - sticks[static_cast(JoystickId::Joystick_Left)]->GetStatus(); + analog_state[static_cast(JoystickId::Joystick_Left)]->GetStatus(); const auto [stick_r_x_f, stick_r_y_f] = - sticks[static_cast(JoystickId::Joystick_Right)]->GetStatus(); + analog_state[static_cast(JoystickId::Joystick_Right)]->GetStatus(); lstick_entry.x = static_cast(stick_l_x_f * HID_JOYSTICK_MAX); lstick_entry.y = static_cast(stick_l_y_f * HID_JOYSTICK_MAX); rstick_entry.x = static_cast(stick_r_x_f * HID_JOYSTICK_MAX); @@ -285,8 +329,10 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { state.d_left.Assign(pad_state.pad_states.d_up.Value()); state.d_right.Assign(pad_state.pad_states.d_down.Value()); state.d_up.Assign(pad_state.pad_states.d_right.Value()); - state.l.Assign(pad_state.pad_states.l.Value() | pad_state.pad_states.sl.Value()); - state.r.Assign(pad_state.pad_states.r.Value() | pad_state.pad_states.sr.Value()); + state.l.Assign(pad_state.pad_states.l.Value() | + pad_state.pad_states.left_sl.Value()); + state.r.Assign(pad_state.pad_states.r.Value() | + pad_state.pad_states.left_sr.Value()); state.zl.Assign(pad_state.pad_states.zl.Value()); state.plus.Assign(pad_state.pad_states.minus.Value()); @@ -302,8 +348,10 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { state.b.Assign(pad_state.pad_states.y.Value()); state.y.Assign(pad_state.pad_states.b.Value()); - state.l.Assign(pad_state.pad_states.l.Value() | pad_state.pad_states.sl.Value()); - state.r.Assign(pad_state.pad_states.r.Value() | pad_state.pad_states.sr.Value()); + state.l.Assign(pad_state.pad_states.l.Value() | + pad_state.pad_states.right_sl.Value()); + state.r.Assign(pad_state.pad_states.r.Value() | + pad_state.pad_states.right_sr.Value()); state.zr.Assign(pad_state.pad_states.zr.Value()); state.plus.Assign(pad_state.pad_states.plus.Value()); @@ -570,7 +618,7 @@ Controller_NPad::NPadControllerType Controller_NPad::DecideBestController( if (IsControllerSupported(priority)) { return priority; } - const auto is_docked = Settings::values->use_docked_mode; + const auto is_docked = Settings::values.use_docked_mode; if (is_docked && priority == NPadControllerType::Handheld) { priority = NPadControllerType::JoyDual; if (IsControllerSupported(priority)) { @@ -659,7 +707,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) { return false; } // Handheld should not be supported in docked mode - if (Settings::values->use_docked_mode) { + if (Settings::values.use_docked_mode) { return false; } } diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 7222bca72..52f92a4f1 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -285,9 +285,14 @@ private: NPadType style{}; std::array shared_memory_entries{}; - std::array, Settings::NativeButton::NUM_BUTTONS_HID> + std::array< + std::array, Settings::NativeButton::NUM_BUTTONS_HID>, + 10> buttons; - std::array, Settings::NativeAnalog::NUM_STICKS_HID> sticks; + std::array< + std::array, Settings::NativeAnalog::NUM_STICKS_HID>, + 10> + sticks; std::vector supported_npad_id_types{}; NpadHoldType hold_type{NpadHoldType::Vertical}; Kernel::SharedPtr styleset_changed_event; From f1aec256d754ac47d74363eb3f2abfa3db414b12 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 1 Nov 2018 22:06:48 -0400 Subject: [PATCH 18/26] configure_input: Add support for multiplayer and controller types This moves the actual button configuration to a separate dialog and only has the enabled and type controls in the tab. --- src/yuzu/configuration/configure_input.cpp | 438 +++----- src/yuzu/configuration/configure_input.h | 53 +- src/yuzu/configuration/configure_input.ui | 1080 ++++++++------------ 3 files changed, 549 insertions(+), 1022 deletions(-) diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 42a7beac6..9ae9827fe 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -9,334 +9,164 @@ #include #include #include "common/param_package.h" +#include "configuration/configure_touchscreen_advanced.h" +#include "core/core.h" #include "input_common/main.h" +#include "ui_configure_input.h" +#include "ui_configure_input_player.h" +#include "ui_configure_mouse_advanced.h" +#include "ui_configure_touchscreen_advanced.h" #include "yuzu/configuration/config.h" #include "yuzu/configuration/configure_input.h" - -const std::array - ConfigureInput::analog_sub_buttons{{ - "up", - "down", - "left", - "right", - "modifier", - }}; - -static QString getKeyName(int key_code) { - switch (key_code) { - case Qt::Key_Shift: - return QObject::tr("Shift"); - case Qt::Key_Control: - return QObject::tr("Ctrl"); - case Qt::Key_Alt: - return QObject::tr("Alt"); - case Qt::Key_Meta: - return ""; - default: - return QKeySequence(key_code).toString(); - } -} - -static void SetAnalogButton(const Common::ParamPackage& input_param, - Common::ParamPackage& analog_param, const std::string& button_name) { - if (analog_param.Get("engine", "") != "analog_from_button") { - analog_param = { - {"engine", "analog_from_button"}, - {"modifier_scale", "0.5"}, - }; - } - analog_param.Set(button_name, input_param.Serialize()); -} - -static QString ButtonToText(const Common::ParamPackage& param) { - if (!param.Has("engine")) { - return QObject::tr("[not set]"); - } else if (param.Get("engine", "") == "keyboard") { - return getKeyName(param.Get("code", 0)); - } else if (param.Get("engine", "") == "sdl") { - if (param.Has("hat")) { - return QString(QObject::tr("Hat %1 %2")) - .arg(param.Get("hat", "").c_str(), param.Get("direction", "").c_str()); - } - if (param.Has("axis")) { - return QString(QObject::tr("Axis %1%2")) - .arg(param.Get("axis", "").c_str(), param.Get("direction", "").c_str()); - } - if (param.Has("button")) { - return QString(QObject::tr("Button %1")).arg(param.Get("button", "").c_str()); - } - return QString(); - } else { - return QObject::tr("[unknown]"); - } -}; - -static QString AnalogToText(const Common::ParamPackage& param, const std::string& dir) { - if (!param.Has("engine")) { - return QObject::tr("[not set]"); - } else if (param.Get("engine", "") == "analog_from_button") { - return ButtonToText(Common::ParamPackage{param.Get(dir, "")}); - } else if (param.Get("engine", "") == "sdl") { - if (dir == "modifier") { - return QString(QObject::tr("[unused]")); - } - - if (dir == "left" || dir == "right") { - return QString(QObject::tr("Axis %1")).arg(param.Get("axis_x", "").c_str()); - } else if (dir == "up" || dir == "down") { - return QString(QObject::tr("Axis %1")).arg(param.Get("axis_y", "").c_str()); - } - return QString(); - } else { - return QObject::tr("[unknown]"); - } -}; +#include "yuzu/configuration/configure_input_player.h" +#include "yuzu/configuration/configure_mouse_advanced.h" ConfigureInput::ConfigureInput(QWidget* parent) - : QWidget(parent), ui(std::make_unique()), - timeout_timer(std::make_unique()), poll_timer(std::make_unique()) { - + : QWidget(parent), ui(std::make_unique()) { ui->setupUi(this); - setFocusPolicy(Qt::ClickFocus); - button_map = { - ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY, - ui->buttonLStick, ui->buttonRStick, ui->buttonL, ui->buttonR, - ui->buttonZL, ui->buttonZR, ui->buttonPlus, ui->buttonMinus, - ui->buttonDpadLeft, ui->buttonDpadUp, ui->buttonDpadRight, ui->buttonDpadDown, - ui->buttonLStickLeft, ui->buttonLStickUp, ui->buttonLStickRight, ui->buttonLStickDown, - ui->buttonRStickLeft, ui->buttonRStickUp, ui->buttonRStickRight, ui->buttonRStickDown, - ui->buttonSL, ui->buttonSR, ui->buttonHome, ui->buttonScreenshot, + players_enabled = { + ui->player1_checkbox, ui->player2_checkbox, ui->player3_checkbox, ui->player4_checkbox, + ui->player5_checkbox, ui->player6_checkbox, ui->player7_checkbox, ui->player8_checkbox, }; - analog_map_buttons = {{ - { - ui->buttonLStickUp, - ui->buttonLStickDown, - ui->buttonLStickLeft, - ui->buttonLStickRight, - ui->buttonLStickMod, - }, - { - ui->buttonRStickUp, - ui->buttonRStickDown, - ui->buttonRStickLeft, - ui->buttonRStickRight, - ui->buttonRStickMod, - }, - }}; + player_controller = { + ui->player1_combobox, ui->player2_combobox, ui->player3_combobox, ui->player4_combobox, + ui->player5_combobox, ui->player6_combobox, ui->player7_combobox, ui->player8_combobox, + }; - analog_map_stick = {ui->buttonLStickAnalog, ui->buttonRStickAnalog}; + player_configure = { + ui->player1_configure, ui->player2_configure, ui->player3_configure, ui->player4_configure, + ui->player5_configure, ui->player6_configure, ui->player7_configure, ui->player8_configure, + }; - for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) { - if (!button_map[button_id]) - continue; - button_map[button_id]->setContextMenuPolicy(Qt::CustomContextMenu); - connect(button_map[button_id], &QPushButton::released, [=]() { - handleClick( - button_map[button_id], - [=](const Common::ParamPackage& params) { buttons_param[button_id] = params; }, - InputCommon::Polling::DeviceType::Button); - }); - connect(button_map[button_id], &QPushButton::customContextMenuRequested, - [=](const QPoint& menu_location) { - QMenu context_menu; - context_menu.addAction(tr("Clear"), [&] { - buttons_param[button_id].Clear(); - button_map[button_id]->setText(tr("[not set]")); - }); - context_menu.addAction(tr("Restore Default"), [&] { - buttons_param[button_id] = Common::ParamPackage{ - InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; - button_map[button_id]->setText(ButtonToText(buttons_param[button_id])); - }); - context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); - }); + for (auto* controller_box : player_controller) { + controller_box->addItems( + {"Pro Controller", "Dual Joycons", "Single Right Joycon", "Single Left Joycon"}); } - for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { - for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { - if (!analog_map_buttons[analog_id][sub_button_id]) - continue; - analog_map_buttons[analog_id][sub_button_id]->setContextMenuPolicy( - Qt::CustomContextMenu); - connect(analog_map_buttons[analog_id][sub_button_id], &QPushButton::released, [=]() { - handleClick(analog_map_buttons[analog_id][sub_button_id], - [=](const Common::ParamPackage& params) { - SetAnalogButton(params, analogs_param[analog_id], - analog_sub_buttons[sub_button_id]); - }, - InputCommon::Polling::DeviceType::Button); - }); - connect(analog_map_buttons[analog_id][sub_button_id], - &QPushButton::customContextMenuRequested, [=](const QPoint& menu_location) { - QMenu context_menu; - context_menu.addAction(tr("Clear"), [&] { - analogs_param[analog_id].Erase(analog_sub_buttons[sub_button_id]); - analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]")); - }); - context_menu.addAction(tr("Restore Default"), [&] { - Common::ParamPackage params{InputCommon::GenerateKeyboardParam( - Config::default_analogs[analog_id][sub_button_id])}; - SetAnalogButton(params, analogs_param[analog_id], - analog_sub_buttons[sub_button_id]); - analog_map_buttons[analog_id][sub_button_id]->setText(AnalogToText( - analogs_param[analog_id], analog_sub_buttons[sub_button_id])); - }); - context_menu.exec(analog_map_buttons[analog_id][sub_button_id]->mapToGlobal( - menu_location)); - }); - } - connect(analog_map_stick[analog_id], &QPushButton::released, [=]() { - QMessageBox::information(this, tr("Information"), - tr("After pressing OK, first move your joystick horizontally, " - "and then vertically.")); - handleClick( - analog_map_stick[analog_id], - [=](const Common::ParamPackage& params) { analogs_param[analog_id] = params; }, - InputCommon::Polling::DeviceType::Analog); - }); - } - - connect(ui->buttonClearAll, &QPushButton::released, [this] { ClearAll(); }); - connect(ui->buttonRestoreDefaults, &QPushButton::released, [this]() { restoreDefaults(); }); - - timeout_timer->setSingleShot(true); - connect(timeout_timer.get(), &QTimer::timeout, [this]() { setPollingResult({}, true); }); - - connect(poll_timer.get(), &QTimer::timeout, [this]() { - Common::ParamPackage params; - for (auto& poller : device_pollers) { - params = poller->GetNextInput(); - if (params.Has("engine")) { - setPollingResult(params, false); - return; - } - } - }); - this->loadConfiguration(); + updateUIEnabled(); - // TODO(wwylele): enable this when we actually emulate it - ui->buttonHome->setEnabled(false); + connect(ui->restore_defaults_button, &QPushButton::pressed, this, + &ConfigureInput::restoreDefaults); + + for (auto* enabled : players_enabled) + connect(enabled, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled); + connect(ui->use_docked_mode, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled); + connect(ui->handheld_connected, &QCheckBox::stateChanged, this, + &ConfigureInput::updateUIEnabled); + connect(ui->mouse_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled); + connect(ui->keyboard_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled); + connect(ui->debug_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled); + connect(ui->touchscreen_enabled, &QCheckBox::stateChanged, this, + &ConfigureInput::updateUIEnabled); + + for (std::size_t i = 0; i < player_configure.size(); ++i) { + connect(player_configure[i], &QPushButton::pressed, this, + [this, i]() { CallConfigureDialog(i, false); }); + } + + connect(ui->handheld_configure, &QPushButton::pressed, this, + [this]() { CallConfigureDialog(8, false); }); + + connect(ui->debug_configure, &QPushButton::pressed, this, + [this]() { CallConfigureDialog(9, true); }); + + connect(ui->mouse_advanced, &QPushButton::pressed, this, + [this]() { CallConfigureDialog(); }); + + connect(ui->touchscreen_advanced, &QPushButton::pressed, this, + [this]() { CallConfigureDialog(); }); + + ui->use_docked_mode->setEnabled(!Core::System::GetInstance().IsPoweredOn()); +} + +template +void ConfigureInput::CallConfigureDialog(Args... args) { + this->applyConfiguration(); + Dialog dialog(this, args...); + + const auto res = dialog.exec(); + if (res == QDialog::Accepted) { + dialog.applyConfiguration(); + } } void ConfigureInput::applyConfiguration() { - std::transform(buttons_param.begin(), buttons_param.end(), Settings::values.buttons.begin(), - [](const Common::ParamPackage& param) { return param.Serialize(); }); - std::transform(analogs_param.begin(), analogs_param.end(), Settings::values.analogs.begin(), - [](const Common::ParamPackage& param) { return param.Serialize(); }); + for (std::size_t i = 0; i < 8; ++i) { + Settings::values.players[i].connected = players_enabled[i]->isChecked(); + Settings::values.players[i].type = + static_cast(player_controller[i]->currentIndex()); + } + + Settings::values.use_docked_mode = ui->use_docked_mode->isChecked(); + Settings::values.players[8].connected = ui->handheld_connected->isChecked(); + Settings::values.debug_pad_enabled = ui->debug_enabled->isChecked(); + Settings::values.mouse_enabled = ui->mouse_enabled->isChecked(); + Settings::values.keyboard_enabled = ui->keyboard_enabled->isChecked(); + Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked(); +} + +void ConfigureInput::updateUIEnabled() { + for (std::size_t i = 0; i < 8; ++i) { + const auto enabled = players_enabled[i]->checkState() == Qt::Checked; + + player_controller[i]->setEnabled(enabled); + player_configure[i]->setEnabled(enabled); + } + + bool hit_disabled = false; + for (auto* player : players_enabled) { + if (hit_disabled) + player->setDisabled(true); + else + player->setEnabled(true); + if (!player->isChecked()) + hit_disabled = true; + } + + ui->handheld_connected->setEnabled(!ui->use_docked_mode->isChecked()); + ui->handheld_configure->setEnabled(ui->handheld_connected->isChecked() && + !ui->use_docked_mode->isChecked()); + ui->mouse_advanced->setEnabled(ui->mouse_enabled->isChecked()); + ui->debug_configure->setEnabled(ui->debug_enabled->isChecked()); + ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked()); } void ConfigureInput::loadConfiguration() { - std::transform(Settings::values.buttons.begin(), Settings::values.buttons.end(), - buttons_param.begin(), - [](const std::string& str) { return Common::ParamPackage(str); }); - std::transform(Settings::values.analogs.begin(), Settings::values.analogs.end(), - analogs_param.begin(), - [](const std::string& str) { return Common::ParamPackage(str); }); - updateButtonLabels(); + std::stable_partition(Settings::values.players.begin(), Settings::values.players.end(), + [](const auto& player) { return player.connected; }); + + for (std::size_t i = 0; i < 8; ++i) { + players_enabled[i]->setChecked(Settings::values.players[i].connected); + player_controller[i]->setCurrentIndex(static_cast(Settings::values.players[i].type)); + } + + ui->use_docked_mode->setChecked(Settings::values.use_docked_mode); + ui->handheld_connected->setChecked(Settings::values.players[8].connected); + ui->debug_enabled->setChecked(Settings::values.debug_pad_enabled); + ui->mouse_enabled->setChecked(Settings::values.mouse_enabled); + ui->keyboard_enabled->setChecked(Settings::values.keyboard_enabled); + ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled); + + updateUIEnabled(); } void ConfigureInput::restoreDefaults() { - for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) { - buttons_param[button_id] = Common::ParamPackage{ - InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; + players_enabled[0]->setCheckState(Qt::Checked); + player_controller[0]->setCurrentIndex(1); + + for (std::size_t i = 1; i < 8; ++i) { + players_enabled[i]->setCheckState(Qt::Unchecked); + player_controller[i]->setCurrentIndex(0); } - for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { - for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { - Common::ParamPackage params{InputCommon::GenerateKeyboardParam( - Config::default_analogs[analog_id][sub_button_id])}; - SetAnalogButton(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]); - } - } - updateButtonLabels(); -} - -void ConfigureInput::ClearAll() { - for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) { - if (button_map[button_id] && button_map[button_id]->isEnabled()) - buttons_param[button_id].Clear(); - } - for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { - for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { - if (analog_map_buttons[analog_id][sub_button_id] && - analog_map_buttons[analog_id][sub_button_id]->isEnabled()) - analogs_param[analog_id].Erase(analog_sub_buttons[sub_button_id]); - } - } - updateButtonLabels(); -} - -void ConfigureInput::updateButtonLabels() { - for (int button = 0; button < Settings::NativeButton::NumButtons; button++) { - button_map[button]->setText(ButtonToText(buttons_param[button])); - } - - for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { - for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { - if (analog_map_buttons[analog_id][sub_button_id]) { - analog_map_buttons[analog_id][sub_button_id]->setText( - AnalogToText(analogs_param[analog_id], analog_sub_buttons[sub_button_id])); - } - } - analog_map_stick[analog_id]->setText(tr("Set Analog Stick")); - } -} - -void ConfigureInput::handleClick(QPushButton* button, - std::function new_input_setter, - InputCommon::Polling::DeviceType type) { - button->setText(tr("[press key]")); - button->setFocus(); - - input_setter = new_input_setter; - - device_pollers = InputCommon::Polling::GetPollers(type); - - // Keyboard keys can only be used as button devices - want_keyboard_keys = type == InputCommon::Polling::DeviceType::Button; - - for (auto& poller : device_pollers) { - poller->Start(); - } - - grabKeyboard(); - grabMouse(); - timeout_timer->start(5000); // Cancel after 5 seconds - poll_timer->start(200); // Check for new inputs every 200ms -} - -void ConfigureInput::setPollingResult(const Common::ParamPackage& params, bool abort) { - releaseKeyboard(); - releaseMouse(); - timeout_timer->stop(); - poll_timer->stop(); - for (auto& poller : device_pollers) { - poller->Stop(); - } - - if (!abort) { - (*input_setter)(params); - } - - updateButtonLabels(); - input_setter = {}; -} - -void ConfigureInput::keyPressEvent(QKeyEvent* event) { - if (!input_setter || !event) - return; - - if (event->key() != Qt::Key_Escape) { - if (want_keyboard_keys) { - setPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, - false); - } else { - // Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling - return; - } - } - setPollingResult({}, true); + ui->use_docked_mode->setCheckState(Qt::Unchecked); + ui->handheld_connected->setCheckState(Qt::Unchecked); + ui->mouse_enabled->setCheckState(Qt::Unchecked); + ui->keyboard_enabled->setCheckState(Qt::Unchecked); + ui->debug_enabled->setCheckState(Qt::Unchecked); + ui->touchscreen_enabled->setCheckState(Qt::Checked); + updateUIEnabled(); } diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h index 32c7183f9..0ba77c5ef 100644 --- a/src/yuzu/configuration/configure_input.h +++ b/src/yuzu/configuration/configure_input.h @@ -18,6 +18,7 @@ #include "core/settings.h" #include "input_common/main.h" #include "ui_configure_input.h" +#include "yuzu/configuration/config.h" class QPushButton; class QString; @@ -37,57 +38,19 @@ public: void applyConfiguration(); private: - std::unique_ptr ui; + void updateUIEnabled(); - std::unique_ptr timeout_timer; - std::unique_ptr poll_timer; - - /// This will be the the setting function when an input is awaiting configuration. - std::optional> input_setter; - - std::array buttons_param; - std::array analogs_param; - - static constexpr int ANALOG_SUB_BUTTONS_NUM = 5; - - /// Each button input is represented by a QPushButton. - std::array button_map; - - /// A group of five QPushButtons represent one analog input. The buttons each represent up, - /// down, left, right, and modifier, respectively. - std::array, Settings::NativeAnalog::NumAnalogs> - analog_map_buttons; - - /// Analog inputs are also represented each with a single button, used to configure with an - /// actual analog stick - std::array analog_map_stick; - - static const std::array analog_sub_buttons; - - std::vector> device_pollers; - - /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false, - /// keyboard events are ignored. - bool want_keyboard_keys = false; + template + void CallConfigureDialog(Args... args); /// Load configuration settings. void loadConfiguration(); /// Restore all buttons to their default values. void restoreDefaults(); - /// Clear all input configuration - void ClearAll(); - /// Update UI to reflect current configuration. - void updateButtonLabels(); + std::unique_ptr ui; - /// Called when the button was pressed. - void handleClick(QPushButton* button, - std::function new_input_setter, - InputCommon::Polling::DeviceType type); - - /// Finish polling and configure input using the input_setter - void setPollingResult(const Common::ParamPackage& params, bool abort); - - /// Handle key press events. - void keyPressEvent(QKeyEvent* event) override; + std::array players_enabled; + std::array player_controller; + std::array player_configure; }; diff --git a/src/yuzu/configuration/configure_input.ui b/src/yuzu/configuration/configure_input.ui index 8a019a693..f12896b47 100644 --- a/src/yuzu/configuration/configure_input.ui +++ b/src/yuzu/configuration/configure_input.ui @@ -6,7 +6,7 @@ 0 0 - 343 + 473 677 @@ -15,740 +15,474 @@ - - - + + + - Misc. + Players - - false - - - false - - - - - - - - Minus: - - - - - - - - - - - + + + + + + 110 + 0 + + + - - - - - - Plus: - - - - - - - - - - - + + + + Configure + + - - - - - - Home: - - - - - - - - - - - + + + + Controller Type + + + Qt::AlignCenter + + - - - - - Screen -Capture: - - - - - - - - - - - + + + Player 1 + + + + + + + Player 7 + + + + + + + Player 4 + + + + + + + Player 5 + + + + + + + Player 6 + + + + + + + Player 8 + + + + + + + Player 3 + + - + + + Player 2 + + + + + + + + 110 + 0 + + + + + + + + + 110 + 0 + + + + + + + + + 110 + 0 + + + + + + + + + 110 + 0 + + + + + + + + + 110 + 0 + + + + + + + + + 110 + 0 + + + + + + + + + 110 + 0 + + + + + + + + Configure + + + + + + + Configure + + + + + + + Configure + + + + + + + Configure + + + + + + + Configure + + + + + + + Configure + + + + + + + Configure + + + + + - Qt::Vertical + Qt::Horizontal - 20 - 40 + 40 + 20 - - - - - - - Face Buttons - - - false - - - false - - - - - - - - A: - - - - - - - - - - - + + + + Qt::Horizontal + + + + 40 + 20 + + + - - - - - B: - - - - - - - - - - - - - - - - - - X: - - - - - - - - - - - - - - - - - - Y: - - - - - - - - - - - + + + Enabled + + + Qt::AlignCenter + + - - + + - Directional Pad - - - false - - - false + Handheld + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 72 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Configure + + + - - - - - Up: - - - - - - - - - - - + + + Qt::Horizontal + + + + 40 + 20 + + + - - - - - Down: - - - - - - - - - - - - - - - - - - Left: - - - - - - - - - - - + + + Connected + + - - - - - Right: - - - - - - - - - - - + + + Use Docked Mode + + - - + + - Shoulder Buttons - - - false - - - false + Other - - - - - - L: - - - - - - - - - - - - - - - - - - R: - - - - - - - - - - - - - - - - - - ZL: - - - - - - - - - - - - - - - - - ZR: - - - - - - - - - - - - - - - - - - SL: - - - - - - - - - - - - - - - - - - SR: - - - - - - - - - - - - - - - - - - - Right Stick - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - false - - - false - - - - - - - - Down: - - - - - - - - - - - - - - - - - - Right: - - - - - - - - - - - - - - + + + + 0 + 23 + + - Set Analog Stick + Keyboard - - - - - - Left: - - - - - - - - - - - - - - - - - - Up: - - - - - - - - - - - - - - - - - - Pressed: - - - - - - - - - - - - - - - - - Modifier: - - - - - - - - - - - - - - - - - - - Left Stick - - - false - - - false - - - - - - - - Down: - - - - - - - - - - - - - - + - Set Analog Stick + Debug Controller - - - - - - Right: - - - - - - - - - - - - - - - - - - Left: - - - - - - - - - - - - - - - - - - Up: - - - - - - - - - - - - - - - - - - Modifier: - - - - - - - - - - - - - - - - - Pressed: - - - - - - - - - - - + + + Touchscreen + + + + + + + + 0 + 23 + + + + Mouse + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 76 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Advanced + + + + + + + Configure + + + + + + + Advanced + + - - - - - + - Qt::Horizontal + Qt::Vertical - 40 - 20 + 20 + 40 - - - - 0 - 0 - - - - - 0 - 0 - - - - - 0 - 0 - - - - Qt::LeftToRight - - - Clear All - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 0 - 0 - - - - Qt::LeftToRight - - - Restore Defaults - - + + + + + Restore Defaults + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + From 2e1dd9c64939a1af43d0a77c63340e88d19f7e61 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 1 Nov 2018 22:07:46 -0400 Subject: [PATCH 19/26] qt: Add UI to configure mouse buttons Supports setting the five mouse buttons to any valid controller button/keyboard key (Left, Right, Middle, Foward, Back) --- src/yuzu/CMakeLists.txt | 3 + .../configure_mouse_advanced.cpp | 211 ++++++++++++++ .../configuration/configure_mouse_advanced.h | 67 +++++ .../configuration/configure_mouse_advanced.ui | 261 ++++++++++++++++++ 4 files changed, 542 insertions(+) create mode 100644 src/yuzu/configuration/configure_mouse_advanced.cpp create mode 100644 src/yuzu/configuration/configure_mouse_advanced.h create mode 100644 src/yuzu/configuration/configure_mouse_advanced.ui diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index f9ca2948e..36714f55e 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -27,6 +27,8 @@ add_executable(yuzu configuration/configure_graphics.h configuration/configure_input.cpp configuration/configure_input.h + configuration/configure_mouse_advanced.cpp + configuration/configure_mouse_advanced.h configuration/configure_system.cpp configuration/configure_system.h configuration/configure_web.cpp @@ -76,6 +78,7 @@ set(UIS configuration/configure_general.ui configuration/configure_graphics.ui configuration/configure_input.ui + configuration/configure_mouse_advanced.ui configuration/configure_system.ui configuration/configure_web.ui hotkeys.ui diff --git a/src/yuzu/configuration/configure_mouse_advanced.cpp b/src/yuzu/configuration/configure_mouse_advanced.cpp new file mode 100644 index 000000000..8cfcd1679 --- /dev/null +++ b/src/yuzu/configuration/configure_mouse_advanced.cpp @@ -0,0 +1,211 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include +#include +#include +#include +#include +#include +#include "common/assert.h" +#include "common/param_package.h" +#include "input_common/main.h" +#include "ui_configure_mouse_advanced.h" +#include "yuzu/configuration/config.h" +#include "yuzu/configuration/configure_mouse_advanced.h" + +static QString getKeyName(int key_code) { + switch (key_code) { + case Qt::Key_Shift: + return QObject::tr("Shift"); + case Qt::Key_Control: + return QObject::tr("Ctrl"); + case Qt::Key_Alt: + return QObject::tr("Alt"); + case Qt::Key_Meta: + return ""; + default: + return QKeySequence(key_code).toString(); + } +} + +static QString ButtonToText(const Common::ParamPackage& param) { + if (!param.Has("engine")) { + return QObject::tr("[not set]"); + } else if (param.Get("engine", "") == "keyboard") { + return getKeyName(param.Get("code", 0)); + } else if (param.Get("engine", "") == "sdl") { + if (param.Has("hat")) { + return QString(QObject::tr("Hat %1 %2")) + .arg(param.Get("hat", "").c_str(), param.Get("direction", "").c_str()); + } + if (param.Has("axis")) { + return QString(QObject::tr("Axis %1%2")) + .arg(param.Get("axis", "").c_str(), param.Get("direction", "").c_str()); + } + if (param.Has("button")) { + return QString(QObject::tr("Button %1")).arg(param.Get("button", "").c_str()); + } + return QString(); + } else { + return QObject::tr("[unknown]"); + } +} + +ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent) + : QDialog(parent), ui(std::make_unique()), + timeout_timer(std::make_unique()), poll_timer(std::make_unique()) { + ui->setupUi(this); + setFocusPolicy(Qt::ClickFocus); + + button_map = { + ui->left_button, ui->right_button, ui->middle_button, ui->forward_button, ui->back_button, + }; + + for (int button_id = 0; button_id < Settings::NativeMouseButton::NumMouseButtons; button_id++) { + if (!button_map[button_id]) + continue; + button_map[button_id]->setContextMenuPolicy(Qt::CustomContextMenu); + connect(button_map[button_id], &QPushButton::released, [=]() { + handleClick( + button_map[button_id], + [=](const Common::ParamPackage& params) { buttons_param[button_id] = params; }, + InputCommon::Polling::DeviceType::Button); + }); + connect(button_map[button_id], &QPushButton::customContextMenuRequested, + [=](const QPoint& menu_location) { + QMenu context_menu; + context_menu.addAction(tr("Clear"), [&] { + buttons_param[button_id].Clear(); + button_map[button_id]->setText(tr("[not set]")); + }); + context_menu.addAction(tr("Restore Default"), [&] { + buttons_param[button_id] = + Common::ParamPackage{InputCommon::GenerateKeyboardParam( + Config::default_mouse_buttons[button_id])}; + button_map[button_id]->setText(ButtonToText(buttons_param[button_id])); + }); + context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); + }); + } + + connect(ui->buttonClearAll, &QPushButton::released, [this] { ClearAll(); }); + connect(ui->buttonRestoreDefaults, &QPushButton::released, [this]() { restoreDefaults(); }); + + timeout_timer->setSingleShot(true); + connect(timeout_timer.get(), &QTimer::timeout, [this]() { setPollingResult({}, true); }); + + connect(poll_timer.get(), &QTimer::timeout, [this]() { + Common::ParamPackage params; + for (auto& poller : device_pollers) { + params = poller->GetNextInput(); + if (params.Has("engine")) { + setPollingResult(params, false); + return; + } + } + }); + + loadConfiguration(); + resize(0, 0); +} + +void ConfigureMouseAdvanced::applyConfiguration() { + std::transform(buttons_param.begin(), buttons_param.end(), + Settings::values.mouse_buttons.begin(), + [](const Common::ParamPackage& param) { return param.Serialize(); }); +} + +void ConfigureMouseAdvanced::loadConfiguration() { + std::transform(Settings::values.mouse_buttons.begin(), Settings::values.mouse_buttons.end(), + buttons_param.begin(), + [](const std::string& str) { return Common::ParamPackage(str); }); + updateButtonLabels(); +} + +void ConfigureMouseAdvanced::restoreDefaults() { + for (int button_id = 0; button_id < Settings::NativeMouseButton::NumMouseButtons; button_id++) { + buttons_param[button_id] = Common::ParamPackage{ + InputCommon::GenerateKeyboardParam(Config::default_mouse_buttons[button_id])}; + } + + updateButtonLabels(); +} + +void ConfigureMouseAdvanced::ClearAll() { + for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { + if (button_map[i] && button_map[i]->isEnabled()) + buttons_param[i].Clear(); + } + + updateButtonLabels(); +} + +void ConfigureMouseAdvanced::updateButtonLabels() { + for (int button = 0; button < Settings::NativeMouseButton::NumMouseButtons; button++) { + button_map[button]->setText(ButtonToText(buttons_param[button])); + } +} + +void ConfigureMouseAdvanced::handleClick( + QPushButton* button, std::function new_input_setter, + InputCommon::Polling::DeviceType type) { + button->setText(tr("[press key]")); + button->setFocus(); + + const auto iter = std::find(button_map.begin(), button_map.end(), button); + ASSERT(iter != button_map.end()); + const auto index = std::distance(button_map.begin(), iter); + ASSERT(index < Settings::NativeButton::NumButtons && index >= 0); + + input_setter = new_input_setter; + + device_pollers = InputCommon::Polling::GetPollers(type); + + // Keyboard keys can only be used as button devices + want_keyboard_keys = type == InputCommon::Polling::DeviceType::Button; + + for (auto& poller : device_pollers) { + poller->Start(); + } + + grabKeyboard(); + grabMouse(); + timeout_timer->start(5000); // Cancel after 5 seconds + poll_timer->start(200); // Check for new inputs every 200ms +} + +void ConfigureMouseAdvanced::setPollingResult(const Common::ParamPackage& params, bool abort) { + releaseKeyboard(); + releaseMouse(); + timeout_timer->stop(); + poll_timer->stop(); + for (auto& poller : device_pollers) { + poller->Stop(); + } + + if (!abort) { + (*input_setter)(params); + } + + updateButtonLabels(); + input_setter = boost::none; +} + +void ConfigureMouseAdvanced::keyPressEvent(QKeyEvent* event) { + if (!input_setter || !event) + return; + + if (event->key() != Qt::Key_Escape) { + if (want_keyboard_keys) { + setPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, + false); + } else { + // Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling + return; + } + } + setPollingResult({}, true); +} diff --git a/src/yuzu/configuration/configure_mouse_advanced.h b/src/yuzu/configuration/configure_mouse_advanced.h new file mode 100644 index 000000000..f897d9044 --- /dev/null +++ b/src/yuzu/configuration/configure_mouse_advanced.h @@ -0,0 +1,67 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include +#include +#include "core/settings.h" + +class QCheckBox; +class QPushButton; +class QTimer; + +namespace Ui { +class ConfigureMouseAdvanced; +} + +class ConfigureMouseAdvanced : public QDialog { + Q_OBJECT + +public: + explicit ConfigureMouseAdvanced(QWidget* parent); + + void applyConfiguration(); + +private: + std::unique_ptr ui; + + /// This will be the the setting function when an input is awaiting configuration. + boost::optional> input_setter; + + std::array button_map; + std::array buttons_param; + + std::vector> device_pollers; + + std::unique_ptr timeout_timer; + std::unique_ptr poll_timer; + + /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false, + /// keyboard events are ignored. + bool want_keyboard_keys = false; + + /// Load configuration settings. + void loadConfiguration(); + /// Restore all buttons to their default values. + void restoreDefaults(); + /// Clear all input configuration + void ClearAll(); + + /// Update UI to reflect current configuration. + void updateButtonLabels(); + + /// Called when the button was pressed. + void handleClick(QPushButton* button, + std::function new_input_setter, + InputCommon::Polling::DeviceType type); + + /// Finish polling and configure input using the input_setter + void setPollingResult(const Common::ParamPackage& params, bool abort); + + /// Handle key press events. + void keyPressEvent(QKeyEvent* event) override; +}; diff --git a/src/yuzu/configuration/configure_mouse_advanced.ui b/src/yuzu/configuration/configure_mouse_advanced.ui new file mode 100644 index 000000000..08245ecf0 --- /dev/null +++ b/src/yuzu/configuration/configure_mouse_advanced.ui @@ -0,0 +1,261 @@ + + + ConfigureMouseAdvanced + + + + 0 + 0 + 250 + 261 + + + + Configure Mouse + + + + + + Mouse Buttons + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + + + + Right: + + + + + + + + + + 75 + 0 + + + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + + + + Middle: + + + + + + + + + + + + + + + + + + + + + + + 54 + 0 + + + + Back: + + + + + + + + + + + + + + + + + + + + + + Left: + + + + + + + + + + 75 + 0 + + + + + + + + + + + + + + + + + Forward: + + + + + + + + + + + + + + + + + + + + + + + Clear All + + + + + + + Restore Defaults + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + ConfigureMouseAdvanced + accept() + + + 124 + 266 + + + 124 + 143 + + + + + buttonBox + rejected() + ConfigureMouseAdvanced + reject() + + + 124 + 266 + + + 124 + 143 + + + + + From afe8df5020d575ee361078aa3bd52706f818dee4 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 1 Nov 2018 22:10:51 -0400 Subject: [PATCH 20/26] qt: Add UI to configure touchscreen parameters This allows adjusting the finger, diameter, and angle of the emulated touchscreen. It also provides a warning to the user about what changing these parameters can do. --- src/yuzu/CMakeLists.txt | 3 + .../configure_touchscreen_advanced.cpp | 48 +++++ .../configure_touchscreen_advanced.h | 31 +++ .../configure_touchscreen_advanced.ui | 199 ++++++++++++++++++ 4 files changed, 281 insertions(+) create mode 100644 src/yuzu/configuration/configure_touchscreen_advanced.cpp create mode 100644 src/yuzu/configuration/configure_touchscreen_advanced.h create mode 100644 src/yuzu/configuration/configure_touchscreen_advanced.ui diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 36714f55e..ff06d2a9a 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -31,6 +31,8 @@ add_executable(yuzu configuration/configure_mouse_advanced.h configuration/configure_system.cpp configuration/configure_system.h + configuration/configure_touchscreen_advanced.cpp + configuration/configure_touchscreen_advanced.h configuration/configure_web.cpp configuration/configure_web.h debugger/graphics/graphics_breakpoint_observer.cpp @@ -80,6 +82,7 @@ set(UIS configuration/configure_input.ui configuration/configure_mouse_advanced.ui configuration/configure_system.ui + configuration/configure_touchscreen_advanced.ui configuration/configure_web.ui hotkeys.ui main.ui diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.cpp b/src/yuzu/configuration/configure_touchscreen_advanced.cpp new file mode 100644 index 000000000..6cf3dab97 --- /dev/null +++ b/src/yuzu/configuration/configure_touchscreen_advanced.cpp @@ -0,0 +1,48 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include +#include +#include +#include +#include +#include "common/assert.h" +#include "common/param_package.h" +#include "input_common/main.h" +#include "ui_configure_touchscreen_advanced.h" +#include "yuzu/configuration/config.h" +#include "yuzu/configuration/configure_touchscreen_advanced.h" + +ConfigureTouchscreenAdvanced::ConfigureTouchscreenAdvanced(QWidget* parent) + : QDialog(parent), ui(std::make_unique()) { + ui->setupUi(this); + + connect(ui->restore_defaults_button, &QPushButton::pressed, this, + &ConfigureTouchscreenAdvanced::restoreDefaults); + + this->loadConfiguration(); + this->resize(0, 0); +} + +void ConfigureTouchscreenAdvanced::applyConfiguration() { + Settings::values.touchscreen.finger = ui->finger_box->value(); + Settings::values.touchscreen.diameter_x = ui->diameter_x_box->value(); + Settings::values.touchscreen.diameter_y = ui->diameter_y_box->value(); + Settings::values.touchscreen.rotation_angle = ui->angle_box->value(); +} + +void ConfigureTouchscreenAdvanced::loadConfiguration() { + ui->finger_box->setValue(Settings::values.touchscreen.finger); + ui->diameter_x_box->setValue(Settings::values.touchscreen.diameter_x); + ui->diameter_y_box->setValue(Settings::values.touchscreen.diameter_y); + ui->angle_box->setValue(Settings::values.touchscreen.rotation_angle); +} + +void ConfigureTouchscreenAdvanced::restoreDefaults() { + ui->finger_box->setValue(0); + ui->diameter_x_box->setValue(15); + ui->diameter_y_box->setValue(15); + ui->angle_box->setValue(0); +} diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.h b/src/yuzu/configuration/configure_touchscreen_advanced.h new file mode 100644 index 000000000..938a62ed3 --- /dev/null +++ b/src/yuzu/configuration/configure_touchscreen_advanced.h @@ -0,0 +1,31 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include +#include "yuzu/configuration/config.h" + +namespace Ui { +class ConfigureTouchscreenAdvanced; +} + +class ConfigureTouchscreenAdvanced : public QDialog { + Q_OBJECT + +public: + explicit ConfigureTouchscreenAdvanced(QWidget* parent); + + void applyConfiguration(); + +private: + /// Load configuration settings. + void loadConfiguration(); + /// Restore all buttons to their default values. + void restoreDefaults(); + + std::unique_ptr ui; +}; diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.ui b/src/yuzu/configuration/configure_touchscreen_advanced.ui new file mode 100644 index 000000000..1171c2dd1 --- /dev/null +++ b/src/yuzu/configuration/configure_touchscreen_advanced.ui @@ -0,0 +1,199 @@ + + + ConfigureTouchscreenAdvanced + + + + 0 + 0 + 298 + 339 + + + + Configure Touchscreen + + + + + + + 280 + 0 + + + + Warning: The settings in this page affect the inner workings of yuzu's emulated touchscreen. Changing them may result in undesirable behavior, such as the touchscreen partially or not working. You should only use this page if you know what you are doing. + + + true + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + Touch Parameters + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Touch Diameter Y + + + + + + + Finger + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Touch Diameter X + + + + + + + + 80 + 0 + + + + + + + + Rotational Angle + + + + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Restore Defaults + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + ConfigureTouchscreenAdvanced + accept() + + + 140 + 318 + + + 140 + 169 + + + + + buttonBox + rejected() + ConfigureTouchscreenAdvanced + reject() + + + 140 + 318 + + + 140 + 169 + + + + + From 3d1a221893127f2be317d9237d26c607a4b736e1 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 1 Nov 2018 22:11:44 -0400 Subject: [PATCH 21/26] qt: Move controller button config to separate dialog Handles button configuration for all controller layouts and debug pads. Configurable at construction. --- src/yuzu/CMakeLists.txt | 3 + .../configuration/configure_input_player.cpp | 506 ++++++++ .../configuration/configure_input_player.h | 102 ++ .../configuration/configure_input_player.ui | 1156 +++++++++++++++++ 4 files changed, 1767 insertions(+) create mode 100644 src/yuzu/configuration/configure_input_player.cpp create mode 100644 src/yuzu/configuration/configure_input_player.h create mode 100644 src/yuzu/configuration/configure_input_player.ui diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index ff06d2a9a..34f36f06b 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -27,6 +27,8 @@ add_executable(yuzu configuration/configure_graphics.h configuration/configure_input.cpp configuration/configure_input.h + configuration/configure_input_player.cpp + configuration/configure_input_player.h configuration/configure_mouse_advanced.cpp configuration/configure_mouse_advanced.h configuration/configure_system.cpp @@ -80,6 +82,7 @@ set(UIS configuration/configure_general.ui configuration/configure_graphics.ui configuration/configure_input.ui + configuration/configure_input_player.ui configuration/configure_mouse_advanced.ui configuration/configure_system.ui configuration/configure_touchscreen_advanced.ui diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp new file mode 100644 index 000000000..5de7dd962 --- /dev/null +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -0,0 +1,506 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include +#include +#include +#include +#include +#include +#include "common/assert.h" +#include "common/param_package.h" +#include "input_common/main.h" +#include "ui_configure_input_player.h" +#include "yuzu/configuration/config.h" +#include "yuzu/configuration/configure_input_player.h" + +const std::array + ConfigureInputPlayer::analog_sub_buttons{{ + "up", + "down", + "left", + "right", + "modifier", + }}; + +static void MoveGridElement(QGridLayout* grid, int row_old, int column_old, int row_new, + int column_new) { + const auto item = grid->itemAtPosition(row_old, column_old); + // grid->removeItem(item); + grid->addItem(item, row_new, column_new); +} + +static void LayerGridElements(QGridLayout* grid, QWidget* item, QWidget* onTopOf) { + const int index1 = grid->indexOf(item); + const int index2 = grid->indexOf(onTopOf); + int row, column, rowSpan, columnSpan; + grid->getItemPosition(index2, &row, &column, &rowSpan, &columnSpan); + grid->takeAt(index1); + grid->addWidget(item, row, column, rowSpan, columnSpan); +} + +static QString getKeyName(int key_code) { + switch (key_code) { + case Qt::Key_Shift: + return QObject::tr("Shift"); + case Qt::Key_Control: + return QObject::tr("Ctrl"); + case Qt::Key_Alt: + return QObject::tr("Alt"); + case Qt::Key_Meta: + return ""; + default: + return QKeySequence(key_code).toString(); + } +} + +static void SetAnalogButton(const Common::ParamPackage& input_param, + Common::ParamPackage& analog_param, const std::string& button_name) { + if (analog_param.Get("engine", "") != "analog_from_button") { + analog_param = { + {"engine", "analog_from_button"}, + {"modifier_scale", "0.5"}, + }; + } + analog_param.Set(button_name, input_param.Serialize()); +} + +static QString ButtonToText(const Common::ParamPackage& param) { + if (!param.Has("engine")) { + return QObject::tr("[not set]"); + } else if (param.Get("engine", "") == "keyboard") { + return getKeyName(param.Get("code", 0)); + } else if (param.Get("engine", "") == "sdl") { + if (param.Has("hat")) { + return QString(QObject::tr("Hat %1 %2")) + .arg(param.Get("hat", "").c_str(), param.Get("direction", "").c_str()); + } + if (param.Has("axis")) { + return QString(QObject::tr("Axis %1%2")) + .arg(param.Get("axis", "").c_str(), param.Get("direction", "").c_str()); + } + if (param.Has("button")) { + return QString(QObject::tr("Button %1")).arg(param.Get("button", "").c_str()); + } + return QString(); + } else { + return QObject::tr("[unknown]"); + } +}; + +static QString AnalogToText(const Common::ParamPackage& param, const std::string& dir) { + if (!param.Has("engine")) { + return QObject::tr("[not set]"); + } else if (param.Get("engine", "") == "analog_from_button") { + return ButtonToText(Common::ParamPackage{param.Get(dir, "")}); + } else if (param.Get("engine", "") == "sdl") { + if (dir == "modifier") { + return QString(QObject::tr("[unused]")); + } + + if (dir == "left" || dir == "right") { + return QString(QObject::tr("Axis %1")).arg(param.Get("axis_x", "").c_str()); + } else if (dir == "up" || dir == "down") { + return QString(QObject::tr("Axis %1")).arg(param.Get("axis_y", "").c_str()); + } + return QString(); + } else { + return QObject::tr("[unknown]"); + } +}; + +ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, u8 player_index, bool debug) + : QDialog(parent), ui(std::make_unique()), + timeout_timer(std::make_unique()), poll_timer(std::make_unique()), + player_index(player_index), debug(debug) { + + ui->setupUi(this); + setFocusPolicy(Qt::ClickFocus); + + button_map = { + ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY, + ui->buttonLStick, ui->buttonRStick, ui->buttonL, ui->buttonR, + ui->buttonZL, ui->buttonZR, ui->buttonPlus, ui->buttonMinus, + ui->buttonDpadLeft, ui->buttonDpadUp, ui->buttonDpadRight, ui->buttonDpadDown, + ui->buttonLStickLeft, ui->buttonLStickUp, ui->buttonLStickRight, ui->buttonLStickDown, + ui->buttonRStickLeft, ui->buttonRStickUp, ui->buttonRStickRight, ui->buttonRStickDown, + ui->buttonSL, ui->buttonSR, ui->buttonHome, ui->buttonScreenshot, + }; + + analog_map_buttons = {{ + { + ui->buttonLStickUp, + ui->buttonLStickDown, + ui->buttonLStickLeft, + ui->buttonLStickRight, + ui->buttonLStickMod, + }, + { + ui->buttonRStickUp, + ui->buttonRStickDown, + ui->buttonRStickLeft, + ui->buttonRStickRight, + ui->buttonRStickMod, + }, + }}; + + debug_hidden = { + ui->buttonSL, ui->labelSL, + ui->buttonSR, ui->labelSR, + ui->buttonLStick, ui->labelLStickPressed, + ui->buttonRStick, ui->labelRStickPressed, + ui->buttonHome, ui->labelHome, + ui->buttonScreenshot, ui->labelScreenshot, + }; + + auto layout = Settings::values.players[player_index].type; + if (debug) + layout = Settings::ControllerType::DualJoycon; + + switch (layout) { + case Settings::ControllerType::ProController: + case Settings::ControllerType::DualJoycon: + layout_hidden = { + ui->buttonSL, + ui->labelSL, + ui->buttonSR, + ui->labelSR, + }; + break; + case Settings::ControllerType::LeftJoycon: + layout_hidden = { + ui->right_body_button, + ui->right_buttons_button, + ui->right_body_label, + ui->right_buttons_label, + ui->buttonR, + ui->labelR, + ui->buttonZR, + ui->labelZR, + ui->labelHome, + ui->buttonHome, + ui->buttonPlus, + ui->labelPlus, + ui->RStick, + ui->faceButtons, + }; + break; + case Settings::ControllerType::RightJoycon: + layout_hidden = { + ui->left_body_button, ui->left_buttons_button, + ui->left_body_label, ui->left_buttons_label, + ui->buttonL, ui->labelL, + ui->buttonZL, ui->labelZL, + ui->labelScreenshot, ui->buttonScreenshot, + ui->buttonMinus, ui->labelMinus, + ui->LStick, ui->Dpad, + }; + break; + } + + if (debug || layout == Settings::ControllerType::ProController) { + ui->controller_color->hide(); + } else { + if (layout == Settings::ControllerType::LeftJoycon || + layout == Settings::ControllerType::RightJoycon) { + ui->horizontalSpacer_4->setGeometry({0, 0, 0, 0}); + + LayerGridElements(ui->buttons, ui->shoulderButtons, ui->Dpad); + LayerGridElements(ui->buttons, ui->misc, ui->RStick); + LayerGridElements(ui->buttons, ui->Dpad, ui->faceButtons); + LayerGridElements(ui->buttons, ui->RStick, ui->LStick); + } + } + + for (auto* widget : layout_hidden) + widget->setVisible(false); + + analog_map_stick = {ui->buttonLStickAnalog, ui->buttonRStickAnalog}; + + for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) { + if (!button_map[button_id]) + continue; + button_map[button_id]->setContextMenuPolicy(Qt::CustomContextMenu); + connect(button_map[button_id], &QPushButton::released, [=]() { + handleClick( + button_map[button_id], + [=](const Common::ParamPackage& params) { buttons_param[button_id] = params; }, + InputCommon::Polling::DeviceType::Button); + }); + connect(button_map[button_id], &QPushButton::customContextMenuRequested, + [=](const QPoint& menu_location) { + QMenu context_menu; + context_menu.addAction(tr("Clear"), [&] { + buttons_param[button_id].Clear(); + button_map[button_id]->setText(tr("[not set]")); + }); + context_menu.addAction(tr("Restore Default"), [&] { + buttons_param[button_id] = Common::ParamPackage{ + InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; + button_map[button_id]->setText(ButtonToText(buttons_param[button_id])); + }); + context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); + }); + } + + for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { + for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { + if (!analog_map_buttons[analog_id][sub_button_id]) + continue; + analog_map_buttons[analog_id][sub_button_id]->setContextMenuPolicy( + Qt::CustomContextMenu); + connect(analog_map_buttons[analog_id][sub_button_id], &QPushButton::released, [=]() { + handleClick(analog_map_buttons[analog_id][sub_button_id], + [=](const Common::ParamPackage& params) { + SetAnalogButton(params, analogs_param[analog_id], + analog_sub_buttons[sub_button_id]); + }, + InputCommon::Polling::DeviceType::Button); + }); + connect(analog_map_buttons[analog_id][sub_button_id], + &QPushButton::customContextMenuRequested, [=](const QPoint& menu_location) { + QMenu context_menu; + context_menu.addAction(tr("Clear"), [&] { + analogs_param[analog_id].Erase(analog_sub_buttons[sub_button_id]); + analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]")); + }); + context_menu.addAction(tr("Restore Default"), [&] { + Common::ParamPackage params{InputCommon::GenerateKeyboardParam( + Config::default_analogs[analog_id][sub_button_id])}; + SetAnalogButton(params, analogs_param[analog_id], + analog_sub_buttons[sub_button_id]); + analog_map_buttons[analog_id][sub_button_id]->setText(AnalogToText( + analogs_param[analog_id], analog_sub_buttons[sub_button_id])); + }); + context_menu.exec(analog_map_buttons[analog_id][sub_button_id]->mapToGlobal( + menu_location)); + }); + } + connect(analog_map_stick[analog_id], &QPushButton::released, [=]() { + QMessageBox::information(this, tr("Information"), + tr("After pressing OK, first move your joystick horizontally, " + "and then vertically.")); + handleClick( + analog_map_stick[analog_id], + [=](const Common::ParamPackage& params) { analogs_param[analog_id] = params; }, + InputCommon::Polling::DeviceType::Analog); + }); + } + + connect(ui->buttonClearAll, &QPushButton::released, [this] { ClearAll(); }); + connect(ui->buttonRestoreDefaults, &QPushButton::released, [this]() { restoreDefaults(); }); + + timeout_timer->setSingleShot(true); + connect(timeout_timer.get(), &QTimer::timeout, [this]() { setPollingResult({}, true); }); + + connect(poll_timer.get(), &QTimer::timeout, [this]() { + Common::ParamPackage params; + for (auto& poller : device_pollers) { + params = poller->GetNextInput(); + if (params.Has("engine")) { + setPollingResult(params, false); + return; + } + } + }); + + controller_color_buttons = { + ui->left_body_button, + ui->left_buttons_button, + ui->right_body_button, + ui->right_buttons_button, + }; + + for (std::size_t i = 0; i < controller_color_buttons.size(); ++i) { + connect(controller_color_buttons[i], &QPushButton::clicked, this, + std::bind(&ConfigureInputPlayer::OnControllerButtonClick, this, i)); + } + + this->loadConfiguration(); + this->resize(0, 0); + + // TODO(wwylele): enable this when we actually emulate it + ui->buttonHome->setEnabled(false); +} + +void ConfigureInputPlayer::applyConfiguration() { + auto& buttons = + debug ? Settings::values.debug_pad_buttons : Settings::values.players[player_index].buttons; + auto& analogs = + debug ? Settings::values.debug_pad_analogs : Settings::values.players[player_index].analogs; + + std::transform(buttons_param.begin(), buttons_param.end(), buttons.begin(), + [](const Common::ParamPackage& param) { return param.Serialize(); }); + std::transform(analogs_param.begin(), analogs_param.end(), analogs.begin(), + [](const Common::ParamPackage& param) { return param.Serialize(); }); + + if (debug) + return; + + std::array colors{}; + std::transform(controller_colors.begin(), controller_colors.end(), colors.begin(), + [](QColor color) { return color.rgb(); }); + + Settings::values.players[player_index].body_color_left = colors[0]; + Settings::values.players[player_index].button_color_left = colors[1]; + Settings::values.players[player_index].body_color_right = colors[2]; + Settings::values.players[player_index].button_color_right = colors[3]; +} + +void ConfigureInputPlayer::OnControllerButtonClick(int i) { + const QColor new_bg_color = QColorDialog::getColor(controller_colors[i]); + if (!new_bg_color.isValid()) + return; + controller_colors[i] = new_bg_color; + controller_color_buttons[i]->setStyleSheet( + QString("QPushButton { background-color: %1 }").arg(controller_colors[i].name())); +} + +void ConfigureInputPlayer::loadConfiguration() { + if (debug) { + std::transform(Settings::values.debug_pad_buttons.begin(), + Settings::values.debug_pad_buttons.end(), buttons_param.begin(), + [](const std::string& str) { return Common::ParamPackage(str); }); + std::transform(Settings::values.debug_pad_analogs.begin(), + Settings::values.debug_pad_analogs.end(), analogs_param.begin(), + [](const std::string& str) { return Common::ParamPackage(str); }); + } else { + std::transform(Settings::values.players[player_index].buttons.begin(), + Settings::values.players[player_index].buttons.end(), buttons_param.begin(), + [](const std::string& str) { return Common::ParamPackage(str); }); + std::transform(Settings::values.players[player_index].analogs.begin(), + Settings::values.players[player_index].analogs.end(), analogs_param.begin(), + [](const std::string& str) { return Common::ParamPackage(str); }); + } + + updateButtonLabels(); + + if (debug) + return; + + std::array colors = { + Settings::values.players[player_index].body_color_left, + Settings::values.players[player_index].button_color_left, + Settings::values.players[player_index].body_color_right, + Settings::values.players[player_index].button_color_right, + }; + + std::transform(colors.begin(), colors.end(), controller_colors.begin(), + [](u32 rgb) { return QColor::fromRgb(rgb); }); + + for (std::size_t i = 0; i < colors.size(); ++i) { + controller_color_buttons[i]->setStyleSheet( + QString("QPushButton { background-color: %1 }").arg(controller_colors[i].name())); + } +} + +void ConfigureInputPlayer::restoreDefaults() { + for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) { + buttons_param[button_id] = Common::ParamPackage{ + InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; + } + + for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { + for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { + Common::ParamPackage params{InputCommon::GenerateKeyboardParam( + Config::default_analogs[analog_id][sub_button_id])}; + SetAnalogButton(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]); + } + } + updateButtonLabels(); +} + +void ConfigureInputPlayer::ClearAll() { + for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) { + if (button_map[button_id] && button_map[button_id]->isEnabled()) + buttons_param[button_id].Clear(); + } + for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { + for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { + if (analog_map_buttons[analog_id][sub_button_id] && + analog_map_buttons[analog_id][sub_button_id]->isEnabled()) + analogs_param[analog_id].Erase(analog_sub_buttons[sub_button_id]); + } + } + + updateButtonLabels(); +} + +void ConfigureInputPlayer::updateButtonLabels() { + for (int button = 0; button < Settings::NativeButton::NumButtons; button++) { + button_map[button]->setText(ButtonToText(buttons_param[button])); + } + + for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { + for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { + if (analog_map_buttons[analog_id][sub_button_id]) { + analog_map_buttons[analog_id][sub_button_id]->setText( + AnalogToText(analogs_param[analog_id], analog_sub_buttons[sub_button_id])); + } + } + analog_map_stick[analog_id]->setText(tr("Set Analog Stick")); + } +} + +void ConfigureInputPlayer::handleClick( + QPushButton* button, std::function new_input_setter, + InputCommon::Polling::DeviceType type) { + button->setText(tr("[press key]")); + button->setFocus(); + + const auto iter = std::find(button_map.begin(), button_map.end(), button); + ASSERT(iter != button_map.end()); + const auto index = std::distance(button_map.begin(), iter); + ASSERT(index < Settings::NativeButton::NumButtons && index >= 0); + + input_setter = new_input_setter; + + device_pollers = InputCommon::Polling::GetPollers(type); + + // Keyboard keys can only be used as button devices + want_keyboard_keys = type == InputCommon::Polling::DeviceType::Button; + + for (auto& poller : device_pollers) { + poller->Start(); + } + + grabKeyboard(); + grabMouse(); + timeout_timer->start(5000); // Cancel after 5 seconds + poll_timer->start(200); // Check for new inputs every 200ms +} + +void ConfigureInputPlayer::setPollingResult(const Common::ParamPackage& params, bool abort) { + releaseKeyboard(); + releaseMouse(); + timeout_timer->stop(); + poll_timer->stop(); + for (auto& poller : device_pollers) { + poller->Stop(); + } + + if (!abort) { + (*input_setter)(params); + } + + updateButtonLabels(); + input_setter = boost::none; +} + +void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) { + if (!input_setter || !event) + return; + + if (event->key() != Qt::Key_Escape) { + if (want_keyboard_keys) { + setPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, + false); + } else { + // Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling + return; + } + } + setPollingResult({}, true); +} diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h new file mode 100644 index 000000000..67cc6a8ca --- /dev/null +++ b/src/yuzu/configuration/configure_input_player.h @@ -0,0 +1,102 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include "common/param_package.h" +#include "core/settings.h" +#include "input_common/main.h" +#include "ui_configure_input.h" + +class QPushButton; +class QString; +class QTimer; + +namespace Ui { +class ConfigureInputPlayer; +} + +class ConfigureInputPlayer : public QDialog { + Q_OBJECT + +public: + explicit ConfigureInputPlayer(QWidget* parent, u8 player_index, bool debug = false); + + /// Save all button configurations to settings file + void applyConfiguration(); + +private: + std::unique_ptr ui; + + u8 player_index; + bool debug; + + std::unique_ptr timeout_timer; + std::unique_ptr poll_timer; + + /// This will be the the setting function when an input is awaiting configuration. + boost::optional> input_setter; + + std::array buttons_param; + std::array analogs_param; + + static constexpr int ANALOG_SUB_BUTTONS_NUM = 5; + + /// Each button input is represented by a QPushButton. + std::array button_map; + + std::vector debug_hidden; + std::vector layout_hidden; + + /// A group of five QPushButtons represent one analog input. The buttons each represent up, + /// down, left, right, and modifier, respectively. + std::array, Settings::NativeAnalog::NumAnalogs> + analog_map_buttons; + + /// Analog inputs are also represented each with a single button, used to configure with an + /// actual analog stick + std::array analog_map_stick; + + static const std::array analog_sub_buttons; + + std::vector> device_pollers; + + /// A flag to indicate if keyboard keys are okay when configuring an input. If this is false, + /// keyboard events are ignored. + bool want_keyboard_keys = false; + + std::array controller_color_buttons; + std::array controller_colors; + + void OnControllerButtonClick(int i); + + /// Load configuration settings. + void loadConfiguration(); + /// Restore all buttons to their default values. + void restoreDefaults(); + /// Clear all input configuration + void ClearAll(); + + /// Update UI to reflect current configuration. + void updateButtonLabels(); + + /// Called when the button was pressed. + void handleClick(QPushButton* button, + std::function new_input_setter, + InputCommon::Polling::DeviceType type); + + /// Finish polling and configure input using the input_setter + void setPollingResult(const Common::ParamPackage& params, bool abort); + + /// Handle key press events. + void keyPressEvent(QKeyEvent* event) override; +}; diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui new file mode 100644 index 000000000..191206663 --- /dev/null +++ b/src/yuzu/configuration/configure_input_player.ui @@ -0,0 +1,1156 @@ + + + ConfigureInputPlayer + + + + 0 + 0 + 408 + 731 + + + + Configure Input + + + + + + + + Right Stick + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + false + + + false + + + + + + + + + + Down: + + + + + + + + + + + + + + + + + + + + + + Right: + + + + + + + + + + + + + + + + + + Set Analog Stick + + + + + + + + + + + Left: + + + + + + + + + + + + + + + + + + + + + + Up: + + + + + + + + + + + + + + + + + + + + + + Pressed: + + + + + + + + + + + + + + + + + + + + + + Modifier: + + + + + + + + + + + + + + + + + + + + + Directional Pad + + + false + + + false + + + + + + + + + + Up: + + + + + + + + + + + + + + + + + + + + + + Down: + + + + + + + + + + + + + + + + + + + + + + Left: + + + + + + + + + + + + + + + + + + + + + + Right: + + + + + + + + + + + + + + + + + + + + + Face Buttons + + + false + + + false + + + + + + + + + + A: + + + + + + + + + + + + + + + + + + + + + + B: + + + + + + + + + + + + + + + + + + + + + + X: + + + + + + + + + + + + + + + + + + + + + + Y: + + + + + + + + + + + + + + + + + + + + + Controller Color + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Left Body + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 90 + 0 + + + + Left Buttons + + + + + + + + 0 + 0 + + + + + 32 + 0 + + + + + 40 + 16777215 + + + + + + + + + + + Right Body + + + + + + + + 90 + 0 + + + + Right Buttons + + + + + + + + 0 + 0 + + + + + 32 + 0 + + + + + 40 + 16777215 + + + + + + + + + + + + 0 + 0 + + + + + 32 + 0 + + + + + 40 + 16777215 + + + + + + + + + + + + 0 + 0 + + + + + 32 + 0 + + + + + 40 + 16777215 + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + + + Left Stick + + + false + + + false + + + + + + + + + + Up: + + + + + + + + + + + + + + + + + + + + + + Right: + + + + + + + + + + + + + + + + + + Set Analog Stick + + + + + + + + + + + Left: + + + + + + + + + + + + + + + + + + + + + + Down: + + + + + + + + + + + + + + + + + + + + + + Modifier: + + + + + + + + + + + + + + + + + + + + + + Pressed: + + + + + + + + + + + + + + + + + + + + + Shoulder Buttons + + + false + + + false + + + + + + + + + + SL: + + + + + + + + + + + + + + + + + + + + + + ZR: + + + + + + + + + + + + + + + + + + + + + + SR: + + + + + + + + + + + + + + + + + + + + + + ZL: + + + + + + + + + + + + + + + + + + + + + + L: + + + + + + + + + + + + + + + + + + + + + + R: + + + + + + + + + + + + + + + + + + + + + Misc. + + + false + + + false + + + + + + + + + + Minus: + + + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + Plus: + + + + + + + + + + + + + + + + + + + + + + Home: + + + + + + + + + + + + + + + + + + + + + + Screen Capture: + + + false + + + + + + + + + + 0 + 0 + + + + + 80 + 16777215 + + + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + Check the box to override the global default key with this one for this game only. + + + true + + + + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 0 + 0 + + + + Qt::LeftToRight + + + Clear All + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 0 + 0 + + + + Qt::LeftToRight + + + Restore Defaults + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + ConfigureInputPlayer + accept() + + + 371 + 730 + + + 229 + 375 + + + + + buttonBox + rejected() + ConfigureInputPlayer + reject() + + + 371 + 730 + + + 229 + 375 + + + + + From 3a6cd5b3c8dec11cc88c6aebdc4773233f615c91 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sat, 3 Nov 2018 12:55:39 -0400 Subject: [PATCH 22/26] hid: Use player-defined controller type as PREFERRED_CONTROLLER --- .../hle/service/hid/controllers/keyboard.cpp | 5 +- src/core/hle/service/hid/controllers/npad.cpp | 213 ++++-------------- src/core/hle/service/hid/controllers/npad.h | 11 +- .../service/hid/controllers/touchscreen.cpp | 6 - src/core/settings.cpp | 50 ++++ src/core/settings.h | 44 +--- src/yuzu/configuration/config.cpp | 127 +++++++---- src/yuzu/configuration/config.h | 10 + src/yuzu/configuration/configure_input.cpp | 27 ++- src/yuzu/configuration/configure_input.h | 2 +- .../configuration/configure_input_player.cpp | 6 +- .../configuration/configure_input_player.h | 4 +- .../configure_mouse_advanced.cpp | 6 +- .../configuration/configure_mouse_advanced.h | 4 +- .../configure_touchscreen_advanced.cpp | 14 +- .../configure_touchscreen_advanced.h | 1 + 16 files changed, 234 insertions(+), 296 deletions(-) diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp index 088f00b43..ca75adc2b 100644 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ b/src/core/hle/service/hid/controllers/keyboard.cpp @@ -10,6 +10,7 @@ namespace Service::HID { constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800; +constexpr u8 KEYS_PER_BYTE = 8; Controller_Keyboard::Controller_Keyboard() = default; Controller_Keyboard::~Controller_Keyboard() = default; @@ -37,8 +38,8 @@ void Controller_Keyboard::OnUpdate(u8* data, std::size_t size) { cur_entry.sampling_number2 = cur_entry.sampling_number; for (std::size_t i = 0; i < keyboard_keys.size(); ++i) { - for (std::size_t k = 0; k < 8; ++k) { - cur_entry.key[i / 8] |= (keyboard_keys[i]->GetStatus() << k); + for (std::size_t k = 0; k < KEYS_PER_BYTE; ++k) { + cur_entry.key[i / KEYS_PER_BYTE] |= (keyboard_keys[i]->GetStatus() << k); } } diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 911ba3574..46604887c 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -21,13 +21,9 @@ constexpr s32 HID_JOYSTICK_MAX = 0x7fff; constexpr s32 HID_JOYSTICK_MIN = -0x7fff; constexpr std::size_t NPAD_OFFSET = 0x9A00; constexpr u32 BATTERY_FULL = 2; -constexpr u32 NPAD_HANDHELD = 32; -constexpr u32 NPAD_UNKNOWN = 16; // TODO(ogniK): What is this? constexpr u32 MAX_NPAD_ID = 7; -constexpr Controller_NPad::NPadControllerType PREFERRED_CONTROLLER = - Controller_NPad::NPadControllerType::JoyDual; constexpr std::array npad_id_list{ - 0, 1, 2, 3, 4, 5, 6, 7, 32, 16, + 0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN, }; enum class JoystickId : std::size_t { @@ -51,7 +47,7 @@ static Controller_NPad::NPadControllerType MapSettingsTypeToNPad(Settings::Contr } } -static std::size_t NPadIdToIndex(u32 npad_id) { +std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) { switch (npad_id) { case 0: case 1: @@ -74,6 +70,27 @@ static std::size_t NPadIdToIndex(u32 npad_id) { } } +u32 Controller_NPad::IndexToNPad(std::size_t index) { + switch (index) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + return static_cast(index); + case 8: + return NPAD_HANDHELD; + case 9: + return NPAD_UNKNOWN; + default: + UNIMPLEMENTED_MSG("Unknown npad index {}", index); + return 0; + }; +} + Controller_NPad::Controller_NPad() = default; Controller_NPad::~Controller_NPad() = default; @@ -190,7 +207,7 @@ void Controller_NPad::OnInit() { supported_npad_id_types.resize(npad_id_list.size()); std::memcpy(supported_npad_id_types.data(), npad_id_list.data(), npad_id_list.size() * sizeof(u32)); - AddNewController(PREFERRED_CONTROLLER); + AddNewController(NPadControllerType::JoyDual); } for (std::size_t i = 0; i < connected_controllers.size(); ++i) { @@ -391,9 +408,9 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) { libnx_entry.connection_status.IsRightJoyConnected.Assign(1); libnx_entry.connection_status.IsConnected.Assign(1); - dual_entry.pad_states.raw = pad_state.raw; - dual_entry.l_stick = lstick_entry; - dual_entry.r_stick = rstick_entry; + dual_entry.pad.pad_states.raw = pad_state.pad_states.raw; + dual_entry.pad.l_stick = pad_state.l_stick; + dual_entry.pad.r_stick = pad_state.r_stick; break; case NPadControllerType::JoyLeft: left_entry.connection_status.raw = 0; @@ -461,23 +478,24 @@ void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) { if (!controller.is_connected) { continue; } - if (!IsControllerSupported(PREFERRED_CONTROLLER)) { - const auto best_type = DecideBestController(PREFERRED_CONTROLLER); - const bool is_handheld = (best_type == NPadControllerType::Handheld || - PREFERRED_CONTROLLER == NPadControllerType::Handheld); + const auto requested_controller = + i <= MAX_NPAD_ID ? MapSettingsTypeToNPad(Settings::values.players[i].type) + : NPadControllerType::Handheld; + if (!IsControllerSupported(requested_controller)) { + const auto is_handheld = requested_controller == NPadControllerType::Handheld; if (is_handheld) { controller.type = NPadControllerType::None; controller.is_connected = false; - AddNewController(best_type); + AddNewController(requested_controller); } else { - controller.type = best_type; + controller.type = requested_controller; InitNewlyAddedControler(i); } had_controller_update = true; } - } - if (had_controller_update) { - styleset_changed_event->Signal(); + if (had_controller_update) { + styleset_changed_event->Signal(); + } } } @@ -530,50 +548,6 @@ Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { return last_processed_vibration; } -std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) { - switch (npad_id) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - return static_cast(npad_id); - case 8: - case 32: - return 8; - case 9: - case 16: - return 9; - default: - UNIMPLEMENTED_MSG("Unknown npad id {}", npad_id); - return 0; - } -} - -u32 Controller_NPad::IndexToNPad(std::size_t index) { - switch (index) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - return static_cast(index); - case 8: - return 32; - case 9: - return 16; - default: - UNIMPLEMENTED_MSG("Unknown npad index {}", index); - return 0; - }; -} - void Controller_NPad::AddNewController(NPadControllerType controller) { controller = DecideBestController(controller); if (controller == NPadControllerType::Handheld) { @@ -596,13 +570,13 @@ void Controller_NPad::AddNewController(NPadControllerType controller) { void Controller_NPad::AddNewControllerAt(NPadControllerType controller, u32 npad_id) { controller = DecideBestController(controller); if (controller == NPadControllerType::Handheld) { - connected_controllers[8] = {controller, true}; - InitNewlyAddedControler(8); + connected_controllers[NPadIdToIndex(NPAD_HANDHELD)] = {controller, true}; + InitNewlyAddedControler(NPadIdToIndex(NPAD_HANDHELD)); return; } - const size_t controller_id = static_cast(npad_id); - connected_controllers[controller_id] = {controller, true}; - InitNewlyAddedControler(controller_id); + + connected_controllers[npad_id] = {controller, true}; + InitNewlyAddedControler(npad_id); } void Controller_NPad::ConnectNPad(u32 npad_id) { @@ -613,97 +587,11 @@ void Controller_NPad::DisconnectNPad(u32 npad_id) { connected_controllers[NPadIdToIndex(npad_id)].is_connected = false; } -Controller_NPad::NPadControllerType Controller_NPad::DecideBestController( - NPadControllerType priority) { - if (IsControllerSupported(priority)) { - return priority; - } - const auto is_docked = Settings::values.use_docked_mode; - if (is_docked && priority == NPadControllerType::Handheld) { - priority = NPadControllerType::JoyDual; - if (IsControllerSupported(priority)) { - return priority; - } - } - std::vector priority_list{}; - switch (priority) { - case NPadControllerType::ProController: - priority_list.push_back(NPadControllerType::JoyDual); - if (!is_docked) { - priority_list.push_back(NPadControllerType::Handheld); - } - priority_list.push_back(NPadControllerType::JoyLeft); - priority_list.push_back(NPadControllerType::JoyRight); - priority_list.push_back(NPadControllerType::Pokeball); - break; - case NPadControllerType::Handheld: - priority_list.push_back(NPadControllerType::JoyDual); - priority_list.push_back(NPadControllerType::ProController); - priority_list.push_back(NPadControllerType::JoyLeft); - priority_list.push_back(NPadControllerType::JoyRight); - priority_list.push_back(NPadControllerType::Pokeball); - break; - case NPadControllerType::JoyDual: - if (!is_docked) { - priority_list.push_back(NPadControllerType::Handheld); - } - priority_list.push_back(NPadControllerType::ProController); - priority_list.push_back(NPadControllerType::JoyLeft); - priority_list.push_back(NPadControllerType::JoyRight); - priority_list.push_back(NPadControllerType::Pokeball); - break; - case NPadControllerType::JoyLeft: - priority_list.push_back(NPadControllerType::JoyRight); - priority_list.push_back(NPadControllerType::JoyDual); - if (!is_docked) { - priority_list.push_back(NPadControllerType::Handheld); - } - priority_list.push_back(NPadControllerType::ProController); - priority_list.push_back(NPadControllerType::Pokeball); - break; - case NPadControllerType::JoyRight: - priority_list.push_back(NPadControllerType::JoyLeft); - priority_list.push_back(NPadControllerType::JoyDual); - if (!is_docked) { - priority_list.push_back(NPadControllerType::Handheld); - } - priority_list.push_back(NPadControllerType::ProController); - priority_list.push_back(NPadControllerType::Pokeball); - break; - case NPadControllerType::Pokeball: - priority_list.push_back(NPadControllerType::JoyLeft); - priority_list.push_back(NPadControllerType::JoyRight); - priority_list.push_back(NPadControllerType::JoyDual); - if (!is_docked) { - priority_list.push_back(NPadControllerType::Handheld); - } - priority_list.push_back(NPadControllerType::ProController); - break; - default: - priority_list.push_back(NPadControllerType::JoyDual); - if (!is_docked) { - priority_list.push_back(NPadControllerType::Handheld); - } - priority_list.push_back(NPadControllerType::ProController); - priority_list.push_back(NPadControllerType::JoyLeft); - priority_list.push_back(NPadControllerType::JoyRight); - priority_list.push_back(NPadControllerType::JoyDual); - } - - for (const auto controller_type : priority_list) { - if (IsControllerSupported(controller_type)) { - return controller_type; - } - } - UNIMPLEMENTED_MSG("Could not find supported controller!"); - return priority; -} - bool Controller_NPad::IsControllerSupported(NPadControllerType controller) { if (controller == NPadControllerType::Handheld) { // Handheld is not even a supported type, lets stop here - if (std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), 32) == - supported_npad_id_types.end()) { + if (std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), + NPAD_HANDHELD) == supported_npad_id_types.end()) { return false; } // Handheld should not be supported in docked mode @@ -761,13 +649,12 @@ void Controller_NPad::SetVibrationEnabled(bool can_vibrate) { } void Controller_NPad::ClearAllConnectedControllers() { - std::for_each(connected_controllers.begin(), connected_controllers.end(), - [](ControllerHolder& controller) { - if (controller.is_connected && controller.type != NPadControllerType::None) { - controller.type = NPadControllerType::None; - controller.is_connected = false; - } - }); + for (auto& controller : connected_controllers) { + if (controller.is_connected && controller.type != NPadControllerType::None) { + controller.type = NPadControllerType::None; + controller.is_connected = false; + } + } } void Controller_NPad::DisconnectAllConnectedControllers() { std::for_each(connected_controllers.begin(), connected_controllers.end(), diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 52f92a4f1..ea8057b80 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -5,13 +5,18 @@ #pragma once #include +#include "common/bit_field.h" #include "common/common_types.h" #include "core/frontend/input.h" +#include "core/hle/kernel/event.h" #include "core/hle/service/hid/controllers/controller_base.h" #include "core/settings.h" namespace Service::HID { +constexpr u32 NPAD_HANDHELD = 32; +constexpr u32 NPAD_UNKNOWN = 16; // TODO(ogniK): What is this? + class Controller_NPad final : public ControllerBase { public: Controller_NPad(); @@ -118,6 +123,9 @@ public: void ConnectAllDisconnectedControllers(); void ClearAllControllers(); + static std::size_t NPadIdToIndex(u32 npad_id); + static u32 IndexToNPad(std::size_t index); + private: struct CommonHeader { s64_le timestamp; @@ -304,10 +312,7 @@ private: bool IsControllerSupported(NPadControllerType controller) const; NPadControllerType DecideBestController(NPadControllerType priority) const; void RequestPadStateUpdate(u32 npad_id); - std::size_t NPadIdToIndex(u32 npad_id); - u32 IndexToNPad(std::size_t index); std::array npad_pad_states{}; - NPadControllerType DecideBestController(NPadControllerType priority); bool IsControllerSupported(NPadControllerType controller); }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index 8b9763de6..f666b1bd8 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp @@ -43,9 +43,6 @@ void Controller_Touchscreen::OnUpdate(u8* data, std::size_t size) { auto& touch_entry = cur_entry.states[0]; touch_entry.attribute.raw = 0; if (pressed && Settings::values.touchscreen.enabled) { - if (cur_entry.entry_count == 0) { - touch_entry.attribute.start_touch.Assign(1); - } touch_entry.x = static_cast(x * Layout::ScreenUndocked::Width); touch_entry.y = static_cast(y * Layout::ScreenUndocked::Height); touch_entry.diameter_x = Settings::values.touchscreen.diameter_x; @@ -57,9 +54,6 @@ void Controller_Touchscreen::OnUpdate(u8* data, std::size_t size) { touch_entry.finger = Settings::values.touchscreen.finger; cur_entry.entry_count = 1; } else { - if (cur_entry.entry_count == 1) { - touch_entry.attribute.end_touch.Assign(1); - } cur_entry.entry_count = 0; } diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 0da159559..26fcd3405 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -10,6 +10,56 @@ namespace Settings { +namespace NativeButton { +const std::array mapping = {{ + "button_a", + "button_b", + "button_x", + "button_y", + "button_lstick", + "button_rstick", + "button_l", + "button_r", + "button_zl", + "button_zr", + "button_plus", + "button_minus", + "button_dleft", + "button_dup", + "button_dright", + "button_ddown", + "button_lstick_left", + "button_lstick_up", + "button_lstick_right", + "button_lstick_down", + "button_rstick_left", + "button_rstick_up", + "button_rstick_right", + "button_rstick_down", + "button_sl", + "button_sr", + "button_home", + "button_screenshot", +}}; +} + +namespace NativeAnalog { +const std::array mapping = {{ + "lstick", + "rstick", +}}; +} + +namespace NativeMouseButton { +const std::array mapping = {{ + "left", + "right", + "middle", + "forward", + "back", +}}; +} + Values values = {}; void Apply() { diff --git a/src/core/settings.h b/src/core/settings.h index 9cc3c1dc8..e63134f80 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -60,36 +60,7 @@ constexpr int BUTTON_NS_END = NumButtons; constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN; constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN; -static const std::array mapping = {{ - "button_a", - "button_b", - "button_x", - "button_y", - "button_lstick", - "button_rstick", - "button_l", - "button_r", - "button_zl", - "button_zr", - "button_plus", - "button_minus", - "button_dleft", - "button_dup", - "button_dright", - "button_ddown", - "button_lstick_left", - "button_lstick_up", - "button_lstick_right", - "button_lstick_down", - "button_rstick_left", - "button_rstick_up", - "button_rstick_right", - "button_rstick_down", - "button_sl", - "button_sr", - "button_home", - "button_screenshot", -}}; +extern const std::array mapping; } // namespace NativeButton @@ -105,10 +76,7 @@ constexpr int STICK_HID_BEGIN = LStick; constexpr int STICK_HID_END = NumAnalogs; constexpr int NUM_STICKS_HID = NumAnalogs; -static const std::array mapping = {{ - "lstick", - "rstick", -}}; +extern const std::array mapping; } // namespace NativeAnalog namespace NativeMouseButton { @@ -126,13 +94,7 @@ constexpr int MOUSE_HID_BEGIN = Left; constexpr int MOUSE_HID_END = NumMouseButtons; constexpr int NUM_MOUSE_HID = NumMouseButtons; -static const std::array mapping = {{ - "left", - "right", - "middle", - "forward", - "back", -}}; +extern const std::array mapping; } // namespace NativeMouseButton namespace NativeKeyboard { diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index c931c7cd6..652f6a0b7 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -203,9 +203,8 @@ const std::array Config::default Qt::Key_Control, Qt::Key_Shift, Qt::Key_AltGr, Qt::Key_ApplicationRight, }; -void Config::ReadValues() { - qt_config->beginGroup("Controls"); - for (std::size_t p = 0; p < 10; ++p) { +void Config::ReadPlayerValues() { + for (std::size_t p = 0; p < Settings::values.players.size(); ++p) { Settings::values.players[p].connected = qt_config->value(QString("player_%1_connected").arg(p), false).toBool(); @@ -265,28 +264,9 @@ void Config::ReadValues() { std::stable_partition(Settings::values.players.begin(), Settings::values.players.end(), [](const auto& player) { return player.connected; }); +} - Settings::values.motion_device = - qt_config->value("motion_device", "engine:motion_emu,update_period:100,sensitivity:0.01") - .toString() - .toStdString(); - - Settings::values.mouse_enabled = qt_config->value("mouse_enabled", false).toBool(); - - for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { - std::string default_param = InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]); - Settings::values.mouse_buttons[i] = - qt_config - ->value(QString("mouse_") + Settings::NativeMouseButton::mapping[i], - QString::fromStdString(default_param)) - .toString() - .toStdString(); - if (Settings::values.mouse_buttons[i].empty()) - Settings::values.mouse_buttons[i] = default_param; - } - - Settings::values.keyboard_enabled = qt_config->value("keyboard_enabled", false).toBool(); - +void Config::ReadDebugValues() { Settings::values.debug_pad_enabled = qt_config->value("debug_pad_enabled", false).toBool(); for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); @@ -313,7 +293,38 @@ void Config::ReadValues() { if (Settings::values.debug_pad_analogs[i].empty()) Settings::values.debug_pad_analogs[i] = default_param; } +} +void Config::ReadKeyboardValues() { + Settings::values.keyboard_enabled = qt_config->value("keyboard_enabled", false).toBool(); + + std::transform(default_keyboard_keys.begin(), default_keyboard_keys.end(), + Settings::values.keyboard_keys.begin(), InputCommon::GenerateKeyboardParam); + std::transform(default_keyboard_mods.begin(), default_keyboard_mods.end(), + Settings::values.keyboard_keys.begin() + + Settings::NativeKeyboard::LeftControlKey, + InputCommon::GenerateKeyboardParam); + std::transform(default_keyboard_mods.begin(), default_keyboard_mods.end(), + Settings::values.keyboard_mods.begin(), InputCommon::GenerateKeyboardParam); +} + +void Config::ReadMouseValues() { + Settings::values.mouse_enabled = qt_config->value("mouse_enabled", false).toBool(); + + for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { + std::string default_param = InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]); + Settings::values.mouse_buttons[i] = + qt_config + ->value(QString("mouse_") + Settings::NativeMouseButton::mapping[i], + QString::fromStdString(default_param)) + .toString() + .toStdString(); + if (Settings::values.mouse_buttons[i].empty()) + Settings::values.mouse_buttons[i] = default_param; + } +} + +void Config::ReadTouchscreenValues() { Settings::values.touchscreen.enabled = qt_config->value("touchscreen_enabled", true).toBool(); Settings::values.touchscreen.device = qt_config->value("touchscreen_device", "engine:emu_window").toString().toStdString(); @@ -325,6 +336,21 @@ void Config::ReadValues() { Settings::values.touchscreen.diameter_y = qt_config->value("touchscreen_diameter_y", 15).toUInt(); qt_config->endGroup(); +} + +void Config::ReadValues() { + qt_config->beginGroup("Controls"); + + ReadPlayerValues(); + ReadDebugValues(); + ReadKeyboardValues(); + ReadMouseValues(); + ReadTouchscreenValues(); + + Settings::values.motion_device = + qt_config->value("motion_device", "engine:motion_emu,update_period:100,sensitivity:0.01") + .toString() + .toStdString(); qt_config->beginGroup("Core"); Settings::values.use_cpu_jit = qt_config->value("use_cpu_jit", true).toBool(); @@ -370,15 +396,6 @@ void Config::ReadValues() { .toStdString()); qt_config->endGroup(); - std::transform(default_keyboard_keys.begin(), default_keyboard_keys.end(), - Settings::values.keyboard_keys.begin(), InputCommon::GenerateKeyboardParam); - std::transform(default_keyboard_mods.begin(), default_keyboard_mods.end(), - Settings::values.keyboard_keys.begin() + - Settings::NativeKeyboard::LeftControlKey, - InputCommon::GenerateKeyboardParam); - std::transform(default_keyboard_mods.begin(), default_keyboard_mods.end(), - Settings::values.keyboard_mods.begin(), InputCommon::GenerateKeyboardParam); - qt_config->beginGroup("Core"); Settings::values.use_cpu_jit = qt_config->value("use_cpu_jit", true).toBool(); Settings::values.use_multi_core = qt_config->value("use_multi_core", false).toBool(); @@ -488,9 +505,8 @@ void Config::ReadValues() { qt_config->endGroup(); } -void Config::SaveValues() { - qt_config->beginGroup("Controls"); - for (int p = 0; p < 10; ++p) { +void Config::SavePlayerValues() { + for (int p = 0; p < Settings::values.players.size(); ++p) { qt_config->setValue(QString("player_%1_connected").arg(p), Settings::values.players[p].connected); qt_config->setValue(QString("player_%1_type").arg(p), @@ -516,19 +532,9 @@ void Config::SaveValues() { QString::fromStdString(Settings::values.players[p].analogs[i])); } } +} - qt_config->setValue("motion_device", QString::fromStdString(Settings::values.motion_device)); - - qt_config->setValue("mouse_enabled", Settings::values.mouse_enabled); - - for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { - qt_config->setValue(QString("mouse_") + - QString::fromStdString(Settings::NativeMouseButton::mapping[i]), - QString::fromStdString(Settings::values.mouse_buttons[i])); - } - - qt_config->setValue("keyboard_enabled", Settings::values.keyboard_enabled); - +void Config::SaveDebugValues() { qt_config->setValue("debug_pad_enabled", Settings::values.debug_pad_enabled); for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { qt_config->setValue(QString("debug_pad_") + @@ -540,7 +546,19 @@ void Config::SaveValues() { QString::fromStdString(Settings::NativeAnalog::mapping[i]), QString::fromStdString(Settings::values.debug_pad_analogs[i])); } +} +void Config::SaveMouseValues() { + qt_config->setValue("mouse_enabled", Settings::values.mouse_enabled); + + for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { + qt_config->setValue(QString("mouse_") + + QString::fromStdString(Settings::NativeMouseButton::mapping[i]), + QString::fromStdString(Settings::values.mouse_buttons[i])); + } +} + +void Config::SaveTouchscreenValues() { qt_config->setValue("touchscreen_enabled", Settings::values.touchscreen.enabled); qt_config->setValue("touchscreen_device", QString::fromStdString(Settings::values.touchscreen.device)); @@ -549,6 +567,19 @@ void Config::SaveValues() { qt_config->setValue("touchscreen_angle", Settings::values.touchscreen.rotation_angle); qt_config->setValue("touchscreen_diameter_x", Settings::values.touchscreen.diameter_x); qt_config->setValue("touchscreen_diameter_y", Settings::values.touchscreen.diameter_y); +} + +void Config::SaveValues() { + qt_config->beginGroup("Controls"); + + SavePlayerValues(); + SaveDebugValues(); + SaveMouseValues(); + SaveTouchscreenValues(); + + qt_config->setValue("motion_device", QString::fromStdString(Settings::values.motion_device)); + qt_config->setValue("keyboard_enabled", Settings::values.keyboard_enabled); + qt_config->endGroup(); qt_config->beginGroup("Core"); diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index 1facd6b55..a1c27bbf9 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h @@ -29,7 +29,17 @@ public: private: void ReadValues(); + void ReadPlayerValues(); + void ReadDebugValues(); + void ReadKeyboardValues(); + void ReadMouseValues(); + void ReadTouchscreenValues(); + void SaveValues(); + void SavePlayerValues(); + void SaveDebugValues(); + void SaveMouseValues(); + void SaveTouchscreenValues(); std::unique_ptr qt_config; std::string qt_config_loc; diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 9ae9827fe..a52abdd8f 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -11,6 +11,7 @@ #include "common/param_package.h" #include "configuration/configure_touchscreen_advanced.h" #include "core/core.h" +#include "core/hle/service/hid/controllers/npad.h" #include "input_common/main.h" #include "ui_configure_input.h" #include "ui_configure_input_player.h" @@ -83,9 +84,9 @@ ConfigureInput::ConfigureInput(QWidget* parent) } template -void ConfigureInput::CallConfigureDialog(Args... args) { +void ConfigureInput::CallConfigureDialog(Args&&... args) { this->applyConfiguration(); - Dialog dialog(this, args...); + Dialog dialog(this, std::forward(args)...); const auto res = dialog.exec(); if (res == QDialog::Accepted) { @@ -94,14 +95,16 @@ void ConfigureInput::CallConfigureDialog(Args... args) { } void ConfigureInput::applyConfiguration() { - for (std::size_t i = 0; i < 8; ++i) { + for (std::size_t i = 0; i < players_enabled.size(); ++i) { Settings::values.players[i].connected = players_enabled[i]->isChecked(); Settings::values.players[i].type = static_cast(player_controller[i]->currentIndex()); } Settings::values.use_docked_mode = ui->use_docked_mode->isChecked(); - Settings::values.players[8].connected = ui->handheld_connected->isChecked(); + Settings::values + .players[Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD)] + .connected = ui->handheld_connected->isChecked(); Settings::values.debug_pad_enabled = ui->debug_enabled->isChecked(); Settings::values.mouse_enabled = ui->mouse_enabled->isChecked(); Settings::values.keyboard_enabled = ui->keyboard_enabled->isChecked(); @@ -109,7 +112,7 @@ void ConfigureInput::applyConfiguration() { } void ConfigureInput::updateUIEnabled() { - for (std::size_t i = 0; i < 8; ++i) { + for (std::size_t i = 0; i < players_enabled.size(); ++i) { const auto enabled = players_enabled[i]->checkState() == Qt::Checked; player_controller[i]->setEnabled(enabled); @@ -118,10 +121,7 @@ void ConfigureInput::updateUIEnabled() { bool hit_disabled = false; for (auto* player : players_enabled) { - if (hit_disabled) - player->setDisabled(true); - else - player->setEnabled(true); + player->setDisabled(hit_disabled); if (!player->isChecked()) hit_disabled = true; } @@ -138,13 +138,16 @@ void ConfigureInput::loadConfiguration() { std::stable_partition(Settings::values.players.begin(), Settings::values.players.end(), [](const auto& player) { return player.connected; }); - for (std::size_t i = 0; i < 8; ++i) { + for (std::size_t i = 0; i < players_enabled.size(); ++i) { players_enabled[i]->setChecked(Settings::values.players[i].connected); player_controller[i]->setCurrentIndex(static_cast(Settings::values.players[i].type)); } ui->use_docked_mode->setChecked(Settings::values.use_docked_mode); - ui->handheld_connected->setChecked(Settings::values.players[8].connected); + ui->handheld_connected->setChecked( + Settings::values + .players[Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD)] + .connected); ui->debug_enabled->setChecked(Settings::values.debug_pad_enabled); ui->mouse_enabled->setChecked(Settings::values.mouse_enabled); ui->keyboard_enabled->setChecked(Settings::values.keyboard_enabled); @@ -157,7 +160,7 @@ void ConfigureInput::restoreDefaults() { players_enabled[0]->setCheckState(Qt::Checked); player_controller[0]->setCurrentIndex(1); - for (std::size_t i = 1; i < 8; ++i) { + for (std::size_t i = 1; i < players_enabled.size(); ++i) { players_enabled[i]->setCheckState(Qt::Unchecked); player_controller[i]->setCurrentIndex(0); } diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h index 0ba77c5ef..51b8e609c 100644 --- a/src/yuzu/configuration/configure_input.h +++ b/src/yuzu/configuration/configure_input.h @@ -41,7 +41,7 @@ private: void updateUIEnabled(); template - void CallConfigureDialog(Args... args); + void CallConfigureDialog(Args&&... args); /// Load configuration settings. void loadConfiguration(); diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 5de7dd962..995725b0f 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -41,7 +41,7 @@ static void LayerGridElements(QGridLayout* grid, QWidget* item, QWidget* onTopOf grid->addWidget(item, row, column, rowSpan, columnSpan); } -static QString getKeyName(int key_code) { +static QString GetKeyName(int key_code) { switch (key_code) { case Qt::Key_Shift: return QObject::tr("Shift"); @@ -71,7 +71,7 @@ static QString ButtonToText(const Common::ParamPackage& param) { if (!param.Has("engine")) { return QObject::tr("[not set]"); } else if (param.Get("engine", "") == "keyboard") { - return getKeyName(param.Get("code", 0)); + return GetKeyName(param.Get("code", 0)); } else if (param.Get("engine", "") == "sdl") { if (param.Has("hat")) { return QString(QObject::tr("Hat %1 %2")) @@ -486,7 +486,7 @@ void ConfigureInputPlayer::setPollingResult(const Common::ParamPackage& params, } updateButtonLabels(); - input_setter = boost::none; + input_setter = std::nullopt; } void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) { diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h index 67cc6a8ca..8248cd7de 100644 --- a/src/yuzu/configuration/configure_input_player.h +++ b/src/yuzu/configuration/configure_input_player.h @@ -7,11 +7,11 @@ #include #include #include +#include #include #include #include #include -#include #include "common/param_package.h" #include "core/settings.h" #include "input_common/main.h" @@ -44,7 +44,7 @@ private: std::unique_ptr poll_timer; /// This will be the the setting function when an input is awaiting configuration. - boost::optional> input_setter; + std::optional> input_setter; std::array buttons_param; std::array analogs_param; diff --git a/src/yuzu/configuration/configure_mouse_advanced.cpp b/src/yuzu/configuration/configure_mouse_advanced.cpp index 8cfcd1679..ac9c84096 100644 --- a/src/yuzu/configuration/configure_mouse_advanced.cpp +++ b/src/yuzu/configuration/configure_mouse_advanced.cpp @@ -16,7 +16,7 @@ #include "yuzu/configuration/config.h" #include "yuzu/configuration/configure_mouse_advanced.h" -static QString getKeyName(int key_code) { +static QString GetKeyName(int key_code) { switch (key_code) { case Qt::Key_Shift: return QObject::tr("Shift"); @@ -35,7 +35,7 @@ static QString ButtonToText(const Common::ParamPackage& param) { if (!param.Has("engine")) { return QObject::tr("[not set]"); } else if (param.Get("engine", "") == "keyboard") { - return getKeyName(param.Get("code", 0)); + return GetKeyName(param.Get("code", 0)); } else if (param.Get("engine", "") == "sdl") { if (param.Has("hat")) { return QString(QObject::tr("Hat %1 %2")) @@ -191,7 +191,7 @@ void ConfigureMouseAdvanced::setPollingResult(const Common::ParamPackage& params } updateButtonLabels(); - input_setter = boost::none; + input_setter = std::nullopt; } void ConfigureMouseAdvanced::keyPressEvent(QKeyEvent* event) { diff --git a/src/yuzu/configuration/configure_mouse_advanced.h b/src/yuzu/configuration/configure_mouse_advanced.h index f897d9044..983ac4158 100644 --- a/src/yuzu/configuration/configure_mouse_advanced.h +++ b/src/yuzu/configuration/configure_mouse_advanced.h @@ -5,9 +5,9 @@ #pragma once #include +#include #include #include -#include #include "core/settings.h" class QCheckBox; @@ -30,7 +30,7 @@ private: std::unique_ptr ui; /// This will be the the setting function when an input is awaiting configuration. - boost::optional> input_setter; + std::optional> input_setter; std::array button_map; std::array buttons_param; diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.cpp b/src/yuzu/configuration/configure_touchscreen_advanced.cpp index 6cf3dab97..9c1561e9d 100644 --- a/src/yuzu/configuration/configure_touchscreen_advanced.cpp +++ b/src/yuzu/configuration/configure_touchscreen_advanced.cpp @@ -2,15 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include #include -#include -#include -#include -#include -#include "common/assert.h" -#include "common/param_package.h" -#include "input_common/main.h" #include "ui_configure_touchscreen_advanced.h" #include "yuzu/configuration/config.h" #include "yuzu/configuration/configure_touchscreen_advanced.h" @@ -22,10 +14,12 @@ ConfigureTouchscreenAdvanced::ConfigureTouchscreenAdvanced(QWidget* parent) connect(ui->restore_defaults_button, &QPushButton::pressed, this, &ConfigureTouchscreenAdvanced::restoreDefaults); - this->loadConfiguration(); - this->resize(0, 0); + loadConfiguration(); + resize(0, 0); } +ConfigureTouchscreenAdvanced::~ConfigureTouchscreenAdvanced() = default; + void ConfigureTouchscreenAdvanced::applyConfiguration() { Settings::values.touchscreen.finger = ui->finger_box->value(); Settings::values.touchscreen.diameter_x = ui->diameter_x_box->value(); diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.h b/src/yuzu/configuration/configure_touchscreen_advanced.h index 938a62ed3..41cd255fb 100644 --- a/src/yuzu/configuration/configure_touchscreen_advanced.h +++ b/src/yuzu/configuration/configure_touchscreen_advanced.h @@ -18,6 +18,7 @@ class ConfigureTouchscreenAdvanced : public QDialog { public: explicit ConfigureTouchscreenAdvanced(QWidget* parent); + ~ConfigureTouchscreenAdvanced() override; void applyConfiguration(); From e58c951a59d7f3851fd3a71ae6f99933fba8cdbb Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sun, 4 Nov 2018 10:18:59 -0500 Subject: [PATCH 23/26] configure_input: Make None a controller option instead of checkbox --- src/yuzu/configuration/config.cpp | 8 +- src/yuzu/configuration/configure_general.cpp | 36 ------ src/yuzu/configuration/configure_general.h | 1 - src/yuzu/configuration/configure_general.ui | 9 +- src/yuzu/configuration/configure_input.cpp | 115 +++++++++++------ src/yuzu/configuration/configure_input.h | 7 +- src/yuzu/configuration/configure_input.ui | 122 +++++++++--------- .../configuration/configure_input_player.cpp | 2 + .../configuration/configure_input_player.h | 1 + .../configure_mouse_advanced.cpp | 2 + .../configuration/configure_mouse_advanced.h | 1 + 11 files changed, 150 insertions(+), 154 deletions(-) diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 652f6a0b7..e24ed5f2b 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -5,6 +5,7 @@ #include #include "common/file_util.h" #include "core/hle/service/acc/profile_manager.h" +#include "core/hle/service/hid/controllers/npad.h" #include "input_common/main.h" #include "yuzu/configuration/config.h" #include "yuzu/ui_settings.h" @@ -262,8 +263,11 @@ void Config::ReadPlayerValues() { } } - std::stable_partition(Settings::values.players.begin(), Settings::values.players.end(), - [](const auto& player) { return player.connected; }); + std::stable_partition( + Settings::values.players.begin(), + Settings::values.players.begin() + + Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD), + [](const auto& player) { return player.connected; }); } void Config::ReadDebugValues() { diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index c22742007..92a441308 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp @@ -3,10 +3,6 @@ // Refer to the license.txt file included. #include "core/core.h" -#include "core/hle/service/am/am.h" -#include "core/hle/service/am/applet_ae.h" -#include "core/hle/service/am/applet_oe.h" -#include "core/hle/service/sm/sm.h" #include "core/settings.h" #include "ui_configure_general.h" #include "yuzu/configuration/configure_general.h" @@ -36,7 +32,6 @@ void ConfigureGeneral::setConfiguration() { ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing); ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme)); ui->use_cpu_jit->setChecked(Settings::values.use_cpu_jit); - ui->use_docked_mode->setChecked(Settings::values.use_docked_mode); ui->enable_nfc->setChecked(Settings::values.enable_nfc); } @@ -44,33 +39,6 @@ void ConfigureGeneral::PopulateHotkeyList(const HotkeyRegistry& registry) { ui->widget->Populate(registry); } -void ConfigureGeneral::OnDockedModeChanged(bool last_state, bool new_state) { - if (last_state == new_state) { - return; - } - - Core::System& system{Core::System::GetInstance()}; - if (!system.IsPoweredOn()) { - return; - } - Service::SM::ServiceManager& sm = system.ServiceManager(); - - // Message queue is shared between these services, we just need to signal an operation - // change to one and it will handle both automatically - auto applet_oe = sm.GetService("appletOE"); - auto applet_ae = sm.GetService("appletAE"); - bool has_signalled = false; - - if (applet_oe != nullptr) { - applet_oe->GetMessageQueue()->OperationModeChanged(); - has_signalled = true; - } - - if (applet_ae != nullptr && !has_signalled) { - applet_ae->GetMessageQueue()->OperationModeChanged(); - } -} - void ConfigureGeneral::applyConfiguration() { UISettings::values.gamedir_deepscan = ui->toggle_deepscan->isChecked(); UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); @@ -78,9 +46,5 @@ void ConfigureGeneral::applyConfiguration() { ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString(); Settings::values.use_cpu_jit = ui->use_cpu_jit->isChecked(); - const bool pre_docked_mode = Settings::values.use_docked_mode; - Settings::values.use_docked_mode = ui->use_docked_mode->isChecked(); - OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode); - Settings::values.enable_nfc = ui->enable_nfc->isChecked(); } diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h index 2210d48da..4770034cc 100644 --- a/src/yuzu/configuration/configure_general.h +++ b/src/yuzu/configuration/configure_general.h @@ -25,7 +25,6 @@ public: private: void setConfiguration(); - void OnDockedModeChanged(bool last_state, bool new_state); std::unique_ptr ui; }; diff --git a/src/yuzu/configuration/configure_general.ui b/src/yuzu/configuration/configure_general.ui index b82fffde8..bf37446c6 100644 --- a/src/yuzu/configuration/configure_general.ui +++ b/src/yuzu/configuration/configure_general.ui @@ -7,7 +7,7 @@ 0 0 300 - 377 + 407 @@ -71,13 +71,6 @@ - - - - Enable docked mode - - - diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index a52abdd8f..25066d4d9 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -11,7 +11,11 @@ #include "common/param_package.h" #include "configuration/configure_touchscreen_advanced.h" #include "core/core.h" +#include "core/hle/service/am/am.h" +#include "core/hle/service/am/applet_ae.h" +#include "core/hle/service/am/applet_oe.h" #include "core/hle/service/hid/controllers/npad.h" +#include "core/hle/service/sm/sm.h" #include "input_common/main.h" #include "ui_configure_input.h" #include "ui_configure_input_player.h" @@ -26,24 +30,19 @@ ConfigureInput::ConfigureInput(QWidget* parent) : QWidget(parent), ui(std::make_unique()) { ui->setupUi(this); - players_enabled = { - ui->player1_checkbox, ui->player2_checkbox, ui->player3_checkbox, ui->player4_checkbox, - ui->player5_checkbox, ui->player6_checkbox, ui->player7_checkbox, ui->player8_checkbox, - }; - - player_controller = { + players_controller = { ui->player1_combobox, ui->player2_combobox, ui->player3_combobox, ui->player4_combobox, ui->player5_combobox, ui->player6_combobox, ui->player7_combobox, ui->player8_combobox, }; - player_configure = { + players_configure = { ui->player1_configure, ui->player2_configure, ui->player3_configure, ui->player4_configure, ui->player5_configure, ui->player6_configure, ui->player7_configure, ui->player8_configure, }; - for (auto* controller_box : player_controller) { - controller_box->addItems( - {"Pro Controller", "Dual Joycons", "Single Right Joycon", "Single Left Joycon"}); + for (auto* controller_box : players_controller) { + controller_box->addItems({"None", "Pro Controller", "Dual Joycons", "Single Right Joycon", + "Single Left Joycon"}); } this->loadConfiguration(); @@ -52,8 +51,9 @@ ConfigureInput::ConfigureInput(QWidget* parent) connect(ui->restore_defaults_button, &QPushButton::pressed, this, &ConfigureInput::restoreDefaults); - for (auto* enabled : players_enabled) - connect(enabled, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled); + for (auto* enabled : players_controller) + connect(enabled, QOverload::of(&QComboBox::currentIndexChanged), this, + &ConfigureInput::updateUIEnabled); connect(ui->use_docked_mode, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled); connect(ui->handheld_connected, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled); @@ -63,8 +63,8 @@ ConfigureInput::ConfigureInput(QWidget* parent) connect(ui->touchscreen_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled); - for (std::size_t i = 0; i < player_configure.size(); ++i) { - connect(player_configure[i], &QPushButton::pressed, this, + for (std::size_t i = 0; i < players_configure.size(); ++i) { + connect(players_configure[i], &QPushButton::pressed, this, [this, i]() { CallConfigureDialog(i, false); }); } @@ -79,8 +79,6 @@ ConfigureInput::ConfigureInput(QWidget* parent) connect(ui->touchscreen_advanced, &QPushButton::pressed, this, [this]() { CallConfigureDialog(); }); - - ui->use_docked_mode->setEnabled(!Core::System::GetInstance().IsPoweredOn()); } template @@ -94,14 +92,50 @@ void ConfigureInput::CallConfigureDialog(Args&&... args) { } } -void ConfigureInput::applyConfiguration() { - for (std::size_t i = 0; i < players_enabled.size(); ++i) { - Settings::values.players[i].connected = players_enabled[i]->isChecked(); - Settings::values.players[i].type = - static_cast(player_controller[i]->currentIndex()); +void ConfigureInput::OnDockedModeChanged(bool last_state, bool new_state) { + if (last_state == new_state) { + return; } + Core::System& system{Core::System::GetInstance()}; + if (!system.IsPoweredOn()) { + return; + } + Service::SM::ServiceManager& sm = system.ServiceManager(); + + // Message queue is shared between these services, we just need to signal an operation + // change to one and it will handle both automatically + auto applet_oe = sm.GetService("appletOE"); + auto applet_ae = sm.GetService("appletAE"); + bool has_signalled = false; + + if (applet_oe != nullptr) { + applet_oe->GetMessageQueue()->OperationModeChanged(); + has_signalled = true; + } + + if (applet_ae != nullptr && !has_signalled) { + applet_ae->GetMessageQueue()->OperationModeChanged(); + } +} + +void ConfigureInput::applyConfiguration() { + for (std::size_t i = 0; i < players_controller.size(); ++i) { + const auto controller_type_index = players_controller[i]->currentIndex(); + + Settings::values.players[i].connected = controller_type_index != 0; + + if (controller_type_index > 0) { + Settings::values.players[i].type = + static_cast(controller_type_index - 1); + } else { + Settings::values.players[i].type = Settings::ControllerType::DualJoycon; + } + } + + const bool pre_docked_mode = Settings::values.use_docked_mode; Settings::values.use_docked_mode = ui->use_docked_mode->isChecked(); + OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode); Settings::values .players[Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD)] .connected = ui->handheld_connected->isChecked(); @@ -112,18 +146,15 @@ void ConfigureInput::applyConfiguration() { } void ConfigureInput::updateUIEnabled() { - for (std::size_t i = 0; i < players_enabled.size(); ++i) { - const auto enabled = players_enabled[i]->checkState() == Qt::Checked; - - player_controller[i]->setEnabled(enabled); - player_configure[i]->setEnabled(enabled); + bool hit_disabled = false; + for (auto* player : players_controller) { + player->setDisabled(hit_disabled); + if (!hit_disabled && player->currentIndex() == 0) + hit_disabled = true; } - bool hit_disabled = false; - for (auto* player : players_enabled) { - player->setDisabled(hit_disabled); - if (!player->isChecked()) - hit_disabled = true; + for (std::size_t i = 0; i < players_controller.size(); ++i) { + players_configure[i]->setEnabled(players_controller[i]->currentIndex() != 0); } ui->handheld_connected->setEnabled(!ui->use_docked_mode->isChecked()); @@ -135,12 +166,16 @@ void ConfigureInput::updateUIEnabled() { } void ConfigureInput::loadConfiguration() { - std::stable_partition(Settings::values.players.begin(), Settings::values.players.end(), - [](const auto& player) { return player.connected; }); + std::stable_partition( + Settings::values.players.begin(), + Settings::values.players.begin() + + Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD), + [](const auto& player) { return player.connected; }); - for (std::size_t i = 0; i < players_enabled.size(); ++i) { - players_enabled[i]->setChecked(Settings::values.players[i].connected); - player_controller[i]->setCurrentIndex(static_cast(Settings::values.players[i].type)); + for (std::size_t i = 0; i < players_controller.size(); ++i) { + const auto connected = Settings::values.players[i].connected; + players_controller[i]->setCurrentIndex( + connected ? static_cast(Settings::values.players[i].type) + 1 : 0); } ui->use_docked_mode->setChecked(Settings::values.use_docked_mode); @@ -157,12 +192,10 @@ void ConfigureInput::loadConfiguration() { } void ConfigureInput::restoreDefaults() { - players_enabled[0]->setCheckState(Qt::Checked); - player_controller[0]->setCurrentIndex(1); + players_controller[0]->setCurrentIndex(2); - for (std::size_t i = 1; i < players_enabled.size(); ++i) { - players_enabled[i]->setCheckState(Qt::Unchecked); - player_controller[i]->setCurrentIndex(0); + for (std::size_t i = 1; i < players_controller.size(); ++i) { + players_controller[i]->setCurrentIndex(0); } ui->use_docked_mode->setCheckState(Qt::Unchecked); diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h index 51b8e609c..29a8a03f8 100644 --- a/src/yuzu/configuration/configure_input.h +++ b/src/yuzu/configuration/configure_input.h @@ -43,6 +43,8 @@ private: template void CallConfigureDialog(Args&&... args); + void OnDockedModeChanged(bool last_state, bool new_state); + /// Load configuration settings. void loadConfiguration(); /// Restore all buttons to their default values. @@ -50,7 +52,6 @@ private: std::unique_ptr ui; - std::array players_enabled; - std::array player_controller; - std::array player_configure; + std::array players_controller; + std::array players_configure; }; diff --git a/src/yuzu/configuration/configure_input.ui b/src/yuzu/configuration/configure_input.ui index f12896b47..8beae959e 100644 --- a/src/yuzu/configuration/configure_input.ui +++ b/src/yuzu/configuration/configure_input.ui @@ -7,7 +7,7 @@ 0 0 473 - 677 + 685 @@ -49,62 +49,6 @@ - - - - Player 1 - - - - - - - Player 7 - - - - - - - Player 4 - - - - - - - Player 5 - - - - - - - Player 6 - - - - - - - Player 8 - - - - - - - Player 3 - - - - - - - Player 2 - - - @@ -250,13 +194,65 @@ - - - - Enabled + + + + + 55 + 0 + - - Qt::AlignCenter + + Player 1 + + + + + + + Player 2 + + + + + + + Player 3 + + + + + + + Player 4 + + + + + + + Player 5 + + + + + + + Player 6 + + + + + + + Player 7 + + + + + + + Player 8 diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 995725b0f..ba6e09368 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -325,6 +325,8 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, u8 player_index, boo ui->buttonHome->setEnabled(false); } +ConfigureInputPlayer::~ConfigureInputPlayer() = default; + void ConfigureInputPlayer::applyConfiguration() { auto& buttons = debug ? Settings::values.debug_pad_buttons : Settings::values.players[player_index].buttons; diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h index 8248cd7de..b0e5550c5 100644 --- a/src/yuzu/configuration/configure_input_player.h +++ b/src/yuzu/configuration/configure_input_player.h @@ -30,6 +30,7 @@ class ConfigureInputPlayer : public QDialog { public: explicit ConfigureInputPlayer(QWidget* parent, u8 player_index, bool debug = false); + ~ConfigureInputPlayer() override; /// Save all button configurations to settings file void applyConfiguration(); diff --git a/src/yuzu/configuration/configure_mouse_advanced.cpp b/src/yuzu/configuration/configure_mouse_advanced.cpp index ac9c84096..dab58fbaa 100644 --- a/src/yuzu/configuration/configure_mouse_advanced.cpp +++ b/src/yuzu/configuration/configure_mouse_advanced.cpp @@ -112,6 +112,8 @@ ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent) resize(0, 0); } +ConfigureMouseAdvanced::~ConfigureMouseAdvanced() = default; + void ConfigureMouseAdvanced::applyConfiguration() { std::transform(buttons_param.begin(), buttons_param.end(), Settings::values.mouse_buttons.begin(), diff --git a/src/yuzu/configuration/configure_mouse_advanced.h b/src/yuzu/configuration/configure_mouse_advanced.h index 983ac4158..218df2bda 100644 --- a/src/yuzu/configuration/configure_mouse_advanced.h +++ b/src/yuzu/configuration/configure_mouse_advanced.h @@ -23,6 +23,7 @@ class ConfigureMouseAdvanced : public QDialog { public: explicit ConfigureMouseAdvanced(QWidget* parent); + ~ConfigureMouseAdvanced() override; void applyConfiguration(); From dd92db3fb0038fea598250948aee7233777dc878 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sat, 10 Nov 2018 17:09:33 -0500 Subject: [PATCH 24/26] configure_input: Properly update UI components on removal of player --- src/yuzu/configuration/configure_input.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 25066d4d9..7ee572761 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -149,6 +149,8 @@ void ConfigureInput::updateUIEnabled() { bool hit_disabled = false; for (auto* player : players_controller) { player->setDisabled(hit_disabled); + if (hit_disabled) + player->setCurrentIndex(0); if (!hit_disabled && player->currentIndex() == 0) hit_disabled = true; } From 312ef596a5fa93f93444b1485d43398f0bcde043 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sat, 17 Nov 2018 16:26:03 -0500 Subject: [PATCH 25/26] configure_input_player: Set minimum width on controls --- .../configuration/configure_input_player.ui | 40 +++++++++++-------- src/yuzu_cmd/config.cpp | 13 +++--- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui index 191206663..42db020be 100644 --- a/src/yuzu/configuration/configure_input_player.ui +++ b/src/yuzu/configuration/configure_input_player.ui @@ -235,6 +235,12 @@ + + + 80 + 0 + + Left: @@ -257,6 +263,12 @@ + + + 80 + 0 + + Right: @@ -294,6 +306,12 @@ + + + 80 + 0 + + A: @@ -316,6 +334,12 @@ + + + 80 + 0 + + B: @@ -1017,22 +1041,6 @@ - - - - - 0 - 0 - - - - Check the box to override the global default key with this one for this game only. - - - true - - - diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 0d5df8fd0..c66353a65 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp @@ -324,13 +324,12 @@ void Config::ReadValues() { Settings::values.current_user = std::clamp( sdl2_config->GetInteger("System", "current_user", 0), 0, Service::Account::MAX_USERS - 1); - const auto enabled = sdl2_config->GetBoolean("System", "rng_seed_enabled", false); - if (enabled) { - Settings::values.rng_seed = sdl2_config->GetInteger("System", "rng_seed", 0); - } - else { - Settings::values.rng_seed = std::nullopt; - } + const auto enabled = sdl2_config->GetBoolean("System", "rng_seed_enabled", false); + if (enabled) { + Settings::values.rng_seed = sdl2_config->GetInteger("System", "rng_seed", 0); + } else { + Settings::values.rng_seed = std::nullopt; + } // Core Settings::values.use_cpu_jit = sdl2_config->GetBoolean("Core", "use_cpu_jit", true); From aef0d88165d08732120de11364701a5f5d0f9a7f Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sun, 18 Nov 2018 18:45:20 -0500 Subject: [PATCH 26/26] configure_input: Use Joycons Docked instead of Connected as label --- src/yuzu/configuration/configure_input.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yuzu/configuration/configure_input.ui b/src/yuzu/configuration/configure_input.ui index 8beae959e..dae8277bc 100644 --- a/src/yuzu/configuration/configure_input.ui +++ b/src/yuzu/configuration/configure_input.ui @@ -317,7 +317,7 @@ - Connected + Joycons Docked