Compare commits

..

4 Commits

Author SHA1 Message Date
Lioncash
0ca91ced2d virtual_buffer: Add compile-time type-safety guarantees with VirtualBuffer
VirtualBuffer makes use of VirtualAlloc (on Windows) and mmap() (on
other platforms). Neither of these ensure that non-trivial objects are
properly constructed in the allocated memory.

To prevent potential undefined behavior occurring due to that, we can
add a static assert to loudly complain about cases where that is done.
2020-11-17 20:09:58 -05:00
Lioncash
b3c8997829 page_table: Allow page tables to be moved
Makes page tables and virtual buffers able to be moved, but not copied,
making the interface more flexible.

Previously, with the destructor specified, but no move assignment or
constructor specified, they wouldn't be implicitly generated.
2020-11-17 20:08:20 -05:00
Lioncash
3cfd962ef4 page_table: Add missing doxygen parameters to Resize()
Resolves two -Wdocumentation warnings.
2020-11-17 19:45:20 -05:00
Lioncash
0890451c55 page_table: Remove unnecessary header inclusions
Prevents indirect inclusions for these headers.
2020-11-17 19:43:27 -05:00
76 changed files with 1686 additions and 3479 deletions

View File

@@ -1,7 +1,3 @@
QAbstractSpinBox {
min-height: 19px;
}
QPushButton#TogglableStatusBarButton {
color: #959595;
border: 1px solid transparent;
@@ -39,10 +35,10 @@ QPushButton#RendererStatusBarButton:!checked {
}
QPushButton#buttonRefreshDevices {
min-width: 21px;
min-height: 21px;
max-width: 21px;
max-height: 21px;
min-width: 20px;
min-height: 20px;
max-width: 20px;
max-height: 20px;
}
QWidget#bottomPerGameInput,
@@ -75,7 +71,7 @@ QWidget#middleControllerApplet {
QWidget#topPerGameInput QComboBox,
QWidget#middleControllerApplet QComboBox {
width: 120px;
width: 123px;
}
QWidget#connectedControllers {

View File

@@ -99,19 +99,12 @@ QGroupBox::indicator:unchecked:disabled {
}
QRadioButton {
color: #eff0f1;
spacing: 3px;
padding: 0px;
border: none;
spacing: 5px;
outline: none;
color: #eff0f1;
margin-bottom: 2px;
}
QGroupBox QRadioButton {
padding-left: 0px;
padding-right: 7px;
}
QRadioButton:disabled {
color: #76797C;
}
@@ -529,12 +522,13 @@ QToolButton#qt_toolbar_ext_button {
QPushButton {
color: #eff0f1;
border: 1px solid #54575B;
border-width: 1px;
border-color: #54575B;
border-style: solid;
padding: 6px 4px;
border-radius: 2px;
padding: 5px 0px 5px 0px;
outline: none;
min-width: 100px;
min-height: 13px;
background-color: #232629;
}
@@ -559,9 +553,8 @@ QComboBox {
selection-background-color: #3daee9;
border: 1px solid #54575B;
border-radius: 2px;
padding: 0px 4px 0px 4px;
min-width: 60px;
min-height: 23px;
padding: 4px 6px;
min-width: 75px;
background-color: #232629;
}
@@ -615,26 +608,26 @@ QComboBox::down-arrow:focus {
}
QAbstractSpinBox {
padding: 4px 6px;
border: 1px solid #54575B;
background-color: #232629;
color: #eff0f1;
border-radius: 2px;
min-width: 52px;
min-height: 23px;
min-width: 75px;
}
QAbstractSpinBox:up-button {
background-color: transparent;
subcontrol-origin: border;
subcontrol-position: center right;
left: -2px;
left: -6px;
}
QAbstractSpinBox:down-button {
background-color: transparent;
subcontrol-origin: border;
subcontrol-position: center left;
right: -2px;
right: -6px;
}
QAbstractSpinBox::up-arrow,
@@ -1284,33 +1277,41 @@ QPushButton#RendererStatusBarButton:!checked {
}
QPushButton#buttonRefreshDevices {
min-width: 23px;
min-height: 23px;
max-width: 23px;
max-height: 23px;
min-width: 24px;
min-height: 24px;
max-width: 24px;
max-height: 24px;
padding: 0px 0px;
}
QSpinBox#spinboxLStickRange,
QSpinBox#spinboxRStickRange,
QSpinBox#vibrationSpinPlayer1,
QSpinBox#vibrationSpinPlayer2,
QSpinBox#vibrationSpinPlayer3,
QSpinBox#vibrationSpinPlayer4,
QSpinBox#vibrationSpinPlayer5,
QSpinBox#vibrationSpinPlayer6,
QSpinBox#vibrationSpinPlayer7,
QSpinBox#vibrationSpinPlayer8 {
min-width: 68px;
QSpinBox#spinboxRStickRange {
padding: 4px 0px 5px 0px;
min-width: 63px;
}
QSpinBox#vibrationSpin {
padding: 4px 0px 5px 0px;
min-width: 63px;
}
QSpinBox#spinboxLStickRange:up-button,
QSpinBox#spinboxRStickRange:up-button,
QSpinBox#vibrationSpin:up-button {
left: -2px;
}
QSpinBox#spinboxLStickRange:down-button,
QSpinBox#spinboxRStickRange:down-button,
QSpinBox#vibrationSpin:down-button {
right: -1px;
}
QDialog#ConfigureVibration QGroupBox::indicator,
QGroupBox#motionGroup::indicator,
QGroupBox#vibrationGroup::indicator {
margin-left: 0px;
}
QDialog#ConfigureVibration QGroupBox::title,
QGroupBox#motionGroup::title,
QGroupBox#vibrationGroup::title {
spacing: 2px;
@@ -1339,7 +1340,16 @@ QWidget#middleControllerApplet {
QWidget#topPerGameInput QComboBox,
QWidget#middleControllerApplet QComboBox {
width: 120px;
width: 119px;
}
QRadioButton#radioDocked {
margin-left: -3px;
}
QRadioButton#radioUndocked {
margin-right: 5px;
}
QWidget#connectedControllers {

View File

@@ -172,8 +172,8 @@ QCheckBox {
color: #F0F0F0;
spacing: 4px;
outline: none;
padding-top: 2px;
padding-bottom: 2px;
padding-top: 4px;
padding-bottom: 4px;
}
QCheckBox:focus {
@@ -239,7 +239,7 @@ QGroupBox {
border: 1px solid #32414B;
border-radius: 4px;
margin-top: 12px;
padding: 2px;
padding: 4px;
}
QGroupBox::title {
@@ -247,7 +247,7 @@ QGroupBox::title {
subcontrol-position: top left;
padding-left: 3px;
padding-right: 5px;
padding-top: 2px;
padding-top: 4px;
}
QGroupBox::indicator {
@@ -298,11 +298,6 @@ QRadioButton {
outline: none;
}
QGroupBox QRadioButton {
padding-left: 0px;
padding-right: 7px;
}
QRadioButton:focus {
border: none;
}
@@ -326,6 +321,7 @@ QRadioButton QWidget {
QRadioButton::indicator {
border: none;
outline: none;
margin-left: 4px;
height: 16px;
width: 16px;
}
@@ -789,8 +785,14 @@ QAbstractSpinBox {
background-color: #19232D;
border: 1px solid #32414B;
color: #F0F0F0;
/* This fixes 103, 111 */
padding-top: 2px;
/* This fixes 103, 111 */
padding-bottom: 2px;
padding-left: 4px;
padding-right: 4px;
border-radius: 4px;
min-height: 19px;
/* min-width: 5px; removed to fix 109 */
}
QAbstractSpinBox:up-button {
@@ -995,11 +997,10 @@ QPushButton {
border: 1px solid #32414B;
color: #F0F0F0;
border-radius: 4px;
padding: 3px 0px 3px 0px;
padding: 3px;
outline: none;
/* Issue #194 - Special case of QPushButton inside dialogs, for better UI */
min-width: 80px;
min-height: 13px;
}
QPushButton:disabled {
@@ -1007,14 +1008,14 @@ QPushButton:disabled {
border: 1px solid #32414B;
color: #787878;
border-radius: 4px;
padding: 3px 0px 3px 0px;
padding: 3px;
}
QPushButton:checked {
background-color: #32414B;
border: 1px solid #32414B;
border-radius: 4px;
padding: 3px 0px 3px 0px;
padding: 3px;
outline: none;
}
@@ -1023,7 +1024,7 @@ QPushButton:checked:disabled {
border: 1px solid #32414B;
color: #787878;
border-radius: 4px;
padding: 3px 0px 3px 0px;
padding: 3px;
outline: none;
}
@@ -1196,9 +1197,15 @@ QComboBox {
border: 1px solid #32414B;
border-radius: 4px;
selection-background-color: #1464A0;
padding: 0px 4px 0px 4px;
min-width: 60px;
min-height: 19px;
padding-left: 4px;
padding-right: 36px;
/* 4 + 16*2 See scrollbar size */
/* Fixes #103, #111 */
min-height: 1.5em;
/* padding-top: 2px; removed to fix #132 */
/* padding-bottom: 2px; removed to fix #132 */
/* min-width: 75px; removed to fix #109 */
/* Needed to remove indicator - fix #132 */
}
QComboBox QAbstractItemView {
@@ -2191,40 +2198,29 @@ QPushButton#RendererStatusBarButton:!checked {
}
QPushButton#buttonRefreshDevices {
min-width: 19px;
min-height: 19px;
max-width: 19px;
max-height: 19px;
min-width: 20px;
min-height: 20px;
max-width: 20px;
max-height: 20px;
padding: 0px 0px;
}
QSpinBox#spinboxLStickRange,
QSpinBox#spinboxRStickRange,
QSpinBox#vibrationSpinPlayer1,
QSpinBox#vibrationSpinPlayer2,
QSpinBox#vibrationSpinPlayer3,
QSpinBox#vibrationSpinPlayer4,
QSpinBox#vibrationSpinPlayer5,
QSpinBox#vibrationSpinPlayer6,
QSpinBox#vibrationSpinPlayer7,
QSpinBox#vibrationSpinPlayer8 {
min-width: 68px;
QSpinBox#spinboxRStickRange {
min-width: 38px;
}
QDialog#ConfigureVibration QGroupBox::indicator,
QGroupBox#motionGroup::indicator,
QGroupBox#vibrationGroup::indicator {
margin-left: 0px;
}
QDialog#ConfigureVibration QGroupBox,
QWidget#bottomPerGameInput QGroupBox#motionGroup,
QWidget#bottomPerGameInput QGroupBox#vibrationGroup,
QWidget#bottomPerGameInput QGroupBox#inputConfigGroup {
padding: 0px;
}
QDialog#ConfigureVibration QGroupBox::title,
QGroupBox#motionGroup::title,
QGroupBox#vibrationGroup::title {
spacing: 2px;
@@ -2264,7 +2260,26 @@ QWidget#middleControllerApplet {
QWidget#topPerGameInput QComboBox,
QWidget#middleControllerApplet QComboBox {
width: 120px;
padding-right: 2px;
width: 127px;
}
QGroupBox#handheldGroup {
padding-left: 0px;
}
QRadioButton#radioDocked {
margin-left: -1px;
padding-left: 0px;
}
QRadioButton#radioDocked::indicator {
margin-left: 0px;
}
QRadioButton#radioUndocked {
margin-right: 2px;
}
QWidget#connectedControllers {
@@ -2337,7 +2352,7 @@ QCheckBox#checkboxPlayer5Connected,
QCheckBox#checkboxPlayer6Connected,
QCheckBox#checkboxPlayer7Connected,
QCheckBox#checkboxPlayer8Connected {
spacing: 0px;
spacing: 0px;
}
QWidget#connectedControllers QLabel {
@@ -2412,7 +2427,7 @@ QCheckBox#checkboxPlayer7Connected::indicator,
QCheckBox#checkboxPlayer8Connected::indicator {
width: 14px;
height: 14px;
margin-left: 0px;
margin-left: 2px;
}
QWidget#Player1LEDs QCheckBox::indicator:checked,

View File

