early-access version 1315
This commit is contained in:
parent
cdca8a3cd5
commit
2a59cc55e2
15 changed files with 2689 additions and 897 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 1314.
|
This is the source code for early-access 1315.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
21
dist/icons/controller/controller.qrc
vendored
21
dist/icons/controller/controller.qrc
vendored
|
@ -1,26 +1,5 @@
|
||||||
<RCC>
|
<RCC>
|
||||||
<qresource prefix="controller">
|
<qresource prefix="controller">
|
||||||
<file alias="dual_joycon">dual_joycon.png</file>
|
|
||||||
<file alias="dual_joycon_dark">dual_joycon_dark.png</file>
|
|
||||||
<file alias="dual_joycon_midnight">dual_joycon_midnight.png</file>
|
|
||||||
<file alias="handheld">handheld.png</file>
|
|
||||||
<file alias="handheld_dark">handheld_dark.png</file>
|
|
||||||
<file alias="handheld_midnight">handheld_midnight.png</file>
|
|
||||||
<file alias="pro_controller">pro_controller.png</file>
|
|
||||||
<file alias="pro_controller_dark">pro_controller_dark.png</file>
|
|
||||||
<file alias="pro_controller_midnight">pro_controller_midnight.png</file>
|
|
||||||
<file alias="single_joycon_left">single_joycon_left.png</file>
|
|
||||||
<file alias="single_joycon_left_dark">single_joycon_left_dark.png</file>
|
|
||||||
<file alias="single_joycon_left_midnight">single_joycon_left_midnight.png</file>
|
|
||||||
<file alias="single_joycon_right">single_joycon_right.png</file>
|
|
||||||
<file alias="single_joycon_right_dark">single_joycon_right_dark.png</file>
|
|
||||||
<file alias="single_joycon_right_midnight">single_joycon_right_midnight.png</file>
|
|
||||||
<file alias="single_joycon_left_vertical">single_joycon_left_vertical.png</file>
|
|
||||||
<file alias="single_joycon_left_vertical_dark">single_joycon_left_vertical_dark.png</file>
|
|
||||||
<file alias="single_joycon_left_vertical_midnight">single_joycon_left_vertical_midnight.png</file>
|
|
||||||
<file alias="single_joycon_right_vertical">single_joycon_right_vertical.png</file>
|
|
||||||
<file alias="single_joycon_right_vertical_dark">single_joycon_right_vertical_dark.png</file>
|
|
||||||
<file alias="single_joycon_right_vertical_midnight">single_joycon_right_vertical_midnight.png</file>
|
|
||||||
<file alias="applet_dual_joycon">applet_dual_joycon.png</file>
|
<file alias="applet_dual_joycon">applet_dual_joycon.png</file>
|
||||||
<file alias="applet_dual_joycon_dark">applet_dual_joycon_dark.png</file>
|
<file alias="applet_dual_joycon_dark">applet_dual_joycon_dark.png</file>
|
||||||
<file alias="applet_dual_joycon_midnight">applet_dual_joycon_midnight.png</file>
|
<file alias="applet_dual_joycon_midnight">applet_dual_joycon_midnight.png</file>
|
||||||
|
|
|
@ -16,17 +16,30 @@ class IntrusiveRedBlackTreeImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IntrusiveRedBlackTreeNode {
|
struct IntrusiveRedBlackTreeNode {
|
||||||
|
public:
|
||||||
|
using EntryType = RBEntry<IntrusiveRedBlackTreeNode>;
|
||||||
|
|
||||||
|
constexpr IntrusiveRedBlackTreeNode() = default;
|
||||||
|
|
||||||
|
void SetEntry(const EntryType& new_entry) {
|
||||||
|
entry = new_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] EntryType& GetEntry() {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const EntryType& GetEntry() const {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RB_ENTRY(IntrusiveRedBlackTreeNode) entry{};
|
EntryType entry{};
|
||||||
|
|
||||||
friend class impl::IntrusiveRedBlackTreeImpl;
|
friend class impl::IntrusiveRedBlackTreeImpl;
|
||||||
|
|
||||||
template <class, class, class>
|
template <class, class, class>
|
||||||
friend class IntrusiveRedBlackTree;
|
friend class IntrusiveRedBlackTree;
|
||||||
|
|
||||||
public:
|
|
||||||
constexpr IntrusiveRedBlackTreeNode() = default;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T, class Traits, class Comparator>
|
template <class T, class Traits, class Comparator>
|
||||||
|
@ -35,17 +48,12 @@ class IntrusiveRedBlackTree;
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
class IntrusiveRedBlackTreeImpl {
|
class IntrusiveRedBlackTreeImpl {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class, class, class>
|
template <class, class, class>
|
||||||
friend class ::Common::IntrusiveRedBlackTree;
|
friend class ::Common::IntrusiveRedBlackTree;
|
||||||
|
|
||||||
private:
|
using RootType = RBHead<IntrusiveRedBlackTreeNode>;
|
||||||
RB_HEAD(IntrusiveRedBlackTreeRoot, IntrusiveRedBlackTreeNode);
|
RootType root;
|
||||||
using RootType = IntrusiveRedBlackTreeRoot;
|
|
||||||
|
|
||||||
private:
|
|
||||||
IntrusiveRedBlackTreeRoot root;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <bool Const>
|
template <bool Const>
|
||||||
|
@ -121,57 +129,45 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
|
||||||
// Generate static implementations for non-comparison operations for IntrusiveRedBlackTreeRoot.
|
|
||||||
RB_GENERATE_WITHOUT_COMPARE_STATIC(IntrusiveRedBlackTreeRoot, IntrusiveRedBlackTreeNode, entry);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Define accessors using RB_* functions.
|
// Define accessors using RB_* functions.
|
||||||
constexpr void InitializeImpl() {
|
|
||||||
RB_INIT(&this->root);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmptyImpl() const {
|
bool EmptyImpl() const {
|
||||||
return RB_EMPTY(&this->root);
|
return root.IsEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
IntrusiveRedBlackTreeNode* GetMinImpl() const {
|
IntrusiveRedBlackTreeNode* GetMinImpl() const {
|
||||||
return RB_MIN(IntrusiveRedBlackTreeRoot,
|
return RB_MIN(const_cast<RootType*>(&root));
|
||||||
const_cast<IntrusiveRedBlackTreeRoot*>(&this->root));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IntrusiveRedBlackTreeNode* GetMaxImpl() const {
|
IntrusiveRedBlackTreeNode* GetMaxImpl() const {
|
||||||
return RB_MAX(IntrusiveRedBlackTreeRoot,
|
return RB_MAX(const_cast<RootType*>(&root));
|
||||||
const_cast<IntrusiveRedBlackTreeRoot*>(&this->root));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IntrusiveRedBlackTreeNode* RemoveImpl(IntrusiveRedBlackTreeNode* node) {
|
IntrusiveRedBlackTreeNode* RemoveImpl(IntrusiveRedBlackTreeNode* node) {
|
||||||
return RB_REMOVE(IntrusiveRedBlackTreeRoot, &this->root, node);
|
return RB_REMOVE(&root, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static IntrusiveRedBlackTreeNode* GetNext(IntrusiveRedBlackTreeNode* node) {
|
static IntrusiveRedBlackTreeNode* GetNext(IntrusiveRedBlackTreeNode* node) {
|
||||||
return RB_NEXT(IntrusiveRedBlackTreeRoot, nullptr, node);
|
return RB_NEXT(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
static IntrusiveRedBlackTreeNode* GetPrev(IntrusiveRedBlackTreeNode* node) {
|
static IntrusiveRedBlackTreeNode* GetPrev(IntrusiveRedBlackTreeNode* node) {
|
||||||
return RB_PREV(IntrusiveRedBlackTreeRoot, nullptr, node);
|
return RB_PREV(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
static IntrusiveRedBlackTreeNode const* GetNext(const IntrusiveRedBlackTreeNode* node) {
|
static const IntrusiveRedBlackTreeNode* GetNext(const IntrusiveRedBlackTreeNode* node) {
|
||||||
return static_cast<const IntrusiveRedBlackTreeNode*>(
|
return static_cast<const IntrusiveRedBlackTreeNode*>(
|
||||||
GetNext(const_cast<IntrusiveRedBlackTreeNode*>(node)));
|
GetNext(const_cast<IntrusiveRedBlackTreeNode*>(node)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static IntrusiveRedBlackTreeNode const* GetPrev(const IntrusiveRedBlackTreeNode* node) {
|
static const IntrusiveRedBlackTreeNode* GetPrev(const IntrusiveRedBlackTreeNode* node) {
|
||||||
return static_cast<const IntrusiveRedBlackTreeNode*>(
|
return static_cast<const IntrusiveRedBlackTreeNode*>(
|
||||||
GetPrev(const_cast<IntrusiveRedBlackTreeNode*>(node)));
|
GetPrev(const_cast<IntrusiveRedBlackTreeNode*>(node)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr IntrusiveRedBlackTreeImpl() : root() {
|
constexpr IntrusiveRedBlackTreeImpl() {}
|
||||||
this->InitializeImpl();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterator accessors.
|
// Iterator accessors.
|
||||||
iterator begin() {
|
iterator begin() {
|
||||||
|
@ -269,8 +265,6 @@ private:
|
||||||
ImplType impl{};
|
ImplType impl{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct IntrusiveRedBlackTreeRootWithCompare : ImplType::IntrusiveRedBlackTreeRoot {};
|
|
||||||
|
|
||||||
template <bool Const>
|
template <bool Const>
|
||||||
class Iterator;
|
class Iterator;
|
||||||
|
|
||||||
|
@ -362,11 +356,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
|
||||||
// Generate static implementations for comparison operations for IntrusiveRedBlackTreeRoot.
|
|
||||||
RB_GENERATE_WITH_COMPARE_STATIC(IntrusiveRedBlackTreeRootWithCompare, IntrusiveRedBlackTreeNode,
|
|
||||||
entry, CompareImpl, LightCompareImpl);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static int CompareImpl(const IntrusiveRedBlackTreeNode* lhs,
|
static int CompareImpl(const IntrusiveRedBlackTreeNode* lhs,
|
||||||
const IntrusiveRedBlackTreeNode* rhs) {
|
const IntrusiveRedBlackTreeNode* rhs) {
|
||||||
|
@ -379,41 +368,27 @@ private:
|
||||||
|
|
||||||
// Define accessors using RB_* functions.
|
// Define accessors using RB_* functions.
|
||||||
IntrusiveRedBlackTreeNode* InsertImpl(IntrusiveRedBlackTreeNode* node) {
|
IntrusiveRedBlackTreeNode* InsertImpl(IntrusiveRedBlackTreeNode* node) {
|
||||||
return RB_INSERT(IntrusiveRedBlackTreeRootWithCompare,
|
return RB_INSERT(&impl.root, node, CompareImpl);
|
||||||
static_cast<IntrusiveRedBlackTreeRootWithCompare*>(&this->impl.root),
|
|
||||||
node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IntrusiveRedBlackTreeNode* FindImpl(const IntrusiveRedBlackTreeNode* node) const {
|
IntrusiveRedBlackTreeNode* FindImpl(const IntrusiveRedBlackTreeNode* node) const {
|
||||||
return RB_FIND(
|
return RB_FIND(const_cast<ImplType::RootType*>(&impl.root),
|
||||||
IntrusiveRedBlackTreeRootWithCompare,
|
const_cast<IntrusiveRedBlackTreeNode*>(node), CompareImpl);
|
||||||
const_cast<IntrusiveRedBlackTreeRootWithCompare*>(
|
|
||||||
static_cast<const IntrusiveRedBlackTreeRootWithCompare*>(&this->impl.root)),
|
|
||||||
const_cast<IntrusiveRedBlackTreeNode*>(node));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IntrusiveRedBlackTreeNode* NFindImpl(const IntrusiveRedBlackTreeNode* node) const {
|
IntrusiveRedBlackTreeNode* NFindImpl(const IntrusiveRedBlackTreeNode* node) const {
|
||||||
return RB_NFIND(
|
return RB_NFIND(const_cast<ImplType::RootType*>(&impl.root),
|
||||||
IntrusiveRedBlackTreeRootWithCompare,
|
const_cast<IntrusiveRedBlackTreeNode*>(node), CompareImpl);
|
||||||
const_cast<IntrusiveRedBlackTreeRootWithCompare*>(
|
|
||||||
static_cast<const IntrusiveRedBlackTreeRootWithCompare*>(&this->impl.root)),
|
|
||||||
const_cast<IntrusiveRedBlackTreeNode*>(node));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IntrusiveRedBlackTreeNode* FindLightImpl(const_light_pointer lelm) const {
|
IntrusiveRedBlackTreeNode* FindLightImpl(const_light_pointer lelm) const {
|
||||||
return RB_FIND_LIGHT(
|
return RB_FIND_LIGHT(const_cast<ImplType::RootType*>(&impl.root),
|
||||||
IntrusiveRedBlackTreeRootWithCompare,
|
static_cast<const void*>(lelm), LightCompareImpl);
|
||||||
const_cast<IntrusiveRedBlackTreeRootWithCompare*>(
|
|
||||||
static_cast<const IntrusiveRedBlackTreeRootWithCompare*>(&this->impl.root)),
|
|
||||||
static_cast<const void*>(lelm));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IntrusiveRedBlackTreeNode* NFindLightImpl(const_light_pointer lelm) const {
|
IntrusiveRedBlackTreeNode* NFindLightImpl(const_light_pointer lelm) const {
|
||||||
return RB_NFIND_LIGHT(
|
return RB_NFIND_LIGHT(const_cast<ImplType::RootType*>(&impl.root),
|
||||||
IntrusiveRedBlackTreeRootWithCompare,
|
static_cast<const void*>(lelm), LightCompareImpl);
|
||||||
const_cast<IntrusiveRedBlackTreeRootWithCompare*>(
|
|
||||||
static_cast<const IntrusiveRedBlackTreeRootWithCompare*>(&this->impl.root)),
|
|
||||||
static_cast<const void*>(lelm));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
1322
src/common/tree.h
1322
src/common/tree.h
File diff suppressed because it is too large
Load diff
|
@ -21,6 +21,11 @@ enum class AnalogDirection : u8 {
|
||||||
UP,
|
UP,
|
||||||
DOWN,
|
DOWN,
|
||||||
};
|
};
|
||||||
|
struct AnalogProperties {
|
||||||
|
float deadzone;
|
||||||
|
float range;
|
||||||
|
float threshold;
|
||||||
|
};
|
||||||
|
|
||||||
/// An abstract class template for an input device (a button, an analog input, etc.).
|
/// An abstract class template for an input device (a button, an analog input, etc.).
|
||||||
template <typename StatusType>
|
template <typename StatusType>
|
||||||
|
@ -30,6 +35,12 @@ public:
|
||||||
virtual StatusType GetStatus() const {
|
virtual StatusType GetStatus() const {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
virtual StatusType GetRawStatus() const {
|
||||||
|
return GetStatus();
|
||||||
|
}
|
||||||
|
virtual AnalogProperties GetAnalogProperties() const {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
virtual bool GetAnalogDirectionStatus([[maybe_unused]] AnalogDirection direction) const {
|
virtual bool GetAnalogDirectionStatus([[maybe_unused]] AnalogDirection direction) const {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,6 +185,16 @@ public:
|
||||||
return {0.0f, 0.0f};
|
return {0.0f, 0.0f};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::tuple<float, float> GetRawStatus() const override {
|
||||||
|
const float x = GetAxis(axis_x);
|
||||||
|
const float y = GetAxis(axis_y);
|
||||||
|
return {x, y};
|
||||||
|
}
|
||||||
|
|
||||||
|
Input::AnalogProperties GetAnalogProperties() const override {
|
||||||
|
return {deadzone, range, 0.5f};
|
||||||
|
}
|
||||||
|
|
||||||
bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
|
bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
|
||||||
const auto [x, y] = GetStatus();
|
const auto [x, y] = GetStatus();
|
||||||
const float directional_deadzone = 0.5f;
|
const float directional_deadzone = 0.5f;
|
||||||
|
|
|
@ -373,6 +373,16 @@ public:
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::tuple<float, float> GetRawStatus() const override {
|
||||||
|
const float x = joystick->GetAxis(axis_x, range);
|
||||||
|
const float y = joystick->GetAxis(axis_y, range);
|
||||||
|
return {x, -y};
|
||||||
|
}
|
||||||
|
|
||||||
|
Input::AnalogProperties GetAnalogProperties() const override {
|
||||||
|
return {deadzone, range, 0.5f};
|
||||||
|
}
|
||||||
|
|
||||||
bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
|
bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override {
|
||||||
const auto [x, y] = GetStatus();
|
const auto [x, y] = GetStatus();
|
||||||
const float directional_deadzone = 0.5f;
|
const float directional_deadzone = 0.5f;
|
||||||
|
|
|
@ -71,6 +71,8 @@ add_executable(yuzu
|
||||||
configuration/configure_input_player.cpp
|
configuration/configure_input_player.cpp
|
||||||
configuration/configure_input_player.h
|
configuration/configure_input_player.h
|
||||||
configuration/configure_input_player.ui
|
configuration/configure_input_player.ui
|
||||||
|
configuration/configure_input_player_widget.cpp
|
||||||
|
configuration/configure_input_player_widget.h
|
||||||
configuration/configure_input_profile_dialog.cpp
|
configuration/configure_input_profile_dialog.cpp
|
||||||
configuration/configure_input_profile_dialog.h
|
configuration/configure_input_profile_dialog.h
|
||||||
configuration/configure_input_profile_dialog.ui
|
configuration/configure_input_profile_dialog.ui
|
||||||
|
|
|
@ -290,8 +290,8 @@ GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_,
|
||||||
QString::fromUtf8(Common::g_scm_branch),
|
QString::fromUtf8(Common::g_scm_branch),
|
||||||
QString::fromUtf8(Common::g_scm_desc)));
|
QString::fromUtf8(Common::g_scm_desc)));
|
||||||
setAttribute(Qt::WA_AcceptTouchEvents);
|
setAttribute(Qt::WA_AcceptTouchEvents);
|
||||||
auto layout = new QHBoxLayout(this);
|
auto* layout = new QHBoxLayout(this);
|
||||||
layout->setMargin(0);
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
input_subsystem->Initialize();
|
input_subsystem->Initialize();
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "ui_configure_input_player.h"
|
#include "ui_configure_input_player.h"
|
||||||
#include "yuzu/configuration/config.h"
|
#include "yuzu/configuration/config.h"
|
||||||
#include "yuzu/configuration/configure_input_player.h"
|
#include "yuzu/configuration/configure_input_player.h"
|
||||||
|
#include "yuzu/configuration/configure_input_player_widget.h"
|
||||||
#include "yuzu/configuration/configure_vibration.h"
|
#include "yuzu/configuration/configure_vibration.h"
|
||||||
#include "yuzu/configuration/input_profiles.h"
|
#include "yuzu/configuration/input_profiles.h"
|
||||||
#include "yuzu/util/limitable_input_dialog.h"
|
#include "yuzu/util/limitable_input_dialog.h"
|
||||||
|
@ -254,11 +255,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||||
analog_map_range_groupbox = {ui->buttonLStickRangeGroup, ui->buttonRStickRangeGroup};
|
analog_map_range_groupbox = {ui->buttonLStickRangeGroup, ui->buttonRStickRangeGroup};
|
||||||
analog_map_range_spinbox = {ui->spinboxLStickRange, ui->spinboxRStickRange};
|
analog_map_range_spinbox = {ui->spinboxLStickRange, ui->spinboxRStickRange};
|
||||||
|
|
||||||
const auto ConfigureButtonClick = [&](QPushButton* button, Common::ParamPackage* param,
|
const auto ConfigureButtonClick = [&](QPushButton* button, std::size_t button_id,
|
||||||
int default_val, InputCommon::Polling::DeviceType type) {
|
Common::ParamPackage* param, int default_val,
|
||||||
|
InputCommon::Polling::DeviceType type) {
|
||||||
connect(button, &QPushButton::clicked, [=, this] {
|
connect(button, &QPushButton::clicked, [=, this] {
|
||||||
HandleClick(
|
HandleClick(
|
||||||
button,
|
button, button_id,
|
||||||
[=, this](Common::ParamPackage params) {
|
[=, this](Common::ParamPackage params) {
|
||||||
// Workaround for ZL & ZR for analog triggers like on XBOX
|
// Workaround for ZL & ZR for analog triggers like on XBOX
|
||||||
// controllers. Analog triggers (from controllers like the XBOX
|
// controllers. Analog triggers (from controllers like the XBOX
|
||||||
|
@ -286,12 +288,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigureButtonClick(button_map[button_id], &buttons_param[button_id],
|
ConfigureButtonClick(button_map[button_id], button_id, &buttons_param[button_id],
|
||||||
Config::default_buttons[button_id],
|
Config::default_buttons[button_id],
|
||||||
InputCommon::Polling::DeviceType::Button);
|
InputCommon::Polling::DeviceType::Button);
|
||||||
|
|
||||||
button->setContextMenuPolicy(Qt::CustomContextMenu);
|
button->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
|
||||||
connect(button, &QPushButton::customContextMenuRequested,
|
connect(button, &QPushButton::customContextMenuRequested,
|
||||||
[=, this](const QPoint& menu_location) {
|
[=, this](const QPoint& menu_location) {
|
||||||
QMenu context_menu;
|
QMenu context_menu;
|
||||||
|
@ -300,6 +301,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||||
button_map[button_id]->setText(tr("[not set]"));
|
button_map[button_id]->setText(tr("[not set]"));
|
||||||
});
|
});
|
||||||
context_menu.exec(button_map[button_id]->mapToGlobal(menu_location));
|
context_menu.exec(button_map[button_id]->mapToGlobal(menu_location));
|
||||||
|
ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,7 +311,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigureButtonClick(motion_map[motion_id], &motions_param[motion_id],
|
ConfigureButtonClick(motion_map[motion_id], motion_id, &motions_param[motion_id],
|
||||||
Config::default_motions[motion_id],
|
Config::default_motions[motion_id],
|
||||||
InputCommon::Polling::DeviceType::Motion);
|
InputCommon::Polling::DeviceType::Motion);
|
||||||
|
|
||||||
|
@ -348,7 +350,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HandleClick(
|
HandleClick(
|
||||||
analog_map_buttons[analog_id][sub_button_id],
|
analog_map_buttons[analog_id][sub_button_id], analog_id,
|
||||||
[=, this](const Common::ParamPackage& params) {
|
[=, this](const Common::ParamPackage& params) {
|
||||||
SetAnalogParam(params, analogs_param[analog_id],
|
SetAnalogParam(params, analogs_param[analog_id],
|
||||||
analog_sub_buttons[sub_button_id]);
|
analog_sub_buttons[sub_button_id]);
|
||||||
|
@ -358,7 +360,8 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||||
|
|
||||||
analog_button->setContextMenuPolicy(Qt::CustomContextMenu);
|
analog_button->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
|
||||||
connect(analog_button, &QPushButton::customContextMenuRequested,
|
connect(
|
||||||
|
analog_button, &QPushButton::customContextMenuRequested,
|
||||||
[=, this](const QPoint& menu_location) {
|
[=, this](const QPoint& menu_location) {
|
||||||
QMenu context_menu;
|
QMenu context_menu;
|
||||||
context_menu.addAction(tr("Clear"), [&] {
|
context_menu.addAction(tr("Clear"), [&] {
|
||||||
|
@ -384,15 +387,16 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||||
analogs_param[analog_id], analog_sub_buttons[sub_button_id]));
|
analogs_param[analog_id], analog_sub_buttons[sub_button_id]));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
context_menu.exec(analog_map_buttons[analog_id][sub_button_id]->mapToGlobal(
|
context_menu.exec(
|
||||||
menu_location));
|
analog_map_buttons[analog_id][sub_button_id]->mapToGlobal(menu_location));
|
||||||
|
ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle clicks for the modifier buttons as well.
|
// Handle clicks for the modifier buttons as well.
|
||||||
connect(analog_map_modifier_button[analog_id], &QPushButton::clicked, [=, this] {
|
connect(analog_map_modifier_button[analog_id], &QPushButton::clicked, [=, this] {
|
||||||
HandleClick(
|
HandleClick(
|
||||||
analog_map_modifier_button[analog_id],
|
analog_map_modifier_button[analog_id], analog_id,
|
||||||
[=, this](const Common::ParamPackage& params) {
|
[=, this](const Common::ParamPackage& params) {
|
||||||
analogs_param[analog_id].Set("modifier", params.Serialize());
|
analogs_param[analog_id].Set("modifier", params.Serialize());
|
||||||
},
|
},
|
||||||
|
@ -416,12 +420,14 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||||
[=, this] {
|
[=, this] {
|
||||||
const auto spinbox_value = analog_map_range_spinbox[analog_id]->value();
|
const auto spinbox_value = analog_map_range_spinbox[analog_id]->value();
|
||||||
analogs_param[analog_id].Set("range", spinbox_value / 100.0f);
|
analogs_param[analog_id].Set("range", spinbox_value / 100.0f);
|
||||||
|
ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(analog_map_deadzone_slider[analog_id], &QSlider::valueChanged, [=, this] {
|
connect(analog_map_deadzone_slider[analog_id], &QSlider::valueChanged, [=, this] {
|
||||||
const auto slider_value = analog_map_deadzone_slider[analog_id]->value();
|
const auto slider_value = analog_map_deadzone_slider[analog_id]->value();
|
||||||
analog_map_deadzone_label[analog_id]->setText(tr("Deadzone: %1%").arg(slider_value));
|
analog_map_deadzone_label[analog_id]->setText(tr("Deadzone: %1%").arg(slider_value));
|
||||||
analogs_param[analog_id].Set("deadzone", slider_value / 100.0f);
|
analogs_param[analog_id].Set("deadzone", slider_value / 100.0f);
|
||||||
|
ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(analog_map_modifier_slider[analog_id], &QSlider::valueChanged, [=, this] {
|
connect(analog_map_modifier_slider[analog_id], &QSlider::valueChanged, [=, this] {
|
||||||
|
@ -433,8 +439,10 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||||
}
|
}
|
||||||
|
|
||||||
// Player Connected checkbox
|
// Player Connected checkbox
|
||||||
connect(ui->groupConnectedController, &QGroupBox::toggled,
|
connect(ui->groupConnectedController, &QGroupBox::toggled, [this](bool checked) {
|
||||||
[this](bool checked) { emit Connected(checked); });
|
emit Connected(checked);
|
||||||
|
ui->controllerFrame->SetConnectedStatus(checked);
|
||||||
|
});
|
||||||
|
|
||||||
if (player_index == 0) {
|
if (player_index == 0) {
|
||||||
connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged),
|
connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged),
|
||||||
|
@ -553,6 +561,8 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||||
|
|
||||||
// TODO(wwylele): enable this when we actually emulate it
|
// TODO(wwylele): enable this when we actually emulate it
|
||||||
ui->buttonHome->setEnabled(false);
|
ui->buttonHome->setEnabled(false);
|
||||||
|
ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
|
||||||
|
ui->controllerFrame->SetConnectedStatus(ui->groupConnectedController->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigureInputPlayer::~ConfigureInputPlayer() = default;
|
ConfigureInputPlayer::~ConfigureInputPlayer() = default;
|
||||||
|
@ -849,6 +859,7 @@ void ConfigureInputPlayer::UpdateUI() {
|
||||||
modifier_label->setVisible(!is_controller);
|
modifier_label->setVisible(!is_controller);
|
||||||
modifier_slider->setVisible(!is_controller);
|
modifier_slider->setVisible(!is_controller);
|
||||||
range_groupbox->setVisible(is_controller);
|
range_groupbox->setVisible(is_controller);
|
||||||
|
ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -965,8 +976,8 @@ void ConfigureInputPlayer::UpdateControllerIcon() {
|
||||||
return QString{};
|
return QString{};
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
ui->controllerFrame->SetControllerType(
|
||||||
ui->controllerFrame->setStyleSheet(stylesheet.arg(theme));
|
GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
|
void ConfigureInputPlayer::UpdateControllerAvailableButtons() {
|
||||||
|
@ -1103,7 +1114,8 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureInputPlayer::HandleClick(
|
void ConfigureInputPlayer::HandleClick(
|
||||||
QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter,
|
QPushButton* button, std::size_t button_id,
|
||||||
|
std::function<void(const Common::ParamPackage&)> new_input_setter,
|
||||||
InputCommon::Polling::DeviceType type) {
|
InputCommon::Polling::DeviceType type) {
|
||||||
if (button == ui->buttonMotionLeft || button == ui->buttonMotionRight) {
|
if (button == ui->buttonMotionLeft || button == ui->buttonMotionRight) {
|
||||||
button->setText(tr("Shake!"));
|
button->setText(tr("Shake!"));
|
||||||
|
@ -1147,6 +1159,12 @@ void ConfigureInputPlayer::HandleClick(
|
||||||
input_subsystem->GetMouseTouch()->BeginConfiguration();
|
input_subsystem->GetMouseTouch()->BeginConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type == InputCommon::Polling::DeviceType::Button) {
|
||||||
|
ui->controllerFrame->BeginMappingButton(button_id);
|
||||||
|
} else if (type == InputCommon::Polling::DeviceType::AnalogPreferred) {
|
||||||
|
ui->controllerFrame->BeginMappingAnalog(button_id);
|
||||||
|
}
|
||||||
|
|
||||||
timeout_timer->start(2500); // Cancel after 2.5 seconds
|
timeout_timer->start(2500); // Cancel after 2.5 seconds
|
||||||
poll_timer->start(50); // Check for new inputs every 50ms
|
poll_timer->start(50); // Check for new inputs every 50ms
|
||||||
}
|
}
|
||||||
|
@ -1177,6 +1195,7 @@ void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params,
|
||||||
|
|
||||||
UpdateUI();
|
UpdateUI();
|
||||||
UpdateInputDeviceCombobox();
|
UpdateInputDeviceCombobox();
|
||||||
|
ui->controllerFrame->EndMapping();
|
||||||
|
|
||||||
input_setter = std::nullopt;
|
input_setter = std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ private:
|
||||||
void LoadConfiguration();
|
void LoadConfiguration();
|
||||||
|
|
||||||
/// Called when the button was pressed.
|
/// Called when the button was pressed.
|
||||||
void HandleClick(QPushButton* button,
|
void HandleClick(QPushButton* button, std::size_t button_id,
|
||||||
std::function<void(const Common::ParamPackage&)> new_input_setter,
|
std::function<void(const Common::ParamPackage&)> new_input_setter,
|
||||||
InputCommon::Polling::DeviceType type);
|
InputCommon::Polling::DeviceType type);
|
||||||
|
|
||||||
|
|
|
@ -1965,7 +1965,7 @@
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QFrame" name="controllerFrame">
|
<widget class="PlayerControlPreview" name="controllerFrame">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
|
@ -3087,6 +3087,14 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>PlayerControlPreview</class>
|
||||||
|
<extends>QFrame</extends>
|
||||||
|
<header>yuzu/configuration/configure_input_player_widget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../../dist/icons/controller/controller.qrc"/>
|
<include location="../../../dist/icons/controller/controller.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
1769
src/yuzu/configuration/configure_input_player_widget.cpp
Executable file
1769
src/yuzu/configuration/configure_input_player_widget.cpp
Executable file
File diff suppressed because it is too large
Load diff
157
src/yuzu/configuration/configure_input_player_widget.h
Executable file
157
src/yuzu/configuration/configure_input_player_widget.h
Executable file
|
@ -0,0 +1,157 @@
|
||||||
|
// Copyright 2020 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <QFrame>
|
||||||
|
#include <QPointer>
|
||||||
|
#include "core/frontend/input.h"
|
||||||
|
#include "core/settings.h"
|
||||||
|
|
||||||
|
class QLabel;
|
||||||
|
|
||||||
|
using AnalogParam = std::array<Common::ParamPackage, Settings::NativeAnalog::NumAnalogs>;
|
||||||
|
using ButtonParam = std::array<Common::ParamPackage, Settings::NativeButton::NumButtons>;
|
||||||
|
|
||||||
|
// Widget for representing touchscreen coordinates
|
||||||
|
class PlayerControlPreview : public QFrame {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit PlayerControlPreview(QWidget* parent);
|
||||||
|
~PlayerControlPreview() override;
|
||||||
|
|
||||||
|
void SetPlayerInput(std::size_t index, const ButtonParam& buttons_param,
|
||||||
|
const AnalogParam& analogs_param);
|
||||||
|
void SetConnectedStatus(bool checked);
|
||||||
|
void SetControllerType(Settings::ControllerType type);
|
||||||
|
void BeginMappingButton(std::size_t button_id);
|
||||||
|
void BeginMappingAnalog(std::size_t button_id);
|
||||||
|
void EndMapping();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent* event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class Direction : std::size_t {
|
||||||
|
None,
|
||||||
|
Up,
|
||||||
|
Right,
|
||||||
|
Down,
|
||||||
|
Left,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AxisValue {
|
||||||
|
QPointF value{};
|
||||||
|
QPointF raw_value{};
|
||||||
|
Input::AnalogProperties properties{};
|
||||||
|
int size{};
|
||||||
|
QPoint offset{};
|
||||||
|
bool active{};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LedPattern {
|
||||||
|
bool position1;
|
||||||
|
bool position2;
|
||||||
|
bool position3;
|
||||||
|
bool position4;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ColorMapping {
|
||||||
|
QColor outline{};
|
||||||
|
QColor primary{};
|
||||||
|
QColor left{};
|
||||||
|
QColor right{};
|
||||||
|
QColor button{};
|
||||||
|
QColor button2{};
|
||||||
|
QColor font{};
|
||||||
|
QColor font2{};
|
||||||
|
QColor highlight{};
|
||||||
|
QColor highlight2{};
|
||||||
|
QColor transparent{};
|
||||||
|
QColor indicator{};
|
||||||
|
QColor led_on{};
|
||||||
|
QColor led_off{};
|
||||||
|
QColor slider{};
|
||||||
|
QColor slider_button{};
|
||||||
|
QColor slider_arrow{};
|
||||||
|
QColor deadzone{};
|
||||||
|
};
|
||||||
|
|
||||||
|
static LedPattern GetColorPattern(std::size_t index, bool player_on);
|
||||||
|
void UpdateColors();
|
||||||
|
|
||||||
|
// Draw controller functions
|
||||||
|
void DrawHandheldController(QPainter& p, QPointF center);
|
||||||
|
void DrawDualController(QPainter& p, QPointF center);
|
||||||
|
void DrawLeftController(QPainter& p, QPointF center);
|
||||||
|
void DrawRightController(QPainter& p, QPointF center);
|
||||||
|
void DrawProController(QPainter& p, QPointF center);
|
||||||
|
|
||||||
|
// Draw body functions
|
||||||
|
void DrawHandheldBody(QPainter& p, QPointF center);
|
||||||
|
void DrawDualBody(QPainter& p, QPointF center);
|
||||||
|
void DrawLeftBody(QPainter& p, QPointF center);
|
||||||
|
void DrawRightBody(QPainter& p, QPointF center);
|
||||||
|
void DrawProBody(QPainter& p, QPointF center);
|
||||||
|
|
||||||
|
// Draw triggers functions
|
||||||
|
void DrawProTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed);
|
||||||
|
void DrawHandheldTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed);
|
||||||
|
void DrawDualTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed);
|
||||||
|
void DrawDualZTriggers(QPainter& p, QPointF center, bool left_pressed, bool right_pressed);
|
||||||
|
void DrawLeftTriggers(QPainter& p, QPointF center, bool left_pressed);
|
||||||
|
void DrawLeftZTriggers(QPainter& p, QPointF center, bool left_pressed);
|
||||||
|
void DrawRightTriggers(QPainter& p, QPointF center, bool right_pressed);
|
||||||
|
void DrawRightZTriggers(QPainter& p, QPointF center, bool right_pressed);
|
||||||
|
|
||||||
|
// Draw joystick functions
|
||||||
|
void DrawJoystick(QPainter& p, QPointF center, float size, bool pressed);
|
||||||
|
void DrawJoystickSideview(QPainter& p, QPointF center, float angle, float size, bool pressed);
|
||||||
|
void DrawRawJoystick(QPainter& p, QPointF center, const QPointF value,
|
||||||
|
const Input::AnalogProperties properties);
|
||||||
|
void DrawProJoystick(QPainter& p, QPointF center, bool pressed);
|
||||||
|
|
||||||
|
// Draw button functions
|
||||||
|
void DrawCircleButton(QPainter& p, QPointF center, bool pressed, int button_size);
|
||||||
|
void DrawRoundButton(QPainter& p, QPointF center, bool pressed, float width, float height,
|
||||||
|
const Direction direction = Direction::None, float radius = 2);
|
||||||
|
void DrawMinusButton(QPainter& p, QPointF center, bool pressed, int button_size);
|
||||||
|
void DrawPlusButton(QPainter& p, QPointF center, bool pressed, int button_size);
|
||||||
|
void DrawArrowButton(QPainter& p, QPointF center, const Direction direction, bool pressed);
|
||||||
|
|
||||||
|
// Draw icon functions
|
||||||
|
void DrawHouseIcon(QPainter& p, QPointF center, float icon_size);
|
||||||
|
void DrawArrow(QPainter& p, QPointF center, const Direction direction, float size);
|
||||||
|
|
||||||
|
// Draw primitive types
|
||||||
|
template <size_t N>
|
||||||
|
void DrawPolygon(QPainter& p, const std::array<QPointF, N>& polygon);
|
||||||
|
void DrawCircle(QPainter& p, QPointF center, float size);
|
||||||
|
void DrawRectangle(QPainter& p, QPointF center, float width, float height);
|
||||||
|
void DrawRoundRectangle(QPainter& p, QPointF center, float width, float height, float round);
|
||||||
|
void DrawText(QPainter& p, QPointF center, float text_size, const QString& text);
|
||||||
|
void SetTextFont(QPainter& p, float text_size,
|
||||||
|
const QString font_family = QStringLiteral("sans-serif"));
|
||||||
|
|
||||||
|
using ButtonArray =
|
||||||
|
std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::BUTTON_NS_END>;
|
||||||
|
using StickArray =
|
||||||
|
std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>;
|
||||||
|
|
||||||
|
bool mapping_active{};
|
||||||
|
int blink_counter{};
|
||||||
|
QColor button_color{};
|
||||||
|
ColorMapping colors{};
|
||||||
|
std::array<QColor, 4> led_color{};
|
||||||
|
ButtonArray buttons{};
|
||||||
|
StickArray sticks{};
|
||||||
|
std::size_t player_index{};
|
||||||
|
std::size_t button_mapping_index{Settings::NativeButton::BUTTON_NS_END};
|
||||||
|
std::size_t analog_mapping_index{Settings::NativeAnalog::NUM_STICKS_HID};
|
||||||
|
std::array<AxisValue, Settings::NativeAnalog::NUM_STICKS_HID> axis_values{};
|
||||||
|
std::array<bool, Settings::NativeButton::NumButtons> button_values{};
|
||||||
|
Settings::ControllerType controller_type{Settings::ControllerType::ProController};
|
||||||
|
};
|
|
@ -119,7 +119,7 @@ void GameListSearchField::setFocus() {
|
||||||
GameListSearchField::GameListSearchField(GameList* parent) : QWidget{parent} {
|
GameListSearchField::GameListSearchField(GameList* parent) : QWidget{parent} {
|
||||||
auto* const key_release_eater = new KeyReleaseEater(parent, this);
|
auto* const key_release_eater = new KeyReleaseEater(parent, this);
|
||||||
layout_filter = new QHBoxLayout;
|
layout_filter = new QHBoxLayout;
|
||||||
layout_filter->setMargin(8);
|
layout_filter->setContentsMargins(8, 8, 8, 8);
|
||||||
label_filter = new QLabel;
|
label_filter = new QLabel;
|
||||||
label_filter->setText(tr("Filter:"));
|
label_filter->setText(tr("Filter:"));
|
||||||
edit_filter = new QLineEdit;
|
edit_filter = new QLineEdit;
|
||||||
|
|
Loading…
Reference in a new issue