DolphinQt: add widget in game properties to list the various graphics mods available
This commit is contained in:
parent
1480b78f64
commit
f3054aa99f
|
@ -129,6 +129,8 @@ add_executable(dolphin-emu
|
|||
Config/Graphics/PostProcessingConfigWindow.h
|
||||
Config/Graphics/SoftwareRendererWidget.cpp
|
||||
Config/Graphics/SoftwareRendererWidget.h
|
||||
Config/GraphicsModListWidget.cpp
|
||||
Config/GraphicsModListWidget.h
|
||||
Config/InfoWidget.cpp
|
||||
Config/InfoWidget.h
|
||||
Config/LogConfigWidget.cpp
|
||||
|
|
|
@ -0,0 +1,268 @@
|
|||
// Copyright 2022 Dolphin Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "DolphinQt/Config/GraphicsModListWidget.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QListWidget>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "DolphinQt/Settings.h"
|
||||
#include "UICommon/GameFile.h"
|
||||
#include "VideoCommon/GraphicsModSystem/Config/GraphicsMod.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
GraphicsModListWidget::GraphicsModListWidget(const UICommon::GameFile& game)
|
||||
: m_game_id(game.GetGameID()), m_mod_group(m_game_id)
|
||||
{
|
||||
CalculateGameRunning(Core::GetState());
|
||||
if (m_loaded_game_is_running && g_Config.graphics_mod_config)
|
||||
{
|
||||
m_mod_group.SetChangeCount(g_Config.graphics_mod_config->GetChangeCount());
|
||||
}
|
||||
CreateWidgets();
|
||||
ConnectWidgets();
|
||||
|
||||
RefreshModList();
|
||||
OnModChanged(std::nullopt);
|
||||
}
|
||||
|
||||
GraphicsModListWidget::~GraphicsModListWidget()
|
||||
{
|
||||
if (m_needs_save)
|
||||
{
|
||||
m_mod_group.Save();
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsModListWidget::CreateWidgets()
|
||||
{
|
||||
auto* main_layout = new QHBoxLayout(this);
|
||||
|
||||
auto* left_v_layout = new QVBoxLayout;
|
||||
|
||||
m_mod_list = new QListWidget;
|
||||
m_mod_list->setSortingEnabled(false);
|
||||
m_mod_list->setSelectionBehavior(QAbstractItemView::SelectionBehavior::SelectItems);
|
||||
m_mod_list->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection);
|
||||
m_mod_list->setSelectionRectVisible(true);
|
||||
m_mod_list->setDragDropMode(QAbstractItemView::InternalMove);
|
||||
|
||||
m_refresh = new QPushButton(tr("&Refresh List"));
|
||||
QHBoxLayout* hlayout = new QHBoxLayout;
|
||||
hlayout->addStretch();
|
||||
hlayout->addWidget(m_refresh);
|
||||
|
||||
left_v_layout->addWidget(m_mod_list);
|
||||
left_v_layout->addLayout(hlayout);
|
||||
|
||||
auto* right_v_layout = new QVBoxLayout;
|
||||
|
||||
m_selected_mod_name = new QLabel();
|
||||
right_v_layout->addWidget(m_selected_mod_name);
|
||||
|
||||
m_mod_meta_layout = new QVBoxLayout;
|
||||
right_v_layout->addLayout(m_mod_meta_layout);
|
||||
|
||||
main_layout->addLayout(left_v_layout);
|
||||
main_layout->addLayout(right_v_layout, 1);
|
||||
|
||||
setLayout(main_layout);
|
||||
}
|
||||
|
||||
void GraphicsModListWidget::ConnectWidgets()
|
||||
{
|
||||
connect(m_mod_list, &QListWidget::itemSelectionChanged, this,
|
||||
&GraphicsModListWidget::ModSelectionChanged);
|
||||
|
||||
connect(m_mod_list, &QListWidget::itemChanged, this, &GraphicsModListWidget::ModItemChanged);
|
||||
|
||||
connect(m_mod_list->model(), &QAbstractItemModel::rowsMoved, this,
|
||||
&GraphicsModListWidget::SaveModList);
|
||||
|
||||
connect(m_refresh, &QPushButton::clicked, this, &GraphicsModListWidget::RefreshModList);
|
||||
|
||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
|
||||
&GraphicsModListWidget::CalculateGameRunning);
|
||||
}
|
||||
|
||||
void GraphicsModListWidget::RefreshModList()
|
||||
{
|
||||
m_mod_list->setCurrentItem(nullptr);
|
||||
m_mod_list->clear();
|
||||
|
||||
m_mod_group = GraphicsModGroupConfig(m_game_id);
|
||||
m_mod_group.Load();
|
||||
|
||||
std::set<std::string> groups;
|
||||
|
||||
for (const auto& mod : m_mod_group.GetMods())
|
||||
{
|
||||
if (mod.m_groups.empty())
|
||||
continue;
|
||||
|
||||
for (const auto& group : mod.m_groups)
|
||||
{
|
||||
groups.insert(group.m_name);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& mod : m_mod_group.GetMods())
|
||||
{
|
||||
// Group only mods shouldn't be shown
|
||||
if (mod.m_features.empty())
|
||||
continue;
|
||||
|
||||
// If the group doesn't exist in the available mod's features, skip
|
||||
if (std::none_of(mod.m_features.begin(), mod.m_features.end(),
|
||||
[&groups](const GraphicsModFeatureConfig& feature) {
|
||||
return groups.count(feature.m_group) == 1;
|
||||
}))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QListWidgetItem* item = new QListWidgetItem(QString::fromStdString(mod.m_title));
|
||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||
item->setData(Qt::UserRole, QString::fromStdString(mod.GetAbsolutePath()));
|
||||
item->setCheckState(mod.m_enabled ? Qt::Checked : Qt::Unchecked);
|
||||
|
||||
m_mod_list->addItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsModListWidget::ModSelectionChanged()
|
||||
{
|
||||
if (m_mod_list->currentItem() == nullptr)
|
||||
return;
|
||||
if (m_mod_list->count() == 0)
|
||||
return;
|
||||
const auto absolute_path = m_mod_list->currentItem()->data(Qt::UserRole).toString().toStdString();
|
||||
OnModChanged(absolute_path);
|
||||
}
|
||||
|
||||
void GraphicsModListWidget::ModItemChanged(QListWidgetItem* item)
|
||||
{
|
||||
const auto absolute_path = item->data(Qt::UserRole).toString();
|
||||
GraphicsModConfig* mod = m_mod_group.GetMod(absolute_path.toStdString());
|
||||
if (!mod)
|
||||
return;
|
||||
|
||||
const bool was_enabled = mod->m_enabled;
|
||||
const bool should_enable = item->checkState() == Qt::Checked;
|
||||
mod->m_enabled = should_enable;
|
||||
if (was_enabled == should_enable)
|
||||
return;
|
||||
|
||||
m_mod_group.SetChangeCount(m_mod_group.GetChangeCount() + 1);
|
||||
if (m_loaded_game_is_running)
|
||||
{
|
||||
g_Config.graphics_mod_config = m_mod_group;
|
||||
}
|
||||
m_needs_save = true;
|
||||
}
|
||||
|
||||
void GraphicsModListWidget::OnModChanged(std::optional<std::string> absolute_path)
|
||||
{
|
||||
ClearLayoutRecursively(m_mod_meta_layout);
|
||||
|
||||
adjustSize();
|
||||
|
||||
if (!absolute_path)
|
||||
{
|
||||
m_selected_mod_name->setText(QStringLiteral("No graphics mod selected"));
|
||||
m_selected_mod_name->setAlignment(Qt::AlignCenter);
|
||||
return;
|
||||
}
|
||||
|
||||
GraphicsModConfig* mod = m_mod_group.GetMod(*absolute_path);
|
||||
if (!mod)
|
||||
return;
|
||||
|
||||
m_selected_mod_name->setText(QString::fromStdString(mod->m_title));
|
||||
m_selected_mod_name->setAlignment(Qt::AlignLeft);
|
||||
QFont font = m_selected_mod_name->font();
|
||||
font.setWeight(QFont::Bold);
|
||||
m_selected_mod_name->setFont(font);
|
||||
|
||||
if (!mod->m_author.empty())
|
||||
{
|
||||
auto* author_label = new QLabel(tr("By: ") + QString::fromStdString(mod->m_author));
|
||||
m_mod_meta_layout->addWidget(author_label);
|
||||
}
|
||||
|
||||
if (!mod->m_description.empty())
|
||||
{
|
||||
auto* description_label =
|
||||
new QLabel(tr("Description: ") + QString::fromStdString(mod->m_description));
|
||||
m_mod_meta_layout->addWidget(description_label);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsModListWidget::SaveModList()
|
||||
{
|
||||
for (int i = 0; i < m_mod_list->count(); i++)
|
||||
{
|
||||
const auto absolute_path = m_mod_list->model()
|
||||
->data(m_mod_list->model()->index(i, 0), Qt::UserRole)
|
||||
.toString()
|
||||
.toStdString();
|
||||
m_mod_group.GetMod(absolute_path)->m_weight = i;
|
||||
}
|
||||
|
||||
if (m_loaded_game_is_running)
|
||||
{
|
||||
g_Config.graphics_mod_config = m_mod_group;
|
||||
}
|
||||
m_needs_save = true;
|
||||
}
|
||||
|
||||
void GraphicsModListWidget::ClearLayoutRecursively(QLayout* layout)
|
||||
{
|
||||
while (QLayoutItem* child = layout->takeAt(0))
|
||||
{
|
||||
if (child == nullptr)
|
||||
continue;
|
||||
|
||||
if (child->widget())
|
||||
{
|
||||
layout->removeWidget(child->widget());
|
||||
delete child->widget();
|
||||
}
|
||||
else if (child->layout())
|
||||
{
|
||||
ClearLayoutRecursively(child->layout());
|
||||
layout->removeItem(child);
|
||||
}
|
||||
else
|
||||
{
|
||||
layout->removeItem(child);
|
||||
}
|
||||
delete child;
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsModListWidget::SaveToDisk()
|
||||
{
|
||||
m_needs_save = false;
|
||||
m_mod_group.Save();
|
||||
}
|
||||
|
||||
const GraphicsModGroupConfig& GraphicsModListWidget::GetGraphicsModConfig() const
|
||||
{
|
||||
return m_mod_group;
|
||||
}
|
||||
|
||||
void GraphicsModListWidget::CalculateGameRunning(Core::State state)
|
||||
{
|
||||
m_loaded_game_is_running =
|
||||
state == Core::State::Running ? m_game_id == SConfig::GetInstance().GetGameID() : false;
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
// Copyright 2022 Dolphin Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "VideoCommon/GraphicsModSystem/Config/GraphicsModGroup.h"
|
||||
|
||||
class QHBoxLayout;
|
||||
class QLabel;
|
||||
class QListWidget;
|
||||
class QListWidgetItem;
|
||||
class QModelIndex;
|
||||
class QPushButton;
|
||||
class QVBoxLayout;
|
||||
|
||||
namespace Core
|
||||
{
|
||||
enum class State;
|
||||
}
|
||||
|
||||
namespace UICommon
|
||||
{
|
||||
class GameFile;
|
||||
}
|
||||
|
||||
class GraphicsModListWidget : public QWidget
|
||||
{
|
||||
public:
|
||||
explicit GraphicsModListWidget(const UICommon::GameFile& game);
|
||||
~GraphicsModListWidget();
|
||||
|
||||
void SaveToDisk();
|
||||
|
||||
const GraphicsModGroupConfig& GetGraphicsModConfig() const;
|
||||
|
||||
private:
|
||||
void CreateWidgets();
|
||||
void ConnectWidgets();
|
||||
|
||||
void RefreshModList();
|
||||
void ModSelectionChanged();
|
||||
void ModItemChanged(QListWidgetItem* item);
|
||||
|
||||
void OnModChanged(std::optional<std::string> absolute_path);
|
||||
|
||||
void SaveModList();
|
||||
|
||||
void ClearLayoutRecursively(QLayout* layout);
|
||||
|
||||
void CalculateGameRunning(Core::State state);
|
||||
bool m_loaded_game_is_running = false;
|
||||
bool m_needs_save = false;
|
||||
|
||||
QListWidget* m_mod_list;
|
||||
|
||||
QLabel* m_selected_mod_name;
|
||||
QVBoxLayout* m_mod_meta_layout;
|
||||
|
||||
QPushButton* m_refresh;
|
||||
|
||||
std::string m_game_id;
|
||||
GraphicsModGroupConfig m_mod_group;
|
||||
};
|
|
@ -17,12 +17,14 @@
|
|||
#include "DolphinQt/Config/FilesystemWidget.h"
|
||||
#include "DolphinQt/Config/GameConfigWidget.h"
|
||||
#include "DolphinQt/Config/GeckoCodeWidget.h"
|
||||
#include "DolphinQt/Config/GraphicsModListWidget.h"
|
||||
#include "DolphinQt/Config/InfoWidget.h"
|
||||
#include "DolphinQt/Config/PatchesWidget.h"
|
||||
#include "DolphinQt/Config/VerifyWidget.h"
|
||||
#include "DolphinQt/QtUtils/WrapInScrollArea.h"
|
||||
|
||||
#include "UICommon/GameFile.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
PropertiesDialog::PropertiesDialog(QWidget* parent, const UICommon::GameFile& game)
|
||||
: QDialog(parent)
|
||||
|
@ -43,6 +45,7 @@ PropertiesDialog::PropertiesDialog(QWidget* parent, const UICommon::GameFile& ga
|
|||
new GeckoCodeWidget(game.GetGameID(), game.GetGameTDBID(), game.GetRevision());
|
||||
PatchesWidget* patches = new PatchesWidget(game);
|
||||
GameConfigWidget* game_config = new GameConfigWidget(game);
|
||||
GraphicsModListWidget* graphics_mod_list = new GraphicsModListWidget(game);
|
||||
|
||||
connect(gecko, &GeckoCodeWidget::OpenGeneralSettings, this,
|
||||
&PropertiesDialog::OpenGeneralSettings);
|
||||
|
@ -57,6 +60,8 @@ PropertiesDialog::PropertiesDialog(QWidget* parent, const UICommon::GameFile& ga
|
|||
tab_widget->addTab(GetWrappedWidget(ar, this, padding_width, padding_height), tr("AR Codes"));
|
||||
tab_widget->addTab(GetWrappedWidget(gecko, this, padding_width, padding_height),
|
||||
tr("Gecko Codes"));
|
||||
tab_widget->addTab(GetWrappedWidget(graphics_mod_list, this, padding_width, padding_height),
|
||||
tr("Graphics Mods"));
|
||||
tab_widget->addTab(GetWrappedWidget(info, this, padding_width, padding_height), tr("Info"));
|
||||
|
||||
if (game.GetPlatform() != DiscIO::Platform::ELFOrDOL)
|
||||
|
@ -82,6 +87,8 @@ PropertiesDialog::PropertiesDialog(QWidget* parent, const UICommon::GameFile& ga
|
|||
QDialogButtonBox* close_box = new QDialogButtonBox(QDialogButtonBox::Close);
|
||||
|
||||
connect(close_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
connect(close_box, &QDialogButtonBox::rejected, graphics_mod_list,
|
||||
&GraphicsModListWidget::SaveToDisk);
|
||||
|
||||
layout->addWidget(close_box);
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@
|
|||
<ClCompile Include="Config\Graphics\HacksWidget.cpp" />
|
||||
<ClCompile Include="Config\Graphics\PostProcessingConfigWindow.cpp" />
|
||||
<ClCompile Include="Config\Graphics\SoftwareRendererWidget.cpp" />
|
||||
<ClCompile Include="Config\GraphicsModListWidget.cpp" />
|
||||
<ClCompile Include="Config\InfoWidget.cpp" />
|
||||
<ClCompile Include="Config\LogConfigWidget.cpp" />
|
||||
<ClCompile Include="Config\LogWidget.cpp" />
|
||||
|
@ -270,6 +271,7 @@
|
|||
<QtMoc Include="Config\Graphics\HacksWidget.h" />
|
||||
<QtMoc Include="Config\Graphics\PostProcessingConfigWindow.h" />
|
||||
<QtMoc Include="Config\Graphics\SoftwareRendererWidget.h" />
|
||||
<QtMoc Include="Config\GraphicsModListWidget.h" />
|
||||
<QtMoc Include="Config\InfoWidget.h" />
|
||||
<QtMoc Include="Config\LogConfigWidget.h" />
|
||||
<QtMoc Include="Config\LogWidget.h" />
|
||||
|
|
Loading…
Reference in New Issue