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 cacheCollision();
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 magicFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation);

View file

@ -10,6 +10,7 @@
#include <QGraphicsSceneMouseEvent>
#include <QCloseEvent>
#include <QAbstractItemModel>
#include <QJSValue>
#include "project.h"
#include "config.h"
#include "map.h"
@ -37,7 +38,9 @@ public:
MainWindow(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:
void scaleMapView(int);

View file

@ -15,7 +15,7 @@ class Scripting
{
public:
Scripting(MainWindow *mainWindow);
QJSValue newBlockObject(Block block);
static QJSValue fromBlock(Block block);
static void init(MainWindow *mainWindow);
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 draw(bool ignoreCache = false);
void updateMetatileSelection(QGraphicsSceneMouseEvent *event);
void paintNormal(int x, int y, bool fromScriptCallback = false);
private:
void paintNormal(int x, int y);
void paintSmartPath(int x, int y);
static QList<int> smartPathTable;

View file

@ -364,12 +364,12 @@ Block* Map::getBlock(int x, int y) {
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;
if (layout->blockdata && layout->blockdata->blocks && i < layout->blockdata->blocks->size()) {
Block prevBlock = layout->blockdata->blocks->value(i);
layout->blockdata->blocks->replace(i, block);
if (invokeCallback) {
if (enableScriptCallback) {
Scripting::cb_MetatileChanged(x, y, prevBlock, block);
}
}

View file

@ -2544,6 +2544,25 @@ void MainWindow::closeEvent(QCloseEvent *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));
}
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) {
this->engine = new QJSEngine(mainWindow);
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->loadModules(this->filepaths);
}
@ -23,7 +23,13 @@ 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'").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;
}
@ -53,14 +59,14 @@ void Scripting::cb_MetatileChanged(int x, int y, Block prevBlock, Block newBlock
QJSValueList args {
x,
y,
instance->newBlockObject(prevBlock),
instance->newBlockObject(newBlock),
instance->fromBlock(prevBlock),
instance->fromBlock(newBlock),
};
instance->invokeCallback(OnBlockChanged, args);
}
QJSValue Scripting::newBlockObject(Block block) {
QJSValue obj = this->engine->newObject();
QJSValue Scripting::fromBlock(Block block) {
QJSValue obj = instance->engine->newObject();
obj.setProperty("tile", block.tile);
obj.setProperty("collision", block.collision);
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();
QList<uint16_t> *selectedMetatiles = this->metatileSelector->getSelectedMetatiles();
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.
// This allows painting via dragging the mouse to tile the painted region.
int xDiff = x - this->paint_tile_initial_x;
int yDiff = y - this->paint_tile_initial_y;
int xDiff = x - initialX;
int yDiff = y - initialY;
if (xDiff < 0 && xDiff % selectionDimensions.x() != 0) xDiff -= selectionDimensions.x();
if (yDiff < 0 && yDiff % selectionDimensions.y() != 0) yDiff -= selectionDimensions.y();
x = this->paint_tile_initial_x + (xDiff / selectionDimensions.x()) * selectionDimensions.x();
y = this->paint_tile_initial_y + (yDiff / selectionDimensions.y()) * selectionDimensions.y();
x = initialX + (xDiff / selectionDimensions.x()) * selectionDimensions.x();
y = initialY + (yDiff / selectionDimensions.y()) * selectionDimensions.y();
for (int i = 0; i < selectionDimensions.x() && i + x < map->getWidth(); i++)
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->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.
export function on_block_changed(x, y, prevBlock, newBlock) {
if (grassTiles.indexOf(newBlock.tile) != -1) {
const i = randInt(0, grassTiles.length);
api.scriptapi_setBlock(x, y, grassTiles[i], newBlock.collision, newBlock.elevation);
try {
if (grassTiles.indexOf(newBlock.tile) != -1) {
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);
}
}