From dac4a0e8f749e96fcdf9f6d9b98f55c4088e1bf1 Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Wed, 1 Jul 2020 20:19:08 -0500 Subject: [PATCH] Add scripting api for metatile layer draw order --- include/core/map.h | 1 + include/mainwindow.h | 2 ++ include/ui/imageproviders.h | 3 ++- include/ui/metatileselector.h | 9 ++++++--- include/ui/tileseteditor.h | 8 +++++--- include/ui/tileseteditormetatileselector.h | 5 ++++- src/core/map.cpp | 7 ++++--- src/editor.cpp | 2 +- src/mainwindow.cpp | 10 ++++++---- src/mainwindow_scriptapi.cpp | 13 ++++++++++++ src/ui/bordermetatilespixmapitem.cpp | 2 +- src/ui/currentselectedmetatilespixmapitem.cpp | 6 +++++- src/ui/imageproviders.cpp | 18 ++++++++++++++--- src/ui/metatileselector.cpp | 2 +- src/ui/tileseteditor.cpp | 20 +++++++++++-------- src/ui/tileseteditormetatileselector.cpp | 8 +++++++- 16 files changed, 85 insertions(+), 31 deletions(-) diff --git a/include/core/map.h b/include/core/map.h index a679a55b..e41052fa 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -57,6 +57,7 @@ public: History metatileHistory; QMap> events; QList connections; + QList metatileLayerOrder; void setName(QString mapName); static QString mapConstantFromName(QString mapName); static QString objectEventsLabelFromName(QString mapName); diff --git a/include/mainwindow.h b/include/mainwindow.h index 06bf9853..9f12374b 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -104,6 +104,8 @@ public: Q_INVOKABLE void setTimeout(QJSValue callback, int milliseconds); void invokeCallback(QJSValue callback); Q_INVOKABLE void log(QString message); + Q_INVOKABLE QList getMetatileLayerOrder(); + Q_INVOKABLE void setMetatileLayerOrder(QList order); public slots: diff --git a/include/ui/imageproviders.h b/include/ui/imageproviders.h index 89dfdce9..8042c440 100644 --- a/include/ui/imageproviders.h +++ b/include/ui/imageproviders.h @@ -8,7 +8,8 @@ QImage getCollisionMetatileImage(Block); QImage getCollisionMetatileImage(int, int); -QImage getMetatileImage(uint16_t, Tileset*, Tileset*, bool useTruePalettes = false); +QImage getMetatileImage(uint16_t, Tileset*, Tileset*, QList, bool useTruePalettes = false); +QImage getMetatileImage(uint16_t tile, Tileset*, Tileset*, bool useTruePalettes = false); QImage getTileImage(uint16_t, Tileset*, Tileset*); QImage getPalettedTileImage(uint16_t, Tileset*, Tileset*, int, bool useTruePalettes = false); QImage getGreyscaleTileImage(uint16_t tile, Tileset *primaryTileset, Tileset *secondaryTileset); diff --git a/include/ui/metatileselector.h b/include/ui/metatileselector.h index 1a8dc59c..486461b7 100644 --- a/include/ui/metatileselector.h +++ b/include/ui/metatileselector.h @@ -3,17 +3,19 @@ #include #include "selectablepixmapitem.h" +#include "map.h" #include "tileset.h" #include "maplayout.h" class MetatileSelector: public SelectablePixmapItem { Q_OBJECT public: - MetatileSelector(int numMetatilesWide, Tileset *primaryTileset, Tileset *secondaryTileset): SelectablePixmapItem(16, 16) { + MetatileSelector(int numMetatilesWide, Map *map): SelectablePixmapItem(16, 16) { this->externalSelection = false; this->numMetatilesWide = numMetatilesWide; - this->primaryTileset = primaryTileset; - this->secondaryTileset = secondaryTileset; + this->map = map; + this->primaryTileset = map->layout->tileset_primary; + this->secondaryTileset = map->layout->tileset_secondary; this->selectedMetatiles = new QList(); this->selectedCollisions = new QList>(); this->externalSelectedMetatiles = new QList(); @@ -37,6 +39,7 @@ protected: private: bool externalSelection; int numMetatilesWide; + Map *map; Tileset *primaryTileset; Tileset *secondaryTileset; QList *selectedMetatiles; diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index 75c8b245..2dedcb39 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -8,6 +8,7 @@ #include "tileseteditormetatileselector.h" #include "tileseteditortileselector.h" #include "metatilelayersitem.h" +#include "map.h" namespace Ui { class TilesetEditor; @@ -34,10 +35,10 @@ class TilesetEditor : public QMainWindow Q_OBJECT public: - explicit TilesetEditor(Project*, QString, QString, QWidget *parent = nullptr); + explicit TilesetEditor(Project*, Map*, QWidget *parent = nullptr); ~TilesetEditor(); + void setMap(Map*); void setTilesets(QString, QString); - void init(Project*, QString, QString); void selectMetatile(uint16_t metatileId); private slots: @@ -91,8 +92,9 @@ private slots: void on_actionImport_Secondary_Metatiles_triggered(); private: + void init(Project*, Map*); void closeEvent(QCloseEvent*); - void initMetatileSelector(); + void initMetatileSelector(Map*); void initTileSelector(); void initSelectedTileItem(); void initMetatileLayersItem(); diff --git a/include/ui/tileseteditormetatileselector.h b/include/ui/tileseteditormetatileselector.h index e1d1f829..253bc360 100644 --- a/include/ui/tileseteditormetatileselector.h +++ b/include/ui/tileseteditormetatileselector.h @@ -3,16 +3,19 @@ #include "selectablepixmapitem.h" #include "tileset.h" +#include "map.h" class TilesetEditorMetatileSelector: public SelectablePixmapItem { Q_OBJECT public: - TilesetEditorMetatileSelector(Tileset *primaryTileset, Tileset *secondaryTileset): SelectablePixmapItem(32, 32, 1, 1) { + TilesetEditorMetatileSelector(Tileset *primaryTileset, Tileset *secondaryTileset, Map *map): SelectablePixmapItem(32, 32, 1, 1) { this->primaryTileset = primaryTileset; this->secondaryTileset = secondaryTileset; this->numMetatilesWide = 8; + this->map = map; setAcceptHoverEvents(true); } + Map *map = nullptr; void draw(); void select(uint16_t metatileId); void setTilesets(Tileset*, Tileset*); diff --git a/src/core/map.cpp b/src/core/map.cpp index 2e777190..0f739b68 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -158,7 +158,7 @@ QPixmap Map::renderCollision(qreal opacity, bool ignoreCache) { } changed_any = true; Block block = layout->blockdata->blocks->value(i); - QImage metatile_image = getMetatileImage(block.tile, layout->tileset_primary, layout->tileset_secondary); + QImage metatile_image = getMetatileImage(block.tile, layout->tileset_primary, layout->tileset_secondary, metatileLayerOrder); QImage collision_metatile_image = getCollisionMetatileImage(block); int map_y = width_ ? i / width_ : 0; int map_x = width_ ? i % width_ : 0; @@ -205,7 +205,8 @@ QPixmap Map::render(bool ignoreCache = false, MapLayout * fromLayout) { QImage metatile_image = getMetatileImage( block.tile, fromLayout ? fromLayout->tileset_primary : layout->tileset_primary, - fromLayout ? fromLayout->tileset_secondary : layout->tileset_secondary + fromLayout ? fromLayout->tileset_secondary : layout->tileset_secondary, + metatileLayerOrder ); int map_y = width_ ? i / width_ : 0; int map_x = width_ ? i % width_ : 0; @@ -246,7 +247,7 @@ QPixmap Map::renderBorder(bool ignoreCache) { changed_any = true; Block block = layout->border->blocks->value(i); uint16_t tile = block.tile; - QImage metatile_image = getMetatileImage(tile, layout->tileset_primary, layout->tileset_secondary); + QImage metatile_image = getMetatileImage(tile, layout->tileset_primary, layout->tileset_secondary, metatileLayerOrder); int map_y = width_ ? i / width_ : 0; int map_x = width_ ? i % width_ : 0; painter.drawImage(QPoint(map_x * 16, map_y * 16), metatile_image); diff --git a/src/editor.cpp b/src/editor.cpp index 59bcedf2..91bf9166 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1212,7 +1212,7 @@ void Editor::displayMetatileSelector() { scene_metatiles = new QGraphicsScene; if (!metatile_selector_item) { - metatile_selector_item = new MetatileSelector(8, map->layout->tileset_primary, map->layout->tileset_secondary); + metatile_selector_item = new MetatileSelector(8, map); connect(metatile_selector_item, SIGNAL(hoveredMetatileSelectionChanged(uint16_t)), this, SLOT(onHoveredMetatileSelectionChanged(uint16_t))); connect(metatile_selector_item, SIGNAL(hoveredMetatileSelectionCleared()), diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 779a3259..353c418d 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -327,6 +327,7 @@ bool MainWindow::openProject(QString dir) { this->closeSupplementaryWindows(); this->setProjectSpecificUIVisibility(); + Scripting::init(this); bool already_open = isProjectOpen() && (editor->project->root == dir); if (!already_open) { editor->closeProject(); @@ -365,7 +366,6 @@ bool MainWindow::openProject(QString dir) { for (auto action : this->registeredActions) { this->ui->menuTools->removeAction(action); } - Scripting::init(this); Scripting::cb_ProjectOpened(dir); } @@ -470,9 +470,9 @@ bool MainWindow::setMap(QString map_name, bool scrollTreeView) { setRecentMap(map_name); updateMapList(); - updateTilesetEditor(); Scripting::cb_MapOpened(map_name); + updateTilesetEditor(); return true; } @@ -1140,6 +1140,7 @@ void MainWindow::on_actionNew_Tileset_triggered() { void MainWindow::updateTilesetEditor() { if (this->tilesetEditor) { + this->tilesetEditor->setMap(this->editor->map); this->tilesetEditor->setTilesets(editor->ui->comboBox_PrimaryTileset->currentText(), editor->ui->comboBox_SecondaryTileset->currentText()); } } @@ -1693,7 +1694,7 @@ void MainWindow::updateSelectedObjects() { combo->addItem(value); } connect(combo, static_cast(&QComboBox::currentTextChanged), - this, [this, item, frame](QString value){ + this, [this, item](QString value){ item->event->setFrameFromMovement(editor->project->facingDirections.value(value)); item->updatePixmap(); }); @@ -2439,7 +2440,8 @@ void MainWindow::on_checkBox_ToggleBorder_stateChanged(int selected) void MainWindow::on_actionTileset_Editor_triggered() { if (!this->tilesetEditor) { - this->tilesetEditor = new TilesetEditor(this->editor->project, this->editor->map->layout->tileset_primary_label, this->editor->map->layout->tileset_secondary_label, this); + logInfo("new one"); + this->tilesetEditor = new TilesetEditor(this->editor->project, this->editor->map, this); connect(this->tilesetEditor, SIGNAL(tilesetsSaved(QString, QString)), this, SLOT(onTilesetsSaved(QString, QString))); connect(this->tilesetEditor, &QObject::destroyed, [=](QObject *) { this->tilesetEditor = nullptr; }); this->tilesetEditor->setAttribute(Qt::WA_DeleteOnClose); diff --git a/src/mainwindow_scriptapi.cpp b/src/mainwindow_scriptapi.cpp index 1df8afb9..2a224c87 100644 --- a/src/mainwindow_scriptapi.cpp +++ b/src/mainwindow_scriptapi.cpp @@ -507,3 +507,16 @@ void MainWindow::invokeCallback(QJSValue callback) { void MainWindow::log(QString message) { logInfo(message); } + +QList MainWindow::getMetatileLayerOrder() { + if (!this->editor || !this->editor->map) + return QList(); + return this->editor->map->metatileLayerOrder; +} + +void MainWindow::setMetatileLayerOrder(QList order) { + if (!this->editor || !this->editor->map) + return; + this->editor->map->metatileLayerOrder = order; + this->refreshAfterPalettePreviewChange(); +} diff --git a/src/ui/bordermetatilespixmapitem.cpp b/src/ui/bordermetatilespixmapitem.cpp index e7a024b7..51b1a798 100644 --- a/src/ui/bordermetatilespixmapitem.cpp +++ b/src/ui/bordermetatilespixmapitem.cpp @@ -35,7 +35,7 @@ void BorderMetatilesPixmapItem::draw() { int x = i * 16; int y = j * 16; int index = j * width + i; - QImage metatile_image = getMetatileImage(blocks->value(index).tile, map->layout->tileset_primary, map->layout->tileset_secondary); + QImage metatile_image = getMetatileImage(blocks->value(index).tile, map->layout->tileset_primary, map->layout->tileset_secondary, map->metatileLayerOrder); QPoint metatile_origin = QPoint(x, y); painter.drawImage(metatile_origin, metatile_image); } diff --git a/src/ui/currentselectedmetatilespixmapitem.cpp b/src/ui/currentselectedmetatilespixmapitem.cpp index e0b2f7d6..2b47d618 100644 --- a/src/ui/currentselectedmetatilespixmapitem.cpp +++ b/src/ui/currentselectedmetatilespixmapitem.cpp @@ -15,7 +15,11 @@ void CurrentSelectedMetatilesPixmapItem::draw() { int x = i * 16; int y = j * 16; int index = j * selectionDimensions.x() + i; - QImage metatile_image = getMetatileImage(selectedMetatiles->at(index), map->layout->tileset_primary, map->layout->tileset_secondary); + QImage metatile_image = getMetatileImage( + selectedMetatiles->at(index), + map->layout->tileset_primary, + map->layout->tileset_secondary, + map->metatileLayerOrder); QPoint metatile_origin = QPoint(x, y); painter.drawImage(metatile_origin, metatile_image); } diff --git a/src/ui/imageproviders.cpp b/src/ui/imageproviders.cpp index e32026ca..01b6e7a5 100644 --- a/src/ui/imageproviders.cpp +++ b/src/ui/imageproviders.cpp @@ -14,7 +14,18 @@ QImage getCollisionMetatileImage(int collision, int elevation) { return collisionImage.toImage(); } +static QList defaultLayerOrder = QList({0, 1, 2}); + QImage getMetatileImage(uint16_t tile, Tileset *primaryTileset, Tileset *secondaryTileset, bool useTruePalettes) { + return getMetatileImage( + tile, + primaryTileset, + secondaryTileset, + defaultLayerOrder, + useTruePalettes); +} + +QImage getMetatileImage(uint16_t tile, Tileset *primaryTileset, Tileset *secondaryTileset, QList layerOrder, bool useTruePalettes) { QImage metatile_image(16, 16, QImage::Format_RGBA8888); Metatile* metatile = Tileset::getMetatile(tile, primaryTileset, secondaryTileset); @@ -36,14 +47,15 @@ QImage getMetatileImage(uint16_t tile, Tileset *primaryTileset, Tileset *seconda for (int layer = 0; layer < numLayers; layer++) for (int y = 0; y < 2; y++) for (int x = 0; x < 2; x++) { - Tile tile_ = metatile->tiles->value((y * 2) + x + (layer * 4)); + int l = layerOrder.size() >= numLayers ? layerOrder[layer] : layer; + Tile tile_ = metatile->tiles->value((y * 2) + x + (l * 4)); QImage tile_image = getTileImage(tile_.tile, primaryTileset, secondaryTileset); if (tile_image.isNull()) { // Some metatiles specify tiles that are outside the valid range. // These are treated as completely transparent, so they can be skipped without // being drawn unless they're on the bottom layer, in which case we need // a placeholder because garbage will be drawn otherwise. - if (layer == 0) { + if (l == 0) { metatile_painter.fillRect(x * 8, y * 8, 8, 8, palettes.value(0).value(0)); } continue; @@ -60,7 +72,7 @@ QImage getMetatileImage(uint16_t tile, Tileset *primaryTileset, Tileset *seconda } // The top layer of the metatile has its first color displayed at transparent. - if (layer > 0) { + if (l > 0) { QColor color(tile_image.color(0)); color.setAlpha(0); tile_image.setColor(0, color.rgba()); diff --git a/src/ui/metatileselector.cpp b/src/ui/metatileselector.cpp index cfe270e5..60f6fff0 100644 --- a/src/ui/metatileselector.cpp +++ b/src/ui/metatileselector.cpp @@ -31,7 +31,7 @@ void MetatileSelector::draw() { if (i >= primaryLength) { tile += Project::getNumMetatilesPrimary() - primaryLength; } - QImage metatile_image = getMetatileImage(tile, this->primaryTileset, this->secondaryTileset); + QImage metatile_image = getMetatileImage(tile, this->primaryTileset, this->secondaryTileset, map->metatileLayerOrder); int map_y = i / this->numMetatilesWide; int map_x = i % this->numMetatilesWide; QPoint metatile_origin = QPoint(map_x * 16, map_y * 16); diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index e038bd97..dda92d3e 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -12,11 +12,11 @@ #include #include -TilesetEditor::TilesetEditor(Project *project, QString primaryTilesetLabel, QString secondaryTilesetLabel, QWidget *parent) : +TilesetEditor::TilesetEditor(Project *project, Map *map, QWidget *parent) : QMainWindow(parent), ui(new Ui::TilesetEditor) { - this->init(project, primaryTilesetLabel, secondaryTilesetLabel); + this->init(project, map); new QShortcut(QKeySequence("Ctrl+Shift+Z"), this, SLOT(on_actionRedo_triggered())); } @@ -37,7 +37,7 @@ TilesetEditor::~TilesetEditor() delete metatileLayersScene; } -void TilesetEditor::init(Project *project, QString primaryTilesetLabel, QString secondaryTilesetLabel) { +void TilesetEditor::init(Project *project, Map *map) { ui->setupUi(this); this->project = project; @@ -46,8 +46,8 @@ void TilesetEditor::init(Project *project, QString primaryTilesetLabel, QString this->tileYFlip = ui->checkBox_yFlip->isChecked(); this->paletteId = ui->spinBox_paletteSelector->value(); - Tileset *primaryTileset = project->getTileset(primaryTilesetLabel); - Tileset *secondaryTileset = project->getTileset(secondaryTilesetLabel); + Tileset *primaryTileset = project->getTileset(map->layout->tileset_primary_label); + Tileset *secondaryTileset = project->getTileset(map->layout->tileset_secondary_label); if (this->primaryTileset) delete this->primaryTileset; if (this->secondaryTileset) delete this->secondaryTileset; this->primaryTileset = primaryTileset->copy(); @@ -95,7 +95,7 @@ void TilesetEditor::init(Project *project, QString primaryTilesetLabel, QString QRegExpValidator *validator = new QRegExpValidator(expression); this->ui->lineEdit_metatileLabel->setValidator(validator); - this->initMetatileSelector(); + this->initMetatileSelector(map); this->initMetatileLayersItem(); this->initTileSelector(); this->initSelectedTileItem(); @@ -111,6 +111,10 @@ void TilesetEditor::selectMetatile(uint16_t metatileId) { this->ui->scrollArea_Metatiles->ensureVisible(pos.x(), pos.y()); } +void TilesetEditor::setMap(Map *map) { + this->metatileSelector->map = map; +} + void TilesetEditor::setTilesets(QString primaryTilesetLabel, QString secondaryTilesetLabel) { delete this->primaryTileset; delete this->secondaryTileset; @@ -135,9 +139,9 @@ void TilesetEditor::refresh() { this->ui->graphicsView_selectedTile->setFixedSize(this->selectedTilePixmapItem->pixmap().width() + 2, this->selectedTilePixmapItem->pixmap().height() + 2); } -void TilesetEditor::initMetatileSelector() +void TilesetEditor::initMetatileSelector(Map *map) { - this->metatileSelector = new TilesetEditorMetatileSelector(this->primaryTileset, this->secondaryTileset); + this->metatileSelector = new TilesetEditorMetatileSelector(this->primaryTileset, this->secondaryTileset, map); connect(this->metatileSelector, SIGNAL(hoveredMetatileChanged(uint16_t)), this, SLOT(onHoveredMetatileChanged(uint16_t))); connect(this->metatileSelector, SIGNAL(hoveredMetatileCleared()), diff --git a/src/ui/tileseteditormetatileselector.cpp b/src/ui/tileseteditormetatileselector.cpp index bc91ea6e..44145047 100644 --- a/src/ui/tileseteditormetatileselector.cpp +++ b/src/ui/tileseteditormetatileselector.cpp @@ -23,7 +23,13 @@ void TilesetEditorMetatileSelector::draw() { if (i >= primaryLength) { tile += Project::getNumMetatilesPrimary() - primaryLength; } - QImage metatile_image = getMetatileImage(tile, this->primaryTileset, this->secondaryTileset, true).scaled(32, 32); + QImage metatile_image = getMetatileImage( + tile, + this->primaryTileset, + this->secondaryTileset, + map->metatileLayerOrder, + true) + .scaled(32, 32); int map_y = i / this->numMetatilesWide; int map_x = i % this->numMetatilesWide; QPoint metatile_origin = QPoint(map_x * 32, map_y * 32);