@@ -8,7 +8,7 @@ namespace Common {
PageTable::PageTable() = default;
PageTable::~PageTable() = default;
PageTable::~PageTable() noexcept = default;
void PageTable::Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits,
bool has_attribute) {

View File

@@ -4,9 +4,7 @@
#pragma once
#include <vector>
#include <boost/icl/interval_map.hpp>
#include <tuple>
#include "common/common_types.h"
#include "common/memory_hook.h"
@@ -51,13 +49,21 @@ struct SpecialRegion {
*/
struct PageTable {
PageTable();
~PageTable();
~PageTable() noexcept;
PageTable(const PageTable&) = delete;
PageTable& operator=(const PageTable&) = delete;
PageTable(PageTable&&) noexcept = default;
PageTable& operator=(PageTable&&) noexcept = default;
/**
* Resizes the page table to be able to accomodate enough pages within
* a given address space.
*
* @param address_space_width_in_bits The address size width in bits.
* @param page_size_in_bits The page size in bits.
* @param has_attribute Whether or not this page has any backing attributes.
*/
void Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits,
bool has_attribute);

View File

@@ -13,7 +13,7 @@
namespace Common {
void* AllocateMemoryPages(std::size_t size) {
void* AllocateMemoryPages(std::size_t size) noexcept {
#ifdef _WIN32
void* base{VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_READWRITE)};
#else
@@ -29,7 +29,7 @@ void* AllocateMemoryPages(std::size_t size) {
return base;
}
void FreeMemoryPages(void* base, [[maybe_unused]] std::size_t size) {
void FreeMemoryPages(void* base, [[maybe_unused]] std::size_t size) noexcept {
if (!base) {
return;
}

View File

@@ -4,25 +4,44 @@
#pragma once
#include "common/common_funcs.h"
#include <type_traits>
#include <utility>
namespace Common {
void* AllocateMemoryPages(std::size_t size);
void FreeMemoryPages(void* base, std::size_t size);
void* AllocateMemoryPages(std::size_t size) noexcept;
void FreeMemoryPages(void* base, std::size_t size) noexcept;
template <typename T>
class VirtualBuffer final : NonCopyable {
class VirtualBuffer final {
public:
static_assert(
std::is_trivially_constructible_v<T>,
"T must be trivially constructible, as non-trivial constructors will not be executed "
"with the current allocator");
constexpr VirtualBuffer() = default;
explicit VirtualBuffer(std::size_t count) : alloc_size{count * sizeof(T)} {
base_ptr = reinterpret_cast<T*>(AllocateMemoryPages(alloc_size));
}
~VirtualBuffer() {
~VirtualBuffer() noexcept {
FreeMemoryPages(base_ptr, alloc_size);
}
VirtualBuffer(const VirtualBuffer&) = delete;
VirtualBuffer& operator=(const VirtualBuffer&) = delete;
VirtualBuffer(VirtualBuffer&& other) noexcept
: alloc_size{std::exchange(other.alloc_size, 0)}, base_ptr{std::exchange(other.base_ptr),
nullptr} {}
VirtualBuffer& operator=(VirtualBuffer&& other) noexcept {
alloc_size = std::exchange(other.alloc_size, 0);
base_ptr = std::exchange(other.base_ptr, nullptr);
return *this;
}
void resize(std::size_t count) {
FreeMemoryPages(base_ptr, alloc_size);

View File

@@ -27,19 +27,19 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb
->GetAppletResource()
->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad);
auto& players = Settings::values.players.GetValue();
auto& players = Settings::values.players;
const std::size_t min_supported_players =
parameters.enable_single_mode ? 1 : parameters.min_players;
// Disconnect Handheld first.
npad.DisconnectNpadAtIndex(8);
npad.DisconnectNPadAtIndex(8);
// Deduce the best configuration based on the input parameters.
for (std::size_t index = 0; index < players.size() - 2; ++index) {
// First, disconnect all controllers regardless of the value of keep_controllers_connected.
// This makes it easy to connect the desired controllers.
npad.DisconnectNpadAtIndex(index);
npad.DisconnectNPadAtIndex(index);
// Only connect the minimum number of required players.
if (index >= min_supported_players) {
@@ -66,7 +66,7 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb
npad.MapSettingsTypeToNPad(Settings::ControllerType::RightJoycon), index);
}
} else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld &&
!Settings::values.use_docked_mode.GetValue()) {
!Settings::values.use_docked_mode) {
// We should *never* reach here under any normal circumstances.
npad.AddNewControllerAt(npad.MapSettingsTypeToNPad(Settings::ControllerType::Handheld),
index);

View File

@@ -47,7 +47,7 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height) {
FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) {
u32 width, height;
if (Settings::values.use_docked_mode.GetValue()) {
if (Settings::values.use_docked_mode) {
width = ScreenDocked::Width * res_scale;
height = ScreenDocked::Height * res_scale;
} else {

View File

@@ -33,7 +33,7 @@ public:
virtual bool GetAnalogDirectionStatus(AnalogDirection direction) const {
return {};
}
virtual bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const {
virtual bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const {
return {};
}
};
@@ -121,13 +121,6 @@ using ButtonDevice = InputDevice<bool>;
*/
using AnalogDevice = InputDevice<std::tuple<float, float>>;
/**
* A vibration device is an input device that returns an unsigned byte as status.
* It represents whether the vibration device supports vibration or not.
* If the status returns 1, it supports vibration. Otherwise, it does not support vibration.
*/
using VibrationDevice = InputDevice<u8>;
/**
* A motion status is an object that returns a tuple of accelerometer state vector,
* gyroscope state vector, rotation state vector and orientation state matrix.

View File

@@ -751,7 +751,7 @@ void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext&
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
if (Settings::values.use_docked_mode.GetValue()) {
if (Settings::values.use_docked_mode) {
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) *
static_cast<u32>(Settings::values.resolution_factor.GetValue()));
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) *
@@ -824,7 +824,7 @@ void IStorage::Open(Kernel::HLERequestContext& ctx) {
}
void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) {
const bool use_docked_mode{Settings::values.use_docked_mode.GetValue()};
const bool use_docked_mode{Settings::values.use_docked_mode};
LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
IPC::ResponseBuilder rb{ctx, 3};

View File

@@ -25,7 +25,7 @@ namespace Service::AM::Applets {
static Core::Frontend::ControllerParameters ConvertToFrontendParameters(
ControllerSupportArgPrivate private_arg, ControllerSupportArgHeader header, bool enable_text,
std::vector<IdentificationColor> identification_colors, std::vector<ExplainText> text) {
HID::Controller_NPad::NpadStyleSet npad_style_set;
HID::Controller_NPad::NPadType npad_style_set;
npad_style_set.raw = private_arg.style_set;
return {
@@ -222,7 +222,7 @@ void Controller::Execute() {
void Controller::ConfigurationComplete() {
ControllerSupportResultInfo result_info{};
const auto& players = Settings::values.players.GetValue();
const auto& players = Settings::values.players;
// If enable_single_mode is enabled, player_count is 1 regardless of any other parameters.
// Otherwise, only count connected players from P1-P8.

View File

@@ -69,8 +69,7 @@ void Controller::SetFromCpuBoostMode(CpuBoostMode mode) {
}
PerformanceMode Controller::GetCurrentPerformanceMode() const {
return Settings::values.use_docked_mode.GetValue() ? PerformanceMode::Docked
: PerformanceMode::Handheld;
return Settings::values.use_docked_mode ? PerformanceMode::Docked : PerformanceMode::Handheld;
}
PerformanceConfiguration Controller::GetCurrentPerformanceConfiguration(PerformanceMode mode) {

View File

@@ -117,10 +117,7 @@ u32 Controller_NPad::IndexToNPad(std::size_t index) {
}
Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {}
Controller_NPad::~Controller_NPad() {
OnRelease();
}
Controller_NPad::~Controller_NPad() = default;
void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
const auto controller_type = connected_controllers[controller_idx].type;
@@ -142,7 +139,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
controller.properties.is_vertical.Assign(1);
controller.properties.use_plus.Assign(1);
controller.properties.use_minus.Assign(1);
controller.pad_assignment = NpadAssignments::Single;
controller.pad_assignment = NPadAssignments::Single;
break;
case NPadControllerType::Handheld:
controller.joy_styles.handheld.Assign(1);
@@ -150,7 +147,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
controller.properties.is_vertical.Assign(1);
controller.properties.use_plus.Assign(1);
controller.properties.use_minus.Assign(1);
controller.pad_assignment = NpadAssignments::Dual;
controller.pad_assignment = NPadAssignments::Dual;
break;
case NPadControllerType::JoyDual:
controller.joy_styles.joycon_dual.Assign(1);
@@ -159,26 +156,26 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
controller.properties.is_vertical.Assign(1);
controller.properties.use_plus.Assign(1);
controller.properties.use_minus.Assign(1);
controller.pad_assignment = NpadAssignments::Dual;
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;
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;
controller.pad_assignment = NPadAssignments::Single;
break;
case NPadControllerType::Pokeball:
controller.joy_styles.pokeball.Assign(1);
controller.device_type.pokeball.Assign(1);
controller.pad_assignment = NpadAssignments::Single;
controller.pad_assignment = NPadAssignments::Single;
break;
}
@@ -187,14 +184,11 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
controller.single_color.button_color = 0;
controller.dual_color_error = ColorReadError::ReadOk;
controller.left_color.body_color =
Settings::values.players.GetValue()[controller_idx].body_color_left;
controller.left_color.button_color =
Settings::values.players.GetValue()[controller_idx].button_color_left;
controller.right_color.body_color =
Settings::values.players.GetValue()[controller_idx].body_color_right;
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.GetValue()[controller_idx].button_color_right;
Settings::values.players[controller_idx].button_color_right;
controller.battery_level[0] = BATTERY_FULL;
controller.battery_level[1] = BATTERY_FULL;
@@ -205,7 +199,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
void Controller_NPad::OnInit() {
auto& kernel = system.Kernel();
for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) {
for (std::size_t i = 0; i < styleset_changed_events.size(); i++) {
styleset_changed_events[i] = Kernel::WritableEvent::CreateEventPair(
kernel, fmt::format("npad:NpadStyleSetChanged_{}", i));
}
@@ -214,8 +208,6 @@ void Controller_NPad::OnInit() {
return;
}
OnLoadInputDevices();
if (style.raw == 0) {
// We want to support all controllers
style.handheld.Assign(1);
@@ -226,27 +218,12 @@ void Controller_NPad::OnInit() {
style.pokeball.Assign(1);
}
std::transform(Settings::values.players.GetValue().begin(),
Settings::values.players.GetValue().end(), connected_controllers.begin(),
[](const Settings::PlayerInput& player) {
std::transform(Settings::values.players.begin(), Settings::values.players.end(),
connected_controllers.begin(), [](const Settings::PlayerInput& player) {
return ControllerHolder{MapSettingsTypeToNPad(player.controller_type),
player.connected};
});
// Connect the Player 1 or Handheld controller if none are connected.
if (std::none_of(connected_controllers.begin(), connected_controllers.end(),
[](const ControllerHolder& controller) { return controller.is_connected; })) {
const auto controller =
MapSettingsTypeToNPad(Settings::values.players.GetValue()[0].controller_type);
if (controller == NPadControllerType::Handheld) {
Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true;
connected_controllers[HANDHELD_INDEX] = {controller, true};
} else {
Settings::values.players.GetValue()[0].connected = true;
connected_controllers[0] = {controller, true};
}
}
// Account for handheld
if (connected_controllers[HANDHELD_INDEX].is_connected) {
connected_controllers[HANDHELD_INDEX].type = NPadControllerType::Handheld;
@@ -265,7 +242,7 @@ void Controller_NPad::OnInit() {
}
void Controller_NPad::OnLoadInputDevices() {
const auto& players = Settings::values.players.GetValue();
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,
@@ -273,26 +250,13 @@ void Controller_NPad::OnLoadInputDevices() {
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<Input::AnalogDevice>);
std::transform(players[i].vibrations.begin() +
Settings::NativeVibration::VIBRATION_HID_BEGIN,
players[i].vibrations.begin() + Settings::NativeVibration::VIBRATION_HID_END,
vibrations[i].begin(), Input::CreateDevice<Input::VibrationDevice>);
std::transform(players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN,
players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_END,
motions[i].begin(), Input::CreateDevice<Input::MotionDevice>);
for (std::size_t device_idx = 0; device_idx < vibrations[i].size(); ++device_idx) {
InitializeVibrationDeviceAtIndex(i, device_idx);
}
}
}
void Controller_NPad::OnRelease() {
for (std::size_t npad_idx = 0; npad_idx < vibrations.size(); ++npad_idx) {
for (std::size_t device_idx = 0; device_idx < vibrations[npad_idx].size(); ++device_idx) {
VibrateControllerAtIndex(npad_idx, device_idx, {});
}
}
}
void Controller_NPad::OnRelease() {}
void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
const auto controller_idx = NPadIdToIndex(npad_id);
@@ -375,7 +339,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
if (!IsControllerActivated()) {
return;
}
for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) {
for (std::size_t i = 0; i < shared_memory_entries.size(); i++) {
auto& npad = shared_memory_entries[i];
const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states,
&npad.handheld_states,
@@ -517,7 +481,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
if (!IsControllerActivated()) {
return;
}
for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) {
for (std::size_t i = 0; i < shared_memory_entries.size(); i++) {
auto& npad = shared_memory_entries[i];
const auto& controller_type = connected_controllers[i].type;
@@ -551,7 +515,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
// Try to read sixaxis sensor states
std::array<MotionDevice, 2> motion_devices;
if (sixaxis_sensors_enabled && Settings::values.motion_enabled.GetValue()) {
if (sixaxis_sensors_enabled && Settings::values.motion_enabled) {
sixaxis_at_rest = true;
for (std::size_t e = 0; e < motion_devices.size(); ++e) {
const auto& device = motions[i][e];
@@ -637,15 +601,15 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
shared_memory_entries.size() * sizeof(NPadEntry));
}
void Controller_NPad::SetSupportedStyleSet(NpadStyleSet style_set) {
void Controller_NPad::SetSupportedStyleSet(NPadType style_set) {
style.raw = style_set.raw;
}
Controller_NPad::NpadStyleSet Controller_NPad::GetSupportedStyleSet() const {
Controller_NPad::NPadType Controller_NPad::GetSupportedStyleSet() const {
return style;
}
void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) {
void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) {
ASSERT(length > 0 && (length % sizeof(u32)) == 0);
supported_npad_id_types.clear();
supported_npad_id_types.resize(length / sizeof(u32));
@@ -657,7 +621,7 @@ void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length)
std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size());
}
std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const {
std::size_t Controller_NPad::GetSupportedNPadIdTypesSize() const {
return supported_npad_id_types.size();
}
@@ -677,7 +641,7 @@ Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActi
return handheld_activation_mode;
}
void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) {
void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) {
const std::size_t npad_index = NPadIdToIndex(npad_id);
ASSERT(npad_index < shared_memory_entries.size());
if (shared_memory_entries[npad_index].pad_assignment != assignment_mode) {
@@ -685,140 +649,35 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode)
}
}
bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index,
const VibrationValue& vibration_value) {
if (!connected_controllers[npad_index].is_connected || !vibrations[npad_index][device_index]) {
return false;
void Controller_NPad::VibrateController(const std::vector<u32>& controllers,
const std::vector<Vibration>& vibrations) {
LOG_TRACE(Service_HID, "called");
if (!Settings::values.vibration_enabled || !can_controllers_vibrate) {
return;
}
const auto& player = Settings::values.players.GetValue()[npad_index];
if (!player.vibration_enabled) {
if (latest_vibration_values[npad_index][device_index].amp_low != 0.0f ||
latest_vibration_values[npad_index][device_index].amp_high != 0.0f) {
// Send an empty vibration to stop any vibrations.
vibrations[npad_index][device_index]->SetRumblePlay(0.0f, 160.0f, 0.0f, 320.0f);
// Then reset the vibration value to its default value.
latest_vibration_values[npad_index][device_index] = {};
bool success = true;
for (std::size_t i = 0; i < controllers.size(); ++i) {
if (!connected_controllers[i].is_connected) {
continue;
}
return false;
}
if (!Settings::values.enable_accurate_vibrations.GetValue()) {
using std::chrono::duration_cast;
using std::chrono::milliseconds;
using std::chrono::steady_clock;
const auto now = steady_clock::now();
// Filter out non-zero vibrations that are within 10ms of each other.
if ((vibration_value.amp_low != 0.0f || vibration_value.amp_high != 0.0f) &&
duration_cast<milliseconds>(now - last_vibration_timepoints[npad_index][device_index]) <
milliseconds(10)) {
return false;
using namespace Settings::NativeButton;
const auto& button_state = buttons[i];
if (button_state[A - BUTTON_HID_BEGIN]) {
if (button_state[A - BUTTON_HID_BEGIN]->SetRumblePlay(
vibrations[0].amp_high, vibrations[0].amp_low, vibrations[0].freq_high,
vibrations[0].freq_low)) {
success = false;
}
}
last_vibration_timepoints[npad_index][device_index] = now;
}
auto& vibration = vibrations[npad_index][device_index];
const auto player_vibration_strength = static_cast<f32>(player.vibration_strength);
const auto amp_low =
std::min(vibration_value.amp_low * player_vibration_strength / 100.0f, 1.0f);
const auto amp_high =
std::min(vibration_value.amp_high * player_vibration_strength / 100.0f, 1.0f);
return vibration->SetRumblePlay(amp_low, vibration_value.freq_low, amp_high,
vibration_value.freq_high);
}
void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle,
const VibrationValue& vibration_value) {
if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
return;
}
const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
if (!vibration_devices_mounted[npad_index][device_index] ||
!connected_controllers[npad_index].is_connected) {
return;
}
if (vibration_device_handle.device_index == DeviceIndex::None) {
UNREACHABLE_MSG("DeviceIndex should never be None!");
return;
}
// Some games try to send mismatched parameters in the device handle, block these.
if ((connected_controllers[npad_index].type == NPadControllerType::JoyLeft &&
(vibration_device_handle.npad_type == NpadType::JoyconRight ||
vibration_device_handle.device_index == DeviceIndex::Right)) ||
(connected_controllers[npad_index].type == NPadControllerType::JoyRight &&
(vibration_device_handle.npad_type == NpadType::JoyconLeft ||
vibration_device_handle.device_index == DeviceIndex::Left))) {
return;
}
// Filter out vibrations with equivalent values to reduce unnecessary state changes.
if (vibration_value.amp_low == latest_vibration_values[npad_index][device_index].amp_low &&
vibration_value.amp_high == latest_vibration_values[npad_index][device_index].amp_high) {
return;
}
if (VibrateControllerAtIndex(npad_index, device_index, vibration_value)) {
latest_vibration_values[npad_index][device_index] = vibration_value;
if (success) {
last_processed_vibration = vibrations.back();
}
}
void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles,
const std::vector<VibrationValue>& vibration_values) {
if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
return;
}
ASSERT_OR_EXECUTE_MSG(
vibration_device_handles.size() == vibration_values.size(), { return; },
"The amount of device handles does not match with the amount of vibration values,"
"this is undefined behavior!");
for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) {
VibrateController(vibration_device_handles[i], vibration_values[i]);
}
}
Controller_NPad::VibrationValue Controller_NPad::GetLastVibration(
const DeviceHandle& vibration_device_handle) const {
const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
return latest_vibration_values[npad_index][device_index];
}
void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) {
const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
InitializeVibrationDeviceAtIndex(npad_index, device_index);
}
void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index,
std::size_t device_index) {
if (vibrations[npad_index][device_index]) {
vibration_devices_mounted[npad_index][device_index] =
vibrations[npad_index][device_index]->GetStatus() == 1;
} else {
vibration_devices_mounted[npad_index][device_index] = false;
}
}
void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) {
permit_vibration_session_enabled = permit_vibration_session;
}
bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const {
const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
return vibration_devices_mounted[npad_index][device_index];
Controller_NPad::Vibration Controller_NPad::GetLastVibration() const {
return last_processed_vibration;
}
std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const {
@@ -837,38 +696,31 @@ void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::siz
void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index,
bool connected) {
if (!connected) {
DisconnectNpadAtIndex(npad_index);
DisconnectNPadAtIndex(npad_index);
return;
}
if (controller == NPadControllerType::Handheld) {
Settings::values.players.GetValue()[HANDHELD_INDEX].controller_type =
Settings::values.players[HANDHELD_INDEX].controller_type =
MapNPadToSettingsType(controller);
Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true;
Settings::values.players[HANDHELD_INDEX].connected = true;
connected_controllers[HANDHELD_INDEX] = {controller, true};
InitNewlyAddedController(HANDHELD_INDEX);
return;
}
Settings::values.players.GetValue()[npad_index].controller_type =
MapNPadToSettingsType(controller);
Settings::values.players.GetValue()[npad_index].connected = true;
Settings::values.players[npad_index].controller_type = MapNPadToSettingsType(controller);
Settings::values.players[npad_index].connected = true;
connected_controllers[npad_index] = {controller, true};
InitNewlyAddedController(npad_index);
}
void Controller_NPad::DisconnectNpad(u32 npad_id) {
DisconnectNpadAtIndex(NPadIdToIndex(npad_id));
void Controller_NPad::DisconnectNPad(u32 npad_id) {
DisconnectNPadAtIndex(NPadIdToIndex(npad_id));
}
void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) {
for (std::size_t device_idx = 0; device_idx < vibrations[npad_index].size(); ++device_idx) {
// Send an empty vibration to stop any vibrations.
VibrateControllerAtIndex(npad_index, device_idx, {});
vibration_devices_mounted[npad_index][device_idx] = false;
}
Settings::values.players.GetValue()[npad_index].connected = false;
void Controller_NPad::DisconnectNPadAtIndex(std::size_t npad_index) {
Settings::values.players[npad_index].connected = false;
connected_controllers[npad_index].is_connected = false;
auto& controller = shared_memory_entries[npad_index];
@@ -906,7 +758,7 @@ void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) {
(connected_controllers[npad_index_2].type == NPadControllerType::JoyLeft &&
connected_controllers[npad_index_1].type == NPadControllerType::JoyRight)) {
// Disconnect the joycon at the second id and connect the dual joycon at the first index.
DisconnectNpad(npad_id_2);
DisconnectNPad(npad_id_2);
AddNewControllerAt(NPadControllerType::JoyDual, npad_index_1);
}
}
@@ -978,6 +830,14 @@ void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_prot
unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled;
}
void Controller_NPad::SetVibrationEnabled(bool can_vibrate) {
can_controllers_vibrate = can_vibrate;
}
bool Controller_NPad::IsVibrationEnabled() const {
return can_controllers_vibrate;
}
void Controller_NPad::ClearAllConnectedControllers() {
for (auto& controller : connected_controllers) {
if (controller.is_connected && controller.type != NPadControllerType::None) {
@@ -1022,7 +882,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
return false;
}
// Handheld should not be supported in docked mode
if (Settings::values.use_docked_mode.GetValue()) {
if (Settings::values.use_docked_mode) {
return false;
}

View File

@@ -39,62 +39,7 @@ public:
// Called when input devices should be loaded
void OnLoadInputDevices() override;
enum class NPadControllerType {
None,
ProController,
Handheld,
JoyDual,
JoyLeft,
JoyRight,
Pokeball,
};
enum class NpadType : u8 {
ProController = 3,
Handheld = 4,
JoyconDual = 5,
JoyconLeft = 6,
JoyconRight = 7,
Pokeball = 9,
};
enum class DeviceIndex : u8 {
Left = 0,
Right = 1,
None = 2,
};
enum class GyroscopeZeroDriftMode : u32 {
Loose = 0,
Standard = 1,
Tight = 2,
};
enum class NpadHoldType : u64 {
Vertical = 0,
Horizontal = 1,
};
enum class NpadAssignments : u32 {
Dual = 0,
Single = 1,
};
enum class NpadHandheldActivationMode : u64 {
Dual = 0,
Single = 1,
None = 2,
};
struct DeviceHandle {
NpadType npad_type{};
u8 npad_id{};
DeviceIndex device_index{};
INSERT_PADDING_BYTES(1);
};
static_assert(sizeof(DeviceHandle) == 4, "DeviceHandle is an invalid size");
struct NpadStyleSet {
struct NPadType {
union {
u32_le raw{};
@@ -107,15 +52,47 @@ public:
BitField<6, 1, u32> pokeball; // TODO(ogniK): Confirm when possible
};
};
static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size");
static_assert(sizeof(NPadType) == 4, "NPadType is an invalid size");
struct VibrationValue {
f32 amp_low{0.0f};
f32 freq_low{160.0f};
f32 amp_high{0.0f};
f32 freq_high{320.0f};
struct Vibration {
f32 amp_low;
f32 freq_low;
f32 amp_high;
f32 freq_high;
};
static_assert(sizeof(Vibration) == 0x10, "Vibration is an invalid size");
enum class GyroscopeZeroDriftMode : u32 {
Loose = 0,
Standard = 1,
Tight = 2,
};
enum class NpadHoldType : u64 {
Vertical = 0,
Horizontal = 1,
};
enum class NPadAssignments : u32_le {
Dual = 0,
Single = 1,
};
enum class NpadHandheldActivationMode : u64 {
Dual = 0,
Single = 1,
None = 2,
};
enum class NPadControllerType {
None,
ProController,
Handheld,
JoyDual,
JoyLeft,
JoyRight,
Pokeball,
};
static_assert(sizeof(VibrationValue) == 0x10, "Vibration is an invalid size");
struct LedPattern {
explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) {
@@ -133,12 +110,12 @@ public:
};
};
void SetSupportedStyleSet(NpadStyleSet style_set);
NpadStyleSet GetSupportedStyleSet() const;
void SetSupportedStyleSet(NPadType style_set);
NPadType GetSupportedStyleSet() const;
void SetSupportedNpadIdTypes(u8* data, std::size_t length);
void SetSupportedNPadIdTypes(u8* data, std::size_t length);
void GetSupportedNpadIdTypes(u32* data, std::size_t max_length);
std::size_t GetSupportedNpadIdTypesSize() const;
std::size_t GetSupportedNPadIdTypesSize() const;
void SetHoldType(NpadHoldType joy_hold_type);
NpadHoldType GetHoldType() const;
@@ -146,26 +123,12 @@ public:
void SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode);
NpadHandheldActivationMode GetNpadHandheldActivationMode() const;
void SetNpadMode(u32 npad_id, NpadAssignments assignment_mode);
void SetNpadMode(u32 npad_id, NPadAssignments assignment_mode);
bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index,
const VibrationValue& vibration_value);
void VibrateController(const std::vector<u32>& controllers,
const std::vector<Vibration>& vibrations);
void VibrateController(const DeviceHandle& vibration_device_handle,
const VibrationValue& vibration_value);
void VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles,
const std::vector<VibrationValue>& vibration_values);
VibrationValue GetLastVibration(const DeviceHandle& vibration_device_handle) const;
void InitializeVibrationDevice(const DeviceHandle& vibration_device_handle);
void InitializeVibrationDeviceAtIndex(std::size_t npad_index, std::size_t device_index);
void SetPermitVibrationSession(bool permit_vibration_session);
bool IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const;
Vibration GetLastVibration() const;
std::shared_ptr<Kernel::ReadableEvent> GetStyleSetChangedEvent(u32 npad_id) const;
void SignalStyleSetChangedEvent(u32 npad_id) const;
@@ -175,8 +138,8 @@ public:
// Adds a new controller at an index with connection status.
void UpdateControllerAt(NPadControllerType controller, std::size_t npad_index, bool connected);
void DisconnectNpad(u32 npad_id);
void DisconnectNpadAtIndex(std::size_t index);
void DisconnectNPad(u32 npad_id);
void DisconnectNPadAtIndex(std::size_t index);
void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode);
GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const;
@@ -185,6 +148,8 @@ public:
LedPattern GetLedPattern(u32 npad_id);
bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const;
void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id);
void SetVibrationEnabled(bool can_vibrate);
bool IsVibrationEnabled() const;
void ClearAllConnectedControllers();
void DisconnectAllConnectedControllers();
void ConnectAllDisconnectedControllers();
@@ -359,8 +324,8 @@ private:
};
struct NPadEntry {
NpadStyleSet joy_styles;
NpadAssignments pad_assignment;
NPadType joy_styles;
NPadAssignments pad_assignment;
ColorReadError single_color_error;
ControllerColor single_color;
@@ -403,7 +368,7 @@ private:
u32 press_state{};
NpadStyleSet style{};
NPadType style{};
std::array<NPadEntry, 10> shared_memory_entries{};
using ButtonArray = std::array<
std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>,
@@ -411,28 +376,22 @@ private:
using StickArray = std::array<
std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>,
10>;
using VibrationArray = std::array<std::array<std::unique_ptr<Input::VibrationDevice>,
Settings::NativeVibration::NUM_VIBRATIONS_HID>,
10>;
using MotionArray = std::array<
std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTIONS_HID>,
std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTION_HID>,
10>;
ButtonArray buttons;
StickArray sticks;
VibrationArray vibrations;
MotionArray motions;
std::vector<u32> supported_npad_id_types{};
NpadHoldType hold_type{NpadHoldType::Vertical};
NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual};
// Each controller should have their own styleset changed event
std::array<Kernel::EventPair, 10> styleset_changed_events;
std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10> last_vibration_timepoints;
std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{};
bool permit_vibration_session_enabled{false};
std::array<std::array<bool, 2>, 10> vibration_devices_mounted{};
Vibration last_processed_vibration{};
std::array<ControllerHolder, 10> connected_controllers{};
std::array<bool, 10> unintended_home_button_input_protection{};
GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
bool can_controllers_vibrate{true};
bool sixaxis_sensors_enabled{true};
bool sixaxis_at_rest{true};
std::array<ControllerPad, 10> npad_pad_states{};

File diff suppressed because it is too large Load Diff

View File

@@ -86,15 +86,17 @@ public:
private:
void CreateAppletResource(Kernel::HLERequestContext& ctx);
void ActivateXpad(Kernel::HLERequestContext& ctx);
void GetXpadIDs(Kernel::HLERequestContext& ctx);
void ActivateSixAxisSensor(Kernel::HLERequestContext& ctx);
void DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx);
void ActivateDebugPad(Kernel::HLERequestContext& ctx);
void ActivateTouchScreen(Kernel::HLERequestContext& ctx);
void ActivateMouse(Kernel::HLERequestContext& ctx);
void ActivateKeyboard(Kernel::HLERequestContext& ctx);
void SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx);
void ActivateXpad(Kernel::HLERequestContext& ctx);
void GetXpadIDs(Kernel::HLERequestContext& ctx);
void ActivateSixAxisSensor(Kernel::HLERequestContext& ctx);
void DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx);
void ActivateGesture(Kernel::HLERequestContext& ctx);
void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx);
void StartSixAxisSensor(Kernel::HLERequestContext& ctx);
void StopSixAxisSensor(Kernel::HLERequestContext& ctx);
void EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx);
@@ -102,7 +104,6 @@ private:
void GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx);
void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx);
void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx);
void ActivateGesture(Kernel::HLERequestContext& ctx);
void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx);
void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx);
void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx);
@@ -111,7 +112,6 @@ private:
void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx);
void DisconnectNpad(Kernel::HLERequestContext& ctx);
void GetPlayerLedPattern(Kernel::HLERequestContext& ctx);
void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx);
void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx);
void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx);
void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx);
@@ -125,16 +125,15 @@ private:
void SwapNpadAssignment(Kernel::HLERequestContext& ctx);
void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx);
void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx);
void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx);
void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx);
void EndPermitVibrationSession(Kernel::HLERequestContext& ctx);
void SendVibrationValue(Kernel::HLERequestContext& ctx);
void SendVibrationValues(Kernel::HLERequestContext& ctx);
void GetActualVibrationValue(Kernel::HLERequestContext& ctx);
void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx);
void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx);
void PermitVibration(Kernel::HLERequestContext& ctx);
void IsVibrationPermitted(Kernel::HLERequestContext& ctx);
void SendVibrationValues(Kernel::HLERequestContext& ctx);
void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx);
void EndPermitVibrationSession(Kernel::HLERequestContext& ctx);
void IsVibrationDeviceMounted(Kernel::HLERequestContext& ctx);
void ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx);
void StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx);
void StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx);
@@ -147,22 +146,6 @@ private:
void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx);
void SetPalmaBoostMode(Kernel::HLERequestContext& ctx);
enum class VibrationDeviceType : u32 {
LinearResonantActuator = 1,
};
enum class VibrationDevicePosition : u32 {
None = 0,
Left = 1,
Right = 2,
};
struct VibrationDeviceInfo {
VibrationDeviceType type{};
VibrationDevicePosition position{};
};
static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incorrect size.");
std::shared_ptr<IAppletResource> applet_resource;
Core::System& system;
};

View File

@@ -771,7 +771,7 @@ private:
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS);
if (Settings::values.use_docked_mode.GetValue()) {
if (Settings::values.use_docked_mode) {
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) *
static_cast<u32>(Settings::values.resolution_factor.GetValue()));
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) *

View File

@@ -49,7 +49,7 @@ void LogSettings() {
};
LOG_INFO(Config, "yuzu Configuration:");
log_setting("Controls_UseDockedMode", values.use_docked_mode.GetValue());
log_setting("Controls_UseDockedMode", values.use_docked_mode);
log_setting("System_RngSeed", values.rng_seed.GetValue().value_or(0));
log_setting("System_CurrentUser", values.current_user);
log_setting("System_LanguageIndex", values.language_index.GetValue());
@@ -145,12 +145,6 @@ void RestoreGlobalState() {
values.rng_seed.SetGlobal(true);
values.custom_rtc.SetGlobal(true);
values.sound_index.SetGlobal(true);
// Controls
values.players.SetGlobal(true);
values.use_docked_mode.SetGlobal(true);
values.vibration_enabled.SetGlobal(true);
values.motion_enabled.SetGlobal(true);
}
void Sanitize() {

View File

@@ -65,38 +65,6 @@ private:
Type local{};
};
/**
* The InputSetting class allows for getting a reference to either the global or local members.
* This is required as we cannot easily modify the values of user-defined types within containers
* using the SetValue() member function found in the Setting class. The primary purpose of this
* class is to store an array of 10 PlayerInput structs for both the global and local (per-game)
* setting and allows for easily accessing and modifying both settings.
*/
template <typename Type>
class InputSetting final {
public:
InputSetting() = default;
explicit InputSetting(Type val) : global{val} {}
~InputSetting() = default;
void SetGlobal(bool to_global) {
use_global = to_global;
}
bool UsingGlobal() const {
return use_global;
}
Type& GetValue(bool need_global = false) {
if (use_global || need_global) {
return global;
}
return local;
}
private:
bool use_global = true;
Type global{};
Type local{};
};
struct TouchFromButtonMap {
std::string name;
std::vector<std::string> buttons;
@@ -165,18 +133,9 @@ struct Values {
Setting<s32> sound_index;
// Controls
InputSetting<std::array<PlayerInput, 10>> players;
std::array<PlayerInput, 10> players;
Setting<bool> use_docked_mode;
Setting<bool> vibration_enabled;
Setting<bool> enable_accurate_vibrations;
Setting<bool> motion_enabled;
std::string motion_device;
std::string udp_input_address;
u16 udp_input_port;
u8 udp_pad_index;
bool use_docked_mode;
bool mouse_enabled;
std::string mouse_device;
@@ -190,14 +149,19 @@ struct Values {
ButtonsRaw debug_pad_buttons;
AnalogsRaw debug_pad_analogs;
TouchscreenInput touchscreen;
bool vibration_enabled;
bool use_touch_from_button;
bool motion_enabled;
std::string motion_device;
std::string touch_device;
int touch_from_button_map_index;
std::vector<TouchFromButtonMap> touch_from_button_maps;
TouchscreenInput touchscreen;
std::atomic_bool is_device_reload_pending{true};
bool use_touch_from_button;
int touch_from_button_map_index;
std::string udp_input_address;
u16 udp_input_port;
u8 udp_pad_index;
std::vector<TouchFromButtonMap> touch_from_button_maps;
// Data Storage
bool use_virtual_sd;

View File

@@ -213,7 +213,7 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) {
Settings::values.use_assembly_shaders.GetValue());
AddField(field_type, "Renderer_UseAsynchronousShaders",
Settings::values.use_asynchronous_shaders.GetValue());
AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode.GetValue());
AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode);
}
bool TelemetrySession::SubmitTestcase() {

View File

@@ -230,8 +230,10 @@ void Adapter::SendVibrations() {
vibration_changed = false;
}
bool Adapter::RumblePlay(std::size_t port, u8 amplitude) {
pads[port].rumble_amplitude = amplitude;
bool Adapter::RumblePlay(std::size_t port, f32 amplitude) {
amplitude = std::clamp(amplitude, 0.0f, 1.0f);
const auto raw_amp = static_cast<u8>(amplitude * 0x8);
pads[port].rumble_amplitude = raw_amp;
return rumble_enabled;
}

View File

@@ -77,8 +77,8 @@ public:
Adapter();
~Adapter();
/// Request a vibration for a controller
bool RumblePlay(std::size_t port, u8 amplitude);
/// Request a vibration for a controlelr
bool RumblePlay(std::size_t port, f32 amplitude);
/// Used for polling
void BeginConfiguration();

View File

@@ -15,7 +15,7 @@ namespace InputCommon {
class GCButton final : public Input::ButtonDevice {
public:
explicit GCButton(u32 port_, s32 button_, const GCAdapter::Adapter* adapter)
explicit GCButton(u32 port_, s32 button_, GCAdapter::Adapter* adapter)
: port(port_), button(button_), gcadapter(adapter) {}
~GCButton() override;
@@ -27,10 +27,18 @@ public:
return false;
}
bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const override {
const float amplitude = amp_high + amp_low > 2.0f ? 1.0f : (amp_high + amp_low) * 0.5f;
const auto new_amp =
static_cast<f32>(pow(amplitude, 0.5f) * (3.0f - 2.0f * pow(amplitude, 0.15f)));
return gcadapter->RumblePlay(port, new_amp);
}
private:
const u32 port;
const s32 button;
const GCAdapter::Adapter* gcadapter;
GCAdapter::Adapter* gcadapter;
};
class GCAxisButton final : public Input::ButtonDevice {
@@ -291,42 +299,4 @@ Common::ParamPackage GCAnalogFactory::GetNextInput() {
return params;
}
class GCVibration final : public Input::VibrationDevice {
public:
explicit GCVibration(u32 port_, GCAdapter::Adapter* adapter)
: port(port_), gcadapter(adapter) {}
u8 GetStatus() const override {
return gcadapter->RumblePlay(port, 0);
}
bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const override {
const auto mean_amplitude = (amp_low + amp_high) * 0.5f;
const auto processed_amplitude = static_cast<u8>(
pow(mean_amplitude, 0.5f) * (3.0f - 2.0f * pow(mean_amplitude, 0.15f)) * 0x8);
return gcadapter->RumblePlay(port, processed_amplitude);
}
private:
const u32 port;
GCAdapter::Adapter* gcadapter;
};
/// An vibration device factory that creates vibration devices from GC Adapter
GCVibrationFactory::GCVibrationFactory(std::shared_ptr<GCAdapter::Adapter> adapter_)
: adapter(std::move(adapter_)) {}
/**
* Creates a vibration device from a joystick
* @param params contains parameters for creating the device:
* - "port": the nth gcpad on the adapter
*/
std::unique_ptr<Input::VibrationDevice> GCVibrationFactory::Create(
const Common::ParamPackage& params) {
const auto port = static_cast<u32>(params.Get("port", 0));
return std::make_unique<GCVibration>(port, adapter.get());
}
} // namespace InputCommon

View File

@@ -64,15 +64,4 @@ private:
bool polling = false;
};
/// A vibration device factory creates vibration devices from GC Adapter
class GCVibrationFactory final : public Input::Factory<Input::VibrationDevice> {
public:
explicit GCVibrationFactory(std::shared_ptr<GCAdapter::Adapter> adapter_);
std::unique_ptr<Input::VibrationDevice> Create(const Common::ParamPackage& params) override;
private:
std::shared_ptr<GCAdapter::Adapter> adapter;
};
} // namespace InputCommon

View File

@@ -28,8 +28,6 @@ struct InputSubsystem::Impl {
Input::RegisterFactory<Input::ButtonDevice>("gcpad", gcbuttons);
gcanalog = std::make_shared<GCAnalogFactory>(gcadapter);
Input::RegisterFactory<Input::AnalogDevice>("gcpad", gcanalog);
gcvibration = std::make_shared<GCVibrationFactory>(gcadapter);
Input::RegisterFactory<Input::VibrationDevice>("gcpad", gcvibration);
keyboard = std::make_shared<Keyboard>();
Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard);
@@ -66,11 +64,9 @@ struct InputSubsystem::Impl {
#endif
Input::UnregisterFactory<Input::ButtonDevice>("gcpad");
Input::UnregisterFactory<Input::AnalogDevice>("gcpad");
Input::UnregisterFactory<Input::VibrationDevice>("gcpad");
gcbuttons.reset();
gcanalog.reset();
gcvibration.reset();
Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp");
Input::UnregisterFactory<Input::TouchDevice>("cemuhookudp");
@@ -82,7 +78,7 @@ struct InputSubsystem::Impl {
[[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const {
std::vector<Common::ParamPackage> devices = {
Common::ParamPackage{{"display", "Any"}, {"class", "any"}},
Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "keyboard"}},
Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "key"}},
};
#ifdef HAVE_SDL2
auto sdl_devices = sdl->GetInputDevices();
@@ -100,6 +96,10 @@ struct InputSubsystem::Impl {
if (!params.Has("class") || params.Get("class", "") == "any") {
return {};
}
if (params.Get("class", "") == "key") {
// TODO consider returning the SDL key codes for the default keybindings
return {};
}
if (params.Get("class", "") == "gcpad") {
return gcadapter->GetAnalogMappingForDevice(params);
}
@@ -116,6 +116,10 @@ struct InputSubsystem::Impl {
if (!params.Has("class") || params.Get("class", "") == "any") {
return {};
}
if (params.Get("class", "") == "key") {
// TODO consider returning the SDL key codes for the default keybindings
return {};
}
if (params.Get("class", "") == "gcpad") {
return gcadapter->GetButtonMappingForDevice(params);
}
@@ -146,7 +150,6 @@ struct InputSubsystem::Impl {
#endif
std::shared_ptr<GCButtonFactory> gcbuttons;
std::shared_ptr<GCAnalogFactory> gcanalog;
std::shared_ptr<GCVibrationFactory> gcvibration;
std::shared_ptr<UDPMotionFactory> udpmotion;
std::shared_ptr<UDPTouchFactory> udptouch;
std::shared_ptr<CemuhookUDP::Client> udp;

View File

@@ -80,13 +80,30 @@ public:
return static_cast<float>(state.axes.at(axis)) / (32767.0f * range);
}
bool RumblePlay(u16 amp_low, u16 amp_high) {
if (sdl_controller) {
return SDL_GameControllerRumble(sdl_controller.get(), amp_low, amp_high, 0) == 0;
} else if (sdl_joystick) {
return SDL_JoystickRumble(sdl_joystick.get(), amp_low, amp_high, 0) == 0;
bool RumblePlay(f32 amp_low, f32 amp_high, u32 time) {
const u16 raw_amp_low = static_cast<u16>(amp_low * 0xFFFF);
const u16 raw_amp_high = static_cast<u16>(amp_high * 0xFFFF);
// Lower drastically the number of state changes
if (raw_amp_low >> 11 == last_state_rumble_low >> 11 &&
raw_amp_high >> 11 == last_state_rumble_high >> 11) {
if (raw_amp_low + raw_amp_high != 0 ||
last_state_rumble_low + last_state_rumble_high == 0) {
return false;
}
}
// Don't change state if last vibration was < 20ms
const auto now = std::chrono::system_clock::now();
if (std::chrono::duration_cast<std::chrono::milliseconds>(now - last_vibration) <
std::chrono::milliseconds(20)) {
return raw_amp_low + raw_amp_high == 0;
}
last_vibration = now;
last_state_rumble_low = raw_amp_low;
last_state_rumble_high = raw_amp_high;
if (sdl_joystick) {
SDL_JoystickRumble(sdl_joystick.get(), raw_amp_low, raw_amp_high, time);
}
return false;
}
@@ -155,6 +172,9 @@ private:
} state;
std::string guid;
int port;
u16 last_state_rumble_high = 0;
u16 last_state_rumble_low = 0;
std::chrono::time_point<std::chrono::system_clock> last_vibration;
std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick;
std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller;
mutable std::mutex mutex;
@@ -307,6 +327,12 @@ public:
return joystick->GetButton(button);
}
bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const override {
const f32 new_amp_low = pow(amp_low, 0.5f) * (3.0f - 2.0f * pow(amp_low, 0.15f));
const f32 new_amp_high = pow(amp_high, 0.5f) * (3.0f - 2.0f * pow(amp_high, 0.15f));
return joystick->RumblePlay(new_amp_low, new_amp_high, 250);
}
private:
std::shared_ptr<SDLJoystick> joystick;
int button;
@@ -390,32 +416,6 @@ private:
const float range;
};
class SDLVibration final : public Input::VibrationDevice {
public:
explicit SDLVibration(std::shared_ptr<SDLJoystick> joystick_)
: joystick(std::move(joystick_)) {}
u8 GetStatus() const override {
joystick->RumblePlay(1, 1);
return joystick->RumblePlay(0, 0);
}
bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const override {
const auto process_amplitude = [](f32 amplitude) {
return static_cast<u16>(std::pow(amplitude, 0.5f) *
(3.0f - 2.0f * std::pow(amplitude, 0.15f)) * 0xFFFF);
};
const auto processed_amp_low = process_amplitude(amp_low);
const auto processed_amp_high = process_amplitude(amp_high);
return joystick->RumblePlay(processed_amp_low, processed_amp_high);
}
private:
std::shared_ptr<SDLJoystick> joystick;
};
class SDLDirectionMotion final : public Input::MotionDevice {
public:
explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_)
@@ -558,7 +558,7 @@ class SDLAnalogFactory final : public Input::Factory<Input::AnalogDevice> {
public:
explicit SDLAnalogFactory(SDLState& state_) : state(state_) {}
/**
* Creates an analog device from joystick axes
* Creates analog device from joystick axes
* @param params contains parameters for creating the device:
* - "guid": the guid of the joystick to bind
* - "port": the nth joystick of the same type
@@ -584,26 +584,6 @@ private:
SDLState& state;
};
/// An vibration device factory that creates vibration devices from SDL joystick
class SDLVibrationFactory final : public Input::Factory<Input::VibrationDevice> {
public:
explicit SDLVibrationFactory(SDLState& state_) : state(state_) {}
/**
* Creates a vibration device from a joystick
* @param params contains parameters for creating the device:
* - "guid": the guid of the joystick to bind
* - "port": the nth joystick of the same type
*/
std::unique_ptr<Input::VibrationDevice> Create(const Common::ParamPackage& params) override {
const std::string guid = params.Get("guid", "0");
const int port = params.Get("port", 0);
return std::make_unique<SDLVibration>(state.GetSDLJoystickByGUID(guid, port));
}
private:
SDLState& state;
};
/// A motion device factory that creates motion devices from SDL joystick
class SDLMotionFactory final : public Input::Factory<Input::MotionDevice> {
public:
@@ -670,13 +650,11 @@ private:
SDLState::SDLState() {
using namespace Input;
button_factory = std::make_shared<SDLButtonFactory>(*this);
analog_factory = std::make_shared<SDLAnalogFactory>(*this);
vibration_factory = std::make_shared<SDLVibrationFactory>(*this);
button_factory = std::make_shared<SDLButtonFactory>(*this);
motion_factory = std::make_shared<SDLMotionFactory>(*this);
RegisterFactory<ButtonDevice>("sdl", button_factory);
RegisterFactory<AnalogDevice>("sdl", analog_factory);
RegisterFactory<VibrationDevice>("sdl", vibration_factory);
RegisterFactory<ButtonDevice>("sdl", button_factory);
RegisterFactory<MotionDevice>("sdl", motion_factory);
// If the frontend is going to manage the event loop, then we don't start one here
@@ -698,7 +676,7 @@ SDLState::SDLState() {
using namespace std::chrono_literals;
while (initialized) {
SDL_PumpEvents();
std::this_thread::sleep_for(1ms);
std::this_thread::sleep_for(5ms);
}
});
}
@@ -713,7 +691,6 @@ SDLState::~SDLState() {
using namespace Input;
UnregisterFactory<ButtonDevice>("sdl");
UnregisterFactory<AnalogDevice>("sdl");
UnregisterFactory<VibrationDevice>("sdl");
UnregisterFactory<MotionDevice>("sdl");
CloseJoysticks();
@@ -1068,6 +1045,7 @@ public:
void Start(const std::string& device_id) override {
SDLPoller::Start(device_id);
// Load the game controller
// Reset stored axes
analog_x_axis = -1;
analog_y_axis = -1;
@@ -1080,22 +1058,41 @@ public:
if (event.type == SDL_JOYAXISMOTION && std::abs(event.jaxis.value / 32767.0) < 0.5) {
continue;
}
// Simplify controller config by testing if game controller support is enabled.
if (event.type == SDL_JOYAXISMOTION) {
const auto axis = event.jaxis.axis;
// In order to return a complete analog param, we need inputs for both axes.
// First we take the x-axis (horizontal) input, then the y-axis (vertical) input.
if (analog_x_axis == -1) {
analog_x_axis = axis;
} else if (analog_y_axis == -1 && analog_x_axis != axis) {
analog_y_axis = axis;
}
} else {
// If the press wasn't accepted as a joy axis, check for a button press
auto button_press = button_poller.FromEvent(event);
if (button_press) {
return *button_press;
if (const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
auto* const controller = joystick->GetSDLGameController()) {
const auto axis_left_x =
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTX)
.value.axis;
const auto axis_left_y =
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_LEFTY)
.value.axis;
const auto axis_right_x =
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTX)
.value.axis;
const auto axis_right_y =
SDL_GameControllerGetBindForAxis(controller, SDL_CONTROLLER_AXIS_RIGHTY)
.value.axis;
if (axis == axis_left_x || axis == axis_left_y) {
analog_x_axis = axis_left_x;
analog_y_axis = axis_left_y;
break;
} else if (axis == axis_right_x || axis == axis_right_y) {
analog_x_axis = axis_right_x;
analog_y_axis = axis_right_y;
break;
}
}
}
// If the press wasn't accepted as a joy axis, check for a button press
auto button_press = button_poller.FromEvent(event);
if (button_press) {
return *button_press;
}
}
if (analog_x_axis != -1 && analog_y_axis != -1) {
@@ -1107,7 +1104,6 @@ public:
return params;
}
}
return {};
}

View File

@@ -22,7 +22,6 @@ namespace InputCommon::SDL {
class SDLAnalogFactory;
class SDLButtonFactory;
class SDLMotionFactory;
class SDLVibrationFactory;
class SDLJoystick;
class SDLState : public State {
@@ -73,7 +72,6 @@ private:
std::shared_ptr<SDLButtonFactory> button_factory;
std::shared_ptr<SDLAnalogFactory> analog_factory;
std::shared_ptr<SDLVibrationFactory> vibration_factory;
std::shared_ptr<SDLMotionFactory> motion_factory;
bool start_thread = false;

View File

@@ -14,20 +14,6 @@ const std::array<const char*, NumButtons> mapping = {{
}};
}
namespace NativeAnalog {
const std::array<const char*, NumAnalogs> mapping = {{
"lstick",
"rstick",
}};
}
namespace NativeVibration {
const std::array<const char*, NumVibrations> mapping = {{
"left_vibration_device",
"right_vibration_device",
}};
}
namespace NativeMotion {
const std::array<const char*, NumMotions> mapping = {{
"motionleft",
@@ -35,6 +21,13 @@ const std::array<const char*, NumMotions> mapping = {{
}};
}
namespace NativeAnalog {
const std::array<const char*, NumAnalogs> mapping = {{
"lstick",
"rstick",
}};
}
namespace NativeMouseButton {
const std::array<const char*, NumMouseButtons> mapping = {{
"left",

View File

@@ -66,32 +66,17 @@ constexpr int NUM_STICKS_HID = NumAnalogs;
extern const std::array<const char*, NumAnalogs> mapping;
} // namespace NativeAnalog
namespace NativeVibration {
enum Values : int {
LeftVibrationDevice,
RightVibrationDevice,
NumVibrations,
};
constexpr int VIBRATION_HID_BEGIN = LeftVibrationDevice;
constexpr int VIBRATION_HID_END = NumVibrations;
constexpr int NUM_VIBRATIONS_HID = NumVibrations;
extern const std::array<const char*, NumVibrations> mapping;
}; // namespace NativeVibration
namespace NativeMotion {
enum Values : int {
MotionLeft,
MotionRight,
MOTIONLEFT,
MOTIONRIGHT,
NumMotions,
};
constexpr int MOTION_HID_BEGIN = MotionLeft;
constexpr int MOTION_HID_BEGIN = MOTIONLEFT;
constexpr int MOTION_HID_END = NumMotions;
constexpr int NUM_MOTIONS_HID = NumMotions;
constexpr int NUM_MOTION_HID = NumMotions;
extern const std::array<const char*, NumMotions> mapping;
} // namespace NativeMotion
@@ -320,11 +305,9 @@ constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods;
} // namespace NativeKeyboard
using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>;
using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
using MotionsRaw = std::array<std::string, NativeMotion::NumMotions>;
using VibrationsRaw = std::array<std::string, NativeVibration::NumVibrations>;
using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>;
using MotionRaw = std::array<std::string, NativeMotion::NumMotions>;
using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>;
using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>;
using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>;
@@ -347,11 +330,7 @@ struct PlayerInput {
ControllerType controller_type;
ButtonsRaw buttons;
AnalogsRaw analogs;
VibrationsRaw vibrations;
MotionsRaw motions;
bool vibration_enabled;
int vibration_strength;
MotionRaw motions;
u32 body_color_left;
u32 body_color_right;

View File

@@ -344,7 +344,7 @@ void TestCommunication(const std::string& host, u16 port, std::size_t pad_index,
};
Socket socket{host, port, pad_index, client_id, std::move(callback)};
std::thread worker_thread{SocketLoop, &socket};
const bool result = success_event.WaitFor(std::chrono::seconds(5));
const bool result = success_event.WaitFor(std::chrono::seconds(8));
socket.Stop();
worker_thread.join();
if (result) {

View File

@@ -17,11 +17,11 @@
#include "video_core/dma_pusher.h"
using CacheAddr = std::uintptr_t;
[[nodiscard]] inline CacheAddr ToCacheAddr(const void* host_ptr) {
inline CacheAddr ToCacheAddr(const void* host_ptr) {
return reinterpret_cast<CacheAddr>(host_ptr);
}
[[nodiscard]] inline u8* FromCacheAddr(CacheAddr cache_addr) {
inline u8* FromCacheAddr(CacheAddr cache_addr) {
return reinterpret_cast<u8*>(cache_addr);
}
@@ -149,13 +149,13 @@ public:
u32 subchannel{};
u32 method_count{};
bool IsLastCall() const {
return method_count <= 1;
}
MethodCall(u32 method, u32 argument, u32 subchannel = 0, u32 method_count = 0)
: method(method), argument(argument), subchannel(subchannel),
method_count(method_count) {}
[[nodiscard]] bool IsLastCall() const {
return method_count <= 1;
}
};
explicit GPU(Core::System& system, bool is_async, bool use_nvdec);
@@ -179,10 +179,10 @@ public:
virtual void OnCommandListEnd();
/// Request a host GPU memory flush from the CPU.
[[nodiscard]] u64 RequestFlush(VAddr addr, std::size_t size);
u64 RequestFlush(VAddr addr, std::size_t size);
/// Obtains current flush request fence id.
[[nodiscard]] u64 CurrentFlushRequestFence() const {
u64 CurrentFlushRequestFence() const {
return current_flush_fence.load(std::memory_order_relaxed);
}
@@ -190,52 +190,48 @@ public:
void TickWork();
/// Returns a reference to the Maxwell3D GPU engine.
[[nodiscard]] Engines::Maxwell3D& Maxwell3D();
Engines::Maxwell3D& Maxwell3D();
/// Returns a const reference to the Maxwell3D GPU engine.
[[nodiscard]] const Engines::Maxwell3D& Maxwell3D() const;
const Engines::Maxwell3D& Maxwell3D() const;
/// Returns a reference to the KeplerCompute GPU engine.
[[nodiscard]] Engines::KeplerCompute& KeplerCompute();
Engines::KeplerCompute& KeplerCompute();
/// Returns a reference to the KeplerCompute GPU engine.
[[nodiscard]] const Engines::KeplerCompute& KeplerCompute() const;
const Engines::KeplerCompute& KeplerCompute() const;
/// Returns a reference to the GPU memory manager.
[[nodiscard]] Tegra::MemoryManager& MemoryManager();
Tegra::MemoryManager& MemoryManager();
/// Returns a const reference to the GPU memory manager.
[[nodiscard]] const Tegra::MemoryManager& MemoryManager() const;
const Tegra::MemoryManager& MemoryManager() const;
/// Returns a reference to the GPU DMA pusher.
[[nodiscard]] Tegra::DmaPusher& DmaPusher();
Tegra::DmaPusher& DmaPusher();
/// Returns a const reference to the GPU DMA pusher.
[[nodiscard]] const Tegra::DmaPusher& DmaPusher() const;
const Tegra::DmaPusher& DmaPusher() const;
/// Returns a reference to the GPU CDMA pusher.
[[nodiscard]] Tegra::CDmaPusher& CDmaPusher();
Tegra::CDmaPusher& CDmaPusher();
/// Returns a const reference to the GPU CDMA pusher.
[[nodiscard]] const Tegra::CDmaPusher& CDmaPusher() const;
const Tegra::CDmaPusher& CDmaPusher() const;
/// Returns a reference to the underlying renderer.
[[nodiscard]] VideoCore::RendererBase& Renderer() {
VideoCore::RendererBase& Renderer() {
return *renderer;
}
/// Returns a const reference to the underlying renderer.
[[nodiscard]] const VideoCore::RendererBase& Renderer() const {
const VideoCore::RendererBase& Renderer() const {
return *renderer;
}
/// Returns a reference to the shader notifier.
[[nodiscard]] VideoCore::ShaderNotify& ShaderNotify() {
VideoCore::ShaderNotify& ShaderNotify() {
return *shader_notify;
}
/// Returns a const reference to the shader notifier.
[[nodiscard]] const VideoCore::ShaderNotify& ShaderNotify() const {
const VideoCore::ShaderNotify& ShaderNotify() const {
return *shader_notify;
}
@@ -247,23 +243,23 @@ public:
void IncrementSyncPoint(u32 syncpoint_id);
[[nodiscard]] u32 GetSyncpointValue(u32 syncpoint_id) const;
u32 GetSyncpointValue(u32 syncpoint_id) const;
void RegisterSyncptInterrupt(u32 syncpoint_id, u32 value);
[[nodiscard]] bool CancelSyncptInterrupt(u32 syncpoint_id, u32 value);
bool CancelSyncptInterrupt(u32 syncpoint_id, u32 value);
[[nodiscard]] u64 GetTicks() const;
u64 GetTicks() const;
[[nodiscard]] std::unique_lock<std::mutex> LockSync() {
std::unique_lock<std::mutex> LockSync() {
return std::unique_lock{sync_mutex};
}
[[nodiscard]] bool IsAsync() const {
bool IsAsync() const {
return is_async;
}
[[nodiscard]] bool UseNvdec() const {
bool UseNvdec() const {
return use_nvdec;
}
@@ -277,7 +273,7 @@ public:
BitField<0, 1, FenceOperation> op;
BitField<8, 24, u32> syncpoint_id;
[[nodiscard]] static CommandHeader Build(FenceOperation op, u32 syncpoint_id) {
static CommandHeader Build(FenceOperation op, u32 syncpoint_id) {
FenceAction result{};
result.op.Assign(op);
result.syncpoint_id.Assign(syncpoint_id);
@@ -295,7 +291,7 @@ public:
u32 address_high;
u32 address_low;
[[nodiscard]] GPUVAddr SemaphoreAddress() const {
GPUVAddr SemaphoreAddress() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
}
@@ -378,7 +374,7 @@ private:
u32 methods_pending);
/// Determines where the method should be executed.
[[nodiscard]] bool ExecuteMethodOnEngine(u32 method);
bool ExecuteMethodOnEngine(u32 method);
protected:
Core::System& system;

View File

@@ -32,7 +32,7 @@ using DiskResourceLoadCallback = std::function<void(LoadCallbackStage, std::size
class RasterizerInterface {
public:
virtual ~RasterizerInterface() = default;
virtual ~RasterizerInterface() {}
/// Dispatches a draw invocation
virtual void Draw(bool is_indexed, bool is_instanced) = 0;
@@ -90,16 +90,15 @@ public:
virtual void TickFrame() = 0;
/// Attempt to use a faster method to perform a surface copy
[[nodiscard]] virtual bool AccelerateSurfaceCopy(
const Tegra::Engines::Fermi2D::Regs::Surface& src,
const Tegra::Engines::Fermi2D::Regs::Surface& dst,
const Tegra::Engines::Fermi2D::Config& copy_config) {
virtual bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src,
const Tegra::Engines::Fermi2D::Regs::Surface& dst,
const Tegra::Engines::Fermi2D::Config& copy_config) {
return false;
}
/// Attempt to use a faster method to display the framebuffer to screen
[[nodiscard]] virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config,
VAddr framebuffer_addr, u32 pixel_stride) {
virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
u32 pixel_stride) {
return false;
}
@@ -111,12 +110,12 @@ public:
const DiskResourceLoadCallback& callback) {}
/// Grant access to the Guest Driver Profile for recording/obtaining info on the guest driver.
[[nodiscard]] GuestDriverProfile& AccessGuestDriverProfile() {
GuestDriverProfile& AccessGuestDriverProfile() {
return guest_driver_profile;
}
/// Grant access to the Guest Driver Profile for recording/obtaining info on the guest driver.
[[nodiscard]] const GuestDriverProfile& AccessGuestDriverProfile() const {
const GuestDriverProfile& AccessGuestDriverProfile() const {
return guest_driver_profile;
}

View File

@@ -38,7 +38,7 @@ public:
virtual ~RendererBase();
/// Initialize the renderer
[[nodiscard]] virtual bool Init() = 0;
virtual bool Init() = 0;
/// Shutdown the renderer
virtual void ShutDown() = 0;
@@ -49,43 +49,43 @@ public:
// Getter/setter functions:
// ------------------------
[[nodiscard]] f32 GetCurrentFPS() const {
f32 GetCurrentFPS() const {
return m_current_fps;
}
[[nodiscard]] int GetCurrentFrame() const {
int GetCurrentFrame() const {
return m_current_frame;
}
[[nodiscard]] RasterizerInterface& Rasterizer() {
RasterizerInterface& Rasterizer() {
return *rasterizer;
}
[[nodiscard]] const RasterizerInterface& Rasterizer() const {
const RasterizerInterface& Rasterizer() const {
return *rasterizer;
}
[[nodiscard]] Core::Frontend::GraphicsContext& Context() {
Core::Frontend::GraphicsContext& Context() {
return *context;
}
[[nodiscard]] const Core::Frontend::GraphicsContext& Context() const {
const Core::Frontend::GraphicsContext& Context() const {
return *context;
}
[[nodiscard]] Core::Frontend::EmuWindow& GetRenderWindow() {
Core::Frontend::EmuWindow& GetRenderWindow() {
return render_window;
}
[[nodiscard]] const Core::Frontend::EmuWindow& GetRenderWindow() const {
const Core::Frontend::EmuWindow& GetRenderWindow() const {
return render_window;
}
[[nodiscard]] RendererSettings& Settings() {
RendererSettings& Settings() {
return renderer_settings;
}
[[nodiscard]] const RendererSettings& Settings() const {
const RendererSettings& Settings() const {
return renderer_settings;
}

View File

@@ -68,12 +68,12 @@ add_executable(yuzu
configuration/configure_input_advanced.cpp
configuration/configure_input_advanced.h
configuration/configure_input_advanced.ui
configuration/configure_input_dialog.cpp
configuration/configure_input_dialog.h
configuration/configure_input_dialog.ui
configuration/configure_input_player.cpp
configuration/configure_input_player.h
configuration/configure_input_player.ui
configuration/configure_input_profile_dialog.cpp
configuration/configure_input_profile_dialog.h
configuration/configure_input_profile_dialog.ui
configuration/configure_motion_touch.cpp
configuration/configure_motion_touch.h
configuration/configure_motion_touch.ui
@@ -105,14 +105,9 @@ add_executable(yuzu
configuration/configure_ui.cpp
configuration/configure_ui.h
configuration/configure_ui.ui
configuration/configure_vibration.cpp
configuration/configure_vibration.h
configuration/configure_vibration.ui
configuration/configure_web.cpp
configuration/configure_web.h
configuration/configure_web.ui
configuration/input_profiles.cpp
configuration/input_profiles.h
debugger/console.cpp
debugger/console.h
debugger/profiler.cpp

View File

@@ -160,12 +160,32 @@ p, li { white-space: pre-wrap; }
<signal>accepted()</signal>
<receiver>AboutDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>AboutDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -3,7 +3,6 @@
// Refer to the license.txt file included.
#include <algorithm>
#include <thread>
#include "common/assert.h"
#include "common/string_util.h"
@@ -14,16 +13,11 @@
#include "core/hle/service/sm/sm.h"
#include "ui_controller.h"
#include "yuzu/applets/controller.h"
#include "yuzu/configuration/configure_input.h"
#include "yuzu/configuration/configure_input_profile_dialog.h"
#include "yuzu/configuration/configure_vibration.h"
#include "yuzu/configuration/input_profiles.h"
#include "yuzu/configuration/configure_input_dialog.h"
#include "yuzu/main.h"
namespace {
constexpr std::size_t HANDHELD_INDEX = 8;
constexpr std::array<std::array<bool, 4>, 8> led_patterns{{
{true, false, false, false},
{true, true, false, false},
@@ -112,8 +106,7 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
QWidget* parent, Core::Frontend::ControllerParameters parameters_,
InputCommon::InputSubsystem* input_subsystem_)
: QDialog(parent), ui(std::make_unique<Ui::QtControllerSelectorDialog>()),
parameters(std::move(parameters_)), input_subsystem{input_subsystem_},
input_profiles(std::make_unique<InputProfiles>()) {
parameters(std::move(parameters_)), input_subsystem(input_subsystem_) {
ui->setupUi(this);
player_widgets = {
@@ -230,22 +223,12 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
}
}
connect(ui->vibrationButton, &QPushButton::clicked, this,
&QtControllerSelectorDialog::CallConfigureVibrationDialog);
connect(ui->inputConfigButton, &QPushButton::clicked, this,
&QtControllerSelectorDialog::CallConfigureInputProfileDialog);
&QtControllerSelectorDialog::CallConfigureInputDialog);
connect(ui->buttonBox, &QDialogButtonBox::accepted, this,
&QtControllerSelectorDialog::ApplyConfiguration);
// Enhancement: Check if the parameters have already been met before disconnecting controllers.
// If all the parameters are met AND only allows a single player,
// stop the constructor here as we do not need to continue.
if (CheckIfParametersMet() && parameters.enable_single_mode) {
return;
}
// If keep_controllers_connected is false, forcefully disconnect all controllers
if (!parameters.keep_controllers_connected) {
for (auto player : player_groupboxes) {
@@ -253,66 +236,58 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
}
}
CheckIfParametersMet();
resize(0, 0);
}
QtControllerSelectorDialog::~QtControllerSelectorDialog() = default;
int QtControllerSelectorDialog::exec() {
if (parameters_met && parameters.enable_single_mode) {
return QDialog::Accepted;
}
return QDialog::exec();
}
void QtControllerSelectorDialog::ApplyConfiguration() {
const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue();
Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked());
OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode.GetValue());
// Update the controller state once more, just to be sure they are properly applied.
for (std::size_t index = 0; index < NUM_PLAYERS; ++index) {
UpdateControllerState(index);
}
Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked());
Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked());
const bool pre_docked_mode = Settings::values.use_docked_mode;
Settings::values.use_docked_mode = ui->radioDocked->isChecked();
OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode);
Settings::values.vibration_enabled = ui->vibrationGroup->isChecked();
}
void QtControllerSelectorDialog::LoadConfiguration() {
for (std::size_t index = 0; index < NUM_PLAYERS; ++index) {
const auto connected =
Settings::values.players.GetValue()[index].connected ||
(index == 0 && Settings::values.players.GetValue()[HANDHELD_INDEX].connected);
const auto connected = Settings::values.players[index].connected ||
(index == 0 && Settings::values.players[8].connected);
player_groupboxes[index]->setChecked(connected);
connected_controller_checkboxes[index]->setChecked(connected);
emulated_controllers[index]->setCurrentIndex(
GetIndexFromControllerType(Settings::values.players.GetValue()[index].controller_type));
GetIndexFromControllerType(Settings::values.players[index].controller_type));
}
UpdateDockedState(Settings::values.players.GetValue()[HANDHELD_INDEX].connected);
UpdateDockedState(Settings::values.players[8].connected);
ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue());
ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue());
ui->vibrationGroup->setChecked(Settings::values.vibration_enabled);
}
void QtControllerSelectorDialog::CallConfigureVibrationDialog() {
ConfigureVibration dialog(this);
void QtControllerSelectorDialog::CallConfigureInputDialog() {
const auto max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players;
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
Qt::WindowSystemMenuHint);
dialog.setWindowModality(Qt::WindowModal);
if (dialog.exec() == QDialog::Accepted) {
dialog.ApplyConfiguration();
}
}
void QtControllerSelectorDialog::CallConfigureInputProfileDialog() {
ConfigureInputProfileDialog dialog(this, input_subsystem, input_profiles.get());
ConfigureInputDialog dialog(this, max_supported_players, input_subsystem);
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
Qt::WindowSystemMenuHint);
dialog.setWindowModality(Qt::WindowModal);
dialog.exec();
dialog.ApplyConfiguration();
LoadConfiguration();
CheckIfParametersMet();
}
bool QtControllerSelectorDialog::CheckIfParametersMet() {
void QtControllerSelectorDialog::CheckIfParametersMet() {
// Here, we check and validate the current configuration against all applicable parameters.
const auto num_connected_players = static_cast<int>(
std::count_if(player_groupboxes.begin(), player_groupboxes.end(),
@@ -326,7 +301,7 @@ bool QtControllerSelectorDialog::CheckIfParametersMet() {
num_connected_players > max_supported_players) {
parameters_met = false;
ui->buttonBox->setEnabled(parameters_met);
return parameters_met;
return;
}
// Next, check against all connected controllers.
@@ -351,13 +326,18 @@ bool QtControllerSelectorDialog::CheckIfParametersMet() {
return true;
}();
parameters_met = all_controllers_compatible;
if (!all_controllers_compatible) {
parameters_met = false;
ui->buttonBox->setEnabled(parameters_met);
return;
}
parameters_met = true;
ui->buttonBox->setEnabled(parameters_met);
return parameters_met;
}
void QtControllerSelectorDialog::SetSupportedControllers() {
const QString theme = [] {
const QString theme = [this] {
if (QIcon::themeName().contains(QStringLiteral("dark"))) {
return QStringLiteral("_dark");
} else if (QIcon::themeName().contains(QStringLiteral("midnight"))) {
@@ -446,7 +426,7 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index)
}
}();
const QString theme = [] {
const QString theme = [this] {
if (QIcon::themeName().contains(QStringLiteral("dark"))) {
return QStringLiteral("_dark");
} else if (QIcon::themeName().contains(QStringLiteral("midnight"))) {
@@ -461,48 +441,32 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index)
}
void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) {
auto& player = Settings::values.players.GetValue()[player_index];
auto& player = Settings::values.players[player_index];
const auto controller_type =
player.controller_type =
GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex());
const auto player_connected = player_groupboxes[player_index]->isChecked() &&
controller_type != Settings::ControllerType::Handheld;
player.connected = player_groupboxes[player_index]->isChecked();
if (player.controller_type == controller_type && player.connected == player_connected) {
// Set vibration devices in the event that the input device has changed.
ConfigureVibration::SetVibrationDevices(player_index);
// Player 2-8
if (player_index != 0) {
UpdateController(player.controller_type, player_index, player.connected);
return;
}
// Disconnect the controller first.
UpdateController(controller_type, player_index, false);
player.controller_type = controller_type;
player.connected = player_connected;
ConfigureVibration::SetVibrationDevices(player_index);
// Handheld
if (player_index == 0) {
auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
if (controller_type == Settings::ControllerType::Handheld) {
handheld = player;
}
handheld.connected = player_groupboxes[player_index]->isChecked() &&
controller_type == Settings::ControllerType::Handheld;
UpdateController(Settings::ControllerType::Handheld, 8, handheld.connected);
// Player 1 and Handheld
auto& handheld = Settings::values.players[8];
// If Handheld is selected, copy all the settings from Player 1 to Handheld.
if (player.controller_type == Settings::ControllerType::Handheld) {
handheld = player;
handheld.connected = player_groupboxes[player_index]->isChecked();
player.connected = false; // Disconnect Player 1
} else {
player.connected = player_groupboxes[player_index]->isChecked();
handheld.connected = false; // Disconnect Handheld
}
if (!player.connected) {
return;
}
// This emulates a delay between disconnecting and reconnecting controllers as some games
// do not respond to a change in controller type if it was instantaneous.
using namespace std::chrono_literals;
std::this_thread::sleep_for(20ms);
UpdateController(controller_type, player_index, player_connected);
UpdateController(player.controller_type, player_index, player.connected);
UpdateController(Settings::ControllerType::Handheld, 8, handheld.connected);
}
void QtControllerSelectorDialog::UpdateLEDPattern(std::size_t player_index) {
@@ -556,8 +520,8 @@ void QtControllerSelectorDialog::UpdateDockedState(bool is_handheld) {
ui->radioDocked->setEnabled(!is_handheld);
ui->radioUndocked->setEnabled(!is_handheld);
ui->radioDocked->setChecked(Settings::values.use_docked_mode.GetValue());
ui->radioUndocked->setChecked(!Settings::values.use_docked_mode.GetValue());
ui->radioDocked->setChecked(Settings::values.use_docked_mode);
ui->radioUndocked->setChecked(!Settings::values.use_docked_mode);
// Also force into undocked mode if the controller type is handheld.
if (is_handheld) {
@@ -600,8 +564,8 @@ void QtControllerSelectorDialog::DisableUnsupportedPlayers() {
for (std::size_t index = max_supported_players; index < NUM_PLAYERS; ++index) {
// Disconnect any unsupported players here and disable or hide them if applicable.
Settings::values.players.GetValue()[index].connected = false;
UpdateController(Settings::values.players.GetValue()[index].controller_type, index, false);
Settings::values.players[index].connected = false;
UpdateController(Settings::values.players[index].controller_type, index, false);
// Hide the player widgets when max_supported_controllers is less than or equal to 4.
if (max_supported_players <= 4) {
player_widgets[index]->hide();

View File

@@ -16,8 +16,6 @@ class QDialogButtonBox;
class QGroupBox;
class QLabel;
class InputProfiles;
namespace InputCommon {
class InputSubsystem;
}
@@ -35,8 +33,6 @@ public:
InputCommon::InputSubsystem* input_subsystem_);
~QtControllerSelectorDialog() override;
int exec() override;
private:
// Applies the current configuration.
void ApplyConfiguration();
@@ -44,15 +40,12 @@ private:
// Loads the current input configuration into the frontend applet.
void LoadConfiguration();
// Initializes the "Configure Vibration" Dialog.
void CallConfigureVibrationDialog();
// Initializes the "Configure Input" Dialog.
void CallConfigureInputDialog();
// Initializes the "Create Input Profile" Dialog.
void CallConfigureInputProfileDialog();
// Checks the current configuration against the given parameters.
// This sets and returns the value of parameters_met.
bool CheckIfParametersMet();
// Checks the current configuration against the given parameters and
// sets the value of parameters_met.
void CheckIfParametersMet();
// Sets the controller icons for "Supported Controller Types".
void SetSupportedControllers();
@@ -85,8 +78,6 @@ private:
InputCommon::InputSubsystem* input_subsystem;
std::unique_ptr<InputProfiles> input_profiles;
// This is true if and only if all parameters are met. Otherwise, this is false.
// This determines whether the "OK" button can be clicked to exit the applet.
bool parameters_met{false};

View File

@@ -1217,6 +1217,9 @@
</item>
<item>
<widget class="QComboBox" name="comboPlayer3Emulated">
<property name="editable">
<bool>false</bool>
</property>
<item>
<property name="text">
<string>Pro Controller</string>
@@ -2276,7 +2279,7 @@
<number>6</number>
</property>
<property name="leftMargin">
<number>8</number>
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
@@ -2329,24 +2332,30 @@
<number>3</number>
</property>
<item>
<widget class="QPushButton" name="vibrationButton">
<widget class="QSpinBox" name="vibrationSpin">
<property name="minimumSize">
<size>
<width>68</width>
<width>65</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>65</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<property name="suffix">
<string>%</string>
</property>
<property name="text">
<string>Configure</string>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>200</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
@@ -2378,18 +2387,18 @@
<widget class="QPushButton" name="motionButton">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Configure</string>
@@ -2402,7 +2411,7 @@
<item>
<widget class="QGroupBox" name="inputConfigGroup">
<property name="title">
<string>Profiles</string>
<string>Input Config</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="leftMargin">
@@ -2421,15 +2430,15 @@
<widget class="QPushButton" name="inputConfigButton">
<property name="maximumSize">
<size>
<width>68</width>
<width>65</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Create</string>
<string>Open</string>
</property>
</widget>
</item>
@@ -2648,6 +2657,16 @@
<signal>accepted()</signal>
<receiver>QtControllerSelectorDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>20</x>
<y>20</y>
</hint>
<hint type="destinationlabel">
<x>20</x>
<y>20</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -382,12 +382,7 @@ void GRenderWindow::keyReleaseEvent(QKeyEvent* event) {
}
void GRenderWindow::mousePressEvent(QMouseEvent* event) {
if (!Settings::values.touchscreen.enabled) {
input_subsystem->GetKeyboard()->PressKey(event->button());
return;
}
// Touch input is handled in TouchBeginEvent
// touch input is handled in TouchBeginEvent
if (event->source() == Qt::MouseEventSynthesizedBySystem) {
return;
}
@@ -403,7 +398,7 @@ void GRenderWindow::mousePressEvent(QMouseEvent* event) {
}
void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
// Touch input is handled in TouchUpdateEvent
// touch input is handled in TouchUpdateEvent
if (event->source() == Qt::MouseEventSynthesizedBySystem) {
return;
}
@@ -416,12 +411,7 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) {
}
void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
if (!Settings::values.touchscreen.enabled) {
input_subsystem->GetKeyboard()->ReleaseKey(event->button());
return;
}
// Touch input is handled in TouchEndEvent
// touch input is handled in TouchEndEvent
if (event->source() == Qt::MouseEventSynthesizedBySystem) {
return;
}

View File

@@ -5,7 +5,6 @@
#include <array>
#include <QKeySequence>
#include <QSettings>
#include "common/common_paths.h"
#include "common/file_util.h"
#include "core/hle/service/acc/profile_manager.h"
#include "core/hle/service/hid/controllers/npad.h"
@@ -15,10 +14,14 @@
namespace FS = Common::FS;
Config::Config(const std::string& config_name, ConfigType config_type) : type(config_type) {
global = config_type == ConfigType::GlobalConfig;
Initialize(config_name);
Config::Config(const std::string& config_file, bool is_global) {
// TODO: Don't hardcode the path; let the frontend decide where to put the config files.
qt_config_loc = FS::GetUserPath(FS::UserPath::ConfigDir) + config_file;
FS::CreateFullPath(qt_config_loc);
qt_config =
std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), QSettings::IniFormat);
global = is_global;
Reload();
}
Config::~Config() {
@@ -239,152 +242,84 @@ const std::array<UISettings::Shortcut, 16> Config::default_hotkeys{{
}};
// clang-format on
void Config::Initialize(const std::string& config_name) {
switch (type) {
case ConfigType::GlobalConfig:
qt_config_loc = fmt::format("{}" DIR_SEP "{}.ini", FS::GetUserPath(FS::UserPath::ConfigDir),
config_name);
FS::CreateFullPath(qt_config_loc);
qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc),
QSettings::IniFormat);
Reload();
break;
case ConfigType::PerGameConfig:
qt_config_loc = fmt::format("{}custom" DIR_SEP "{}.ini",
FS::GetUserPath(FS::UserPath::ConfigDir), config_name);
FS::CreateFullPath(qt_config_loc);
qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc),
QSettings::IniFormat);
Reload();
break;
case ConfigType::InputProfile:
qt_config_loc = fmt::format("{}input" DIR_SEP "{}.ini",
FS::GetUserPath(FS::UserPath::ConfigDir), config_name);
FS::CreateFullPath(qt_config_loc);
qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc),
QSettings::IniFormat);
break;
}
}
void Config::ReadPlayerValues() {
for (std::size_t p = 0; p < Settings::values.players.size(); ++p) {
auto& player = Settings::values.players[p];
void Config::ReadPlayerValue(std::size_t player_index) {
const QString player_prefix = [this, player_index] {
if (type == ConfigType::InputProfile) {
return QString{};
} else {
return QStringLiteral("player_%1_").arg(player_index);
}
}();
auto& player = Settings::values.players.GetValue()[player_index];
if (player_prefix.isEmpty()) {
const auto controller = static_cast<Settings::ControllerType>(
qt_config
->value(QStringLiteral("%1type").arg(player_prefix),
static_cast<u8>(Settings::ControllerType::ProController))
.toUInt());
if (controller == Settings::ControllerType::LeftJoycon ||
controller == Settings::ControllerType::RightJoycon) {
player.controller_type = controller;
}
} else {
player.connected =
ReadSetting(QStringLiteral("%1connected").arg(player_prefix), player_index == 0)
.toBool();
ReadSetting(QStringLiteral("player_%1_connected").arg(p), false).toBool();
player.controller_type = static_cast<Settings::ControllerType>(
qt_config
->value(QStringLiteral("%1type").arg(player_prefix),
->value(QStringLiteral("player_%1_type").arg(p),
static_cast<u8>(Settings::ControllerType::ProController))
.toUInt());
player.vibration_enabled =
qt_config->value(QStringLiteral("%1vibration_enabled").arg(player_prefix), true)
.toBool();
player.vibration_strength =
qt_config->value(QStringLiteral("%1vibration_strength").arg(player_prefix), 100)
.toInt();
player.body_color_left = qt_config
->value(QStringLiteral("%1body_color_left").arg(player_prefix),
->value(QStringLiteral("player_%1_body_color_left").arg(p),
Settings::JOYCON_BODY_NEON_BLUE)
.toUInt();
player.body_color_right =
qt_config
->value(QStringLiteral("%1body_color_right").arg(player_prefix),
Settings::JOYCON_BODY_NEON_RED)
.toUInt();
player.button_color_left =
qt_config
->value(QStringLiteral("%1button_color_left").arg(player_prefix),
Settings::JOYCON_BUTTONS_NEON_BLUE)
.toUInt();
player.body_color_right = qt_config
->value(QStringLiteral("player_%1_body_color_right").arg(p),
Settings::JOYCON_BODY_NEON_RED)
.toUInt();
player.button_color_left = qt_config
->value(QStringLiteral("player_%1_button_color_left").arg(p),
Settings::JOYCON_BUTTONS_NEON_BLUE)
.toUInt();
player.button_color_right =
qt_config
->value(QStringLiteral("%1button_color_right").arg(player_prefix),
->value(QStringLiteral("player_%1_button_color_right").arg(p),
Settings::JOYCON_BUTTONS_NEON_RED)
.toUInt();
}
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
auto& player_buttons = player.buttons[i];
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
const std::string default_param =
InputCommon::GenerateKeyboardParam(default_buttons[i]);
auto& player_buttons = player.buttons[i];
player_buttons = qt_config
->value(QStringLiteral("%1").arg(player_prefix) +
QString::fromUtf8(Settings::NativeButton::mapping[i]),
QString::fromStdString(default_param))
.toString()
.toStdString();
if (player_buttons.empty()) {
player_buttons = default_param;
player_buttons = qt_config
->value(QStringLiteral("player_%1_").arg(p) +
QString::fromUtf8(Settings::NativeButton::mapping[i]),
QString::fromStdString(default_param))
.toString()
.toStdString();
if (player_buttons.empty()) {
player_buttons = default_param;
}
}
}
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
default_analogs[i][3], default_stick_mod[i], 0.5f);
auto& player_analogs = player.analogs[i];
for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
const std::string default_param =
InputCommon::GenerateKeyboardParam(default_motions[i]);
auto& player_motions = player.motions[i];
player_analogs = qt_config
->value(QStringLiteral("%1").arg(player_prefix) +
QString::fromUtf8(Settings::NativeAnalog::mapping[i]),
QString::fromStdString(default_param))
.toString()
.toStdString();
if (player_analogs.empty()) {
player_analogs = default_param;
player_motions = qt_config
->value(QStringLiteral("player_%1_").arg(p) +
QString::fromUtf8(Settings::NativeMotion::mapping[i]),
QString::fromStdString(default_param))
.toString()
.toStdString();
if (player_motions.empty()) {
player_motions = default_param;
}
}
}
for (int i = 0; i < Settings::NativeVibration::NumVibrations; ++i) {
auto& player_vibrations = player.vibrations[i];
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
default_analogs[i][3], default_stick_mod[i], 0.5f);
auto& player_analogs = player.analogs[i];
player_vibrations =
qt_config
->value(QStringLiteral("%1").arg(player_prefix) +
QString::fromUtf8(Settings::NativeVibration::mapping[i]),
QString{})
.toString()
.toStdString();
}
for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]);
auto& player_motions = player.motions[i];
player_motions = qt_config
->value(QStringLiteral("%1").arg(player_prefix) +
QString::fromUtf8(Settings::NativeMotion::mapping[i]),
QString::fromStdString(default_param))
.toString()
.toStdString();
if (player_motions.empty()) {
player_motions = default_param;
player_analogs = qt_config
->value(QStringLiteral("player_%1_").arg(p) +
QString::fromUtf8(Settings::NativeAnalog::mapping[i]),
QString::fromStdString(default_param))
.toString()
.toStdString();
if (player_analogs.empty()) {
player_analogs = default_param;
}
}
}
}
@@ -501,21 +436,18 @@ void Config::ReadAudioValues() {
void Config::ReadControlValues() {
qt_config->beginGroup(QStringLiteral("Controls"));
for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
ReadPlayerValue(p);
}
ReadPlayerValues();
ReadDebugValues();
ReadKeyboardValues();
ReadMouseValues();
ReadTouchscreenValues();
ReadMotionTouchValues();
ReadSettingGlobal(Settings::values.use_docked_mode, QStringLiteral("use_docked_mode"), false);
ReadSettingGlobal(Settings::values.vibration_enabled, QStringLiteral("vibration_enabled"),
true);
ReadSettingGlobal(Settings::values.enable_accurate_vibrations,
QStringLiteral("enable_accurate_vibrations"), false);
ReadSettingGlobal(Settings::values.motion_enabled, QStringLiteral("motion_enabled"), true);
Settings::values.vibration_enabled =
ReadSetting(QStringLiteral("vibration_enabled"), true).toBool();
Settings::values.motion_enabled = ReadSetting(QStringLiteral("motion_enabled"), true).toBool();
Settings::values.use_docked_mode =
ReadSetting(QStringLiteral("use_docked_mode"), false).toBool();
qt_config->endGroup();
}
@@ -988,64 +920,49 @@ void Config::ReadValues() {
ReadSystemValues();
}
void Config::SavePlayerValue(std::size_t player_index) {
const QString player_prefix = [this, player_index] {
if (type == ConfigType::InputProfile) {
return QString{};
} else {
return QStringLiteral("player_%1_").arg(player_index);
}
}();
void Config::SavePlayerValues() {
for (std::size_t p = 0; p < Settings::values.players.size(); ++p) {
const auto& player = Settings::values.players[p];
const auto& player = Settings::values.players.GetValue()[player_index];
WriteSetting(QStringLiteral("player_%1_connected").arg(p), player.connected, false);
WriteSetting(QStringLiteral("player_%1_type").arg(p),
static_cast<u8>(player.controller_type),
static_cast<u8>(Settings::ControllerType::ProController));
WriteSetting(QStringLiteral("%1type").arg(player_prefix),
static_cast<u8>(player.controller_type),
static_cast<u8>(Settings::ControllerType::ProController));
if (!player_prefix.isEmpty()) {
WriteSetting(QStringLiteral("%1connected").arg(player_prefix), player.connected, false);
WriteSetting(QStringLiteral("%1vibration_enabled").arg(player_prefix),
player.vibration_enabled, true);
WriteSetting(QStringLiteral("%1vibration_strength").arg(player_prefix),
player.vibration_strength, 100);
WriteSetting(QStringLiteral("%1body_color_left").arg(player_prefix), player.body_color_left,
WriteSetting(QStringLiteral("player_%1_body_color_left").arg(p), player.body_color_left,
Settings::JOYCON_BODY_NEON_BLUE);
WriteSetting(QStringLiteral("%1body_color_right").arg(player_prefix),
player.body_color_right, Settings::JOYCON_BODY_NEON_RED);
WriteSetting(QStringLiteral("%1button_color_left").arg(player_prefix),
player.button_color_left, Settings::JOYCON_BUTTONS_NEON_BLUE);
WriteSetting(QStringLiteral("%1button_color_right").arg(player_prefix),
WriteSetting(QStringLiteral("player_%1_body_color_right").arg(p), player.body_color_right,
Settings::JOYCON_BODY_NEON_RED);
WriteSetting(QStringLiteral("player_%1_button_color_left").arg(p), player.button_color_left,
Settings::JOYCON_BUTTONS_NEON_BLUE);
WriteSetting(QStringLiteral("player_%1_button_color_right").arg(p),
player.button_color_right, Settings::JOYCON_BUTTONS_NEON_RED);
}
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
WriteSetting(QStringLiteral("%1").arg(player_prefix) +
QString::fromStdString(Settings::NativeButton::mapping[i]),
QString::fromStdString(player.buttons[i]),
QString::fromStdString(default_param));
}
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
default_analogs[i][3], default_stick_mod[i], 0.5f);
WriteSetting(QStringLiteral("%1").arg(player_prefix) +
QString::fromStdString(Settings::NativeAnalog::mapping[i]),
QString::fromStdString(player.analogs[i]),
QString::fromStdString(default_param));
}
for (int i = 0; i < Settings::NativeVibration::NumVibrations; ++i) {
WriteSetting(QStringLiteral("%1").arg(player_prefix) +
QString::fromStdString(Settings::NativeVibration::mapping[i]),
QString::fromStdString(player.vibrations[i]), QString{});
}
for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
const std::string default_param = InputCommon::GenerateKeyboardParam(default_motions[i]);
WriteSetting(QStringLiteral("%1").arg(player_prefix) +
QString::fromStdString(Settings::NativeMotion::mapping[i]),
QString::fromStdString(player.motions[i]),
QString::fromStdString(default_param));
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
const std::string default_param =
InputCommon::GenerateKeyboardParam(default_buttons[i]);
WriteSetting(QStringLiteral("player_%1_").arg(p) +
QString::fromStdString(Settings::NativeButton::mapping[i]),
QString::fromStdString(player.buttons[i]),
QString::fromStdString(default_param));
}
for (int i = 0; i < Settings::NativeMotion::NumMotions; ++i) {
const std::string default_param =
InputCommon::GenerateKeyboardParam(default_motions[i]);
WriteSetting(QStringLiteral("player_%1_").arg(p) +
QString::fromStdString(Settings::NativeMotion::mapping[i]),
QString::fromStdString(player.motions[i]),
QString::fromStdString(default_param));
}
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
default_analogs[i][3], default_stick_mod[i], 0.5f);
WriteSetting(QStringLiteral("player_%1_").arg(p) +
QString::fromStdString(Settings::NativeAnalog::mapping[i]),
QString::fromStdString(player.analogs[i]),
QString::fromStdString(default_param));
}
}
}
@@ -1170,20 +1087,14 @@ void Config::SaveAudioValues() {
void Config::SaveControlValues() {
qt_config->beginGroup(QStringLiteral("Controls"));
for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
SavePlayerValue(p);
}
SavePlayerValues();
SaveDebugValues();
SaveMouseValues();
SaveTouchscreenValues();
SaveMotionTouchValues();
WriteSettingGlobal(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false);
WriteSettingGlobal(QStringLiteral("vibration_enabled"), Settings::values.vibration_enabled,
true);
WriteSettingGlobal(QStringLiteral("enable_accurate_vibrations"),
Settings::values.enable_accurate_vibrations, false);
WriteSettingGlobal(QStringLiteral("motion_enabled"), Settings::values.motion_enabled, true);
WriteSetting(QStringLiteral("vibration_enabled"), Settings::values.vibration_enabled, true);
WriteSetting(QStringLiteral("motion_enabled"), Settings::values.motion_enabled, true);
WriteSetting(QStringLiteral("motion_device"),
QString::fromStdString(Settings::values.motion_device),
QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01"));
@@ -1191,6 +1102,7 @@ void Config::SaveControlValues() {
QString::fromStdString(Settings::values.touch_device),
QStringLiteral("engine:emu_window"));
WriteSetting(QStringLiteral("keyboard_enabled"), Settings::values.keyboard_enabled, false);
WriteSetting(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false);
qt_config->endGroup();
}
@@ -1603,19 +1515,3 @@ void Config::Save() {
Settings::Sanitize();
SaveValues();
}
void Config::ReadControlPlayerValue(std::size_t player_index) {
qt_config->beginGroup(QStringLiteral("Controls"));
ReadPlayerValue(player_index);
qt_config->endGroup();
}
void Config::SaveControlPlayerValue(std::size_t player_index) {
qt_config->beginGroup(QStringLiteral("Controls"));
SavePlayerValue(player_index);
qt_config->endGroup();
}
const std::string& Config::GetConfigFilePath() const {
return qt_config_loc;
}

View File

@@ -16,24 +16,12 @@ class QSettings;
class Config {
public:
enum class ConfigType {
GlobalConfig,
PerGameConfig,
InputProfile,
};
explicit Config(const std::string& config_name = "qt-config",
ConfigType config_type = ConfigType::GlobalConfig);
explicit Config(const std::string& config_loc = "qt-config.ini", bool is_global = true);
~Config();
void Reload();
void Save();
void ReadControlPlayerValue(std::size_t player_index);
void SaveControlPlayerValue(std::size_t player_index);
const std::string& GetConfigFilePath() const;
static const std::array<int, Settings::NativeButton::NumButtons> default_buttons;
static const std::array<int, Settings::NativeMotion::NumMotions> default_motions;
static const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> default_analogs;
@@ -45,10 +33,8 @@ public:
static const std::array<UISettings::Shortcut, 16> default_hotkeys;
private:
void Initialize(const std::string& config_name);
void ReadValues();
void ReadPlayerValue(std::size_t player_index);
void ReadPlayerValues();
void ReadDebugValues();
void ReadKeyboardValues();
void ReadMouseValues();
@@ -76,7 +62,7 @@ private:
void ReadWebServiceValues();
void SaveValues();
void SavePlayerValue(std::size_t player_index);
void SavePlayerValues();
void SaveDebugValues();
void SaveMouseValues();
void SaveTouchscreenValues();
@@ -125,9 +111,9 @@ private:
void WriteSettingGlobal(const QString& name, const QVariant& value, bool use_global,
const QVariant& default_value);
ConfigType type;
std::unique_ptr<QSettings> qt_config;
std::string qt_config_loc;
bool global;
};

View File

@@ -275,12 +275,32 @@
<signal>accepted()</signal>
<receiver>ConfigureDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>220</x>
<y>380</y>
</hint>
<hint type="destinationlabel">
<x>220</x>
<y>200</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>ConfigureDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>220</x>
<y>380</y>
</hint>
<hint type="destinationlabel">
<x>220</x>
<y>200</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -4,14 +4,11 @@
#include "ui_configure_debug_controller.h"
#include "yuzu/configuration/configure_debug_controller.h"
#include "yuzu/configuration/configure_input_player.h"
ConfigureDebugController::ConfigureDebugController(QWidget* parent,
InputCommon::InputSubsystem* input_subsystem,
InputProfiles* profiles)
InputCommon::InputSubsystem* input_subsystem)
: QDialog(parent), ui(std::make_unique<Ui::ConfigureDebugController>()),
debug_controller(
new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, profiles, true)) {
debug_controller(new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, true)) {
ui->setupUi(this);
ui->controllerLayout->addWidget(debug_controller);

View File

@@ -6,13 +6,10 @@
#include <memory>
#include <QDialog>
#include "yuzu/configuration/configure_input_player.h"
class QPushButton;
class ConfigureInputPlayer;
class InputProfiles;
namespace InputCommon {
class InputSubsystem;
}
@@ -25,8 +22,8 @@ class ConfigureDebugController : public QDialog {
Q_OBJECT
public:
explicit ConfigureDebugController(QWidget* parent, InputCommon::InputSubsystem* input_subsystem,
InputProfiles* profiles);
explicit ConfigureDebugController(QWidget* parent,
InputCommon::InputSubsystem* input_subsystem);
~ConfigureDebugController() override;
void ApplyConfiguration();

View File

@@ -66,12 +66,32 @@
<signal>accepted()</signal>
<receiver>ConfigureDebugController</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>140</x>
<y>318</y>
</hint>
<hint type="destinationlabel">
<x>140</x>
<y>169</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>ConfigureDebugController</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>140</x>
<y>318</y>
</hint>
<hint type="destinationlabel">
<x>140</x>
<y>169</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -23,8 +23,6 @@
#include "yuzu/configuration/configure_motion_touch.h"
#include "yuzu/configuration/configure_mouse_advanced.h"
#include "yuzu/configuration/configure_touchscreen_advanced.h"
#include "yuzu/configuration/configure_vibration.h"
#include "yuzu/configuration/input_profiles.h"
namespace {
template <typename Dialog, typename... Args>
@@ -66,8 +64,7 @@ void OnDockedModeChanged(bool last_state, bool new_state) {
}
ConfigureInput::ConfigureInput(QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()),
profiles(std::make_unique<InputProfiles>()) {
: QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) {
ui->setupUi(this);
}
@@ -76,22 +73,14 @@ ConfigureInput::~ConfigureInput() = default;
void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
std::size_t max_players) {
player_controllers = {
new ConfigureInputPlayer(this, 0, ui->consoleInputSettings, input_subsystem,
profiles.get()),
new ConfigureInputPlayer(this, 1, ui->consoleInputSettings, input_subsystem,
profiles.get()),
new ConfigureInputPlayer(this, 2, ui->consoleInputSettings, input_subsystem,
profiles.get()),
new ConfigureInputPlayer(this, 3, ui->consoleInputSettings, input_subsystem,
profiles.get()),
new ConfigureInputPlayer(this, 4, ui->consoleInputSettings, input_subsystem,
profiles.get()),
new ConfigureInputPlayer(this, 5, ui->consoleInputSettings, input_subsystem,
profiles.get()),
new ConfigureInputPlayer(this, 6, ui->consoleInputSettings, input_subsystem,
profiles.get()),
new ConfigureInputPlayer(this, 7, ui->consoleInputSettings, input_subsystem,
profiles.get()),
new ConfigureInputPlayer(this, 0, ui->consoleInputSettings, input_subsystem),
new ConfigureInputPlayer(this, 1, ui->consoleInputSettings, input_subsystem),
new ConfigureInputPlayer(this, 2, ui->consoleInputSettings, input_subsystem),
new ConfigureInputPlayer(this, 3, ui->consoleInputSettings, input_subsystem),
new ConfigureInputPlayer(this, 4, ui->consoleInputSettings, input_subsystem),
new ConfigureInputPlayer(this, 5, ui->consoleInputSettings, input_subsystem),
new ConfigureInputPlayer(this, 6, ui->consoleInputSettings, input_subsystem),
new ConfigureInputPlayer(this, 7, ui->consoleInputSettings, input_subsystem),
};
player_tabs = {
@@ -124,10 +113,8 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
}
}
});
connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputDevices, this,
&ConfigureInput::UpdateAllInputDevices);
connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputProfiles, this,
&ConfigureInput::UpdateAllInputProfiles, Qt::QueuedConnection);
connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputDevices,
[this] { UpdateAllInputDevices(); });
connect(player_connected[i], &QCheckBox::stateChanged, [this, i](int state) {
player_controllers[i]->ConnectPlayer(state == Qt::Checked);
});
@@ -147,7 +134,7 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced));
ui->tabAdvanced->layout()->addWidget(advanced);
connect(advanced, &ConfigureInputAdvanced::CallDebugControllerDialog, [this, input_subsystem] {
CallConfigureDialog<ConfigureDebugController>(*this, input_subsystem, profiles.get());
CallConfigureDialog<ConfigureDebugController>(*this, input_subsystem);
});
connect(advanced, &ConfigureInputAdvanced::CallMouseConfigDialog, [this, input_subsystem] {
CallConfigureDialog<ConfigureMouseAdvanced>(*this, input_subsystem);
@@ -159,9 +146,6 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem);
});
connect(ui->vibrationButton, &QPushButton::clicked,
[this] { CallConfigureDialog<ConfigureVibration>(*this); });
connect(ui->motionButton, &QPushButton::clicked, [this, input_subsystem] {
CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem);
});
@@ -187,12 +171,12 @@ void ConfigureInput::ApplyConfiguration() {
advanced->ApplyConfiguration();
const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue();
Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked());
OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode.GetValue());
const bool pre_docked_mode = Settings::values.use_docked_mode;
Settings::values.use_docked_mode = ui->radioDocked->isChecked();
OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode);
Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked());
Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked());
Settings::values.vibration_enabled = ui->vibrationGroup->isChecked();
Settings::values.motion_enabled = ui->motionGroup->isChecked();
}
void ConfigureInput::changeEvent(QEvent* event) {
@@ -209,16 +193,16 @@ void ConfigureInput::RetranslateUI() {
void ConfigureInput::LoadConfiguration() {
LoadPlayerControllerIndices();
UpdateDockedState(Settings::values.players.GetValue()[8].connected);
UpdateDockedState(Settings::values.players[8].connected);
ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue());
ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue());
ui->vibrationGroup->setChecked(Settings::values.vibration_enabled);
ui->motionGroup->setChecked(Settings::values.motion_enabled);
}
void ConfigureInput::LoadPlayerControllerIndices() {
for (std::size_t i = 0; i < player_connected.size(); ++i) {
const auto connected = Settings::values.players.GetValue()[i].connected ||
(i == 0 && Settings::values.players.GetValue()[8].connected);
const auto connected = Settings::values.players[i].connected ||
(i == 0 && Settings::values.players[8].connected);
player_connected[i]->setChecked(connected);
}
}
@@ -247,8 +231,8 @@ void ConfigureInput::UpdateDockedState(bool is_handheld) {
ui->radioDocked->setEnabled(!is_handheld);
ui->radioUndocked->setEnabled(!is_handheld);
ui->radioDocked->setChecked(Settings::values.use_docked_mode.GetValue());
ui->radioUndocked->setChecked(!Settings::values.use_docked_mode.GetValue());
ui->radioDocked->setChecked(Settings::values.use_docked_mode);
ui->radioUndocked->setChecked(!Settings::values.use_docked_mode);
// Also force into undocked mode if the controller type is handheld.
if (is_handheld) {
@@ -258,16 +242,6 @@ void ConfigureInput::UpdateDockedState(bool is_handheld) {
void ConfigureInput::UpdateAllInputDevices() {
for (const auto& player : player_controllers) {
player->UpdateInputDeviceCombobox();
}
}
void ConfigureInput::UpdateAllInputProfiles(std::size_t player_index) {
for (std::size_t i = 0; i < player_controllers.size(); ++i) {
if (i == player_index) {
continue;
}
player_controllers[i]->UpdateInputProfiles();
player->UpdateInputDevices();
}
}

View File

@@ -8,18 +8,17 @@
#include <memory>
#include <QKeyEvent>
#include <QList>
#include <QWidget>
#include "yuzu/configuration/configure_input_advanced.h"
#include "yuzu/configuration/configure_input_player.h"
#include "ui_configure_input.h"
class QCheckBox;
class QString;
class QTimer;
class ConfigureInputAdvanced;
class ConfigureInputPlayer;
class InputProfiles;
namespace InputCommon {
class InputSubsystem;
}
@@ -52,7 +51,6 @@ private:
void UpdateDockedState(bool is_handheld);
void UpdateAllInputDevices();
void UpdateAllInputProfiles(std::size_t player_index);
/// Load configuration settings.
void LoadConfiguration();
@@ -63,8 +61,6 @@ private:
std::unique_ptr<Ui::ConfigureInput> ui;
std::unique_ptr<InputProfiles> profiles;
std::array<ConfigureInputPlayer*, 8> player_controllers;
std::array<QWidget*, 8> player_tabs;
std::array<QCheckBox*, 8> player_connected;

View File

@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>680</width>
<width>700</width>
<height>540</height>
</rect>
</property>
@@ -142,7 +142,7 @@
<number>6</number>
</property>
<property name="leftMargin">
<number>8</number>
<number>3</number>
</property>
<property name="topMargin">
<number>6</number>
@@ -195,24 +195,30 @@
<number>3</number>
</property>
<item>
<widget class="QPushButton" name="vibrationButton">
<widget class="QSpinBox" name="vibrationSpin">
<property name="minimumSize">
<size>
<width>68</width>
<height>0</height>
<width>65</width>
<height>21</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>65</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<property name="suffix">
<string>%</string>
</property>
<property name="text">
<string>Configure</string>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>200</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
@@ -244,18 +250,18 @@
<widget class="QPushButton" name="motionButton">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Configure</string>
@@ -266,7 +272,7 @@
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<widget class="QWidget" name="connectedControllers" native="true">
<widget class="QWidget" name="widget" native="true">
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>5</number>
@@ -462,13 +468,13 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
@@ -488,7 +494,7 @@
<enum>Qt::LeftToRight</enum>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Defaults</string>
@@ -505,13 +511,13 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
@@ -531,7 +537,7 @@
<enum>Qt::LeftToRight</enum>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Clear</string>

View File

@@ -68,7 +68,8 @@ ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent)
for (std::size_t button_idx = 0; button_idx < color_buttons.size(); ++button_idx) {
connect(color_buttons[button_idx], &QPushButton::clicked, this,
[this, player_idx, button_idx] {
OnControllerButtonClick(player_idx, button_idx);
OnControllerButtonClick(static_cast<int>(player_idx),
static_cast<int>(button_idx));
});
}
}
@@ -93,21 +94,20 @@ ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent)
ConfigureInputAdvanced::~ConfigureInputAdvanced() = default;
void ConfigureInputAdvanced::OnControllerButtonClick(std::size_t player_idx,
std::size_t button_idx) {
void ConfigureInputAdvanced::OnControllerButtonClick(int player_idx, int button_idx) {
const QColor new_bg_color = QColorDialog::getColor(controllers_colors[player_idx][button_idx]);
if (!new_bg_color.isValid()) {
return;
}
controllers_colors[player_idx][button_idx] = new_bg_color;
controllers_color_buttons[player_idx][button_idx]->setStyleSheet(
QStringLiteral("background-color: %1; min-width: 60px;")
QStringLiteral("background-color: %1; min-width: 55px;")
.arg(controllers_colors[player_idx][button_idx].name()));
}
void ConfigureInputAdvanced::ApplyConfiguration() {
for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) {
auto& player = Settings::values.players.GetValue()[player_idx];
auto& player = Settings::values.players[player_idx];
std::array<u32, 4> colors{};
std::transform(controllers_colors[player_idx].begin(), controllers_colors[player_idx].end(),
colors.begin(), [](QColor color) { return color.rgb(); });
@@ -126,7 +126,7 @@ void ConfigureInputAdvanced::ApplyConfiguration() {
void ConfigureInputAdvanced::LoadConfiguration() {
for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) {
auto& player = Settings::values.players.GetValue()[player_idx];
auto& player = Settings::values.players[player_idx];
std::array<u32, 4> colors = {
player.body_color_left,
player.button_color_left,
@@ -139,7 +139,7 @@ void ConfigureInputAdvanced::LoadConfiguration() {
for (std::size_t button_idx = 0; button_idx < colors.size(); ++button_idx) {
controllers_color_buttons[player_idx][button_idx]->setStyleSheet(
QStringLiteral("background-color: %1; min-width: 60px;")
QStringLiteral("background-color: %1; min-width: 55px;")
.arg(controllers_colors[player_idx][button_idx].name()));
}
}

View File

@@ -35,7 +35,7 @@ private:
void RetranslateUI();
void UpdateUIEnabled();
void OnControllerButtonClick(std::size_t player_idx, std::size_t button_idx);
void OnControllerButtonClick(int player_idx, int button_idx);
void LoadConfiguration();

View File

@@ -192,18 +192,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -247,18 +247,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -323,18 +323,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -378,18 +378,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -478,18 +478,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -533,18 +533,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -609,18 +609,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -664,18 +664,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -782,18 +782,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -837,18 +837,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -913,18 +913,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -968,18 +968,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -1068,18 +1068,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -1123,18 +1123,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -1199,18 +1199,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -1254,18 +1254,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -1393,18 +1393,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -1448,18 +1448,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -1524,18 +1524,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -1579,18 +1579,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -1679,18 +1679,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -1734,18 +1734,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -1810,18 +1810,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -1865,18 +1865,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -1983,18 +1983,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -2038,18 +2038,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -2114,18 +2114,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -2169,18 +2169,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -2269,18 +2269,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -2324,18 +2324,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -2400,18 +2400,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>
@@ -2455,18 +2455,18 @@
</property>
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string/>

View File

@@ -0,0 +1,37 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "ui_configure_input_dialog.h"
#include "yuzu/configuration/configure_input_dialog.h"
ConfigureInputDialog::ConfigureInputDialog(QWidget* parent, std::size_t max_players,
InputCommon::InputSubsystem* input_subsystem)
: QDialog(parent), ui(std::make_unique<Ui::ConfigureInputDialog>()),
input_widget(new ConfigureInput(this)) {
ui->setupUi(this);
input_widget->Initialize(input_subsystem, max_players);
ui->inputLayout->addWidget(input_widget);
RetranslateUI();
}
ConfigureInputDialog::~ConfigureInputDialog() = default;
void ConfigureInputDialog::ApplyConfiguration() {
input_widget->ApplyConfiguration();
}
void ConfigureInputDialog::changeEvent(QEvent* event) {
if (event->type() == QEvent::LanguageChange) {
RetranslateUI();
}
QDialog::changeEvent(event);
}
void ConfigureInputDialog::RetranslateUI() {
ui->retranslateUi(this);
}

View File

@@ -0,0 +1,38 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include <QDialog>
#include "yuzu/configuration/configure_input.h"
class QPushButton;
namespace InputCommon {
class InputSubsystem;
}
namespace Ui {
class ConfigureInputDialog;
}
class ConfigureInputDialog : public QDialog {
Q_OBJECT
public:
explicit ConfigureInputDialog(QWidget* parent, std::size_t max_players,
InputCommon::InputSubsystem* input_subsystem);
~ConfigureInputDialog() override;
void ApplyConfiguration();
private:
void changeEvent(QEvent* event) override;
void RetranslateUI();
std::unique_ptr<Ui::ConfigureInputDialog> ui;
ConfigureInput* input_widget;
};

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConfigureInputProfileDialog</class>
<widget class="QDialog" name="ConfigureInputProfileDialog">
<class>ConfigureInputDialog</class>
<widget class="QDialog" name="ConfigureInputDialog">
<property name="geometry">
<rect>
<x>0</x>
@@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
<string>Create Input Profile</string>
<string>Configure Input</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
@@ -30,24 +30,10 @@
<number>9</number>
</property>
<item>
<layout class="QHBoxLayout" name="controllerLayout"/>
<layout class="QHBoxLayout" name="inputLayout"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="clear_all_button">
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="restore_defaults_button">
<property name="text">
<string>Defaults</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
@@ -64,7 +50,7 @@
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>ConfigureInputProfileDialog</receiver>
<receiver>ConfigureInputDialog</receiver>
<slot>accept()</slot>
</connection>
</connections>

View File

@@ -4,7 +4,6 @@
#include <algorithm>
#include <memory>
#include <thread>
#include <utility>
#include <QGridLayout>
#include <QInputDialog>
@@ -23,9 +22,8 @@
#include "ui_configure_input_player.h"
#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_input_player.h"
#include "yuzu/configuration/configure_vibration.h"
#include "yuzu/configuration/input_profiles.h"
#include "yuzu/util/limitable_input_dialog.h"
constexpr std::size_t HANDHELD_INDEX = 8;
const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM>
ConfigureInputPlayer::analog_sub_buttons{{
@@ -37,8 +35,6 @@ const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM>
namespace {
constexpr std::size_t HANDHELD_INDEX = 8;
void UpdateController(Settings::ControllerType controller_type, std::size_t npad_index,
bool connected) {
Core::System& system{Core::System::GetInstance()};
@@ -244,11 +240,10 @@ QString AnalogToText(const Common::ParamPackage& param, const std::string& dir)
ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index,
QWidget* bottom_row,
InputCommon::InputSubsystem* input_subsystem_,
InputProfiles* profiles_, bool debug)
bool debug)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index),
debug(debug), input_subsystem{input_subsystem_}, profiles(profiles_),
timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()),
bottom_row(bottom_row) {
debug(debug), input_subsystem{input_subsystem_}, timeout_timer(std::make_unique<QTimer>()),
poll_timer(std::make_unique<QTimer>()), bottom_row(bottom_row) {
ui->setupUi(this);
setFocusPolicy(Qt::ClickFocus);
@@ -371,18 +366,6 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
}
connect(analog_button, &QPushButton::clicked, [=, this] {
if (!map_analog_stick_accepted) {
map_analog_stick_accepted =
QMessageBox::information(
this, tr("Map Analog Stick"),
tr("After pressing OK, first move your joystick horizontally, and then "
"vertically.\nTo invert the axes, first move your joystick "
"vertically, and then horizontally."),
QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok;
if (!map_analog_stick_accepted) {
return;
}
}
HandleClick(
analog_map_buttons[analog_id][sub_button_id],
[=, this](const Common::ParamPackage& params) {
@@ -472,14 +455,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
});
}
if (debug || player_index == 9) {
ui->groupConnectedController->setCheckable(false);
}
// The Debug Controller can only choose the Pro Controller.
if (debug) {
ui->buttonScreenshot->setEnabled(false);
ui->buttonHome->setEnabled(false);
ui->groupConnectedController->setCheckable(false);
QStringList debug_controller_types = {
tr("Pro Controller"),
};
@@ -497,12 +477,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
UpdateMotionButtons();
});
connect(ui->comboDevices, qOverload<int>(&QComboBox::activated), this,
connect(ui->comboDevices, qOverload<int>(&QComboBox::currentIndexChanged), this,
&ConfigureInputPlayer::UpdateMappingWithDefaults);
ui->comboDevices->setCurrentIndex(-1);
ui->buttonRefreshDevices->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh")));
UpdateInputDevices();
connect(ui->buttonRefreshDevices, &QPushButton::clicked,
[this] { emit RefreshInputDevices(); });
@@ -513,14 +492,14 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
Common::ParamPackage params;
if (input_subsystem->GetGCButtons()->IsPolling()) {
params = input_subsystem->GetGCButtons()->GetNextInput();
if (params.Has("engine") && IsInputAcceptable(params)) {
if (params.Has("engine")) {
SetPollingResult(params, false);
return;
}
}
if (input_subsystem->GetGCAnalogs()->IsPolling()) {
params = input_subsystem->GetGCAnalogs()->GetNextInput();
if (params.Has("engine") && IsInputAcceptable(params)) {
if (params.Has("engine")) {
SetPollingResult(params, false);
return;
}
@@ -534,24 +513,13 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
}
for (auto& poller : device_pollers) {
params = poller->GetNextInput();
if (params.Has("engine") && IsInputAcceptable(params)) {
if (params.Has("engine")) {
SetPollingResult(params, false);
return;
}
}
});
UpdateInputProfiles();
connect(ui->buttonProfilesNew, &QPushButton::clicked, this,
&ConfigureInputPlayer::CreateProfile);
connect(ui->buttonProfilesDelete, &QPushButton::clicked, this,
&ConfigureInputPlayer::DeleteProfile);
connect(ui->comboProfiles, qOverload<int>(&QComboBox::activated), this,
&ConfigureInputPlayer::LoadProfile);
connect(ui->buttonProfilesSave, &QPushButton::clicked, this,
&ConfigureInputPlayer::SaveProfile);
LoadConfiguration();
// TODO(wwylele): enable this when we actually emulate it
@@ -561,7 +529,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
ConfigureInputPlayer::~ConfigureInputPlayer() = default;
void ConfigureInputPlayer::ApplyConfiguration() {
auto& player = Settings::values.players.GetValue()[player_index];
auto& player = Settings::values.players[player_index];
auto& buttons = debug ? Settings::values.debug_pad_buttons : player.buttons;
auto& analogs = debug ? Settings::values.debug_pad_analogs : player.analogs;
@@ -575,58 +543,33 @@ void ConfigureInputPlayer::ApplyConfiguration() {
}
auto& motions = player.motions;
std::transform(motions_param.begin(), motions_param.end(), motions.begin(),
[](const Common::ParamPackage& param) { return param.Serialize(); });
const auto controller_type =
GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
const auto player_connected = ui->groupConnectedController->isChecked() &&
controller_type != Settings::ControllerType::Handheld;
player.controller_type =
static_cast<Settings::ControllerType>(ui->comboControllerType->currentIndex());
player.connected = ui->groupConnectedController->isChecked();
if (player.controller_type == controller_type && player.connected == player_connected) {
// Set vibration devices in the event that the input device has changed.
ConfigureVibration::SetVibrationDevices(player_index);
// Player 2-8
if (player_index != 0) {
UpdateController(player.controller_type, player_index, player.connected);
return;
}
// Disconnect the controller first.
UpdateController(controller_type, player_index, false);
player.controller_type = controller_type;
player.connected = player_connected;
ConfigureVibration::SetVibrationDevices(player_index);
// Handheld
if (player_index == 0) {
auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
if (controller_type == Settings::ControllerType::Handheld) {
handheld = player;
}
handheld.connected = ui->groupConnectedController->isChecked() &&
controller_type == Settings::ControllerType::Handheld;
UpdateController(Settings::ControllerType::Handheld, HANDHELD_INDEX, handheld.connected);
// Player 1 and Handheld
auto& handheld = Settings::values.players[HANDHELD_INDEX];
// If Handheld is selected, copy all the settings from Player 1 to Handheld.
if (player.controller_type == Settings::ControllerType::Handheld) {
handheld = player;
handheld.connected = ui->groupConnectedController->isChecked();
player.connected = false; // Disconnect Player 1
} else {
player.connected = ui->groupConnectedController->isChecked();
handheld.connected = false; // Disconnect Handheld
}
if (!player.connected) {
return;
}
// This emulates a delay between disconnecting and reconnecting controllers as some games
// do not respond to a change in controller type if it was instantaneous.
using namespace std::chrono_literals;
std::this_thread::sleep_for(20ms);
UpdateController(controller_type, player_index, player_connected);
}
void ConfigureInputPlayer::showEvent(QShowEvent* event) {
if (bottom_row == nullptr) {
return;
}
QWidget::showEvent(event);
ui->main->addWidget(bottom_row);
UpdateController(player.controller_type, player_index, player.connected);
UpdateController(Settings::ControllerType::Handheld, HANDHELD_INDEX, handheld.connected);
}
void ConfigureInputPlayer::changeEvent(QEvent* event) {
@@ -643,7 +586,7 @@ void ConfigureInputPlayer::RetranslateUI() {
}
void ConfigureInputPlayer::LoadConfiguration() {
auto& player = Settings::values.players.GetValue()[player_index];
auto& player = Settings::values.players[player_index];
if (debug) {
std::transform(Settings::values.debug_pad_buttons.begin(),
Settings::values.debug_pad_buttons.end(), buttons_param.begin(),
@@ -661,7 +604,6 @@ void ConfigureInputPlayer::LoadConfiguration() {
}
UpdateUI();
UpdateInputDeviceCombobox();
if (debug) {
return;
@@ -670,75 +612,44 @@ void ConfigureInputPlayer::LoadConfiguration() {
ui->comboControllerType->setCurrentIndex(static_cast<int>(player.controller_type));
ui->groupConnectedController->setChecked(
player.connected ||
(player_index == 0 && Settings::values.players.GetValue()[HANDHELD_INDEX].connected));
(player_index == 0 && Settings::values.players[HANDHELD_INDEX].connected));
}
void ConfigureInputPlayer::ConnectPlayer(bool connected) {
ui->groupConnectedController->setChecked(connected);
}
void ConfigureInputPlayer::UpdateInputDeviceCombobox() {
// Skip input device persistence if "Input Devices" is set to "Any".
if (ui->comboDevices->currentIndex() == 0) {
UpdateInputDevices();
return;
}
// Find the first button that isn't empty.
const auto button_param =
std::find_if(buttons_param.begin(), buttons_param.end(),
[](const Common::ParamPackage param) { return param.Has("engine"); });
const bool buttons_empty = button_param == buttons_param.end();
const auto current_engine = button_param->Get("engine", "");
const auto current_guid = button_param->Get("guid", "");
const auto current_port = button_param->Get("port", "");
const bool is_keyboard_mouse = current_engine == "keyboard" || current_engine == "mouse";
UpdateInputDevices();
if (buttons_empty) {
return;
}
const bool all_one_device =
std::all_of(buttons_param.begin(), buttons_param.end(),
[current_engine, current_guid, current_port,
is_keyboard_mouse](const Common::ParamPackage param) {
if (is_keyboard_mouse) {
return !param.Has("engine") || param.Get("engine", "") == "keyboard" ||
param.Get("engine", "") == "mouse";
}
return !param.Has("engine") || (param.Get("engine", "") == current_engine &&
param.Get("guid", "") == current_guid &&
param.Get("port", "") == current_port);
});
if (all_one_device) {
if (is_keyboard_mouse) {
ui->comboDevices->setCurrentIndex(1);
return;
}
const auto devices_it = std::find_if(
input_devices.begin(), input_devices.end(),
[current_engine, current_guid, current_port](const Common::ParamPackage param) {
return param.Get("class", "") == current_engine &&
param.Get("guid", "") == current_guid &&
param.Get("port", "") == current_port;
});
const int device_index =
devices_it != input_devices.end()
? static_cast<int>(std::distance(input_devices.begin(), devices_it))
: 0;
ui->comboDevices->setCurrentIndex(device_index);
} else {
ui->comboDevices->setCurrentIndex(0);
void ConfigureInputPlayer::UpdateInputDevices() {
input_devices = input_subsystem->GetInputDevices();
ui->comboDevices->clear();
for (auto device : input_devices) {
ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {});
}
}
void ConfigureInputPlayer::RestoreDefaults() {
UpdateMappingWithDefaults();
// Reset Buttons
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])};
}
// Reset Analogs and Modifier Buttons
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])};
SetAnalogParam(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]);
}
analogs_param[analog_id].Set(
"modifier", InputCommon::GenerateKeyboardParam(Config::default_stick_mod[analog_id]));
}
for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
motions_param[motion_id] = Common::ParamPackage{
InputCommon::GenerateKeyboardParam(Config::default_motions[motion_id])};
}
UpdateUI();
UpdateInputDevices();
ui->comboControllerType->setCurrentIndex(0);
}
void ConfigureInputPlayer::ClearAll() {
@@ -841,12 +752,117 @@ void ConfigureInputPlayer::UpdateUI() {
}
}
void ConfigureInputPlayer::UpdateInputDevices() {
input_devices = input_subsystem->GetInputDevices();
ui->comboDevices->clear();
for (auto device : input_devices) {
ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {});
void ConfigureInputPlayer::UpdateMappingWithDefaults() {
if (ui->comboDevices->currentIndex() < 2) {
return;
}
const auto& device = input_devices[ui->comboDevices->currentIndex()];
auto button_mapping = input_subsystem->GetButtonMappingForDevice(device);
auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device);
for (std::size_t i = 0; i < buttons_param.size(); ++i) {
buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)];
}
for (std::size_t i = 0; i < analogs_param.size(); ++i) {
analogs_param[i] = analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)];
}
UpdateUI();
}
void ConfigureInputPlayer::HandleClick(
QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter,
InputCommon::Polling::DeviceType type) {
if (button == ui->buttonMotionLeft || button == ui->buttonMotionRight) {
button->setText(tr("Shake!"));
} else {
button->setText(tr("[waiting]"));
}
button->setFocus();
// The first two input devices are always Any and Keyboard/Mouse. If the user filtered to a
// controller, then they don't want keyboard/mouse input
want_keyboard_mouse = ui->comboDevices->currentIndex() < 2;
input_setter = new_input_setter;
device_pollers = input_subsystem->GetPollers(type);
for (auto& poller : device_pollers) {
poller->Start();
}
QWidget::grabMouse();
QWidget::grabKeyboard();
if (type == InputCommon::Polling::DeviceType::Button) {
input_subsystem->GetGCButtons()->BeginConfiguration();
} else {
input_subsystem->GetGCAnalogs()->BeginConfiguration();
}
if (type == InputCommon::Polling::DeviceType::Motion) {
input_subsystem->GetUDPMotions()->BeginConfiguration();
}
timeout_timer->start(2500); // Cancel after 2.5 seconds
poll_timer->start(50); // Check for new inputs every 50ms
}
void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, bool abort) {
timeout_timer->stop();
poll_timer->stop();
for (auto& poller : device_pollers) {
poller->Stop();
}
QWidget::releaseMouse();
QWidget::releaseKeyboard();
input_subsystem->GetGCButtons()->EndConfiguration();
input_subsystem->GetGCAnalogs()->EndConfiguration();
input_subsystem->GetUDPMotions()->EndConfiguration();
if (!abort) {
(*input_setter)(params);
}
UpdateUI();
input_setter = std::nullopt;
}
void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) {
if (!input_setter || !event) {
return;
}
if (want_keyboard_mouse) {
SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->button())},
false);
} else {
// We don't want any mouse buttons, so don't stop polling
return;
}
SetPollingResult({}, true);
}
void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) {
if (!input_setter || !event) {
return;
}
if (event->key() != Qt::Key_Escape) {
if (want_keyboard_mouse) {
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);
}
void ConfigureInputPlayer::UpdateControllerIcon() {
@@ -869,7 +885,7 @@ void ConfigureInputPlayer::UpdateControllerIcon() {
}
}();
const QString theme = [] {
const QString theme = [this] {
if (QIcon::themeName().contains(QStringLiteral("dark"))) {
return QStringLiteral("_dark");
} else if (QIcon::themeName().contains(QStringLiteral("midnight"))) {
@@ -970,260 +986,14 @@ void ConfigureInputPlayer::UpdateMotionButtons() {
}
}
void ConfigureInputPlayer::UpdateMappingWithDefaults() {
if (ui->comboDevices->currentIndex() == 0) {
void ConfigureInputPlayer::showEvent(QShowEvent* event) {
if (bottom_row == nullptr) {
return;
}
if (ui->comboDevices->currentIndex() == 1) {
// Reset keyboard bindings
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])};
SetAnalogParam(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]);
}
analogs_param[analog_id].Set("modifier", InputCommon::GenerateKeyboardParam(
Config::default_stick_mod[analog_id]));
}
for (int motion_id = 0; motion_id < Settings::NativeMotion::NumMotions; ++motion_id) {
motions_param[motion_id] = Common::ParamPackage{
InputCommon::GenerateKeyboardParam(Config::default_motions[motion_id])};
}
UpdateUI();
return;
}
// Reset controller bindings
const auto& device = input_devices[ui->comboDevices->currentIndex()];
auto button_mapping = input_subsystem->GetButtonMappingForDevice(device);
auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device);
for (std::size_t i = 0; i < buttons_param.size(); ++i) {
buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)];
}
for (std::size_t i = 0; i < analogs_param.size(); ++i) {
analogs_param[i] = analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)];
}
UpdateUI();
QWidget::showEvent(event);
ui->main->addWidget(bottom_row);
}
void ConfigureInputPlayer::HandleClick(
QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter,
InputCommon::Polling::DeviceType type) {
if (button == ui->buttonMotionLeft || button == ui->buttonMotionRight) {
button->setText(tr("Shake!"));
} else {
button->setText(tr("[waiting]"));
}
button->setFocus();
// The first two input devices are always Any and Keyboard/Mouse. If the user filtered to a
// controller, then they don't want keyboard/mouse input
want_keyboard_mouse = ui->comboDevices->currentIndex() < 2;
input_setter = new_input_setter;
device_pollers = input_subsystem->GetPollers(type);
for (auto& poller : device_pollers) {
poller->Start();
}
QWidget::grabMouse();
QWidget::grabKeyboard();
if (type == InputCommon::Polling::DeviceType::Button) {
input_subsystem->GetGCButtons()->BeginConfiguration();
} else {
input_subsystem->GetGCAnalogs()->BeginConfiguration();
}
if (type == InputCommon::Polling::DeviceType::Motion) {
input_subsystem->GetUDPMotions()->BeginConfiguration();
}
timeout_timer->start(2500); // Cancel after 2.5 seconds
poll_timer->start(50); // Check for new inputs every 50ms
}
void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, bool abort) {
timeout_timer->stop();
poll_timer->stop();
for (auto& poller : device_pollers) {
poller->Stop();
}
QWidget::releaseMouse();
QWidget::releaseKeyboard();
input_subsystem->GetGCButtons()->EndConfiguration();
input_subsystem->GetGCAnalogs()->EndConfiguration();
input_subsystem->GetUDPMotions()->EndConfiguration();
if (!abort) {
(*input_setter)(params);
}
UpdateUI();
UpdateInputDeviceCombobox();
input_setter = std::nullopt;
}
bool ConfigureInputPlayer::IsInputAcceptable(const Common::ParamPackage& params) const {
if (ui->comboDevices->currentIndex() == 0) {
return true;
}
// Keyboard/Mouse
if (ui->comboDevices->currentIndex() == 1) {
return params.Get("engine", "") == "keyboard" || params.Get("engine", "") == "mouse";
}
const auto current_input_device = input_devices[ui->comboDevices->currentIndex()];
return params.Get("engine", "") == current_input_device.Get("class", "") &&
params.Get("guid", "") == current_input_device.Get("guid", "") &&
params.Get("port", "") == current_input_device.Get("port", "");
}
void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) {
if (!input_setter || !event) {
return;
}
if (want_keyboard_mouse) {
SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->button())},
false);
} else {
// We don't want any mouse buttons, so don't stop polling
return;
}
SetPollingResult({}, true);
}
void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) {
if (!input_setter || !event) {
return;
}
if (event->key() != Qt::Key_Escape) {
if (want_keyboard_mouse) {
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);
}
void ConfigureInputPlayer::CreateProfile() {
const auto profile_name =
LimitableInputDialog::GetText(this, tr("New Profile"), tr("Enter a profile name:"), 1, 20);
if (profile_name.isEmpty()) {
return;
}
if (!InputProfiles::IsProfileNameValid(profile_name.toStdString())) {
QMessageBox::critical(this, tr("Create Input Profile"),
tr("The given profile name is not valid!"));
return;
}
ApplyConfiguration();
if (!profiles->CreateProfile(profile_name.toStdString(), player_index)) {
QMessageBox::critical(this, tr("Create Input Profile"),
tr("Failed to create the input profile \"%1\"").arg(profile_name));
UpdateInputProfiles();
emit RefreshInputProfiles(player_index);
return;
}
emit RefreshInputProfiles(player_index);
ui->comboProfiles->addItem(profile_name);
ui->comboProfiles->setCurrentIndex(ui->comboProfiles->count() - 1);
}
void ConfigureInputPlayer::DeleteProfile() {
const QString profile_name = ui->comboProfiles->itemText(ui->comboProfiles->currentIndex());
if (profile_name.isEmpty()) {
return;
}
if (!profiles->DeleteProfile(profile_name.toStdString())) {
QMessageBox::critical(this, tr("Delete Input Profile"),
tr("Failed to delete the input profile \"%1\"").arg(profile_name));
UpdateInputProfiles();
emit RefreshInputProfiles(player_index);
return;
}
emit RefreshInputProfiles(player_index);
ui->comboProfiles->removeItem(ui->comboProfiles->currentIndex());
ui->comboProfiles->setCurrentIndex(-1);
}
void ConfigureInputPlayer::LoadProfile() {
const QString profile_name = ui->comboProfiles->itemText(ui->comboProfiles->currentIndex());
if (profile_name.isEmpty()) {
return;
}
ApplyConfiguration();
if (!profiles->LoadProfile(profile_name.toStdString(), player_index)) {
QMessageBox::critical(this, tr("Load Input Profile"),
tr("Failed to load the input profile \"%1\"").arg(profile_name));
UpdateInputProfiles();
emit RefreshInputProfiles(player_index);
return;
}
LoadConfiguration();
}
void ConfigureInputPlayer::SaveProfile() {
const QString profile_name = ui->comboProfiles->itemText(ui->comboProfiles->currentIndex());
if (profile_name.isEmpty()) {
return;
}
ApplyConfiguration();
if (!profiles->SaveProfile(profile_name.toStdString(), player_index)) {
QMessageBox::critical(this, tr("Save Input Profile"),
tr("Failed to save the input profile \"%1\"").arg(profile_name));
UpdateInputProfiles();
emit RefreshInputProfiles(player_index);
return;
}
}
void ConfigureInputPlayer::UpdateInputProfiles() {
ui->comboProfiles->clear();
for (const auto& profile_name : profiles->GetInputProfileNames()) {
ui->comboProfiles->addItem(QString::fromStdString(profile_name));
}
ui->comboProfiles->setCurrentIndex(-1);
void ConfigureInputPlayer::ConnectPlayer(bool connected) {
ui->groupConnectedController->setChecked(connected);
}

View File

@@ -26,8 +26,6 @@ class QString;
class QTimer;
class QWidget;
class InputProfiles;
namespace InputCommon {
class InputSubsystem;
}
@@ -47,20 +45,14 @@ class ConfigureInputPlayer : public QWidget {
public:
explicit ConfigureInputPlayer(QWidget* parent, std::size_t player_index, QWidget* bottom_row,
InputCommon::InputSubsystem* input_subsystem_,
InputProfiles* profiles_, bool debug = false);
bool debug = false);
~ConfigureInputPlayer() override;
/// Save all button configurations to settings file.
void ApplyConfiguration();
/// Set the connection state checkbox (used to sync state).
void ConnectPlayer(bool connected);
/// Update the input devices combobox.
void UpdateInputDeviceCombobox();
/// Updates the list of controller profiles.
void UpdateInputProfiles();
void UpdateInputDevices();
/// Restore all buttons to their default values.
void RestoreDefaults();
@@ -68,6 +60,9 @@ public:
/// Clear all input configuration.
void ClearAll();
/// Set the connection state checkbox (used to sync state).
void ConnectPlayer(bool connected);
signals:
/// Emitted when this controller is connected by the user.
void Connected(bool connected);
@@ -75,12 +70,6 @@ signals:
void HandheldStateChanged(bool is_handheld);
/// Emitted when the input devices combobox is being refreshed.
void RefreshInputDevices();
/**
* Emitted when the input profiles combobox is being refreshed.
* The player_index represents the current player's index, and the profile combobox
* will not be updated for this index as they are already updated by other mechanisms.
*/
void RefreshInputProfiles(std::size_t player_index);
protected:
void showEvent(QShowEvent* event) override;
@@ -100,9 +89,6 @@ private:
/// Finish polling and configure input using the input_setter.
void SetPollingResult(const Common::ParamPackage& params, bool abort);
/// Checks whether a given input can be accepted.
bool IsInputAcceptable(const Common::ParamPackage& params) const;
/// Handle mouse button press events.
void mousePressEvent(QMouseEvent* event) override;
@@ -112,8 +98,8 @@ private:
/// Update UI to reflect current configuration.
void UpdateUI();
/// Update the available input devices.
void UpdateInputDevices();
/// Update the controller selection combobox
void UpdateControllerCombobox();
/// Update the current controller icon.
void UpdateControllerIcon();
@@ -127,18 +113,6 @@ private:
/// Gets the default controller mapping for this device and auto configures the input to match.
void UpdateMappingWithDefaults();
/// Creates a controller profile.
void CreateProfile();
/// Deletes the selected controller profile.
void DeleteProfile();
/// Loads the selected controller profile.
void LoadProfile();
/// Saves the current controller configuration into a selected controller profile.
void SaveProfile();
std::unique_ptr<Ui::ConfigureInputPlayer> ui;
std::size_t player_index;
@@ -146,8 +120,6 @@ private:
InputCommon::InputSubsystem* input_subsystem;
InputProfiles* profiles;
std::unique_ptr<QTimer> timeout_timer;
std::unique_ptr<QTimer> poll_timer;
@@ -187,15 +159,12 @@ private:
std::vector<std::unique_ptr<InputCommon::Polling::DevicePoller>> device_pollers;
/// A flag to indicate that the "Map Analog Stick" pop-up has been shown and accepted once.
bool map_analog_stick_accepted{};
/// A flag to indicate if keyboard keys are okay when configuring an input. If this is false,
/// keyboard events are ignored.
bool want_keyboard_mouse{};
bool want_keyboard_mouse = false;
/// List of physical devices users can map with. If a SDL backed device is selected, then you
/// can use this device to get a default mapping.
/// can usue this device to get a default mapping.
std::vector<Common::ParamPackage> input_devices;
/// Bottom row is where console wide settings are held, and its "owned" by the parent

View File

@@ -83,12 +83,6 @@
</property>
<item>
<widget class="QComboBox" name="comboControllerType">
<property name="minimumSize">
<size>
<width>0</width>
<height>21</height>
</size>
</property>
<item>
<property name="text">
<string>Pro Controller</string>
@@ -142,12 +136,6 @@
</property>
<item>
<widget class="QComboBox" name="comboDevices">
<property name="minimumSize">
<size>
<width>0</width>
<height>21</height>
</size>
</property>
<item>
<property name="text">
<string>Any</string>
@@ -164,14 +152,14 @@
<widget class="QPushButton" name="buttonRefreshDevices">
<property name="minimumSize">
<size>
<width>21</width>
<height>21</height>
<width>24</width>
<height>22</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>21</width>
<height>21</height>
<width>24</width>
<height>22</height>
</size>
</property>
<property name="styleSheet">
@@ -210,25 +198,18 @@
<number>5</number>
</property>
<item>
<widget class="QComboBox" name="comboProfiles">
<property name="minimumSize">
<size>
<width>0</width>
<height>21</height>
</size>
</property>
</widget>
<widget class="QComboBox" name="comboProfiles"/>
</item>
<item>
<widget class="QPushButton" name="buttonProfilesSave">
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Save</string>
@@ -239,12 +220,12 @@
<widget class="QPushButton" name="buttonProfilesNew">
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>New</string>
@@ -255,12 +236,12 @@
<widget class="QPushButton" name="buttonProfilesDelete">
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Delete</string>
@@ -412,18 +393,18 @@
<widget class="QPushButton" name="buttonLStickUp">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Up</string>
@@ -482,18 +463,18 @@
<widget class="QPushButton" name="buttonLStickLeft">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Left</string>
@@ -531,18 +512,18 @@
<widget class="QPushButton" name="buttonLStickRight">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Right</string>
@@ -613,18 +594,18 @@
<widget class="QPushButton" name="buttonLStickDown">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Down</string>
@@ -683,18 +664,18 @@
<widget class="QPushButton" name="buttonLStick">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Pressed</string>
@@ -732,18 +713,18 @@
<widget class="QPushButton" name="buttonLStickMod">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Modifier</string>
@@ -778,13 +759,13 @@
<widget class="QSpinBox" name="spinboxLStickRange">
<property name="minimumSize">
<size>
<width>68</width>
<width>55</width>
<height>21</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
@@ -985,18 +966,18 @@
<widget class="QPushButton" name="buttonDpadUp">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Up</string>
@@ -1055,18 +1036,18 @@
<widget class="QPushButton" name="buttonDpadLeft">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Left</string>
@@ -1104,18 +1085,18 @@
<widget class="QPushButton" name="buttonDpadRight">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Right</string>
@@ -1186,18 +1167,18 @@
<widget class="QPushButton" name="buttonDpadDown">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Down</string>
@@ -1311,18 +1292,18 @@
<widget class="QPushButton" name="buttonL">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>L</string>
@@ -1360,18 +1341,18 @@
<widget class="QPushButton" name="buttonZL">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>ZL</string>
@@ -1464,18 +1445,18 @@
<widget class="QPushButton" name="buttonMinus">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Minus</string>
@@ -1513,18 +1494,18 @@
<widget class="QPushButton" name="buttonScreenshot">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Capture</string>
@@ -1583,18 +1564,18 @@
<widget class="QPushButton" name="buttonPlus">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Plus</string>
@@ -1632,18 +1613,18 @@
<widget class="QPushButton" name="buttonHome">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Home</string>
@@ -1736,18 +1717,18 @@
<widget class="QPushButton" name="buttonR">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>R</string>
@@ -1785,18 +1766,18 @@
<widget class="QPushButton" name="buttonZR">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>ZR</string>
@@ -1889,18 +1870,18 @@
<widget class="QPushButton" name="buttonSL">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>SL</string>
@@ -1938,18 +1919,18 @@
<widget class="QPushButton" name="buttonSR">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>SR</string>
@@ -2046,18 +2027,18 @@
<widget class="QPushButton" name="buttonMotionLeft">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Left</string>
@@ -2095,18 +2076,18 @@
<widget class="QPushButton" name="buttonMotionRight">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Right</string>
@@ -2244,18 +2225,18 @@
<widget class="QPushButton" name="buttonX">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>X</string>
@@ -2314,18 +2295,18 @@
<widget class="QPushButton" name="buttonY">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Y</string>
@@ -2363,18 +2344,18 @@
<widget class="QPushButton" name="buttonA">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>A</string>
@@ -2445,18 +2426,18 @@
<widget class="QPushButton" name="buttonB">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>B</string>
@@ -2599,18 +2580,18 @@
<widget class="QPushButton" name="buttonRStickUp">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Up</string>
@@ -2669,18 +2650,18 @@
<widget class="QPushButton" name="buttonRStickLeft">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Left</string>
@@ -2718,18 +2699,18 @@
<widget class="QPushButton" name="buttonRStickRight">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Right</string>
@@ -2800,18 +2781,18 @@
<widget class="QPushButton" name="buttonRStickDown">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Down</string>
@@ -2870,18 +2851,18 @@
<widget class="QPushButton" name="buttonRStick">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Pressed</string>
@@ -2919,18 +2900,18 @@
<widget class="QPushButton" name="buttonRStickMod">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">min-width: 68px;</string>
<string notr="true">min-width: 55px;</string>
</property>
<property name="text">
<string>Modifier</string>
@@ -2965,13 +2946,13 @@
<widget class="QSpinBox" name="spinboxRStickRange">
<property name="minimumSize">
<size>
<width>68</width>
<width>55</width>
<height>21</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>55</width>
<height>16777215</height>
</size>
</property>

View File

@@ -1,37 +0,0 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "ui_configure_input_profile_dialog.h"
#include "yuzu/configuration/configure_input_player.h"
#include "yuzu/configuration/configure_input_profile_dialog.h"
ConfigureInputProfileDialog::ConfigureInputProfileDialog(
QWidget* parent, InputCommon::InputSubsystem* input_subsystem, InputProfiles* profiles)
: QDialog(parent), ui(std::make_unique<Ui::ConfigureInputProfileDialog>()),
profile_widget(new ConfigureInputPlayer(this, 9, nullptr, input_subsystem, profiles, false)) {
ui->setupUi(this);
ui->controllerLayout->addWidget(profile_widget);
connect(ui->clear_all_button, &QPushButton::clicked, this,
[this] { profile_widget->ClearAll(); });
connect(ui->restore_defaults_button, &QPushButton::clicked, this,
[this] { profile_widget->RestoreDefaults(); });
RetranslateUI();
}
ConfigureInputProfileDialog::~ConfigureInputProfileDialog() = default;
void ConfigureInputProfileDialog::changeEvent(QEvent* event) {
if (event->type() == QEvent::LanguageChange) {
RetranslateUI();
}
QDialog::changeEvent(event);
}
void ConfigureInputProfileDialog::RetranslateUI() {
ui->retranslateUi(this);
}

View File

@@ -1,40 +0,0 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include <QDialog>
class QPushButton;
class ConfigureInputPlayer;
class InputProfiles;
namespace InputCommon {
class InputSubsystem;
}
namespace Ui {
class ConfigureInputProfileDialog;
}
class ConfigureInputProfileDialog : public QDialog {
Q_OBJECT
public:
explicit ConfigureInputProfileDialog(QWidget* parent,
InputCommon::InputSubsystem* input_subsystem,
InputProfiles* profiles);
~ConfigureInputProfileDialog() override;
private:
void changeEvent(QEvent* event) override;
void RetranslateUI();
std::unique_ptr<Ui::ConfigureInputProfileDialog> ui;
ConfigureInputPlayer* profile_widget;
};

View File

@@ -312,6 +312,16 @@
<signal>accepted()</signal>
<receiver>ConfigureMotionTouch</receiver>
<slot>ApplyConfiguration()</slot>
<hints>
<hint type="sourcelabel">
<x>220</x>
<y>380</y>
</hint>
<hint type="destinationlabel">
<x>220</x>
<y>200</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -15,7 +15,7 @@
</property>
<property name="styleSheet">
<string notr="true">QPushButton {
min-width: 60px;
min-width: 55px;
}</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
@@ -42,13 +42,13 @@
<widget class="QPushButton" name="forward_button">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
@@ -82,7 +82,7 @@
<widget class="QPushButton" name="back_button">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
@@ -110,7 +110,7 @@
<widget class="QPushButton" name="left_button">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
@@ -138,13 +138,13 @@
<widget class="QPushButton" name="middle_button">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
@@ -204,13 +204,13 @@
<widget class="QPushButton" name="right_button">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
@@ -256,13 +256,13 @@
<widget class="QPushButton" name="buttonClearAll">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
@@ -275,13 +275,13 @@
<widget class="QPushButton" name="buttonRestoreDefaults">
<property name="minimumSize">
<size>
<width>68</width>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
@@ -324,12 +324,32 @@
<signal>accepted()</signal>
<receiver>ConfigureMouseAdvanced</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>124</x>
<y>266</y>
</hint>
<hint type="destinationlabel">
<x>124</x>
<y>143</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>ConfigureMouseAdvanced</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>124</x>
<y>266</y>
</hint>
<hint type="destinationlabel">
<x>124</x>
<y>143</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -29,8 +29,7 @@
ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id)
: QDialog(parent), ui(std::make_unique<Ui::ConfigurePerGame>()), title_id(title_id) {
game_config = std::make_unique<Config>(fmt::format("{:016X}", title_id),
Config::ConfigType::PerGameConfig);
game_config = std::make_unique<Config>(fmt::format("{:016X}.ini", title_id), false);
Settings::SetConfiguringGlobal(false);

View File

@@ -319,12 +319,32 @@
<signal>accepted()</signal>
<receiver>ConfigurePerGame</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>ConfigurePerGame</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -216,6 +216,16 @@ Drag points to change position, or double-click table cells to edit values.</str
<signal>rejected()</signal>
<receiver>ConfigureTouchFromButton</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>249</x>
<y>428</y>
</hint>
<hint type="destinationlabel">
<x>249</x>
<y>224</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -168,12 +168,32 @@
<signal>accepted()</signal>
<receiver>ConfigureTouchscreenAdvanced</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>140</x>
<y>318</y>
</hint>
<hint type="destinationlabel">
<x>140</x>
<y>169</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>ConfigureTouchscreenAdvanced</receiver>
<slot>reject()</slot>
</connection>
<hints>
<hint type="sourcelabel">
<x>140</x>
<y>318</y>
</hint>
<hint type="destinationlabel">
<x>140</x>
<y>169</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -1,146 +0,0 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include <unordered_map>
#include <fmt/format.h>
#include "common/param_package.h"
#include "core/settings.h"
#include "ui_configure_vibration.h"
#include "yuzu/configuration/configure_vibration.h"
ConfigureVibration::ConfigureVibration(QWidget* parent)
: QDialog(parent), ui(std::make_unique<Ui::ConfigureVibration>()) {
ui->setupUi(this);
vibration_groupboxes = {
ui->vibrationGroupPlayer1, ui->vibrationGroupPlayer2, ui->vibrationGroupPlayer3,
ui->vibrationGroupPlayer4, ui->vibrationGroupPlayer5, ui->vibrationGroupPlayer6,
ui->vibrationGroupPlayer7, ui->vibrationGroupPlayer8,
};
vibration_spinboxes = {
ui->vibrationSpinPlayer1, ui->vibrationSpinPlayer2, ui->vibrationSpinPlayer3,
ui->vibrationSpinPlayer4, ui->vibrationSpinPlayer5, ui->vibrationSpinPlayer6,
ui->vibrationSpinPlayer7, ui->vibrationSpinPlayer8,
};
const auto& players = Settings::values.players.GetValue();
for (std::size_t i = 0; i < NUM_PLAYERS; ++i) {
vibration_groupboxes[i]->setChecked(players[i].vibration_enabled);
vibration_spinboxes[i]->setValue(players[i].vibration_strength);
}
ui->checkBoxAccurateVibration->setChecked(
Settings::values.enable_accurate_vibrations.GetValue());
if (!Settings::IsConfiguringGlobal()) {
ui->checkBoxAccurateVibration->setDisabled(true);
}
RetranslateUI();
}
ConfigureVibration::~ConfigureVibration() = default;
void ConfigureVibration::ApplyConfiguration() {
auto& players = Settings::values.players.GetValue();
for (std::size_t i = 0; i < NUM_PLAYERS; ++i) {
players[i].vibration_enabled = vibration_groupboxes[i]->isChecked();
players[i].vibration_strength = vibration_spinboxes[i]->value();
}
Settings::values.enable_accurate_vibrations.SetValue(
ui->checkBoxAccurateVibration->isChecked());
}
void ConfigureVibration::SetVibrationDevices(std::size_t player_index) {
using namespace Settings::NativeButton;
static constexpr std::array<std::array<Settings::NativeButton::Values, 6>, 2> buttons{{
{DLeft, DUp, DRight, DDown, L, ZL}, // Left Buttons
{A, B, X, Y, R, ZR}, // Right Buttons
}};
auto& player = Settings::values.players.GetValue()[player_index];
for (std::size_t device_idx = 0; device_idx < buttons.size(); ++device_idx) {
std::unordered_map<std::string, int> params_count;
for (const auto button_index : buttons[device_idx]) {
const auto& player_button = player.buttons[button_index];
if (params_count.find(player_button) != params_count.end()) {
++params_count[player_button];
continue;
}
params_count.insert_or_assign(player_button, 1);
}
const auto it = std::max_element(
params_count.begin(), params_count.end(),
[](const auto& lhs, const auto& rhs) { return lhs.second < rhs.second; });
auto& vibration_param_str = player.vibrations[device_idx];
vibration_param_str.clear();
if (it->first.empty()) {
continue;
}
const auto param = Common::ParamPackage(it->first);
const auto engine = param.Get("engine", "");
const auto guid = param.Get("guid", "");
const auto port = param.Get("port", "");
if (engine.empty() || engine == "keyboard" || engine == "mouse") {
continue;
}
vibration_param_str += fmt::format("engine:{}", engine);
if (!port.empty()) {
vibration_param_str += fmt::format(",port:{}", port);
}
if (!guid.empty()) {
vibration_param_str += fmt::format(",guid:{}", guid);
}
}
if (player.vibrations[0] != player.vibrations[1]) {
return;
}
if (!player.vibrations[0].empty() &&
player.controller_type != Settings::ControllerType::RightJoycon) {
player.vibrations[1].clear();
} else if (!player.vibrations[1].empty() &&
player.controller_type == Settings::ControllerType::RightJoycon) {
player.vibrations[0].clear();
}
}
void ConfigureVibration::SetAllVibrationDevices() {
// Set vibration devices for all player indices including handheld
for (std::size_t player_idx = 0; player_idx < NUM_PLAYERS + 1; ++player_idx) {
SetVibrationDevices(player_idx);
}
}
void ConfigureVibration::changeEvent(QEvent* event) {
if (event->type() == QEvent::LanguageChange) {
RetranslateUI();
}
QDialog::changeEvent(event);
}
void ConfigureVibration::RetranslateUI() {
ui->retranslateUi(this);
}

View File

@@ -1,43 +0,0 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
#include <memory>
#include <QDialog>
class QGroupBox;
class QSpinBox;
namespace Ui {
class ConfigureVibration;
}
class ConfigureVibration : public QDialog {
Q_OBJECT
public:
explicit ConfigureVibration(QWidget* parent);
~ConfigureVibration() override;
void ApplyConfiguration();
static void SetVibrationDevices(std::size_t player_index);
static void SetAllVibrationDevices();
private:
void changeEvent(QEvent* event) override;
void RetranslateUI();
std::unique_ptr<Ui::ConfigureVibration> ui;
static constexpr std::size_t NUM_PLAYERS = 8;
// Groupboxes encapsulating the vibration strength spinbox.
std::array<QGroupBox*, NUM_PLAYERS> vibration_groupboxes;
// Spinboxes representing the vibration strength percentage.
std::array<QSpinBox*, NUM_PLAYERS> vibration_spinboxes;
};

View File

@@ -1,546 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConfigureVibration</class>
<widget class="QDialog" name="ConfigureVibration">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>364</width>
<height>242</height>
</rect>
</property>
<property name="windowTitle">
<string>Configure Vibration</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout">
<item>
<widget class="QGroupBox" name="vibrationStrengthGroup">
<property name="title">
<string>Vibration</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="0,0">
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
<widget class="QWidget" name="player14Widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="vibrationGroupPlayer1">
<property name="title">
<string>Player 1</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QSpinBox" name="vibrationSpinPlayer1">
<property name="minimumSize">
<size>
<width>68</width>
<height>21</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<height>16777215</height>
</size>
</property>
<property name="suffix">
<string>%</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>150</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="vibrationGroupPlayer2">
<property name="title">
<string>Player 2</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QSpinBox" name="vibrationSpinPlayer2">
<property name="minimumSize">
<size>
<width>68</width>
<height>21</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<height>16777215</height>
</size>
</property>
<property name="suffix">
<string>%</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>150</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="vibrationGroupPlayer3">
<property name="title">
<string>Player 3</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QSpinBox" name="vibrationSpinPlayer3">
<property name="minimumSize">
<size>
<width>68</width>
<height>21</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<height>16777215</height>
</size>
</property>
<property name="suffix">
<string>%</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>150</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="vibrationGroupPlayer4">
<property name="title">
<string>Player 4</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QSpinBox" name="vibrationSpinPlayer4">
<property name="minimumSize">
<size>
<width>68</width>
<height>21</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<height>16777215</height>
</size>
</property>
<property name="suffix">
<string>%</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>150</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="player58Widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="vibrationGroupPlayer7">
<property name="title">
<string>Player 5</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_14">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QSpinBox" name="vibrationSpinPlayer7">
<property name="minimumSize">
<size>
<width>68</width>
<height>21</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<height>16777215</height>
</size>
</property>
<property name="suffix">
<string>%</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>150</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="vibrationGroupPlayer8">
<property name="title">
<string>Player 6</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_15">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QSpinBox" name="vibrationSpinPlayer8">
<property name="minimumSize">
<size>
<width>68</width>
<height>21</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<height>16777215</height>
</size>
</property>
<property name="suffix">
<string>%</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>150</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="vibrationGroupPlayer5">
<property name="title">
<string>Player 7</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QSpinBox" name="vibrationSpinPlayer5">
<property name="minimumSize">
<size>
<width>68</width>
<height>21</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<height>16777215</height>
</size>
</property>
<property name="suffix">
<string>%</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>150</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="vibrationGroupPlayer6">
<property name="title">
<string>Player 8</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QSpinBox" name="vibrationSpinPlayer6">
<property name="minimumSize">
<size>
<width>68</width>
<height>21</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>68</width>
<height>16777215</height>
</size>
</property>
<property name="suffix">
<string>%</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>150</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="vibrationSettingsGroup">
<property name="title">
<string>Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="checkBoxAccurateVibration">
<property name="text">
<string>Enable Accurate Vibration</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="spacerVibration">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>167</width>
<height>55</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBoxVibration">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBoxVibration</sender>
<signal>accepted()</signal>
<receiver>ConfigureVibration</receiver>
<slot>accept()</slot>
</connection>
<connection>
<sender>buttonBoxVibration</sender>
<signal>rejected()</signal>
<receiver>ConfigureVibration</receiver>
<slot>reject()</slot>
</connection>
</connections>
</ui>

View File

@@ -1,131 +0,0 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <fmt/format.h>
#include "common/common_paths.h"
#include "common/file_util.h"
#include "yuzu/configuration/config.h"
#include "yuzu/configuration/input_profiles.h"
namespace FS = Common::FS;
namespace {
bool ProfileExistsInFilesystem(std::string_view profile_name) {
return FS::Exists(fmt::format("{}input" DIR_SEP "{}.ini",
FS::GetUserPath(FS::UserPath::ConfigDir), profile_name));
}
bool IsINI(std::string_view filename) {
const std::size_t index = filename.rfind('.');
if (index == std::string::npos) {
return false;
}
return filename.substr(index) == ".ini";
}
std::string GetNameWithoutExtension(const std::string& filename) {
const std::size_t index = filename.rfind('.');
if (index == std::string::npos) {
return filename;
}
return filename.substr(0, index);
}
} // namespace
InputProfiles::InputProfiles() {
const std::string input_profile_loc =
fmt::format("{}input", FS::GetUserPath(FS::UserPath::ConfigDir));
FS::ForeachDirectoryEntry(
nullptr, input_profile_loc,
[this](u64* entries_out, const std::string& directory, const std::string& filename) {
if (IsINI(filename) && IsProfileNameValid(GetNameWithoutExtension(filename))) {
map_profiles.insert_or_assign(
GetNameWithoutExtension(filename),
std::make_unique<Config>(GetNameWithoutExtension(filename),
Config::ConfigType::InputProfile));
}
return true;
});
}
InputProfiles::~InputProfiles() = default;
std::vector<std::string> InputProfiles::GetInputProfileNames() {
std::vector<std::string> profile_names;
profile_names.reserve(map_profiles.size());
for (const auto& [profile_name, config] : map_profiles) {
if (!ProfileExistsInFilesystem(profile_name)) {
DeleteProfile(profile_name);
continue;
}
profile_names.push_back(profile_name);
}
return profile_names;
}
bool InputProfiles::IsProfileNameValid(std::string_view profile_name) {
return profile_name.find_first_of("<>:;\"/\\|,.!?*") == std::string::npos;
}
bool InputProfiles::CreateProfile(const std::string& profile_name, std::size_t player_index) {
if (ProfileExistsInMap(profile_name)) {
return false;
}
map_profiles.insert_or_assign(
profile_name, std::make_unique<Config>(profile_name, Config::ConfigType::InputProfile));
return SaveProfile(profile_name, player_index);
}
bool InputProfiles::DeleteProfile(const std::string& profile_name) {
if (!ProfileExistsInMap(profile_name)) {
return false;
}
if (!ProfileExistsInFilesystem(profile_name) ||
FS::Delete(map_profiles[profile_name]->GetConfigFilePath())) {
map_profiles.erase(profile_name);
}
return !ProfileExistsInMap(profile_name) && !ProfileExistsInFilesystem(profile_name);
}
bool InputProfiles::LoadProfile(const std::string& profile_name, std::size_t player_index) {
if (!ProfileExistsInMap(profile_name)) {
return false;
}
if (!ProfileExistsInFilesystem(profile_name)) {
map_profiles.erase(profile_name);
return false;
}
map_profiles[profile_name]->ReadControlPlayerValue(player_index);
return true;
}
bool InputProfiles::SaveProfile(const std::string& profile_name, std::size_t player_index) {
if (!ProfileExistsInMap(profile_name)) {
return false;
}
map_profiles[profile_name]->SaveControlPlayerValue(player_index);
return true;
}
bool InputProfiles::ProfileExistsInMap(const std::string& profile_name) const {
return map_profiles.find(profile_name) != map_profiles.end();
}

View File

@@ -1,32 +0,0 @@
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <string>
#include <string_view>
#include <unordered_map>
class Config;
class InputProfiles {
public:
explicit InputProfiles();
virtual ~InputProfiles();
std::vector<std::string> GetInputProfileNames();
static bool IsProfileNameValid(std::string_view profile_name);
bool CreateProfile(const std::string& profile_name, std::size_t player_index);
bool DeleteProfile(const std::string& profile_name);
bool LoadProfile(const std::string& profile_name, std::size_t player_index);
bool SaveProfile(const std::string& profile_name, std::size_t player_index);
private:
bool ProfileExistsInMap(const std::string& profile_name) const;
std::unordered_map<std::string, std::unique_ptr<Config>> map_profiles;
};

View File

@@ -18,7 +18,6 @@
#include "applets/web_browser.h"
#include "configuration/configure_input.h"
#include "configuration/configure_per_game.h"
#include "configuration/configure_vibration.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs_real.h"
#include "core/frontend/applets/controller.h"
@@ -51,14 +50,12 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
#include <QDesktopServices>
#include <QDesktopWidget>
#include <QDialogButtonBox>
#include <QDir>
#include <QFile>
#include <QFileDialog>
#include <QInputDialog>
#include <QMessageBox>
#include <QProgressBar>
#include <QProgressDialog>
#include <QPushButton>
#include <QShortcut>
#include <QStatusBar>
#include <QSysInfo>
@@ -280,8 +277,6 @@ GMainWindow::GMainWindow()
if (args.length() >= 2) {
BootGame(args[1]);
}
MigrateConfigFiles();
}
GMainWindow::~GMainWindow() {
@@ -293,7 +288,6 @@ GMainWindow::~GMainWindow() {
void GMainWindow::ControllerSelectorReconfigureControllers(
const Core::Frontend::ControllerParameters& parameters) {
QtControllerSelectorDialog dialog(this, parameters, input_subsystem.get());
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint |
Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
dialog.setWindowModality(Qt::WindowModal);
@@ -553,14 +547,13 @@ void GMainWindow::InitializeWidgets() {
dock_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton"));
dock_status_button->setFocusPolicy(Qt::NoFocus);
connect(dock_status_button, &QPushButton::clicked, [&] {
Settings::values.use_docked_mode.SetValue(!Settings::values.use_docked_mode.GetValue());
dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue());
OnDockedModeChanged(!Settings::values.use_docked_mode.GetValue(),
Settings::values.use_docked_mode.GetValue());
Settings::values.use_docked_mode = !Settings::values.use_docked_mode;
dock_status_button->setChecked(Settings::values.use_docked_mode);
OnDockedModeChanged(!Settings::values.use_docked_mode, Settings::values.use_docked_mode);
});
dock_status_button->setText(tr("DOCK"));
dock_status_button->setCheckable(true);
dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue());
dock_status_button->setChecked(Settings::values.use_docked_mode);
statusBar()->insertPermanentWidget(0, dock_status_button);
// Setup ASync button
@@ -799,11 +792,10 @@ void GMainWindow::InitializeHotkeys() {
});
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Change Docked Mode"), this),
&QShortcut::activated, this, [&] {
Settings::values.use_docked_mode.SetValue(
!Settings::values.use_docked_mode.GetValue());
OnDockedModeChanged(!Settings::values.use_docked_mode.GetValue(),
Settings::values.use_docked_mode.GetValue());
dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue());
Settings::values.use_docked_mode = !Settings::values.use_docked_mode;
OnDockedModeChanged(!Settings::values.use_docked_mode,
Settings::values.use_docked_mode);
dock_status_button->setChecked(Settings::values.use_docked_mode);
});
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Mute Audio"), this),
&QShortcut::activated, this,
@@ -1095,11 +1087,9 @@ void GMainWindow::BootGame(const QString& filename) {
const auto loader = Loader::GetLoader(v_file);
if (!(loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success)) {
// Load per game settings
Config per_game_config(fmt::format("{:016X}", title_id), Config::ConfigType::PerGameConfig);
Config per_game_config(fmt::format("{:016X}.ini", title_id), false);
}
ConfigureVibration::SetAllVibrationDevices();
Settings::LogSettings();
if (UISettings::values.select_user_on_boot) {
@@ -1587,8 +1577,7 @@ void GMainWindow::RemoveCustomConfiguration(u64 program_id) {
const QString config_dir =
QString::fromStdString(Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir));
const QString custom_config_file_path =
config_dir + QStringLiteral("custom") + QDir::separator() +
QString::fromStdString(fmt::format("{:016X}.ini", program_id));
config_dir + QString::fromStdString(fmt::format("{:016X}.ini", program_id));
if (!QFile::exists(custom_config_file_path)) {
QMessageBox::warning(this, tr("Error Removing Custom Configuration"),
@@ -2404,29 +2393,6 @@ void GMainWindow::OnCaptureScreenshot() {
OnStartGame();
}
// TODO: Written 2020-10-01: Remove per-game config migration code when it is irrelevant
void GMainWindow::MigrateConfigFiles() {
const std::string& config_dir_str = Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir);
const QDir config_dir = QDir(QString::fromStdString(config_dir_str));
const QStringList config_dir_list = config_dir.entryList(QStringList(QStringLiteral("*.ini")));
Common::FS::CreateFullPath(fmt::format("{}custom" DIR_SEP, config_dir_str));
for (QStringList::const_iterator it = config_dir_list.constBegin();
it != config_dir_list.constEnd(); ++it) {
const auto filename = it->toStdString();
if (filename.find_first_not_of("0123456789abcdefACBDEF", 0) < 16) {
continue;
}
const auto origin = fmt::format("{}{}", config_dir_str, filename);
const auto destination = fmt::format("{}custom" DIR_SEP "{}", config_dir_str, filename);
LOG_INFO(Frontend, "Migrating config file from {} to {}", origin, destination);
if (!Common::FS::Rename(origin, destination)) {
// Delete the old config file if one already exists in the new location.
Common::FS::Delete(origin);
}
}
}
void GMainWindow::UpdateWindowTitle(const std::string& title_name,
const std::string& title_version) {
const auto full_name = std::string(Common::g_build_fullname);
@@ -2484,7 +2450,7 @@ void GMainWindow::UpdateStatusBar() {
}
void GMainWindow::UpdateStatusButtons() {
dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue());
dock_status_button->setChecked(Settings::values.use_docked_mode);
multicore_status_button->setChecked(Settings::values.use_multi_core.GetValue());
Settings::values.use_asynchronous_gpu_emulation.SetValue(
Settings::values.use_asynchronous_gpu_emulation.GetValue() ||

View File

@@ -251,7 +251,6 @@ private:
std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id);
InstallResult InstallNSPXCI(const QString& filename);
InstallResult InstallNCA(const QString& filename);
void MigrateConfigFiles();
void UpdateWindowTitle(const std::string& title_name = {},
const std::string& title_version = {});
void UpdateStatusBar();

View File

@@ -228,24 +228,24 @@ static const std::array<int, 8> keyboard_mods{
void Config::ReadValues() {
// Controls
for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
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.GetValue()[p].buttons[i] =
Settings::values.players[p].buttons[i] =
sdl2_config->Get(group, Settings::NativeButton::mapping[i], default_param);
if (Settings::values.players.GetValue()[p].buttons[i].empty())
Settings::values.players.GetValue()[p].buttons[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.GetValue()[p].analogs[i] =
Settings::values.players[p].analogs[i] =
sdl2_config->Get(group, Settings::NativeAnalog::mapping[i], default_param);
if (Settings::values.players.GetValue()[p].analogs[i].empty())
Settings::values.players.GetValue()[p].analogs[i] = default_param;
if (Settings::values.players[p].analogs[i].empty())
Settings::values.players[p].analogs[i] = default_param;
}
}
@@ -288,12 +288,10 @@ void Config::ReadValues() {
Settings::values.debug_pad_analogs[i] = default_param;
}
Settings::values.vibration_enabled.SetValue(
sdl2_config->GetBoolean("ControlsGeneral", "vibration_enabled", true));
Settings::values.enable_accurate_vibrations.SetValue(
sdl2_config->GetBoolean("ControlsGeneral", "enable_accurate_vibrations", false));
Settings::values.motion_enabled.SetValue(
sdl2_config->GetBoolean("ControlsGeneral", "motion_enabled", true));
Settings::values.vibration_enabled =
sdl2_config->GetBoolean("ControlsGeneral", "vibration_enabled", true);
Settings::values.motion_enabled =
sdl2_config->GetBoolean("ControlsGeneral", "motion_enabled", true);
Settings::values.touchscreen.enabled =
sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true);
Settings::values.touchscreen.device =
@@ -345,8 +343,7 @@ void Config::ReadValues() {
Settings::values.gamecard_path = sdl2_config->Get("Data Storage", "gamecard_path", "");
// System
Settings::values.use_docked_mode.SetValue(
sdl2_config->GetBoolean("System", "use_docked_mode", false));
Settings::values.use_docked_mode = sdl2_config->GetBoolean("System", "use_docked_mode", false);
const auto size = sdl2_config->GetInteger("System", "users_size", 0);
Settings::values.current_user = std::clamp<int>(

View File

@@ -65,14 +65,6 @@ button_screenshot=
lstick=
rstick=
# Whether to enable or disable vibration
# 0: Disabled, 1 (default): Enabled
vibration_enabled=
# Whether to enable or disable accurate vibrations
# 0 (default): Disabled, 1: Enabled
enable_accurate_vibrations=
# for motion input, the following devices are available:
# - "motion_emu" (default) for emulating motion input from mouse input. Required parameters:
# - "update_period": update period in milliseconds (default to 100)

View File

@@ -47,13 +47,13 @@ bool Config::LoadINI(const std::string& default_contents, bool retry) {
void Config::ReadValues() {
// Controls
for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
for (std::size_t p = 0; p < Settings::values.players.size(); ++p) {
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
Settings::values.players.GetValue()[p].buttons[i] = "";
Settings::values.players[p].buttons[i] = "";
}
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
Settings::values.players.GetValue()[p].analogs[i] = "";
Settings::values.players[p].analogs[i] = "";
}
}
@@ -75,9 +75,8 @@ void Config::ReadValues() {
Settings::values.debug_pad_analogs[i] = "";
}
Settings::values.vibration_enabled.SetValue(true);
Settings::values.enable_accurate_vibrations.SetValue(false);
Settings::values.motion_enabled.SetValue(true);
Settings::values.vibration_enabled = true;
Settings::values.motion_enabled = true;
Settings::values.touchscreen.enabled = "";
Settings::values.touchscreen.device = "";
Settings::values.touchscreen.finger = 0;
@@ -85,8 +84,8 @@ void Config::ReadValues() {
Settings::values.touchscreen.diameter_x = 15;
Settings::values.touchscreen.diameter_y = 15;
Settings::values.use_docked_mode.SetValue(
sdl2_config->GetBoolean("Controls", "use_docked_mode", false));
Settings::values.use_docked_mode =
sdl2_config->GetBoolean("Controls", "use_docked_mode", false);
// Data Storage
Settings::values.use_virtual_sd =