Add custom_scripts project config, and cleanup scripts when switching projects

This commit is contained in:
Marcus Huderle 2020-05-08 11:26:23 -05:00
parent b8d0268d5d
commit 998ea1fcc8
7 changed files with 75 additions and 15 deletions

View file

@ -113,6 +113,7 @@ public:
this->baseGameVersion = BaseGameVersion::pokeemerald;
this->useEncounterJson = true;
this->useCustomBorderSize = false;
this->customScripts.clear();
}
void setBaseGameVersion(BaseGameVersion baseGameVersion);
BaseGameVersion getBaseGameVersion();
@ -121,8 +122,11 @@ public:
void setUsePoryScript(bool usePoryScript);
bool getUsePoryScript();
void setProjectDir(QString projectDir);
QString getProjectDir();
void setUseCustomBorderSize(bool enable);
bool getUseCustomBorderSize();
void setCustomScripts(QList<QString> scripts);
QList<QString> getCustomScripts();
protected:
virtual QString getConfigFilepath() override;
virtual void parseConfigKeyValue(QString key, QString value) override;
@ -134,6 +138,7 @@ private:
bool useEncounterJson;
bool usePoryScript;
bool useCustomBorderSize;
QList<QString> customScripts;
};
extern ProjectConfig projectConfig;

View file

@ -253,6 +253,8 @@ private:
DraggablePixmapItem *selectedBG;
DraggablePixmapItem *selectedHealspot;
QList<QAction *> registeredActions;
bool isProgrammaticEventTabChange;
bool projectHasUnsavedChanges;

View file

@ -9,6 +9,7 @@
enum CallbackType {
OnProjectOpened,
OnProjectClosed,
OnBlockChanged,
OnMapOpened,
};
@ -25,6 +26,7 @@ public:
static int numRegisteredActions();
static void invokeAction(QString actionName);
static void cb_ProjectOpened(QString projectPath);
static void cb_ProjectClosed(QString projectPath);
static void cb_MetatileChanged(int x, int y, Block prevBlock, Block newBlock);
static void cb_MapOpened(QString mapName);

View file

