Implement three map scripting functions

This commit is contained in:
Marcus Huderle 2020-04-29 20:41:19 -05:00
parent 267cd5e2cb
commit d685718f8d
9 changed files with 57 additions and 22 deletions

View file

@ -74,7 +74,7 @@ public:
void cacheBlockdata(); void cacheBlockdata();
void cacheCollision(); void cacheCollision();
Block *getBlock(int x, int y); Block *getBlock(int x, int y);
void setBlock(int x, int y, Block block, bool invokeCallback = false); void setBlock(int x, int y, Block block, bool enableScriptCallback = false);
void floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation); void floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation);
void _floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation); void _floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation);
void magicFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation); void magicFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation);

View file

@ -10,6 +10,7 @@
#include <QGraphicsSceneMouseEvent> #include <QGraphicsSceneMouseEvent>
#include <QCloseEvent> #include <QCloseEvent>
#include <QAbstractItemModel> #include <QAbstractItemModel>
#include <QJSValue>
#include "project.h" #include "project.h"
#include "config.h" #include "config.h"
#include "map.h" #include "map.h"
@ -37,7 +38,9 @@ public:
MainWindow(const MainWindow &) = delete; MainWindow(const MainWindow &) = delete;
MainWindow & operator = (const MainWindow &) = delete; MainWindow & operator = (const MainWindow &) = delete;
Q_INVOKABLE void scriptapi_setBlock(int x, int y, int tile, int collision, int elevation); Q_INVOKABLE QJSValue getBlock(int x, int y);
Q_INVOKABLE void setBlock(int x, int y, int tile, int collision, int elevation);
Q_INVOKABLE void setBlocksFromSelection(int x, int y);
public slots: public slots:
void scaleMapView(int); void scaleMapView(int);

View file

