mirror of
https://github.com/huderlem/porymap.git
synced 2026-03-21 17:45:44 -05:00
Clean up tile/metatile image changes
This commit is contained in:
parent
c5117e458b
commit
15b300f864
|
|
@ -158,7 +158,6 @@ public:
|
|||
|
||||
QPixmap render(bool ignoreCache = false, Layout *fromLayout = nullptr, const QRect &bounds = QRect(0, 0, -1, -1));
|
||||
QPixmap renderCollision(bool ignoreCache);
|
||||
// QPixmap renderConnection(MapConnection, Layout *);
|
||||
QPixmap renderBorder(bool ignoreCache = false);
|
||||
|
||||
QPixmap getLayoutItemPixmap();
|
||||
|
|
|
|||
|
|
@ -76,13 +76,17 @@ public:
|
|||
void addMetatile(Metatile* metatile);
|
||||
|
||||
const QList<Metatile*> &metatiles() const { return m_metatiles; }
|
||||
Metatile* metatileAt(unsigned int i) const { return m_metatiles.at(i); }
|
||||
const Metatile* metatileAt(unsigned int i) const { return m_metatiles.at(i); }
|
||||
|
||||
void clearMetatiles();
|
||||
void resizeMetatiles(int newNumMetatiles);
|
||||
int numMetatiles() const { return m_metatiles.length(); }
|
||||
int maxMetatiles() const;
|
||||
|
||||
uint16_t firstMetatileId() const;
|
||||
uint16_t lastMetatileId() const;
|
||||
bool contains(uint16_t metatileId) const { return metatileId >= firstMetatileId() && metatileId <= lastMetatileId(); }
|
||||
|
||||
int numTiles() const { return m_tiles.length(); }
|
||||
int maxTiles() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ enum CallbackType {
|
|||
OnMapResized,
|
||||
OnBorderResized,
|
||||
OnMapShifted,
|
||||
OnTilesetsChanged,
|
||||
OnTilesetUpdated,
|
||||
OnMainTabChanged,
|
||||
OnMapViewTabChanged,
|
||||
OnBorderVisibilityToggled,
|
||||
|
|
@ -51,7 +51,7 @@ public:
|
|||
static void cb_MapResized(int oldWidth, int oldHeight, const QMargins &delta);
|
||||
static void cb_BorderResized(int oldWidth, int oldHeight, int newWidth, int newHeight);
|
||||
static void cb_MapShifted(int xDelta, int yDelta);
|
||||
static void cb_TilesetsChanged(const QString &primaryTilesetName, const QString &secondaryTilesetName);
|
||||
static void cb_TilesetUpdated(const QString &tilesetName);
|
||||
static void cb_MainTabChanged(int oldTab, int newTab);
|
||||
static void cb_MapViewTabChanged(int oldTab, int newTab);
|
||||
static void cb_BorderVisibilityToggled(bool visible);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,8 @@ QImage getMetatileSheetImage(Tileset *primaryTileset,
|
|||
|
||||
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);
|
||||
QImage getColoredTileImage(uint16_t tileId, Tileset *primaryTileset, Tileset *secondaryTileset, const QList<QRgb> &palette);
|
||||
QImage getGreyscaleTileImage(uint16_t tileId, Tileset *primaryTileset, Tileset *secondaryTileset);
|
||||
|
||||
void flattenTo4bppImage(QImage * image);
|
||||
|
||||
|
|
|
|||
|
|
@ -89,8 +89,6 @@ private:
|
|||
void syncMetatileWidth();
|
||||
void validateMetatileStart();
|
||||
void validateMetatileEnd();
|
||||
uint16_t getExpectedMetatileStart();
|
||||
uint16_t getExpectedMetatileEnd();
|
||||
void updateMetatileRange();
|
||||
void copyRenderSettings();
|
||||
void restoreRenderSettings();
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ private:
|
|||
signals:
|
||||
void tileChanged(int, int);
|
||||
void selectedTilesChanged(QPoint, int, int);
|
||||
void hoveredTileChanged(uint16_t);
|
||||
void hoveredTileChanged(const Tile &tile);
|
||||
void hoveredTileCleared();
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ struct MetatileSelection
|
|||
class MetatileSelector: public SelectablePixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
MetatileSelector(int numMetatilesWide, Layout *layout): SelectablePixmapItem(Metatile::pixelWidth(), Metatile::pixelHeight()) {
|
||||
MetatileSelector(int numMetatilesWide, Layout *layout): SelectablePixmapItem(Metatile::pixelSize()) {
|
||||
this->externalSelection = false;
|
||||
this->prefabSelection = false;
|
||||
this->numMetatilesWide = numMetatilesWide;
|
||||
|
|
@ -41,16 +41,16 @@ public:
|
|||
setAcceptHoverEvents(true);
|
||||
}
|
||||
|
||||
QPoint getSelectionDimensions() override;
|
||||
QPoint getSelectionDimensions() const override;
|
||||
void draw() override;
|
||||
void refresh();
|
||||
|
||||
bool select(uint16_t metatile);
|
||||
void selectFromMap(uint16_t metatileId, uint16_t collision, uint16_t elevation);
|
||||
MetatileSelection getMetatileSelection();
|
||||
MetatileSelection getMetatileSelection() const { return this->selection; }
|
||||
void setPrefabSelection(MetatileSelection selection);
|
||||
void setExternalSelection(int, int, QList<uint16_t>, QList<QPair<uint16_t, uint16_t>>);
|
||||
QPoint getMetatileIdCoordsOnWidget(uint16_t);
|
||||
void setExternalSelection(int, int, const QList<uint16_t>&, const QList<QPair<uint16_t, uint16_t>>&);
|
||||
QPoint getMetatileIdCoordsOnWidget(uint16_t metatileId) const;
|
||||
void setLayout(Layout *layout);
|
||||
bool isInternalSelection() const { return (!this->externalSelection && !this->prefabSelection); }
|
||||
|
||||
|
|
@ -79,8 +79,9 @@ private:
|
|||
void updateBasePixmap();
|
||||
void updateSelectedMetatiles();
|
||||
void updateExternalSelectedMetatiles();
|
||||
uint16_t getMetatileId(int x, int y) const;
|
||||
QPoint getMetatileIdCoords(uint16_t);
|
||||
uint16_t posToMetatileId(int x, int y, bool *ok = nullptr) const;
|
||||
uint16_t posToMetatileId(const QPoint &pos, bool *ok = nullptr) const;
|
||||
QPoint metatileIdToPos(uint16_t metatileId, bool *ok = nullptr) const;
|
||||
bool positionIsValid(const QPoint &pos) const;
|
||||
bool selectionIsValid();
|
||||
void hoverChanged();
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ public:
|
|||
selectionOffsetX(0),
|
||||
selectionOffsetY(0)
|
||||
{}
|
||||
virtual QPoint getSelectionDimensions();
|
||||
virtual QPoint getSelectionDimensions() const;
|
||||
virtual void draw() = 0;
|
||||
|
||||
protected:
|
||||
|
|
@ -33,7 +33,8 @@ protected:
|
|||
int selectionOffsetY;
|
||||
|
||||
QPoint getSelectionStart();
|
||||
void select(int, int, int, int);
|
||||
void select(int x, int y, int width = 0, int height = 0);
|
||||
void select(const QPoint &pos, const QSize &size = QSize(0,0)) { select(pos.x(), pos.y(), size.width(), size.height()); }
|
||||
void updateSelection(int, int);
|
||||
QPoint getCellPos(QPointF);
|
||||
virtual void mousePressEvent(QGraphicsSceneMouseEvent*) override;
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ private slots:
|
|||
void onWindowActivated();
|
||||
void onHoveredMetatileChanged(uint16_t);
|
||||
void onHoveredMetatileCleared();
|
||||
void onHoveredTileChanged(const Tile&);
|
||||
void onHoveredTileChanged(uint16_t);
|
||||
void onHoveredTileCleared();
|
||||
void onSelectedTilesChanged();
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ public:
|
|||
|
||||
bool select(uint16_t metatileId);
|
||||
void setTilesets(Tileset*, Tileset*);
|
||||
uint16_t getSelectedMetatileId();
|
||||
uint16_t getSelectedMetatileId() const { return this->selectedMetatileId; }
|
||||
void updateSelectedMetatile();
|
||||
QPoint getMetatileIdCoordsOnWidget(uint16_t metatileId);
|
||||
QPoint getMetatileIdCoordsOnWidget(uint16_t metatileId) const;
|
||||
|
||||
QVector<uint16_t> usedMetatiles;
|
||||
bool selectorShowUnused = false;
|
||||
|
|
@ -44,11 +44,12 @@ private:
|
|||
int numMetatilesWide;
|
||||
int numMetatilesHigh;
|
||||
void updateBasePixmap();
|
||||
uint16_t getMetatileId(int x, int y);
|
||||
QPoint getMetatileIdCoords(uint16_t);
|
||||
uint16_t posToMetatileId(int x, int y, bool *ok = nullptr) const;
|
||||
uint16_t posToMetatileId(const QPoint &pos, bool *ok = nullptr) const;
|
||||
QPoint metatileIdToPos(uint16_t metatileId, bool *ok = nullptr) const;
|
||||
bool shouldAcceptEvent(QGraphicsSceneMouseEvent*);
|
||||
int numRows(int numMetatiles);
|
||||
int numRows();
|
||||
int numRows(int numMetatiles) const;
|
||||
int numRows() const;
|
||||
void drawGrid();
|
||||
void drawDivider();
|
||||
void drawFilters();
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ public:
|
|||
this->paletteChanged = false;
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
QPoint getSelectionDimensions();
|
||||
void draw();
|
||||
QPoint getSelectionDimensions() const override;
|
||||
void draw() override;
|
||||
void select(uint16_t metatileId);
|
||||
void highlight(uint16_t metatileId);
|
||||
void setTilesets(Tileset*, Tileset*);
|
||||
|
|
@ -36,11 +36,11 @@ public:
|
|||
bool showDivider = false;
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||
void hoverMoveEvent(QGraphicsSceneHoverEvent*);
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent*);
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*) override;
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent*) override;
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent*) override;
|
||||
void hoverMoveEvent(QGraphicsSceneHoverEvent*) override;
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent*) override;
|
||||
|
||||
private:
|
||||
QPixmap basePixmap;
|
||||
|
|
|
|||
|
|
@ -53,8 +53,8 @@ export function onMapShifted(xDelta, yDelta) {
|
|||
|
||||
}
|
||||
|
||||
// Called when a currently loaded tileset is changed by switching to a new one or by saving changes in the Tileset Editor.
|
||||
export function onTilesetsChanged(primaryTilesetName, secondaryTilesetName) {
|
||||
// Called when the currently loaded tileset is changed by switching to a new one or by saving changes to it in the Tileset Editor.
|
||||
export function onTilesetUpdated(tilesetName) {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -298,6 +298,9 @@ uint32_t KeyValueConfigBase::getConfigUint32(const QString &key, const QString &
|
|||
}
|
||||
|
||||
QColor KeyValueConfigBase::getConfigColor(const QString &key, const QString &value, const QColor &defaultValue) {
|
||||
if (value.isEmpty())
|
||||
return QColor();
|
||||
|
||||
QColor color = QColor("#" + value);
|
||||
if (!color.isValid()) {
|
||||
logWarn(QString("Invalid config value for %1: '%2'. Must be a color in the format 'RRGGBB'. Using default value '%3'.").arg(key).arg(value).arg(defaultValue.name()));
|
||||
|
|
@ -307,7 +310,7 @@ QColor KeyValueConfigBase::getConfigColor(const QString &key, const QString &val
|
|||
}
|
||||
|
||||
QString KeyValueConfigBase::toConfigColor(const QColor &color) {
|
||||
return color.name().remove("#"); // Our text config treats '#' as the start of a comment.
|
||||
return color.isValid() ? color.name().remove("#") : QString(); // Our text config treats '#' as the start of a comment.
|
||||
}
|
||||
|
||||
PorymapConfig porymapConfig;
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ QList<Metatile*> AdvanceMapParser::parseMetatiles(const QString &filepath, bool
|
|||
}
|
||||
|
||||
int attrSize = Metatile::getDefaultAttributesSize(version);
|
||||
int maxMetatiles = primaryTileset ? Project::getNumMetatilesPrimary() : Project::getNumMetatilesTotal() - Project::getNumMetatilesPrimary();
|
||||
int maxMetatiles = primaryTileset ? Project::getNumMetatilesPrimary() : Project::getNumMetatilesSecondary();
|
||||
int numMetatiles = static_cast<unsigned char>(in.at(0)) |
|
||||
(static_cast<unsigned char>(in.at(1)) << 8) |
|
||||
(static_cast<unsigned char>(in.at(2)) << 16) |
|
||||
|
|
|
|||
|
|
@ -76,15 +76,15 @@ QPoint MapConnection::relativePixelPos(bool clipped) const {
|
|||
int x = 0, y = 0;
|
||||
if (m_direction == "right") {
|
||||
if (m_parentMap) x = m_parentMap->pixelWidth();
|
||||
y = m_offset;
|
||||
y = m_offset * Metatile::pixelHeight();
|
||||
} else if (m_direction == "down") {
|
||||
x = m_offset;
|
||||
x = m_offset * Metatile::pixelWidth();
|
||||
if (m_parentMap) y = m_parentMap->pixelHeight();
|
||||
} else if (m_direction == "left") {
|
||||
if (targetMap()) x = !clipped ? -targetMap()->pixelWidth() : -targetMap()->getConnectionRect(m_direction).width();
|
||||
y = m_offset;
|
||||
y = m_offset * Metatile::pixelHeight();
|
||||
} else if (m_direction == "up") {
|
||||
x = m_offset;
|
||||
x = m_offset * Metatile::pixelWidth();
|
||||
if (targetMap()) y = !clipped ? -targetMap()->pixelHeight() : -targetMap()->getConnectionRect(m_direction).height();
|
||||
}
|
||||
return QPoint(x, y);
|
||||
|
|
|
|||
|
|
@ -530,6 +530,7 @@ bool Layout::loadBorder(const QString &root) {
|
|||
logError(QString("Failed to load border for %1 from '%2': %3").arg(this->name).arg(path).arg(error));
|
||||
return false;
|
||||
}
|
||||
this->border = blockdata;
|
||||
|
||||
// 0 is an expected border width/height that should be handled, GF used it for the RS layouts in FRLG
|
||||
if (this->border_width <= 0) {
|
||||
|
|
@ -539,10 +540,6 @@ bool Layout::loadBorder(const QString &root) {
|
|||
this->border_height = DEFAULT_BORDER_HEIGHT;
|
||||
}
|
||||
|
||||
this->border = blockdata;
|
||||
this->lastCommitBlocks.border = blockdata;
|
||||
this->lastCommitBlocks.borderDimensions = QSize(this->border_width, this->border_height);
|
||||
|
||||
int expectedSize = this->border_width * this->border_height;
|
||||
if (this->border.count() != expectedSize) {
|
||||
logWarn(QString("%1 border blockdata length %2 does not match dimensions %3x%4 (should be %5). Resizing border blockdata.")
|
||||
|
|
@ -553,6 +550,10 @@ bool Layout::loadBorder(const QString &root) {
|
|||
.arg(expectedSize));
|
||||
this->border.resize(expectedSize);
|
||||
}
|
||||
|
||||
this->lastCommitBlocks.border = this->border;
|
||||
this->lastCommitBlocks.borderDimensions = QSize(this->border_width, this->border_height);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -569,10 +570,7 @@ bool Layout::loadBlockdata(const QString &root) {
|
|||
logError(QString("Failed to load blockdata for %1 from '%2': %3").arg(this->name).arg(path).arg(error));
|
||||
return false;
|
||||
}
|
||||
|
||||
this->blockdata = blockdata;
|
||||
this->lastCommitBlocks.blocks = blockdata;
|
||||
this->lastCommitBlocks.layoutDimensions = QSize(this->width, this->height);
|
||||
|
||||
int expectedSize = this->width * this->height;
|
||||
if (expectedSize <= 0) {
|
||||
|
|
@ -588,6 +586,10 @@ bool Layout::loadBlockdata(const QString &root) {
|
|||
.arg(expectedSize));
|
||||
this->blockdata.resize(expectedSize);
|
||||
}
|
||||
|
||||
this->lastCommitBlocks.blocks = this->blockdata;
|
||||
this->lastCommitBlocks.layoutDimensions = QSize(this->width, this->height);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -94,6 +94,14 @@ void Tileset::resizeMetatiles(int newNumMetatiles) {
|
|||
}
|
||||
}
|
||||
|
||||
uint16_t Tileset::firstMetatileId() const {
|
||||
return this->is_secondary ? Project::getNumMetatilesPrimary() : 0;
|
||||
}
|
||||
|
||||
uint16_t Tileset::lastMetatileId() const {
|
||||
return firstMetatileId() + qMax(m_metatiles.length(), 1) - 1;
|
||||
}
|
||||
|
||||
int Tileset::maxMetatiles() const {
|
||||
return this->is_secondary ? Project::getNumMetatilesSecondary() : Project::getNumMetatilesPrimary();
|
||||
}
|
||||
|
|
@ -213,16 +221,8 @@ QString Tileset::getMetatileLabelPrefix(const QString &name)
|
|||
}
|
||||
|
||||
bool Tileset::metatileIsValid(uint16_t metatileId, Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
if (metatileId >= Project::getNumMetatilesTotal())
|
||||
return false;
|
||||
|
||||
if (metatileId < Project::getNumMetatilesPrimary() && metatileId >= primaryTileset->numMetatiles())
|
||||
return false;
|
||||
|
||||
if (metatileId >= Project::getNumMetatilesPrimary() + secondaryTileset->numMetatiles())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return (primaryTileset && primaryTileset->contains(metatileId))
|
||||
|| (secondaryTileset && secondaryTileset->contains(metatileId));
|
||||
}
|
||||
|
||||
QList<QList<QRgb>> Tileset::getBlockPalettes(Tileset *primaryTileset, Tileset *secondaryTileset, bool useTruePalettes) {
|
||||
|
|
@ -252,10 +252,12 @@ QList<QRgb> Tileset::getPalette(int paletteId, Tileset *primaryTileset, Tileset
|
|||
Tileset *tileset = paletteId < Project::getNumPalettesPrimary()
|
||||
? primaryTileset
|
||||
: secondaryTileset;
|
||||
auto palettes = useTruePalettes ? tileset->palettes : tileset->palettePreviews;
|
||||
if (!tileset) {
|
||||
return paletteTable;
|
||||
}
|
||||
|
||||
if (paletteId < 0 || paletteId >= palettes.length()){
|
||||
logError(QString("Invalid tileset palette id '%1' requested.").arg(paletteId));
|
||||
auto palettes = useTruePalettes ? tileset->palettes : tileset->palettePreviews;
|
||||
if (paletteId < 0 || paletteId >= palettes.length()) {
|
||||
return paletteTable;
|
||||
}
|
||||
|
||||
|
|
@ -636,20 +638,20 @@ bool Tileset::savePalettes() {
|
|||
|
||||
bool Tileset::load() {
|
||||
bool success = true;
|
||||
if (!loadPalettes()) success = false;
|
||||
if (!loadTilesImage()) success = false;
|
||||
if (!loadMetatiles()) success = false;
|
||||
if (!loadMetatileAttributes()) success = false;
|
||||
if (!loadTilesImage()) success = false;
|
||||
if (!loadPalettes()) success = false;
|
||||
return success;
|
||||
}
|
||||
|
||||
// Because metatile labels are global (and handled by the project) we don't save them here.
|
||||
bool Tileset::save() {
|
||||
bool success = true;
|
||||
if (!savePalettes()) success = false;
|
||||
if (!saveTilesImage()) success = false;
|
||||
if (!saveMetatiles()) success = false;
|
||||
if (!saveMetatileAttributes()) success = false;
|
||||
if (!saveTilesImage()) success = false;
|
||||
if (!savePalettes()) success = false;
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1372,8 +1372,10 @@ bool Editor::setLayout(QString layoutId) {
|
|||
|
||||
if (this->layout->name != prevLayoutName)
|
||||
Scripting::cb_LayoutOpened(this->layout->name);
|
||||
if (this->layout->tileset_primary_label != prevPrimaryTileset || this->layout->tileset_secondary_label != prevSecondaryTileset)
|
||||
Scripting::cb_TilesetsChanged(this->layout->tileset_primary_label, this->layout->tileset_secondary_label);
|
||||
if (this->layout->tileset_primary_label != prevPrimaryTileset)
|
||||
Scripting::cb_TilesetUpdated(this->layout->tileset_primary_label);
|
||||
if (this->layout->tileset_secondary_label != prevSecondaryTileset)
|
||||
Scripting::cb_TilesetUpdated(this->layout->tileset_secondary_label);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1820,7 +1820,9 @@ void MainWindow::currentMetatilesSelectionChanged() {
|
|||
redrawMetatileSelection();
|
||||
if (this->tilesetEditor) {
|
||||
MetatileSelection selection = editor->metatile_selector_item->getMetatileSelection();
|
||||
this->tilesetEditor->selectMetatile(selection.metatileItems.first().metatileId);
|
||||
if (!selection.metatileItems.isEmpty()) {
|
||||
this->tilesetEditor->selectMetatile(selection.metatileItems.first().metatileId);
|
||||
}
|
||||
}
|
||||
|
||||
// Don't scroll to internal selections here, it will disrupt the user while they make their selection.
|
||||
|
|
@ -2603,20 +2605,20 @@ void MainWindow::onTilesetsSaved(QString primaryTilesetLabel, QString secondaryT
|
|||
bool updated = false;
|
||||
if (primaryTilesetLabel == this->editor->layout->tileset_primary_label) {
|
||||
this->editor->updatePrimaryTileset(primaryTilesetLabel, true);
|
||||
Scripting::cb_TilesetUpdated(primaryTilesetLabel);
|
||||
updated = true;
|
||||
} else {
|
||||
this->editor->project->getTileset(primaryTilesetLabel, true);
|
||||
}
|
||||
if (secondaryTilesetLabel == this->editor->layout->tileset_secondary_label) {
|
||||
this->editor->updateSecondaryTileset(secondaryTilesetLabel, true);
|
||||
Scripting::cb_TilesetUpdated(secondaryTilesetLabel);
|
||||
updated = true;
|
||||
} else {
|
||||
this->editor->project->getTileset(secondaryTilesetLabel, true);
|
||||
}
|
||||
if (updated) {
|
||||
if (updated)
|
||||
redrawMapScene();
|
||||
Scripting::cb_TilesetsChanged(primaryTilesetLabel, secondaryTilesetLabel);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onMapRulerStatusChanged(const QString &status) {
|
||||
|
|
|
|||
|
|
@ -1558,9 +1558,8 @@ Tileset *Project::createNewTileset(QString name, bool secondary, bool checkerboa
|
|||
tileset->loadTilesImage(&tilesImage);
|
||||
|
||||
// Create default metatiles
|
||||
const int numMetatiles = tileset->is_secondary ? (Project::getNumMetatilesTotal() - Project::getNumMetatilesPrimary()) : Project::getNumMetatilesPrimary();
|
||||
const int tilesPerMetatile = projectConfig.getNumTilesInMetatile();
|
||||
for (int i = 0; i < numMetatiles; ++i) {
|
||||
for (int i = 0; i < tileset->maxMetatiles(); ++i) {
|
||||
auto metatile = new Metatile();
|
||||
for(int j = 0; j < tilesPerMetatile; ++j){
|
||||
Tile tile = Tile();
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ const QMap<CallbackType, QString> callbackFunctions = {
|
|||
{OnMapResized, "onMapResized"},
|
||||
{OnBorderResized, "onBorderResized"},
|
||||
{OnMapShifted, "onMapShifted"},
|
||||
{OnTilesetsChanged, "onTilesetsChanged"},
|
||||
{OnTilesetUpdated, "onTilesetUpdated"},
|
||||
{OnMainTabChanged, "onMainTabChanged"},
|
||||
{OnMapViewTabChanged, "onMapViewTabChanged"},
|
||||
{OnBorderVisibilityToggled, "onBorderVisibilityToggled"},
|
||||
|
|
@ -99,15 +99,12 @@ void Scripting::populateGlobalObject(MainWindow *mainWindow) {
|
|||
constants.setProperty("version", version);
|
||||
|
||||
// Get basic tileset information
|
||||
int numTilesPrimary = Project::getNumTilesPrimary();
|
||||
int numMetatilesPrimary = Project::getNumMetatilesPrimary();
|
||||
int numPalettesPrimary = Project::getNumPalettesPrimary();
|
||||
constants.setProperty("max_primary_tiles", numTilesPrimary);
|
||||
constants.setProperty("max_secondary_tiles", Project::getNumTilesTotal() - numTilesPrimary);
|
||||
constants.setProperty("max_primary_metatiles", numMetatilesPrimary);
|
||||
constants.setProperty("max_secondary_metatiles", Project::getNumMetatilesTotal() - numMetatilesPrimary);
|
||||
constants.setProperty("num_primary_palettes", numPalettesPrimary);
|
||||
constants.setProperty("num_secondary_palettes", Project::getNumPalettesTotal() - numPalettesPrimary);
|
||||
constants.setProperty("max_primary_tiles", Project::getNumTilesPrimary());
|
||||
constants.setProperty("max_secondary_tiles", Project::getNumTilesSecondary());
|
||||
constants.setProperty("max_primary_metatiles", Project::getNumMetatilesPrimary());
|
||||
constants.setProperty("max_secondary_metatiles", Project::getNumMetatilesSecondary());
|
||||
constants.setProperty("num_primary_palettes", Project::getNumPalettesPrimary());
|
||||
constants.setProperty("num_secondary_palettes", Project::getNumPalettesSecondary());
|
||||
constants.setProperty("layers_per_metatile", projectConfig.getNumLayersInMetatile());
|
||||
constants.setProperty("tiles_per_metatile", projectConfig.getNumTilesInMetatile());
|
||||
|
||||
|
|
@ -301,14 +298,13 @@ void Scripting::cb_MapShifted(int xDelta, int yDelta) {
|
|||
instance->invokeCallback(OnMapShifted, args);
|
||||
}
|
||||
|
||||
void Scripting::cb_TilesetsChanged(const QString &primaryTilesetName, const QString &secondaryTilesetName) {
|
||||
void Scripting::cb_TilesetUpdated(const QString &tilesetName) {
|
||||
if (!instance) return;
|
||||
|
||||
QJSValueList args {
|
||||
primaryTilesetName,
|
||||
secondaryTilesetName
|
||||
tilesetName,
|
||||
};
|
||||
instance->invokeCallback(OnTilesetsChanged, args);
|
||||
instance->invokeCallback(OnTilesetUpdated, args);
|
||||
}
|
||||
|
||||
void Scripting::cb_MainTabChanged(int oldTab, int newTab) {
|
||||
|
|
|
|||
|
|
@ -44,11 +44,10 @@ void BorderMetatilesPixmapItem::draw() {
|
|||
|
||||
for (int i = 0; i < width; i++) {
|
||||
for (int j = 0; j < height; j++) {
|
||||
QImage metatile_image = getMetatileImage(layout->getBorderMetatileId(i, j), layout);
|
||||
int x = i * Metatile::pixelWidth();
|
||||
int y = j * Metatile::pixelHeight();
|
||||
QImage metatile_image = getMetatileImage(layout->getBorderMetatileId(i, j), layout);
|
||||
QPoint metatile_origin = QPoint(x, y);
|
||||
painter.drawImage(metatile_origin, metatile_image);
|
||||
painter.drawImage(x, y, metatile_image);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#include "config.h"
|
||||
#include "imageproviders.h"
|
||||
#include "log.h"
|
||||
#include "editor.h"
|
||||
#include <QPainter>
|
||||
|
||||
|
|
@ -62,10 +61,10 @@ QImage getMetatileImage(
|
|||
const QList<float> &layerOpacity,
|
||||
bool useTruePalettes)
|
||||
{
|
||||
QImage metatile_image(Metatile::pixelWidth(), Metatile::pixelHeight(), QImage::Format_RGBA8888);
|
||||
QImage metatileImage(Metatile::pixelSize(), QImage::Format_RGBA8888);
|
||||
if (!metatile) {
|
||||
metatile_image.fill(getInvalidImageColor());
|
||||
return metatile_image;
|
||||
metatileImage.fill(getInvalidImageColor());
|
||||
return metatileImage;
|
||||
}
|
||||
|
||||
QList<QList<QRgb>> palettes = Tileset::getBlockPalettes(primaryTileset, secondaryTileset, useTruePalettes);
|
||||
|
|
@ -75,9 +74,9 @@ QImage getMetatileImage(
|
|||
// The GBA renders transparent pixels using palette 0 color 0. We have this color,
|
||||
// but all 3 games actually overwrite it with black when loading the tileset palettes,
|
||||
// so we have a setting to specify an override transparency color.
|
||||
metatile_image.fill(projectConfig.transparencyColor.isValid() ? projectConfig.transparencyColor : QColor(palettes.value(0).value(0)));
|
||||
metatileImage.fill(projectConfig.transparencyColor.isValid() ? projectConfig.transparencyColor : QColor(palettes.value(0).value(0)));
|
||||
|
||||
QPainter metatile_painter(&metatile_image);
|
||||
QPainter painter(&metatileImage);
|
||||
|
||||
uint32_t layerType = metatile->layerType();
|
||||
for (const auto &layer : layerOrder)
|
||||
|
|
@ -115,45 +114,31 @@ QImage getMetatileImage(
|
|||
}
|
||||
}
|
||||
|
||||
QImage tile_image = getTileImage(tile.tileId, primaryTileset, secondaryTileset);
|
||||
if (tile_image.isNull()) {
|
||||
// Some metatiles specify tiles that are outside the valid range.
|
||||
// The way the GBA will render these depends on what's in memory (which Porymap can't know)
|
||||
// so we treat them as if they were transparent.
|
||||
continue;
|
||||
}
|
||||
QImage tileImage = getColoredTileImage(tile.tileId, primaryTileset, secondaryTileset, palettes.value(tile.palette));
|
||||
|
||||
// Colorize the metatile tiles with its palette.
|
||||
if (tile.palette < palettes.length()) {
|
||||
const QList<QRgb> palette = palettes.value(tile.palette);
|
||||
for (int j = 0; j < palette.length(); j++) {
|
||||
tile_image.setColor(j, palette.value(j));
|
||||
}
|
||||
} else {
|
||||
logWarn(QString("Tile '%1' is referring to invalid palette number: '%2'").arg(tile.tileId).arg(tile.palette));
|
||||
}
|
||||
|
||||
QPoint origin = QPoint(x * Tile::pixelWidth(), y * Tile::pixelHeight());
|
||||
float opacity = layerOpacity.value(layer, 1.0);
|
||||
if (opacity < 1.0) {
|
||||
int alpha = 255 * opacity;
|
||||
for (int c = 0; c < tile_image.colorCount(); c++) {
|
||||
QColor color(tile_image.color(c));
|
||||
for (int c = 0; c < tileImage.colorCount(); c++) {
|
||||
QColor color(tileImage.color(c));
|
||||
color.setAlpha(alpha);
|
||||
tile_image.setColor(c, color.rgba());
|
||||
tileImage.setColor(c, color.rgba());
|
||||
}
|
||||
}
|
||||
|
||||
// Color 0 is displayed as transparent.
|
||||
QColor color(tile_image.color(0));
|
||||
color.setAlpha(0);
|
||||
tile_image.setColor(0, color.rgba());
|
||||
tile.flip(&tile_image);
|
||||
metatile_painter.drawImage(origin, tile_image);
|
||||
}
|
||||
metatile_painter.end();
|
||||
if (tileImage.colorCount()) {
|
||||
QColor color(tileImage.color(0));
|
||||
color.setAlpha(0);
|
||||
tileImage.setColor(0, color.rgba());
|
||||
}
|
||||
|
||||
return metatile_image;
|
||||
tile.flip(&tileImage);
|
||||
painter.drawImage(x * Tile::pixelWidth(), y * Tile::pixelHeight(), tileImage);
|
||||
}
|
||||
painter.end();
|
||||
|
||||
return metatileImage;
|
||||
}
|
||||
|
||||
QImage getTileImage(uint16_t tileId, Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
|
|
@ -164,15 +149,16 @@ QImage getTileImage(uint16_t tileId, Tileset *primaryTileset, Tileset *secondary
|
|||
QImage getColoredTileImage(uint16_t tileId, Tileset *primaryTileset, Tileset *secondaryTileset, const QList<QRgb> &palette) {
|
||||
QImage tileImage = getTileImage(tileId, primaryTileset, secondaryTileset);
|
||||
if (tileImage.isNull()) {
|
||||
tileImage = QImage(Tile::pixelWidth(), Tile::pixelHeight(), QImage::Format_RGBA8888);
|
||||
QPainter painter(&tileImage);
|
||||
painter.fillRect(0, 0, tileImage.width(), tileImage.height(), palette.value(0));
|
||||
// Some tiles specify tile IDs or palette IDs that are outside the valid range.
|
||||
// The way the GBA will render these depends on what's in memory (which Porymap can't know)
|
||||
// so we render them using the invalid color
|
||||
tileImage = QImage(Tile::pixelSize(), QImage::Format_RGBA8888);
|
||||
tileImage.fill(getInvalidImageColor());
|
||||
} else {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
tileImage.setColor(i, palette.value(i));
|
||||
tileImage.setColor(i, palette.value(i, getInvalidImageColor().rgb()));
|
||||
}
|
||||
}
|
||||
|
||||
return tileImage;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -255,23 +255,20 @@ void MetatileImageExporter::validateMetatileEnd() {
|
|||
ui->spinBox_MetatileEnd->value()));
|
||||
}
|
||||
|
||||
uint16_t MetatileImageExporter::getExpectedMetatileStart() {
|
||||
if (ui->checkBox_PrimaryTileset->isChecked()) return 0;
|
||||
if (ui->checkBox_SecondaryTileset->isChecked()) return Project::getNumMetatilesPrimary();
|
||||
return ui->spinBox_MetatileStart->value();
|
||||
}
|
||||
|
||||
uint16_t MetatileImageExporter::getExpectedMetatileEnd() {
|
||||
if (ui->checkBox_SecondaryTileset->isChecked()) return Project::getNumMetatilesPrimary() + (m_secondaryTileset ? (m_secondaryTileset->numMetatiles() - 1) : 0);
|
||||
if (ui->checkBox_PrimaryTileset->isChecked()) return m_primaryTileset ? (m_primaryTileset->numMetatiles() - 1) : 0;
|
||||
return ui->spinBox_MetatileEnd->value();
|
||||
}
|
||||
|
||||
void MetatileImageExporter::updateMetatileRange() {
|
||||
Tileset *tileset = nullptr;
|
||||
if (ui->checkBox_PrimaryTileset->isChecked()) {
|
||||
tileset = m_primaryTileset;
|
||||
} else if (ui->checkBox_PrimaryTileset->isChecked()) {
|
||||
tileset = m_secondaryTileset;
|
||||
}
|
||||
if (!tileset)
|
||||
return;
|
||||
|
||||
const QSignalBlocker b_MetatileStart(ui->spinBox_MetatileStart);
|
||||
const QSignalBlocker b_MetatileEnd(ui->spinBox_MetatileEnd);
|
||||
ui->spinBox_MetatileStart->setValue(getExpectedMetatileStart());
|
||||
ui->spinBox_MetatileEnd->setValue(getExpectedMetatileEnd());
|
||||
ui->spinBox_MetatileStart->setValue(tileset->firstMetatileId());
|
||||
ui->spinBox_MetatileEnd->setValue(tileset->lastMetatileId());
|
||||
}
|
||||
|
||||
void MetatileImageExporter::updateTilesetUI() {
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ void MetatileLayersItem::hoverMoveEvent(QGraphicsSceneHoverEvent * event) {
|
|||
if (tileIndex < 0 || tileIndex >= this->metatile->tiles.length())
|
||||
return;
|
||||
|
||||
emit this->hoveredTileChanged(this->metatile->tiles.at(tileIndex).tileId);
|
||||
emit this->hoveredTileChanged(this->metatile->tiles.at(tileIndex));
|
||||
}
|
||||
|
||||
void MetatileLayersItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *) {
|
||||
|
|
|
|||
|
|
@ -3,15 +3,16 @@
|
|||
#include "project.h"
|
||||
#include <QPainter>
|
||||
|
||||
QPoint MetatileSelector::getSelectionDimensions() {
|
||||
QPoint MetatileSelector::getSelectionDimensions() const {
|
||||
if (this->prefabSelection || this->externalSelection)
|
||||
return selection.dimensions;
|
||||
return SelectablePixmapItem::getSelectionDimensions();
|
||||
}
|
||||
|
||||
int MetatileSelector::numPrimaryMetatilesRounded() const {
|
||||
// We round up the number of primary metatiles to keep the tilesets on separate rows.
|
||||
return ceil((double)this->primaryTileset()->numMetatiles() / this->numMetatilesWide) * this->numMetatilesWide;
|
||||
if (!primaryTileset())
|
||||
return 0;
|
||||
return Util::roundUpToMultiple(primaryTileset()->numMetatiles(), this->numMetatilesWide);
|
||||
}
|
||||
|
||||
void MetatileSelector::updateBasePixmap() {
|
||||
|
|
@ -32,7 +33,11 @@ void MetatileSelector::drawSelection() {
|
|||
}
|
||||
|
||||
bool MetatileSelector::select(uint16_t metatileId) {
|
||||
if (!this->layout->metatileIsValid(metatileId)) return false;
|
||||
bool ok;
|
||||
QPoint pos = metatileIdToPos(metatileId, &ok);
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
this->externalSelection = false;
|
||||
this->prefabSelection = false;
|
||||
this->selection = MetatileSelection{
|
||||
|
|
@ -41,8 +46,7 @@ bool MetatileSelector::select(uint16_t metatileId) {
|
|||
QList<MetatileSelectionItem>({MetatileSelectionItem{true, metatileId}}),
|
||||
QList<CollisionSelectionItem>(),
|
||||
};
|
||||
QPoint coords = this->getMetatileIdCoords(metatileId);
|
||||
SelectablePixmapItem::select(coords.x(), coords.y(), 0, 0);
|
||||
SelectablePixmapItem::select(pos);
|
||||
this->updateSelectedMetatiles();
|
||||
return true;
|
||||
}
|
||||
|
|
@ -67,11 +71,7 @@ void MetatileSelector::refresh() {
|
|||
setLayout(this->layout);
|
||||
}
|
||||
|
||||
MetatileSelection MetatileSelector::getMetatileSelection() {
|
||||
return selection;
|
||||
}
|
||||
|
||||
void MetatileSelector::setExternalSelection(int width, int height, QList<uint16_t> metatiles, QList<QPair<uint16_t, uint16_t>> collisions) {
|
||||
void MetatileSelector::setExternalSelection(int width, int height, const QList<uint16_t> &metatiles, const QList<QPair<uint16_t, uint16_t>> &collisions) {
|
||||
this->prefabSelection = false;
|
||||
this->externalSelection = true;
|
||||
this->externalSelectionWidth = width;
|
||||
|
|
@ -81,18 +81,18 @@ void MetatileSelector::setExternalSelection(int width, int height, QList<uint16_
|
|||
this->selection.collisionItems.clear();
|
||||
this->selection.hasCollision = true;
|
||||
this->selection.dimensions = QPoint(width, height);
|
||||
for (int i = 0; i < metatiles.length(); i++) {
|
||||
auto collision = collisions.at(i);
|
||||
this->selection.collisionItems.append(CollisionSelectionItem{true, collision.first, collision.second});
|
||||
for (int i = 0; i < qMin(metatiles.length(), collisions.length()); i++) {
|
||||
uint16_t metatileId = metatiles.at(i);
|
||||
uint16_t collision = collisions.at(i).first;
|
||||
uint16_t elevation = collisions.at(i).second;
|
||||
this->selection.collisionItems.append(CollisionSelectionItem{true, collision, elevation});
|
||||
this->externalSelectedMetatiles.append(metatileId);
|
||||
if (!this->layout->metatileIsValid(metatileId))
|
||||
metatileId = 0;
|
||||
this->selection.metatileItems.append(MetatileSelectionItem{true, metatileId});
|
||||
}
|
||||
if (this->selection.metatileItems.length() == 1) {
|
||||
QPoint coords = this->getMetatileIdCoords(this->selection.metatileItems.first().metatileId);
|
||||
SelectablePixmapItem::select(coords.x(), coords.y(), 0, 0);
|
||||
SelectablePixmapItem::select(metatileIdToPos(this->selection.metatileItems.first().metatileId));
|
||||
}
|
||||
|
||||
this->draw();
|
||||
|
|
@ -109,7 +109,9 @@ void MetatileSelector::setPrefabSelection(MetatileSelection selection) {
|
|||
}
|
||||
|
||||
bool MetatileSelector::positionIsValid(const QPoint &pos) const {
|
||||
return this->layout->metatileIsValid(getMetatileId(pos.x(), pos.y()));
|
||||
bool ok;
|
||||
posToMetatileId(pos, &ok);
|
||||
return ok;
|
||||
}
|
||||
|
||||
void MetatileSelector::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||
|
|
@ -150,8 +152,14 @@ void MetatileSelector::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
|
|||
}
|
||||
|
||||
void MetatileSelector::hoverChanged() {
|
||||
uint16_t metatileId = this->getMetatileId(this->cellPos.x(), this->cellPos.y());
|
||||
emit this->hoveredMetatileSelectionChanged(metatileId);
|
||||
bool ok;
|
||||
uint16_t metatileId = posToMetatileId(this->cellPos, &ok);
|
||||
if (ok) {
|
||||
emit this->hoveredMetatileSelectionChanged(metatileId);
|
||||
} else {
|
||||
emit this->hoveredMetatileSelectionCleared();
|
||||
this->cellPos = QPoint(-1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void MetatileSelector::hoverLeaveEvent(QGraphicsSceneHoverEvent*) {
|
||||
|
|
@ -169,9 +177,7 @@ void MetatileSelector::updateSelectedMetatiles() {
|
|||
QPoint origin = this->getSelectionStart();
|
||||
for (int j = 0; j < this->selection.dimensions.y(); j++) {
|
||||
for (int i = 0; i < this->selection.dimensions.x(); i++) {
|
||||
uint16_t metatileId = this->getMetatileId(origin.x() + i, origin.y() + j);
|
||||
if (!this->layout->metatileIsValid(metatileId))
|
||||
metatileId = 0;
|
||||
uint16_t metatileId = posToMetatileId(origin.x() + i, origin.y() + j);
|
||||
this->selection.metatileItems.append(MetatileSelectionItem{true, metatileId});
|
||||
}
|
||||
}
|
||||
|
|
@ -190,29 +196,56 @@ void MetatileSelector::updateExternalSelectedMetatiles() {
|
|||
emit selectedMetatilesChanged();
|
||||
}
|
||||
|
||||
uint16_t MetatileSelector::getMetatileId(int x, int y) const {
|
||||
uint16_t MetatileSelector::posToMetatileId(const QPoint &pos, bool *ok) const {
|
||||
return posToMetatileId(pos.x(), pos.y(), ok);
|
||||
}
|
||||
|
||||
uint16_t MetatileSelector::posToMetatileId(int x, int y, bool *ok) const {
|
||||
if (ok) *ok = true;
|
||||
int index = y * this->numMetatilesWide + x;
|
||||
int numPrimary = this->numPrimaryMetatilesRounded();
|
||||
if (index < numPrimary) {
|
||||
return static_cast<uint16_t>(index);
|
||||
} else {
|
||||
return static_cast<uint16_t>(Project::getNumMetatilesPrimary() + index - numPrimary);
|
||||
}
|
||||
}
|
||||
|
||||
QPoint MetatileSelector::getMetatileIdCoords(uint16_t metatileId) {
|
||||
if (!this->layout->metatileIsValid(metatileId)) {
|
||||
return QPoint(0, 0);
|
||||
uint16_t metatileId = static_cast<uint16_t>(index);
|
||||
if (primaryTileset() && primaryTileset()->contains(metatileId)) {
|
||||
return metatileId;
|
||||
}
|
||||
|
||||
int index = metatileId < Project::getNumMetatilesPrimary()
|
||||
? metatileId
|
||||
: metatileId - Project::getNumMetatilesPrimary() + this->numPrimaryMetatilesRounded();
|
||||
return QPoint(index % this->numMetatilesWide, index / this->numMetatilesWide);
|
||||
// There's some extra handling here because we round the tilesets to keep them on separate rows.
|
||||
// This means if the maximum number of primary metatiles is not divisible by the metatile width
|
||||
// then the metatiles we used to round the primary tileset would have the index of valid secondary metatiles.
|
||||
// These need to be ignored, or they'll appear to be duplicates of the subseqeunt secondary metatiles.
|
||||
int numPrimaryRounded = numPrimaryMetatilesRounded();
|
||||
int firstSecondaryRow = numPrimaryRounded / qMax(this->numMetatilesWide, 1);
|
||||
metatileId = static_cast<uint16_t>(Project::getNumMetatilesPrimary() + index - numPrimaryRounded);
|
||||
if (secondaryTileset() && secondaryTileset()->contains(metatileId) && y >= firstSecondaryRow) {
|
||||
return metatileId;
|
||||
}
|
||||
|
||||
if (ok) *ok = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
QPoint MetatileSelector::getMetatileIdCoordsOnWidget(uint16_t metatileId) {
|
||||
QPoint pos = getMetatileIdCoords(metatileId);
|
||||
QPoint MetatileSelector::metatileIdToPos(uint16_t metatileId, bool *ok) const {
|
||||
if (this->numMetatilesWide == 0) {
|
||||
if (ok) *ok = false;
|
||||
return QPoint(0,0);
|
||||
}
|
||||
|
||||
if (primaryTileset() && primaryTileset()->contains(metatileId)) {
|
||||
if (ok) *ok = true;
|
||||
int index = metatileId;
|
||||
return QPoint(index % this->numMetatilesWide, index / this->numMetatilesWide);
|
||||
}
|
||||
if (secondaryTileset() && secondaryTileset()->contains(metatileId)) {
|
||||
if (ok) *ok = true;
|
||||
int index = metatileId - Project::getNumMetatilesPrimary() + numPrimaryMetatilesRounded();
|
||||
return QPoint(index % this->numMetatilesWide, index / this->numMetatilesWide);
|
||||
}
|
||||
|
||||
if (ok) *ok = false;
|
||||
return QPoint(0,0);
|
||||
}
|
||||
|
||||
QPoint MetatileSelector::getMetatileIdCoordsOnWidget(uint16_t metatileId) const {
|
||||
QPoint pos = metatileIdToPos(metatileId);
|
||||
pos.rx() = (pos.x() * this->cellWidth) + (this->cellWidth / 2);
|
||||
pos.ry() = (pos.y() * this->cellHeight) + (this->cellHeight / 2);
|
||||
return pos;
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ QList<uint16_t> ProjectSettingsEditor::getBorderMetatileIds(bool customSize) {
|
|||
// Custom border size, read metatiles from line edit
|
||||
for (auto s : ui->lineEdit_BorderMetatiles->text().split(",")) {
|
||||
uint16_t metatileId = s.toUInt(nullptr, 0);
|
||||
metatileIds.append(qMin(metatileId, static_cast<uint16_t>(Project::getNumMetatilesTotal() - 1)));
|
||||
metatileIds.append(qMin(metatileId, Block::getMaxMetatileId()));
|
||||
}
|
||||
} else {
|
||||
// Default border size, read metatiles from spin boxes
|
||||
|
|
@ -475,11 +475,10 @@ void ProjectSettingsEditor::refresh() {
|
|||
ui->checkBox_PreserveMatchingOnlyData->setChecked(projectConfig.preserveMatchingOnlyData);
|
||||
|
||||
// Radio buttons
|
||||
// TODO: Replace
|
||||
/*if (projectConfig.setTransparentPixelsBlack)
|
||||
if (projectConfig.transparencyColor == QColor(Qt::black))
|
||||
ui->radioButton_RenderBlack->setChecked(true);
|
||||
else
|
||||
ui->radioButton_RenderFirstPalColor->setChecked(true);*/
|
||||
ui->radioButton_RenderFirstPalColor->setChecked(true);
|
||||
|
||||
// Set spin box values
|
||||
ui->spinBox_Elevation->setValue(projectConfig.defaultElevation);
|
||||
|
|
@ -575,7 +574,7 @@ void ProjectSettingsEditor::save() {
|
|||
projectConfig.tilesetsHaveCallback = ui->checkBox_OutputCallback->isChecked();
|
||||
projectConfig.tilesetsHaveIsCompressed = ui->checkBox_OutputIsCompressed->isChecked();
|
||||
porymapConfig.warpBehaviorWarningDisabled = ui->checkBox_DisableWarning->isChecked();
|
||||
//projectConfig.setTransparentPixelsBlack = ui->radioButton_RenderBlack->isChecked(); // TODO
|
||||
projectConfig.transparencyColor = ui->radioButton_RenderBlack->isChecked() ? QColor(Qt::black) : QColor();
|
||||
projectConfig.preserveMatchingOnlyData = ui->checkBox_PreserveMatchingOnlyData->isChecked();
|
||||
|
||||
// Save spin box settings
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "selectablepixmapitem.h"
|
||||
#include <QPainter>
|
||||
|
||||
QPoint SelectablePixmapItem::getSelectionDimensions()
|
||||
QPoint SelectablePixmapItem::getSelectionDimensions() const
|
||||
{
|
||||
return QPoint(abs(this->selectionOffsetX) + 1, abs(this->selectionOffsetY) + 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -241,8 +241,9 @@ void TilesetEditor::initMetatileLayersItem() {
|
|||
this, &TilesetEditor::onMetatileLayerTileChanged);
|
||||
connect(this->metatileLayersItem, &MetatileLayersItem::selectedTilesChanged,
|
||||
this, &TilesetEditor::onMetatileLayerSelectionChanged);
|
||||
connect(this->metatileLayersItem, &MetatileLayersItem::hoveredTileChanged,
|
||||
this, &TilesetEditor::onHoveredTileChanged);
|
||||
connect(this->metatileLayersItem, &MetatileLayersItem::hoveredTileChanged, [this](const Tile &tile) {
|
||||
onHoveredTileChanged(tile);
|
||||
});
|
||||
connect(this->metatileLayersItem, &MetatileLayersItem::hoveredTileCleared,
|
||||
this, &TilesetEditor::onHoveredTileCleared);
|
||||
|
||||
|
|
@ -258,8 +259,9 @@ void TilesetEditor::initMetatileLayersItem() {
|
|||
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::hoveredTileChanged, [this](uint16_t tileId) {
|
||||
onHoveredTileChanged(tileId);
|
||||
});
|
||||
connect(this->tileSelector, &TilesetEditorTileSelector::hoveredTileCleared,
|
||||
this, &TilesetEditor::onHoveredTileCleared);
|
||||
connect(this->tileSelector, &TilesetEditorTileSelector::selectedTilesChanged,
|
||||
|
|
@ -453,8 +455,17 @@ void TilesetEditor::queueMetatileReload(uint16_t metatileId) {
|
|||
this->metatileReloadQueue.insert(metatileId);
|
||||
}
|
||||
|
||||
void TilesetEditor::onHoveredTileChanged(uint16_t tile) {
|
||||
this->ui->statusbar->showMessage(QString("Tile: %1").arg(Util::toHexString(tile, 3)));
|
||||
void TilesetEditor::onHoveredTileChanged(const Tile &tile) {
|
||||
this->ui->statusbar->showMessage(QString("Tile: %1, Palette: %2%3%4")
|
||||
.arg(Util::toHexString(tile.tileId, 3))
|
||||
.arg(QString::number(tile.palette))
|
||||
.arg(tile.xflip ? ", X-flipped" : "")
|
||||
.arg(tile.yflip ? ", Y-flipped" : "")
|
||||
);
|
||||
}
|
||||
|
||||
void TilesetEditor::onHoveredTileChanged(uint16_t tileId) {
|
||||
this->ui->statusbar->showMessage(QString("Tile: %1").arg(Util::toHexString(tileId, 3)));
|
||||
}
|
||||
|
||||
void TilesetEditor::onHoveredTileCleared() {
|
||||
|
|
@ -834,7 +845,7 @@ void TilesetEditor::on_actionChange_Metatiles_Count_triggered()
|
|||
primarySpinBox->setMinimum(1);
|
||||
secondarySpinBox->setMinimum(1);
|
||||
primarySpinBox->setMaximum(Project::getNumMetatilesPrimary());
|
||||
secondarySpinBox->setMaximum(Project::getNumMetatilesTotal() - Project::getNumMetatilesPrimary());
|
||||
secondarySpinBox->setMaximum(Project::getNumMetatilesSecondary());
|
||||
primarySpinBox->setValue(this->primaryTileset->numMetatiles());
|
||||
secondarySpinBox->setValue(this->secondaryTileset->numMetatiles());
|
||||
form.addRow(new QLabel("Primary Tileset"), primarySpinBox);
|
||||
|
|
@ -1018,7 +1029,7 @@ void TilesetEditor::importAdvanceMapMetatiles(Tileset *tileset) {
|
|||
|
||||
// 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();
|
||||
uint16_t metatileIdBase = tileset->firstMetatileId();
|
||||
for (int i = 0; i < metatiles.length(); i++) {
|
||||
if (i >= tileset->numMetatiles()) {
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@
|
|||
#include "project.h"
|
||||
#include <QPainter>
|
||||
|
||||
// TODO: This class has a decent bit of overlap with the MetatileSelector class.
|
||||
// They should be refactored to inherit from a single parent class.
|
||||
|
||||
TilesetEditorMetatileSelector::TilesetEditorMetatileSelector(Tileset *primaryTileset, Tileset *secondaryTileset, Layout *layout)
|
||||
: SelectablePixmapItem(32, 32, 1, 1) {
|
||||
this->primaryTileset = primaryTileset;
|
||||
|
|
@ -13,7 +16,7 @@ TilesetEditorMetatileSelector::TilesetEditorMetatileSelector(Tileset *primaryTil
|
|||
this->usedMetatiles.resize(Project::getNumMetatilesTotal());
|
||||
}
|
||||
|
||||
int TilesetEditorMetatileSelector::numRows(int numMetatiles) {
|
||||
int TilesetEditorMetatileSelector::numRows(int numMetatiles) const {
|
||||
int numMetatilesHigh = numMetatiles / this->numMetatilesWide;
|
||||
if (numMetatiles % this->numMetatilesWide != 0) {
|
||||
// Round up height for incomplete last row
|
||||
|
|
@ -22,17 +25,21 @@ int TilesetEditorMetatileSelector::numRows(int numMetatiles) {
|
|||
return numMetatilesHigh;
|
||||
}
|
||||
|
||||
int TilesetEditorMetatileSelector::numRows() {
|
||||
int TilesetEditorMetatileSelector::numRows() const {
|
||||
return this->numRows(this->numPrimaryMetatilesRounded() + this->secondaryTileset->numMetatiles());
|
||||
}
|
||||
|
||||
int TilesetEditorMetatileSelector::numPrimaryMetatilesRounded() const {
|
||||
// We round up the number of primary metatiles to keep the tilesets on separate rows.
|
||||
return ceil((double)this->primaryTileset->numMetatiles() / this->numMetatilesWide) * this->numMetatilesWide;
|
||||
if (!this->primaryTileset)
|
||||
return 0;
|
||||
return Util::roundUpToMultiple(this->primaryTileset->numMetatiles(), this->numMetatilesWide);
|
||||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::drawMetatile(uint16_t metatileId) {
|
||||
QPoint pos = getMetatileIdCoords(metatileId);
|
||||
bool ok;
|
||||
QPoint pos = metatileIdToPos(metatileId, &ok);
|
||||
if (!ok)
|
||||
return;
|
||||
|
||||
QPainter painter(&this->baseImage);
|
||||
QImage metatile_image = getMetatileImage(
|
||||
|
|
@ -78,9 +85,11 @@ void TilesetEditorMetatileSelector::draw() {
|
|||
}
|
||||
|
||||
bool TilesetEditorMetatileSelector::select(uint16_t metatileId) {
|
||||
if (!Tileset::metatileIsValid(metatileId, this->primaryTileset, this->secondaryTileset)) return false;
|
||||
QPoint coords = this->getMetatileIdCoords(metatileId);
|
||||
SelectablePixmapItem::select(coords.x(), coords.y(), 0, 0);
|
||||
bool ok;
|
||||
QPoint pos = metatileIdToPos(metatileId, &ok);
|
||||
if (!ok)
|
||||
return false;
|
||||
SelectablePixmapItem::select(pos);
|
||||
this->selectedMetatileId = metatileId;
|
||||
emit selectedMetatileChanged(metatileId);
|
||||
return true;
|
||||
|
|
@ -95,32 +104,19 @@ void TilesetEditorMetatileSelector::setTilesets(Tileset *primaryTileset, Tileset
|
|||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::updateSelectedMetatile() {
|
||||
QPoint origin = this->getSelectionStart();
|
||||
uint16_t metatileId = this->getMetatileId(origin.x(), origin.y());
|
||||
if (Tileset::metatileIsValid(metatileId, this->primaryTileset, this->secondaryTileset))
|
||||
this->selectedMetatileId = metatileId;
|
||||
else
|
||||
this->selectedMetatileId = Project::getNumMetatilesPrimary() + this->secondaryTileset->numMetatiles() - 1;
|
||||
bool ok;
|
||||
uint16_t metatileId = posToMetatileId(getSelectionStart(), &ok);
|
||||
if (!ok)
|
||||
return;
|
||||
|
||||
this->selectedMetatileId = metatileId;
|
||||
emit selectedMetatileChanged(this->selectedMetatileId);
|
||||
}
|
||||
|
||||
uint16_t TilesetEditorMetatileSelector::getSelectedMetatileId() {
|
||||
return this->selectedMetatileId;
|
||||
}
|
||||
|
||||
uint16_t TilesetEditorMetatileSelector::getMetatileId(int x, int y) {
|
||||
int index = y * this->numMetatilesWide + x;
|
||||
int numPrimary = numPrimaryMetatilesRounded();
|
||||
if (index < numPrimary) {
|
||||
return static_cast<uint16_t>(index);
|
||||
} else {
|
||||
return static_cast<uint16_t>(Project::getNumMetatilesPrimary() + index - numPrimary);
|
||||
}
|
||||
}
|
||||
|
||||
bool TilesetEditorMetatileSelector::shouldAcceptEvent(QGraphicsSceneMouseEvent *event) {
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
return Tileset::metatileIsValid(getMetatileId(pos.x(), pos.y()), this->primaryTileset, this->secondaryTileset);
|
||||
bool ok;
|
||||
posToMetatileId(getCellPos(event->pos()), &ok);
|
||||
return ok;
|
||||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||
|
|
@ -143,29 +139,69 @@ void TilesetEditorMetatileSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent *
|
|||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
uint16_t metatileId = this->getMetatileId(pos.x(), pos.y());
|
||||
emit this->hoveredMetatileChanged(metatileId);
|
||||
bool ok;
|
||||
uint16_t metatileId = posToMetatileId(getCellPos(event->pos()), &ok);
|
||||
if (ok) {
|
||||
emit this->hoveredMetatileChanged(metatileId);
|
||||
} else {
|
||||
emit this->hoveredMetatileCleared();
|
||||
}
|
||||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::hoverLeaveEvent(QGraphicsSceneHoverEvent*) {
|
||||
emit this->hoveredMetatileCleared();
|
||||
}
|
||||
|
||||
QPoint TilesetEditorMetatileSelector::getMetatileIdCoords(uint16_t metatileId) {
|
||||
if (!Tileset::metatileIsValid(metatileId, this->primaryTileset, this->secondaryTileset))
|
||||
{
|
||||
// Invalid metatile id.
|
||||
return QPoint(0, 0);
|
||||
}
|
||||
int index = metatileId < Project::getNumMetatilesPrimary()
|
||||
? metatileId
|
||||
: metatileId - Project::getNumMetatilesPrimary() + this->numPrimaryMetatilesRounded();
|
||||
return QPoint(index % this->numMetatilesWide, index / this->numMetatilesWide);
|
||||
uint16_t TilesetEditorMetatileSelector::posToMetatileId(const QPoint &pos, bool *ok) const {
|
||||
return posToMetatileId(pos.x(), pos.y(), ok);
|
||||
}
|
||||
|
||||
QPoint TilesetEditorMetatileSelector::getMetatileIdCoordsOnWidget(uint16_t metatileId) {
|
||||
QPoint pos = getMetatileIdCoords(metatileId);
|
||||
uint16_t TilesetEditorMetatileSelector::posToMetatileId(int x, int y, bool *ok) const {
|
||||
if (ok) *ok = true;
|
||||
int index = y * this->numMetatilesWide + x;
|
||||
uint16_t metatileId = static_cast<uint16_t>(index);
|
||||
if (this->primaryTileset && this->primaryTileset->contains(metatileId)) {
|
||||
return metatileId;
|
||||
}
|
||||
|
||||
// There's some extra handling here because we round the tilesets to keep them on separate rows.
|
||||
// This means if the maximum number of primary metatiles is not divisible by the metatile width
|
||||
// then the metatiles we used to round the primary tileset would have the index of valid secondary metatiles.
|
||||
// These need to be ignored, or they'll appear to be duplicates of the subseqeunt secondary metatiles.
|
||||
int numPrimaryRounded = numPrimaryMetatilesRounded();
|
||||
int firstSecondaryRow = numPrimaryRounded / qMax(this->numMetatilesWide, 1);
|
||||
metatileId = static_cast<uint16_t>(Project::getNumMetatilesPrimary() + index - numPrimaryRounded);
|
||||
if (this->secondaryTileset && this->secondaryTileset->contains(metatileId) && y >= firstSecondaryRow) {
|
||||
return metatileId;
|
||||
}
|
||||
|
||||
if (ok) *ok = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
QPoint TilesetEditorMetatileSelector::metatileIdToPos(uint16_t metatileId, bool *ok) const {
|
||||
if (this->numMetatilesWide == 0) {
|
||||
if (ok) *ok = false;
|
||||
return QPoint(0,0);
|
||||
}
|
||||
|
||||
if (this->primaryTileset && this->primaryTileset->contains(metatileId)) {
|
||||
if (ok) *ok = true;
|
||||
int index = metatileId;
|
||||
return QPoint(index % this->numMetatilesWide, index / this->numMetatilesWide);
|
||||
}
|
||||
if (this->secondaryTileset && this->secondaryTileset->contains(metatileId)) {
|
||||
if (ok) *ok = true;
|
||||
int index = metatileId - Project::getNumMetatilesPrimary() + numPrimaryMetatilesRounded();
|
||||
return QPoint(index % this->numMetatilesWide, index / this->numMetatilesWide);
|
||||
}
|
||||
|
||||
if (ok) *ok = false;
|
||||
return QPoint(0,0);
|
||||
}
|
||||
|
||||
QPoint TilesetEditorMetatileSelector::getMetatileIdCoordsOnWidget(uint16_t metatileId) const {
|
||||
QPoint pos = metatileIdToPos(metatileId);
|
||||
pos.rx() = (pos.x() * this->cellWidth) + (this->cellWidth / 2);
|
||||
pos.ry() = (pos.y() * this->cellHeight) + (this->cellHeight / 2);
|
||||
return pos;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include <QPainter>
|
||||
#include <QVector>
|
||||
|
||||
QPoint TilesetEditorTileSelector::getSelectionDimensions() {
|
||||
QPoint TilesetEditorTileSelector::getSelectionDimensions() const {
|
||||
if (this->externalSelection) {
|
||||
return QPoint(this->externalSelectionWidth, this->externalSelectionHeight);
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user