diff --git a/include/config.h b/include/config.h index 51c11a74..6e38ae4a 100644 --- a/include/config.h +++ b/include/config.h @@ -66,57 +66,7 @@ class PorymapConfig: public KeyValueConfigBase { public: PorymapConfig(); - virtual void reset() override { - setRoot(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); - this->recentProjects.clear(); - this->projectManuallyClosed = false; - this->reopenOnLaunch = true; - this->mapListTab = 0; - this->mapListEditGroupsEnabled = false; - this->mapListHideEmptyEnabled.clear(); - this->prettyCursors = true; - this->mirrorConnectingMaps = true; - this->showDiveEmergeMaps = false; - this->diveEmergeMapOpacity = 30; - this->diveMapOpacity = 15; - this->emergeMapOpacity = 15; - this->collisionOpacity = 50; - this->collisionZoom = 30; - this->metatilesZoom = 30; - this->tilesetEditorMetatilesZoom = 30; - this->tilesetEditorTilesZoom = 30; - this->showPlayerView = false; - this->showCursorTile = true; - this->showBorder = true; - this->showGrid = false; - this->showTilesetEditorMetatileGrid = false; - this->showTilesetEditorLayerGrid = true; - this->showTilesetEditorDivider = false; - this->showTilesetEditorRawAttributes = false; - this->monitorFiles = true; - this->tilesetCheckerboardFill = true; - this->newMapHeaderSectionExpanded = false; - this->theme = "default"; - this->wildMonChartTheme = ""; - this->textEditorOpenFolder = ""; - this->textEditorGotoLine = ""; - this->paletteEditorBitDepth = 24; - this->projectSettingsTab = 0; - this->loadAllEventScripts = false; - this->warpBehaviorWarningDisabled = false; - this->eventDeleteWarningDisabled = false; - this->eventOverlayEnabled = false; - this->checkForUpdates = true; - this->lastUpdateCheckTime = QDateTime(); - this->lastUpdateCheckVersion = porymapVersion; - this->rateLimitTimes.clear(); - this->eventSelectionShapeMode = QGraphicsPixmapItem::MaskShape; - this->shownInGameReloadMessage = false; - this->gridSettings = GridSettings(); - this->statusBarLogTypes = { LogType::LOG_ERROR, LogType::LOG_WARN }; - this->applicationFont = QFont(); - this->mapListFont = PorymapConfig::defaultMapListFont(); - } + virtual void reset() override; void addRecentProject(QString project); void setRecentProjects(QStringList projects); QString getRecentProject(); diff --git a/include/core/map.h b/include/core/map.h index f5cc1ef1..3b843f2a 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -51,10 +51,12 @@ public: void setLayoutId(const QString &layoutId) { m_layoutId = layoutId; } QString layoutId() const { return layout() ? layout()->id : m_layoutId; } - int getWidth() const; - int getHeight() const; - int getBorderWidth() const; - int getBorderHeight() const; + int getWidth() const { return m_layout ? m_layout->getWidth() : 0; } + int getHeight() const { return m_layout ? m_layout->getHeight() : 0; } + int getBorderWidth() const { return m_layout ? m_layout->getBorderWidth() : 0; } + int getBorderHeight() const { return m_layout ? m_layout->getBorderHeight() : 0; } + int pixelWidth() const { return m_layout ? m_layout->pixelWidth() : 0; } + int pixelHeight() const { return m_layout ? m_layout->pixelHeight() : 0; } void setHeader(const MapHeader &header) { *m_header = header; } MapHeader* header() const { return m_header; } diff --git a/include/core/mapconnection.h b/include/core/mapconnection.h index 5df071bd..ba7c95a8 100644 --- a/include/core/mapconnection.h +++ b/include/core/mapconnection.h @@ -42,7 +42,7 @@ public: MapConnection* createMirror(); QPixmap render() const; - QPoint relativePos(bool clipped = false) const; + QPoint relativePixelPos(bool clipped = false) const; static QPointer project; static const QMap oppositeDirections; diff --git a/include/core/maplayout.h b/include/core/maplayout.h index 8091469a..2dc3cc24 100644 --- a/include/core/maplayout.h +++ b/include/core/maplayout.h @@ -32,6 +32,9 @@ public: int height; int border_width; int border_height; + int pixelWidth() const { return this->width * Metatile::pixelWidth(); } + int pixelHeight() const { return this->height * Metatile::pixelHeight(); } + QSize pixelSize() const { return QSize(pixelWidth(), pixelHeight()); } QString border_path; QString blockdata_path; @@ -153,7 +156,7 @@ public: void _floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation); void magicFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation); - QPixmap render(bool ignoreCache = false, Layout *fromLayout = nullptr, QRect bounds = QRect(0, 0, -1, -1)); + 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); diff --git a/include/core/metatile.h b/include/core/metatile.h index a57717fe..e35e1fa3 100644 --- a/include/core/metatile.h +++ b/include/core/metatile.h @@ -64,12 +64,12 @@ public: static QString getMetatileIdStrings(const QList metatileIds); static QString getLayerName(int layerNum); - static int tileWidth() { return 2; } - static int tileHeight() { return 2; } - static int tilesPerLayer() { return Metatile::tileWidth() * Metatile::tileHeight(); } - static int pixelWidth() { return Metatile::tileWidth() * Tile::pixelWidth(); } - static int pixelHeight() { return Metatile::tileHeight() * Tile::pixelHeight(); } - static QSize pixelSize() { return QSize(pixelWidth(), pixelHeight()); } + static constexpr int tileWidth() { return 2; } + static constexpr int tileHeight() { return 2; } + static constexpr int tilesPerLayer() { return Metatile::tileWidth() * Metatile::tileHeight(); } + static constexpr int pixelWidth() { return Metatile::tileWidth() * Tile::pixelWidth(); } + static constexpr int pixelHeight() { return Metatile::tileHeight() * Tile::pixelHeight(); } + static constexpr QSize pixelSize() { return QSize(pixelWidth(), pixelHeight()); } inline bool operator==(const Metatile &other) { return this->tiles == other.tiles && this->attributes == other.attributes; diff --git a/include/core/tile.h b/include/core/tile.h index d7ae5061..585ceebf 100644 --- a/include/core/tile.h +++ b/include/core/tile.h @@ -26,9 +26,9 @@ public: static const uint16_t maxValue; - static int pixelWidth() { return 8; } - static int pixelHeight() { return 8; } - static QSize pixelSize() { return QSize(Tile::pixelWidth(), Tile::pixelHeight()); } + static constexpr int pixelWidth() { return 8; } + static constexpr int pixelHeight() { return 8; } + static constexpr QSize pixelSize() { return QSize(Tile::pixelWidth(), Tile::pixelHeight()); } }; inline bool operator==(const Tile &a, const Tile &b) { diff --git a/include/project.h b/include/project.h index ca7d9bbe..c5ef6338 100644 --- a/include/project.h +++ b/include/project.h @@ -251,6 +251,7 @@ public: static QString getDynamicMapDefineName(); static QString getDynamicMapName(); static QString getEmptySpeciesName(); + static QMargins getPixelViewDistance(); static QMargins getMetatileViewDistance(); static int getNumTilesPrimary() { return num_tiles_primary; } static int getNumTilesTotal() { return num_tiles_total; } diff --git a/include/ui/connectionpixmapitem.h b/include/ui/connectionpixmapitem.h index 32e309f9..5106ba8f 100644 --- a/include/ui/connectionpixmapitem.h +++ b/include/ui/connectionpixmapitem.h @@ -2,6 +2,7 @@ #define CONNECTIONPIXMAPITEM_H #include "mapconnection.h" +#include "metatile.h" #include #include #include @@ -31,8 +32,8 @@ private: bool selected = false; unsigned actionId = 0; - static const int mWidth = 16; - static const int mHeight = 16; + static const int mWidth = Metatile::pixelWidth(); + static const int mHeight = Metatile::pixelHeight(); void updatePos(); void updateOrigin(); diff --git a/include/ui/mapruler.h b/include/ui/mapruler.h index 151492e3..160978cc 100644 --- a/include/ui/mapruler.h +++ b/include/ui/mapruler.h @@ -3,6 +3,7 @@ #include #include +#include "metatile.h" class MapRuler : public QGraphicsObject, private QLine @@ -63,8 +64,8 @@ private: QPoint snapToWithinBounds(QPoint pos) const; void updateGeometry(); void updateStatus(Qt::Corner corner); - int pixWidth() const { return width() * 16; } - int pixHeight() const { return height() * 16; } + int pixWidth() const { return width() * Metatile::pixelWidth(); } + int pixHeight() const { return height() * Metatile::pixelHeight(); } }; #endif // MAPRULER_H diff --git a/include/ui/metatileselector.h b/include/ui/metatileselector.h index f5faa1e0..d7c6a40b 100644 --- a/include/ui/metatileselector.h +++ b/include/ui/metatileselector.h @@ -31,7 +31,7 @@ struct MetatileSelection class MetatileSelector: public SelectablePixmapItem { Q_OBJECT public: - MetatileSelector(int numMetatilesWide, Layout *layout): SelectablePixmapItem(16, 16) { + MetatileSelector(int numMetatilesWide, Layout *layout): SelectablePixmapItem(Metatile::pixelWidth(), Metatile::pixelHeight()) { this->externalSelection = false; this->prefabSelection = false; this->numMetatilesWide = numMetatilesWide; diff --git a/include/ui/movablerect.h b/include/ui/movablerect.h index 552ad6f5..7940e592 100644 --- a/include/ui/movablerect.h +++ b/include/ui/movablerect.h @@ -10,7 +10,7 @@ class MovableRect : public QGraphicsRectItem { public: - MovableRect(const QRectF &rect, const QRgb &color); + MovableRect(const QRectF &rect, const QSize &cellSize, const QRgb &color); QRectF boundingRect() const override { qreal penWidth = 4; return QRectF(-penWidth, @@ -31,6 +31,7 @@ public: protected: QRectF baseRect; + QSize cellSize; QRgb color; void updateVisibility(); @@ -43,7 +44,7 @@ class ResizableRect : public QObject, public MovableRect { Q_OBJECT public: - ResizableRect(QObject *parent, int width, int height, QRgb color); + ResizableRect(QObject *parent, const QSize &cellSize, const QSize &size, const QRgb &color); QRectF boundingRect() const override { return QRectF(this->rect() + QMargins(lineWidth, lineWidth, lineWidth, lineWidth)); diff --git a/include/ui/resizelayoutpopup.h b/include/ui/resizelayoutpopup.h index 89ce2e99..4f8482a7 100644 --- a/include/ui/resizelayoutpopup.h +++ b/include/ui/resizelayoutpopup.h @@ -45,10 +45,10 @@ private: /// PixmapItem subclass which allows for creating a boundary which determine whether /// the pixmap paints normally or with a black tint. -/// This item is movable and snaps on a 16x16 grid. +/// This item is movable and snaps on a 'cellSize' grid. class BoundedPixmapItem : public QGraphicsPixmapItem { public: - BoundedPixmapItem(const QPixmap &pixmap, QGraphicsItem *parent = nullptr); + BoundedPixmapItem(const QPixmap &pixmap, const QSize &cellSize, QGraphicsItem *parent = nullptr); void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override; void setBoundary(ResizableRect *rect) { this->boundary = rect; } @@ -59,6 +59,7 @@ protected: private: ResizableRect *boundary = nullptr; QPointF clickedPos = QPointF(); + QSize cellSize; }; diff --git a/include/ui/selectablepixmapitem.h b/include/ui/selectablepixmapitem.h index 2681e485..d497e00d 100644 --- a/include/ui/selectablepixmapitem.h +++ b/include/ui/selectablepixmapitem.h @@ -7,13 +7,18 @@ class SelectablePixmapItem : public QObject, public QGraphicsPixmapItem { Q_OBJECT public: - SelectablePixmapItem(int cellWidth, int cellHeight): SelectablePixmapItem(cellWidth, cellHeight, INT_MAX, INT_MAX) {} - SelectablePixmapItem(int cellWidth, int cellHeight, int maxSelectionWidth, int maxSelectionHeight) { - this->cellWidth = cellWidth; - this->cellHeight = cellHeight; - this->maxSelectionWidth = maxSelectionWidth; - this->maxSelectionHeight = maxSelectionHeight; - } + SelectablePixmapItem(const QSize &size, const QSize &maxSelectionSize = QSize(INT_MAX, INT_MAX)) + : SelectablePixmapItem(size.width(), size.height(), maxSelectionSize.width(), maxSelectionSize.height()) {} + SelectablePixmapItem(int cellWidth, int cellHeight, int maxSelectionWidth = INT_MAX, int maxSelectionHeight = INT_MAX) + : cellWidth(cellWidth), + cellHeight(cellHeight), + maxSelectionWidth(maxSelectionWidth), + maxSelectionHeight(maxSelectionHeight), + selectionInitialX(0), + selectionInitialY(0), + selectionOffsetX(0), + selectionOffsetY(0) + {} virtual QPoint getSelectionDimensions(); virtual void draw() = 0; diff --git a/include/ui/tileseteditortileselector.h b/include/ui/tileseteditortileselector.h index aa2a1923..bed655e1 100644 --- a/include/ui/tileseteditortileselector.h +++ b/include/ui/tileseteditortileselector.h @@ -8,7 +8,7 @@ class TilesetEditorTileSelector: public SelectablePixmapItem { Q_OBJECT public: TilesetEditorTileSelector(Tileset *primaryTileset, Tileset *secondaryTileset, int numLayers) - : SelectablePixmapItem(16, 16, numLayers * 2, 2) { + : SelectablePixmapItem(16, 16, numLayers * Metatile::tileWidth(), Metatile::tileHeight()) { this->primaryTileset = primaryTileset; this->secondaryTileset = secondaryTileset; this->numTilesWide = 16; diff --git a/src/config.cpp b/src/config.cpp index 8b2f24a9..f3457e9e 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -4,6 +4,7 @@ #include "map.h" #include "validator.h" #include "utility.h" +#include "metatile.h" #include #include #include @@ -315,6 +316,60 @@ PorymapConfig::PorymapConfig() : KeyValueConfigBase(QStringLiteral("porymap.cfg" reset(); } +void PorymapConfig::reset() { + setRoot(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); + this->recentProjects.clear(); + this->projectManuallyClosed = false; + this->reopenOnLaunch = true; + this->mapListTab = 0; + this->mapListEditGroupsEnabled = false; + this->mapListHideEmptyEnabled.clear(); + this->prettyCursors = true; + this->mirrorConnectingMaps = true; + this->showDiveEmergeMaps = false; + this->diveEmergeMapOpacity = 30; + this->diveMapOpacity = 15; + this->emergeMapOpacity = 15; + this->collisionOpacity = 50; + this->collisionZoom = 30; + this->metatilesZoom = 30; + this->tilesetEditorMetatilesZoom = 30; + this->tilesetEditorTilesZoom = 30; + this->showPlayerView = false; + this->showCursorTile = true; + this->showBorder = true; + this->showGrid = false; + this->showTilesetEditorMetatileGrid = false; + this->showTilesetEditorLayerGrid = true; + this->showTilesetEditorDivider = false; + this->showTilesetEditorRawAttributes = false; + this->monitorFiles = true; + this->tilesetCheckerboardFill = true; + this->newMapHeaderSectionExpanded = false; + this->theme = "default"; + this->wildMonChartTheme = ""; + this->textEditorOpenFolder = ""; + this->textEditorGotoLine = ""; + this->paletteEditorBitDepth = 24; + this->projectSettingsTab = 0; + this->loadAllEventScripts = false; + this->warpBehaviorWarningDisabled = false; + this->eventDeleteWarningDisabled = false; + this->eventOverlayEnabled = false; + this->checkForUpdates = true; + this->lastUpdateCheckTime = QDateTime(); + this->lastUpdateCheckVersion = porymapVersion; + this->rateLimitTimes.clear(); + this->eventSelectionShapeMode = QGraphicsPixmapItem::MaskShape; + this->shownInGameReloadMessage = false; + this->gridSettings = GridSettings(); + this->gridSettings.width = Metatile::pixelWidth(); + this->gridSettings.height = Metatile::pixelHeight(); + this->statusBarLogTypes = { LogType::LOG_ERROR, LogType::LOG_WARN }; + this->applicationFont = QFont(); + this->mapListFont = PorymapConfig::defaultMapListFont(); +} + void PorymapConfig::parseConfigKeyValue(QString key, QString value) { if (key == "recent_project") { this->recentProjects = value.split(",", Qt::SkipEmptyParts); @@ -1186,7 +1241,7 @@ int ProjectConfig::getNumLayersInMetatile() { } int ProjectConfig::getNumTilesInMetatile() { - return this->tripleLayerMetatilesEnabled ? 12 : 8; + return getNumLayersInMetatile() * Metatile::tilesPerLayer(); } void ProjectConfig::setEventIconPath(Event::Group group, const QString &path) { diff --git a/src/core/map.cpp b/src/core/map.cpp index 03fee13e..079f336a 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -62,44 +62,28 @@ QString Map::mapConstantFromName(const QString &name) { return projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix) + Util::toDefineCase(name); } -int Map::getWidth() const { - return m_layout ? m_layout->getWidth() : 0; -} - -int Map::getHeight() const { - return m_layout ? m_layout->getHeight() : 0; -} - -int Map::getBorderWidth() const { - return m_layout ? m_layout->getBorderWidth() : 0; -} - -int Map::getBorderHeight() const { - return m_layout ? m_layout->getBorderHeight() : 0; -} - // Get the portion of the map that can be rendered when rendered as a map connection. // Cardinal connections render the nearest segment of their map and within the bounds of the border draw distance, // Dive/Emerge connections are rendered normally within the bounds of their parent map. QRect Map::getConnectionRect(const QString &direction, Layout * fromLayout) const { int x = 0, y = 0; - int w = getWidth(), h = getHeight(); + int w = pixelWidth(), h = pixelHeight(); - QMargins viewDistance = Project::getMetatileViewDistance(); + QMargins viewDistance = Project::getPixelViewDistance(); if (direction == "up") { h = qMin(h, viewDistance.top()); - y = getHeight() - h; + y = pixelHeight() - h; } else if (direction == "down") { h = qMin(h, viewDistance.bottom()); } else if (direction == "left") { w = qMin(w, viewDistance.left()); - x = getWidth() - w; + x = pixelWidth() - w; } else if (direction == "right") { w = qMin(w, viewDistance.right()); } else if (MapConnection::isDiving(direction)) { if (fromLayout) { - w = qMin(w, fromLayout->getWidth()); - h = qMin(h, fromLayout->getHeight()); + w = qMin(w, fromLayout->pixelWidth()); + h = qMin(h, fromLayout->pixelHeight()); } } else { // Unknown direction @@ -122,7 +106,7 @@ QPixmap Map::renderConnection(const QString &direction, Layout * fromLayout) { fromLayout = nullptr; QPixmap connectionPixmap = m_layout->render(true, fromLayout, bounds); - return connectionPixmap.copy(bounds.x() * 16, bounds.y() * 16, bounds.width() * 16, bounds.height() * 16); + return connectionPixmap.copy(bounds); } void Map::openScript(const QString &label) { diff --git a/src/core/mapconnection.cpp b/src/core/mapconnection.cpp index d37a8c74..3e5d82dd 100644 --- a/src/core/mapconnection.cpp +++ b/src/core/mapconnection.cpp @@ -72,20 +72,20 @@ QPixmap MapConnection::render() const { // For right/down connections this is offset by the dimensions of the parent map. // For left/up connections this is offset by the dimensions of the target map. // If 'clipped' is true, only the rendered dimensions of the target map will be used, rather than its full dimensions. -QPoint MapConnection::relativePos(bool clipped) const { +QPoint MapConnection::relativePixelPos(bool clipped) const { int x = 0, y = 0; if (m_direction == "right") { - if (m_parentMap) x = m_parentMap->getWidth(); + if (m_parentMap) x = m_parentMap->pixelWidth(); y = m_offset; } else if (m_direction == "down") { x = m_offset; - if (m_parentMap) y = m_parentMap->getHeight(); + if (m_parentMap) y = m_parentMap->pixelHeight(); } else if (m_direction == "left") { - if (targetMap()) x = !clipped ? -targetMap()->getWidth() : -targetMap()->getConnectionRect(m_direction).width(); + if (targetMap()) x = !clipped ? -targetMap()->pixelWidth() : -targetMap()->getConnectionRect(m_direction).width(); y = m_offset; } else if (m_direction == "up") { x = m_offset; - if (targetMap()) y = !clipped ? -targetMap()->getHeight() : -targetMap()->getConnectionRect(m_direction).height(); + if (targetMap()) y = !clipped ? -targetMap()->pixelHeight() : -targetMap()->getConnectionRect(m_direction).height(); } return QPoint(x, y); } diff --git a/src/core/maplayout.cpp b/src/core/maplayout.cpp index 7ab13ec7..a8d3934d 100644 --- a/src/core/maplayout.cpp +++ b/src/core/maplayout.cpp @@ -92,12 +92,11 @@ QMargins Layout::getBorderMargins() const { return distance; } -// Get a rectangle that represents (in pixels) the layout's map area and the visible area of its border. -// At maximum, this is equal to the map size plus the border margins. -// If the border is large (and so beyond player the view) it may be smaller than that. +// Get a rectangle that represents (in pixels) the layout's map area + the distance the player can see. +// Note that this may be smaller than the map area + the size of the border for layouts with large border dimensions. QRect Layout::getVisibleRect() const { - QRect area = QRect(0, 0, this->width * 16, this->height * 16); - return area += (Project::getMetatileViewDistance() * 16); + QRect area = QRect(0, 0, this->pixelWidth(), this->pixelHeight()); + return area += Project::getPixelViewDistance(); } bool Layout::getBlock(int x, int y, Block *out) { @@ -344,15 +343,13 @@ void Layout::magicFillCollisionElevation(int initialX, int initialY, uint16_t co } } -QPixmap Layout::render(bool ignoreCache, Layout *fromLayout, QRect bounds) { +QPixmap Layout::render(bool ignoreCache, Layout *fromLayout, const QRect &bounds) { bool changed_any = false; - int width_ = getWidth(); - int height_ = getHeight(); - if (this->image.isNull() || this->image.width() != width_ * 16 || this->image.height() != height_ * 16) { - this->image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888); + if (this->image.isNull() || this->image.width() != pixelWidth() || this->image.height() != pixelHeight()) { + this->image = QImage(pixelWidth(), pixelHeight(), QImage::Format_RGBA8888); changed_any = true; } - if (this->blockdata.isEmpty() || !width_ || !height_) { + if (this->blockdata.isEmpty() || this->width == 0 || this->height == 0) { this->pixmap = this->pixmap.fromImage(this->image); return this->pixmap; } @@ -368,9 +365,9 @@ QPixmap Layout::render(bool ignoreCache, Layout *fromLayout, QRect bounds) { if (!ignoreCache && !layoutBlockChanged(i, this->blockdata, this->cached_blockdata)) { continue; } - int map_y = width_ ? i / width_ : 0; - int map_x = width_ ? i % width_ : 0; - if (bounds.isValid() && !bounds.contains(map_x, map_y)) { + int x = this->width ? ((i % this->width) * Metatile::pixelWidth()) : 0; + int y = this->width ? ((i / this->width) * Metatile::pixelHeight()) : 0; + if (bounds.isValid() && !bounds.contains(x, y)) { continue; } @@ -388,9 +385,7 @@ QPixmap Layout::render(bool ignoreCache, Layout *fromLayout, QRect bounds) { ); imageCache.insert(metatileId, metatileImage); } - - QPoint metatileOrigin = QPoint(map_x * 16, map_y * 16); - painter.drawImage(metatileOrigin, metatileImage); + painter.drawImage(x, y, metatileImage); changed_any = true; } painter.end(); @@ -404,13 +399,11 @@ QPixmap Layout::render(bool ignoreCache, Layout *fromLayout, QRect bounds) { QPixmap Layout::renderCollision(bool ignoreCache) { bool changed_any = false; - int width_ = getWidth(); - int height_ = getHeight(); - if (collision_image.isNull() || collision_image.width() != width_ * 16 || collision_image.height() != height_ * 16) { - collision_image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888); + if (collision_image.isNull() || collision_image.width() != pixelWidth() || collision_image.height() != pixelHeight()) { + collision_image = QImage(pixelWidth(), pixelHeight(), QImage::Format_RGBA8888); changed_any = true; } - if (this->blockdata.isEmpty() || !width_ || !height_) { + if (this->blockdata.isEmpty() || this->width == 0 || this->height == 0) { collision_pixmap = collision_pixmap.fromImage(collision_image); return collision_pixmap; } @@ -422,10 +415,9 @@ QPixmap Layout::renderCollision(bool ignoreCache) { changed_any = true; Block block = this->blockdata.at(i); QImage collision_metatile_image = getCollisionMetatileImage(block); - int map_y = width_ ? i / width_ : 0; - int map_x = width_ ? i % width_ : 0; - QPoint metatile_origin = QPoint(map_x * 16, map_y * 16); - painter.drawImage(metatile_origin, collision_metatile_image); + int x = this->width ? ((i % this->width) * Metatile::pixelWidth()) : 0; + int y = this->width ? ((i / this->width) * Metatile::pixelHeight()) : 0; + painter.drawImage(x, y, collision_metatile_image); } painter.end(); cacheCollision(); @@ -437,14 +429,14 @@ QPixmap Layout::renderCollision(bool ignoreCache) { QPixmap Layout::renderBorder(bool ignoreCache) { bool changed_any = false, border_resized = false; - int width_ = getBorderWidth(); - int height_ = getBorderHeight(); + int pixelWidth = this->border_width * Metatile::pixelWidth(); + int pixelHeight = this->border_height * Metatile::pixelHeight(); if (this->border_image.isNull()) { - this->border_image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888); + this->border_image = QImage(pixelWidth, pixelHeight, QImage::Format_RGBA8888); changed_any = true; } - if (this->border_image.width() != width_ * 16 || this->border_image.height() != height_ * 16) { - this->border_image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888); + if (this->border_image.width() != pixelWidth || this->border_image.height() != pixelHeight) { + this->border_image = QImage(pixelWidth, pixelHeight, QImage::Format_RGBA8888); border_resized = true; } if (this->border.isEmpty()) { @@ -461,9 +453,9 @@ QPixmap Layout::renderBorder(bool ignoreCache) { Block block = this->border.at(i); uint16_t metatileId = block.metatileId(); QImage metatile_image = getMetatileImage(metatileId, this); - int map_y = width_ ? i / width_ : 0; - int map_x = width_ ? i % width_ : 0; - painter.drawImage(QPoint(map_x * 16, map_y * 16), metatile_image); + int x = this->border_width ? ((i % this->border_width) * Metatile::pixelWidth()) : 0; + int y = this->border_width ? ((i / this->border_width) * Metatile::pixelHeight()) : 0; + painter.drawImage(x, y, metatile_image); } painter.end(); if (changed_any) { diff --git a/src/core/tileset.cpp b/src/core/tileset.cpp index 75c9c362..ca0650fe 100644 --- a/src/core/tileset.cpp +++ b/src/core/tileset.cpp @@ -501,7 +501,7 @@ bool Tileset::loadTilesImage(QImage *importedImage) { image = QImage(this->tilesImagePath).convertToFormat(QImage::Format_Indexed8, Qt::ThresholdDither); } else { // Use default image - image = QImage(8, 8, QImage::Format_Indexed8); + image = QImage(Tile::pixelWidth(), Tile::pixelHeight(), QImage::Format_Indexed8); } // Validate image contains 16 colors. @@ -517,11 +517,9 @@ bool Tileset::loadTilesImage(QImage *importedImage) { } QList tiles; - int w = 8; - int h = 8; - for (int y = 0; y < image.height(); y += h) - for (int x = 0; x < image.width(); x += w) { - QImage tile = image.copy(x, y, w, h); + for (int y = 0; y < image.height(); y += Tile::pixelHeight()) + for (int x = 0; x < image.width(); x += Tile::pixelWidth()) { + QImage tile = image.copy(x, y, Tile::pixelWidth(), Tile::pixelHeight()); tiles.append(tile); } this->tilesImage = image; diff --git a/src/editor.cpp b/src/editor.cpp index d301d60e..b043c942 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -30,7 +30,7 @@ Editor::Editor(Ui::MainWindow* ui) { this->ui = ui; this->settings = new Settings(); - this->cursorMapTileRect = new CursorTileRect(QSize(16,16), qRgb(255, 255, 255)); + this->cursorMapTileRect = new CursorTileRect(Metatile::pixelSize(), qRgb(255, 255, 255)); this->map_ruler = new MapRuler(4); connect(this->map_ruler, &MapRuler::statusChanged, this, &Editor::mapRulerStatusChanged); @@ -1171,7 +1171,7 @@ bool Editor::isMouseInMap() const { void Editor::setPlayerViewRect(const QRectF &rect) { delete this->playerViewRect; - this->playerViewRect = new MovableRect(rect, qRgb(255, 255, 255)); + this->playerViewRect = new MovableRect(rect, Metatile::pixelSize(), qRgb(255, 255, 255)); updateCursorRectVisibility(); } @@ -1913,8 +1913,8 @@ void Editor::displayMapBorder() { for (int y = -borderMargins.top(); y < this->layout->getHeight() + borderMargins.bottom(); y += this->layout->getBorderHeight()) for (int x = -borderMargins.left(); x < this->layout->getWidth() + borderMargins.right(); x += this->layout->getBorderWidth()) { QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap); - item->setX(x * 16); - item->setY(y * 16); + item->setX(x * Metatile::pixelWidth()); + item->setY(y * Metatile::pixelHeight()); item->setZValue(ZValue::MapBorder); scene->addItem(item); borderItems.append(item); @@ -1962,8 +1962,8 @@ void Editor::displayMapGrid() { // elements of the scripting API, so they're painted manually in MapView::drawForeground. this->mapGrid = new QGraphicsItemGroup(); - const int pixelMapWidth = this->layout->getWidth() * 16; - const int pixelMapHeight = this->layout->getHeight() * 16; + const int pixelMapWidth = this->layout->pixelWidth(); + const int pixelMapHeight = this->layout->pixelHeight(); // The grid can be moved with a user-specified x/y offset. The grid's dash patterns will only wrap in full pattern increments, // so we draw an additional row/column outside the map that can be revealed as the offset changes. @@ -2476,7 +2476,7 @@ void Editor::setCollisionGraphics() { // Use the image sheet to create an icon for each collision/elevation combination. // Any icons for combinations that aren't provided by the image sheet are also created now using default graphics. - const int w = 16, h = 16; + const int w = Metatile::pixelWidth(), h = Metatile::pixelHeight(); imgSheet = imgSheet.scaled(w * imgColumns, h * imgRows); for (int collision = 0; collision <= Block::getMaxCollision(); collision++) { // If (collision >= imgColumns) here, it's a valid collision value, but it is not represented with an icon on the image sheet. diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 8d44895e..36aef9e5 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1408,7 +1408,7 @@ bool MainWindow::setProjectUI() { ui->newEventToolButton->setEventTypeVisible(Event::Type::SecretBase, projectConfig.eventSecretBaseEnabled); ui->newEventToolButton->setEventTypeVisible(Event::Type::CloneObject, projectConfig.eventCloneObjectEnabled); - this->editor->setPlayerViewRect(QRectF(0, 0, 16, 16).marginsAdded(projectConfig.playerViewDistance)); + this->editor->setPlayerViewRect(QRectF(QPoint(0,0), Metatile::pixelSize()).marginsAdded(projectConfig.playerViewDistance)); editor->setCollisionGraphics(); ui->spinBox_SelectedElevation->setMaximum(Block::getMaxElevation()); @@ -1809,7 +1809,7 @@ void MainWindow::scrollMetatileSelectorToSelection() { QPoint pos = editor->metatile_selector_item->getMetatileIdCoordsOnWidget(selection.metatileItems.first().metatileId); QPoint size = editor->metatile_selector_item->getSelectionDimensions(); - pos += QPoint(size.x() - 1, size.y() - 1) * 16 / 2; // We want to focus on the center of the whole selection + pos += QPoint((size.x() - 1) * Metatile::pixelWidth(), (size.y() - 1) * Metatile::pixelHeight()) / 2; // We want to focus on the center of the whole selection pos *= getMetatilesZoomScale(); auto viewport = ui->scrollArea_MetatileSelector->viewport(); diff --git a/src/project.cpp b/src/project.cpp index 9a65ac38..cc3a567f 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -2400,12 +2400,11 @@ bool Project::readFieldmapProperties() { // We can determine whether triple-layer metatiles are in-use by reading this constant. // If the constant is missing (or is using a value other than 8 or 12) the user must tell // us whether they're using triple-layer metatiles under Project Settings. - static const int numTilesPerLayer = 4; int numTilesPerMetatile = it.value(); - if (numTilesPerMetatile == 2 * numTilesPerLayer) { + if (numTilesPerMetatile == 2 * Metatile::tilesPerLayer()) { projectConfig.tripleLayerMetatilesEnabled = false; this->disabledSettingsNames.insert(numTilesPerMetatileName); - } else if (numTilesPerMetatile == 3 * numTilesPerLayer) { + } else if (numTilesPerMetatile == 3 * Metatile::tilesPerLayer()) { projectConfig.tripleLayerMetatilesEnabled = true; this->disabledSettingsNames.insert(numTilesPerMetatileName); } @@ -3422,14 +3421,25 @@ QString Project::getEmptySpeciesName() { return projectConfig.getIdentifier(ProjectIdentifier::define_species_prefix) + projectConfig.getIdentifier(ProjectIdentifier::define_species_empty); } -// Get the distance in metatiles (rounded up) that the player is able to see in each direction in-game. +// Get the distance in pixels that the player is able to see in each direction in-game, +// rounded up to a multiple of a metatile's pixel size. +QMargins Project::getPixelViewDistance() { + QMargins viewDistance = projectConfig.playerViewDistance; + viewDistance.setTop(Util::roundUpToMultiple(viewDistance.top(), Metatile::pixelHeight())); + viewDistance.setBottom(Util::roundUpToMultiple(viewDistance.bottom(), Metatile::pixelHeight())); + viewDistance.setLeft(Util::roundUpToMultiple(viewDistance.left(), Metatile::pixelWidth())); + viewDistance.setRight(Util::roundUpToMultiple(viewDistance.right(), Metatile::pixelWidth())); + return viewDistance; +} + +// Get the distance in metatiles that the player is able to see in each direction in-game. // For the default view distance (i.e. assuming the player is centered in a 240x160 pixel GBA screen) this is 7x5 metatiles. QMargins Project::getMetatileViewDistance() { - QMargins viewDistance = projectConfig.playerViewDistance; - viewDistance.setTop(qCeil(viewDistance.top() / 16.0)); - viewDistance.setBottom(qCeil(viewDistance.bottom() / 16.0)); - viewDistance.setLeft(qCeil(viewDistance.left() / 16.0)); - viewDistance.setRight(qCeil(viewDistance.right() / 16.0)); + QMargins viewDistance = getPixelViewDistance(); + viewDistance.setTop(viewDistance.top() / Metatile::pixelHeight()); + viewDistance.setBottom(viewDistance.bottom() / Metatile::pixelHeight()); + viewDistance.setLeft(viewDistance.left() / Metatile::pixelWidth()); + viewDistance.setRight(viewDistance.right() / Metatile::pixelWidth()); return viewDistance; } diff --git a/src/ui/bordermetatilespixmapitem.cpp b/src/ui/bordermetatilespixmapitem.cpp index 9d6ab07f..4e847b1b 100644 --- a/src/ui/bordermetatilespixmapitem.cpp +++ b/src/ui/bordermetatilespixmapitem.cpp @@ -39,13 +39,13 @@ void BorderMetatilesPixmapItem::draw() { int width = layout->getBorderWidth(); int height = layout->getBorderHeight(); - QImage image(16 * width, 16 * height, QImage::Format_RGBA8888); + QImage image(width * Metatile::pixelWidth(), height * Metatile::pixelHeight(), QImage::Format_RGBA8888); QPainter painter(&image); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { - int x = i * 16; - int y = j * 16; + 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); diff --git a/src/ui/connectionpixmapitem.cpp b/src/ui/connectionpixmapitem.cpp index b4fbfa12..db05ffab 100644 --- a/src/ui/connectionpixmapitem.cpp +++ b/src/ui/connectionpixmapitem.cpp @@ -100,9 +100,9 @@ void ConnectionPixmapItem::updatePos() { void ConnectionPixmapItem::updateOrigin() { if (this->connection->isVertical()) { this->originX = 0; - this->originY = this->connection->relativePos(true).y() * this->mHeight; + this->originY = this->connection->relativePixelPos(true).y(); } else if (this->connection->isHorizontal()) { - this->originX = this->connection->relativePos(true).x() * this->mWidth; + this->originX = this->connection->relativePixelPos(true).x(); this->originY = 0; } updatePos(); diff --git a/src/ui/currentselectedmetatilespixmapitem.cpp b/src/ui/currentselectedmetatilespixmapitem.cpp index dcc3cb24..33425131 100644 --- a/src/ui/currentselectedmetatilespixmapitem.cpp +++ b/src/ui/currentselectedmetatilespixmapitem.cpp @@ -3,16 +3,16 @@ #include QPixmap drawMetatileSelection(MetatileSelection selection, Layout *layout) { - int width = selection.dimensions.x() * 16; - int height = selection.dimensions.y() * 16; + int width = selection.dimensions.x() * Metatile::pixelWidth(); + int height = selection.dimensions.y() * Metatile::pixelHeight(); QImage image(width, height, QImage::Format_RGBA8888); image.fill(QColor(0, 0, 0, 0)); QPainter painter(&image); for (int i = 0; i < selection.dimensions.x(); i++) { for (int j = 0; j < selection.dimensions.y(); j++) { - int x = i * 16; - int y = j * 16; + int x = i * Metatile::pixelWidth(); + int y = j * Metatile::pixelHeight(); QPoint metatile_origin = QPoint(x, y); int index = j * selection.dimensions.x() + i; MetatileSelectionItem item = selection.metatileItems.at(index); diff --git a/src/ui/cursortilerect.cpp b/src/ui/cursortilerect.cpp index ef1de285..e62bcdc8 100644 --- a/src/ui/cursortilerect.cpp +++ b/src/ui/cursortilerect.cpp @@ -65,6 +65,6 @@ void CursorTileRect::updateLocation(int coordX, int coordY) { } } - this->setX(coordX * 16); - this->setY(coordY * 16); + this->setX(coordX * m_tileSize.width()); + this->setY(coordY * m_tileSize.height()); } diff --git a/src/ui/graphicsview.cpp b/src/ui/graphicsview.cpp index c8fc4495..667e0aab 100644 --- a/src/ui/graphicsview.cpp +++ b/src/ui/graphicsview.cpp @@ -33,7 +33,7 @@ void MapView::drawForeground(QPainter *painter, const QRectF&) { painter->save(); if (editor->layout) { // We're clipping here to hide parts of the grid that are outside the map. - const QRectF mapRect(-0.5, -0.5, editor->layout->getWidth() * 16 + 1.5, editor->layout->getHeight() * 16 + 1.5); + const QRectF mapRect(-0.5, -0.5, editor->layout->pixelWidth() + 1.5, editor->layout->pixelHeight() + 1.5); painter->setClipping(true); painter->setClipRect(mapRect); } diff --git a/src/ui/mapimageexporter.cpp b/src/ui/mapimageexporter.cpp index 59efbe4b..450ad9d0 100644 --- a/src/ui/mapimageexporter.cpp +++ b/src/ui/mapimageexporter.cpp @@ -333,8 +333,8 @@ QGifImage* MapImageExporter::createTimelapseGifImage(QProgressDialog *progress) if (currentHistoryAppliesToFrame(step.historyStack) || step.historyStack->index() == step.initialStackIndex) { // Either this is relevant edit history, or it's the final frame (which is always rendered). Record the size of the map at this point. QMargins margins = getMargins(m_map); - canvasSize = canvasSize.expandedTo(QSize(m_layout->getWidth() * 16 + margins.left() + margins.right(), - m_layout->getHeight() * 16 + margins.top() + margins.bottom())); + canvasSize = canvasSize.expandedTo(QSize(m_layout->pixelWidth() + margins.left() + margins.right(), + m_layout->pixelHeight() + margins.top() + margins.bottom())); } if (step.historyStack->canUndo()){ step.historyStack->undo(); @@ -434,8 +434,8 @@ QPixmap MapImageExporter::getStitchedImage(QProgressDialog *progress) { if (!connection->isCardinal()) continue; Map *connectedMap = connection->targetMap(); if (!connectedMap) continue; - QPoint pos = connection->relativePos(); - unvisited.append(StitchedMap{cur.x + (pos.x() * 16), cur.y + (pos.y() * 16), connectedMap}); + QPoint pos = connection->relativePixelPos(); + unvisited.append(StitchedMap{cur.x + pos.x(), cur.y + pos.y(), connectedMap}); } } if (stitchedMaps.isEmpty()) @@ -447,7 +447,7 @@ QPixmap MapImageExporter::getStitchedImage(QProgressDialog *progress) { // Determine the overall dimensions of the stitched maps. QRect dimensions = QRect(0, 0, m_map->getWidth(), m_map->getHeight()) + getMargins(m_map); for (const StitchedMap &map : stitchedMaps) { - dimensions |= (QRect(map.x, map.y, map.map->getWidth() * 16, map.map->getHeight() * 16) + getMargins(map.map)); + dimensions |= (QRect(map.x, map.y, map.map->pixelWidth(), map.map->pixelHeight()) + getMargins(map.map)); } QPixmap stitchedPixmap(dimensions.width(), dimensions.height()); @@ -602,7 +602,7 @@ QPixmap MapImageExporter::getFormattedMapPixmap() { QMargins MapImageExporter::getMargins(const Map *map) { QMargins margins; if (m_settings.showBorder) { - margins = m_project->getMetatileViewDistance() * 16; + margins = m_project->getPixelViewDistance(); } else if (map && connectionsEnabled()) { for (const auto &connection : map->getConnections()) { const QString dir = connection->direction(); @@ -612,10 +612,10 @@ QMargins MapImageExporter::getMargins(const Map *map) { if (!targetMap) continue; QRect rect = targetMap->getConnectionRect(dir); - if (dir == "up") margins.setTop(rect.height() * 16); - else if (dir == "down") margins.setBottom(rect.height() * 16); - else if (dir == "left") margins.setLeft(rect.width() * 16); - else if (dir == "right") margins.setRight(rect.width() * 16); + if (dir == "up") margins.setTop(rect.height()); + else if (dir == "down") margins.setBottom(rect.height()); + else if (dir == "left") margins.setLeft(rect.width()); + else if (dir == "right") margins.setRight(rect.width()); } } if (m_settings.showGrid) { @@ -652,7 +652,7 @@ void MapImageExporter::paintBorder(QPainter *painter, Layout *layout) { // Skip border painting if it would be fully covered by the rest of the map if (layout->isWithinBounds(QRect(x, y, layout->getBorderWidth(), layout->getBorderHeight()))) continue; - painter->drawPixmap(x * 16, y * 16, layout->border_pixmap); + painter->drawPixmap(x * Metatile::pixelWidth(), y * Metatile::pixelHeight(), layout->border_pixmap); } painter->restore(); @@ -665,7 +665,7 @@ void MapImageExporter::paintConnections(QPainter *painter, const Map *map) { for (const auto &connection : map->getConnections()) { if (!m_settings.showConnections.contains(connection->direction())) continue; - painter->drawImage(connection->relativePos(true) * 16, connection->render().toImage()); + painter->drawImage(connection->relativePixelPos(true), connection->render().toImage()); } } @@ -693,12 +693,12 @@ void MapImageExporter::paintGrid(QPainter *painter, const Layout *layout) { if (!m_settings.showGrid) return; - int w = layout->getWidth() * 16; - int h = layout->getHeight() * 16; - for (int x = 0; x <= w; x += 16) { + int w = layout->pixelWidth(); + int h = layout->pixelHeight(); + for (int x = 0; x <= w; x += Metatile::pixelWidth()) { painter->drawLine(x, 0, x, h); } - for (int y = 0; y <= h; y += 16) { + for (int y = 0; y <= h; y += Metatile::pixelHeight()) { painter->drawLine(0, y, w, y); } } diff --git a/src/ui/mapruler.cpp b/src/ui/mapruler.cpp index 908e0a46..da83821c 100644 --- a/src/ui/mapruler.cpp +++ b/src/ui/mapruler.cpp @@ -37,9 +37,11 @@ QPainterPath MapRuler::shape() const { ruler.addRect(xRuler); ruler.addRect(yRuler); ruler = ruler.simplified(); - for (int x = 16; x < pixWidth(); x += 16) + int w = Metatile::pixelWidth(); + int h = Metatile::pixelHeight(); + for (int x = w; x < pixWidth(); x += w) ruler.addRect(x, xRuler.y(), 0, thickness); - for (int y = 16; y < pixHeight(); y += 16) + for (int y = h; y < pixHeight(); y += h) ruler.addRect(yRuler.x(), y, thickness, 0); if (deltaX() && deltaY()) ruler.addPolygon(QVector({ cornerTick.p1(), cornerTick.p2() })); @@ -131,7 +133,9 @@ QPoint MapRuler::snapToWithinBounds(QPoint pos) const { void MapRuler::updateGeometry() { prepareGeometryChange(); - setPos(QPoint(left() * 16 + 8, top() * 16 + 8)); + int w = Metatile::pixelWidth(); + int h = Metatile::pixelHeight(); + setPos(QPoint(left() * w + w/2, top() * h + h/2)); /* Determine what quadrant the end point is in relative to the anchor point. The anchor * point is the top-left corner of the metatile the ruler starts in, so a zero-length * ruler is considered to be in the bottom-right quadrant from the anchor point. */ diff --git a/src/ui/metatilelayersitem.cpp b/src/ui/metatilelayersitem.cpp index b0279e4e..5ce6e68c 100644 --- a/src/ui/metatilelayersitem.cpp +++ b/src/ui/metatilelayersitem.cpp @@ -4,7 +4,7 @@ #include MetatileLayersItem::MetatileLayersItem(Metatile *metatile, Tileset *primaryTileset, Tileset *secondaryTileset) - : SelectablePixmapItem(16, 16, 2 * projectConfig.getNumLayersInMetatile(), 2), + : SelectablePixmapItem(16, 16, Metatile::tileWidth() * projectConfig.getNumLayersInMetatile(), Metatile::tileHeight()), metatile(metatile), primaryTileset(primaryTileset), secondaryTileset(secondaryTileset) @@ -31,8 +31,8 @@ static const QList tilePositions = { void MetatileLayersItem::draw() { const int numLayers = projectConfig.getNumLayersInMetatile(); - const int layerWidth = this->cellWidth * 2; - const int layerHeight = this->cellHeight * 2; + const int layerWidth = this->cellWidth * Metatile::tileWidth(); + const int layerHeight = this->cellHeight * Metatile::tileHeight(); QPixmap pixmap(numLayers * layerWidth, layerHeight); QPainter painter(&pixmap); diff --git a/src/ui/movablerect.cpp b/src/ui/movablerect.cpp index 70e08e46..1e751aa9 100644 --- a/src/ui/movablerect.cpp +++ b/src/ui/movablerect.cpp @@ -5,16 +5,17 @@ #include "movablerect.h" #include "utility.h" -MovableRect::MovableRect(const QRectF &rect, const QRgb &color) +MovableRect::MovableRect(const QRectF &rect, const QSize &cellSize, const QRgb &color) : QGraphicsRectItem(rect), baseRect(rect), + cellSize(cellSize), color(color) { } /// Center rect on grid position (x, y) void MovableRect::updateLocation(int x, int y) { - setRect(this->baseRect.x() + (x * 16), - this->baseRect.y() + (y * 16), + setRect(this->baseRect.x() + (x * this->cellSize.width()), + this->baseRect.y() + (y * this->cellSize.height()), this->baseRect.width(), this->baseRect.height()); } @@ -24,9 +25,9 @@ void MovableRect::updateLocation(int x, int y) { ************************************************************************ ******************************************************************************/ -ResizableRect::ResizableRect(QObject *parent, int width, int height, QRgb color) +ResizableRect::ResizableRect(QObject *parent, const QSize &cellSize, const QSize &size, const QRgb &color) : QObject(parent), - MovableRect(QRect(0, 0, width * 16, height * 16), color) + MovableRect(QRect(0, 0, size.width(), size.height()), cellSize, color) { setAcceptHoverEvents(true); setFlags(this->flags() | QGraphicsItem::ItemIsMovable); @@ -114,8 +115,8 @@ void ResizableRect::mousePressEvent(QGraphicsSceneMouseEvent *event) { } void ResizableRect::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - int dx = Util::roundUpToMultiple(event->scenePos().x() - this->clickedPos.x(), 16); - int dy = Util::roundUpToMultiple(event->scenePos().y() - this->clickedPos.y(), 16); + int dx = Util::roundUpToMultiple(event->scenePos().x() - this->clickedPos.x(), this->cellSize.width()); + int dy = Util::roundUpToMultiple(event->scenePos().y() - this->clickedPos.y(), this->cellSize.height()); QRect resizedRect = this->clickedRect; @@ -149,20 +150,20 @@ void ResizableRect::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { break; } - // Lower limits: smallest possible size is 16x16 square - if (resizedRect.width() < 16) { + // Lower limits: smallest possible size is 1 cell + if (resizedRect.width() < this->cellSize.width()) { if (dx < 0) { // right sided adjustment made - resizedRect.setWidth(16); + resizedRect.setWidth(this->cellSize.width()); } else { // left sided adjustment slightly more complicated - int dxMax = this->clickedRect.right() - this->clickedRect.left() - 16; + int dxMax = this->clickedRect.right() - this->clickedRect.left() - this->cellSize.width(); resizedRect.adjust(dxMax - dx, 0, 0, 0); } } - if (resizedRect.height() < 16) { + if (resizedRect.height() < this->cellSize.height()) { if (dy < 0) { // bottom - resizedRect.setHeight(16); + resizedRect.setHeight(this->cellSize.height()); } else { // top - int dyMax = this->clickedRect.bottom() - this->clickedRect.top() - 16; + int dyMax = this->clickedRect.bottom() - this->clickedRect.top() - this->cellSize.height(); resizedRect.adjust(0, dyMax - dy, 0, 0); } } diff --git a/src/ui/prefabcreationdialog.cpp b/src/ui/prefabcreationdialog.cpp index ef6e6a0f..76c71f39 100644 --- a/src/ui/prefabcreationdialog.cpp +++ b/src/ui/prefabcreationdialog.cpp @@ -23,12 +23,12 @@ PrefabCreationDialog::PrefabCreationDialog(QWidget *parent, MetatileSelector *me QObject::connect(this->ui->graphicsView_Prefab, &ClickableGraphicsView::clicked, [=](QMouseEvent *event){ auto pos = event->pos(); - int selectionWidth = this->selection.dimensions.x() * 16; - int selectionHeight = this->selection.dimensions.y() * 16; + int selectionWidth = this->selection.dimensions.x() * Metatile::pixelWidth(); + int selectionHeight = this->selection.dimensions.y() * Metatile::pixelHeight(); if (pos.x() < 0 || pos.x() >= selectionWidth || pos.y() < 0 || pos.y() >= selectionHeight) return; - int metatileX = pos.x() / 16; - int metatileY = pos.y() / 16; + int metatileX = pos.x() / Metatile::pixelWidth(); + int metatileY = pos.y() / Metatile::pixelHeight(); int index = metatileY * this->selection.dimensions.x() + metatileX; bool toggledState = !this->selection.metatileItems[index].enabled; this->selection.metatileItems[index].enabled = toggledState; diff --git a/src/ui/resizelayoutpopup.cpp b/src/ui/resizelayoutpopup.cpp index e6b814b1..738d4861 100644 --- a/src/ui/resizelayoutpopup.cpp +++ b/src/ui/resizelayoutpopup.cpp @@ -41,8 +41,9 @@ void CheckeredBgScene::drawBackground(QPainter *painter, const QRectF &rect) { ************************************************************************ ******************************************************************************/ -BoundedPixmapItem::BoundedPixmapItem(const QPixmap &pixmap, QGraphicsItem *parent) : QGraphicsPixmapItem(pixmap, parent) { +BoundedPixmapItem::BoundedPixmapItem(const QPixmap &pixmap, const QSize &cellSize, QGraphicsItem *parent) : QGraphicsPixmapItem(pixmap, parent) { setFlags(this->flags() | QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemSendsGeometryChanges | QGraphicsItem::ItemIsSelectable); + this->cellSize = cellSize; } void BoundedPixmapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { @@ -61,7 +62,8 @@ void BoundedPixmapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem QVariant BoundedPixmapItem::itemChange(GraphicsItemChange change, const QVariant &value) { if (change == ItemPositionChange && scene()) { QPointF newPos = value.toPointF(); - return QPointF(Util::roundUpToMultiple(newPos.x(), 16), Util::roundUpToMultiple(newPos.y(), 16)); + return QPointF(Util::roundUpToMultiple(newPos.x(), this->cellSize.width()), + Util::roundUpToMultiple(newPos.y(), this->cellSize.height())); } else return QGraphicsItem::itemChange(change, value); @@ -124,11 +126,13 @@ void ResizeLayoutPopup::setupLayoutView() { this->ui->spinBox_borderHeight->setValue(this->layout->getBorderHeight()); // Layout stuff - this->layoutPixmap = new BoundedPixmapItem(this->layout->pixmap); + this->layoutPixmap = new BoundedPixmapItem(this->layout->pixmap, Metatile::pixelSize()); this->scene->addItem(layoutPixmap); int maxWidth = this->project->getMaxMapWidth(); int maxHeight = this->project->getMaxMapHeight(); - QGraphicsRectItem *cover = new QGraphicsRectItem(-maxWidth * 8, -maxHeight * 8, maxWidth * 16, maxHeight * 16); + int maxPixelWidth = maxWidth * Metatile::pixelWidth() * 2; // *2 to allow reaching max dimension by expanding from 0,0 in either direction + int maxPixelHeight = maxHeight * Metatile::pixelHeight() * 2; + QGraphicsRectItem *cover = new QGraphicsRectItem(-(maxPixelWidth / 2), -(maxPixelHeight / 2), maxPixelWidth, maxPixelHeight); this->scene->addItem(cover); this->ui->spinBox_width->setMinimum(1); @@ -136,12 +140,14 @@ void ResizeLayoutPopup::setupLayoutView() { this->ui->spinBox_height->setMinimum(1); this->ui->spinBox_height->setMaximum(maxHeight); - this->outline = new ResizableRect(this, this->layout->getWidth(), this->layout->getHeight(), qRgb(255, 0, 255)); + this->outline = new ResizableRect(this, Metatile::pixelSize(), this->layout->pixelSize(), qRgb(255, 0, 255)); this->outline->setZValue(Editor::ZValue::ResizeLayoutPopup); // Ensure on top of view this->outline->setLimit(cover->rect().toAlignedRect()); connect(outline, &ResizableRect::rectUpdated, [=](QRect rect){ // Note: this extra limit check needs access to the project values, so it is done here and not ResizableRect::mouseMoveEvent - int size = this->project->getMapDataSize(rect.width() / 16, rect.height() / 16); + int metatilesWide = rect.width() / Metatile::pixelWidth(); + int metatilesTall = rect.height() / Metatile::pixelHeight(); + int size = this->project->getMapDataSize(metatilesWide, metatilesTall); int maxSize = this->project->getMaxMapDataSize(); if (size > maxSize) { QSize addition = this->project->getMapSizeAddition(); @@ -151,8 +157,8 @@ void ResizeLayoutPopup::setupLayoutView() { .arg(addition.width()) .arg(addition.height()) .arg(maxSize) - .arg(rect.width() / 16) - .arg(rect.height() / 16) + .arg(metatilesWide) + .arg(metatilesTall) .arg(size), this); // adjust rect to last accepted size @@ -160,8 +166,11 @@ void ResizeLayoutPopup::setupLayoutView() { } this->scene->setValidRect(rect); this->outline->setRect(rect); - this->ui->spinBox_width->setValue(rect.width() / 16); - this->ui->spinBox_height->setValue(rect.height() / 16); + + const QSignalBlocker b_Width(this->ui->spinBox_width); + const QSignalBlocker b_Height(this->ui->spinBox_height); + this->ui->spinBox_width->setValue(metatilesWide); + this->ui->spinBox_height->setValue(metatilesTall); }); scene->addItem(outline); @@ -171,7 +180,7 @@ void ResizeLayoutPopup::setupLayoutView() { this->scale = 1.0; QRectF rect = this->outline->rect(); - const int marginSize = 10 * 16; // Leave a margin of 10 metatiles around the map + const int marginSize = 10 * Metatile::pixelWidth(); // Leave a margin of 10 metatiles around the map rect += QMargins(marginSize, marginSize, marginSize, marginSize); this->ui->graphicsView->fitInView(rect, Qt::KeepAspectRatio); } @@ -179,25 +188,23 @@ void ResizeLayoutPopup::setupLayoutView() { void ResizeLayoutPopup::on_spinBox_width_valueChanged(int value) { if (!this->outline) return; QRectF rect = this->outline->rect(); - this->outline->updatePosFromRect(QRect(rect.x(), rect.y(), value * 16, rect.height())); + this->outline->updatePosFromRect(QRect(rect.x(), rect.y(), value * Metatile::pixelWidth(), rect.height())); } void ResizeLayoutPopup::on_spinBox_height_valueChanged(int value) { if (!this->outline) return; QRectF rect = this->outline->rect(); - this->outline->updatePosFromRect(QRect(rect.x(), rect.y(), rect.width(), value * 16)); + this->outline->updatePosFromRect(QRect(rect.x(), rect.y(), rect.width(), value * Metatile::pixelHeight())); } /// Result is the number of metatiles to add (or subtract) to each side of the map after dimension changes QMargins ResizeLayoutPopup::getResult() { QMargins result = QMargins(); - - result.setLeft(this->layoutPixmap->x() - this->outline->rect().left()); - result.setTop(this->layoutPixmap->y() - this->outline->rect().top()); - result.setRight(this->outline->rect().right() - (this->layoutPixmap->x() + this->layoutPixmap->pixmap().width())); - result.setBottom(this->outline->rect().bottom() - (this->layoutPixmap->y() + this->layoutPixmap->pixmap().height())); - - return result / 16; + result.setLeft((this->layoutPixmap->x() - this->outline->rect().left()) / Metatile::pixelWidth()); + result.setTop((this->layoutPixmap->y() - this->outline->rect().top()) / Metatile::pixelHeight()); + result.setRight((this->outline->rect().right() - (this->layoutPixmap->x() + this->layoutPixmap->pixmap().width())) / Metatile::pixelWidth()); + result.setBottom((this->outline->rect().bottom() - (this->layoutPixmap->y() + this->layoutPixmap->pixmap().height())) / Metatile::pixelHeight()); + return result; } QSize ResizeLayoutPopup::getBorderResult() { diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index 55545616..b25130bd 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -388,19 +388,21 @@ void TilesetEditor::drawSelectedTiles() { return; } + const int imgTileWidth = 16; + const int imgTileHeight = 16; this->selectedTileScene->clear(); QList tiles = this->tileSelector->getSelectedTiles(); QPoint dimensions = this->tileSelector->getSelectionDimensions(); - QImage selectionImage(16 * dimensions.x(), 16 * dimensions.y(), QImage::Format_RGBA8888); + QImage selectionImage(imgTileWidth * dimensions.x(), imgTileHeight * 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++) { auto tile = tiles.at(tileIndex); - QImage tileImage = getPalettedTileImage(tile.tileId, this->primaryTileset, this->secondaryTileset, tile.palette, true).scaled(16, 16); + QImage tileImage = getPalettedTileImage(tile.tileId, this->primaryTileset, this->secondaryTileset, tile.palette, true).scaled(imgTileWidth, imgTileHeight); tile.flip(&tileImage); tileIndex++; - painter.drawImage(i * 16, j * 16, tileImage); + painter.drawImage(i * imgTileWidth, j * imgTileHeight, tileImage); } } @@ -730,18 +732,20 @@ void TilesetEditor::importTilesetTiles(Tileset *tileset) { } else { logError(QString("Failed to open image file: '%1'").arg(filepath)); } - if (image.width() == 0 || image.height() == 0 || image.width() % 8 != 0 || image.height() % 8 != 0) { + if (image.width() == 0 || image.height() == 0 || image.width() % Tile::pixelWidth() != 0 || image.height() % Tile::pixelHeight() != 0) { ErrorMessage::show(QStringLiteral("Failed to import tiles."), - QString("The image dimensions (%1 x %2) are invalid. Width and height must be multiples of 8 pixels.") + QString("The image dimensions (%1x%2) are invalid. The dimensions must be a multiple of %3x%4 pixels.") .arg(image.width()) - .arg(image.height()), + .arg(image.height()) + .arg(Tile::pixelWidth()) + .arg(Tile::pixelHeight()), this); return; } // Validate total number of tiles in image. - int numTilesWide = image.width() / 8; - int numTilesHigh = image.height() / 8; + int numTilesWide = image.width() / Tile::pixelWidth(); + int numTilesHigh = image.height() / Tile::pixelHeight(); int totalTiles = numTilesHigh * numTilesWide; int maxAllowedTiles = primary ? Project::getNumTilesPrimary() : Project::getNumTilesTotal() - Project::getNumTilesPrimary(); if (totalTiles > maxAllowedTiles) { diff --git a/src/ui/tileseteditortileselector.cpp b/src/ui/tileseteditortileselector.cpp index 034a86a7..56c65073 100644 --- a/src/ui/tileseteditortileselector.cpp +++ b/src/ui/tileseteditortileselector.cpp @@ -244,19 +244,16 @@ QImage TilesetEditorTileSelector::buildSecondaryTilesIndexedImage() { } QImage TilesetEditorTileSelector::buildImage(int tileIdStart, int numTiles) { - const int tileWidth = 8; - const int tileHeight = 8; int height = qCeil(numTiles / static_cast(this->numTilesWide)); - QImage image(this->numTilesWide * tileWidth, height * tileHeight, QImage::Format_RGBA8888); + QImage image(this->numTilesWide * Tile::pixelWidth(), height * Tile::pixelHeight(), QImage::Format_RGBA8888); image.fill(0); QPainter painter(&image); for (int i = 0; i < numTiles; i++) { QImage tileImage = getGreyscaleTileImage(tileIdStart + i, this->primaryTileset, this->secondaryTileset); - int y = i / this->numTilesWide; - int x = i % this->numTilesWide; - QPoint origin = QPoint(x * tileWidth, y * tileHeight); - painter.drawImage(origin, tileImage); + int x = (i % this->numTilesWide) * Tile::pixelWidth(); + int y = (i / this->numTilesWide) * Tile::pixelHeight(); + painter.drawImage(x, y, tileImage); } painter.end();