Merge pull request #310 from BigBahss/ruler-tool

Ruler tool
This commit is contained in:
huderlem 2020-10-24 08:58:38 -05:00 committed by GitHub
commit 1b3bd9314d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 474 additions and 184 deletions

View file

@ -16,6 +16,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
- Some new shortcuts were added in [porymap/#290](https://github.com/huderlem/porymap/pull/290). - Some new shortcuts were added in [porymap/#290](https://github.com/huderlem/porymap/pull/290).
- All plain text boxes now have a clear button to delete the text. - All plain text boxes now have a clear button to delete the text.
- The window sizes and positions of the tileset editor, palette editor, and region map editor are now stored in `porymap.cfg`. - The window sizes and positions of the tileset editor, palette editor, and region map editor are now stored in `porymap.cfg`.
- Add ruler tool for measuring metatile distance in events tab (Right-click to turn on/off, left-click to lock in place).
### Changed ### Changed
- Holding `shift` now toggles "Smart Path" drawing; when the "Smart Paths" checkbox is checked, holding `shift` will temporarily disable it. - Holding `shift` now toggles "Smart Path" drawing; when the "Smart Paths" checkbox is checked, holding `shift` will temporarily disable it.

View file

@ -237,17 +237,32 @@ The event editing tab also extends functionality to a few of the tool buttons de
A brief description and animation is listed for each of the available tools below: A brief description and animation is listed for each of the available tools below:
Pencil Pencil
When clicking on an existing event, the pencil tool will behave normally (as the standard cursor). It can also be used to "draw" events in a certain location. The event created will be a default-valued event of the same type as the currently selected event. When clicking on an existing event, the pencil tool will behave normally (as the standard cursor). It can also be used to "draw" events in a certain location. The event created will be a default-valued event of the same type as the currently selected event. Right-clicking with the Pencil Tool will return to the Pointer tool.
.. figure:: images/editing-map-events/event-tool-pencil.gif .. figure:: images/editing-map-events/event-tool-pencil.gif
:alt: Drawing Object Events with the Pencil Tool :alt: Drawing Object Events with the Pencil Tool
Drawing Object Events with the Pencil Tool Drawing Object Events with the Pencil Tool
Pointer
The Pointer Tool is the default tool for the event editing tab and allows you to select and move events on the map. The Pointer Tool also gives you access to the :ref:`Ruler Tool <ruler-tool>`.
Shift Shift
You can use the shift tool to move any number of events together. When a selected event is dragged, all other selected events will move with it. When a tile with no event is clicked, all events on the map can be dragged. You can use the Shift Tool to move any number of events together. When a selected event is dragged, all other selected events will move with it. When a tile with no event is clicked, all events on the map can be dragged.
.. figure:: images/editing-map-events/event-tool-shift.gif .. figure:: images/editing-map-events/event-tool-shift.gif
:alt: Moving Events with the Shift Tool :alt: Moving Events with the Shift Tool
Moving Events with the Shift Tool Moving Events with the Shift Tool
.. _ruler-tool:
Ruler Tool
----------
The Ruler Tool provides a convenient way to measure distance on the map. This is particularly useful for scripting object movement. With the Pointer Tool selected you can activate the ruler with a Right-click. With the ruler active you can drag the mouse around to extend the ruler. The ruler can be deactivated with another Right-click, or locked in place with a Left-click (Left-click again to unlock the ruler). The dimensions of the ruler are displayed in a tool-tip and in the status bar in the bottom left corner of the widnow.
.. figure:: images/editing-map-events/event-tool-ruler.gif
:alt: Measuring metatile distance with the Ruler Tool
Measuring metatile distance with the Ruler Tool

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

View file

@ -38,10 +38,10 @@ Main Window
:header: Map Editing :header: Map Editing
:widths: 20, 20 :widths: 20, 20
Select Tiles From Map, Hold Right-click while dragging Select Metatile, Right-click in "paint" or "fill" mode
Select Multiple Metatiles, Hold Right-click while dragging
Bucket Fill Metatiles, Middle-click from "paint" or "fill" mode Bucket Fill Metatiles, Middle-click from "paint" or "fill" mode
Magic Fill Metatiles, ``Ctrl+`` Middle-click from "paint" or "fill" mode Magic Fill Metatiles, ``Ctrl+`` Middle-click from "paint" or "fill" mode
Select Metatile, Right-click in "paint" or "fill" mode
Zoom In, ``Ctrl++`` `or` ``Ctrl+=`` Zoom In, ``Ctrl++`` `or` ``Ctrl+=``
Zoom Out, ``Ctrl+-`` Zoom Out, ``Ctrl+-``
Reset View Scale, ``Ctrl+0`` Reset View Scale, ``Ctrl+0``
@ -52,8 +52,9 @@ Main Window
Draw Straight Paths, Hold ``Ctrl`` Draw Straight Paths, Hold ``Ctrl``
Duplicate Event(s), ``Ctrl+D`` while selected Duplicate Event(s), ``Ctrl+D`` while selected
Delete Event(s), ``DEL`` while selected Delete Event(s), ``DEL`` while selected
Select Event, Right-click in paint mode Pointer, Right-click in "paint" mode
Update Event Selection, `Ctrl+` click Select Event, Left-click in "pointer" mode or Right-click in "paint" mode
Select Multiple Events, `Ctrl+` click

View file

@ -113,6 +113,7 @@ private:
signals: signals:
void mapChanged(Map *map); void mapChanged(Map *map);
void mapDimensionsChanged(const QSize &size);
void mapNeedsRedrawing(); void mapNeedsRedrawing();
}; };

View file

@ -3,6 +3,7 @@
#include "tile.h" #include "tile.h"
#include <QImage> #include <QImage>
#include <QPoint>
#include <QString> #include <QString>
class Metatile class Metatile
@ -20,6 +21,7 @@ public:
Metatile *copy(); Metatile *copy();
void copyInPlace(Metatile*); void copyInPlace(Metatile*);
static int getBlockIndex(int); static int getBlockIndex(int);
static QPoint coordFromPixmapCoord(const QPointF &pixelCoord);
}; };
#endif // METATILE_H #endif // METATILE_H

View file

@ -23,6 +23,7 @@
#include "settings.h" #include "settings.h"
#include "movablerect.h" #include "movablerect.h"
#include "cursortilerect.h" #include "cursortilerect.h"
#include "mapruler.h"
class DraggablePixmapItem; class DraggablePixmapItem;
class MetatilesPixmapItem; class MetatilesPixmapItem;
@ -117,6 +118,7 @@ public:
QList<QGraphicsLineItem*> gridLines; QList<QGraphicsLineItem*> gridLines;
MovableRect *playerViewRect = nullptr; MovableRect *playerViewRect = nullptr;
CursorTileRect *cursorMapTileRect = nullptr; CursorTileRect *cursorMapTileRect = nullptr;
MapRuler *map_ruler = nullptr;
QGraphicsScene *scene_metatiles = nullptr; QGraphicsScene *scene_metatiles = nullptr;
QGraphicsScene *scene_current_metatile_selection = nullptr; QGraphicsScene *scene_current_metatile_selection = nullptr;
@ -196,12 +198,13 @@ private slots:
void onHoveredMovementPermissionCleared(); void onHoveredMovementPermissionCleared();
void onHoveredMetatileSelectionChanged(uint16_t); void onHoveredMetatileSelectionChanged(uint16_t);
void onHoveredMetatileSelectionCleared(); void onHoveredMetatileSelectionCleared();
void onHoveredMapMetatileChanged(int, int); void onHoveredMapMetatileChanged(const QPoint &pos);
void onHoveredMapMetatileCleared(); void onHoveredMapMetatileCleared();
void onHoveredMapMovementPermissionChanged(int, int); void onHoveredMapMovementPermissionChanged(int, int);
void onHoveredMapMovementPermissionCleared(); void onHoveredMapMovementPermissionCleared();
void onSelectedMetatilesChanged(); void onSelectedMetatilesChanged();
void onWheelZoom(int); void onWheelZoom(int);
void onMapRulerLengthChanged();
signals: signals:
void objectsChanged(); void objectsChanged();

