Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.25 FATAL_ERROR)
# Create project
project(sdk_launcher
DESCRIPTION "An SDK launcher for Strata Source engine games"
VERSION "1.0.1"
VERSION "1.1.0"
HOMEPAGE_URL "https://github.com/StrataSource/sdk-launcher")
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,12 @@ Here is an example config file that may be loaded into the SDK launcher.
"window_height": 300,
// Optional, holds the download URL of the mod template for the game (must point to a zip file)
// For reference, this is the P2CE template mod download URL:
"mod_template_url": "https://github.com/StrataSource/p2ce-mod-template/archive/refs/heads/main.zip",
//"mod_template_url": "https://github.com/StrataSource/p2ce-mod-template/archive/refs/heads/main.zip",
// OR it can be a JSON object if there are multiple mod templates:
"mod_template_url": {
"Full Support (HL2/P1/P2)": "https://github.com/StrataSource/p2ce-mod-template/archive/refs/heads/main.zip",
"Lite Support (Portal 2)": "https://github.com/StrataSource/p2ce-mod-template/archive/refs/heads/feat/lite.zip"
},
// Optional, the default is false (enables P2CE-style addons)
"supports_p2ce_addons": false,
// Sections hold titled groups of buttons
Expand Down
5 changes: 4 additions & 1 deletion res/config/p2ce.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
"game_default": "p2ce",
"window_width": 308,
"window_height": 621,
"mod_template_url": "https://github.com/StrataSource/p2ce-mod-template/archive/refs/heads/main.zip",
"mod_template_url": {
"Full Support (HL2/P1/P2)": "https://github.com/StrataSource/p2ce-mod-template/archive/refs/heads/main.zip",
"Lite Support (Portal 2)": "https://github.com/StrataSource/p2ce-mod-template/archive/refs/heads/feat/lite.zip"
},
"supports_p2ce_addons": true,
"sections": [
{
Expand Down
16 changes: 14 additions & 2 deletions src/GameConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ GameConfig::OS GameConfig::osFromString(const QString& string) {
if (string.contains("linux")) {
out |= static_cast<unsigned char>(LINUX);
}
if (string.contains("macos")) {
out |= static_cast<unsigned char>(MACOS);
}
if (out == static_cast<unsigned char>(NONE)) {
out = static_cast<unsigned char>(ALL);
}
Expand Down Expand Up @@ -76,8 +79,17 @@ std::optional<GameConfig> GameConfig::parse(const QString& path) {
gameConfig.windowHeight = configObject["window_height"].toInt(DEFAULT_WINDOW_HEIGHT);
}

if (configObject.contains("mod_template_url") && configObject["mod_template_url"].isString()) {
gameConfig.modTemplateURL = configObject["mod_template_url"].toString();
if (configObject.contains("mod_template_url")) {
if (configObject["mod_template_url"].isString()) {
gameConfig.modTemplateURL["Mod Template"] = configObject["mod_template_url"].toString();
} else if (configObject["mod_template_url"].isObject()) {
for (
const auto& modTemplateObject = configObject["mod_template_url"].toObject().toVariantMap();
const auto& [desc, url] : modTemplateObject.asKeyValueRange()
) {
gameConfig.modTemplateURL[desc] = url.toString();
}
}
}

if (configObject.contains("supports_p2ce_addons") && configObject["supports_p2ce_addons"].isBool()) {
Expand Down
8 changes: 5 additions & 3 deletions src/GameConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <optional>
#include <QList>
#include <QMap>
#include <QString>

constexpr int DEFAULT_WINDOW_WIDTH = 256;
Expand All @@ -22,7 +23,8 @@ class GameConfig {
NONE = 0,
WINDOWS = 1 << 0,
LINUX = 1 << 1,
ALL = WINDOWS | LINUX,
MACOS = 1 << 2,
ALL = WINDOWS | LINUX | MACOS,
};

[[nodiscard]] static OS osFromString(const QString& string);
Expand Down Expand Up @@ -52,7 +54,7 @@ class GameConfig {

[[nodiscard]] int getWindowHeight() const { return this->windowHeight; }

[[nodiscard]] const QString& getModTemplateURL() const { return this->modTemplateURL; }
[[nodiscard]] const QMap<QString, QString>& getModTemplateURL() const { return this->modTemplateURL; }

[[nodiscard]] bool supportsP2CEAddons() const { return this->p2ceAddonsSupported; }

Expand All @@ -66,7 +68,7 @@ class GameConfig {
bool usesLegacyBinDir = false;
int windowWidth = DEFAULT_WINDOW_WIDTH;
int windowHeight = DEFAULT_WINDOW_HEIGHT;
QString modTemplateURL;
QMap<QString, QString> modTemplateURL;
bool p2ceAddonsSupported = false;
QList<Section> sections;

Expand Down
37 changes: 26 additions & 11 deletions src/NewModDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <QDialogButtonBox>
#include <QDir>
#include <QFile>
#include <QFileDialog>
#include <QFormLayout>
#include <QLabel>
#include <QLineEdit>
Expand All @@ -19,6 +20,7 @@
#include <QNetworkReply>
#include <QProgressBar>
#include <QProgressDialog>
#include <QPushButton>
#include <QStandardPaths>

#include "Steam.h"
Expand Down Expand Up @@ -155,10 +157,25 @@ NewModDialog::NewModDialog(QString gameRoot_, QString downloadURL_, QWidget* par
this->parentFolder->addItem(tr("Custom Location"));
layout->addRow(tr("Install Location"), this->parentFolder);

auto* parentFolderCustomLabel = new QLabel{tr("Custom Location"), this};
this->parentFolderCustom = new QLineEdit{this};
this->parentFolderCustom->setPlaceholderText(tr("path/to/mod/parent/folder"));
layout->addRow(parentFolderCustomLabel, this->parentFolderCustom);
auto* parentFolderCustomParent = new QWidget{this};
auto* parentFolderCustomLayout = new QHBoxLayout{parentFolderCustomParent};
parentFolderCustomLayout->setSpacing(4);
parentFolderCustomLayout->setContentsMargins(0, 0, 0, 0);

this->parentFolderCustomPath = new QLineEdit{parentFolderCustomParent};
parentFolderCustomLayout->addWidget(this->parentFolderCustomPath);

auto* parentFolderCustomSearch = new QPushButton{parentFolderCustomParent};
parentFolderCustomSearch->setIcon(this->style()->standardIcon(QStyle::SP_DirOpenIcon));
parentFolderCustomLayout->addWidget(parentFolderCustomSearch);

QObject::connect(parentFolderCustomSearch, &QPushButton::clicked, this, [this] {
if (const auto path = QFileDialog::getExistingDirectory(this, tr("Select Parent Folder")); !path.isEmpty()) {
this->parentFolderCustomPath->setText(path);
}
});

layout->addRow(tr("Custom Location"), parentFolderCustomParent);

this->modID = new QLineEdit{this};
this->modID->setPlaceholderText(tr("For example: p2ce, revolution, portal2"));
Expand All @@ -179,12 +196,10 @@ NewModDialog::NewModDialog(QString gameRoot_, QString downloadURL_, QWidget* par
this->network = new QNetworkAccessManager{this};

// We want the custom input to be invisible unless the combo box is on the custom option
parentFolderCustomLabel->hide();
this->parentFolderCustom->hide();
QObject::connect(this->parentFolder, &QComboBox::currentIndexChanged, this, [this, knowsSourcemodsDirLocation, parentFolderCustomLabel](int index) {
layout->setRowVisible(parentFolderCustomParent, false);
QObject::connect(this->parentFolder, &QComboBox::currentIndexChanged, this, [knowsSourcemodsDirLocation, layout, parentFolderCustomParent](int index) {
const int customIndex = knowsSourcemodsDirLocation ? 2 : 1;
parentFolderCustomLabel->setVisible(index == customIndex);
this->parentFolderCustom->setVisible(index == customIndex);
layout->setRowVisible(parentFolderCustomParent, index == customIndex);
});

// Connect ok/cancel buttons to download stuff
Expand Down Expand Up @@ -256,9 +271,9 @@ NewModDialog::NewModDialog(QString gameRoot_, QString downloadURL_, QWidget* par
// If installing to sourcemods, tell user they will need to restart steam
if (this->parentFolder->count() == 3 && this->parentFolder->currentIndex() == 0) {
QMessageBox::information(this, tr("Info"), tr("Your mod has been installed to Steam's SourceMods folder, which means it will show up in your Steam library! This requires you to restart Steam once."));
QDesktopServices::openUrl({QString("file:///") + modInstallDir});
}

QDesktopServices::openUrl(QUrl::fromLocalFile(modInstallDir));
this->accept();
});
});
Expand All @@ -277,7 +292,7 @@ QString NewModDialog::getModInstallDirParent() const {
return this->gameRoot;
default:
case 2:
return this->parentFolderCustom->text();
return this->parentFolderCustomPath->text();
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/NewModDialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public Q_SLOTS:
QString downloadURL;

QComboBox* parentFolder;
QLineEdit* parentFolderCustom;
QLineEdit* parentFolderCustomPath;
QLineEdit* modID;
QCheckBox* addShortcutOnDesktop;
QProgressBar* downloadProgress;
Expand Down
17 changes: 13 additions & 4 deletions src/Window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,7 @@ Window::Window(QWidget* parent)
// Utilities menu
auto* utilitiesMenu = this->menuBar()->addMenu(tr("Utilities"));

this->utilities_createNewMod = utilitiesMenu->addAction(this->style()->standardIcon(QStyle::SP_FileIcon), tr("Create New Mod"), [this] {
NewModDialog::open(::getRootPath(this->configUsingLegacyBinDir), this->configModTemplateURL, this);
});
this->utilities_createNewMod = utilitiesMenu->addMenu(this->style()->standardIcon(QStyle::SP_FileIcon), tr("Create New Mod"));

this->utilities_createNewAddon = utilitiesMenu->addAction(this->style()->standardIcon(QStyle::SP_FileIcon), tr("Create New Addon"), [this] {
QString gameRoot;
Expand Down Expand Up @@ -225,7 +223,18 @@ void Window::loadGameConfig(const QString& path) {

this->configUsingLegacyBinDir = gameConfig->getUsesLegacyBinDir();
this->configModTemplateURL = gameConfig->getModTemplateURL();
this->utilities_createNewMod->setDisabled(this->configModTemplateURL.isEmpty());

this->utilities_createNewMod->clear();
if (this->configModTemplateURL.isEmpty()) {
this->utilities_createNewMod->setDisabled(true);
} else {
for (const auto& [desc, url] : this->configModTemplateURL.asKeyValueRange()) {
this->utilities_createNewMod->addAction(desc, [this, url] {
NewModDialog::open(::getRootPath(this->configUsingLegacyBinDir), url, this);
});
}
}

this->utilities_createNewAddon->setDisabled(!gameConfig->supportsP2CEAddons());

auto recentConfigs = Options::get<QStringList>(STR_RECENT_CONFIGS);
Expand Down
4 changes: 2 additions & 2 deletions src/Window.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ class Window : public QMainWindow {
private:
QString gameDefault;
bool configUsingLegacyBinDir;
QString configModTemplateURL;
QMap<QString, QString> configModTemplateURL;

QMenu* recent;
QAction* config_loadDefault;
QAction* game_overrideGame;
QAction* game_resetToDefault;
QAction* utilities_createNewMod;
QMenu* utilities_createNewMod;
QAction* utilities_createNewAddon;

QWidget* main;
Expand Down
Loading