MapRuler: Fix artifacting, fix centering for other thickness values

This commit is contained in:
BigBahss 2020-11-19 00:55:22 -05:00 committed by huderlem
parent 6ca4802948
commit b9aaef24c6
3 changed files with 77 additions and 55 deletions

View file

@ -10,7 +10,8 @@ class MapRuler : public QGraphicsObject, private QLine
Q_OBJECT Q_OBJECT
public: 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; QRectF boundingRect() const override;
QPainterPath shape() const override; QPainterPath shape() const override;
@ -45,23 +46,23 @@ signals:
void statusChanged(const QString &statusMessage); void statusChanged(const QString &statusMessage);
private: private:
QColor innerColor; const int thickness;
QColor borderColor; const qreal half_thickness;
const QColor innerColor;
const QColor borderColor;
QSize mapSize; QSize mapSize;
QString statusMessage; QRectF xRuler;
QRect xRuler; QRectF yRuler;
QRect yRuler;
QLineF cornerTick; QLineF cornerTick;
bool anchored; bool anchored;
bool locked; bool locked;
static int thickness; void reset();
void init();
void setAnchor(const QPointF &scenePos); void setAnchor(const QPointF &scenePos);
void setEndPos(const QPointF &scenePos); void setEndPos(const QPointF &scenePos);
QPoint snapToWithinBounds(QPoint pos) const; QPoint snapToWithinBounds(QPoint pos) const;
void updateGeometry(); void updateGeometry();
void updateStatus(Qt::Corner corner);
int pixWidth() const { return width() * 16; } int pixWidth() const { return width() * 16; }
int pixHeight() const { return height() * 16; } int pixHeight() const { return height() * 16; }
}; };

View file

@ -24,7 +24,7 @@ Editor::Editor(Ui::MainWindow* ui)
this->settings = new Settings(); this->settings = new Settings();
this->playerViewRect = new MovableRect(&this->settings->playerViewRectEnabled, 30 * 8, 20 * 8, qRgb(255, 255, 255)); 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->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); connect(this->map_ruler, &MapRuler::statusChanged, this, &Editor::mapRulerStatusChanged);
/// Instead of updating the selected events after every single undo action /// Instead of updating the selected events after every single undo action

View file

