mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-12-08 21:17:53 +00:00
Migrate over to Qt 6 so that we can keep the UI toolkit pegged at the current major version. Unfortunately this also means we have to gut a small feature in the progress dialogs, since the extras module doesn't exist in Qt6 anymore. Few things of note: QVector<> is internally an alias of QList now, so any changeover is due to that to make the semantics a little clearer. QtConcurrent requires arguments to be swapped on some invocations, and discarding instances need to use the global thread pool instead. fromStdList(), etc can be replaced with range constructors. --no-angle and other commands are removed from newer versions of windeployqt QVariant::Invalid (and other type IDs) are deprecated and also break existing functionality. Instead we can return default constructed QVariants where applicable, which restores functionality that would be broken if left as is (e.g. many list would straight up not populate or have wonky size hinting). The reason for this is that the QVariant(QVariant::Type) constructor models a unique kind of internal QVariant state where it's considered to be in an invalid state, but accessing the (supposedly) invalid state will instead return a default constructed value of the internal type. This kinda sucks because this means genuinely invalid states that would warrant an assertion or other type of error would be silently ignored and execution would continue on as normal, so this also enforces correctness a little bit (on top of, well, fixing all the broken UI controls).
210 lines
7.0 KiB
C++
210 lines
7.0 KiB
C++
#include "CProjectSettingsDialog.h"
|
|
#include "ui_CProjectSettingsDialog.h"
|
|
#include "CEditorApplication.h"
|
|
#include "CExportGameDialog.h"
|
|
#include "CProgressDialog.h"
|
|
#include "NDolphinIntegration.h"
|
|
#include "UICommon.h"
|
|
#include "Editor/ResourceBrowser/CResourceBrowser.h"
|
|
#include <Common/Macros.h>
|
|
#include <Core/GameProject/CGameExporter.h>
|
|
#include <Core/GameProject/COpeningBanner.h>
|
|
|
|
#include <nod/nod.hpp>
|
|
|
|
#include <QFileDialog>
|
|
#include <QFuture>
|
|
#include <QFutureWatcher>
|
|
#include <QMessageBox>
|
|
#include <QtConcurrentRun>
|
|
|
|
CProjectSettingsDialog::CProjectSettingsDialog(QWidget *pParent)
|
|
: QDialog(pParent)
|
|
, mpUI(std::make_unique<Ui::CProjectSettingsDialog>())
|
|
{
|
|
mpUI->setupUi(this);
|
|
|
|
connect(mpUI->GameNameLineEdit, &QLineEdit::editingFinished, this, &CProjectSettingsDialog::GameNameChanged);
|
|
connect(mpUI->CookPackageButton, &QPushButton::clicked, this, &CProjectSettingsDialog::CookPackage);
|
|
connect(mpUI->CookAllDirtyPackagesButton, &QPushButton::clicked, this, &CProjectSettingsDialog::CookAllDirtyPackages);
|
|
connect(mpUI->BuildIsoButton, &QPushButton::clicked, this, &CProjectSettingsDialog::BuildISO);
|
|
|
|
connect(gpEdApp, &CEditorApplication::ActiveProjectChanged, this, &CProjectSettingsDialog::ActiveProjectChanged);
|
|
connect(gpEdApp, &CEditorApplication::AssetsModified, this, &CProjectSettingsDialog::SetupPackagesList);
|
|
connect(gpEdApp, &CEditorApplication::PackagesCooked, this, &CProjectSettingsDialog::SetupPackagesList);
|
|
|
|
// Set build ISO button color
|
|
QPalette Palette = mpUI->BuildIsoButton->palette();
|
|
QBrush ButtonBrush = Palette.button();
|
|
ButtonBrush.setColor( UICommon::kImportantButtonColor );
|
|
Palette.setBrush(QPalette::Button, ButtonBrush);
|
|
mpUI->BuildIsoButton->setPalette(Palette);
|
|
}
|
|
|
|
CProjectSettingsDialog::~CProjectSettingsDialog() = default;
|
|
|
|
void CProjectSettingsDialog::ActiveProjectChanged(CGameProject *pProj)
|
|
{
|
|
mpProject = pProj;
|
|
|
|
if (mpProject)
|
|
{
|
|
// Set up project info
|
|
mpUI->ProjectNameLineEdit->setText(TO_QSTRING(pProj->Name()));
|
|
mpUI->GameLineEdit->setText(TO_QSTRING(GetGameName(pProj->Game())));
|
|
mpUI->GameIdLineEdit->setText(TO_QSTRING(pProj->GameID()));
|
|
|
|
const float BuildVer = pProj->BuildVersion();
|
|
const ERegion Region = pProj->Region();
|
|
const TString RegionName = TEnumReflection<ERegion>::ConvertValueToString(Region);
|
|
const TString BuildName = pProj->GameInfo()->GetBuildName(BuildVer, Region);
|
|
mpUI->BuildLineEdit->setText(tr("%1 (%2)").arg(BuildVer).arg(TO_QSTRING(BuildName)));
|
|
mpUI->RegionLineEdit->setText(TO_QSTRING(RegionName));
|
|
|
|
// Banner info
|
|
const COpeningBanner Banner(pProj);
|
|
mpUI->GameNameLineEdit->setText(TO_QSTRING(Banner.EnglishGameName()));
|
|
mpUI->GameNameLineEdit->setMaxLength(Banner.MaxGameNameLength());
|
|
}
|
|
else
|
|
{
|
|
// Clear project info
|
|
mpUI->ProjectNameLineEdit->clear();
|
|
mpUI->GameLineEdit->clear();
|
|
mpUI->GameIdLineEdit->clear();
|
|
mpUI->BuildLineEdit->clear();
|
|
mpUI->RegionLineEdit->clear();
|
|
mpUI->GameNameLineEdit->clear();
|
|
close();
|
|
}
|
|
|
|
SetupPackagesList();
|
|
}
|
|
|
|
void CProjectSettingsDialog::GameNameChanged()
|
|
{
|
|
if (mpProject)
|
|
{
|
|
QString NewName = mpUI->GameNameLineEdit->text();
|
|
|
|
COpeningBanner Banner(mpProject);
|
|
Banner.SetEnglishGameName( TO_TSTRING(NewName) );
|
|
Banner.Save();
|
|
}
|
|
}
|
|
|
|
void CProjectSettingsDialog::SetupPackagesList()
|
|
{
|
|
mpUI->PackagesList->clear();
|
|
if (!mpProject) return;
|
|
|
|
for (size_t iPkg = 0; iPkg < mpProject->NumPackages(); iPkg++)
|
|
{
|
|
CPackage *pPackage = mpProject->PackageByIndex(iPkg);
|
|
ASSERT(pPackage != nullptr);
|
|
|
|
QString PackageName = TO_QSTRING(pPackage->Name());
|
|
if (pPackage->NeedsRecook())
|
|
PackageName += '*';
|
|
mpUI->PackagesList->addItem(PackageName);
|
|
}
|
|
}
|
|
|
|
void CProjectSettingsDialog::CookPackage()
|
|
{
|
|
const auto PackageIdx = static_cast<uint32>(mpUI->PackagesList->currentRow());
|
|
|
|
if (PackageIdx == UINT32_MAX)
|
|
return;
|
|
|
|
CPackage *pPackage = mpProject->PackageByIndex(PackageIdx);
|
|
gpEdApp->CookPackage(pPackage);
|
|
}
|
|
|
|
void CProjectSettingsDialog::CookAllDirtyPackages()
|
|
{
|
|
gpEdApp->CookAllDirtyPackages();
|
|
}
|
|
|
|
void CProjectSettingsDialog::BuildISO()
|
|
{
|
|
CGameProject *pProj = gpEdApp->ActiveProject();
|
|
ASSERT(pProj);
|
|
|
|
QString DefaultExtension, FilterString;
|
|
|
|
if (!pProj->IsWiiBuild())
|
|
{
|
|
DefaultExtension = QStringLiteral(".gcm");
|
|
FilterString = QStringLiteral("*.gcm;*.iso");
|
|
}
|
|
else
|
|
{
|
|
DefaultExtension = QStringLiteral(".iso");
|
|
FilterString = QStringLiteral("*.iso");
|
|
}
|
|
|
|
QString DefaultPath = TO_QSTRING( pProj->ProjectRoot() + FileUtil::SanitizeName(pProj->Name(), false) ) + DefaultExtension;
|
|
QString IsoPath = UICommon::SaveFileDialog(this, tr("Choose output ISO path"), FilterString, DefaultPath);
|
|
|
|
if (!IsoPath.isEmpty())
|
|
{
|
|
bool NeedsDiscMerge = pProj->IsWiiDeAsobu() || pProj->IsTrilogy();
|
|
std::unique_ptr<nod::DiscBase> pBaseDisc = nullptr;
|
|
|
|
if (NeedsDiscMerge)
|
|
{
|
|
FilterString += QStringLiteral(";*.wbfs;*.nfs");
|
|
QString SourceIsoPath = UICommon::OpenFileDialog(this, tr("Select the original ISO"), FilterString, DefaultPath);
|
|
|
|
if (SourceIsoPath.isEmpty())
|
|
return;
|
|
|
|
// Verify this ISO matches the original
|
|
bool IsWii;
|
|
pBaseDisc = nod::OpenDiscFromImage(QStringToNodString(SourceIsoPath), IsWii);
|
|
|
|
if (!pBaseDisc || !IsWii)
|
|
{
|
|
UICommon::ErrorMsg(this, tr("The ISO provided is not a valid Wii ISO!"));
|
|
return;
|
|
}
|
|
|
|
const nod::Header& rkHeader = pBaseDisc->getHeader();
|
|
TString GameID = pProj->GameID();
|
|
|
|
if (strncmp(*GameID, rkHeader.m_gameID, 6) != 0)
|
|
{
|
|
UICommon::ErrorMsg(this, tr("The ISO provided doesn't match the project!"));
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (gpEdApp->CookAllDirtyPackages())
|
|
{
|
|
// Make sure there will be no leftover quickplay files in the built ISO
|
|
NDolphinIntegration::CleanupQuickplayFiles(pProj);
|
|
|
|
CProgressDialog Dialog(tr("Building ISO"), false, true, this);
|
|
Dialog.DisallowCanceling();
|
|
bool Success;
|
|
|
|
if (!NeedsDiscMerge)
|
|
{
|
|
QFuture<bool> Future = QtConcurrent::run(&CGameProject::BuildISO, pProj, TO_TSTRING(IsoPath), &Dialog);
|
|
Success = Dialog.WaitForResults(Future);
|
|
}
|
|
else
|
|
{
|
|
QFuture<bool> Future = QtConcurrent::run(&CGameProject::MergeISO, pProj, TO_TSTRING(IsoPath), (nod::DiscWii*)pBaseDisc.get(), &Dialog);
|
|
Success = Dialog.WaitForResults(Future);
|
|
}
|
|
|
|
if (Success)
|
|
UICommon::InfoMsg(this, tr("Success"), tr("ISO built successfully!"));
|
|
else
|
|
UICommon::ErrorMsg(this, tr("ISO build failed!"));
|
|
}
|
|
}
|
|
}
|