View file

@ -77,7 +77,7 @@ public:
void updateMetatileSelection(QGraphicsSceneMouseEvent *event); void updateMetatileSelection(QGraphicsSceneMouseEvent *event);
void paintNormal(int x, int y, bool fromScriptCall = false); void paintNormal(int x, int y, bool fromScriptCall = false);
void lockNondominantAxis(QGraphicsSceneMouseEvent *event); void lockNondominantAxis(QGraphicsSceneMouseEvent *event);
int adjustCoord(int coord, MapPixmapItem::Axis axis); QPoint adjustCoords(QPoint pos);
private: private:
void paintSmartPath(int x, int y, bool fromScriptCall = false); void paintSmartPath(int x, int y, bool fromScriptCall = false);
@ -89,7 +89,7 @@ signals:
void startPaint(QGraphicsSceneMouseEvent *, MapPixmapItem *); void startPaint(QGraphicsSceneMouseEvent *, MapPixmapItem *);
void endPaint(QGraphicsSceneMouseEvent *, MapPixmapItem *); void endPaint(QGraphicsSceneMouseEvent *, MapPixmapItem *);
void mouseEvent(QGraphicsSceneMouseEvent *, MapPixmapItem *); void mouseEvent(QGraphicsSceneMouseEvent *, MapPixmapItem *);
void hoveredMapMetatileChanged(int x, int y); void hoveredMapMetatileChanged(const QPoint &pos);
void hoveredMapMetatileCleared(); void hoveredMapMetatileCleared();
protected: protected:

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

@ -0,0 +1,81 @@
#ifndef MAPRULER_H
#define MAPRULER_H
#include <QGraphicsObject>
#include <QPainter>
#include <QColor>
class MapRuler : public QGraphicsObject, private QLine
{
Q_OBJECT
public:
MapRuler(QColor innerColor = Qt::yellow, QColor borderColor = Qt::black) :
innerColor(innerColor),
borderColor(borderColor),
mapSize(QSize())
{
init();
}
void init();
QRectF boundingRect() const override;
QPainterPath shape() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override;
bool eventFilter(QObject *, QEvent *event) override;
void setEnabled(bool enabled);
bool isAnchored() const { return anchored; }
bool isLocked() const { return locked; }
// 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's left edge in metatiles
int left() const { return qMin(anchor().x(), endPos().x()); }
// Y-coordinate of the ruler's 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()); }
QString statusMessage;
public slots:
void mouseEvent(QGraphicsSceneMouseEvent *event);
void setMapDimensions(const QSize &size);
private:
QColor innerColor;
QColor borderColor;
QSize mapSize;
QRect xRuler;
QRect yRuler;
QLineF cornerTick;
bool anchored;
bool locked;
static int thickness;
QPoint snapToWithinBounds(QPoint pos) const;
void setAnchor(const QPointF &scenePos, const QPoint &screenPos);
void endAnchor();
void setEndPos(const QPointF &scenePos, const QPoint &screenPos);
void showDimensions(const QPoint &screenPos) const;
void hideDimensions() const;
void updateGeometry();
int pixWidth() const { return width() * 16; }
int pixHeight() const { return height() * 16; }
signals:
void lengthChanged();
void deactivated(const QPoint &endPos);
};
#endif // MAPRULER_H

View file

@ -68,7 +68,9 @@ SOURCES += src/core/block.cpp \
src/ui/regionmapeditor.cpp \ src/ui/regionmapeditor.cpp \
src/ui/newmappopup.cpp \ src/ui/newmappopup.cpp \
src/ui/mapimageexporter.cpp \ src/ui/mapimageexporter.cpp \
src/ui/newtilesetdialog.cpp \
src/ui/flowlayout.cpp \ src/ui/flowlayout.cpp \
src/ui/mapruler.cpp \
src/config.cpp \ src/config.cpp \
src/editor.cpp \ src/editor.cpp \
src/main.cpp \ src/main.cpp \
@ -76,8 +78,7 @@ SOURCES += src/core/block.cpp \
src/project.cpp \ src/project.cpp \
src/scripting.cpp \ src/scripting.cpp \
src/settings.cpp \ src/settings.cpp \
src/log.cpp \ src/log.cpp
src/ui/newtilesetdialog.cpp
HEADERS += include/core/block.h \ HEADERS += include/core/block.h \
include/core/blockdata.h \ include/core/blockdata.h \
@ -135,16 +136,17 @@ HEADERS += include/core/block.h \
include/ui/regionmapeditor.h \ include/ui/regionmapeditor.h \
include/ui/newmappopup.h \ include/ui/newmappopup.h \
include/ui/mapimageexporter.h \ include/ui/mapimageexporter.h \
include/ui/newtilesetdialog.h \
include/ui/overlay.h \
include/ui/flowlayout.h \ include/ui/flowlayout.h \
include/ui/mapruler.h \
include/config.h \ include/config.h \
include/editor.h \ include/editor.h \
include/mainwindow.h \ include/mainwindow.h \
include/project.h \ include/project.h \
include/scripting.h \ include/scripting.h \
include/settings.h \ include/settings.h \
include/log.h \ include/log.h
include/ui/newtilesetdialog.h \
include/ui/overlay.h
FORMS += forms/mainwindow.ui \ FORMS += forms/mainwindow.ui \
forms/eventpropertiesframe.ui \ forms/eventpropertiesframe.ui \

View file

@ -353,6 +353,7 @@ void Map::setDimensions(int newWidth, int newHeight, bool setNewBlockdata) {
layout->height = QString::number(newHeight); layout->height = QString::number(newHeight);
emit mapChanged(this); emit mapChanged(this);
emit mapDimensionsChanged(QSize(getWidth(), getHeight()));
} }
void Map::setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata) { void Map::setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata) {

View file

@ -39,3 +39,9 @@ int Metatile::getBlockIndex(int index) {
return index - Project::getNumMetatilesPrimary(); return index - Project::getNumMetatilesPrimary();
} }
} }
QPoint Metatile::coordFromPixmapCoord(const QPointF &pixelCoord) {
int x = static_cast<int>(pixelCoord.x()) / 16;
int y = static_cast<int>(pixelCoord.y()) / 16;
return QPoint(x, y);
}

View file