@ -36,7 +36,7 @@ void KeyValueConfigBase::load() {
QTextStream in(&file);
in.setCodec("UTF-8");
QList<QString> configLines;
QRegularExpression re("^(?<key>.+)=(?<value>.+)$");
QRegularExpression re("^(?<key>.+)=(?<value>.*)$");
while (!in.atEnd()) {
QString line = in.readLine().trimmed();
int commentIndex = line.indexOf("#");
@ -380,6 +380,15 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
if (!ok) {
logWarn(QString("Invalid config value for use_custom_border_size: '%1'. Must be 0 or 1.").arg(value));
}
} else if (key == "custom_scripts") {
this->customScripts.clear();
QList<QString> paths = value.split(",");
paths.removeDuplicates();
for (QString script : paths) {
if (!script.isEmpty()) {
this->customScripts.append(script);
}
}
} else {
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
}
@ -391,6 +400,7 @@ QMap<QString, QString> ProjectConfig::getKeyValueMap() {
map.insert("use_encounter_json", QString::number(this->useEncounterJson));
map.insert("use_poryscript", QString::number(this->usePoryScript));
map.insert("use_custom_border_size", QString::number(this->useCustomBorderSize));
map.insert("custom_scripts", this->customScripts.join(","));
return map;
}
@ -423,12 +433,17 @@ void ProjectConfig::onNewConfigFileCreated() {
this->useCustomBorderSize = this->baseGameVersion == BaseGameVersion::pokefirered;
this->useEncounterJson = true;
this->usePoryScript = false;
this->customScripts.clear();
}
void ProjectConfig::setProjectDir(QString projectDir) {
this->projectDir = projectDir;
}
QString ProjectConfig::getProjectDir() {
return this->projectDir;
}
void ProjectConfig::setBaseGameVersion(BaseGameVersion baseGameVersion) {
this->baseGameVersion = baseGameVersion;
this->save();
@ -464,3 +479,12 @@ void ProjectConfig::setUseCustomBorderSize(bool enable) {
bool ProjectConfig::getUseCustomBorderSize() {
return this->useCustomBorderSize;
}
void ProjectConfig::setCustomScripts(QList<QString> scripts) {
this->customScripts = scripts;
this->save();
}
QList<QString> ProjectConfig::getCustomScripts() {
return this->customScripts;
}

View file

@ -46,7 +46,6 @@ MainWindow::MainWindow(QWidget *parent) :
QCoreApplication::setApplicationName("porymap");
QApplication::setApplicationDisplayName("porymap");
QApplication::setWindowIcon(QIcon(":/icons/porymap-icon-2.ico"));
Scripting::init(this);
ui->setupUi(this);
this->initWindow();
@ -349,6 +348,10 @@ bool MainWindow::openProject(QString dir) {
}
if (success) {
for (auto action : this->registeredActions) {
this->ui->menuTools->removeAction(action);
}
Scripting::init(this);
Scripting::cb_ProjectOpened(dir);
}
@ -395,6 +398,7 @@ void MainWindow::on_action_Open_Project_triggered()
}
QString dir = getExistingDirectory(recent);
if (!dir.isEmpty()) {
Scripting::cb_ProjectClosed(this->editor->project->root);
porymapConfig.setRecentProject(dir);
if (!openProject(dir)) {
this->initWindow();

View file

@ -434,7 +434,8 @@ void MainWindow::registerAction(QString functionName, QString actionName, QStrin
Scripting::registerAction(functionName, actionName);
if (Scripting::numRegisteredActions() == 1) {
this->ui->menuTools->addSection("Custom Actions");
QAction *section = this->ui->menuTools->addSection("Custom Actions");
this->registeredActions.append(section);
}
QAction *action = this->ui->menuTools->addAction(actionName, [actionName](){
Scripting::invokeAction(actionName);
@ -442,6 +443,7 @@ void MainWindow::registerAction(QString functionName, QString actionName, QStrin
if (!shortcut.isEmpty()) {
action->setShortcut(QKeySequence(shortcut));
}
this->registeredActions.append(action);
}
void MainWindow::setTimeout(QJSValue callback, int milliseconds) {

View file

@ -2,14 +2,19 @@
#include "log.h"
QMap<CallbackType, QString> callbackFunctions = {
{OnProjectOpened, "on_project_opened"},
{OnBlockChanged, "on_block_changed"},
{OnMapOpened, "on_map_opened"},
{OnProjectOpened, "onProjectOpened"},
{OnProjectClosed, "onProjectClosed"},
{OnBlockChanged, "onBlockChanged"},
{OnMapOpened, "onMapOpened"},
};
Scripting *instance = nullptr;
void Scripting::init(MainWindow *mainWindow) {
if (instance) {
instance->engine->setInterrupted(true);
delete instance;
}
instance = new Scripting(mainWindow);
}
@ -17,7 +22,9 @@ Scripting::Scripting(MainWindow *mainWindow) {
this->engine = new QJSEngine(mainWindow);
this->engine->installExtensions(QJSEngine::ConsoleExtension);
this->engine->globalObject().setProperty("map", this->engine->newQObject(mainWindow));
this->filepaths.append("D:\\devkitProOld\\msys\\home\\huder\\pretmap\\test_script.js");
for (QString script : projectConfig.getCustomScripts()) {
this->filepaths.append(script);
}
this->loadModules(this->filepaths);
}
@ -25,16 +32,21 @@ void Scripting::loadModules(QStringList moduleFiles) {
for (QString filepath : moduleFiles) {
QJSValue module = this->engine->importModule(filepath);
if (module.isError()) {
logError(QString("Failed to load custom script file '%1'\nName: %2\nMessage: %3\nFile: %4\nLine Number: %5\nStack: %6")
.arg(filepath)
.arg(module.property("name").toString())
.arg(module.property("message").toString())
.arg(module.property("fileName").toString())
.arg(module.property("lineNumber").toString())
.arg(module.property("stack").toString()));
continue;
QString relativePath = QDir::cleanPath(projectConfig.getProjectDir() + QDir::separator() + filepath);
module = this->engine->importModule(relativePath);
if (module.isError()) {
logError(QString("Failed to load custom script file '%1'\nName: %2\nMessage: %3\nFile: %4\nLine Number: %5\nStack: %6")
.arg(filepath)
.arg(module.property("name").toString())
.arg(module.property("message").toString())
.arg(module.property("fileName").toString())
.arg(module.property("lineNumber").toString())
.arg(module.property("stack").toString()));
continue;
}
}
logInfo(QString("Successfully loaded custom script file '%1'").arg(filepath));
this->modules.append(module);
}
}
@ -93,6 +105,15 @@ void Scripting::cb_ProjectOpened(QString projectPath) {
instance->invokeCallback(OnProjectOpened, args);
}
void Scripting::cb_ProjectClosed(QString projectPath) {
if (!instance) return;
QJSValueList args {
projectPath,
};
instance->invokeCallback(OnProjectClosed, args);
}
void Scripting::cb_MetatileChanged(int x, int y, Block prevBlock, Block newBlock) {
if (!instance) return;