Browse Source

Add to per game addons tab

Signed-off-by: crueter <crueter@eden-emu.dev>
pull/3472/head
crueter 6 days ago
parent
commit
72e9bebf61
No known key found for this signature in database GPG Key ID: 425ACD2D4830EBC6
  1. 7
      src/frontend_common/mod_manager.cpp
  2. 41
      src/qt_common/util/mod.cpp
  3. 4
      src/qt_common/util/mod.h
  4. 35
      src/yuzu/configuration/configure_per_game_addons.cpp
  5. 4
      src/yuzu/configuration/configure_per_game_addons.h
  6. 18
      src/yuzu/configuration/configure_per_game_addons.ui

7
src/frontend_common/mod_manager.cpp

@ -49,10 +49,9 @@ bool InstallMod(const std::filesystem::path& path, const u64 program_id, const b
// now copy
try {
if (copy)
std::filesystem::copy(path, mod_dir, std::filesystem::copy_options::recursive);
else
std::filesystem::rename(path, mod_dir);
std::filesystem::copy(path, mod_dir, std::filesystem::copy_options::recursive);
if (!copy)
std::filesystem::remove_all(path);
} catch (std::exception& e) {
LOG_ERROR(Frontend, "Mod install failed with message {}", e.what());
return false;

41
src/qt_common/util/mod.cpp

@ -1,4 +1,5 @@
#include <filesystem>
#include <JlCompress.h>
#include "frontend_common/mod_manager.h"
#include "mod.h"
#include "qt_common/abstract/frontend.h"
@ -11,16 +12,18 @@ QString GetModFolder(const QString& root, const QString& fallbackName) {
auto std_path = FrontendCommon::GetModFolder(std_root);
QString default_name;
if (std_path)
if (!fallbackName.isEmpty())
default_name = fallbackName;
else if (std_path)
default_name = QString::fromStdString(std_path->filename());
else if (fallbackName.isEmpty())
default_name = root.split(QLatin1Char('/')).last();
else
default_name = fallbackName;
default_name = root.split(QLatin1Char('/')).last();
QString name = QtCommon::Frontend::GetTextInput(
tr("Mod Name"), tr("What should this mod be called?"), default_name);
qDebug() << "Naming mod:" << name;
// if std_path is empty, frontend_common could not determine mod type and/or name.
// so we have to prompt the user and set up the structure ourselves
if (!std_path) {
@ -63,6 +66,7 @@ QString GetModFolder(const QString& root, const QString& fallbackName) {
std_path = mod_dir;
// ... and copy everything from the root to the temp dir
for (const auto& entry : fs::directory_iterator(root.toStdString())) {
const auto target = tmp / entry.path().filename();
@ -70,8 +74,15 @@ QString GetModFolder(const QString& root, const QString& fallbackName) {
fs::copy(entry.path(), target,
fs::copy_options::recursive | fs::copy_options::overwrite_existing);
}
} else {
// Rename the existing mod folder.
const auto new_path = std_path->parent_path() / name.toStdString();
fs::rename(std_path.value(), new_path);
std_path = new_path;
}
qDebug() << "Mod path" << std_path->string();
return QString::fromStdString(std_path->string());
}
@ -81,4 +92,26 @@ bool InstallMod(const QString& path, const QString& fallbackName, const u64 prog
return FrontendCommon::InstallMod(target.toStdString(), program_id, copy);
}
bool InstallModFromZip(const QString& path, const u64 program_id) {
namespace fs = std::filesystem;
fs::path tmp{fs::temp_directory_path() / "eden" / "unzip_mod"};
fs::remove_all(tmp);
if (!fs::create_directories(tmp))
return false;
QString qCacheDir = QString::fromStdString(tmp.string());
QFile zip{path};
// TODO(crueter): use QtCompress
QStringList result = JlCompress::extractDir(&zip, qCacheDir);
if (result.isEmpty())
return false;
const auto fallback = fs::path{path.toStdString()}.stem();
return InstallMod(qCacheDir, QString::fromStdString(fallback.string()), program_id, false);
}
} // namespace QtCommon::Mod

4
src/qt_common/util/mod.h

@ -7,6 +7,8 @@ namespace QtCommon::Mod {
QString GetModFolder(const QString &root, const QString &fallbackName);
bool InstallMod(const QString &path, const QString &fallbackName, const u64 program_id, const bool copy);
bool InstallMod(const QString &path, const QString &fallbackName, const u64 program_id, const bool copy = true);
bool InstallModFromZip(const QString &path, const u64 program_id);
}

35
src/yuzu/configuration/configure_per_game_addons.cpp

@ -19,8 +19,9 @@
#include "common/fs/path_util.h"
#include "core/core.h"
#include "core/file_sys/patch_manager.h"
#include "core/file_sys/xts_archive.h"
#include "core/loader/loader.h"
#include "qt_common/abstract/frontend.h"
#include "qt_common/util/mod.h"
#include "ui_configure_per_game_addons.h"
#include "yuzu/configuration/configure_input.h"
#include "yuzu/configuration/configure_per_game_addons.h"
@ -66,6 +67,9 @@ ConfigurePerGameAddons::ConfigurePerGameAddons(Core::System& system_, QWidget* p
connect(item_model, &QStandardItemModel::itemChanged,
[] { UISettings::values.is_game_list_reload_pending.exchange(true); });
connect(ui->folder, &QAbstractButton::clicked, this, &ConfigurePerGameAddons::InstallModFolder);
connect(ui->zip, &QAbstractButton::clicked, this, &ConfigurePerGameAddons::InstallModZip);
}
ConfigurePerGameAddons::~ConfigurePerGameAddons() = default;
@ -99,6 +103,35 @@ void ConfigurePerGameAddons::SetTitleId(u64 id) {
this->title_id = id;
}
void ConfigurePerGameAddons::InstallModFolder() {
const auto path = QtCommon::Frontend::GetExistingDirectory(tr("Mod Folder"));
if (path.isEmpty()) {
return;
}
// TODO: Pending refresh game list
if (QtCommon::Mod::InstallMod(path, {}, title_id)) {
QtCommon::Frontend::Information(tr("Mod Installed"), tr("Mod was successfully installed."));
LoadConfiguration();
} else {
QtCommon::Frontend::Critical(tr("Mod Install Failed"), tr("Mod install was unsuccessful. Check the log for details."));
}
}
void ConfigurePerGameAddons::InstallModZip() {
const auto path = QtCommon::Frontend::GetOpenFileName(tr("Zipped Mod Location"), {}, tr("Zipped Archives (*.zip)"));
if (path.isEmpty()) {
return;
}
if (QtCommon::Mod::InstallModFromZip(path, title_id)) {
QtCommon::Frontend::Information(tr("Mod Installed"), tr("Mod was successfully installed."));
LoadConfiguration();
} else {
QtCommon::Frontend::Critical(tr("Mod Install Failed"), tr("Mod install was unsuccessful. Check the log for details."));
}
}
void ConfigurePerGameAddons::changeEvent(QEvent* event) {
if (event->type() == QEvent::LanguageChange) {
RetranslateUI();

4
src/yuzu/configuration/configure_per_game_addons.h

@ -7,6 +7,7 @@
#include <vector>
#include <QList>
#include <QWidget>
#include "core/file_sys/vfs/vfs_types.h"
@ -38,6 +39,9 @@ public:
void SetTitleId(u64 id);
public slots:
void InstallModFolder();
void InstallModZip();
private:
void changeEvent(QEvent* event) override;
void RetranslateUI();

18
src/yuzu/configuration/configure_per_game_addons.ui

@ -17,7 +17,21 @@
<string>Add-Ons</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<item row="1" column="0">
<widget class="QPushButton" name="zip">
<property name="text">
<string>Import Mod from ZIP</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="folder">
<property name="text">
<string>Import Mod from Folder</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
@ -28,7 +42,7 @@
<x>0</x>
<y>0</y>
<width>380</width>
<height>280</height>
<height>249</height>
</rect>
</property>
</widget>

Loading…
Cancel
Save