Browse Source
Merge pull request #1780 from DarkLordZach/controller-profiles
Merge pull request #1780 from DarkLordZach/controller-profiles
configure_input: Add Controller Setup Profiles and simplify input UInce_cpp
committed by
GitHub
12 changed files with 401 additions and 66 deletions
-
3src/yuzu/CMakeLists.txt
-
12src/yuzu/configuration/config.cpp
-
1src/yuzu/configuration/config.h
-
52src/yuzu/configuration/configure.ui
-
60src/yuzu/configuration/configure_input.cpp
-
8src/yuzu/configuration/configure_input.h
-
48src/yuzu/configuration/configure_input.ui
-
1src/yuzu/configuration/configure_input_player.cpp
-
142src/yuzu/configuration/configure_input_simple.cpp
-
40src/yuzu/configuration/configure_input_simple.h
-
97src/yuzu/configuration/configure_input_simple.ui
-
3src/yuzu/ui_settings.h
@ -0,0 +1,142 @@ |
|||
// Copyright 2016 Citra Emulator Project
|
|||
// Licensed under GPLv2 or any later version
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include <array>
|
|||
#include <cstring>
|
|||
#include <functional>
|
|||
#include <tuple>
|
|||
|
|||
#include <QDialog>
|
|||
|
|||
#include "ui_configure_input_simple.h"
|
|||
#include "yuzu/configuration/configure_input.h"
|
|||
#include "yuzu/configuration/configure_input_player.h"
|
|||
#include "yuzu/configuration/configure_input_simple.h"
|
|||
#include "yuzu/ui_settings.h"
|
|||
|
|||
namespace { |
|||
|
|||
template <typename Dialog, typename... Args> |
|||
void CallConfigureDialog(ConfigureInputSimple* caller, Args&&... args) { |
|||
caller->applyConfiguration(); |
|||
Dialog dialog(caller, std::forward<Args>(args)...); |
|||
|
|||
const auto res = dialog.exec(); |
|||
if (res == QDialog::Accepted) { |
|||
dialog.applyConfiguration(); |
|||
} |
|||
} |
|||
|
|||
// OnProfileSelect functions should (when applicable):
|
|||
// - Set controller types
|
|||
// - Set controller enabled
|
|||
// - Set docked mode
|
|||
// - Set advanced controller config/enabled (i.e. debug, kbd, mouse, touch)
|
|||
//
|
|||
// OnProfileSelect function should NOT however:
|
|||
// - Reset any button mappings
|
|||
// - Open any dialogs
|
|||
// - Block in any way
|
|||
|
|||
constexpr std::size_t HANDHELD_INDEX = 8; |
|||
|
|||
void HandheldOnProfileSelect() { |
|||
Settings::values.players[HANDHELD_INDEX].connected = true; |
|||
Settings::values.players[HANDHELD_INDEX].type = Settings::ControllerType::DualJoycon; |
|||
|
|||
for (std::size_t player = 0; player < HANDHELD_INDEX; ++player) { |
|||
Settings::values.players[player].connected = false; |
|||
} |
|||
|
|||
Settings::values.use_docked_mode = false; |
|||
Settings::values.keyboard_enabled = false; |
|||
Settings::values.mouse_enabled = false; |
|||
Settings::values.debug_pad_enabled = false; |
|||
Settings::values.touchscreen.enabled = true; |
|||
} |
|||
|
|||
void DualJoyconsDockedOnProfileSelect() { |
|||
Settings::values.players[0].connected = true; |
|||
Settings::values.players[0].type = Settings::ControllerType::DualJoycon; |
|||
|
|||
for (std::size_t player = 1; player <= HANDHELD_INDEX; ++player) { |
|||
Settings::values.players[player].connected = false; |
|||
} |
|||
|
|||
Settings::values.use_docked_mode = true; |
|||
Settings::values.keyboard_enabled = false; |
|||
Settings::values.mouse_enabled = false; |
|||
Settings::values.debug_pad_enabled = false; |
|||
Settings::values.touchscreen.enabled = false; |
|||
} |
|||
|
|||
// Name, OnProfileSelect (called when selected in drop down), OnConfigure (called when configure
|
|||
// is clicked)
|
|||
using InputProfile = |
|||
std::tuple<QString, std::function<void()>, std::function<void(ConfigureInputSimple*)>>; |
|||
|
|||
const std::array<InputProfile, 3> INPUT_PROFILES{{ |
|||
{ConfigureInputSimple::tr("Single Player - Handheld - Undocked"), HandheldOnProfileSelect, |
|||
[](ConfigureInputSimple* caller) { |
|||
CallConfigureDialog<ConfigureInputPlayer>(caller, HANDHELD_INDEX, false); |
|||
}}, |
|||
{ConfigureInputSimple::tr("Single Player - Dual Joycons - Docked"), |
|||
DualJoyconsDockedOnProfileSelect, |
|||
[](ConfigureInputSimple* caller) { |
|||
CallConfigureDialog<ConfigureInputPlayer>(caller, 1, false); |
|||
}}, |
|||
{ConfigureInputSimple::tr("Custom"), [] {}, CallConfigureDialog<ConfigureInput>}, |
|||
}}; |
|||
|
|||
} // namespace
|
|||
|
|||
void ApplyInputProfileConfiguration(int profile_index) { |
|||
std::get<1>( |
|||
INPUT_PROFILES.at(std::min(profile_index, static_cast<int>(INPUT_PROFILES.size() - 1))))(); |
|||
} |
|||
|
|||
ConfigureInputSimple::ConfigureInputSimple(QWidget* parent) |
|||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureInputSimple>()) { |
|||
ui->setupUi(this); |
|||
|
|||
for (const auto& profile : INPUT_PROFILES) { |
|||
ui->profile_combobox->addItem(std::get<0>(profile), std::get<0>(profile)); |
|||
} |
|||
|
|||
connect(ui->profile_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, |
|||
&ConfigureInputSimple::OnSelectProfile); |
|||
connect(ui->profile_configure, &QPushButton::pressed, this, &ConfigureInputSimple::OnConfigure); |
|||
|
|||
this->loadConfiguration(); |
|||
} |
|||
|
|||
ConfigureInputSimple::~ConfigureInputSimple() = default; |
|||
|
|||
void ConfigureInputSimple::applyConfiguration() { |
|||
auto index = ui->profile_combobox->currentIndex(); |
|||
// Make the stored index for "Custom" very large so that if new profiles are added it
|
|||
// doesn't change.
|
|||
if (index >= static_cast<int>(INPUT_PROFILES.size() - 1)) |
|||
index = std::numeric_limits<int>::max(); |
|||
|
|||
UISettings::values.profile_index = index; |
|||
} |
|||
|
|||
void ConfigureInputSimple::loadConfiguration() { |
|||
const auto index = UISettings::values.profile_index; |
|||
if (index >= static_cast<int>(INPUT_PROFILES.size()) || index < 0) |
|||
ui->profile_combobox->setCurrentIndex(static_cast<int>(INPUT_PROFILES.size() - 1)); |
|||
else |
|||
ui->profile_combobox->setCurrentIndex(index); |
|||
} |
|||
|
|||
void ConfigureInputSimple::OnSelectProfile(int index) { |
|||
const auto old_docked = Settings::values.use_docked_mode; |
|||
ApplyInputProfileConfiguration(index); |
|||
OnDockedModeChanged(old_docked, Settings::values.use_docked_mode); |
|||
} |
|||
|
|||
void ConfigureInputSimple::OnConfigure() { |
|||
std::get<2>(INPUT_PROFILES.at(ui->profile_combobox->currentIndex()))(this); |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
// Copyright 2016 Citra Emulator Project |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include <memory> |
|||
|
|||
#include <QWidget> |
|||
|
|||
class QPushButton; |
|||
class QString; |
|||
class QTimer; |
|||
|
|||
namespace Ui { |
|||
class ConfigureInputSimple; |
|||
} |
|||
|
|||
// Used by configuration loader to apply a profile if the input is invalid. |
|||
void ApplyInputProfileConfiguration(int profile_index); |
|||
|
|||
class ConfigureInputSimple : public QWidget { |
|||
Q_OBJECT |
|||
|
|||
public: |
|||
explicit ConfigureInputSimple(QWidget* parent = nullptr); |
|||
~ConfigureInputSimple() override; |
|||
|
|||
/// Save all button configurations to settings file |
|||
void applyConfiguration(); |
|||
|
|||
private: |
|||
/// Load configuration settings. |
|||
void loadConfiguration(); |
|||
|
|||
void OnSelectProfile(int index); |
|||
void OnConfigure(); |
|||
|
|||
std::unique_ptr<Ui::ConfigureInputSimple> ui; |
|||
}; |
|||
@ -0,0 +1,97 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<ui version="4.0"> |
|||
<class>ConfigureInputSimple</class> |
|||
<widget class="QWidget" name="ConfigureInputSimple"> |
|||
<property name="geometry"> |
|||
<rect> |
|||
<x>0</x> |
|||
<y>0</y> |
|||
<width>473</width> |
|||
<height>685</height> |
|||
</rect> |
|||
</property> |
|||
<property name="windowTitle"> |
|||
<string>ConfigureInputSimple</string> |
|||
</property> |
|||
<layout class="QVBoxLayout" name="verticalLayout_5"> |
|||
<item> |
|||
<layout class="QVBoxLayout" name="verticalLayout"> |
|||
<item> |
|||
<widget class="QGroupBox" name="gridGroupBox"> |
|||
<property name="title"> |
|||
<string>Profile</string> |
|||
</property> |
|||
<layout class="QGridLayout" name="gridLayout"> |
|||
<item row="1" column="2"> |
|||
<widget class="QPushButton" name="profile_configure"> |
|||
<property name="text"> |
|||
<string>Configure</string> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="1" column="0"> |
|||
<spacer name="horizontalSpacer"> |
|||
<property name="orientation"> |
|||
<enum>Qt::Horizontal</enum> |
|||
</property> |
|||
<property name="sizeHint" stdset="0"> |
|||
<size> |
|||
<width>40</width> |
|||
<height>20</height> |
|||
</size> |
|||
</property> |
|||
</spacer> |
|||
</item> |
|||
<item row="1" column="3"> |
|||
<spacer name="horizontalSpacer_2"> |
|||
<property name="orientation"> |
|||
<enum>Qt::Horizontal</enum> |
|||
</property> |
|||
<property name="sizeHint" stdset="0"> |
|||
<size> |
|||
<width>40</width> |
|||
<height>20</height> |
|||
</size> |
|||
</property> |
|||
</spacer> |
|||
</item> |
|||
<item row="1" column="1"> |
|||
<widget class="QComboBox" name="profile_combobox"> |
|||
<property name="minimumSize"> |
|||
<size> |
|||
<width>250</width> |
|||
<height>0</height> |
|||
</size> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="0" column="1" colspan="2"> |
|||
<widget class="QLabel" name="label"> |
|||
<property name="text"> |
|||
<string>Choose a controller configuration:</string> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</item> |
|||
<item> |
|||
<spacer name="verticalSpacer"> |
|||
<property name="orientation"> |
|||
<enum>Qt::Vertical</enum> |
|||
</property> |
|||
<property name="sizeHint" stdset="0"> |
|||
<size> |
|||
<width>20</width> |
|||
<height>40</height> |
|||
</size> |
|||
</property> |
|||
</spacer> |
|||
</item> |
|||
</layout> |
|||
</widget> |
|||
<resources/> |
|||
<connections/> |
|||
</ui> |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue