diff --git a/include/ui/mapruler.h b/include/ui/mapruler.h index c9531703..151492e3 100644 --- a/include/ui/mapruler.h +++ b/include/ui/mapruler.h @@ -10,7 +10,8 @@ class MapRuler : public QGraphicsObject, private QLine Q_OBJECT public: - MapRuler(QColor innerColor = Qt::yellow, QColor borderColor = Qt::black); + // thickness is given in scene pixels + MapRuler(int thickness, QColor innerColor = Qt::yellow, QColor borderColor = Qt::black); QRectF boundingRect() const override; QPainterPath shape() const override; @@ -45,23 +46,23 @@ signals: void statusChanged(const QString &statusMessage); private: - QColor innerColor; - QColor borderColor; + const int thickness; + const qreal half_thickness; + const QColor innerColor; + const QColor borderColor; QSize mapSize; - QString statusMessage; - QRect xRuler; - QRect yRuler; + QRectF xRuler; + QRectF yRuler; QLineF cornerTick; bool anchored; bool locked; - static int thickness; - - void init(); + void reset(); void setAnchor(const QPointF &scenePos); void setEndPos(const QPointF &scenePos); QPoint snapToWithinBounds(QPoint pos) const; void updateGeometry(); + void updateStatus(Qt::Corner corner); int pixWidth() const { return width() * 16; } int pixHeight() const { return height() * 16; } }; diff --git a/src/editor.cpp b/src/editor.cpp index ce45443c..12697eb6 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -24,7 +24,7 @@ Editor::Editor(Ui::MainWindow* ui) this->settings = new Settings(); this->playerViewRect = new MovableRect(&this->settings->playerViewRectEnabled, 30 * 8, 20 * 8, qRgb(255, 255, 255)); this->cursorMapTileRect = new CursorTileRect(&this->settings->cursorTileRectEnabled, qRgb(255, 255, 255)); - this->map_ruler = new MapRuler(); + this->map_ruler = new MapRuler(4); connect(this->map_ruler, &MapRuler::statusChanged, this, &Editor::mapRulerStatusChanged); /// Instead of updating the selected events after every single undo action diff --git a/src/ui/mapruler.cpp b/src/ui/mapruler.cpp index 77f6322b..908e0a46 100644 --- a/src/ui/mapruler.cpp +++ b/src/ui/mapruler.cpp @@ -4,29 +4,31 @@ #include #include #include - -int MapRuler::thickness = 3; +#include -MapRuler::MapRuler(QColor innerColor, QColor borderColor) : +MapRuler::MapRuler(int thickness, QColor innerColor, QColor borderColor) : + /* The logical representation of rectangles are always one less than + * the rendered shape, so we subtract 1 from thickness. */ + thickness(thickness - 1), + half_thickness(qreal(thickness - 1) / 2.0), innerColor(innerColor), borderColor(borderColor), mapSize(QSize()), - statusMessage(QString()), - xRuler(QRect()), - yRuler(QRect()), - cornerTick(QLine()), + xRuler(QRectF()), + yRuler(QRectF()), + cornerTick(QLineF()), anchored(false), locked(false) { connect(this, &QGraphicsObject::enabledChanged, [this]() { if (!isEnabled() && anchored) - init(); + reset(); }); } QRectF MapRuler::boundingRect() const { - return QRectF(-thickness, -thickness, pixWidth() + thickness * 2, pixHeight() + thickness * 2); + return QRectF(-(half_thickness + 1), -(half_thickness + 1), pixWidth() + thickness + 2, pixHeight() + thickness + 2); } QPainterPath MapRuler::shape() const { @@ -35,10 +37,12 @@ QPainterPath MapRuler::shape() const { ruler.addRect(xRuler); ruler.addRect(yRuler); ruler = ruler.simplified(); - for (int x = 17; x < pixWidth(); x += 16) + for (int x = 16; x < pixWidth(); x += 16) ruler.addRect(x, xRuler.y(), 0, thickness); - for (int y = 17; y < pixHeight(); y += 16) + for (int y = 16; y < pixHeight(); y += 16) ruler.addRect(yRuler.x(), y, thickness, 0); + if (deltaX() && deltaY()) + ruler.addPolygon(QVector({ cornerTick.p1(), cornerTick.p2() })); return ruler; } @@ -46,16 +50,14 @@ void MapRuler::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidge painter->setPen(QPen(borderColor)); painter->setBrush(QBrush(innerColor)); painter->drawPath(shape()); - if (deltaX() && deltaY()) - painter->drawLine(cornerTick); } -bool MapRuler::eventFilter(QObject*, QEvent *event) { +bool MapRuler::eventFilter(QObject *, QEvent *event) { if (!isEnabled() || mapSize.isEmpty()) return false; if (event->type() == QEvent::GraphicsSceneMousePress || event->type() == QEvent::GraphicsSceneMouseMove) { - auto mouse_event = static_cast(event); + auto *mouse_event = static_cast(event); if (mouse_event->button() == Qt::RightButton || anchored) { mouseEvent(mouse_event); } @@ -71,7 +73,7 @@ void MapRuler::mouseEvent(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::LeftButton) locked = !locked; if (event->button() == Qt::RightButton) - init(); + reset(); else setEndPos(event->scenePos()); } @@ -79,20 +81,19 @@ void MapRuler::mouseEvent(QGraphicsSceneMouseEvent *event) { void MapRuler::setMapDimensions(const QSize &size) { mapSize = size; - init(); + reset(); } -void MapRuler::init() { +void MapRuler::reset() { prepareGeometryChange(); hide(); setPoints(QPoint(), QPoint()); - statusMessage = QString(); - xRuler = QRect(); - yRuler = QRect(); - cornerTick = QLine(); + xRuler = QRectF(); + yRuler = QRectF(); + cornerTick = QLineF(); anchored = false; locked = false; - emit statusChanged(statusMessage); + emit statusChanged(QString()); } void MapRuler::setAnchor(const QPointF &scenePos) { @@ -130,42 +131,60 @@ QPoint MapRuler::snapToWithinBounds(QPoint pos) const { void MapRuler::updateGeometry() { prepareGeometryChange(); - setPos(QPoint(left() * 16 + 7, top() * 16 + 7)); + setPos(QPoint(left() * 16 + 8, top() * 16 + 8)); /* 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(s) + * 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. */ if (deltaX() < 0 && deltaY() < 0) { // Top-left - xRuler = QRect(0, pixHeight(), pixWidth() + thickness, thickness); - yRuler = QRect(0, 0, thickness, pixHeight() + thickness); + xRuler = QRectF(-half_thickness, pixHeight() - half_thickness, pixWidth() + thickness, thickness); + yRuler = QRectF(-half_thickness, -half_thickness, thickness, pixHeight() + thickness); cornerTick = QLineF(yRuler.x() + 0.5, xRuler.y() + thickness - 0.5, yRuler.x() + thickness, xRuler.y()); - statusMessage = QString("Ruler: Left %1, Up %2\nStart(%3, %4), End(%5, %6)").arg(width()).arg(height()) - .arg(anchor().x()).arg(anchor().y()).arg(endPos().x()).arg(endPos().y()); + updateStatus(Qt::TopLeftCorner); } else if (deltaX() < 0) { // Bottom-left - xRuler = QRect(0, 0, pixWidth() + thickness, thickness); - yRuler = QRect(0, 0, thickness, pixHeight() + thickness); + xRuler = QRectF(-half_thickness, -half_thickness, pixWidth() + thickness, thickness); + yRuler = QRectF(-half_thickness, -half_thickness, thickness, pixHeight() + thickness); cornerTick = QLineF(xRuler.x() + 0.5, xRuler.y() + 0.5, xRuler.x() + thickness, xRuler.y() + thickness); + updateStatus(Qt::BottomLeftCorner); + } else if (deltaY() < 0) { + // Top-right + xRuler = QRectF(-half_thickness, pixHeight() - half_thickness, pixWidth() + thickness, thickness); + yRuler = QRectF(pixWidth() - half_thickness, -half_thickness, thickness, pixHeight() + thickness); + cornerTick = QLineF(yRuler.x(), xRuler.y(), yRuler.x() + thickness - 0.5, xRuler.y() + thickness - 0.5); + updateStatus(Qt::TopRightCorner); + } else { + // Bottom-right + xRuler = QRectF(-half_thickness, -half_thickness, pixWidth() + thickness, thickness); + yRuler = QRectF(pixWidth() - half_thickness, -half_thickness, thickness, pixHeight() + thickness); + cornerTick = QLineF(yRuler.x(), yRuler.y() + thickness, yRuler.x() + thickness - 0.5, yRuler.y() + 0.5); + updateStatus(Qt::BottomRightCorner); + } +} + +void MapRuler::updateStatus(Qt::Corner corner) { + QString statusMessage; + switch (corner) + { + case Qt::TopLeftCorner: + statusMessage = QString("Ruler: Left %1, Up %2\nStart(%3, %4), End(%5, %6)").arg(width()).arg(height()) + .arg(anchor().x()).arg(anchor().y()).arg(endPos().x()).arg(endPos().y()); + break; + case Qt::BottomLeftCorner: statusMessage = QString("Ruler: Left %1").arg(width()); if (deltaY()) statusMessage += QString(", Down %1").arg(height()); statusMessage += QString("\nStart(%1, %2), End(%3, %4)") - .arg(anchor().x()).arg(anchor().y()).arg(endPos().x()).arg(endPos().y()); - } else if (deltaY() < 0) { - // Top-right - xRuler = QRect(0, pixHeight(), pixWidth() + thickness, thickness); - yRuler = QRect(pixWidth(), 0, thickness, pixHeight() + thickness); - cornerTick = QLineF(yRuler.x(), xRuler.y(), yRuler.x() + thickness - 0.5, xRuler.y() + thickness - 0.5); + .arg(anchor().x()).arg(anchor().y()).arg(endPos().x()).arg(endPos().y()); + break; + case Qt::TopRightCorner: statusMessage = QString("Ruler: "); if (deltaX()) statusMessage += QString("Right %1, ").arg(width()); statusMessage += QString("Up %1\nStart(%2, %3), End(%4, %5)").arg(height()) - .arg(anchor().x()).arg(anchor().y()).arg(endPos().x()).arg(endPos().y()); - } else { - // Bottom-right - xRuler = QRect(0, 0, pixWidth() + thickness, thickness); - yRuler = QRect(pixWidth(), 0, thickness, pixHeight() + thickness); - cornerTick = QLineF(yRuler.x(), yRuler.y() + thickness, yRuler.x() + thickness - 0.5, yRuler.y() + 0.5); + .arg(anchor().x()).arg(anchor().y()).arg(endPos().x()).arg(endPos().y()); + break; + case Qt::BottomRightCorner: statusMessage = QString("Ruler: "); if (deltaX() || deltaY()) { if (deltaX()) @@ -176,10 +195,12 @@ void MapRuler::updateGeometry() { statusMessage += QString("Down: %1").arg(height()); } statusMessage += QString("\nStart(%1, %2), End(%3, %4)") - .arg(anchor().x()).arg(anchor().y()).arg(endPos().x()).arg(endPos().y()); + .arg(anchor().x()).arg(anchor().y()).arg(endPos().x()).arg(endPos().y()); } else { - statusMessage += QString("0\nStart(%1, %2)").arg(anchor().x()).arg(anchor().y()); + statusMessage += QString("0\nStart(%1, %2)") + .arg(anchor().x()).arg(anchor().y()); } + break; } emit statusChanged(statusMessage); }