DolphinQt: add widget in game properties to list the various graphics mods available

This commit is contained in:
iwubcode 2022-03-02 00:38:00 -06:00
parent 1480b78f64
commit f3054aa99f
5 changed files with 348 additions and 0 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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);

View File

@ -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" />