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
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; }
};

View file

@ -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

View file

@ -4,29 +4,31 @@
#include <QGraphicsSceneEvent>
#include <QPainter>
#include <QColor>
int MapRuler::thickness = 3;
#include <QVector>
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<QPointF>({ 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<QGraphicsSceneMouseEvent *>(event);
auto *mouse_event = static_cast<QGraphicsSceneMouseEvent *>(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);
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);
break;
case Qt::BottomRightCorner:
statusMessage = QString("Ruler: ");
if (deltaX() || deltaY()) {
if (deltaX())
@ -178,8 +197,10 @@ void MapRuler::updateGeometry() {
statusMessage += QString("\nStart(%1, %2), End(%3, %4)")
.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);
}