From 4feb913fe888c0feb26d4703144add07ecd7ca05 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 3 Aug 2022 15:14:25 -0400 Subject: [PATCH 01/10] Add setBlock overload, handle collision values of 2 or 3 --- include/mainwindow.h | 3 ++- src/editor.cpp | 2 +- src/mainwindow_scriptapi.cpp | 12 ++++++++++-- src/ui/imageproviders.cpp | 2 +- src/ui/movementpermissionsselector.cpp | 2 +- 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index 1174060b..19b8cbef 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -46,7 +46,8 @@ public: Q_INVOKABLE QJSValue getBlock(int x, int y); void tryRedrawMapArea(bool forceRedraw); void tryCommitMapChanges(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 setBlock(int x, int y, int metatileId, int collision, int elevation, bool forceRedraw = true, bool commitChanges = true); + Q_INVOKABLE void setBlock(int x, int y, int rawValue, 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); Q_INVOKABLE void setMetatileId(int x, int y, int metatileId, bool forceRedraw = true, bool commitChanges = true); diff --git a/src/editor.cpp b/src/editor.cpp index d15b3bbc..ef4e6ff1 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1075,7 +1075,7 @@ QString Editor::getMovementPermissionText(uint16_t collision, uint16_t elevation } else if (collision == 0) { message = QString("Collision: Passable, Elevation: %1").arg(elevation); } else { - message = QString("Collision: Impassable, Elevation: %1").arg(elevation); + message = QString("Collision: Impassable (%1), Elevation: %2").arg(collision).arg(elevation); } return message; } diff --git a/src/mainwindow_scriptapi.cpp b/src/mainwindow_scriptapi.cpp index 5875bb08..784a0354 100644 --- a/src/mainwindow_scriptapi.cpp +++ b/src/mainwindow_scriptapi.cpp @@ -50,10 +50,18 @@ void MainWindow::tryCommitMapChanges(bool commitChanges) { } } -void MainWindow::setBlock(int x, int y, int tile, int collision, int elevation, bool forceRedraw, bool commitChanges) { +void MainWindow::setBlock(int x, int y, int metatileId, int collision, int elevation, bool forceRedraw, bool commitChanges) { if (!this->editor || !this->editor->map) return; - this->editor->map->setBlock(x, y, Block(tile, collision, elevation)); + this->editor->map->setBlock(x, y, Block(metatileId, collision, elevation)); + this->tryCommitMapChanges(commitChanges); + this->tryRedrawMapArea(forceRedraw); +} + +void MainWindow::setBlock(int x, int y, int rawValue, bool forceRedraw, bool commitChanges) { + if (!this->editor || !this->editor->map) + return; + this->editor->map->setBlock(x, y, Block(static_cast(rawValue))); this->tryCommitMapChanges(commitChanges); this->tryRedrawMapArea(forceRedraw); } diff --git a/src/ui/imageproviders.cpp b/src/ui/imageproviders.cpp index 200d478b..192afc85 100644 --- a/src/ui/imageproviders.cpp +++ b/src/ui/imageproviders.cpp @@ -8,7 +8,7 @@ QImage getCollisionMetatileImage(Block block) { } QImage getCollisionMetatileImage(int collision, int elevation) { - int x = collision * 16; + int x = (collision != 0) * 16; int y = elevation * 16; QPixmap collisionImage = QPixmap(":/images/collisions.png").copy(x, y, 16, 16); return collisionImage.toImage(); diff --git a/src/ui/movementpermissionsselector.cpp b/src/ui/movementpermissionsselector.cpp index da6d7178..9bad2a0f 100644 --- a/src/ui/movementpermissionsselector.cpp +++ b/src/ui/movementpermissionsselector.cpp @@ -16,7 +16,7 @@ uint16_t MovementPermissionsSelector::getSelectedElevation() { } void MovementPermissionsSelector::select(uint16_t collision, uint16_t elevation) { - SelectablePixmapItem::select(collision, elevation, 0, 0); + SelectablePixmapItem::select(collision != 0, elevation, 0, 0); } void MovementPermissionsSelector::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { From 0df5f878828b8dd06eeda9797ce9b40377ad9a07 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 3 Aug 2022 15:27:08 -0400 Subject: [PATCH 02/10] Update manual, changelog --- CHANGELOG.md | 4 ++-- docsrc/manual/scripting-capabilities.rst | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48006ea7..51d3dc35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,8 +12,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d ### Added - Add Copy/Paste for metatiles in the Tileset Editor. -- Add ability to set the opacity of the scripting overlay. -- Add ability to get/set map header properties and read tile pixel data via the API. +- Add new features to the scripting API, including the ability to set overlay opacity, get/set map header properties, read tile pixel data, and set blocks using a raw value. - Add button to copy the full metatile label to the clipboard in the Tileset Editor. - Add option to not open the most recent project on launch. - Add color picker to palette editor for taking colors from the screen. @@ -33,6 +32,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d - Fix cursor tile and player view outlines exiting map bounds while painting. - Fix cursor tile and player view outlines not updating immediately when toggled in Collision view. - Fix selected space not updating while painting in Collision view. +- Fix collision values of 2 or 3 not rendering properly. - Fix the map music dropdown being empty when importing a map from Advance Map. - Fixed a bug where saving the tileset editor would reselect the main editor's first selected metatile. diff --git a/docsrc/manual/scripting-capabilities.rst b/docsrc/manual/scripting-capabilities.rst index d86208cc..21f53591 100644 --- a/docsrc/manual/scripting-capabilities.rst +++ b/docsrc/manual/scripting-capabilities.rst @@ -190,11 +190,21 @@ The following functions are related to editing the map's blocks or retrieving in :param number x: x coordinate of the block :param number y: y coordinate of the block :param number metatileId: the metatile id of the block - :param number collision: the collision of the block (``0`` = passable, ``1`` = impassable) + :param number collision: the collision of the block (``0`` = passable, ``1-3`` = impassable) :param number elevation: the elevation of the block :param boolean forceRedraw: Force the map view to refresh. Defaults to ``true``. Redrawing the map view is expensive, so set to ``false`` when making many consecutive map edits, and then redraw the map once using ``map.redraw()``. :param boolean commitChanges: Commit the changes to the map's edit/undo history. Defaults to ``true``. When making many related map edits, it can be useful to set this to ``false``, and then commit all of them together with ``map.commit()``. +.. js:function:: map.setBlock(x, y, rawValue, forceRedraw = true, commitChanges = true) + + Sets a block in the currently-opened map. This is an overloaded function that takes the raw value of a block instead of each of the block's properties individually. + + :param number x: x coordinate of the block + :param number y: y coordinate of the block + :param number rawValue: the 16 bit value of the block. Bits ``0-9`` will be the metatile id, bits ``10-11`` will be the collision, and bits ``12-15`` will be the elevation. + :param boolean forceRedraw: Force the map view to refresh. Defaults to ``true``. Redrawing the map view is expensive, so set to ``false`` when making many consecutive map edits, and then redraw the map once using ``map.redraw()``. + :param boolean commitChanges: Commit the changes to the map's edit/undo history. Defaults to ``true``. When making many related map edits, it can be useful to set this to ``false``, and then commit all of them together with ``map.commit()``. + .. js:function:: map.getMetatileId(x, y) Gets the metatile id of a block in the currently-opened map. @@ -215,7 +225,7 @@ The following functions are related to editing the map's blocks or retrieving in .. js:function:: map.getCollision(x, y) - Gets the collision of a block in the currently-opened map. (``0`` = passable, ``1`` = impassable) + Gets the collision of a block in the currently-opened map. (``0`` = passable, ``1-3`` = impassable) :param number x: x coordinate of the block :param number y: y coordinate of the block @@ -223,7 +233,7 @@ The following functions are related to editing the map's blocks or retrieving in .. js:function:: map.setCollision(x, y, collision, forceRedraw = true, commitChanges = true) - Sets the collision of a block in the currently-opened map. (``0`` = passable, ``1`` = impassable) + Sets the collision of a block in the currently-opened map. (``0`` = passable, ``1-3`` = impassable) :param number x: x coordinate of the block :param number y: y coordinate of the block From c88b8b7663fb725ecb967ae020c6c6bc693d46c2 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 3 Aug 2022 21:30:17 -0400 Subject: [PATCH 03/10] Fix manual typo --- docsrc/manual/scripting-capabilities.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docsrc/manual/scripting-capabilities.rst b/docsrc/manual/scripting-capabilities.rst index 21f53591..73950d4c 100644 --- a/docsrc/manual/scripting-capabilities.rst +++ b/docsrc/manual/scripting-capabilities.rst @@ -1124,7 +1124,7 @@ The following functions are related to tilesets and how they are rendered. The f :param number tileEnd: index of the last tile to set. Defaults to ``-1`` (the last tile) :param boolean forceRedraw: Force the map view to refresh. Defaults to ``true``. Redrawing the map view is expensive, so set to ``false`` when making many consecutive map edits, and then redraw the map once using ``map.redraw()``. -..js:function:: map.getTilePixels(tileId) +.. js:function:: map.getTilePixels(tileId) Gets the pixel data for the specified tile. The pixel data is an array of indexes indicating which palette color each pixel uses. Tiles are 8x8, so the pixel array will be 64 elements long. From 778cc2ba4766c5c55cda6d4101b61e50c4916835 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 27 Jul 2022 13:39:31 -0400 Subject: [PATCH 04/10] Fix API crashes on bad palette ids / tile numbers --- include/core/tile.h | 1 + src/core/tile.cpp | 11 +++++++++++ src/core/tileset.cpp | 6 ++++++ src/mainwindow_scriptapi.cpp | 8 ++++++-- src/scripting.cpp | 20 ++++++++++---------- 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/include/core/tile.h b/include/core/tile.h index 1a862987..bd673f74 100644 --- a/include/core/tile.h +++ b/include/core/tile.h @@ -18,6 +18,7 @@ public: int palette; uint16_t rawValue() const; + void sanitize(); static int getIndexInTileset(int); }; diff --git a/src/core/tile.cpp b/src/core/tile.cpp index 56465160..10baa720 100644 --- a/src/core/tile.cpp +++ b/src/core/tile.cpp @@ -30,6 +30,17 @@ uint16_t Tile::rawValue() const { | ((this->palette & 0xF) << 12)); } +void Tile::sanitize() { + if (tileId < 0 || tileId >= Project::getNumTilesTotal()) { + logWarn(QString("Resetting tile's invalid tile id '%1' to 0.").arg(tileId)); + tileId = 0; + } + if (palette < 0 || palette >= Project::getNumPalettesTotal()) { + logWarn(QString("Resetting tile's invalid palette id '%1' to 0.").arg(palette)); + palette = 0; + } +} + int Tile::getIndexInTileset(int tileId) { if (tileId < Project::getNumTilesPrimary()) { return tileId; diff --git a/src/core/tileset.cpp b/src/core/tileset.cpp index b87cfa69..9a055690 100644 --- a/src/core/tileset.cpp +++ b/src/core/tileset.cpp @@ -120,6 +120,12 @@ QList Tileset::getPalette(int paletteId, Tileset *primaryTileset, Tileset ? primaryTileset : secondaryTileset; auto palettes = useTruePalettes ? tileset->palettes : tileset->palettePreviews; + + if (paletteId < 0 || paletteId >= palettes.length()){ + logError(QString("Invalid tileset palette id '%1' requested.").arg(paletteId)); + return paletteTable; + } + for (int i = 0; i < palettes.at(paletteId).length(); i++) { paletteTable.append(palettes.at(paletteId).at(i)); } diff --git a/src/mainwindow_scriptapi.cpp b/src/mainwindow_scriptapi.cpp index 784a0354..931bc26a 100644 --- a/src/mainwindow_scriptapi.cpp +++ b/src/mainwindow_scriptapi.cpp @@ -991,8 +991,11 @@ void MainWindow::setMetatileTiles(int metatileId, QJSValue tilesObj, int tileSta // Write to metatile using as many of the given Tiles as possible int numTileObjs = qMin(tilesObj.property("length").toInt(), numTiles); int i = 0; - for (; i < numTileObjs; i++, tileStart++) - metatile->tiles[tileStart] = Scripting::toTile(tilesObj.property(i)); + for (; i < numTileObjs; i++, tileStart++) { + Tile tile = Scripting::toTile(tilesObj.property(i)); + tile.sanitize(); + metatile->tiles[tileStart] = tile; + } // Fill remainder of specified length with empty Tiles for (; i < numTiles; i++, tileStart++) @@ -1011,6 +1014,7 @@ void MainWindow::setMetatileTiles(int metatileId, int tileId, bool xflip, bool y // Write to metatile using Tiles of the specified value Tile tile = Tile(tileId, xflip, yflip, palette); + tile.sanitize(); for (int i = tileStart; i <= tileEnd; i++) metatile->tiles[i] = tile; diff --git a/src/scripting.cpp b/src/scripting.cpp index ef757464..946380ab 100644 --- a/src/scripting.cpp +++ b/src/scripting.cpp @@ -239,17 +239,17 @@ QJSValue Scripting::position(int x, int y) { } Tile Scripting::toTile(QJSValue obj) { - if (!obj.hasProperty("tileId") - || !obj.hasProperty("xflip") - || !obj.hasProperty("yflip") - || !obj.hasProperty("palette")) { - return Tile(); - } Tile tile = Tile(); - tile.tileId = obj.property("tileId").toInt(); - tile.xflip = obj.property("xflip").toBool(); - tile.yflip = obj.property("yflip").toBool(); - tile.palette = obj.property("palette").toInt(); + + if (obj.hasProperty("tileId")) + tile.tileId = obj.property("tileId").toInt(); + if (obj.hasProperty("xflip")) + tile.xflip = obj.property("xflip").toBool(); + if (obj.hasProperty("yflip")) + tile.yflip = obj.property("yflip").toBool(); + if (obj.hasProperty("palette")) + tile.palette = obj.property("palette").toInt(); + return tile; } From f8edaec83828209051e4ea7a45b1f26a47913be7 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 27 Jul 2022 13:41:49 -0400 Subject: [PATCH 05/10] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51d3dc35..feceffc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d - Fix collision values of 2 or 3 not rendering properly. - Fix the map music dropdown being empty when importing a map from Advance Map. - Fixed a bug where saving the tileset editor would reselect the main editor's first selected metatile. +- Fix crashes / unexpected behavior if certain scripting API functions are given invalid palette or tile numbers. ## [4.5.0] - 2021-12-26 ### Added From d22aab9b1075818a87146b00b5ae49871fb280c1 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 2 Aug 2022 18:53:05 -0400 Subject: [PATCH 06/10] Fix setOverlayOpacity setting the opacity of the cursor rect and map grid --- src/ui/overlay.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ui/overlay.cpp b/src/ui/overlay.cpp index 635d76f9..996edb8e 100644 --- a/src/ui/overlay.cpp +++ b/src/ui/overlay.cpp @@ -26,9 +26,11 @@ void OverlayImage::render(QPainter *painter, int x, int y) { void Overlay::renderItems(QPainter *painter) { if (this->hidden) return; + qreal oldOpacity = painter->opacity(); painter->setOpacity(this->opacity); for (auto item : this->items) item->render(painter, this->x, this->y); + painter->setOpacity(oldOpacity); } void Overlay::clearItems() { From fd4ba874d233aadb578daf5ade5cfa72b77e7d16 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 26 Aug 2022 19:29:48 -0400 Subject: [PATCH 07/10] Fix unused layer rendering for METATILE_LAYER_MIDDLE_TOP --- src/ui/imageproviders.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/imageproviders.cpp b/src/ui/imageproviders.cpp index 192afc85..6a246cc9 100644 --- a/src/ui/imageproviders.cpp +++ b/src/ui/imageproviders.cpp @@ -66,13 +66,13 @@ QImage getMetatileImage( tile = metatile->tiles.value(tileOffset + (l * 4)); } else { // "Vanilla" metatiles only have 8 tiles, but render 12. - // The remaining 4 tiles are rendered either as tile 0 or 0x3014 (invalid) depending on layer type. + // The remaining 4 tiles are rendered either as tile 0 or 0x3014 (tile 20, palette 3) depending on layer type. switch (layerType) { default: case METATILE_LAYER_MIDDLE_TOP: if (l == 0) - tile = Tile(0x3014, false, false, 0); + tile = Tile(0x3014); else // Tiles are on layers 1 and 2 tile = metatile->tiles.value(tileOffset + ((l - 1) * 4)); break; From aad1266e912e045be7a3dc21c5be4d60e0f6996f Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 26 Aug 2022 19:30:40 -0400 Subject: [PATCH 08/10] Tile properties to bitfield --- include/core/tile.h | 12 +++++------- src/core/tile.cpp | 13 +------------ src/mainwindow_scriptapi.cpp | 8 ++------ 3 files changed, 8 insertions(+), 25 deletions(-) diff --git a/include/core/tile.h b/include/core/tile.h index bd673f74..5d85066a 100644 --- a/include/core/tile.h +++ b/include/core/tile.h @@ -8,17 +8,15 @@ class Tile { public: Tile(); - Tile(int tileId, bool xflip, bool yflip, int palette); + Tile(uint16_t tileId, uint16_t xflip, uint16_t yflip, uint16_t palette); Tile(uint16_t raw); public: - int tileId; - bool xflip; - bool yflip; - int palette; - + uint16_t tileId:10; + uint16_t xflip:1; + uint16_t yflip:1; + uint16_t palette:4; uint16_t rawValue() const; - void sanitize(); static int getIndexInTileset(int); }; diff --git a/src/core/tile.cpp b/src/core/tile.cpp index 10baa720..cc89c2a9 100644 --- a/src/core/tile.cpp +++ b/src/core/tile.cpp @@ -8,7 +8,7 @@ palette(0) { } - Tile::Tile(int tileId, bool xflip, bool yflip, int palette) : + Tile::Tile(uint16_t tileId, uint16_t xflip, uint16_t yflip, uint16_t palette) : tileId(tileId), xflip(xflip), yflip(yflip), @@ -30,17 +30,6 @@ uint16_t Tile::rawValue() const { | ((this->palette & 0xF) << 12)); } -void Tile::sanitize() { - if (tileId < 0 || tileId >= Project::getNumTilesTotal()) { - logWarn(QString("Resetting tile's invalid tile id '%1' to 0.").arg(tileId)); - tileId = 0; - } - if (palette < 0 || palette >= Project::getNumPalettesTotal()) { - logWarn(QString("Resetting tile's invalid palette id '%1' to 0.").arg(palette)); - palette = 0; - } -} - int Tile::getIndexInTileset(int tileId) { if (tileId < Project::getNumTilesPrimary()) { return tileId; diff --git a/src/mainwindow_scriptapi.cpp b/src/mainwindow_scriptapi.cpp index 931bc26a..784a0354 100644 --- a/src/mainwindow_scriptapi.cpp +++ b/src/mainwindow_scriptapi.cpp @@ -991,11 +991,8 @@ void MainWindow::setMetatileTiles(int metatileId, QJSValue tilesObj, int tileSta // Write to metatile using as many of the given Tiles as possible int numTileObjs = qMin(tilesObj.property("length").toInt(), numTiles); int i = 0; - for (; i < numTileObjs; i++, tileStart++) { - Tile tile = Scripting::toTile(tilesObj.property(i)); - tile.sanitize(); - metatile->tiles[tileStart] = tile; - } + for (; i < numTileObjs; i++, tileStart++) + metatile->tiles[tileStart] = Scripting::toTile(tilesObj.property(i)); // Fill remainder of specified length with empty Tiles for (; i < numTiles; i++, tileStart++) @@ -1014,7 +1011,6 @@ void MainWindow::setMetatileTiles(int metatileId, int tileId, bool xflip, bool y // Write to metatile using Tiles of the specified value Tile tile = Tile(tileId, xflip, yflip, palette); - tile.sanitize(); for (int i = tileStart; i <= tileEnd; i++) metatile->tiles[i] = tile; From 778257ccd9fa07b1dd5c4c07886d89cdcdd709de Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 26 Aug 2022 19:37:07 -0400 Subject: [PATCH 09/10] Add get/setMetatileAttributes --- CHANGELOG.md | 4 ++-- docsrc/manual/scripting-capabilities.rst | 16 ++++++++++++++++ include/mainwindow.h | 2 ++ src/mainwindow_scriptapi.cpp | 16 ++++++++++++++++ 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index feceffc3..1481ee53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,17 +12,17 @@ The **"Breaking Changes"** listed below are changes that have been made in the d ### Added - Add Copy/Paste for metatiles in the Tileset Editor. -- Add new features to the scripting API, including the ability to set overlay opacity, get/set map header properties, read tile pixel data, and set blocks using a raw value. +- Add new features to the scripting API, including the ability to set overlay opacity, get/set map header properties, read tile pixel data, and set blocks or metatile attributes using a raw value. - Add button to copy the full metatile label to the clipboard in the Tileset Editor. - Add option to not open the most recent project on launch. - Add color picker to palette editor for taking colors from the screen. ### Changed +- Overhauled the region map editor, adding support for tilemaps, and significant customization. Also now supports pokefirered. - If an object event is inanimate, it will always render using its first frame. - Only log "Unknown custom script function" when a registered script function is not present in any script. - Unused metatile attribute bits that are set are preserved instead of being cleared. - The wild encounter editor is automatically disabled if the encounter JSON data cannot be read -- Overhauled the region map editor, adding support for tilemaps, and significant customization. Also now supports pokefirered. - Metatiles are always rendered accurately with 3 layers, and the unused layer is not assumed to be transparent. - `object_event_graphics_info.h` can now be parsed correctly if it uses structs with attributes. - Palette editor ui is updated a bit to allow hex and rgb value input. diff --git a/docsrc/manual/scripting-capabilities.rst b/docsrc/manual/scripting-capabilities.rst index 73950d4c..a18a6c5b 100644 --- a/docsrc/manual/scripting-capabilities.rst +++ b/docsrc/manual/scripting-capabilities.rst @@ -1054,6 +1054,22 @@ The following functions are related to tilesets and how they are rendered. The f :param number metatileId: id of target metatile :param number behavior: the behavior +.. js:function:: map.getMetatileAttributes(metatileId) + + Gets the raw attributes value for the specified metatile. + + :param number metatileId: id of target metatile + :returns number: the raw attributes value + +.. js:function:: map.setMetatileAttributes(metatileId, attributes) + + Sets the raw attributes value for the specified metatile. + + **Warning:** This function writes directly to the tileset. There is no undo for this. Porymap will not limit the value of existing attributes to their usual range. + + :param number metatileId: id of target metatile + :param number attributes: the raw attributes value + .. js:function:: map.getMetatileTile(metatileId, tileIndex) Gets the tile at the specified index of the metatile. diff --git a/include/mainwindow.h b/include/mainwindow.h index 19b8cbef..94c595cb 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -167,6 +167,8 @@ public: Q_INVOKABLE void setMetatileTerrainType(int metatileId, int terrainType); Q_INVOKABLE int getMetatileBehavior(int metatileId); Q_INVOKABLE void setMetatileBehavior(int metatileId, int behavior); + Q_INVOKABLE int getMetatileAttributes(int metatileId); + Q_INVOKABLE void setMetatileAttributes(int metatileId, int attributes); Q_INVOKABLE QJSValue getMetatileTile(int metatileId, int tileIndex); Q_INVOKABLE void setMetatileTile(int metatileId, int tileIndex, int tileId, bool xflip, bool yflip, int palette, bool forceRedraw = true); Q_INVOKABLE void setMetatileTile(int metatileId, int tileIndex, QJSValue tileObj, bool forceRedraw = true); diff --git a/src/mainwindow_scriptapi.cpp b/src/mainwindow_scriptapi.cpp index 784a0354..10ca897a 100644 --- a/src/mainwindow_scriptapi.cpp +++ b/src/mainwindow_scriptapi.cpp @@ -961,6 +961,22 @@ void MainWindow::setMetatileBehavior(int metatileId, int behavior) { this->saveMetatileAttributesByMetatileId(metatileId); } +int MainWindow::getMetatileAttributes(int metatileId) { + Metatile * metatile = this->getMetatile(metatileId); + if (!metatile) + return -1; + return metatile->getAttributes(projectConfig.getBaseGameVersion()); +} + +void MainWindow::setMetatileAttributes(int metatileId, int attributes) { + Metatile * metatile = this->getMetatile(metatileId); + uint32_t u_attributes = static_cast(attributes); + if (!metatile) + return; + metatile->setAttributes(u_attributes, projectConfig.getBaseGameVersion()); + this->saveMetatileAttributesByMetatileId(metatileId); +} + int MainWindow::calculateTileBounds(int * tileStart, int * tileEnd) { int maxNumTiles = this->getNumTilesInMetatile(); if (*tileEnd >= maxNumTiles || *tileEnd < 0) From 46b4b51302e483a13b811c3cd9e9e53d013970a1 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Mon, 29 Aug 2022 13:14:06 -0400 Subject: [PATCH 10/10] Handle negative coordinates in Map::setBlock --- src/core/map.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/map.cpp b/src/core/map.cpp index baee10a3..d7936524 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -344,6 +344,7 @@ bool Map::getBlock(int x, int y, Block *out) { } void Map::setBlock(int x, int y, Block block, bool enableScriptCallback) { + if (!isWithinBounds(x, y)) return; int i = y * getWidth() + x; if (i < layout->blockdata.size()) { Block prevBlock = layout->blockdata.at(i);