early-access version 2251

This commit is contained in:
pineappleEA
2021-11-28 11:31:20 +01:00
parent a657cf53a1
commit faf5b13e48
58 changed files with 171227 additions and 121316 deletions
+2
View File
@@ -126,6 +126,8 @@ add_executable(yuzu
configuration/configure_web.ui
configuration/input_profiles.cpp
configuration/input_profiles.h
controller_navigation.cpp
controller_navigation.h
debugger/console.cpp
debugger/console.h
debugger/controller.cpp
+13 -1
View File
@@ -201,6 +201,16 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
connect(ui->buttonBox, &QDialogButtonBox::accepted, this,
&QtControllerSelectorDialog::ApplyConfiguration);
controller_navigation = new ControllerNavigation(system.HIDCore(), this);
connect(controller_navigation, &ControllerNavigation::TriggerKeyboardEvent,
[this](Qt::Key key) {
if (!this->isActiveWindow()) {
return;
}
QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier);
QCoreApplication::postEvent(this, event);
});
// 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.
@@ -218,7 +228,9 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
resize(0, 0);
}
QtControllerSelectorDialog::~QtControllerSelectorDialog() = default;
QtControllerSelectorDialog::~QtControllerSelectorDialog() {
controller_navigation->UnloadController();
};
int QtControllerSelectorDialog::exec() {
if (parameters_met && parameters.enable_single_mode) {
+4
View File
@@ -9,6 +9,7 @@
#include <QDialog>
#include "core/core.h"
#include "core/frontend/applets/controller.h"
#include "yuzu/controller_navigation.h"
class GMainWindow;
class QCheckBox;
@@ -148,6 +149,9 @@ private:
// Checkboxes representing the "Connected Controllers".
std::array<QCheckBox*, NUM_PLAYERS> connected_controller_checkboxes;
// QObject for navigating the UI with a controller
ControllerNavigation* controller_navigation = nullptr;
};
class QtControllerSelector final : public QObject, public Core::Frontend::ControllerApplet {
+14 -2
View File
@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include <mutex>
#include <QApplication>
#include <QDialogButtonBox>
#include <QHeaderView>
#include <QLabel>
@@ -45,7 +46,7 @@ QPixmap GetIcon(Common::UUID uuid) {
}
} // Anonymous namespace
QtProfileSelectionDialog::QtProfileSelectionDialog(QWidget* parent)
QtProfileSelectionDialog::QtProfileSelectionDialog(Core::HID::HIDCore& hid_core, QWidget* parent)
: QDialog(parent), profile_manager(std::make_unique<Service::Account::ProfileManager>()) {
outer_layout = new QVBoxLayout;
@@ -65,6 +66,7 @@ QtProfileSelectionDialog::QtProfileSelectionDialog(QWidget* parent)
tree_view = new QTreeView;
item_model = new QStandardItemModel(tree_view);
tree_view->setModel(item_model);
controller_navigation = new ControllerNavigation(hid_core, this);
tree_view->setAlternatingRowColors(true);
tree_view->setSelectionMode(QHeaderView::SingleSelection);
@@ -91,6 +93,14 @@ QtProfileSelectionDialog::QtProfileSelectionDialog(QWidget* parent)
scroll_area->setLayout(layout);
connect(tree_view, &QTreeView::clicked, this, &QtProfileSelectionDialog::SelectUser);
connect(controller_navigation, &ControllerNavigation::TriggerKeyboardEvent,
[this](Qt::Key key) {
if (!this->isActiveWindow()) {
return;
}
QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier);
QCoreApplication::postEvent(tree_view, event);
});
const auto& profiles = profile_manager->GetAllUsers();
for (const auto& user : profiles) {
@@ -113,7 +123,9 @@ QtProfileSelectionDialog::QtProfileSelectionDialog(QWidget* parent)
resize(550, 400);
}
QtProfileSelectionDialog::~QtProfileSelectionDialog() = default;
QtProfileSelectionDialog::~QtProfileSelectionDialog() {
controller_navigation->UnloadController();
};
int QtProfileSelectionDialog::exec() {
// Skip profile selection when there's only one.
+3 -1
View File
@@ -10,6 +10,7 @@
#include <QTreeView>
#include "core/frontend/applets/profile_select.h"
#include "core/hle/service/acc/profile_manager.h"
#include "yuzu/controller_navigation.h"
class GMainWindow;
class QDialogButtonBox;
@@ -24,7 +25,7 @@ class QtProfileSelectionDialog final : public QDialog {
Q_OBJECT
public:
explicit QtProfileSelectionDialog(QWidget* parent);
explicit QtProfileSelectionDialog(Core::HID::HIDCore& hid_core, QWidget* parent);
~QtProfileSelectionDialog() override;
int exec() override;
@@ -51,6 +52,7 @@ private:
QDialogButtonBox* buttons;
std::unique_ptr<Service::Account::ProfileManager> profile_manager;
ControllerNavigation* controller_navigation = nullptr;
};
class QtProfileSelector final : public QObject, public Core::Frontend::ProfileSelectApplet {
+2
View File
@@ -508,6 +508,7 @@ void Config::ReadDebuggingValues() {
ReadBasicSetting(Settings::values.extended_logging);
ReadBasicSetting(Settings::values.use_debug_asserts);
ReadBasicSetting(Settings::values.use_auto_stub);
ReadBasicSetting(Settings::values.enable_all_controllers);
qt_config->endGroup();
}
@@ -1051,6 +1052,7 @@ void Config::SaveDebuggingValues() {
WriteBasicSetting(Settings::values.quest_flag);
WriteBasicSetting(Settings::values.use_debug_asserts);
WriteBasicSetting(Settings::values.disable_macro_jit);
WriteBasicSetting(Settings::values.enable_all_controllers);
qt_config->endGroup();
}
@@ -42,6 +42,7 @@ void ConfigureDebug::SetConfiguration() {
ui->quest_flag->setChecked(Settings::values.quest_flag.GetValue());
ui->use_debug_asserts->setChecked(Settings::values.use_debug_asserts.GetValue());
ui->use_auto_stub->setChecked(Settings::values.use_auto_stub.GetValue());
ui->enable_all_controllers->setChecked(Settings::values.enable_all_controllers.GetValue());
ui->enable_graphics_debugging->setEnabled(runtime_lock);
ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug.GetValue());
ui->enable_shader_feedback->setEnabled(runtime_lock);
@@ -69,6 +70,7 @@ void ConfigureDebug::ApplyConfiguration() {
Settings::values.quest_flag = ui->quest_flag->isChecked();
Settings::values.use_debug_asserts = ui->use_debug_asserts->isChecked();
Settings::values.use_auto_stub = ui->use_auto_stub->isChecked();
Settings::values.enable_all_controllers = ui->enable_all_controllers->isChecked();
Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked();
Settings::values.renderer_shader_feedback = ui->enable_shader_feedback->isChecked();
Settings::values.cpu_debug_mode = ui->enable_cpu_debugging->isChecked();
@@ -211,6 +211,13 @@
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="enable_all_controllers">
<property name="text">
<string>Enable all Controller Types</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@@ -947,6 +947,40 @@ void ConfigureInputPlayer::SetConnectableControllers() {
Core::HID::NpadStyleIndex::GameCube);
ui->comboControllerType->addItem(tr("GameCube Controller"));
}
// Disable all unsupported controllers
if (!Settings::values.enable_all_controllers) {
return;
}
if (enable_all || npad_style_set.palma == 1) {
index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
Core::HID::NpadStyleIndex::Pokeball);
ui->comboControllerType->addItem(tr("Poke Ball Plus"));
}
if (enable_all || npad_style_set.lark == 1) {
index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
Core::HID::NpadStyleIndex::NES);
ui->comboControllerType->addItem(tr("NES Controller"));
}
if (enable_all || npad_style_set.lucia == 1) {
index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
Core::HID::NpadStyleIndex::SNES);
ui->comboControllerType->addItem(tr("SNES Controller"));
}
if (enable_all || npad_style_set.lagoon == 1) {
index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
Core::HID::NpadStyleIndex::N64);
ui->comboControllerType->addItem(tr("N64 Controller"));
}
if (enable_all || npad_style_set.lager == 1) {
index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
Core::HID::NpadStyleIndex::SegaGenesis);
ui->comboControllerType->addItem(tr("Sega Genesis"));
}
};
if (!is_powered_on) {
+160
View File
@@ -0,0 +1,160 @@
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included
#include "common/settings_input.h"
#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
#include "yuzu/controller_navigation.h"
ControllerNavigation::ControllerNavigation(Core::HID::HIDCore& hid_core, QWidget* parent) {
controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
Core::HID::ControllerUpdateCallback engine_callback{
.on_change = [this](Core::HID::ControllerTriggerType type) { ControllerUpdateEvent(type); },
.is_npad_service = false,
};
callback_key = controller->SetCallback(engine_callback);
is_controller_set = true;
}
ControllerNavigation::~ControllerNavigation() {
UnloadController();
}
void ControllerNavigation::UnloadController() {
if (is_controller_set) {
controller->DeleteCallback(callback_key);
is_controller_set = false;
}
}
void ControllerNavigation::TriggerButton(const Core::HID::ButtonValues& buttons,
Settings::NativeButton::Values native_button,
Qt::Key key) {
if (buttons[native_button].value && !button_values[native_button].locked) {
emit TriggerKeyboardEvent(key);
}
}
void ControllerNavigation::ControllerUpdateEvent(Core::HID::ControllerTriggerType type) {
if (type == Core::HID::ControllerTriggerType::Button) {
const auto controller_type = controller->GetNpadStyleIndex();
const auto& buttons = controller->GetButtonsValues();
for (std::size_t i = 0; i < buttons.size(); ++i) {
// Trigger only once
if (buttons[i].value == button_values[i].value) {
button_values[i].locked = true;
} else {
button_values[i].value = buttons[i].value;
button_values[i].locked = false;
}
}
switch (controller_type) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::JoyconDual:
case Core::HID::NpadStyleIndex::Handheld:
case Core::HID::NpadStyleIndex::GameCube:
TriggerButton(buttons, Settings::NativeButton::A, Qt::Key_Enter);
TriggerButton(buttons, Settings::NativeButton::B, Qt::Key_Escape);
TriggerButton(buttons, Settings::NativeButton::DDown, Qt::Key_Down);
TriggerButton(buttons, Settings::NativeButton::DLeft, Qt::Key_Left);
TriggerButton(buttons, Settings::NativeButton::DRight, Qt::Key_Right);
TriggerButton(buttons, Settings::NativeButton::DUp, Qt::Key_Up);
break;
case Core::HID::NpadStyleIndex::JoyconLeft:
TriggerButton(buttons, Settings::NativeButton::DDown, Qt::Key_Enter);
TriggerButton(buttons, Settings::NativeButton::DLeft, Qt::Key_Escape);
break;
case Core::HID::NpadStyleIndex::JoyconRight:
TriggerButton(buttons, Settings::NativeButton::X, Qt::Key_Enter);
TriggerButton(buttons, Settings::NativeButton::A, Qt::Key_Escape);
break;
default:
break;
}
return;
}
if (type == Core::HID::ControllerTriggerType::Stick) {
const auto controller_type = controller->GetNpadStyleIndex();
const auto& sticks = controller->GetSticksValues();
bool update = false;
for (std::size_t i = 0; i < sticks.size(); ++i) {
// Trigger only once
if (sticks[i].down != stick_values[i].down || sticks[i].left != stick_values[i].left ||
sticks[i].right != stick_values[i].right || sticks[i].up != stick_values[i].up) {
update = true;
}
stick_values[i] = sticks[i];
}
if (!update) {
return;
}
switch (controller_type) {
case Core::HID::NpadStyleIndex::ProController:
case Core::HID::NpadStyleIndex::JoyconDual:
case Core::HID::NpadStyleIndex::Handheld:
case Core::HID::NpadStyleIndex::GameCube:
if (sticks[Settings::NativeAnalog::LStick].down) {
emit TriggerKeyboardEvent(Qt::Key_Down);
return;
}
if (sticks[Settings::NativeAnalog::LStick].left) {
emit TriggerKeyboardEvent(Qt::Key_Left);
return;
}
if (sticks[Settings::NativeAnalog::LStick].right) {
emit TriggerKeyboardEvent(Qt::Key_Right);
return;
}
if (sticks[Settings::NativeAnalog::LStick].up) {
emit TriggerKeyboardEvent(Qt::Key_Up);
return;
}
break;
case Core::HID::NpadStyleIndex::JoyconLeft:
if (sticks[Settings::NativeAnalog::LStick].left) {
emit TriggerKeyboardEvent(Qt::Key_Down);
return;
}
if (sticks[Settings::NativeAnalog::LStick].up) {
emit TriggerKeyboardEvent(Qt::Key_Left);
return;
}
if (sticks[Settings::NativeAnalog::LStick].down) {
emit TriggerKeyboardEvent(Qt::Key_Right);
return;
}
if (sticks[Settings::NativeAnalog::LStick].right) {
emit TriggerKeyboardEvent(Qt::Key_Up);
return;
}
break;
case Core::HID::NpadStyleIndex::JoyconRight:
if (sticks[Settings::NativeAnalog::RStick].right) {
emit TriggerKeyboardEvent(Qt::Key_Down);
return;
}
if (sticks[Settings::NativeAnalog::RStick].down) {
emit TriggerKeyboardEvent(Qt::Key_Left);
return;
}
if (sticks[Settings::NativeAnalog::RStick].up) {
emit TriggerKeyboardEvent(Qt::Key_Right);
return;
}
if (sticks[Settings::NativeAnalog::RStick].left) {
emit TriggerKeyboardEvent(Qt::Key_Up);
return;
}
break;
default:
break;
}
return;
}
}
+42
View File
@@ -0,0 +1,42 @@
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included
#pragma once
#include <QKeyEvent>
#include <QObject>
#include "common/input.h"
#include "common/settings.h"
#include "core/hid/emulated_controller.h"
namespace Core::HID {
class HIDCore;
} // namespace Core::HID
class ControllerNavigation : public QObject {
Q_OBJECT
public:
explicit ControllerNavigation(Core::HID::HIDCore& hid_core, QWidget* parent = nullptr);
~ControllerNavigation();
/// Disables events from the emulated controller
void UnloadController();
signals:
void TriggerKeyboardEvent(Qt::Key key);
private:
void TriggerButton(const Core::HID::ButtonValues& buttons,
Settings::NativeButton::Values native_button, Qt::Key key);
void ControllerUpdateEvent(Core::HID::ControllerTriggerType type);
Core::HID::ButtonValues button_values{};
Core::HID::SticksValues stick_values{};
int callback_key;
bool is_controller_set{};
Core::HID::EmulatedController* controller;
};
+19
View File
@@ -17,6 +17,7 @@
#include <fmt/format.h>
#include "common/common_types.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/file_sys/patch_manager.h"
#include "core/file_sys/registered_cache.h"
#include "yuzu/compatibility_list.h"
@@ -312,6 +313,7 @@ GameList::GameList(FileSys::VirtualFilesystem vfs, FileSys::ManualContentProvide
this->main_window = parent;
layout = new QVBoxLayout;
tree_view = new QTreeView;
controller_navigation = new ControllerNavigation(system.HIDCore(), this);
search_field = new GameListSearchField(this);
item_model = new QStandardItemModel(tree_view);
tree_view->setModel(item_model);
@@ -341,6 +343,18 @@ GameList::GameList(FileSys::VirtualFilesystem vfs, FileSys::ManualContentProvide
connect(tree_view, &QTreeView::customContextMenuRequested, this, &GameList::PopupContextMenu);
connect(tree_view, &QTreeView::expanded, this, &GameList::OnItemExpanded);
connect(tree_view, &QTreeView::collapsed, this, &GameList::OnItemExpanded);
connect(controller_navigation, &ControllerNavigation::TriggerKeyboardEvent,
[this](Qt::Key key) {
// Avoid pressing buttons while playing
if (system.IsPoweredOn()) {
return;
}
if (!this->isActiveWindow()) {
return;
}
QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier);
QCoreApplication::postEvent(tree_view, event);
});
// We must register all custom types with the Qt Automoc system so that we are able to use
// it with signals/slots. In this case, QList falls under the umbrells of custom types.
@@ -353,7 +367,12 @@ GameList::GameList(FileSys::VirtualFilesystem vfs, FileSys::ManualContentProvide
setLayout(layout);
}
void GameList::UnloadController() {
controller_navigation->UnloadController();
}
GameList::~GameList() {
UnloadController();
emit ShouldCancelWorker();
}
+5
View File
@@ -23,6 +23,7 @@
#include "common/common_types.h"
#include "uisettings.h"
#include "yuzu/compatibility_list.h"
#include "yuzu/controller_navigation.h"
class GameListWorker;
class GameListSearchField;
@@ -88,6 +89,9 @@ public:
void SaveInterfaceLayout();
void LoadInterfaceLayout();
/// Disables events from the emulated controller
void UnloadController();
static const QStringList supported_file_extensions;
signals:
@@ -143,6 +147,7 @@ private:
QStandardItemModel* item_model = nullptr;
GameListWorker* current_worker = nullptr;
QFileSystemWatcher* watcher = nullptr;
ControllerNavigation* controller_navigation = nullptr;
CompatibilityList compatibility_list;
friend class GameListSearchField;
+6 -3
View File
@@ -449,7 +449,7 @@ void GMainWindow::ControllerSelectorReconfigureControllers(
}
void GMainWindow::ProfileSelectorSelectProfile() {
QtProfileSelectionDialog dialog(this);
QtProfileSelectionDialog dialog(system->HIDCore(), this);
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint |
Qt::WindowTitleHint | Qt::WindowSystemMenuHint |
Qt::WindowCloseButtonHint);
@@ -1346,7 +1346,7 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p
}
void GMainWindow::SelectAndSetCurrentUser() {
QtProfileSelectionDialog dialog(this);
QtProfileSelectionDialog dialog(system->HIDCore(), this);
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
dialog.setWindowModality(Qt::WindowModal);
@@ -1608,7 +1608,7 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
if (has_user_save) {
// User save data
const auto select_profile = [this] {
QtProfileSelectionDialog dialog(this);
QtProfileSelectionDialog dialog(system->HIDCore(), this);
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
dialog.setWindowModality(Qt::WindowModal);
@@ -3376,7 +3376,10 @@ void GMainWindow::closeEvent(QCloseEvent* event) {
UpdateUISettings();
game_list->SaveInterfaceLayout();
hotkey_registry.SaveHotkeys();
// Unload controllers early
controller_dialog->UnloadController();
game_list->UnloadController();
system->HIDCore().UnloadInputDevices();
// Shutdown session if the emu thread is active...