Add MapRuler (right-click & drag in events view)

This commit is contained in:
BigBahss 2020-09-25 11:53:07 -04:00
parent 457cd1bb85
commit ca6969564f
6 changed files with 207 additions and 14 deletions

View file

@ -23,6 +23,7 @@
#include "settings.h"
#include "movablerect.h"
#include "cursortilerect.h"
#include "mapruler.h"
class DraggablePixmapItem;
class MetatilesPixmapItem;
@ -115,6 +116,7 @@ public:
QList<QGraphicsLineItem*> gridLines;
MovableRect *playerViewRect = nullptr;
CursorTileRect *cursorMapTileRect = nullptr;
MapRuler *map_ruler = nullptr;
QGraphicsScene *scene_metatiles = nullptr;
QGraphicsScene *scene_current_metatile_selection = nullptr;

71
include/ui/mapruler.h Normal file
View file

@ -0,0 +1,71 @@
#ifndef MAPRULER_H
#define MAPRULER_H
#include <QGraphicsItem>
#include <QPainter>
#include <QColor>
class MapRuler : public QGraphicsItem, private QLine
{
public:
MapRuler(QColor interior = Qt::yellow, QColor exterior = Qt::black)
: interiorColor(interior), exteriorColor(exterior)
{
init();
setAcceptedMouseButtons(Qt::RightButton);
}
void init();
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override;
QPainterPath shape() const override;
// Anchor the ruler on metatile 'tilePos' and show the ruler
void setAnchor(const QPoint &tilePos);
// Anchor the ruler on metatile (tileX,tileY) and show the ruler
void setAnchor(int tileX, int tileY) { setAnchor(QPoint(tileX, tileY)); }
// Release the ruler anchor and hide the ruler
void endAnchor();
// Set the ruler end point to metatile 'tilePos' and repaint
void setEndPos(const QPoint &tilePos);
// Set the ruler end point to metatile (tileX, tileY) and repaint
void setEndPos(int tileX, int tileY) { setEndPos(QPoint(tileX, tileY)); }
// Ruler start point in metatiles
QPoint anchor() const { return QLine::p1(); }
// Ruler end point in metatiles
QPoint endPos() const { return QLine::p2(); }
// X-coordinate of the ruler left edge in metatiles
int left() const { return qMin(anchor().x(), endPos().x()); }
// Y-coordinate of the ruler top edge in metatiles
int top() const { return qMin(anchor().y(), endPos().y()); }
// Horizontal component of the ruler in metatiles
int deltaX() const { return QLine::dx(); }
// Vertical component of the ruler in metatiles
int deltaY() const { return QLine::dy(); }
// Ruler width in metatiles
int width() const { return qAbs(deltaX()); }
// Ruler height in metatiles
int height() const { return qAbs(deltaY()); }
// Ruler width in map pixels
int pixWidth() const { return width() * 16; }
// Ruler height in map pixels
int pixHeight() const { return height() * 16; }
bool mousePressed(Qt::MouseButtons buttons) { return buttons & acceptedMouseButtons(); }
private:
QRect xRuler;
QRect yRuler;
QRect widthTextBox;
QRect heightTextBox;
QColor interiorColor;
QColor exteriorColor;
static int padding;
static int thickness;
void updateShape();
};
#endif // MAPRULER_H

View file

