#include "scripting.h" #include "log.h" QMap callbackFunctions = { {OnProjectOpened, "on_project_opened"}, {OnBlockChanged, "on_block_changed"}, {OnMapOpened, "on_map_opened"}, }; Scripting *instance = nullptr; void Scripting::init(MainWindow *mainWindow) { instance = new Scripting(mainWindow); } 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"); this->loadModules(this->filepaths); } 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; } 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; } } } 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); } void Scripting::cb_MetatileChanged(int x, int y, Block prevBlock, Block newBlock) { if (!instance) return; QJSValueList args { x, y, instance->fromBlock(prevBlock), instance->fromBlock(newBlock), }; instance->invokeCallback(OnBlockChanged, args); } void Scripting::cb_MapOpened(QString mapName) { if (!instance) return; QJSValueList args { mapName, }; instance->invokeCallback(OnMapOpened, args); } QJSValue Scripting::fromBlock(Block block) { QJSValue obj = instance->engine->newObject(); obj.setProperty("metatileId", block.tile); obj.setProperty("collision", block.collision); obj.setProperty("elevation", block.elevation); obj.setProperty("rawValue", block.rawValue()); return obj; } QJSValue Scripting::dimensions(int width, int height) { QJSValue obj = instance->engine->newObject(); obj.setProperty("width", width); obj.setProperty("height", height); return obj; } QJSEngine *Scripting::getEngine() { return instance->engine; }