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

View file

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

View file

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

View file

@ -36,7 +36,7 @@ void KeyValueConfigBase::load() {
QTextStream in(&file); QTextStream in(&file);
in.setCodec("UTF-8"); in.setCodec("UTF-8");
QList<QString> configLines; QList<QString> configLines;
QRegularExpression re("^(?<key>.+)=(?<value>.+)$"); QRegularExpression re("^(?<key>.+)=(?<value>.*)$");
while (!in.atEnd()) { while (!in.atEnd()) {
QString line = in.readLine().trimmed(); QString line = in.readLine().trimmed();
int commentIndex = line.indexOf("#"); int commentIndex = line.indexOf("#");
@ -380,6 +380,15 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
if (!ok) { if (!ok) {
logWarn(QString("Invalid config value for use_custom_border_size: '%1'. Must be 0 or 1.").arg(value)); 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 { } else {
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key)); 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_encounter_json", QString::number(this->useEncounterJson));
map.insert("use_poryscript", QString::number(this->usePoryScript)); map.insert("use_poryscript", QString::number(this->usePoryScript));
map.insert("use_custom_border_size", QString::number(this->useCustomBorderSize)); map.insert("use_custom_border_size", QString::number(this->useCustomBorderSize));
map.insert("custom_scripts", this->customScripts.join(","));
return map; return map;
} }
@ -423,12 +433,17 @@ void ProjectConfig::onNewConfigFileCreated() {
this->useCustomBorderSize = this->baseGameVersion == BaseGameVersion::pokefirered; this->useCustomBorderSize = this->baseGameVersion == BaseGameVersion::pokefirered;
this->useEncounterJson = true; this->useEncounterJson = true;
this->usePoryScript = false; this->usePoryScript = false;
this->customScripts.clear();
} }
void ProjectConfig::setProjectDir(QString projectDir) { void ProjectConfig::setProjectDir(QString projectDir) {
this->projectDir = projectDir; this->projectDir = projectDir;
} }
QString ProjectConfig::getProjectDir() {
return this->projectDir;
}
void ProjectConfig::setBaseGameVersion(BaseGameVersion baseGameVersion) { void ProjectConfig::setBaseGameVersion(BaseGameVersion baseGameVersion) {
this->baseGameVersion = baseGameVersion; this->baseGameVersion = baseGameVersion;
this->save(); this->save();
@ -464,3 +479,12 @@ void ProjectConfig::setUseCustomBorderSize(bool enable) {
bool ProjectConfig::getUseCustomBorderSize() { bool ProjectConfig::getUseCustomBorderSize() {
return this->useCustomBorderSize; 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"); QCoreApplication::setApplicationName("porymap");
QApplication::setApplicationDisplayName("porymap"); QApplication::setApplicationDisplayName("porymap");
QApplication::setWindowIcon(QIcon(":/icons/porymap-icon-2.ico")); QApplication::setWindowIcon(QIcon(":/icons/porymap-icon-2.ico"));
Scripting::init(this);
ui->setupUi(this); ui->setupUi(this);
this->initWindow(); this->initWindow();
@ -349,6 +348,10 @@ bool MainWindow::openProject(QString dir) {
} }
if (success) { if (success) {
for (auto action : this->registeredActions) {
this->ui->menuTools->removeAction(action);
}
Scripting::init(this);
Scripting::cb_ProjectOpened(dir); Scripting::cb_ProjectOpened(dir);
} }
@ -395,6 +398,7 @@ void MainWindow::on_action_Open_Project_triggered()
} }
QString dir = getExistingDirectory(recent); QString dir = getExistingDirectory(recent);
if (!dir.isEmpty()) { if (!dir.isEmpty()) {
Scripting::cb_ProjectClosed(this->editor->project->root);
porymapConfig.setRecentProject(dir); porymapConfig.setRecentProject(dir);
if (!openProject(dir)) { if (!openProject(dir)) {
this->initWindow(); this->initWindow();

View file

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

View file

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