mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-05-09 04:13:28 -05:00
Now SerialInterfaceManager::UpdateDevices reads the configured SI devices directly from Config instead. The main reason why I wanted to do this is so that Android can change SI devices while emulation is running. (Android didn't have the code for calling ChangeDevice.) But when implementing the change, I noticed that NetPlay and Movie were using ChangeDevice as a way of overriding the SI devices configured by the user. Replacing this ended up making the change larger than I first anticipated. For Wii Remotes, there was no equivalent to ChangeDevice, so NetPlay and Movie were using Config::SetCurrent to override the Wii Remote source configured by the user. If we can use the config system to override Wii Remote sources, why not do the same for SI devices? This commit makes NetPlay and Movie set SI devices and Wii Remote sources in the NetPlay and Movie config layers, as that is the conceptually appropriate place to do it. As far as I can tell, the old Movie code for overriding SI devices and Wii Remote sources didn't actually work. This new code does. I didn't investigate exactly why it didn't work, but maybe it's because loading a movie happens before emulation actually starts.
202 lines
6.5 KiB
C++
202 lines
6.5 KiB
C++
// Copyright 2021 Dolphin Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include "DolphinQt/Config/GamecubeControllersWidget.h"
|
|
|
|
#include <QComboBox>
|
|
#include <QGridLayout>
|
|
#include <QGroupBox>
|
|
#include <QLabel>
|
|
#include <QPushButton>
|
|
#include <QVBoxLayout>
|
|
|
|
#include <optional>
|
|
#include <utility>
|
|
|
|
#include "Core/ConfigManager.h"
|
|
#include "Core/Core.h"
|
|
#include "Core/HW/SI/SI_Device.h"
|
|
#include "Core/NetPlayProto.h"
|
|
#include "Core/System.h"
|
|
|
|
#include "DolphinQt/Config/Mapping/GCPadWiiUConfigDialog.h"
|
|
#include "DolphinQt/Config/Mapping/MappingWindow.h"
|
|
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
|
|
#include "DolphinQt/QtUtils/SignalBlocking.h"
|
|
#include "DolphinQt/Settings.h"
|
|
|
|
using SIDeviceName = std::pair<SerialInterface::SIDevices, const char*>;
|
|
static constexpr std::array s_gc_types = {
|
|
SIDeviceName{SerialInterface::SIDEVICE_NONE, _trans("None")},
|
|
SIDeviceName{SerialInterface::SIDEVICE_GC_CONTROLLER, _trans("Standard Controller")},
|
|
SIDeviceName{SerialInterface::SIDEVICE_WIIU_ADAPTER,
|
|
_trans("GameCube Controller Adapter (USB)")},
|
|
SIDeviceName{SerialInterface::SIDEVICE_GC_STEERING, _trans("Steering Wheel")},
|
|
SIDeviceName{SerialInterface::SIDEVICE_DANCEMAT, _trans("Dance Mat")},
|
|
SIDeviceName{SerialInterface::SIDEVICE_GC_TARUKONGA, _trans("DK Bongos")},
|
|
#ifdef HAS_LIBMGBA
|
|
SIDeviceName{SerialInterface::SIDEVICE_GC_GBA_EMULATED, _trans("GBA (Integrated)")},
|
|
#endif
|
|
SIDeviceName{SerialInterface::SIDEVICE_GC_GBA, _trans("GBA (TCP)")},
|
|
SIDeviceName{SerialInterface::SIDEVICE_GC_KEYBOARD, _trans("Keyboard Controller")},
|
|
SIDeviceName{SerialInterface::SIDEVICE_AM_BASEBOARD, _trans("Triforce Baseboard")},
|
|
};
|
|
|
|
static std::optional<int> ToGCMenuIndex(const SerialInterface::SIDevices sidevice)
|
|
{
|
|
for (size_t i = 0; i < s_gc_types.size(); ++i)
|
|
{
|
|
if (s_gc_types[i].first == sidevice)
|
|
return static_cast<int>(i);
|
|
}
|
|
return {};
|
|
}
|
|
|
|
static SerialInterface::SIDevices FromGCMenuIndex(const int menudevice)
|
|
{
|
|
return s_gc_types[menudevice].first;
|
|
}
|
|
|
|
GamecubeControllersWidget::GamecubeControllersWidget(QWidget* parent) : QWidget(parent)
|
|
{
|
|
CreateLayout();
|
|
ConnectWidgets();
|
|
|
|
connect(&Settings::Instance(), &Settings::ConfigChanged, this,
|
|
[this] { LoadSettings(Core::GetState(Core::System::GetInstance())); });
|
|
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
|
|
[this](Core::State state) { LoadSettings(state); });
|
|
LoadSettings(Core::GetState(Core::System::GetInstance()));
|
|
}
|
|
|
|
void GamecubeControllersWidget::CreateLayout()
|
|
{
|
|
m_gc_box = new QGroupBox(tr("GameCube Controllers"));
|
|
m_gc_layout = new QGridLayout();
|
|
m_gc_layout->setVerticalSpacing(7);
|
|
m_gc_layout->setColumnStretch(1, 1);
|
|
|
|
for (size_t i = 0; i < m_gc_groups.size(); i++)
|
|
{
|
|
auto* gc_label = new QLabel(tr("Port %1").arg(i + 1));
|
|
auto* gc_box = m_gc_controller_boxes[i] = new QComboBox();
|
|
auto* gc_button = m_gc_buttons[i] = new NonDefaultQPushButton(tr("Configure"));
|
|
|
|
for (const auto& item : s_gc_types)
|
|
{
|
|
gc_box->addItem(tr(item.second));
|
|
}
|
|
|
|
int controller_row = m_gc_layout->rowCount();
|
|
m_gc_layout->addWidget(gc_label, controller_row, 0);
|
|
m_gc_layout->addWidget(gc_box, controller_row, 1);
|
|
m_gc_layout->addWidget(gc_button, controller_row, 2);
|
|
}
|
|
m_gc_box->setLayout(m_gc_layout);
|
|
|
|
auto* layout = new QVBoxLayout;
|
|
layout->setContentsMargins(0, 0, 0, 0);
|
|
layout->setAlignment(Qt::AlignTop);
|
|
layout->addWidget(m_gc_box);
|
|
setLayout(layout);
|
|
}
|
|
|
|
void GamecubeControllersWidget::ConnectWidgets()
|
|
{
|
|
for (size_t i = 0; i < m_gc_controller_boxes.size(); ++i)
|
|
{
|
|
connect(m_gc_controller_boxes[i], &QComboBox::currentIndexChanged, this, [this, i] {
|
|
OnGCTypeChanged(i);
|
|
SaveSettings();
|
|
});
|
|
connect(m_gc_buttons[i], &QPushButton::clicked, this, [this, i] { OnGCPadConfigure(i); });
|
|
}
|
|
}
|
|
|
|
void GamecubeControllersWidget::OnGCTypeChanged(size_t index)
|
|
{
|
|
const SerialInterface::SIDevices si_device =
|
|
FromGCMenuIndex(m_gc_controller_boxes[index]->currentIndex());
|
|
m_gc_buttons[index]->setEnabled(si_device != SerialInterface::SIDEVICE_NONE &&
|
|
si_device != SerialInterface::SIDEVICE_GC_GBA);
|
|
}
|
|
|
|
void GamecubeControllersWidget::OnGCPadConfigure(size_t index)
|
|
{
|
|
MappingWindow::Type type;
|
|
|
|
switch (FromGCMenuIndex(m_gc_controller_boxes[index]->currentIndex()))
|
|
{
|
|
case SerialInterface::SIDEVICE_NONE:
|
|
case SerialInterface::SIDEVICE_GC_GBA:
|
|
return;
|
|
case SerialInterface::SIDEVICE_GC_CONTROLLER:
|
|
type = MappingWindow::Type::MAPPING_GCPAD;
|
|
break;
|
|
case SerialInterface::SIDEVICE_WIIU_ADAPTER:
|
|
{
|
|
GCPadWiiUConfigDialog dialog(static_cast<int>(index), this);
|
|
dialog.exec();
|
|
return;
|
|
}
|
|
case SerialInterface::SIDEVICE_GC_STEERING:
|
|
type = MappingWindow::Type::MAPPING_GC_STEERINGWHEEL;
|
|
break;
|
|
case SerialInterface::SIDEVICE_DANCEMAT:
|
|
type = MappingWindow::Type::MAPPING_GC_DANCEMAT;
|
|
break;
|
|
case SerialInterface::SIDEVICE_GC_TARUKONGA:
|
|
type = MappingWindow::Type::MAPPING_GC_BONGOS;
|
|
break;
|
|
case SerialInterface::SIDEVICE_GC_GBA_EMULATED:
|
|
type = MappingWindow::Type::MAPPING_GC_GBA;
|
|
break;
|
|
case SerialInterface::SIDEVICE_GC_KEYBOARD:
|
|
type = MappingWindow::Type::MAPPING_GC_KEYBOARD;
|
|
break;
|
|
case SerialInterface::SIDEVICE_AM_BASEBOARD:
|
|
type = MappingWindow::Type::MAPPING_AM_BASEBOARD;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
MappingWindow* window = new MappingWindow(this, type, static_cast<int>(index));
|
|
window->setAttribute(Qt::WA_DeleteOnClose, true);
|
|
window->setWindowModality(Qt::WindowModality::WindowModal);
|
|
window->show();
|
|
}
|
|
|
|
void GamecubeControllersWidget::LoadSettings(Core::State state)
|
|
{
|
|
const bool running = state != Core::State::Uninitialized;
|
|
for (size_t i = 0; i < m_gc_groups.size(); i++)
|
|
{
|
|
const SerialInterface::SIDevices si_device =
|
|
Config::Get(Config::GetInfoForSIDevice(static_cast<int>(i)));
|
|
const std::optional<int> gc_index = ToGCMenuIndex(si_device);
|
|
if (gc_index)
|
|
{
|
|
SignalBlocking(m_gc_controller_boxes[i])->setCurrentIndex(*gc_index);
|
|
m_gc_controller_boxes[i]->setEnabled(NetPlay::IsNetPlayRunning() ? !running : true);
|
|
OnGCTypeChanged(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
void GamecubeControllersWidget::SaveSettings()
|
|
{
|
|
{
|
|
Config::ConfigChangeCallbackGuard config_guard;
|
|
|
|
for (size_t i = 0; i < m_gc_groups.size(); ++i)
|
|
{
|
|
const SerialInterface::SIDevices si_device =
|
|
FromGCMenuIndex(m_gc_controller_boxes[i]->currentIndex());
|
|
Config::SetBaseOrCurrent(Config::GetInfoForSIDevice(static_cast<int>(i)), si_device);
|
|
}
|
|
}
|
|
|
|
SConfig::GetInstance().SaveSettings();
|
|
}
|