2020-04-27 01:38:20 +01:00
|
|
|
#include "scripting.h"
|
|
|
|
#include "log.h"
|
|
|
|
|
|
|
|
QMap<CallbackType, QString> callbackFunctions = {
|
2020-05-08 17:26:23 +01:00
|
|
|
{OnProjectOpened, "onProjectOpened"},
|
|
|
|
{OnProjectClosed, "onProjectClosed"},
|
|
|
|
{OnBlockChanged, "onBlockChanged"},
|
|
|
|
{OnMapOpened, "onMapOpened"},
|
2020-04-27 01:38:20 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
Scripting *instance = nullptr;
|
|
|
|
|
|
|
|
void Scripting::init(MainWindow *mainWindow) {
|
2020-05-08 17:26:23 +01:00
|
|
|
if (instance) {
|
|
|
|
instance->engine->setInterrupted(true);
|
|
|
|
delete instance;
|
|
|
|
}
|
2020-04-27 01:38:20 +01:00
|
|
|
instance = new Scripting(mainWindow);
|
|
|
|
}
|
|
|
|
|
|
|
|
Scripting::Scripting(MainWindow *mainWindow) {
|
|
|
|
this->engine = new QJSEngine(mainWindow);
|
|
|
|
this->engine->installExtensions(QJSEngine::ConsoleExtension);
|
2020-04-30 02:41:19 +01:00
|
|
|
this->engine->globalObject().setProperty("map", this->engine->newQObject(mainWindow));
|
2020-05-08 17:26:23 +01:00
|
|
|
for (QString script : projectConfig.getCustomScripts()) {
|
|
|
|
this->filepaths.append(script);
|
|
|
|
}
|
2020-04-27 01:38:20 +01:00
|
|
|
this->loadModules(this->filepaths);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Scripting::loadModules(QStringList moduleFiles) {
|
|
|
|
for (QString filepath : moduleFiles) {
|
|
|
|
QJSValue module = this->engine->importModule(filepath);
|
|
|
|
if (module.isError()) {
|
2020-05-08 17:26:23 +01:00
|
|
|
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;
|
|
|
|
}
|
2020-04-27 01:38:20 +01:00
|
|
|
}
|
|
|
|
|
2020-05-08 17:26:23 +01:00
|
|
|
logInfo(QString("Successfully loaded custom script file '%1'").arg(filepath));
|
2020-04-27 01:38:20 +01:00
|
|
|
this->modules.append(module);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Scripting::invokeCallback(CallbackType type, QJSValueList args) {
|
|
|
|
for (QJSValue module : this->modules) {
|
|
|
|
QString functionName = callbackFunctions[type];
|
|
|
|
QJSValue callbackFunction = module.property(functionName);
|
|
|
|
if (callbackFunction.isError()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
QJSValue result = callbackFunction.call(args);
|
|
|
|
if (result.isError()) {
|
|
|
|
logError(QString("Module %1 encountered an error when calling '%2'").arg(module.toString()).arg(functionName));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-03 17:28:02 +01:00
|
|
|
void Scripting::registerAction(QString functionName, QString actionName) {
|
|
|
|
if (!instance) return;
|
|
|
|
instance->registeredActions.insert(actionName, functionName);
|
|
|
|
}
|
|
|
|
|
|
|
|
int Scripting::numRegisteredActions() {
|
|
|
|
if (!instance) return 0;
|
|
|
|
return instance->registeredActions.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Scripting::invokeAction(QString actionName) {
|
|
|
|
if (!instance) return;
|
|
|
|
if (!instance->registeredActions.contains(actionName)) return;
|
|
|
|
|
|
|
|
QString functionName = instance->registeredActions.value(actionName);
|
|
|
|
for (QJSValue module : instance->modules) {
|
|
|
|
QJSValue callbackFunction = module.property(functionName);
|
|
|
|
if (callbackFunction.isError()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
QJSValue result = callbackFunction.call(QJSValueList());
|
|
|
|
if (result.isError()) {
|
|
|
|
logError(QString("Module %1 encountered an error when calling '%2'").arg(module.toString()).arg(functionName));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Scripting::cb_ProjectOpened(QString projectPath) {
|
|
|
|
if (!instance) return;
|
|
|
|
|
|
|
|
QJSValueList args {
|
|
|
|
projectPath,
|
|
|
|
};
|
|
|
|
instance->invokeCallback(OnProjectOpened, args);
|
|
|
|
}
|
|
|
|
|
2020-05-08 17:26:23 +01:00
|
|
|
void Scripting::cb_ProjectClosed(QString projectPath) {
|
|
|
|
if (!instance) return;
|
|
|
|
|
|
|
|
QJSValueList args {
|
|
|
|
projectPath,
|
|
|
|
};
|
|
|
|
instance->invokeCallback(OnProjectClosed, args);
|
|
|
|
}
|
|
|
|
|
2020-04-27 01:38:20 +01:00
|
|
|
void Scripting::cb_MetatileChanged(int x, int y, Block prevBlock, Block newBlock) {
|
|
|
|
if (!instance) return;
|
|
|
|
|
|
|
|
QJSValueList args {
|
|
|
|
x,
|
|
|
|
y,
|
2020-04-30 02:41:19 +01:00
|
|
|
instance->fromBlock(prevBlock),
|
|
|
|
instance->fromBlock(newBlock),
|
2020-04-27 01:38:20 +01:00
|
|
|
};
|
|
|
|
instance->invokeCallback(OnBlockChanged, args);
|
|
|
|
}
|
|
|
|
|
2020-05-02 22:25:35 +01:00
|
|
|
void Scripting::cb_MapOpened(QString mapName) {
|
|
|
|
if (!instance) return;
|
|
|
|
|
|
|
|
QJSValueList args {
|
|
|
|
mapName,
|
|
|
|
};
|
|
|
|
instance->invokeCallback(OnMapOpened, args);
|
|
|
|
}
|
|
|
|
|
2020-04-30 02:41:19 +01:00
|
|
|
QJSValue Scripting::fromBlock(Block block) {
|
|
|
|
QJSValue obj = instance->engine->newObject();
|
2020-05-02 22:25:35 +01:00
|
|
|
obj.setProperty("metatileId", block.tile);
|
2020-04-27 01:38:20 +01:00
|
|
|
obj.setProperty("collision", block.collision);
|
|
|
|
obj.setProperty("elevation", block.elevation);
|
|
|
|
obj.setProperty("rawValue", block.rawValue());
|
|
|
|
return obj;
|
|
|
|
}
|
2020-05-01 00:30:24 +01:00
|
|
|
|
|
|
|
QJSValue Scripting::dimensions(int width, int height) {
|
|
|
|
QJSValue obj = instance->engine->newObject();
|
|
|
|
obj.setProperty("width", width);
|
|
|
|
obj.setProperty("height", height);
|
|
|
|
return obj;
|
|
|
|
}
|
2020-05-03 16:00:56 +01:00
|
|
|
|
|
|
|
QJSEngine *Scripting::getEngine() {
|
|
|
|
return instance->engine;
|
|
|
|
}
|