mirror of
https://github.com/huderlem/porymap.git
synced 2026-09-28 02:46:45 -05:00
add options to count metatiles to tileset editor
- count the total number of usages across all maps of specific metatiles - display the count and/or display unused metatiles - this does not account for metatiles used in code (most of these are labeled)
This commit is contained in:
@@ -63,19 +63,19 @@ QString Map::bgEventsLabelFromName(QString mapName)
|
||||
}
|
||||
|
||||
int Map::getWidth() {
|
||||
return layout->width.toInt(nullptr, 0);
|
||||
return layout->getWidth();
|
||||
}
|
||||
|
||||
int Map::getHeight() {
|
||||
return layout->height.toInt(nullptr, 0);
|
||||
return layout->getHeight();
|
||||
}
|
||||
|
||||
int Map::getBorderWidth() {
|
||||
return layout->border_width.toInt(nullptr, 0);
|
||||
return layout->getBorderWidth();
|
||||
}
|
||||
|
||||
int Map::getBorderHeight() {
|
||||
return layout->border_height.toInt(nullptr, 0);
|
||||
return layout->getBorderHeight();
|
||||
}
|
||||
|
||||
bool Map::mapBlockChanged(int i, const Blockdata &cache) {
|
||||
|
||||
@@ -14,3 +14,19 @@ QString MapLayout::layoutConstantFromName(QString mapName) {
|
||||
|
||||
return constantName;
|
||||
}
|
||||
|
||||
int MapLayout::getWidth() {
|
||||
return width.toInt(nullptr, 0);
|
||||
}
|
||||
|
||||
int MapLayout::getHeight() {
|
||||
return height.toInt(nullptr, 0);
|
||||
}
|
||||
|
||||
int MapLayout::getBorderWidth() {
|
||||
return border_width.toInt(nullptr, 0);
|
||||
}
|
||||
|
||||
int MapLayout::getBorderHeight() {
|
||||
return border_height.toInt(nullptr, 0);
|
||||
}
|
||||
|
||||
108
src/project.cpp
108
src/project.cpp
@@ -447,6 +447,17 @@ void Project::setNewMapHeader(Map* map, int mapIndex) {
|
||||
map->battle_scene = mapBattleScenes.value(0, "MAP_BATTLE_SCENE_NORMAL");
|
||||
}
|
||||
|
||||
bool Project::loadLayout(MapLayout *layout) {
|
||||
// Force these to run even if one fails
|
||||
bool loadedTilesets = loadLayoutTilesets(layout);
|
||||
bool loadedBlockdata = loadBlockdata(layout);
|
||||
bool loadedBorder = loadLayoutBorder(layout);
|
||||
|
||||
return loadedTilesets
|
||||
&& loadedBlockdata
|
||||
&& loadedBorder;
|
||||
}
|
||||
|
||||
bool Project::loadMapLayout(Map* map) {
|
||||
if (!map->isPersistedToFile) {
|
||||
return true;
|
||||
@@ -459,14 +470,11 @@ bool Project::loadMapLayout(Map* map) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Force these to run even if one fails
|
||||
bool loadedTilesets = loadMapTilesets(map);
|
||||
bool loadedBlockdata = loadBlockdata(map);
|
||||
bool loadedBorder = loadMapBorder(map);
|
||||
|
||||
return loadedTilesets
|
||||
&& loadedBlockdata
|
||||
&& loadedBorder;
|
||||
if (map->hasUnsavedChanges()) {
|
||||
return true;
|
||||
} else {
|
||||
return loadLayout(map->layout);
|
||||
}
|
||||
}
|
||||
|
||||
bool Project::readMapLayouts() {
|
||||
@@ -1080,30 +1088,31 @@ void Project::saveTilesetPalettes(Tileset *tileset) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Project::loadMapTilesets(Map* map) {
|
||||
if (map->hasUnsavedChanges()) {
|
||||
return true;
|
||||
}
|
||||
bool Project::loadLayoutTilesets(MapLayout *layout) {
|
||||
// TODO: investigate where to put this now
|
||||
// if (map->hasUnsavedChanges()) {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
map->layout->tileset_primary = getTileset(map->layout->tileset_primary_label);
|
||||
if (!map->layout->tileset_primary) {
|
||||
layout->tileset_primary = getTileset(layout->tileset_primary_label);
|
||||
if (!layout->tileset_primary) {
|
||||
QString defaultTileset = tilesetLabels["primary"].value(0, "gTileset_General");
|
||||
logWarn(QString("Map layout %1 has invalid primary tileset '%2'. Using default '%3'").arg(map->layout->id).arg(map->layout->tileset_primary_label).arg(defaultTileset));
|
||||
map->layout->tileset_primary_label = defaultTileset;
|
||||
map->layout->tileset_primary = getTileset(map->layout->tileset_primary_label);
|
||||
if (!map->layout->tileset_primary) {
|
||||
logWarn(QString("Map layout %1 has invalid primary tileset '%2'. Using default '%3'").arg(layout->id).arg(layout->tileset_primary_label).arg(defaultTileset));
|
||||
layout->tileset_primary_label = defaultTileset;
|
||||
layout->tileset_primary = getTileset(layout->tileset_primary_label);
|
||||
if (!layout->tileset_primary) {
|
||||
logError(QString("Failed to set default primary tileset."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
map->layout->tileset_secondary = getTileset(map->layout->tileset_secondary_label);
|
||||
if (!map->layout->tileset_secondary) {
|
||||
layout->tileset_secondary = getTileset(layout->tileset_secondary_label);
|
||||
if (!layout->tileset_secondary) {
|
||||
QString defaultTileset = tilesetLabels["secondary"].value(0, projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered ? "gTileset_PalletTown" : "gTileset_Petalburg");
|
||||
logWarn(QString("Map layout %1 has invalid secondary tileset '%2'. Using default '%3'").arg(map->layout->id).arg(map->layout->tileset_secondary_label).arg(defaultTileset));
|
||||
map->layout->tileset_secondary_label = defaultTileset;
|
||||
map->layout->tileset_secondary = getTileset(map->layout->tileset_secondary_label);
|
||||
if (!map->layout->tileset_secondary) {
|
||||
logWarn(QString("Map layout %1 has invalid secondary tileset '%2'. Using default '%3'").arg(layout->id).arg(layout->tileset_secondary_label).arg(defaultTileset));
|
||||
layout->tileset_secondary_label = defaultTileset;
|
||||
layout->tileset_secondary = getTileset(layout->tileset_secondary_label);
|
||||
if (!layout->tileset_secondary) {
|
||||
logError(QString("Failed to set default secondary tileset."));
|
||||
return false;
|
||||
}
|
||||
@@ -1140,23 +1149,23 @@ Tileset* Project::loadTileset(QString label, Tileset *tileset) {
|
||||
return tileset;
|
||||
}
|
||||
|
||||
bool Project::loadBlockdata(Map *map) {
|
||||
if (map->hasUnsavedChanges()) {
|
||||
return true;
|
||||
}
|
||||
bool Project::loadBlockdata(MapLayout *layout) {
|
||||
// if (map->hasUnsavedChanges()) {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
QString path = QString("%1/%2").arg(root).arg(map->layout->blockdata_path);
|
||||
map->layout->blockdata = readBlockdata(path);
|
||||
map->layout->lastCommitMapBlocks.blocks = map->layout->blockdata;
|
||||
map->layout->lastCommitMapBlocks.dimensions = QSize(map->getWidth(), map->getHeight());
|
||||
QString path = QString("%1/%2").arg(root).arg(layout->blockdata_path);
|
||||
layout->blockdata = readBlockdata(path);
|
||||
layout->lastCommitMapBlocks.blocks = layout->blockdata;
|
||||
layout->lastCommitMapBlocks.dimensions = QSize(layout->getWidth(), layout->getHeight());
|
||||
|
||||
if (map->layout->blockdata.count() != map->getWidth() * map->getHeight()) {
|
||||
if (layout->blockdata.count() != layout->getWidth() * layout->getHeight()) {
|
||||
logWarn(QString("Layout blockdata length %1 does not match dimensions %2x%3 (should be %4). Resizing blockdata.")
|
||||
.arg(map->layout->blockdata.count())
|
||||
.arg(map->getWidth())
|
||||
.arg(map->getHeight())
|
||||
.arg(map->getWidth() * map->getHeight()));
|
||||
map->layout->blockdata.resize(map->getWidth() * map->getHeight());
|
||||
.arg(layout->blockdata.count())
|
||||
.arg(layout->getWidth())
|
||||
.arg(layout->getHeight())
|
||||
.arg(layout->getWidth() * layout->getHeight()));
|
||||
layout->blockdata.resize(layout->getWidth() * layout->getHeight());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1170,19 +1179,19 @@ void Project::setNewMapBlockdata(Map *map) {
|
||||
map->layout->lastCommitMapBlocks.dimensions = QSize(map->getWidth(), map->getHeight());
|
||||
}
|
||||
|
||||
bool Project::loadMapBorder(Map *map) {
|
||||
if (map->hasUnsavedChanges()) {
|
||||
return true;
|
||||
}
|
||||
bool Project::loadLayoutBorder(MapLayout *layout) {
|
||||
// if (map->hasUnsavedChanges()) {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
QString path = QString("%1/%2").arg(root).arg(map->layout->border_path);
|
||||
map->layout->border = readBlockdata(path);
|
||||
int borderLength = map->getBorderWidth() * map->getBorderHeight();
|
||||
if (map->layout->border.count() != borderLength) {
|
||||
QString path = QString("%1/%2").arg(root).arg(layout->border_path);
|
||||
layout->border = readBlockdata(path);
|
||||
int borderLength = layout->getBorderWidth() * layout->getBorderHeight();
|
||||
if (layout->border.count() != borderLength) {
|
||||
logWarn(QString("Layout border blockdata length %1 must be %2. Resizing border blockdata.")
|
||||
.arg(map->layout->border.count())
|
||||
.arg(layout->border.count())
|
||||
.arg(borderLength));
|
||||
map->layout->border.resize(borderLength);
|
||||
layout->border.resize(borderLength);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1856,7 +1865,8 @@ Map* Project::addNewMapToGroup(QString mapName, int groupNum, Map *newMap, bool
|
||||
setNewMapBorder(newMap);
|
||||
}
|
||||
|
||||
loadMapTilesets(newMap);
|
||||
//loadMapTilesets(newMap);
|
||||
loadLayoutTilesets(newMap->layout);
|
||||
setNewMapEvents(newMap);
|
||||
setNewMapConnections(newMap);
|
||||
|
||||
|
||||
@@ -281,6 +281,13 @@ void TilesetEditor::refresh() {
|
||||
this->metatileSelector->select(this->metatileSelector->getSelectedMetatile());
|
||||
this->drawSelectedTiles();
|
||||
|
||||
if (metatileSelector) {
|
||||
if (metatileSelector->selectorShowUnused || metatileSelector->selectorShowCounts) {
|
||||
countMetatileUsage();
|
||||
this->metatileSelector->draw();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -909,3 +916,60 @@ void TilesetEditor::importTilesetMetatiles(Tileset *tileset, bool primary)
|
||||
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();
|
||||
}
|
||||
|
||||
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 tile = layout->blockdata.at(i).tile;
|
||||
if (tile < this->project->getNumMetatilesPrimary()) {
|
||||
if (usesPrimary) metatileSelector->usedMetatiles[tile]++;
|
||||
} else {
|
||||
if (usesSecondary) metatileSelector->usedMetatiles[tile]++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < layout->border.length(); i++) {
|
||||
uint16_t tile = layout->border.at(i).tile;
|
||||
if (tile < this->project->getNumMetatilesPrimary()) {
|
||||
if (usesPrimary) metatileSelector->usedMetatiles[tile]++;
|
||||
} else {
|
||||
if (usesSecondary) metatileSelector->usedMetatiles[tile]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,15 @@
|
||||
#include "project.h"
|
||||
#include <QPainter>
|
||||
|
||||
TilesetEditorMetatileSelector::TilesetEditorMetatileSelector(Tileset *primaryTileset, Tileset *secondaryTileset, Map *map)
|
||||
: SelectablePixmapItem(32, 32, 1, 1) {
|
||||
this->setTilesets(primaryTileset, secondaryTileset, false);
|
||||
this->numMetatilesWide = 8;
|
||||
this->map = map;
|
||||
setAcceptHoverEvents(true);
|
||||
this->usedMetatiles.resize(Project::getNumMetatilesTotal());
|
||||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::draw() {
|
||||
if (!this->primaryTileset || !this->secondaryTileset) {
|
||||
this->setPixmap(QPixmap());
|
||||
@@ -39,6 +48,8 @@ void TilesetEditorMetatileSelector::draw() {
|
||||
painter.end();
|
||||
this->setPixmap(QPixmap::fromImage(image));
|
||||
this->drawSelection();
|
||||
|
||||
drawFilters();
|
||||
}
|
||||
|
||||
bool TilesetEditorMetatileSelector::select(uint16_t metatileId) {
|
||||
@@ -50,10 +61,11 @@ bool TilesetEditorMetatileSelector::select(uint16_t metatileId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::setTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
void TilesetEditorMetatileSelector::setTilesets(Tileset *primaryTileset, Tileset *secondaryTileset, bool draw) {
|
||||
this->primaryTileset = primaryTileset;
|
||||
this->secondaryTileset = secondaryTileset;
|
||||
this->draw();
|
||||
|
||||
if (draw) this->draw();
|
||||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::updateSelectedMetatile() {
|
||||
@@ -131,3 +143,92 @@ QPoint TilesetEditorMetatileSelector::getMetatileIdCoordsOnWidget(uint16_t metat
|
||||
pos.ry() = (pos.y() * this->cellHeight) + (this->cellHeight / 2);
|
||||
return pos;
|
||||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::drawFilters() {
|
||||
if (selectorShowUnused) {
|
||||
drawUnused();
|
||||
}
|
||||
if (selectorShowCounts) {
|
||||
drawCounts();
|
||||
}
|
||||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::drawUnused() {
|
||||
// setup the circle with a line through it image to layer above unused metatiles
|
||||
QPixmap redX(32, 32);
|
||||
redX.fill(Qt::transparent);
|
||||
|
||||
QPen whitePen(Qt::white);
|
||||
whitePen.setWidth(1);
|
||||
QPen redPen(Qt::magenta);
|
||||
redPen.setWidth(1);
|
||||
|
||||
QPainter oPainter(&redX);
|
||||
|
||||
oPainter.setPen(whitePen);
|
||||
oPainter.drawEllipse(QRect(1, 1, 30, 30));
|
||||
oPainter.setPen(redPen);
|
||||
oPainter.drawEllipse(QRect(2, 2, 28, 28));
|
||||
oPainter.drawEllipse(QRect(3, 3, 26, 26));
|
||||
|
||||
oPainter.setPen(whitePen);
|
||||
oPainter.drawEllipse(QRect(4, 4, 24, 24));
|
||||
|
||||
whitePen.setWidth(5);
|
||||
oPainter.setPen(whitePen);
|
||||
oPainter.drawLine(0, 0, 31, 31);
|
||||
|
||||
redPen.setWidth(3);
|
||||
oPainter.setPen(redPen);
|
||||
oPainter.drawLine(2, 2, 29, 29);
|
||||
|
||||
oPainter.end();
|
||||
|
||||
// draw symbol on unused metatiles
|
||||
QPixmap metatilesPixmap = this->pixmap();
|
||||
|
||||
QPainter unusedPainter(&metatilesPixmap);
|
||||
|
||||
for (int tile = 0; tile < this->usedMetatiles.size(); tile++) {
|
||||
if (!usedMetatiles[tile]) {
|
||||
unusedPainter.drawPixmap((tile % 8) * 32, (tile / 8) * 32, redX);
|
||||
}
|
||||
}
|
||||
|
||||
unusedPainter.end();
|
||||
|
||||
this->setPixmap(metatilesPixmap);
|
||||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::drawCounts() {
|
||||
QPen blackPen(Qt::black);
|
||||
blackPen.setWidth(1);
|
||||
|
||||
QPixmap metatilesPixmap = this->pixmap();
|
||||
|
||||
QPainter countPainter(&metatilesPixmap);
|
||||
countPainter.setPen(blackPen);
|
||||
|
||||
for (int tile = 0; tile < this->usedMetatiles.size(); tile++) {
|
||||
int count = usedMetatiles[tile];
|
||||
QString countText = QString::number(count);
|
||||
if (count > 1000) countText = ">1k";
|
||||
countPainter.drawText((tile % 8) * 32, (tile / 8) * 32 + 32, countText);
|
||||
}
|
||||
|
||||
// write in white and black for contrast
|
||||
QPen whitePen(Qt::white);
|
||||
whitePen.setWidth(1);
|
||||
countPainter.setPen(whitePen);
|
||||
|
||||
for (int tile = 0; tile < this->usedMetatiles.size(); tile++) {
|
||||
int count = usedMetatiles[tile];
|
||||
QString countText = QString::number(count);
|
||||
if (count > 1000) countText = ">1k";
|
||||
countPainter.drawText((tile % 8) * 32 + 1, (tile / 8) * 32 + 32 - 1, countText);
|
||||
}
|
||||
|
||||
countPainter.end();
|
||||
|
||||
this->setPixmap(metatilesPixmap);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user