@ -68,6 +68,8 @@ SOURCES += src/core/block.cpp \
src/ui/regionmapeditor.cpp \
src/ui/newmappopup.cpp \
src/ui/mapimageexporter.cpp \
src/ui/newtilesetdialog.cpp \
src/ui/mapruler.cpp \
src/config.cpp \
src/editor.cpp \
src/main.cpp \
@ -75,8 +77,7 @@ SOURCES += src/core/block.cpp \
src/project.cpp \
src/scripting.cpp \
src/settings.cpp \
src/log.cpp \
src/ui/newtilesetdialog.cpp
src/log.cpp
HEADERS += include/core/block.h \
include/core/blockdata.h \
@ -134,15 +135,16 @@ HEADERS += include/core/block.h \
include/ui/regionmapeditor.h \
include/ui/newmappopup.h \
include/ui/mapimageexporter.h \
include/ui/newtilesetdialog.h \
include/ui/overlay.h \
include/ui/mapruler.h \
include/config.h \
include/editor.h \
include/mainwindow.h \
include/project.h \
include/scripting.h \
include/settings.h \
include/log.h \
include/ui/newtilesetdialog.h \
include/ui/overlay.h
include/log.h
FORMS += forms/mainwindow.ui \
forms/eventpropertiesframe.ui \

View file