@ -6,6 +6,7 @@
#include "mapconnection.h" #include "mapconnection.h"
#include "currentselectedmetatilespixmapitem.h" #include "currentselectedmetatilespixmapitem.h"
#include "mapsceneeventfilter.h" #include "mapsceneeventfilter.h"
#include "metatile.h"
#include "montabwidget.h" #include "montabwidget.h"
#include "editcommands.h" #include "editcommands.h"
#include <QCheckBox> #include <QCheckBox>
@ -23,6 +24,9 @@ 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();
connect(this->map_ruler, &MapRuler::lengthChanged, this, &Editor::onMapRulerLengthChanged);
connect(this->map_ruler, &MapRuler::deactivated, this, &Editor::onHoveredMapMetatileChanged);
/// Instead of updating the selected events after every single undo action /// Instead of updating the selected events after every single undo action
/// (eg when the user rolls back several at once), only reselect events when /// (eg when the user rolls back several at once), only reselect events when
@ -41,6 +45,7 @@ Editor::~Editor()
delete this->settings; delete this->settings;
delete this->playerViewRect; delete this->playerViewRect;
delete this->cursorMapTileRect; delete this->cursorMapTileRect;
delete this->map_ruler;
closeProject(); closeProject();
} }
@ -910,32 +915,45 @@ void Editor::scaleMapView(int s) {
} }
} }
void Editor::onHoveredMapMetatileChanged(int x, int y) { void Editor::onHoveredMapMetatileChanged(const QPoint &pos) {
this->playerViewRect->updateLocation(x, y); this->playerViewRect->updateLocation(pos.x(), pos.y());
this->cursorMapTileRect->updateLocation(x, y); this->cursorMapTileRect->updateLocation(pos.x(), pos.y());
if (map_item->paintingMode == MapPixmapItem::PaintMode::Metatiles if (map_item->paintingMode == MapPixmapItem::PaintMode::Metatiles
&& x >= 0 && x < map->getWidth() && y >= 0 && y < map->getHeight()) { && pos.x() >= 0 && pos.x() < map->getWidth() && pos.y() >= 0 && pos.y() < map->getHeight()) {
int blockIndex = y * map->getWidth() + x; int blockIndex = pos.y() * map->getWidth() + pos.x();
int metatileId = map->layout->blockdata->blocks->at(blockIndex).tile; int metatileId = map->layout->blockdata->blocks->at(blockIndex).tile;
this->ui->statusBar->showMessage(QString("X: %1, Y: %2, %3, Scale = %4x") this->ui->statusBar->showMessage(QString("X: %1, Y: %2, %3, Scale = %4x")
.arg(x) .arg(pos.x())
.arg(y) .arg(pos.y())
.arg(getMetatileDisplayMessage(metatileId)) .arg(getMetatileDisplayMessage(metatileId))
.arg(QString::number(pow(scale_base, scale_exp), 'g', 2))); .arg(QString::number(pow(scale_base, scale_exp), 'g', 2)));
} else if (map_item->paintingMode == MapPixmapItem::PaintMode::EventObjects } else if (map_item->paintingMode == MapPixmapItem::PaintMode::EventObjects
&& x >= 0 && x < map->getWidth() && y >= 0 && y < map->getHeight()) { && pos.x() >= 0 && pos.x() < map->getWidth() && pos.y() >= 0 && pos.y() < map->getHeight()) {
this->ui->statusBar->showMessage(QString("X: %1, Y: %2") this->ui->statusBar->showMessage(QString("X: %1, Y: %2, Scale = %3x")
.arg(x) .arg(pos.x())
.arg(y)); .arg(pos.y())
.arg(QString::number(pow(scale_base, scale_exp), 'g', 2)));
} }
} }
void Editor::onMapRulerLengthChanged() {
const QPoint pos = map_ruler->endPos();
ui->statusBar->showMessage(QString("X: %1, Y: %2, Scale = %3x; %4")
.arg(pos.x())
.arg(pos.y())
.arg(QString::number(pow(scale_base, scale_exp), 'g', 2))
.arg(map_ruler->statusMessage));
}
void Editor::onHoveredMapMetatileCleared() { void Editor::onHoveredMapMetatileCleared() {
this->playerViewRect->setVisible(false); this->playerViewRect->setVisible(false);
this->cursorMapTileRect->setVisible(false); this->cursorMapTileRect->setVisible(false);
if (map_item->paintingMode == MapPixmapItem::PaintMode::Metatiles if (map_item->paintingMode == MapPixmapItem::PaintMode::Metatiles
|| map_item->paintingMode == MapPixmapItem::PaintMode::EventObjects) { || map_item->paintingMode == MapPixmapItem::PaintMode::EventObjects) {
this->ui->statusBar->clearMessage(); this->ui->statusBar->clearMessage();
if (this->map_ruler->isAnchored()) {
this->ui->statusBar->showMessage(this->map_ruler->statusMessage);
}
} }
} }
@ -1005,6 +1023,8 @@ bool Editor::setMap(QString map_name) {
if (!displayMap()) { if (!displayMap()) {
return false; return false;
} }
map_ruler->setMapDimensions(QSize(map->getWidth(), map->getHeight()));
connect(map, &Map::mapDimensionsChanged, map_ruler, &MapRuler::setMapDimensions);
updateSelectedEvents(); updateSelectedEvents();
} }
@ -1012,17 +1032,15 @@ bool Editor::setMap(QString map_name) {
} }
void Editor::onMapStartPaint(QGraphicsSceneMouseEvent *event, MapPixmapItem *item) { void Editor::onMapStartPaint(QGraphicsSceneMouseEvent *event, MapPixmapItem *item) {
if (!(item->paintingMode == MapPixmapItem::PaintMode::Metatiles)) { if (item->paintingMode != MapPixmapItem::PaintMode::Metatiles) {
return; return;
} }
QPointF pos = event->pos(); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int x = static_cast<int>(pos.x()) / 16;
int y = static_cast<int>(pos.y()) / 16;
if (event->buttons() & Qt::RightButton && (map_edit_mode == "paint" || map_edit_mode == "fill")) { if (event->buttons() & Qt::RightButton && (map_edit_mode == "paint" || map_edit_mode == "fill")) {
this->cursorMapTileRect->initRightClickSelectionAnchor(x, y); this->cursorMapTileRect->initRightClickSelectionAnchor(pos.x(), pos.y());
} else { } else {
this->cursorMapTileRect->initAnchor(x, y); this->cursorMapTileRect->initAnchor(pos.x(), pos.y());
} }
} }
@ -1066,9 +1084,7 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item
return; return;
} }
QPointF pos = event->pos(); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int x = static_cast<int>(pos.x()) / 16;
int y = static_cast<int>(pos.y()) / 16;
if (item->paintingMode == MapPixmapItem::PaintMode::Metatiles) { if (item->paintingMode == MapPixmapItem::PaintMode::Metatiles) {
if (map_edit_mode == "paint") { if (map_edit_mode == "paint") {
@ -1085,8 +1101,7 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item
this->setStraightPathCursorMode(event); this->setStraightPathCursorMode(event);
if (this->cursorMapTileRect->getStraightPathMode()) { if (this->cursorMapTileRect->getStraightPathMode()) {
item->lockNondominantAxis(event); item->lockNondominantAxis(event);
x = item->adjustCoord(x, MapPixmapItem::Axis::X); pos = item->adjustCoords(pos);
y = item->adjustCoord(y, MapPixmapItem::Axis::Y);
} }
item->paint(event); item->paint(event);
} }
@ -1110,8 +1125,7 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item
this->setStraightPathCursorMode(event); this->setStraightPathCursorMode(event);
if (this->cursorMapTileRect->getStraightPathMode()) { if (this->cursorMapTileRect->getStraightPathMode()) {
item->lockNondominantAxis(event); item->lockNondominantAxis(event);
x = item->adjustCoord(x, MapPixmapItem::Axis::X); pos = item->adjustCoords(pos);
y = item->adjustCoord(y, MapPixmapItem::Axis::Y);
} }
item->shift(event); item->shift(event);
} }
@ -1135,7 +1149,7 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item
if (eventType != EventType::HealLocation) { if (eventType != EventType::HealLocation) {
DraggablePixmapItem * newEvent = addNewEvent(eventType); DraggablePixmapItem * newEvent = addNewEvent(eventType);
if (newEvent) { if (newEvent) {
newEvent->move(x, y); newEvent->move(pos.x(), pos.y());
emit objectsChanged(); emit objectsChanged();
selectMapEvent(newEvent, false); selectMapEvent(newEvent, false);
} }
@ -1152,18 +1166,18 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item
actionId++; actionId++;
} else { } else {
if (event->type() == QEvent::GraphicsSceneMousePress) { if (event->type() == QEvent::GraphicsSceneMousePress) {
selection_origin = QPoint(x, y); selection_origin = QPoint(pos.x(), pos.y());
} else if (event->type() == QEvent::GraphicsSceneMouseMove) { } else if (event->type() == QEvent::GraphicsSceneMouseMove) {
if (x != selection_origin.x() || y != selection_origin.y()) { if (pos.x() != selection_origin.x() || pos.y() != selection_origin.y()) {
int xDelta = x - selection_origin.x(); int xDelta = pos.x() - selection_origin.x();
int yDelta = y - selection_origin.y(); int yDelta = pos.y() - selection_origin.y();
QList<Event *> selectedEvents; QList<Event *> selectedEvents;
for (DraggablePixmapItem *item : getObjects()) { for (DraggablePixmapItem *item : getObjects()) {
selectedEvents.append(item->event); selectedEvents.append(item->event);
} }
selection_origin = QPoint(x, y); selection_origin = QPoint(pos.x(), pos.y());
map->editHistory.push(new EventShift(selectedEvents, xDelta, yDelta, actionId)); map->editHistory.push(new EventShift(selectedEvents, xDelta, yDelta, actionId));
} }
@ -1171,8 +1185,8 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item
} }
} }
} }
this->playerViewRect->updateLocation(x, y); this->playerViewRect->updateLocation(pos.x(), pos.y());
this->cursorMapTileRect->updateLocation(x, y); this->cursorMapTileRect->updateLocation(pos.x(), pos.y());
} }
void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item) { void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item) {
@ -1180,9 +1194,7 @@ void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixm
return; return;
} }
QPointF pos = event->pos(); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int x = static_cast<int>(pos.x()) / 16;
int y = static_cast<int>(pos.y()) / 16;
if (map_edit_mode == "paint") { if (map_edit_mode == "paint") {
if (event->buttons() & Qt::RightButton) { if (event->buttons() & Qt::RightButton) {
@ -1197,8 +1209,7 @@ void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixm
this->setStraightPathCursorMode(event); this->setStraightPathCursorMode(event);
if (this->cursorMapTileRect->getStraightPathMode()) { if (this->cursorMapTileRect->getStraightPathMode()) {
item->lockNondominantAxis(event); item->lockNondominantAxis(event);
x = item->adjustCoord(x, MapPixmapItem::Axis::X); pos = item->adjustCoords(pos);
y = item->adjustCoord(y, MapPixmapItem::Axis::Y);
} }
item->paint(event); item->paint(event);
} }
@ -1218,13 +1229,12 @@ void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixm
this->setStraightPathCursorMode(event); this->setStraightPathCursorMode(event);
if (this->cursorMapTileRect->getStraightPathMode()) { if (this->cursorMapTileRect->getStraightPathMode()) {
item->lockNondominantAxis(event); item->lockNondominantAxis(event);
x = item->adjustCoord(x, MapPixmapItem::Axis::X); pos = item->adjustCoords(pos);
y = item->adjustCoord(y, MapPixmapItem::Axis::Y);
} }
item->shift(event); item->shift(event);
} }
this->playerViewRect->updateLocation(x, y); this->playerViewRect->updateLocation(pos.x(), pos.y());
this->cursorMapTileRect->updateLocation(x, y); this->cursorMapTileRect->updateLocation(pos.x(), pos.y());
} }
bool Editor::displayMap() { bool Editor::displayMap() {
@ -1233,6 +1243,7 @@ bool Editor::displayMap() {
MapSceneEventFilter *filter = new MapSceneEventFilter(); MapSceneEventFilter *filter = new MapSceneEventFilter();
scene->installEventFilter(filter); scene->installEventFilter(filter);
connect(filter, &MapSceneEventFilter::wheelZoom, this, &Editor::onWheelZoom); connect(filter, &MapSceneEventFilter::wheelZoom, this, &Editor::onWheelZoom);
scene->installEventFilter(this->map_ruler);
} }
if (map_item && scene) { if (map_item && scene) {
@ -1240,6 +1251,7 @@ bool Editor::displayMap() {
delete map_item; delete map_item;
scene->removeItem(this->playerViewRect); scene->removeItem(this->playerViewRect);
scene->removeItem(this->cursorMapTileRect); scene->removeItem(this->cursorMapTileRect);
scene->removeItem(this->map_ruler);
} }
displayMetatileSelector(); displayMetatileSelector();
@ -1256,8 +1268,10 @@ bool Editor::displayMap() {
this->playerViewRect->setZValue(1000); this->playerViewRect->setZValue(1000);
this->cursorMapTileRect->setZValue(1001); this->cursorMapTileRect->setZValue(1001);
this->map_ruler->setZValue(1002);
scene->addItem(this->playerViewRect); scene->addItem(this->playerViewRect);
scene->addItem(this->cursorMapTileRect); scene->addItem(this->cursorMapTileRect);
scene->addItem(this->map_ruler);
if (map_item) { if (map_item) {
map_item->setVisible(false); map_item->setVisible(false);
@ -1303,8 +1317,8 @@ void Editor::displayMapMetatiles() {
this, SLOT(onMapStartPaint(QGraphicsSceneMouseEvent*,MapPixmapItem*))); this, SLOT(onMapStartPaint(QGraphicsSceneMouseEvent*,MapPixmapItem*)));
connect(map_item, SIGNAL(endPaint(QGraphicsSceneMouseEvent*,MapPixmapItem*)), connect(map_item, SIGNAL(endPaint(QGraphicsSceneMouseEvent*,MapPixmapItem*)),
this, SLOT(onMapEndPaint(QGraphicsSceneMouseEvent*,MapPixmapItem*))); this, SLOT(onMapEndPaint(QGraphicsSceneMouseEvent*,MapPixmapItem*)));
connect(map_item, SIGNAL(hoveredMapMetatileChanged(int, int)), connect(map_item, SIGNAL(hoveredMapMetatileChanged(const QPoint&)),
this, SLOT(onHoveredMapMetatileChanged(int, int))); this, SLOT(onHoveredMapMetatileChanged(const QPoint&)));
connect(map_item, SIGNAL(hoveredMapMetatileCleared()), connect(map_item, SIGNAL(hoveredMapMetatileCleared()),
this, SLOT(onHoveredMapMetatileCleared())); this, SLOT(onHoveredMapMetatileCleared()));
@ -1996,8 +2010,8 @@ void Editor::objectsView_onMousePress(QMouseEvent *event) {
if (map_item && map_item->paintingMode != MapPixmapItem::PaintMode::EventObjects) { if (map_item && map_item->paintingMode != MapPixmapItem::PaintMode::EventObjects) {
return; return;
} }
if (this->map_edit_mode == "paint" && event->buttons() & Qt::RightButton) { if (this->obj_edit_mode == "paint" && event->buttons() & Qt::RightButton) {
this->map_edit_mode = "select"; this->obj_edit_mode = "select";
this->settings->mapCursor = QCursor(); this->settings->mapCursor = QCursor();
this->cursorMapTileRect->setSingleTileMode(); this->cursorMapTileRect->setSingleTileMode();
this->ui->toolButton_Paint->setChecked(false); this->ui->toolButton_Paint->setChecked(false);

View file

@ -1356,6 +1356,9 @@ void MainWindow::on_mainTabBar_tabBarClicked(int index)
if (projectConfig.getEncounterJsonActive()) if (projectConfig.getEncounterJsonActive())
editor->saveEncounterTabData(); editor->saveEncounterTabData();
} }
if (index != 1) {
editor->map_ruler->setEnabled(false);
}
} }
void MainWindow::on_actionZoom_In_triggered() { void MainWindow::on_actionZoom_In_triggered() {
@ -2212,10 +2215,15 @@ void MainWindow::on_toolButton_Shift_clicked()
void MainWindow::checkToolButtons() { void MainWindow::checkToolButtons() {
QString edit_mode; QString edit_mode;
if (ui->mainTabBar->currentIndex() == 0) if (ui->mainTabBar->currentIndex() == 0) {
edit_mode = editor->map_edit_mode; edit_mode = editor->map_edit_mode;
else } else {
edit_mode = editor->obj_edit_mode; edit_mode = editor->obj_edit_mode;
if (edit_mode == "select" && editor->map_ruler)
editor->map_ruler->setEnabled(true);
else if (editor->map_ruler)
editor->map_ruler->setEnabled(false);
}
ui->toolButton_Paint->setChecked(edit_mode == "paint"); ui->toolButton_Paint->setChecked(edit_mode == "paint");
ui->toolButton_Select->setChecked(edit_mode == "select"); ui->toolButton_Select->setChecked(edit_mode == "select");

View file

@ -1,22 +1,21 @@
#include "bordermetatilespixmapitem.h" #include "bordermetatilespixmapitem.h"
#include "imageproviders.h" #include "imageproviders.h"
#include "metatile.h"
#include "editcommands.h" #include "editcommands.h"
#include <QPainter> #include <QPainter>
void BorderMetatilesPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { void BorderMetatilesPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
QList<uint16_t> *selectedMetatiles = this->metatileSelector->getSelectedMetatiles(); QList<uint16_t> *selectedMetatiles = this->metatileSelector->getSelectedMetatiles();
QPoint selectionDimensions = this->metatileSelector->getSelectionDimensions(); QPoint selectionDimensions = this->metatileSelector->getSelectionDimensions();
QPointF pos = event->pos(); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int x = static_cast<int>(pos.x()) / 16;
int y = static_cast<int>(pos.y()) / 16;
int width = map->getBorderWidth(); int width = map->getBorderWidth();
int height = map->getBorderHeight(); int height = map->getBorderHeight();
Blockdata *oldBorder = map->layout->border->copy(); Blockdata *oldBorder = map->layout->border->copy();
for (int i = 0; i < selectionDimensions.x() && (i + x) < width; i++) { for (int i = 0; i < selectionDimensions.x() && (i + pos.x()) < width; i++) {
for (int j = 0; j < selectionDimensions.y() && (j + y) < height; j++) { for (int j = 0; j < selectionDimensions.y() && (j + pos.y()) < height; j++) {
int blockIndex = (j + y) * width + (i + x); int blockIndex = (j + pos.y()) * width + (i + pos.x());
uint16_t tile = selectedMetatiles->at(j * selectionDimensions.x() + i); uint16_t tile = selectedMetatiles->at(j * selectionDimensions.x() + i);
(*map->layout->border->blocks)[blockIndex].tile = tile; (*map->layout->border->blocks)[blockIndex].tile = tile;
} }

View file

@ -1,5 +1,6 @@
#include "collisionpixmapitem.h" #include "collisionpixmapitem.h"
#include "editcommands.h" #include "editcommands.h"
#include "metatile.h"
void CollisionPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { void CollisionPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
int x = static_cast<int>(event->pos().x()) / 16; int x = static_cast<int>(event->pos().x()) / 16;
@ -18,11 +19,9 @@ void CollisionPixmapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *) {
} }
void CollisionPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { void CollisionPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
QPointF pos = event->pos(); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int x = static_cast<int>(pos.x()) / 16; this->paint_tile_initial_x = this->straight_path_initial_x = pos.x();
int y = static_cast<int>(pos.y()) / 16; this->paint_tile_initial_y = this->straight_path_initial_y = pos.y();
this->paint_tile_initial_x = this->straight_path_initial_x = x;
this->paint_tile_initial_y = this->straight_path_initial_y = y;
emit mouseEvent(event, this); emit mouseEvent(event, this);
} }
@ -48,25 +47,22 @@ void CollisionPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
} else if (map) { } else if (map) {
Blockdata *oldCollision = map->layout->blockdata->copy(); Blockdata *oldCollision = map->layout->blockdata->copy();
QPointF pos = event->pos(); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int x = static_cast<int>(pos.x()) / 16;
int y = static_cast<int>(pos.y()) / 16;
// Set straight paths on/off and snap to the dominant axis when on // Set straight paths on/off and snap to the dominant axis when on
if (event->modifiers() & Qt::ControlModifier) { if (event->modifiers() & Qt::ControlModifier) {
this->lockNondominantAxis(event); this->lockNondominantAxis(event);
x = this->adjustCoord(x, MapPixmapItem::Axis::X); pos = this->adjustCoords(pos);
y = this->adjustCoord(y, MapPixmapItem::Axis::Y);
} else { } else {
this->prevStraightPathState = false; this->prevStraightPathState = false;
this->lockedAxis = MapPixmapItem::Axis::None; this->lockedAxis = MapPixmapItem::Axis::None;
} }
Block *block = map->getBlock(x, y); Block *block = map->getBlock(pos.x(), pos.y());
if (block) { if (block) {
block->collision = this->movementPermissionsSelector->getSelectedCollision(); block->collision = this->movementPermissionsSelector->getSelectedCollision();
block->elevation = this->movementPermissionsSelector->getSelectedElevation(); block->elevation = this->movementPermissionsSelector->getSelectedElevation();
map->setBlock(x, y, *block, true); map->setBlock(pos.x(), pos.y(), *block, true);
} }
Blockdata *newCollision = map->layout->blockdata->copy(); Blockdata *newCollision = map->layout->blockdata->copy();
@ -85,12 +81,10 @@ void CollisionPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) {
} else if (map) { } else if (map) {
Blockdata *oldCollision = map->layout->blockdata->copy(); Blockdata *oldCollision = map->layout->blockdata->copy();
QPointF pos = event->pos(); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int x = static_cast<int>(pos.x()) / 16;
int y = static_cast<int>(pos.y()) / 16;
uint16_t collision = this->movementPermissionsSelector->getSelectedCollision(); uint16_t collision = this->movementPermissionsSelector->getSelectedCollision();
uint16_t elevation = this->movementPermissionsSelector->getSelectedElevation(); uint16_t elevation = this->movementPermissionsSelector->getSelectedElevation();
map->floodFillCollisionElevation(x, y, collision, elevation); map->floodFillCollisionElevation(pos.x(), pos.y(), collision, elevation);
Blockdata *newCollision = map->layout->blockdata->copy(); Blockdata *newCollision = map->layout->blockdata->copy();
if (newCollision->equals(oldCollision)) { if (newCollision->equals(oldCollision)) {
@ -107,12 +101,10 @@ void CollisionPixmapItem::magicFill(QGraphicsSceneMouseEvent *event) {
this->actionId_++; this->actionId_++;
} else if (map) { } else if (map) {
Blockdata *oldCollision = map->layout->blockdata->copy(); Blockdata *oldCollision = map->layout->blockdata->copy();
QPointF pos = event->pos(); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int x = static_cast<int>(pos.x()) / 16;
int y = static_cast<int>(pos.y()) / 16;
uint16_t collision = this->movementPermissionsSelector->getSelectedCollision(); uint16_t collision = this->movementPermissionsSelector->getSelectedCollision();
uint16_t elevation = this->movementPermissionsSelector->getSelectedElevation(); uint16_t elevation = this->movementPermissionsSelector->getSelectedElevation();
map->magicFillCollisionElevation(x, y, collision, elevation); map->magicFillCollisionElevation(pos.x(), pos.y(), collision, elevation);
Blockdata *newCollision = map->layout->blockdata->copy(); Blockdata *newCollision = map->layout->blockdata->copy();
if (newCollision->equals(oldCollision)) { if (newCollision->equals(oldCollision)) {
@ -125,26 +117,22 @@ void CollisionPixmapItem::magicFill(QGraphicsSceneMouseEvent *event) {
} }
void CollisionPixmapItem::pick(QGraphicsSceneMouseEvent *event) { void CollisionPixmapItem::pick(QGraphicsSceneMouseEvent *event) {
QPointF pos = event->pos(); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int x = static_cast<int>(pos.x()) / 16; Block *block = map->getBlock(pos.x(), pos.y());
int y = static_cast<int>(pos.y()) / 16;
Block *block = map->getBlock(x, y);
if (block) { if (block) {
this->movementPermissionsSelector->select(block->collision, block->elevation); this->movementPermissionsSelector->select(block->collision, block->elevation);
} }
} }
void CollisionPixmapItem::updateMovementPermissionSelection(QGraphicsSceneMouseEvent *event) { void CollisionPixmapItem::updateMovementPermissionSelection(QGraphicsSceneMouseEvent *event) {
QPointF pos = event->pos(); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int x = static_cast<int>(pos.x()) / 16;
int y = static_cast<int>(pos.y()) / 16;
// Snap point to within map bounds. // Snap point to within map bounds.
if (x < 0) x = 0; if (pos.x() < 0) pos.setX(0);
if (x >= map->getWidth()) x = map->getWidth() - 1; if (pos.x() >= map->getWidth()) pos.setX(map->getWidth() - 1);
if (y < 0) y = 0; if (pos.y() < 0) pos.setY(0);
if (y >= map->getHeight()) y = map->getHeight() - 1; if (pos.y() >= map->getHeight()) pos.setY(map->getHeight() - 1);
Block *block = map->getBlock(x, y); Block *block = map->getBlock(pos.x(), pos.y());
this->movementPermissionsSelector->select(block->collision, block->elevation); this->movementPermissionsSelector->select(block->collision, block->elevation);
} }

View file

@ -1,8 +1,8 @@
#include "draggablepixmapitem.h" #include "draggablepixmapitem.h"
#include "editor.h" #include "editor.h"
#include "editcommands.h" #include "editcommands.h"
#include "mapruler.h"
#include "metatile.h"
static unsigned currentActionId = 0; static unsigned currentActionId = 0;
@ -58,8 +58,9 @@ void DraggablePixmapItem::bindToUserData(QComboBox *combo, QString key) {
void DraggablePixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *mouse) { void DraggablePixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *mouse) {
active = true; active = true;
last_x = static_cast<int>(mouse->pos().x() + this->pos().x()) / 16; QPoint pos = Metatile::coordFromPixmapCoord(mouse->scenePos());
last_y = static_cast<int>(mouse->pos().y() + this->pos().y()) / 16; last_x = pos.x();
last_y = pos.y();
this->editor->selectMapEvent(this, mouse->modifiers() & Qt::ControlModifier); this->editor->selectMapEvent(this, mouse->modifiers() & Qt::ControlModifier);
this->editor->selectingEvent = true; this->editor->selectingEvent = true;
} }
@ -73,10 +74,9 @@ void DraggablePixmapItem::move(int x, int y) {
void DraggablePixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *mouse) { void DraggablePixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *mouse) {
if (active) { if (active) {
int x = static_cast<int>(mouse->pos().x() + this->pos().x()) / 16; QPoint pos = Metatile::coordFromPixmapCoord(mouse->scenePos());
int y = static_cast<int>(mouse->pos().y() + this->pos().y()) / 16; emit this->editor->map_item->hoveredMapMetatileChanged(pos);
emit this->editor->map_item->hoveredMapMetatileChanged(x, y); if (pos.x() != last_x || pos.y() != last_y) {
if (x != last_x || y != last_y) {
QList <Event *> selectedEvents; QList <Event *> selectedEvents;
if (editor->selected_events->contains(this)) { if (editor->selected_events->contains(this)) {
for (DraggablePixmapItem *item : *editor->selected_events) { for (DraggablePixmapItem *item : *editor->selected_events) {
@ -85,9 +85,9 @@ void DraggablePixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *mouse) {
} else { } else {
selectedEvents.append(this->event); selectedEvents.append(this->event);
} }
editor->map->editHistory.push(new EventMove(selectedEvents, x - last_x, y - last_y, currentActionId)); editor->map->editHistory.push(new EventMove(selectedEvents, pos.x() - last_x, pos.y() - last_y, currentActionId));
last_x = x; last_x = pos.x();
last_y = y; last_y = pos.y();
} }
} }
} }

View file

@ -1,4 +1,5 @@
#include "mappixmapitem.h" #include "mappixmapitem.h"
#include "metatile.h"
#include "log.h" #include "log.h"
#include "editcommands.h" #include "editcommands.h"
@ -10,15 +11,12 @@ void MapPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
if (event->type() == QEvent::GraphicsSceneMouseRelease) { if (event->type() == QEvent::GraphicsSceneMouseRelease) {
actionId_++; actionId_++;
} else { } else {
QPointF pos = event->pos(); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int x = static_cast<int>(pos.x()) / 16;
int y = static_cast<int>(pos.y()) / 16;
// Set straight paths on/off and snap to the dominant axis when on // Set straight paths on/off and snap to the dominant axis when on
if (event->modifiers() & Qt::ControlModifier) { if (event->modifiers() & Qt::ControlModifier) {
this->lockNondominantAxis(event); this->lockNondominantAxis(event);
x = this->adjustCoord(x, MapPixmapItem::Axis::X); pos = this->adjustCoords(pos);
y = this->adjustCoord(y, MapPixmapItem::Axis::Y);
} else { } else {
this->prevStraightPathState = false; this->prevStraightPathState = false;
this->lockedAxis = MapPixmapItem::Axis::None; this->lockedAxis = MapPixmapItem::Axis::None;
@ -29,15 +27,15 @@ void MapPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
QPoint selectionDimensions = this->metatileSelector->getSelectionDimensions(); QPoint selectionDimensions = this->metatileSelector->getSelectionDimensions();
if (settings->smartPathsEnabled) { if (settings->smartPathsEnabled) {
if (!shiftPressed && selectionDimensions.x() == 3 && selectionDimensions.y() == 3) { if (!shiftPressed && selectionDimensions.x() == 3 && selectionDimensions.y() == 3) {
paintSmartPath(x, y); paintSmartPath(pos.x(), pos.y());
} else { } else {
paintNormal(x, y); paintNormal(pos.x(), pos.y());
} }
} else { } else {
if (shiftPressed && selectionDimensions.x() == 3 && selectionDimensions.y() == 3) { if (shiftPressed && selectionDimensions.x() == 3 && selectionDimensions.y() == 3) {
paintSmartPath(x, y); paintSmartPath(pos.x(), pos.y());
} else { } else {
paintNormal(x, y); paintNormal(pos.x(), pos.y());
} }
} }
} }
@ -49,29 +47,26 @@ void MapPixmapItem::shift(QGraphicsSceneMouseEvent *event) {
if (event->type() == QEvent::GraphicsSceneMouseRelease) { if (event->type() == QEvent::GraphicsSceneMouseRelease) {
actionId_++; actionId_++;
} else { } else {
QPointF pos = event->pos(); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int x = static_cast<int>(pos.x()) / 16;
int y = static_cast<int>(pos.y()) / 16;
// Set straight paths on/off and snap to the dominant axis when on // Set straight paths on/off and snap to the dominant axis when on
if (event->modifiers() & Qt::ControlModifier) { if (event->modifiers() & Qt::ControlModifier) {
this->lockNondominantAxis(event); this->lockNondominantAxis(event);
x = this->adjustCoord(x, MapPixmapItem::Axis::X); pos = this->adjustCoords(pos);
y = this->adjustCoord(y, MapPixmapItem::Axis::Y);
} else { } else {
this->prevStraightPathState = false; this->prevStraightPathState = false;
this->lockedAxis = MapPixmapItem::Axis::None; this->lockedAxis = MapPixmapItem::Axis::None;
} }
if (event->type() == QEvent::GraphicsSceneMousePress) { if (event->type() == QEvent::GraphicsSceneMousePress) {
selection_origin = QPoint(x, y); selection_origin = QPoint(pos.x(), pos.y());
selection.clear(); selection.clear();
} else if (event->type() == QEvent::GraphicsSceneMouseMove) { } else if (event->type() == QEvent::GraphicsSceneMouseMove) {
if (x != selection_origin.x() || y != selection_origin.y()) { if (pos.x() != selection_origin.x() || pos.y() != selection_origin.y()) {
int xDelta = x - selection_origin.x(); int xDelta = pos.x() - selection_origin.x();
int yDelta = y - selection_origin.y(); int yDelta = pos.y() - selection_origin.y();
this->shift(xDelta, yDelta); this->shift(xDelta, yDelta);
selection_origin = QPoint(x, y); selection_origin = QPoint(pos.x(), pos.y());
selection.clear(); selection.clear();
draw(); draw();
} }
@ -286,18 +281,16 @@ void MapPixmapItem::lockNondominantAxis(QGraphicsSceneMouseEvent *event) {
if (this->lockedAxis != MapPixmapItem::Axis::None || event->type() == QEvent::GraphicsSceneMouseRelease) if (this->lockedAxis != MapPixmapItem::Axis::None || event->type() == QEvent::GraphicsSceneMouseRelease)
return; return;
QPointF pos = event->pos(); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int x = static_cast<int>(pos.x()) / 16;
int y = static_cast<int>(pos.y()) / 16;
if (!this->prevStraightPathState) { if (!this->prevStraightPathState) {
this->prevStraightPathState = true; this->prevStraightPathState = true;
this->straight_path_initial_x = x; this->straight_path_initial_x = pos.x();
this->straight_path_initial_y = y; this->straight_path_initial_y = pos.y();
} }
// Only lock an axis when the current position != initial // Only lock an axis when the current position != initial
int xDiff = x - this->straight_path_initial_x; int xDiff = pos.x() - this->straight_path_initial_x;
int yDiff = y - this->straight_path_initial_y; int yDiff = pos.y() - this->straight_path_initial_y;
if (xDiff || yDiff) { if (xDiff || yDiff) {
if (abs(xDiff) < abs(yDiff)) { if (abs(xDiff) < abs(yDiff)) {
this->lockedAxis = MapPixmapItem::Axis::X; this->lockedAxis = MapPixmapItem::Axis::X;
@ -308,38 +301,36 @@ void MapPixmapItem::lockNondominantAxis(QGraphicsSceneMouseEvent *event) {
} }
// Adjust the cooresponding coordinate when it is locked // Adjust the cooresponding coordinate when it is locked
int MapPixmapItem::adjustCoord(int coord, MapPixmapItem::Axis axis) { QPoint MapPixmapItem::adjustCoords(QPoint pos) {
if (axis == MapPixmapItem::Axis::X && this->lockedAxis == MapPixmapItem::Axis::X) { if (this->lockedAxis == MapPixmapItem::Axis::X) {
coord = this->straight_path_initial_x; pos.setX(this->straight_path_initial_x);
} else if (axis == MapPixmapItem::Axis::Y && this->lockedAxis == MapPixmapItem::Axis::Y) { } else if (this->lockedAxis == MapPixmapItem::Axis::Y) {
coord = this->straight_path_initial_y; pos.setY(this->straight_path_initial_y);
} }
return coord; return pos;
} }
void MapPixmapItem::updateMetatileSelection(QGraphicsSceneMouseEvent *event) { void MapPixmapItem::updateMetatileSelection(QGraphicsSceneMouseEvent *event) {
QPointF pos = event->pos(); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int x = static_cast<int>(pos.x()) / 16;
int y = static_cast<int>(pos.y()) / 16;
// Snap point to within map bounds. // Snap point to within map bounds.
if (x < 0) x = 0; if (pos.x() < 0) pos.setX(0);
if (x >= map->getWidth()) x = map->getWidth() - 1; if (pos.x() >= map->getWidth()) pos.setX(map->getWidth() - 1);
if (y < 0) y = 0; if (pos.y() < 0) pos.setY(0);
if (y >= map->getHeight()) y = map->getHeight() - 1; if (pos.y() >= map->getHeight()) pos.setY(map->getHeight() - 1);
// Update/apply copied metatiles. // Update/apply copied metatiles.
if (event->type() == QEvent::GraphicsSceneMousePress) { if (event->type() == QEvent::GraphicsSceneMousePress) {
selection_origin = QPoint(x, y); selection_origin = QPoint(pos.x(), pos.y());
selection.clear(); selection.clear();
selection.append(QPoint(x, y)); selection.append(QPoint(pos.x(), pos.y()));
Block *block = map->getBlock(x, y); Block *block = map->getBlock(pos.x(), pos.y());
this->metatileSelector->selectFromMap(block->tile, block->collision, block->elevation); this->metatileSelector->selectFromMap(block->tile, block->collision, block->elevation);
} else if (event->type() == QEvent::GraphicsSceneMouseMove) { } else if (event->type() == QEvent::GraphicsSceneMouseMove) {
int x1 = selection_origin.x(); int x1 = selection_origin.x();
int y1 = selection_origin.y(); int y1 = selection_origin.y();
int x2 = x; int x2 = pos.x();
int y2 = y; int y2 = pos.y();
if (x1 > x2) SWAP(x1, x2); if (x1 > x2) SWAP(x1, x2);
if (y1 > y2) SWAP(y1, y2); if (y1 > y2) SWAP(y1, y2);
selection.clear(); selection.clear();
@ -369,19 +360,17 @@ void MapPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) {
if (event->type() == QEvent::GraphicsSceneMouseRelease) { if (event->type() == QEvent::GraphicsSceneMouseRelease) {
actionId_++; actionId_++;
} else { } else {
QPointF pos = event->pos(); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int x = static_cast<int>(pos.x()) / 16; Block *block = map->getBlock(pos.x(), pos.y());
int y = static_cast<int>(pos.y()) / 16;
Block *block = map->getBlock(x, y);
QList<uint16_t> *selectedMetatiles = this->metatileSelector->getSelectedMetatiles(); QList<uint16_t> *selectedMetatiles = this->metatileSelector->getSelectedMetatiles();
QPoint selectionDimensions = this->metatileSelector->getSelectionDimensions(); QPoint selectionDimensions = this->metatileSelector->getSelectionDimensions();
int tile = selectedMetatiles->first(); int tile = selectedMetatiles->first();
if (selectedMetatiles->count() > 1 || (block && block->tile != tile)) { if (selectedMetatiles->count() > 1 || (block && block->tile != tile)) {
bool smartPathsEnabled = event->modifiers() & Qt::ShiftModifier; bool smartPathsEnabled = event->modifiers() & Qt::ShiftModifier;
if ((this->settings->smartPathsEnabled || smartPathsEnabled) && selectionDimensions.x() == 3 && selectionDimensions.y() == 3) if ((this->settings->smartPathsEnabled || smartPathsEnabled) && selectionDimensions.x() == 3 && selectionDimensions.y() == 3)
this->floodFillSmartPath(x, y); this->floodFillSmartPath(pos.x(), pos.y());
else else
this->floodFill(x, y); this->floodFill(pos.x(), pos.y());
} }
} }
} }
@ -392,10 +381,8 @@ void MapPixmapItem::magicFill(QGraphicsSceneMouseEvent *event) {
if (event->type() == QEvent::GraphicsSceneMouseRelease) { if (event->type() == QEvent::GraphicsSceneMouseRelease) {
actionId_++; actionId_++;
} else { } else {
QPointF pos = event->pos(); QPoint initialPos = Metatile::coordFromPixmapCoord(event->pos());
int initialX = static_cast<int>(pos.x()) / 16; this->magicFill(initialPos.x(), initialPos.y());
int initialY = static_cast<int>(pos.y()) / 16;
this->magicFill(initialX, initialY);
} }
} }
} }
@ -691,26 +678,22 @@ void MapPixmapItem::floodFillSmartPath(int initialX, int initialY, bool fromScri
} }
void MapPixmapItem::pick(QGraphicsSceneMouseEvent *event) { void MapPixmapItem::pick(QGraphicsSceneMouseEvent *event) {
QPointF pos = event->pos(); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int x = static_cast<int>(pos.x()) / 16; Block *block = map->getBlock(pos.x(), pos.y());
int y = static_cast<int>(pos.y()) / 16;
Block *block = map->getBlock(x, y);
if (block) { if (block) {
this->metatileSelector->selectFromMap(block->tile, block->collision, block->elevation); this->metatileSelector->selectFromMap(block->tile, block->collision, block->elevation);
} }
} }
void MapPixmapItem::select(QGraphicsSceneMouseEvent *event) { void MapPixmapItem::select(QGraphicsSceneMouseEvent *event) {
QPointF pos = event->pos(); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int x = static_cast<int>(pos.x()) / 16;
int y = static_cast<int>(pos.y()) / 16;
if (event->type() == QEvent::GraphicsSceneMousePress) { if (event->type() == QEvent::GraphicsSceneMousePress) {
selection_origin = QPoint(x, y); selection_origin = QPoint(pos.x(), pos.y());
selection.clear(); selection.clear();
} else if (event->type() == QEvent::GraphicsSceneMouseMove) { } else if (event->type() == QEvent::GraphicsSceneMouseMove) {
if (event->buttons() & Qt::LeftButton) { if (event->buttons() & Qt::LeftButton) {
selection.clear(); selection.clear();
selection.append(QPoint(x, y)); selection.append(QPoint(pos.x(), pos.y()));
} }
} else if (event->type() == QEvent::GraphicsSceneMouseRelease) { } else if (event->type() == QEvent::GraphicsSceneMouseRelease) {
if (!selection.isEmpty()) { if (!selection.isEmpty()) {
@ -740,9 +723,8 @@ void MapPixmapItem::draw(bool ignoreCache) {
} }
void MapPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { void MapPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
int x = static_cast<int>(event->pos().x()) / 16; QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int y = static_cast<int>(event->pos().y()) / 16; emit this->hoveredMapMetatileChanged(pos);
emit this->hoveredMapMetatileChanged(x, y);
if (this->settings->betterCursors && this->paintingMode != MapPixmapItem::PaintMode::Disabled) { if (this->settings->betterCursors && this->paintingMode != MapPixmapItem::PaintMode::Disabled) {
setCursor(this->settings->mapCursor); setCursor(this->settings->mapCursor);
} }
@ -758,18 +740,15 @@ void MapPixmapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *) {
this->has_mouse = false; this->has_mouse = false;
} }
void MapPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { void MapPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
QPointF pos = event->pos(); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int x = static_cast<int>(pos.x()) / 16; this->paint_tile_initial_x = this->straight_path_initial_x = pos.x();
int y = static_cast<int>(pos.y()) / 16; this->paint_tile_initial_y = this->straight_path_initial_y = pos.y();
this->paint_tile_initial_x = this->straight_path_initial_x = x;
this->paint_tile_initial_y = this->straight_path_initial_y = y;
emit startPaint(event, this); emit startPaint(event, this);
emit mouseEvent(event, this); emit mouseEvent(event, this);
} }
void MapPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { void MapPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
int x = static_cast<int>(event->pos().x()) / 16; QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int y = static_cast<int>(event->pos().y()) / 16; emit this->hoveredMapMetatileChanged(pos);
emit this->hoveredMapMetatileChanged(x, y);
emit mouseEvent(event, this); emit mouseEvent(event, this);
} }
void MapPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { void MapPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {

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

@ -0,0 +1,189 @@
#include "mapruler.h"
#include "metatile.h"
#include <QGraphicsObject>
#include <QGraphicsSceneEvent>
#include <QPainter>
#include <QColor>
#include <QToolTip>
int MapRuler::thickness = 3;
void MapRuler::init() {
setVisible(false);
setPoints(QPoint(), QPoint());
anchored = false;
locked = false;
statusMessage = QString("Ruler: 0");
xRuler = QRect();
yRuler = QRect();
cornerTick = QLine();
}
QRectF MapRuler::boundingRect() const {
return QRectF(-thickness, -thickness, pixWidth() + thickness * 2, pixHeight() + thickness * 2);
}
QPainterPath MapRuler::shape() const {
QPainterPath ruler;
ruler.setFillRule(Qt::WindingFill);
ruler.addRect(xRuler);
ruler.addRect(yRuler);
ruler = ruler.simplified();
for (int x = 17.5; x < pixWidth(); x += 16)
ruler.addRect(x, xRuler.y(), 0, thickness);
for (int y = 17.5; y < pixHeight(); y += 16)
ruler.addRect(yRuler.x(), y, thickness, 0);
return ruler;
}
void MapRuler::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) {
painter->setPen(QPen(borderColor));
painter->setBrush(QBrush(innerColor));
painter->drawPath(shape());
if (deltaX() && deltaY())
painter->drawLine(cornerTick);
}
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);
if (mouse_event->button() == Qt::RightButton || anchored) {
mouseEvent(mouse_event);
event->accept();
return true;
}
}
return false;
}
void MapRuler::mouseEvent(QGraphicsSceneMouseEvent *event) {
if (!anchored && event->button() == Qt::RightButton) {
setAnchor(event->scenePos(), event->screenPos());
} else if (anchored) {
if (event->button() == Qt::LeftButton)
locked = !locked;
if (event->button() == Qt::RightButton)
endAnchor();
else
setEndPos(event->scenePos(), event->screenPos());
}
}
void MapRuler::setMapDimensions(const QSize &size) {
mapSize = size;
init();
}
void MapRuler::setEnabled(bool enabled) {
QGraphicsItem::setEnabled(enabled);
if (!enabled && anchored)
endAnchor();
}
QPoint MapRuler::snapToWithinBounds(QPoint pos) const {
if (pos.x() < 0)
pos.setX(0);
if (pos.y() < 0)
pos.setY(0);
if (pos.x() >= mapSize.width())
pos.setX(mapSize.width() - 1);
if (pos.y() >= mapSize.height())
pos.setY(mapSize.height() - 1);
return pos;
}
void MapRuler::setAnchor(const QPointF &scenePos, const QPoint &screenPos) {
QPoint pos = Metatile::coordFromPixmapCoord(scenePos);
pos = snapToWithinBounds(pos);
anchored = true;
locked = false;
setPoints(pos, pos);
updateGeometry();
setVisible(true);
showDimensions(screenPos);
}
void MapRuler::endAnchor() {
emit deactivated(endPos());
hideDimensions();
prepareGeometryChange();
init();
}
void MapRuler::setEndPos(const QPointF &scenePos, const QPoint &screenPos) {
if (locked)
return;
QPoint pos = Metatile::coordFromPixmapCoord(scenePos);
pos = snapToWithinBounds(pos);
const QPoint lastEndPos = endPos();
setP2(pos);
if (pos != lastEndPos)
updateGeometry();
showDimensions(screenPos);
}
void MapRuler::showDimensions(const QPoint &screenPos) const {
// This is a hack to make the tool tip follow the cursor since it won't change position if the text is the same.
QToolTip::showText(screenPos + QPoint(16, -8), statusMessage + ' ');
QToolTip::showText(screenPos + QPoint(16, -8), statusMessage);
}
void MapRuler::hideDimensions() const {
QToolTip::hideText();
}
void MapRuler::updateGeometry() {
prepareGeometryChange();
setPos(QPoint(left() * 16 + 7, top() * 16 + 7));
/* 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)
* 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);
cornerTick = QLineF(yRuler.x() + 0.5, xRuler.y() + thickness - 0.5, yRuler.x() + thickness, xRuler.y());
statusMessage = QString("Ruler: Left %1, Up %2").arg(width()).arg(height());
} else if (deltaX() < 0) {
// Bottom-left
xRuler = QRect(0, 0, pixWidth() + thickness, thickness);
yRuler = QRect(0, 0, thickness, pixHeight() + thickness);
cornerTick = QLineF(xRuler.x() + 0.5, xRuler.y() + 0.5, xRuler.x() + thickness, xRuler.y() + thickness);
statusMessage = QString("Ruler: Left %1").arg(width());
if (deltaY())
statusMessage += QString(", Down %1").arg(height());
} 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);
statusMessage = QString("Ruler: ");
if (deltaX())
statusMessage += QString("Right %1, ").arg(width());
statusMessage += QString("Up %1").arg(height());
} 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);
statusMessage = QString("Ruler: ");
if (deltaX() || deltaY()) {
if (deltaX())
statusMessage += QString("Right %1").arg(width());
if (deltaY()) {
if (deltaX())
statusMessage += ", ";
statusMessage += QString("Down: %1").arg(height());
}
} else {
statusMessage += QString("0");
}
}
emit lengthChanged();
}