diff --git a/include/core/map.h b/include/core/map.h index 8122659c..2ea85eec 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -17,6 +17,10 @@ #define DEFAULT_BORDER_WIDTH 2 #define DEFAULT_BORDER_HEIGHT 2 +// Maximum based only on data type (u8) of map border width/height +#define MAX_BORDER_WIDTH 255 +#define MAX_BORDER_HEIGHT 255 + // Number of metatiles to draw out from edge of map. Could allow modification of this in the future. // porymap will reflect changes to it, but the value is hard-coded in the projects at the moment #define BORDER_DISTANCE 7 @@ -82,6 +86,9 @@ public: bool getBlock(int x, int y, Block *out); void setBlock(int x, int y, Block block, bool enableScriptCallback = false); void setBlockdata(Blockdata blockdata); + uint16_t getBorderMetatileId(int x, int y); + void setBorderMetatileId(int x, int y, uint16_t metatileId, bool enableScriptCallback = false); + void setBorderBlockData(Blockdata blockdata); 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); @@ -96,6 +103,7 @@ public: void cacheBorder(); bool hasUnsavedChanges(); bool isWithinBounds(int x, int y); + bool isWithinBorderBounds(int x, int y); // for memory management QVector ownedEvents; diff --git a/include/mainwindow.h b/include/mainwindow.h index d64e0d65..c68473b4 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -46,6 +46,8 @@ public: Q_INVOKABLE QJSValue getBlock(int x, int y); void tryRedrawMapArea(bool forceRedraw); void tryCommitMapChanges(bool commitChanges); + void tryRedrawBorder(bool forceRedraw); + void tryCommitBorderChanges(bool commitChanges); Q_INVOKABLE void setBlock(int x, int y, int tile, int collision, int elevation, bool forceRedraw = true, bool commitChanges = true); Q_INVOKABLE void setBlocksFromSelection(int x, int y, bool forceRedraw = true, bool commitChanges = true); Q_INVOKABLE int getMetatileId(int x, int y); diff --git a/include/scripting.h b/include/scripting.h index 176f69e9..55f5a3ef 100644 --- a/include/scripting.h +++ b/include/scripting.h @@ -12,10 +12,12 @@ enum CallbackType { OnProjectOpened, OnProjectClosed, OnBlockChanged, + OnBorderMetatileChanged, OnBlockHoverChanged, OnBlockHoverCleared, OnMapOpened, OnMapResized, + OnBorderResized, OnMapShifted, OnTilesetUpdated, OnMainTabChanged, @@ -40,10 +42,12 @@ public: 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_BorderMetatileChanged(int x, int y, uint16_t prevMetatileId, uint16_t newMetatileId); static void cb_BlockHoverChanged(int x, int y); static void cb_BlockHoverCleared(); static void cb_MapOpened(QString mapName); static void cb_MapResized(int oldWidth, int oldHeight, int newWidth, int newHeight); + static void cb_BorderResized(int oldWidth, int oldHeight, int newWidth, int newHeight); static void cb_MapShifted(int xDelta, int yDelta); static void cb_TilesetUpdated(QString tilesetName); static void cb_MainTabChanged(int oldTab, int newTab); diff --git a/src/core/editcommands.cpp b/src/core/editcommands.cpp index f755da6e..62885aaa 100644 --- a/src/core/editcommands.cpp +++ b/src/core/editcommands.cpp @@ -101,7 +101,7 @@ void PaintBorder::redo() { if (!map) return; - map->layout->border = newBorder; + map->setBorderBlockData(newBorder); map->borderItem->draw(); } @@ -109,7 +109,7 @@ void PaintBorder::redo() { void PaintBorder::undo() { if (!map) return; - map->layout->border = oldBorder; + map->setBorderBlockData(oldBorder); map->borderItem->draw(); diff --git a/src/core/map.cpp b/src/core/map.cpp index baee10a3..95bd6def 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -328,9 +328,15 @@ void Map::setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata) setNewBorderDimensionsBlockdata(newWidth, newHeight); } + int oldWidth = layout->border_width.toInt(); + int oldHeight = layout->border_height.toInt(); layout->border_width = QString::number(newWidth); layout->border_height = QString::number(newHeight); + if (oldWidth != newWidth || oldHeight != newHeight) { + Scripting::cb_BorderResized(oldWidth, oldHeight, newWidth, newHeight); + } + emit mapChanged(this); } @@ -367,6 +373,35 @@ void Map::setBlockdata(Blockdata blockdata) { } } +uint16_t Map::getBorderMetatileId(int x, int y) { + int i = y * getBorderWidth() + x; + return layout->border[i].metatileId; +} + +void Map::setBorderMetatileId(int x, int y, uint16_t metatileId, bool enableScriptCallback) { + int i = y * getBorderWidth() + x; + if (i < layout->border.size()) { + uint16_t prevMetatileId = layout->border[i].metatileId; + layout->border[i].metatileId = metatileId; + if (prevMetatileId != metatileId && enableScriptCallback) { + Scripting::cb_BorderMetatileChanged(x, y, prevMetatileId, metatileId); + } + } +} + +void Map::setBorderBlockData(Blockdata blockdata) { + int width = getBorderWidth(); + int size = qMin(blockdata.size(), layout->border.size()); + for (int i = 0; i < size; i++) { + Block prevBlock = layout->border.at(i); + Block newBlock = blockdata.at(i); + if (prevBlock != newBlock) { + layout->border.replace(i, newBlock); + Scripting::cb_BorderMetatileChanged(i % width, i / width, prevBlock.metatileId, newBlock.metatileId); + } + } +} + void Map::_floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation) { QList todo; todo.append(QPoint(x, y)); @@ -474,3 +509,7 @@ bool Map::hasUnsavedChanges() { bool Map::isWithinBounds(int x, int y) { return (x >= 0 && x < this->getWidth() && y >= 0 && y < this->getHeight()); } + +bool Map::isWithinBorderBounds(int x, int y) { + return (x >= 0 && x < this->getBorderWidth() && y >= 0 && y < this->getBorderHeight()); +} diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 71089327..711d5a3e 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2906,9 +2906,8 @@ void MainWindow::on_pushButton_ChangeDimensions_clicked() bheightSpinBox->setMinimum(1); widthSpinBox->setMaximum(editor->project->getMaxMapWidth()); heightSpinBox->setMaximum(editor->project->getMaxMapHeight()); - // Maximum based only on data type (u8) of map border width/height - bwidthSpinBox->setMaximum(255); - bheightSpinBox->setMaximum(255); + bwidthSpinBox->setMaximum(MAX_BORDER_WIDTH); + bheightSpinBox->setMaximum(MAX_BORDER_HEIGHT); widthSpinBox->setValue(editor->map->getWidth()); heightSpinBox->setValue(editor->map->getHeight()); bwidthSpinBox->setValue(editor->map->getBorderWidth()); diff --git a/src/mainwindow_scriptapi.cpp b/src/mainwindow_scriptapi.cpp index d2281a9d..8ec8d688 100644 --- a/src/mainwindow_scriptapi.cpp +++ b/src/mainwindow_scriptapi.cpp @@ -50,6 +50,16 @@ void MainWindow::tryCommitMapChanges(bool commitChanges) { } } +void MainWindow::tryRedrawBorder(bool forceRedraw) { + if (!forceRedraw) return; + // TODO +} + +void MainWindow::tryCommitBorderChanges(bool commitChanges) { + if (!commitChanges) return; + // TODO +} + void MainWindow::setBlock(int x, int y, int tile, int collision, int elevation, bool forceRedraw, bool commitChanges) { if (!this->editor || !this->editor->map) return; @@ -91,13 +101,19 @@ void MainWindow::setMetatileId(int x, int y, int metatileId, bool forceRedraw, b int MainWindow::getBorderMetatileId(int x, int y) { if (!this->editor || !this->editor->map) return 0; - // TODO + if (!this->editor->map->isWithinBorderBounds(x, y)) + return 0; + return this->editor->map->getBorderMetatileId(x, y); } void MainWindow::setBorderMetatileId(int x, int y, int metatileId, bool forceRedraw, bool commitChanges) { if (!this->editor || !this->editor->map) return; - // TODO + if (!this->editor->map->isWithinBorderBounds(x, y)) + return; + this->editor->map->setBorderMetatileId(x, y, metatileId); + this->tryCommitBorderChanges(commitChanges); + this->tryRedrawBorder(forceRedraw); } int MainWindow::getCollision(int x, int y) { @@ -213,19 +229,19 @@ int MainWindow::getHeight() { QJSValue MainWindow::getBorderDimensions() { if (!this->editor || !this->editor->map) return QJSValue(); - // TODO + return Scripting::dimensions(this->editor->map->getBorderWidth(), this->editor->map->getBorderHeight()); } int MainWindow::getBorderWidth() { if (!this->editor || !this->editor->map) return 0; - // TODO + return this->editor->map->getBorderWidth(); } int MainWindow::getBorderHeight() { if (!this->editor || !this->editor->map) return 0; - // TODO + return this->editor->map->getBorderHeight(); } void MainWindow::setDimensions(int width, int height) { @@ -259,20 +275,32 @@ void MainWindow::setHeight(int height) { } void MainWindow::setBorderDimensions(int width, int height) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->map || !projectConfig.getUseCustomBorderSize()) return; - // TODO + if (width < 1 || height < 1 || width > MAX_BORDER_WIDTH || height > MAX_BORDER_HEIGHT) + return; + this->editor->map->setBorderDimensions(width, height); + this->tryCommitBorderChanges(true); + // TODO } void MainWindow::setBorderWidth(int width) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->map || !projectConfig.getUseCustomBorderSize()) return; + if (width < 1 || width > MAX_BORDER_WIDTH) + return; + this->editor->map->setBorderDimensions(width, this->editor->map->getBorderHeight()); + this->tryCommitBorderChanges(true); // TODO } void MainWindow::setBorderHeight(int height) { - if (!this->editor || !this->editor->map) + if (!this->editor || !this->editor->map || !projectConfig.getUseCustomBorderSize()) return; + if (height < 1 || height > MAX_BORDER_HEIGHT) + return; + this->editor->map->setBorderDimensions(this->editor->map->getBorderWidth(), height); + this->tryCommitBorderChanges(true); // TODO } diff --git a/src/scripting.cpp b/src/scripting.cpp index ef757464..d5100312 100644 --- a/src/scripting.cpp +++ b/src/scripting.cpp @@ -5,10 +5,12 @@ QMap callbackFunctions = { {OnProjectOpened, "onProjectOpened"}, {OnProjectClosed, "onProjectClosed"}, {OnBlockChanged, "onBlockChanged"}, + {OnBorderMetatileChanged, "onBorderMetatileChanged"}, {OnBlockHoverChanged, "onBlockHoverChanged"}, {OnBlockHoverCleared, "onBlockHoverCleared"}, {OnMapOpened, "onMapOpened"}, {OnMapResized, "onMapResized"}, + {OnBorderResized, "onBorderResized"}, {OnMapShifted, "onMapShifted"}, {OnTilesetUpdated, "onTilesetUpdated"}, {OnMainTabChanged, "onMainTabChanged"}, @@ -140,6 +142,18 @@ void Scripting::cb_MetatileChanged(int x, int y, Block prevBlock, Block newBlock instance->invokeCallback(OnBlockChanged, args); } +void Scripting::cb_BorderMetatileChanged(int x, int y, uint16_t prevMetatileId, uint16_t newMetatileId) { + if (!instance) return; + + QJSValueList args { + x, + y, + prevMetatileId, + newMetatileId, + }; + instance->invokeCallback(OnBorderMetatileChanged, args); +} + void Scripting::cb_BlockHoverChanged(int x, int y) { if (!instance) return; @@ -176,6 +190,18 @@ void Scripting::cb_MapResized(int oldWidth, int oldHeight, int newWidth, int new instance->invokeCallback(OnMapResized, args); } +void Scripting::cb_BorderResized(int oldWidth, int oldHeight, int newWidth, int newHeight) { + if (!instance) return; + + QJSValueList args { + oldWidth, + oldHeight, + newWidth, + newHeight, + }; + instance->invokeCallback(OnBorderResized, args); +} + void Scripting::cb_MapShifted(int xDelta, int yDelta) { if (!instance) return; diff --git a/src/ui/bordermetatilespixmapitem.cpp b/src/ui/bordermetatilespixmapitem.cpp index 0f03e2aa..8f3bda9b 100644 --- a/src/ui/bordermetatilespixmapitem.cpp +++ b/src/ui/bordermetatilespixmapitem.cpp @@ -15,9 +15,8 @@ void BorderMetatilesPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) for (int i = 0; i < selectionDimensions.x() && (i + pos.x()) < width; i++) { for (int j = 0; j < selectionDimensions.y() && (j + pos.y()) < height; j++) { - int blockIndex = (j + pos.y()) * width + (i + pos.x()); uint16_t metatileId = selectedMetatiles->at(j * selectionDimensions.x() + i); - map->layout->border[blockIndex].metatileId = metatileId; + map->setBorderMetatileId(pos.x() + i, pos.y() + j, metatileId, true); } } @@ -40,9 +39,8 @@ void BorderMetatilesPixmapItem::draw() { for (int j = 0; j < height; j++) { int x = i * 16; int y = j * 16; - int index = j * width + i; QImage metatile_image = getMetatileImage( - map->layout->border.value(index).metatileId, + map->getBorderMetatileId(i, j), map->layout->tileset_primary, map->layout->tileset_secondary, map->metatileLayerOrder,