@ -4,29 +4,31 @@
#include <QGraphicsSceneEvent> #include <QGraphicsSceneEvent>
#include <QPainter> #include <QPainter>
#include <QColor> #include <QColor>
#include <QVector>
int MapRuler::thickness = 3;
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), innerColor(innerColor),
borderColor(borderColor), borderColor(borderColor),
mapSize(QSize()), mapSize(QSize()),
statusMessage(QString()), xRuler(QRectF()),
xRuler(QRect()), yRuler(QRectF()),
yRuler(QRect()), cornerTick(QLineF()),
cornerTick(QLine()),
anchored(false), anchored(false),
locked(false) locked(false)
{ {
connect(this, &QGraphicsObject::enabledChanged, [this]() { connect(this, &QGraphicsObject::enabledChanged, [this]() {
if (!isEnabled() && anchored) if (!isEnabled() && anchored)
init(); reset();
}); });
} }
QRectF MapRuler::boundingRect() const { 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 { QPainterPath MapRuler::shape() const {
@ -35,10 +37,12 @@ QPainterPath MapRuler::shape() const {
ruler.addRect(xRuler); ruler.addRect(xRuler);
ruler.addRect(yRuler); ruler.addRect(yRuler);
ruler = ruler.simplified(); 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); 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); ruler.addRect(yRuler.x(), y, thickness, 0);
if (deltaX() && deltaY())
ruler.addPolygon(QVector<QPointF>({ cornerTick.p1(), cornerTick.p2() }));
return ruler; return ruler;
} }
@ -46,16 +50,14 @@ void MapRuler::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidge
painter->setPen(QPen(borderColor)); painter->setPen(QPen(borderColor));
painter->setBrush(QBrush(innerColor)); painter->setBrush(QBrush(innerColor));
painter->drawPath(shape()); 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()) if (!isEnabled() || mapSize.isEmpty())
return false; return false;
if (event->type() == QEvent::GraphicsSceneMousePress || event->type() == QEvent::GraphicsSceneMouseMove) { if (event->type() == QEvent::GraphicsSceneMousePress || event->type() == QEvent::GraphicsSceneMouseMove) {
auto mouse_event = static_cast<QGraphicsSceneMouseEvent *>(event); auto *mouse_event = static_cast<QGraphicsSceneMouseEvent *>(event);
if (mouse_event->button() == Qt::RightButton || anchored) { if (mouse_event->button() == Qt::RightButton || anchored) {
mouseEvent(mouse_event); mouseEvent(mouse_event);
} }
@ -71,7 +73,7 @@ void MapRuler::mouseEvent(QGraphicsSceneMouseEvent *event) {
if (event->button() == Qt::LeftButton) if (event->button() == Qt::LeftButton)
locked = !locked; locked = !locked;
if (event->button() == Qt::RightButton) if (event->button() == Qt::RightButton)
init(); reset();
else else
setEndPos(event->scenePos()); setEndPos(event->scenePos());
} }
@ -79,20 +81,19 @@ void MapRuler::mouseEvent(QGraphicsSceneMouseEvent *event) {
void MapRuler::setMapDimensions(const QSize &size) { void MapRuler::setMapDimensions(const QSize &size) {
mapSize = size; mapSize = size;
init(); reset();
} }
void MapRuler::init() { void MapRuler::reset() {
prepareGeometryChange(); prepareGeometryChange();
hide(); hide();
setPoints(QPoint(), QPoint()); setPoints(QPoint(), QPoint());
statusMessage = QString(); xRuler = QRectF();
xRuler = QRect(); yRuler = QRectF();
yRuler = QRect(); cornerTick = QLineF();
cornerTick = QLine();
anchored = false; anchored = false;
locked = false; locked = false;
emit statusChanged(statusMessage); emit statusChanged(QString());
} }
void MapRuler::setAnchor(const QPointF &scenePos) { void MapRuler::setAnchor(const QPointF &scenePos) {
@ -130,42 +131,60 @@ QPoint MapRuler::snapToWithinBounds(QPoint pos) const {
void MapRuler::updateGeometry() { void MapRuler::updateGeometry() {
prepareGeometryChange(); 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 /* 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. */ * ruler is considered to be in the bottom-right quadrant from the anchor point. */
if (deltaX() < 0 && deltaY() < 0) { if (deltaX() < 0 && deltaY() < 0) {
// Top-left // Top-left
xRuler = QRect(0, pixHeight(), pixWidth() + thickness, thickness); xRuler = QRectF(-half_thickness, pixHeight() - half_thickness, pixWidth() + thickness, thickness);
yRuler = QRect(0, 0, thickness, pixHeight() + 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()); 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()) updateStatus(Qt::TopLeftCorner);
.arg(anchor().x()).arg(anchor().y()).arg(endPos().x()).arg(endPos().y());
} else if (deltaX() < 0) { } else if (deltaX() < 0) {
// Bottom-left // Bottom-left
xRuler = QRect(0, 0, pixWidth() + thickness, thickness); xRuler = QRectF(-half_thickness, -half_thickness, pixWidth() + thickness, thickness);
yRuler = QRect(0, 0, thickness, pixHeight() + 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); 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()); statusMessage = QString("Ruler: Left %1").arg(width());
if (deltaY()) if (deltaY())
statusMessage += QString(", Down %1").arg(height()); statusMessage += QString(", Down %1").arg(height());
statusMessage += QString("\nStart(%1, %2), End(%3, %4)") 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 if (deltaY() < 0) { break;
// Top-right case Qt::TopRightCorner:
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);
statusMessage = QString("Ruler: "); statusMessage = QString("Ruler: ");
if (deltaX()) if (deltaX())
statusMessage += QString("Right %1, ").arg(width()); statusMessage += QString("Right %1, ").arg(width());
statusMessage += QString("Up %1\nStart(%2, %3), End(%4, %5)").arg(height()) statusMessage += QString("Up %1\nStart(%2, %3), End(%4, %5)").arg(height())
.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 { break;
// Bottom-right case Qt::BottomRightCorner:
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);
statusMessage = QString("Ruler: "); statusMessage = QString("Ruler: ");
if (deltaX() || deltaY()) { if (deltaX() || deltaY()) {
if (deltaX()) if (deltaX())
@ -176,10 +195,12 @@ void MapRuler::updateGeometry() {
statusMessage += QString("Down: %1").arg(height()); statusMessage += QString("Down: %1").arg(height());
} }
statusMessage += QString("\nStart(%1, %2), End(%3, %4)") 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 { } 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); emit statusChanged(statusMessage);
} }