@ -23,6 +23,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();
/// Instead of updating the selected events after every single undo action
/// (eg when the user rolls back several at once), only reselect events when
@ -41,6 +42,7 @@ Editor::~Editor()
delete this->settings;
delete this->playerViewRect;
delete this->cursorMapTileRect;
delete this->map_ruler;
closeProject();
}
@ -1119,7 +1121,14 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item
}
}
} else if (obj_edit_mode == "select") {
// do nothing here, at least for now
if (!this->map_ruler->isEnabled() && this->map_ruler->mousePressed(event->buttons())) {
this->map_ruler->setAnchor(x, y);
} else if (event->type() == QEvent::GraphicsSceneMouseRelease
&& !this->map_ruler->mousePressed(event->buttons())) {
this->map_ruler->endAnchor();
} else if (this->map_ruler->isEnabled()) {
this->map_ruler->setEndPos(x, y);
}
} else if (obj_edit_mode == "shift" && item->map) {
static QPoint selection_origin;
static unsigned actionId = 0;
@ -1217,6 +1226,7 @@ bool Editor::displayMap() {
delete map_item;
scene->removeItem(this->playerViewRect);
scene->removeItem(this->cursorMapTileRect);
scene->removeItem(this->map_ruler);
}
displayMetatileSelector();
@ -1233,8 +1243,10 @@ bool Editor::displayMap() {
this->playerViewRect->setZValue(1000);
this->cursorMapTileRect->setZValue(1001);
this->map_ruler->setZValue(1002);
scene->addItem(this->playerViewRect);
scene->addItem(this->cursorMapTileRect);
scene->addItem(this->map_ruler);
if (map_item) {
map_item->setVisible(false);

View file

@ -1,8 +1,7 @@
#include "draggablepixmapitem.h"
#include "editor.h"
#include "editcommands.h"
#include "mapruler.h"
static unsigned currentActionId = 0;
@ -57,9 +56,15 @@ void DraggablePixmapItem::bindToUserData(QComboBox *combo, QString key) {
}
void DraggablePixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *mouse) {
int x = static_cast<int>(mouse->pos().x() + this->pos().x()) / 16;
int y = static_cast<int>(mouse->pos().y() + this->pos().y()) / 16;
if (mouse->buttons() & this->editor->map_ruler->acceptedMouseButtons()) {
this->editor->map_ruler->setAnchor(x, y);
return;
}
active = true;
last_x = static_cast<int>(mouse->pos().x() + this->pos().x()) / 16;
last_y = static_cast<int>(mouse->pos().y() + this->pos().y()) / 16;
last_x = x;
last_y = y;
this->editor->selectMapEvent(this, mouse->modifiers() & Qt::ControlModifier);
this->editor->selectingEvent = true;
}
@ -76,7 +81,9 @@ void DraggablePixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *mouse) {
int x = static_cast<int>(mouse->pos().x() + this->pos().x()) / 16;
int y = static_cast<int>(mouse->pos().y() + this->pos().y()) / 16;
emit this->editor->map_item->hoveredMapMetatileChanged(x, y);
if (x != last_x || y != last_y) {
if (this->editor->map_ruler->isEnabled()) {
this->editor->map_ruler->setEndPos(x, y);
} else if (x != last_x || y != last_y) {
QList <Event *> selectedEvents;
if (editor->selected_events->contains(this)) {
for (DraggablePixmapItem *item : *editor->selected_events) {
@ -92,9 +99,14 @@ void DraggablePixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *mouse) {
}
}
void DraggablePixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *) {
active = false;
currentActionId++;
void DraggablePixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouse) {
if (!(mouse->buttons() & this->editor->map_ruler->acceptedMouseButtons())) {
this->editor->map_ruler->endAnchor();
}
if (!this->editor->map_ruler->isEnabled()) {
active = false;
currentActionId++;
}
}
void DraggablePixmapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) {

94
src/ui/mapruler.cpp Normal file
View file

@ -0,0 +1,94 @@
#include "mapruler.h"
#include <QGraphicsItem>
#include <QPainter>
#include <QColor>
int MapRuler::padding = 24;
int MapRuler::thickness = 3;
void MapRuler::init() {
setVisible(false);
setEnabled(false);
setPoints(QPoint(), QPoint());
xRuler = QRect();
yRuler = QRect();
widthTextBox = QRect();
heightTextBox = QRect();
}
QRectF MapRuler::boundingRect() const {
return QRectF(-padding, -padding, pixWidth() + padding * 2, pixHeight() + padding * 2);
}
QPainterPath MapRuler::shape() const {
QPainterPath ruler;
ruler.setFillRule(Qt::WindingFill);
ruler.addRect(xRuler);
ruler.addRect(yRuler);
ruler = ruler.simplified();
return ruler;
}
void MapRuler::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) {
painter->setPen(exteriorColor);
painter->setBrush(QBrush(interiorColor));
painter->drawPath(shape());
painter->drawText(widthTextBox, Qt::AlignCenter, QString("%1").arg(width()));
painter->drawText(heightTextBox, Qt::AlignCenter, QString("%1").arg(height()));
}
void MapRuler::setAnchor(const QPoint &tilePos) {
setEnabled(true);
setPoints(tilePos, tilePos);
updateShape();
setVisible(true);
}
void MapRuler::endAnchor() {
setVisible(false);
setEnabled(false);
prepareGeometryChange();
init();
}
void MapRuler::setEndPos(const QPoint &tilePos) {
if (!isEnabled() || (tilePos == endPos() && tilePos != anchor()))
return;
prepareGeometryChange();
setP2(tilePos);
updateShape();
}
void MapRuler::updateShape() {
setPos(QPoint(left() * 16 + 7, top() * 16 + 7));
/* Determines what quadrant the ruler exists 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) ruler is
* treated as being 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);
widthTextBox = QRect(0, pixHeight(), pixWidth(), padding);
heightTextBox = QRect(-padding, 0, padding, pixHeight());
} else if (deltaX() < 0) {
// Bottom-left
xRuler = QRect(0, 0, pixWidth() + thickness, thickness);
yRuler = QRect(0, 0, thickness, pixHeight() + thickness);
widthTextBox = QRect(0, -padding, pixWidth(), padding);
heightTextBox = QRect(-padding, 0, padding, pixHeight());
} else if (deltaY() < 0) {
// Top-right
xRuler = QRect(0, pixHeight(), pixWidth() + thickness, thickness);
yRuler = QRect(pixWidth(), 0, thickness, pixHeight() + thickness);
widthTextBox = QRect(0, pixHeight(), pixWidth(), padding);
heightTextBox = QRect(pixWidth(), 0, padding, pixHeight());
} else {
// Bottom-right
xRuler = QRect(0, 0, pixWidth() + thickness, thickness);
yRuler = QRect(pixWidth(), 0, thickness, pixHeight() + thickness);
widthTextBox = QRect(0, -padding, pixWidth(), padding);
heightTextBox = QRect(pixWidth(), 0, padding, pixHeight());
}
}