porymap/src/ui/tileseteditor.cpp

1131 lines
45 KiB
C++
Raw Normal View History

2018-09-29 20:13:07 +01:00
#include "tileseteditor.h"
#include "ui_tileseteditor.h"
#include "log.h"
#include "imageproviders.h"
#include "metatileparser.h"
#include "paletteutil.h"
#include "imageexport.h"
#include "config.h"
#include "shortcut.h"
2018-10-03 01:01:24 +01:00
#include <QFileDialog>
#include <QMessageBox>
#include <QDialogButtonBox>
#include <QCloseEvent>
#include <QImageReader>
2018-09-29 20:13:07 +01:00
TilesetEditor::TilesetEditor(Project *project, Map *map, QWidget *parent) :
2018-09-29 20:13:07 +01:00
QMainWindow(parent),
2020-09-25 13:20:51 +01:00
ui(new Ui::TilesetEditor),
project(project),
map(map),
hasUnsavedChanges(false)
2018-09-29 20:13:07 +01:00
{
2020-09-25 13:20:51 +01:00
this->setTilesets(this->map->layout->tileset_primary_label, this->map->layout->tileset_secondary_label);
this->initUi();
this->initMetatileHistory();
}
TilesetEditor::~TilesetEditor()
{
delete ui;
delete metatileSelector;
delete tileSelector;
delete metatileLayersItem;
delete paletteEditor;
delete metatile;
delete primaryTileset;
delete secondaryTileset;
delete metatilesScene;
delete tilesScene;
delete selectedTilePixmapItem;
delete selectedTileScene;
delete metatileLayersScene;
2022-03-30 23:03:13 +01:00
delete copiedMetatile;
}
2020-09-25 13:20:51 +01:00
void TilesetEditor::update(Map *map, QString primaryTilesetLabel, QString secondaryTilesetLabel) {
this->updateMap(map);
this->updateTilesets(primaryTilesetLabel, secondaryTilesetLabel);
}
void TilesetEditor::updateMap(Map *map) {
this->map = map;
this->metatileSelector->map = map;
}
2018-09-29 20:13:07 +01:00
2020-09-25 13:20:51 +01:00
void TilesetEditor::updateTilesets(QString primaryTilesetLabel, QString secondaryTilesetLabel) {
if (this->hasUnsavedChanges) {
QMessageBox::StandardButton result = QMessageBox::question(
this,
"porymap",
"Tileset has been modified, save changes?",
QMessageBox::No | QMessageBox::Yes,
QMessageBox::Yes);
if (result == QMessageBox::Yes)
this->on_actionSave_Tileset_triggered();
}
this->hasUnsavedChanges = false;
2020-09-25 13:20:51 +01:00
this->setTilesets(primaryTilesetLabel, secondaryTilesetLabel);
this->refresh();
}
2018-10-03 01:01:15 +01:00
2020-09-25 13:20:51 +01:00
bool TilesetEditor::selectMetatile(uint16_t metatileId) {
if (!Tileset::metatileIsValid(metatileId, this->primaryTileset, this->secondaryTileset)) return false;
this->metatileSelector->select(metatileId);
QPoint pos = this->metatileSelector->getMetatileIdCoordsOnWidget(metatileId);
this->ui->scrollArea_Metatiles->ensureVisible(pos.x(), pos.y());
return true;
}
2022-03-30 23:03:13 +01:00
uint16_t TilesetEditor::getSelectedMetatileId() {
return this->metatileSelector->getSelectedMetatileId();
2021-11-23 17:58:04 +00:00
}
2020-09-25 13:20:51 +01:00
void TilesetEditor::setTilesets(QString primaryTilesetLabel, QString secondaryTilesetLabel) {
Tileset *primaryTileset = project->getTileset(primaryTilesetLabel);
Tileset *secondaryTileset = project->getTileset(secondaryTilesetLabel);
if (this->primaryTileset) delete this->primaryTileset;
if (this->secondaryTileset) delete this->secondaryTileset;
2021-02-17 02:45:54 +00:00
this->primaryTileset = new Tileset(*primaryTileset);
this->secondaryTileset = new Tileset(*secondaryTileset);
2021-01-16 16:12:38 +00:00
if (paletteEditor) paletteEditor->setTilesets(this->primaryTileset, this->secondaryTileset);
2020-09-25 13:20:51 +01:00
}
void TilesetEditor::initUi() {
ui->setupUi(this);
this->tileXFlip = ui->checkBox_xFlip->isChecked();
this->tileYFlip = ui->checkBox_yFlip->isChecked();
this->paletteId = ui->spinBox_paletteSelector->value();
this->ui->spinBox_paletteSelector->setMinimum(0);
this->ui->spinBox_paletteSelector->setMaximum(Project::getNumPalettesTotal() - 1);
this->setMetatileBehaviors();
this->setMetatileLayersUi();
this->setVersionSpecificUi();
this->setMetatileLabelValidator();
this->initMetatileSelector();
this->initMetatileLayersItem();
this->initTileSelector();
this->initSelectedTileItem();
this->initShortcuts();
2020-09-25 13:20:51 +01:00
this->metatileSelector->select(0);
this->restoreWindowState();
}
2020-09-25 13:20:51 +01:00
void TilesetEditor::setMetatileBehaviors() {
for (int num : project->metatileBehaviorMapInverse.keys()) {
this->ui->comboBox_metatileBehaviors->addItem(project->metatileBehaviorMapInverse[num], num);
}
2020-09-25 13:20:51 +01:00
}
2020-09-25 13:20:51 +01:00
void TilesetEditor::setMetatileLayersUi() {
if (!projectConfig.getTripleLayerMetatilesEnabled()) {
this->ui->comboBox_layerType->addItem("Normal - Middle/Top", METATILE_LAYER_MIDDLE_TOP);
this->ui->comboBox_layerType->addItem("Covered - Bottom/Middle", METATILE_LAYER_BOTTOM_MIDDLE);
this->ui->comboBox_layerType->addItem("Split - Bottom/Top", METATILE_LAYER_BOTTOM_TOP);
} else {
this->ui->comboBox_layerType->setVisible(false);
this->ui->label_layerType->setVisible(false);
this->ui->label_BottomTop->setText("Bottom/Middle/Top");
}
2020-09-25 13:20:51 +01:00
}
2020-09-25 13:20:51 +01:00
void TilesetEditor::setVersionSpecificUi() {
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
this->ui->comboBox_encounterType->setVisible(true);
this->ui->label_encounterType->setVisible(true);
this->ui->comboBox_encounterType->addItem("None", ENCOUNTER_NONE);
this->ui->comboBox_encounterType->addItem("Land", ENCOUNTER_LAND);
this->ui->comboBox_encounterType->addItem("Water", ENCOUNTER_WATER);
this->ui->comboBox_terrainType->setVisible(true);
this->ui->label_terrainType->setVisible(true);
this->ui->comboBox_terrainType->addItem("Normal", TERRAIN_NONE);
this->ui->comboBox_terrainType->addItem("Grass", TERRAIN_GRASS);
this->ui->comboBox_terrainType->addItem("Water", TERRAIN_WATER);
this->ui->comboBox_terrainType->addItem("Waterfall", TERRAIN_WATERFALL);
} else {
this->ui->comboBox_encounterType->setVisible(false);
this->ui->label_encounterType->setVisible(false);
this->ui->comboBox_terrainType->setVisible(false);
this->ui->label_terrainType->setVisible(false);
}
2020-09-25 13:20:51 +01:00
}
2020-09-25 13:20:51 +01:00
void TilesetEditor::setMetatileLabelValidator() {
//only allow characters valid for a symbol
2021-02-06 00:43:49 +00:00
QRegularExpression expression("[_A-Za-z0-9]*$");
QRegularExpressionValidator *validator = new QRegularExpressionValidator(expression);
this->ui->lineEdit_metatileLabel->setValidator(validator);
}
2020-09-25 13:20:51 +01:00
void TilesetEditor::initMetatileSelector()
2018-09-29 20:13:07 +01:00
{
2020-09-25 13:20:51 +01:00
this->metatileSelector = new TilesetEditorMetatileSelector(this->primaryTileset, this->secondaryTileset, this->map);
connect(this->metatileSelector, &TilesetEditorMetatileSelector::hoveredMetatileChanged,
this, &TilesetEditor::onHoveredMetatileChanged);
connect(this->metatileSelector, &TilesetEditorMetatileSelector::hoveredMetatileCleared,
this, &TilesetEditor::onHoveredMetatileCleared);
connect(this->metatileSelector, &TilesetEditorMetatileSelector::selectedMetatileChanged,
this, &TilesetEditor::onSelectedMetatileChanged);
this->metatilesScene = new QGraphicsScene;
this->metatilesScene->addItem(this->metatileSelector);
this->metatileSelector->draw();
this->ui->graphicsView_Metatiles->setScene(this->metatilesScene);
this->ui->graphicsView_Metatiles->setFixedSize(this->metatileSelector->pixmap().width() + 2, this->metatileSelector->pixmap().height() + 2);
}
2020-09-25 13:20:51 +01:00
void TilesetEditor::initMetatileLayersItem() {
2022-03-30 23:03:13 +01:00
Metatile *metatile = Tileset::getMetatile(this->getSelectedMetatileId(), this->primaryTileset, this->secondaryTileset);
2020-09-25 13:20:51 +01:00
this->metatileLayersItem = new MetatileLayersItem(metatile, this->primaryTileset, this->secondaryTileset);
connect(this->metatileLayersItem, &MetatileLayersItem::tileChanged,
this, &TilesetEditor::onMetatileLayerTileChanged);
connect(this->metatileLayersItem, &MetatileLayersItem::selectedTilesChanged,
this, &TilesetEditor::onMetatileLayerSelectionChanged);
2020-09-25 13:20:51 +01:00
this->metatileLayersScene = new QGraphicsScene;
this->metatileLayersScene->addItem(this->metatileLayersItem);
this->ui->graphicsView_metatileLayers->setScene(this->metatileLayersScene);
}
void TilesetEditor::initTileSelector()
{
this->tileSelector = new TilesetEditorTileSelector(this->primaryTileset, this->secondaryTileset, projectConfig.getNumLayersInMetatile());
connect(this->tileSelector, &TilesetEditorTileSelector::hoveredTileChanged,
this, &TilesetEditor::onHoveredTileChanged);
connect(this->tileSelector, &TilesetEditorTileSelector::hoveredTileCleared,
this, &TilesetEditor::onHoveredTileCleared);
connect(this->tileSelector, &TilesetEditorTileSelector::selectedTilesChanged,
this, &TilesetEditor::onSelectedTilesChanged);
this->tilesScene = new QGraphicsScene;
this->tilesScene->addItem(this->tileSelector);
this->tileSelector->select(0);
this->tileSelector->draw();
this->ui->graphicsView_Tiles->setScene(this->tilesScene);
this->ui->graphicsView_Tiles->setFixedSize(this->tileSelector->pixmap().width() + 2, this->tileSelector->pixmap().height() + 2);
}
void TilesetEditor::initSelectedTileItem() {
this->selectedTileScene = new QGraphicsScene;
this->drawSelectedTiles();
this->ui->graphicsView_selectedTile->setScene(this->selectedTileScene);
2018-10-08 20:42:51 +01:00
this->ui->graphicsView_selectedTile->setFixedSize(this->selectedTilePixmapItem->pixmap().width() + 2, this->selectedTilePixmapItem->pixmap().height() + 2);
}
void TilesetEditor::initShortcuts() {
initExtraShortcuts();
shortcutsConfig.load();
shortcutsConfig.setDefaultShortcuts(shortcutableObjects());
applyUserShortcuts();
}
void TilesetEditor::initExtraShortcuts() {
ui->actionRedo->setShortcuts({ui->actionRedo->shortcut(), QKeySequence("Ctrl+Shift+Z")});
auto *shortcut_xFlip = new Shortcut(QKeySequence(), ui->checkBox_xFlip, SLOT(toggle()));
shortcut_xFlip->setObjectName("shortcut_xFlip");
shortcut_xFlip->setWhatsThis("X Flip");
auto *shortcut_yFlip = new Shortcut(QKeySequence(), ui->checkBox_yFlip, SLOT(toggle()));
shortcut_yFlip->setObjectName("shortcut_yFlip");
shortcut_yFlip->setWhatsThis("Y Flip");
}
QObjectList TilesetEditor::shortcutableObjects() const {
QObjectList shortcutable_objects;
for (auto *action : findChildren<QAction *>())
if (!action->objectName().isEmpty())
shortcutable_objects.append(qobject_cast<QObject *>(action));
for (auto *shortcut : findChildren<Shortcut *>())
if (!shortcut->objectName().isEmpty())
shortcutable_objects.append(qobject_cast<QObject *>(shortcut));
return shortcutable_objects;
}
void TilesetEditor::applyUserShortcuts() {
for (auto *action : findChildren<QAction *>())
if (!action->objectName().isEmpty())
action->setShortcuts(shortcutsConfig.userShortcuts(action));
for (auto *shortcut : findChildren<Shortcut *>())
if (!shortcut->objectName().isEmpty())
shortcut->setKeys(shortcutsConfig.userShortcuts(shortcut));
}
void TilesetEditor::restoreWindowState() {
logInfo("Restoring tileset editor geometry from previous session.");
QMap<QString, QByteArray> geometry = porymapConfig.getTilesetEditorGeometry();
this->restoreGeometry(geometry.value("tileset_editor_geometry"));
this->restoreState(geometry.value("tileset_editor_state"));
}
2020-09-25 13:20:51 +01:00
void TilesetEditor::initMetatileHistory() {
MetatileHistoryItem *commit = new MetatileHistoryItem(0, nullptr, new Metatile(*metatile));
2020-09-25 13:20:51 +01:00
metatileHistory.push(commit);
}
void TilesetEditor::reset() {
this->hasUnsavedChanges = false;
this->setTilesets(this->primaryTileset->name, this->secondaryTileset->name);
if (this->paletteEditor)
this->paletteEditor->setTilesets(this->primaryTileset, this->secondaryTileset);
this->refresh();
}
2020-09-25 13:20:51 +01:00
void TilesetEditor::refresh() {
this->metatileLayersItem->setTilesets(this->primaryTileset, this->secondaryTileset);
this->tileSelector->setTilesets(this->primaryTileset, this->secondaryTileset);
this->metatileSelector->setTilesets(this->primaryTileset, this->secondaryTileset);
2022-03-30 23:03:13 +01:00
this->metatileSelector->select(this->getSelectedMetatileId());
2020-09-25 13:20:51 +01:00
this->drawSelectedTiles();
if (metatileSelector) {
if (metatileSelector->selectorShowUnused || metatileSelector->selectorShowCounts) {
countMetatileUsage();
this->metatileSelector->draw();
}
}
2021-07-21 23:55:33 +01:00
if (tileSelector) {
if (tileSelector->showUnused) {
countTileUsage();
this->tileSelector->draw();
}
}
2020-09-25 13:20:51 +01:00
this->ui->graphicsView_Tiles->setSceneRect(0, 0, this->tileSelector->pixmap().width() + 2, this->tileSelector->pixmap().height() + 2);
this->ui->graphicsView_Tiles->setFixedSize(this->tileSelector->pixmap().width() + 2, this->tileSelector->pixmap().height() + 2);
this->ui->graphicsView_Metatiles->setSceneRect(0, 0, this->metatileSelector->pixmap().width() + 2, this->metatileSelector->pixmap().height() + 2);
this->ui->graphicsView_Metatiles->setFixedSize(this->metatileSelector->pixmap().width() + 2, this->metatileSelector->pixmap().height() + 2);
this->ui->graphicsView_selectedTile->setFixedSize(this->selectedTilePixmapItem->pixmap().width() + 2, this->selectedTilePixmapItem->pixmap().height() + 2);
}
void TilesetEditor::drawSelectedTiles() {
if (!this->selectedTileScene) {
return;
}
2018-09-30 22:15:04 +01:00
this->selectedTileScene->clear();
QList<Tile> tiles = this->tileSelector->getSelectedTiles();
QPoint dimensions = this->tileSelector->getSelectionDimensions();
2018-10-03 01:01:34 +01:00
QImage selectionImage(16 * dimensions.x(), 16 * dimensions.y(), QImage::Format_RGBA8888);
QPainter painter(&selectionImage);
int tileIndex = 0;
for (int j = 0; j < dimensions.y(); j++) {
for (int i = 0; i < dimensions.x(); i++) {
QImage tileImage = getPalettedTileImage(tiles.at(tileIndex).tileId, this->primaryTileset, this->secondaryTileset, tiles.at(tileIndex).palette, true)
.mirrored(tiles.at(tileIndex).xflip, tiles.at(tileIndex).yflip)
2018-10-03 01:01:34 +01:00
.scaled(16, 16);
tileIndex++;
2018-10-03 01:01:34 +01:00
painter.drawImage(i * 16, j * 16, tileImage);
}
}
this->selectedTilePixmapItem = new QGraphicsPixmapItem(QPixmap::fromImage(selectionImage));
this->selectedTileScene->addItem(this->selectedTilePixmapItem);
2018-10-08 20:42:51 +01:00
this->ui->graphicsView_selectedTile->setFixedSize(this->selectedTilePixmapItem->pixmap().width() + 2, this->selectedTilePixmapItem->pixmap().height() + 2);
}
void TilesetEditor::onHoveredMetatileChanged(uint16_t metatileId) {
Metatile *metatile = Tileset::getMetatile(metatileId, this->primaryTileset, this->secondaryTileset);
QString message;
QString hexString = QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper();
if (metatile && metatile->label.size() != 0) {
message = QString("Metatile: 0x%1 \"%2\"").arg(hexString, metatile->label);
} else {
message = QString("Metatile: 0x%1").arg(hexString);
}
this->ui->statusbar->showMessage(message);
}
void TilesetEditor::onHoveredMetatileCleared() {
this->ui->statusbar->clearMessage();
}
void TilesetEditor::setComboValue(QComboBox * combo, int value) {
int index = combo->findData(value);
if (index >= 0) {
// Valid item
combo->setCurrentIndex(index);
} else if (combo->isEditable()) {
// Invalid item in editable box, just display the text
combo->setCurrentText(QString::number(value));
} else {
// Invalid item in uneditable box, display text as placeholder
// On Qt < 5.15 this will display an empty box
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
combo->setPlaceholderText(QString::number(value));
#endif
combo->setCurrentIndex(index);
}
}
2018-09-30 22:15:04 +01:00
void TilesetEditor::onSelectedMetatileChanged(uint16_t metatileId) {
2018-10-03 01:01:15 +01:00
this->metatile = Tileset::getMetatile(metatileId, this->primaryTileset, this->secondaryTileset);
2018-09-30 22:15:04 +01:00
this->metatileLayersItem->setMetatile(metatile);
this->metatileLayersItem->draw();
this->ui->graphicsView_metatileLayers->setFixedSize(this->metatileLayersItem->pixmap().width() + 2, this->metatileLayersItem->pixmap().height() + 2);
this->ui->lineEdit_metatileLabel->setText(this->metatile->label);
setComboValue(this->ui->comboBox_metatileBehaviors, this->metatile->behavior);
if (!projectConfig.getTripleLayerMetatilesEnabled()) {
setComboValue(this->ui->comboBox_layerType, this->metatile->layerType);
}
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
setComboValue(this->ui->comboBox_encounterType, this->metatile->encounterType);
setComboValue(this->ui->comboBox_terrainType, this->metatile->terrainType);
}
2018-09-29 20:13:07 +01:00
}
void TilesetEditor::onHoveredTileChanged(uint16_t tile) {
QString message = QString("Tile: 0x%1")
.arg(QString("%1").arg(tile, 3, 16, QChar('0')).toUpper());
this->ui->statusbar->showMessage(message);
}
void TilesetEditor::onHoveredTileCleared() {
this->ui->statusbar->clearMessage();
}
void TilesetEditor::onSelectedTilesChanged() {
this->drawSelectedTiles();
}
void TilesetEditor::onMetatileLayerTileChanged(int x, int y) {
2021-02-16 17:14:27 +00:00
static const QList<QPoint> tileCoords = QList<QPoint>{
QPoint(0, 0),
QPoint(1, 0),
QPoint(0, 1),
QPoint(1, 1),
QPoint(2, 0),
QPoint(3, 0),
QPoint(2, 1),
QPoint(3, 1),
QPoint(4, 0),
QPoint(5, 0),
QPoint(4, 1),
QPoint(5, 1),
};
Metatile *prevMetatile = new Metatile(*this->metatile);
QPoint dimensions = this->tileSelector->getSelectionDimensions();
QList<Tile> tiles = this->tileSelector->getSelectedTiles();
int selectedTileIndex = 0;
int maxTileIndex = projectConfig.getNumTilesInMetatile();
for (int j = 0; j < dimensions.y(); j++) {
for (int i = 0; i < dimensions.x(); i++) {
int tileIndex = ((x + i) / 2 * 4) + ((y + j) * 2) + ((x + i) % 2);
if (tileIndex < maxTileIndex
&& tileCoords.at(tileIndex).x() >= x
&& tileCoords.at(tileIndex).y() >= y){
2021-02-16 17:14:27 +00:00
Tile &tile = this->metatile->tiles[tileIndex];
tile.tileId = tiles.at(selectedTileIndex).tileId;
2021-02-16 17:14:27 +00:00
tile.xflip = tiles.at(selectedTileIndex).xflip;
tile.yflip = tiles.at(selectedTileIndex).yflip;
tile.palette = tiles.at(selectedTileIndex).palette;
}
selectedTileIndex++;
}
}
2018-09-30 22:15:04 +01:00
this->metatileSelector->draw();
this->metatileLayersItem->draw();
this->hasUnsavedChanges = true;
2022-03-30 23:03:13 +01:00
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(),
prevMetatile, new Metatile(*this->metatile));
metatileHistory.push(commit);
2018-09-30 22:15:04 +01:00
}
void TilesetEditor::onMetatileLayerSelectionChanged(QPoint selectionOrigin, int width, int height) {
QList<Tile> tiles;
QList<int> tileIdxs;
int x = selectionOrigin.x();
int y = selectionOrigin.y();
int maxTileIndex = projectConfig.getNumTilesInMetatile();
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
int tileIndex = ((x + i) / 2 * 4) + ((y + j) * 2) + ((x + i) % 2);
if (tileIndex < maxTileIndex) {
2021-02-16 17:14:27 +00:00
tiles.append(this->metatile->tiles.at(tileIndex));
tileIdxs.append(tileIndex);
}
}
}
2018-10-08 20:42:51 +01:00
if (width == 1 && height == 1) {
this->tileSelector->highlight(static_cast<uint16_t>(tiles[0].tileId));
2018-10-08 20:42:51 +01:00
ui->spinBox_paletteSelector->setValue(tiles[0].palette);
QPoint pos = tileSelector->getTileCoordsOnWidget(static_cast<uint16_t>(tiles[0].tileId));
ui->scrollArea_Tiles->ensureVisible(pos.x(), pos.y());
}
this->tileSelector->setExternalSelection(width, height, tiles, tileIdxs);
this->metatileLayersItem->clearLastModifiedCoords();
}
void TilesetEditor::on_spinBox_paletteSelector_valueChanged(int paletteId)
{
2018-10-03 01:01:41 +01:00
this->ui->spinBox_paletteSelector->blockSignals(true);
this->ui->spinBox_paletteSelector->setValue(paletteId);
this->ui->spinBox_paletteSelector->blockSignals(false);
this->paletteId = paletteId;
this->tileSelector->setPaletteId(paletteId);
this->drawSelectedTiles();
2018-10-03 01:01:41 +01:00
if (this->paletteEditor) {
this->paletteEditor->setPaletteId(paletteId);
}
this->metatileLayersItem->clearLastModifiedCoords();
}
void TilesetEditor::on_checkBox_xFlip_stateChanged(int checked)
{
this->tileXFlip = checked;
this->tileSelector->setTileFlips(this->tileXFlip, this->tileYFlip);
this->drawSelectedTiles();
this->metatileLayersItem->clearLastModifiedCoords();
}
void TilesetEditor::on_checkBox_yFlip_stateChanged(int checked)
{
this->tileYFlip = checked;
this->tileSelector->setTileFlips(this->tileXFlip, this->tileYFlip);
this->drawSelectedTiles();
this->metatileLayersItem->clearLastModifiedCoords();
}
2021-02-06 00:43:49 +00:00
void TilesetEditor::on_comboBox_metatileBehaviors_textActivated(const QString &metatileBehavior)
{
if (this->metatile) {
Metatile *prevMetatile = new Metatile(*this->metatile);
this->metatile->behavior = static_cast<uint16_t>(project->metatileBehaviorMap[metatileBehavior]);
2022-03-30 23:03:13 +01:00
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(),
prevMetatile, new Metatile(*this->metatile));
metatileHistory.push(commit);
this->hasUnsavedChanges = true;
}
}
2021-11-23 17:58:04 +00:00
void TilesetEditor::setMetatileLabel(QString label)
{
this->ui->lineEdit_metatileLabel->setText(label);
saveMetatileLabel();
}
void TilesetEditor::on_lineEdit_metatileLabel_editingFinished()
{
saveMetatileLabel();
}
void TilesetEditor::saveMetatileLabel()
{
// Only commit if the field has changed.
if (this->metatile && this->metatile->label != this->ui->lineEdit_metatileLabel->text()) {
Metatile *prevMetatile = new Metatile(*this->metatile);
this->metatile->label = this->ui->lineEdit_metatileLabel->text();
2022-03-30 23:03:13 +01:00
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(),
prevMetatile, new Metatile(*this->metatile));
metatileHistory.push(commit);
this->hasUnsavedChanges = true;
}
}
void TilesetEditor::on_comboBox_layerType_activated(int layerType)
{
if (this->metatile) {
Metatile *prevMetatile = new Metatile(*this->metatile);
this->metatile->layerType = static_cast<uint8_t>(layerType);
2022-03-30 23:03:13 +01:00
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(),
prevMetatile, new Metatile(*this->metatile));
metatileHistory.push(commit);
this->hasUnsavedChanges = true;
this->metatileSelector->draw(); // Changing the layer type can affect how fully transparent metatiles appear
}
}
void TilesetEditor::on_comboBox_encounterType_activated(int encounterType)
{
if (this->metatile) {
Metatile *prevMetatile = new Metatile(*this->metatile);
this->metatile->encounterType = static_cast<uint8_t>(encounterType);
2022-03-30 23:03:13 +01:00
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(),
prevMetatile, new Metatile(*this->metatile));
metatileHistory.push(commit);
this->hasUnsavedChanges = true;
}
}
void TilesetEditor::on_comboBox_terrainType_activated(int terrainType)
{
if (this->metatile) {
Metatile *prevMetatile = new Metatile(*this->metatile);
this->metatile->terrainType = static_cast<uint8_t>(terrainType);
2022-03-30 23:03:13 +01:00
MetatileHistoryItem *commit = new MetatileHistoryItem(this->getSelectedMetatileId(),
prevMetatile, new Metatile(*this->metatile));
metatileHistory.push(commit);
this->hasUnsavedChanges = true;
}
}
void TilesetEditor::on_actionSave_Tileset_triggered()
{
// need this temporary metatile ID to reset selection after saving
// when the tilesetsSaved signal is sent, it will be reset to the current map metatile
uint16_t reselectMetatileID = this->metatileSelector->getSelectedMetatileId();
saveMetatileLabel();
2018-10-03 01:01:15 +01:00
this->project->saveTilesets(this->primaryTileset, this->secondaryTileset);
emit this->tilesetsSaved(this->primaryTileset->name, this->secondaryTileset->name);
this->metatileSelector->select(reselectMetatileID);
if (this->paletteEditor) {
this->paletteEditor->setTilesets(this->primaryTileset, this->secondaryTileset);
}
2018-10-03 01:01:21 +01:00
this->ui->statusbar->showMessage(QString("Saved primary and secondary Tilesets!"), 5000);
this->hasUnsavedChanges = false;
}
2018-10-03 01:01:24 +01:00
void TilesetEditor::on_actionImport_Primary_Tiles_triggered()
{
this->importTilesetTiles(this->primaryTileset, true);
}
void TilesetEditor::on_actionImport_Secondary_Tiles_triggered()
{
this->importTilesetTiles(this->secondaryTileset, false);
}
void TilesetEditor::importTilesetTiles(Tileset *tileset, bool primary) {
QString descriptor = primary ? "primary" : "secondary";
QString descriptorCaps = primary ? "Primary" : "Secondary";
QString filepath = QFileDialog::getOpenFileName(
this,
QString("Import %1 Tileset Tiles Image").arg(descriptorCaps),
this->project->root,
"Image Files (*.png *.bmp *.jpg *.dib)");
2018-10-03 01:01:24 +01:00
if (filepath.isEmpty()) {
return;
}
logInfo(QString("Importing %1 tileset tiles '%2'").arg(descriptor).arg(filepath));
2018-10-03 01:01:24 +01:00
// Read image data from buffer so that the built-in QImage doesn't try to detect file format
// purely from the extension name. Advance Map exports ".png" files that are actually BMP format, for example.
QFile file(filepath);
QImage image;
if (file.open(QIODevice::ReadOnly)) {
QByteArray imageData = file.readAll();
image = QImage::fromData(imageData);
} else {
logError(QString("Failed to open image file: '%1'").arg(filepath));
}
2018-10-03 01:01:24 +01:00
if (image.width() == 0 || image.height() == 0 || image.width() % 8 != 0 || image.height() % 8 != 0) {
QMessageBox msgBox(this);
msgBox.setText("Failed to import tiles.");
msgBox.setInformativeText(QString("The image dimensions (%1 x %2) are invalid. Width and height must be multiples of 8 pixels.")
.arg(image.width())
.arg(image.height()));
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.setIcon(QMessageBox::Icon::Critical);
msgBox.exec();
return;
}
// Validate total number of tiles in image.
int numTilesWide = image.width() / 8;
int numTilesHigh = image.height() / 8;
2018-10-03 01:01:24 +01:00
int totalTiles = numTilesHigh * numTilesWide;
int maxAllowedTiles = primary ? Project::getNumTilesPrimary() : Project::getNumTilesTotal() - Project::getNumTilesPrimary();
if (totalTiles > maxAllowedTiles) {
QMessageBox msgBox(this);
msgBox.setText("Failed to import tiles.");
msgBox.setInformativeText(QString("The maximum number of tiles allowed in the %1 tileset is %2, but the provided image contains %3 total tiles.")
.arg(descriptor)
.arg(maxAllowedTiles)
.arg(totalTiles));
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.setIcon(QMessageBox::Icon::Critical);
msgBox.exec();
return;
}
// Ask user to provide a palette for the un-indexed image.
if (image.colorCount() == 0) {
QMessageBox msgBox(this);
msgBox.setText("Select Palette for Tiles");
msgBox.setInformativeText(QString("The provided image is not indexed. Please select a palette file for the image. An indexed image will be generated using the provided image and palette.")
.arg(image.colorCount()));
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.setIcon(QMessageBox::Icon::Warning);
msgBox.exec();
QString filepath = QFileDialog::getOpenFileName(
this,
QString("Select Palette for Tiles Image").arg(descriptorCaps),
this->project->root,
"Palette Files (*.pal *.act *tpl *gpl)");
if (filepath.isEmpty()) {
return;
}
bool error = false;
2021-02-18 08:25:26 +00:00
QList<QRgb> palette = PaletteUtil::parse(filepath, &error);
if (error) {
QMessageBox msgBox(this);
msgBox.setText("Failed to import palette.");
QString message = QString("The palette file could not be processed. View porymap.log for specific errors.");
msgBox.setInformativeText(message);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.setIcon(QMessageBox::Icon::Critical);
msgBox.exec();
return;
} else if (palette.length() != 16) {
QMessageBox msgBox(this);
msgBox.setText("Failed to import palette.");
QString message = QString("The palette must have exactly 16 colors, but it has %1.").arg(palette.length());
msgBox.setInformativeText(message);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.setIcon(QMessageBox::Icon::Critical);
msgBox.exec();
return;
}
QVector<QRgb> colorTable = palette.toVector();
image = image.convertToFormat(QImage::Format::Format_Indexed8, colorTable);
}
// Validate image is properly indexed to 16 colors.
if (image.colorCount() != 16) {
QMessageBox msgBox(this);
msgBox.setText("Failed to import tiles.");
msgBox.setInformativeText(QString("The image must be indexed and contain 16 total colors, or it must be un-indexed. The provided image has %1 indexed colors.")
.arg(image.colorCount()));
msgBox.setDefaultButton(QMessageBox::Ok);
2018-10-03 01:01:24 +01:00
msgBox.setIcon(QMessageBox::Icon::Critical);
msgBox.exec();
return;
}
this->project->loadTilesetTiles(tileset, image);
this->refresh();
this->hasUnsavedChanges = true;
}
void TilesetEditor::closeEvent(QCloseEvent *event)
{
if (this->hasUnsavedChanges) {
QMessageBox::StandardButton result = QMessageBox::question(
this,
"porymap",
"Tileset has been modified, save changes?",
QMessageBox::No | QMessageBox::Yes | QMessageBox::Cancel,
QMessageBox::Yes);
if (result == QMessageBox::Yes) {
this->on_actionSave_Tileset_triggered();
event->accept();
} else if (result == QMessageBox::No) {
this->reset();
event->accept();
} else if (result == QMessageBox::Cancel) {
event->ignore();
}
} else {
event->accept();
}
if (event->isAccepted()) {
if (this->paletteEditor) this->paletteEditor->close();
porymapConfig.setTilesetEditorGeometry(
this->saveGeometry(),
this->saveState()
);
}
2018-10-03 01:01:24 +01:00
}
void TilesetEditor::on_actionChange_Metatiles_Count_triggered()
{
QDialog dialog(this, Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
dialog.setWindowTitle("Change Number of Metatiles");
dialog.setWindowModality(Qt::NonModal);
QFormLayout form(&dialog);
QSpinBox *primarySpinBox = new QSpinBox();
QSpinBox *secondarySpinBox = new QSpinBox();
primarySpinBox->setMinimum(1);
secondarySpinBox->setMinimum(1);
primarySpinBox->setMaximum(Project::getNumMetatilesPrimary());
secondarySpinBox->setMaximum(Project::getNumMetatilesTotal() - Project::getNumMetatilesPrimary());
2021-02-17 02:45:54 +00:00
primarySpinBox->setValue(this->primaryTileset->metatiles.length());
secondarySpinBox->setValue(this->secondaryTileset->metatiles.length());
form.addRow(new QLabel("Primary Tileset"), primarySpinBox);
form.addRow(new QLabel("Secondary Tileset"), secondarySpinBox);
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog);
connect(&buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
connect(&buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
form.addRow(&buttonBox);
if (dialog.exec() == QDialog::Accepted) {
int numPrimaryMetatiles = primarySpinBox->value();
int numSecondaryMetatiles = secondarySpinBox->value();
int numTiles = projectConfig.getNumTilesInMetatile();
2021-02-17 02:45:54 +00:00
while (this->primaryTileset->metatiles.length() > numPrimaryMetatiles) {
delete this->primaryTileset->metatiles.takeLast();
}
2021-02-17 02:45:54 +00:00
while (this->primaryTileset->metatiles.length() < numPrimaryMetatiles) {
this->primaryTileset->metatiles.append(new Metatile(numTiles));
}
2021-02-17 02:45:54 +00:00
while (this->secondaryTileset->metatiles.length() > numSecondaryMetatiles) {
delete this->secondaryTileset->metatiles.takeLast();
}
2021-02-17 02:45:54 +00:00
while (this->secondaryTileset->metatiles.length() < numSecondaryMetatiles) {
this->secondaryTileset->metatiles.append(new Metatile(numTiles));
}
this->metatileSelector->updateSelectedMetatile();
this->refresh();
this->hasUnsavedChanges = true;
}
}
2018-10-03 01:01:41 +01:00
void TilesetEditor::on_actionChange_Palettes_triggered()
{
if (!this->paletteEditor) {
this->paletteEditor = new PaletteEditor(this->project, this->primaryTileset,
this->secondaryTileset, this->paletteId, this);
connect(this->paletteEditor, &PaletteEditor::changedPaletteColor,
this, &TilesetEditor::onPaletteEditorChangedPaletteColor);
connect(this->paletteEditor, &PaletteEditor::changedPalette,
this, &TilesetEditor::onPaletteEditorChangedPalette);
2018-10-03 01:01:41 +01:00
}
if (!this->paletteEditor->isVisible()) {
this->paletteEditor->show();
} else if (this->paletteEditor->isMinimized()) {
this->paletteEditor->showNormal();
} else {
this->paletteEditor->raise();
2018-10-03 01:01:41 +01:00
this->paletteEditor->activateWindow();
}
}
void TilesetEditor::onPaletteEditorChangedPaletteColor() {
this->refresh();
this->hasUnsavedChanges = true;
}
void TilesetEditor::onPaletteEditorChangedPalette(int paletteId) {
this->on_spinBox_paletteSelector_valueChanged(paletteId);
}
2022-10-04 02:03:43 +01:00
bool TilesetEditor::replaceMetatile(uint16_t metatileId, const Metatile * src)
2022-03-30 23:03:13 +01:00
{
Metatile * dest = Tileset::getMetatile(metatileId, this->primaryTileset, this->secondaryTileset);
if (!dest || !src || *dest == *src)
2022-03-30 23:03:13 +01:00
return false;
this->metatile = dest;
*this->metatile = *src;
this->metatileSelector->select(metatileId);
this->metatileSelector->draw();
this->metatileLayersItem->draw();
this->metatileLayersItem->clearLastModifiedCoords();
return true;
}
void TilesetEditor::on_actionUndo_triggered()
{
MetatileHistoryItem *commit = this->metatileHistory.current();
if (!commit) return;
Metatile *prev = commit->prevMetatile;
if (!prev) return;
this->metatileHistory.back();
2022-03-30 23:03:13 +01:00
this->replaceMetatile(commit->metatileId, prev);
}
void TilesetEditor::on_actionRedo_triggered()
{
MetatileHistoryItem *commit = this->metatileHistory.next();
if (!commit) return;
2022-03-30 23:03:13 +01:00
this->replaceMetatile(commit->metatileId, commit->newMetatile);
}
2022-10-04 02:03:43 +01:00
void TilesetEditor::on_actionCut_triggered()
{
Metatile * empty = new Metatile(projectConfig.getNumTilesInMetatile());
2022-10-04 02:03:43 +01:00
this->copyMetatile(true);
this->pasteMetatile(empty);
delete empty;
}
2022-03-30 23:03:13 +01:00
void TilesetEditor::on_actionCopy_triggered()
{
2022-10-04 02:03:43 +01:00
this->copyMetatile(false);
}
void TilesetEditor::on_actionPaste_triggered()
{
this->pasteMetatile(this->copiedMetatile);
}
void TilesetEditor::copyMetatile(bool cut) {
2022-03-30 23:03:13 +01:00
Metatile * toCopy = Tileset::getMetatile(this->getSelectedMetatileId(), this->primaryTileset, this->secondaryTileset);
if (!toCopy) return;
if (!this->copiedMetatile)
this->copiedMetatile = new Metatile(*toCopy);
else
*this->copiedMetatile = *toCopy;
2022-10-04 02:03:43 +01:00
if (!cut) this->copiedMetatile->label = ""; // Don't copy the label unless it's a cut, these should be unique to each metatile
2022-03-30 23:03:13 +01:00
}
2022-10-04 02:03:43 +01:00
void TilesetEditor::pasteMetatile(const Metatile * toPaste)
2022-03-30 23:03:13 +01:00
{
Metatile *prevMetatile = new Metatile(*this->metatile);
uint16_t metatileId = this->getSelectedMetatileId();
2022-10-04 02:03:43 +01:00
if (!this->replaceMetatile(metatileId, toPaste)) {
2022-06-29 23:37:53 +01:00
delete prevMetatile;
2022-03-30 23:03:13 +01:00
return;
}
2022-03-30 23:03:13 +01:00
MetatileHistoryItem *commit = new MetatileHistoryItem(metatileId, prevMetatile, new Metatile(*this->metatile));
metatileHistory.push(commit);
}
void TilesetEditor::on_actionExport_Primary_Tiles_Image_triggered()
{
QString defaultName = QString("%1_Tiles_Pal%2").arg(this->primaryTileset->name).arg(this->paletteId);
QString defaultFilepath = QString("%1/%2.png").arg(this->project->root).arg(defaultName);
QString filepath = QFileDialog::getSaveFileName(this, "Export Primary Tiles Image", defaultFilepath, "Image Files (*.png)");
if (!filepath.isEmpty()) {
QImage image = this->tileSelector->buildPrimaryTilesIndexedImage();
exportIndexed4BPPPng(image, filepath);
}
}
void TilesetEditor::on_actionExport_Secondary_Tiles_Image_triggered()
{
QString defaultName = QString("%1_Tiles_Pal%2").arg(this->secondaryTileset->name).arg(this->paletteId);
QString defaultFilepath = QString("%1/%2.png").arg(this->project->root).arg(defaultName);
QString filepath = QFileDialog::getSaveFileName(this, "Export Secondary Tiles Image", defaultFilepath, "Image Files (*.png)");
if (!filepath.isEmpty()) {
QImage image = this->tileSelector->buildSecondaryTilesIndexedImage();
exportIndexed4BPPPng(image, filepath);
}
}
2022-10-05 13:54:04 +01:00
void TilesetEditor::on_actionExport_Primary_Metatiles_Image_triggered()
{
QString defaultName = QString("%1_Metatiles").arg(this->primaryTileset->name);
QString defaultFilepath = QString("%1/%2.png").arg(this->project->root).arg(defaultName);
QString filepath = QFileDialog::getSaveFileName(this, "Export Primary Metatiles Image", defaultFilepath, "Image Files (*.png)");
if (!filepath.isEmpty()) {
QImage image = this->metatileSelector->buildPrimaryMetatilesImage();
image.save(filepath, "PNG");
}
}
void TilesetEditor::on_actionExport_Secondary_Metatiles_Image_triggered()
{
QString defaultName = QString("%1_Metatiles").arg(this->secondaryTileset->name);
QString defaultFilepath = QString("%1/%2.png").arg(this->project->root).arg(defaultName);
QString filepath = QFileDialog::getSaveFileName(this, "Export Secondary Metatiles Image", defaultFilepath, "Image Files (*.png)");
if (!filepath.isEmpty()) {
QImage image = this->metatileSelector->buildSecondaryMetatilesImage();
image.save(filepath, "PNG");
}
}
void TilesetEditor::on_actionImport_Primary_Metatiles_triggered()
{
this->importTilesetMetatiles(this->primaryTileset, true);
}
void TilesetEditor::on_actionImport_Secondary_Metatiles_triggered()
{
this->importTilesetMetatiles(this->secondaryTileset, false);
}
void TilesetEditor::importTilesetMetatiles(Tileset *tileset, bool primary)
{
QString descriptor = primary ? "primary" : "secondary";
QString descriptorCaps = primary ? "Primary" : "Secondary";
QString filepath = QFileDialog::getOpenFileName(
this,
QString("Import %1 Tileset Metatiles from Advance Map 1.92").arg(descriptorCaps),
this->project->root,
"Advance Map 1.92 Metatile Files (*.bvd)");
if (filepath.isEmpty()) {
return;
}
bool error = false;
QList<Metatile*> metatiles = MetatileParser::parse(filepath, &error, primary);
if (error) {
QMessageBox msgBox(this);
msgBox.setText("Failed to import metatiles from Advance Map 1.92 .bvd file.");
QString message = QString("The .bvd file could not be processed. View porymap.log for specific errors.");
msgBox.setInformativeText(message);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.setIcon(QMessageBox::Icon::Critical);
msgBox.exec();
return;
}
// TODO: This is crude because it makes a history entry for every newly-imported metatile.
// Revisit this when tiles and num metatiles are added to tileset editory history.
int metatileIdBase = primary ? 0 : Project::getNumMetatilesPrimary();
2021-02-17 02:45:54 +00:00
for (int i = 0; i < metatiles.length(); i++) {
if (i >= tileset->metatiles.length()) {
break;
}
2021-02-17 02:45:54 +00:00
Metatile *prevMetatile = new Metatile(*tileset->metatiles.at(i));
MetatileHistoryItem *commit = new MetatileHistoryItem(static_cast<uint16_t>(metatileIdBase + i),
2021-02-17 02:45:54 +00:00
prevMetatile, new Metatile(*metatiles.at(i)));
metatileHistory.push(commit);
}
tileset->metatiles = metatiles;
this->refresh();
this->hasUnsavedChanges = true;
}
void TilesetEditor::on_actionShow_Unused_toggled(bool checked) {
this->metatileSelector->selectorShowUnused = checked;
if (checked) countMetatileUsage();
this->metatileSelector->draw();
}
void TilesetEditor::on_actionShow_Counts_toggled(bool checked) {
this->metatileSelector->selectorShowCounts = checked;
if (checked) countMetatileUsage();
this->metatileSelector->draw();
}
2021-07-21 23:55:33 +01:00
void TilesetEditor::on_actionShow_UnusedTiles_toggled(bool checked) {
this->tileSelector->showUnused = checked;
if (checked) countTileUsage();
this->tileSelector->draw();
}
void TilesetEditor::countMetatileUsage() {
// do not double count
metatileSelector->usedMetatiles.fill(0);
for (auto layout : this->project->mapLayouts.values()) {
bool usesPrimary = false;
bool usesSecondary = false;
if (layout->tileset_primary_label == this->primaryTileset->name) {
usesPrimary = true;
}
if (layout->tileset_secondary_label == this->secondaryTileset->name) {
usesSecondary = true;
}
if (usesPrimary || usesSecondary) {
this->project->loadLayout(layout);
// for each block in the layout, mark in the vector that it is used
for (int i = 0; i < layout->blockdata.length(); i++) {
uint16_t metatileId = layout->blockdata.at(i).metatileId;
if (metatileId < this->project->getNumMetatilesPrimary()) {
if (usesPrimary) metatileSelector->usedMetatiles[metatileId]++;
} else {
if (usesSecondary) metatileSelector->usedMetatiles[metatileId]++;
}
}
for (int i = 0; i < layout->border.length(); i++) {
uint16_t metatileId = layout->border.at(i).metatileId;
if (metatileId < this->project->getNumMetatilesPrimary()) {
if (usesPrimary) metatileSelector->usedMetatiles[metatileId]++;
} else {
if (usesSecondary) metatileSelector->usedMetatiles[metatileId]++;
}
}
}
}
}
2021-07-21 23:55:33 +01:00
void TilesetEditor::countTileUsage() {
// check primary tiles
this->tileSelector->usedTiles.resize(Project::getNumTilesTotal());
this->tileSelector->usedTiles.fill(0);
QSet<Tileset*> primaryTilesets;
QSet<Tileset*> secondaryTilesets;
for (auto layout : this->project->mapLayouts.values()) {
if (layout->tileset_primary_label == this->primaryTileset->name
|| layout->tileset_secondary_label == this->secondaryTileset->name) {
this->project->loadLayoutTilesets(layout);
// need to check metatiles
if (layout->tileset_primary && layout->tileset_secondary) {
primaryTilesets.insert(layout->tileset_primary);
secondaryTilesets.insert(layout->tileset_secondary);
}
}
}
// check primary tilesets that are used with this secondary tileset for
// reference to secondary tiles in primary metatiles
for (Tileset *tileset : primaryTilesets) {
for (Metatile *metatile : tileset->metatiles) {
for (Tile tile : metatile->tiles) {
if (tile.tileId >= Project::getNumTilesPrimary())
this->tileSelector->usedTiles[tile.tileId]++;
2021-07-21 23:55:33 +01:00
}
}
}
// do the opposite for primary tiles in secondary metatiles
for (Tileset *tileset : secondaryTilesets) {
for (Metatile *metatile : tileset->metatiles) {
for (Tile tile : metatile->tiles) {
if (tile.tileId < Project::getNumTilesPrimary())
this->tileSelector->usedTiles[tile.tileId]++;
2021-07-21 23:55:33 +01:00
}
}
}
// check this primary tileset metatiles
for (Metatile *metatile : this->primaryTileset->metatiles) {
for (Tile tile : metatile->tiles) {
this->tileSelector->usedTiles[tile.tileId]++;
2021-07-21 23:55:33 +01:00
}
}
// and the secondary metatiles
for (Metatile *metatile : this->secondaryTileset->metatiles) {
for (Tile tile : metatile->tiles) {
this->tileSelector->usedTiles[tile.tileId]++;
2021-07-21 23:55:33 +01:00
}
}
}
2022-02-10 14:53:04 +00:00
void TilesetEditor::on_copyButton_metatileLabel_clicked() {
QString label = this->ui->lineEdit_metatileLabel->text();
if (label.isEmpty()) return;
Tileset * tileset = Tileset::getMetatileTileset(this->getSelectedMetatileId(), this->primaryTileset, this->secondaryTileset);
if (tileset)
label.prepend("METATILE_" + QString(tileset->name).replace("gTileset_", "") + "_");
QGuiApplication::clipboard()->setText(label);
QToolTip::showText(this->ui->copyButton_metatileLabel->mapToGlobal(QPoint(0, 0)), "Copied!");
2022-02-10 14:53:04 +00:00
}