@ -15,7 +15,7 @@ class Scripting
{ {
public: public:
Scripting(MainWindow *mainWindow); Scripting(MainWindow *mainWindow);
QJSValue newBlockObject(Block block); static QJSValue fromBlock(Block block);
static void init(MainWindow *mainWindow); static void init(MainWindow *mainWindow);
static void cb_MetatileChanged(int x, int y, Block prevBlock, Block newBlock); static void cb_MetatileChanged(int x, int y, Block prevBlock, Block newBlock);

View file

@ -45,9 +45,9 @@ public:
virtual void shift(QGraphicsSceneMouseEvent*); virtual void shift(QGraphicsSceneMouseEvent*);
virtual void draw(bool ignoreCache = false); virtual void draw(bool ignoreCache = false);
void updateMetatileSelection(QGraphicsSceneMouseEvent *event); void updateMetatileSelection(QGraphicsSceneMouseEvent *event);
void paintNormal(int x, int y, bool fromScriptCallback = false);
private: private:
void paintNormal(int x, int y);
void paintSmartPath(int x, int y); void paintSmartPath(int x, int y);
static QList<int> smartPathTable; static QList<int> smartPathTable;

View file

@ -364,12 +364,12 @@ Block* Map::getBlock(int x, int y) {
return nullptr; return nullptr;
} }
void Map::setBlock(int x, int y, Block block, bool invokeCallback) { void Map::setBlock(int x, int y, Block block, bool enableScriptCallback) {
int i = y * getWidth() + x; int i = y * getWidth() + x;
if (layout->blockdata && layout->blockdata->blocks && i < layout->blockdata->blocks->size()) { if (layout->blockdata && layout->blockdata->blocks && i < layout->blockdata->blocks->size()) {
Block prevBlock = layout->blockdata->blocks->value(i); Block prevBlock = layout->blockdata->blocks->value(i);
layout->blockdata->blocks->replace(i, block); layout->blockdata->blocks->replace(i, block);
if (invokeCallback) { if (enableScriptCallback) {
Scripting::cb_MetatileChanged(x, y, prevBlock, block); Scripting::cb_MetatileChanged(x, y, prevBlock, block);
} }
} }

View file

@ -2544,6 +2544,25 @@ void MainWindow::closeEvent(QCloseEvent *event) {
QMainWindow::closeEvent(event); QMainWindow::closeEvent(event);
} }
void MainWindow::scriptapi_setBlock(int x, int y, int tile, int collision, int elevation) { QJSValue MainWindow::getBlock(int x, int y) {
if (!this->editor || !this->editor->map)
return QJSValue();
Block *block = this->editor->map->getBlock(x, y);
if (!block) {
return Scripting::fromBlock(Block());
}
return Scripting::fromBlock(*block);
}
void MainWindow::setBlock(int x, int y, int tile, int collision, int elevation) {
if (!this->editor || !this->editor->map)
return;
this->editor->map->setBlock(x, y, Block(tile, collision, elevation)); this->editor->map->setBlock(x, y, Block(tile, collision, elevation));
} }
void MainWindow::setBlocksFromSelection(int x, int y) {
if (this->editor && this->editor->map_item) {
this->editor->map_item->paintNormal(x, y, true);
}
}

View file

@ -14,7 +14,7 @@ void Scripting::init(MainWindow *mainWindow) {
Scripting::Scripting(MainWindow *mainWindow) { 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("api", 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"); this->filepaths.append("D:\\devkitProOld\\msys\\home\\huder\\pretmap\\test_script.js");
this->loadModules(this->filepaths); this->loadModules(this->filepaths);
} }
@ -23,7 +23,13 @@ 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'").arg(filepath)); 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; continue;
} }
@ -53,14 +59,14 @@ void Scripting::cb_MetatileChanged(int x, int y, Block prevBlock, Block newBlock
QJSValueList args { QJSValueList args {
x, x,
y, y,
instance->newBlockObject(prevBlock), instance->fromBlock(prevBlock),
instance->newBlockObject(newBlock), instance->fromBlock(newBlock),
}; };
instance->invokeCallback(OnBlockChanged, args); instance->invokeCallback(OnBlockChanged, args);
} }
QJSValue Scripting::newBlockObject(Block block) { QJSValue Scripting::fromBlock(Block block) {
QJSValue obj = this->engine->newObject(); QJSValue obj = instance->engine->newObject();
obj.setProperty("tile", block.tile); obj.setProperty("tile", block.tile);
obj.setProperty("collision", block.collision); obj.setProperty("collision", block.collision);
obj.setProperty("elevation", block.elevation); obj.setProperty("elevation", block.elevation);

View file

@ -69,20 +69,22 @@ void MapPixmapItem::shift(QGraphicsSceneMouseEvent *event) {
} }
} }
void MapPixmapItem::paintNormal(int x, int y) { void MapPixmapItem::paintNormal(int x, int y, bool fromScriptCallback) {
QPoint selectionDimensions = this->metatileSelector->getSelectionDimensions(); QPoint selectionDimensions = this->metatileSelector->getSelectionDimensions();
QList<uint16_t> *selectedMetatiles = this->metatileSelector->getSelectedMetatiles(); QList<uint16_t> *selectedMetatiles = this->metatileSelector->getSelectedMetatiles();
QList<QPair<uint16_t, uint16_t>> *selectedCollisions = this->metatileSelector->getSelectedCollisions(); QList<QPair<uint16_t, uint16_t>> *selectedCollisions = this->metatileSelector->getSelectedCollisions();
int initialX = fromScriptCallback ? x : this->paint_tile_initial_x;
int initialY = fromScriptCallback ? y : this->paint_tile_initial_y;
// Snap the selected position to the top-left of the block boundary. // Snap the selected position to the top-left of the block boundary.
// This allows painting via dragging the mouse to tile the painted region. // This allows painting via dragging the mouse to tile the painted region.
int xDiff = x - this->paint_tile_initial_x; int xDiff = x - initialX;
int yDiff = y - this->paint_tile_initial_y; int yDiff = y - initialY;
if (xDiff < 0 && xDiff % selectionDimensions.x() != 0) xDiff -= selectionDimensions.x(); if (xDiff < 0 && xDiff % selectionDimensions.x() != 0) xDiff -= selectionDimensions.x();
if (yDiff < 0 && yDiff % selectionDimensions.y() != 0) yDiff -= selectionDimensions.y(); if (yDiff < 0 && yDiff % selectionDimensions.y() != 0) yDiff -= selectionDimensions.y();
x = this->paint_tile_initial_x + (xDiff / selectionDimensions.x()) * selectionDimensions.x(); x = initialX + (xDiff / selectionDimensions.x()) * selectionDimensions.x();
y = this->paint_tile_initial_y + (yDiff / selectionDimensions.y()) * selectionDimensions.y(); y = initialY + (yDiff / selectionDimensions.y()) * selectionDimensions.y();
for (int i = 0; i < selectionDimensions.x() && i + x < map->getWidth(); i++) for (int i = 0; i < selectionDimensions.x() && i + x < map->getWidth(); i++)
for (int j = 0; j < selectionDimensions.y() && j + y < map->getHeight(); j++) { for (int j = 0; j < selectionDimensions.y() && j + y < map->getHeight(); j++) {
@ -96,7 +98,7 @@ void MapPixmapItem::paintNormal(int x, int y) {
block->collision = selectedCollisions->at(index).first; block->collision = selectedCollisions->at(index).first;
block->elevation = selectedCollisions->at(index).second; block->elevation = selectedCollisions->at(index).second;
} }
map->setBlock(actualX, actualY, *block, true); map->setBlock(actualX, actualY, *block, !fromScriptCallback);
} }
} }
} }

View file

@ -8,8 +8,13 @@ const grassTiles = [0x8, 0x9, 0x10, 0x11];
// Porymap callback when a block is painted. // Porymap callback when a block is painted.
export function on_block_changed(x, y, prevBlock, newBlock) { export function on_block_changed(x, y, prevBlock, newBlock) {
if (grassTiles.indexOf(newBlock.tile) != -1) { try {
const i = randInt(0, grassTiles.length); if (grassTiles.indexOf(newBlock.tile) != -1) {
api.scriptapi_setBlock(x, y, grassTiles[i], newBlock.collision, newBlock.elevation); const i = randInt(0, grassTiles.length);
map.setBlock(x, y, grassTiles[i], newBlock.collision, newBlock.elevation);
}
map.setBlocksFromSelection(1, 1)
} catch(err) {
console.log(err);
} }
} }