diff --git a/include/core/map.h b/include/core/map.h index aaf5b8b7..8c4bead4 100644 --- a/include/core/map.h +++ b/include/core/map.h @@ -22,10 +22,6 @@ #define MAX_BORDER_WIDTH 255 #define MAX_BORDER_HEIGHT 255 -// Number of metatiles to draw out from edge of map. Could allow modification of this in the future. -// porymap will reflect changes to it, but the value is hard-coded in the projects at the moment -#define BORDER_DISTANCE 7 - class LayoutPixmapItem; class CollisionPixmapItem; class BorderMetatilesPixmapItem; diff --git a/include/core/maplayout.h b/include/core/maplayout.h index 40a3a035..8d1d64bc 100644 --- a/include/core/maplayout.h +++ b/include/core/maplayout.h @@ -98,6 +98,7 @@ public: int getBorderHeight() const { return border_height; } int getBorderDrawWidth() const; int getBorderDrawHeight() const; + QRect getVisibleRect() const; bool isWithinBounds(int x, int y) const; bool isWithinBounds(const QRect &rect) const; diff --git a/include/project.h b/include/project.h index 93e6b162..b9a94776 100644 --- a/include/project.h +++ b/include/project.h @@ -256,6 +256,8 @@ public: static QString getDynamicMapDefineName(); static QString getDynamicMapName(); static QString getEmptySpeciesName(); + static QSize getViewDistance(); + static QSize getMetatileViewDistance(); static int getNumTilesPrimary() { return num_tiles_primary; } static int getNumTilesTotal() { return num_tiles_total; } static int getNumMetatilesPrimary() { return num_metatiles_primary; } diff --git a/include/ui/movablerect.h b/include/ui/movablerect.h index 87f7a36e..a9f15917 100644 --- a/include/ui/movablerect.h +++ b/include/ui/movablerect.h @@ -22,10 +22,10 @@ public: void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override { if (!(*enabled)) return; painter->setPen(this->color); - painter->drawRect(this->rect().x() - 2, this->rect().y() - 2, this->rect().width() + 3, this->rect().height() + 3); - painter->setPen(QColor(0, 0, 0)); - painter->drawRect(this->rect().x() - 3, this->rect().y() - 3, this->rect().width() + 5, this->rect().height() + 5); - painter->drawRect(this->rect().x() - 1, this->rect().y() - 1, this->rect().width() + 1, this->rect().height() + 1); + painter->drawRect(this->rect() + QMargins(1,1,1,1)); // Fill + painter->setPen(Qt::black); + painter->drawRect(this->rect() + QMargins(2,2,2,2)); // Outer border + painter->drawRect(this->rect()); // Inner border } void updateLocation(int x, int y); bool *enabled; diff --git a/src/core/map.cpp b/src/core/map.cpp index b9fe4c90..793090c0 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -83,16 +83,17 @@ QRect Map::getConnectionRect(const QString &direction, Layout * fromLayout) cons int x = 0, y = 0; int w = getWidth(), h = getHeight(); + QSize viewDistance = Project::getMetatileViewDistance(); if (direction == "up") { - h = qMin(h, BORDER_DISTANCE); + h = qMin(h, viewDistance.height()); y = getHeight() - h; } else if (direction == "down") { - h = qMin(h, BORDER_DISTANCE); + h = qMin(h, viewDistance.height()); } else if (direction == "left") { - w = qMin(w, BORDER_DISTANCE); + w = qMin(w, viewDistance.width()); x = getWidth() - w; } else if (direction == "right") { - w = qMin(w, BORDER_DISTANCE); + w = qMin(w, viewDistance.width()); } else if (MapConnection::isDiving(direction)) { if (fromLayout) { w = qMin(w, fromLayout->getWidth()); diff --git a/src/core/maplayout.cpp b/src/core/maplayout.cpp index 45b35f91..e70d8040 100644 --- a/src/core/maplayout.cpp +++ b/src/core/maplayout.cpp @@ -64,16 +64,18 @@ bool Layout::isWithinBorderBounds(int x, int y) const { } int Layout::getBorderDrawWidth() const { - return getBorderDrawDistance(border_width, BORDER_DISTANCE); + return getBorderDrawDistance(border_width, Project::getMetatileViewDistance().width()); } int Layout::getBorderDrawHeight() const { - return getBorderDrawDistance(border_height, BORDER_DISTANCE); + return getBorderDrawDistance(border_height, Project::getMetatileViewDistance().height()); } -// We need to draw sufficient border blocks to fill the area that gets loaded around the player in-game (BORDER_DISTANCE). -// Note that this is not the same as the player's view distance. -// The result will be some multiple of the input dimension, because we only draw the border in increments of its full width/height. +// Calculate the distance away from the layout's edge that we need to start drawing border blocks. +// We need to fulfill two requirements here: +// - We should draw enough to fill the player's in-game view +// - The value should be some multiple of the border's dimension +// (otherwise the border won't be positioned the same as it would in-game). int Layout::getBorderDrawDistance(int dimension, qreal minimum) { if (dimension >= minimum) return dimension; @@ -82,6 +84,14 @@ int Layout::getBorderDrawDistance(int dimension, qreal minimum) { return dimension * qCeil(minimum / qMax(dimension, 1)); } +// Get a rectangle that represents (in pixels) the layout's map area and the visible area of its border. +QRect Layout::getVisibleRect() const { + QRect area = QRect(0, 0, this->width * 16, this->height * 16); + QSize viewDistance = Project::getMetatileViewDistance() * 16; + area += QMargins(viewDistance.width(), viewDistance.height(), viewDistance.width(), viewDistance.height()); + return area; +} + bool Layout::getBlock(int x, int y, Block *out) { if (isWithinBounds(x, y)) { int i = y * getWidth() + x; diff --git a/src/editor.cpp b/src/editor.cpp index db4d4694..54fc9640 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1572,14 +1572,8 @@ void Editor::displayMapMetatiles() { map_item->draw(true); scene->addItem(map_item); - int tw = 16; - int th = 16; - scene->setSceneRect( - -BORDER_DISTANCE * tw, - -BORDER_DISTANCE * th, - map_item->pixmap().width() + BORDER_DISTANCE * 2 * tw, - map_item->pixmap().height() + BORDER_DISTANCE * 2 * th - ); + // Scene rect is the map plus a margin that gives enough space to scroll and see the edge of the player view rectangle. + scene->setSceneRect(this->layout->getVisibleRect() + QMargins(3,3,3,3)); } void Editor::clearMapMovementPermissions() { @@ -1772,18 +1766,13 @@ void Editor::clearConnectionMask() { } } -// Hides connected map tiles that cannot be seen from the current map (beyond BORDER_DISTANCE). +// Hides connected map tiles that cannot be seen from the current map void Editor::maskNonVisibleConnectionTiles() { clearConnectionMask(); QPainterPath mask; mask.addRect(scene->itemsBoundingRect().toRect()); - mask.addRect( - -BORDER_DISTANCE * 16, - -BORDER_DISTANCE * 16, - (layout->getWidth() + BORDER_DISTANCE * 2) * 16, - (layout->getHeight() + BORDER_DISTANCE * 2) * 16 - ); + mask.addRect(layout->getVisibleRect()); // Mask the tiles with the current theme's background color. QPen pen(ui->graphicsView_Map->palette().color(QPalette::Active, QPalette::Base)); @@ -1805,13 +1794,11 @@ void Editor::clearMapBorder() { void Editor::displayMapBorder() { clearMapBorder(); - int borderWidth = this->layout->getBorderWidth(); - int borderHeight = this->layout->getBorderHeight(); int borderHorzDist = this->layout->getBorderDrawWidth(); int borderVertDist = this->layout->getBorderDrawHeight(); QPixmap pixmap = this->layout->renderBorder(); - for (int y = -borderVertDist; y < this->layout->getHeight() + borderVertDist; y += borderHeight) - for (int x = -borderHorzDist; x < this->layout->getWidth() + borderHorzDist; x += borderWidth) { + for (int y = -borderVertDist; y < this->layout->getHeight() + borderVertDist; y += this->layout->getBorderHeight()) + for (int x = -borderHorzDist; x < this->layout->getWidth() + borderHorzDist; x += this->layout->getBorderWidth()) { QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap); item->setX(x * 16); item->setY(y * 16); diff --git a/src/project.cpp b/src/project.cpp index 158d4f02..d91d63da 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -3235,6 +3235,21 @@ QString Project::getEmptySpeciesName() { return projectConfig.getIdentifier(ProjectIdentifier::define_species_prefix) + projectConfig.getIdentifier(ProjectIdentifier::define_species_empty); } +// Get the distance in pixels that the player is able to see from the space they're standing on. +// For the default size of the view area (i.e. the full 240x160 GBA screen) this is 112x72. +QSize Project::getViewDistance() { + return ((projectConfig.playerViewSize) - QSize(16,16)) / 2; +} + +// Get the distance in metatiles that the player is able to see from the space they're standing on, rounded up. +// For the default size of the view area (i.e. the full 240x160 GBA screen) this is 7x5 metatiles. +QSize Project::getMetatileViewDistance() { + QSize viewDistance = getViewDistance(); + viewDistance.setWidth(qCeil(viewDistance.width() / 16.0)); + viewDistance.setHeight(qCeil(viewDistance.height() / 16.0)); + return viewDistance; +} + // If the provided filepath is an absolute path to an existing file, return filepath. // If not, and the provided filepath is a relative path from the project dir to an existing file, return the relative path. // Otherwise return empty string. diff --git a/src/ui/mapimageexporter.cpp b/src/ui/mapimageexporter.cpp index 58b63cbd..9a65af8f 100644 --- a/src/ui/mapimageexporter.cpp +++ b/src/ui/mapimageexporter.cpp @@ -606,9 +606,11 @@ QPixmap MapImageExporter::getFormattedMapPixmap() { QMargins MapImageExporter::getMargins(const Map *map) { QMargins margins; if (m_settings.showBorder) { - // The border may technically extend beyond BORDER_DISTANCE, but when the border is painted - // we will be limiting it to the visible sight range. - margins = QMargins(BORDER_DISTANCE, BORDER_DISTANCE, BORDER_DISTANCE, BORDER_DISTANCE) * 16; + // When we render map borders we render them in full increments of the border dimensions. + // This means for large border dimensions the painted area of the border may extend well beyond the area the player can see. + // When we call paintBorder we will clip the painting to this visible area, so we only need to consider the visible area here. + QSize viewDistance = m_project->getMetatileViewDistance() * 16; + margins = QMargins(viewDistance.width(), viewDistance.height(), viewDistance.width(), viewDistance.height()); } else if (map && connectionsEnabled()) { for (const auto &connection : map->getConnections()) { const QString dir = connection->direction(); @@ -649,10 +651,8 @@ void MapImageExporter::paintBorder(QPainter *painter, Layout *layout) { layout->renderBorder(true); // Clip parts of the border that would be beyond player visibility. - QRect visibleArea(0, 0, layout->getWidth() * 16, layout->getHeight() * 16); - visibleArea += (QMargins(BORDER_DISTANCE, BORDER_DISTANCE, BORDER_DISTANCE, BORDER_DISTANCE) * 16); painter->save(); - painter->setClipRect(visibleArea); + painter->setClipRect(layout->getVisibleRect()); int borderHorzDist = layout->getBorderDrawWidth(); int borderVertDist = layout->getBorderDrawHeight();