Skip to content

Commit

Permalink
Fixed "Offset Map" action to offset all objects when choosing "Whole …
Browse files Browse the repository at this point in the history
…Map" as bounds

Also take into account tile object size and alignment when determining
whether an object is within the area to offset.
  • Loading branch information
bjorn committed Jun 7, 2023
1 parent 7322755 commit 6b66aa4
Show file tree
Hide file tree
Showing 11 changed files with 36 additions and 41 deletions.
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Fixed object preview position with parallax factor on group layer (#3669)
* Fixed hover highlight rendering with active parallax factor (#3669)
* Fixed updating of object selection outlines when changing parallax factor (#3669)
* Fixed "Offset Map" action to offset all objects when choosing "Whole Map" as bounds
* AppImage: Updated to Sentry 0.6.3
* Qt 6: Increased the image allocation limit from 1 GB to 4 GB (#3616)

Expand Down
33 changes: 11 additions & 22 deletions src/libtiled/mapobject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,35 +117,24 @@ void MapObject::setTextData(const TextData &textData)
mTextData = textData;
}

static void align(QRectF &r, Alignment alignment)
{
r.translate(-alignmentOffset(r.size(), alignment));
}

/**
* Shortcut to getting a QRectF from position() and size() that uses cell tile
* if present.
*
* \deprecated See problems in comment.
* \deprecated See problems in comment. Try to use \a screenBounds instead.
*/
QRectF MapObject::boundsUseTile() const
{
// FIXME: This is outdated code:
// * It does not take into account that a tile object can be scaled.
// * It neglects that origin is not the same in orthogonal and isometric
// maps (see MapObject::alignment).
// * It does not deal with rotation.

if (const Tile *tile = mCell.tile()) {
// Using the tile for determining boundary
// Note the position given is the bottom-left corner so correct for that
return QRectF(QPointF(mPos.x(),
mPos.y() - tile->height()),
tile->size());
}

// No tile so just use regular bounds
return bounds();
}

static void align(QRectF &r, Alignment alignment)
{
r.translate(-alignmentOffset(r.size(), alignment));
// FIXME: This does not deal with tile offset, rotation, isometric
// projection and polygons.
QRectF b = bounds();
align(b, alignment());
return b;
}

/**
Expand Down
11 changes: 5 additions & 6 deletions src/libtiled/objectgroup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,26 +158,25 @@ void ObjectGroup::replaceReferencesToTileset(Tileset *oldTileset,

void ObjectGroup::offsetObjects(const QPointF &offset,
const QRectF &bounds,
bool wholeMap,
bool wrapX, bool wrapY)
{
if (offset.isNull())
return;

const bool boundsValid = bounds.isValid();

for (MapObject *object : std::as_const(mObjects)) {
const QPointF objectCenter = object->bounds().center();
if (boundsValid && !bounds.contains(objectCenter))
const QPointF objectCenter = object->boundsUseTile().center();
if (!wholeMap && !bounds.contains(objectCenter))
continue;

QPointF newCenter(objectCenter + offset);

if (wrapX && boundsValid) {
if (wrapX && bounds.width() > 0) {
qreal nx = std::fmod(newCenter.x() - bounds.left(), bounds.width());
newCenter.setX(bounds.left() + (nx < 0 ? bounds.width() + nx : nx));
}

if (wrapY && boundsValid) {
if (wrapY && bounds.height() > 0) {
qreal ny = std::fmod(newCenter.y() - bounds.top(), bounds.height());
newCenter.setY(bounds.top() + (ny < 0 ? bounds.height() + ny : ny));
}
Expand Down
1 change: 1 addition & 0 deletions src/libtiled/objectgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ class TILEDSHARED_EXPORT ObjectGroup : public Layer
* \sa TileLayer::offsetTiles()
*/
void offsetObjects(const QPointF &offset, const QRectF &bounds,
bool wholeMap,
bool wrapX, bool wrapY);

bool canMergeWith(const Layer *other) const override;
Expand Down
2 changes: 2 additions & 0 deletions src/tiled/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1908,9 +1908,11 @@ void MainWindow::offsetMap()
if (layers.empty())
return;

const bool wholeMap = offsetDialog.boundsSelection() == OffsetMapDialog::WholeMap;
mapDocument->offsetMap(layers,
offsetDialog.offset(),
offsetDialog.affectedBoundingRect(),
wholeMap,
offsetDialog.wrapX(),
offsetDialog.wrapY());
}
Expand Down
3 changes: 2 additions & 1 deletion src/tiled/mapdocument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ void MapDocument::autocropMap()
void MapDocument::offsetMap(const QList<Layer*> &layers,
const QPoint offset,
const QRect &bounds,
bool wholeMap,
bool wrapX, bool wrapY)
{
if (layers.empty())
Expand All @@ -421,7 +422,7 @@ void MapDocument::offsetMap(const QList<Layer*> &layers,
undoStack()->beginMacro(tr("Offset Map"));
for (auto layer : layers) {
undoStack()->push(new OffsetLayer(this, layer, offset,
bounds, wrapX, wrapY));
bounds, wholeMap, wrapX, wrapY));
}
undoStack()->endMacro();
}
Expand Down
1 change: 1 addition & 0 deletions src/tiled/mapdocument.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ class TILED_EDITOR_EXPORT MapDocument : public Document
void offsetMap(const QList<Layer *> &layers,
QPoint offset,
const QRect &bounds,
bool wholeMap,
bool wrapX, bool wrapY);

void flipSelectedObjects(FlipDirection direction);
Expand Down
5 changes: 2 additions & 3 deletions src/tiled/offsetlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,13 @@ OffsetLayer::OffsetLayer(MapDocument *mapDocument,
Layer *layer,
QPoint offset,
const QRect &bounds,
bool wholeMap,
bool wrapX,
bool wrapY)
: QUndoCommand(QCoreApplication::translate("Undo Commands",
"Offset Layer"))
, mMapDocument(mapDocument)
, mDone(false)
, mOriginalLayer(layer)
, mOffsetLayer(nullptr)
{
switch (mOriginalLayer->layerType()) {
case Layer::TileLayerType:
Expand All @@ -74,7 +73,7 @@ OffsetLayer::OffsetLayer(MapDocument *mapDocument,
const QRectF pixelBounds = renderer->tileToPixelCoords(bounds);

if (mOriginalLayer->layerType() == Layer::ObjectGroupType) {
static_cast<ObjectGroup*>(mOffsetLayer)->offsetObjects(pixelOffset, pixelBounds, wrapX, wrapY);
static_cast<ObjectGroup*>(mOffsetLayer)->offsetObjects(pixelOffset, pixelBounds, wholeMap, wrapX, wrapY);
} else {
// (wrapping not supported for image layers and group layers)
mOldOffset = mOriginalLayer->offset();
Expand Down
5 changes: 3 additions & 2 deletions src/tiled/offsetlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class OffsetLayer : public QUndoCommand
Layer *layer,
QPoint offset,
const QRect &bounds,
bool wholeMap,
bool xWrap,
bool yWrap);

Expand All @@ -51,9 +52,9 @@ class OffsetLayer : public QUndoCommand

private:
MapDocument *mMapDocument;
bool mDone;
bool mDone = false;
Layer *mOriginalLayer;
Layer *mOffsetLayer;
Layer *mOffsetLayer = nullptr;
QPointF mOldOffset;
QPointF mNewOffset;
};
Expand Down
2 changes: 1 addition & 1 deletion src/tiled/offsetmapdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ QRect OffsetMapDialog::affectedBoundingRect() const
switch (boundsSelection()) {
case WholeMap:
if (!mMapDocument->map()->infinite())
boundingRect = QRect(QPoint(0, 0), mMapDocument->map()->size());
boundingRect = mMapDocument->map()->tileBoundingRect();
break;
case CurrentSelectionArea: {
const QRegion &selection = mMapDocument->selectedArea();
Expand Down
13 changes: 7 additions & 6 deletions src/tiled/offsetmapdialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ class OffsetMapDialog : public QDialog
bool wrapX() const;
bool wrapY() const;

enum BoundsSelection {
WholeMap,
CurrentSelectionArea
};

BoundsSelection boundsSelection() const;

private:
void boundsSelectionChanged();

Expand All @@ -58,14 +65,8 @@ class OffsetMapDialog : public QDialog
SelectedLayers
};

enum BoundsSelection {
WholeMap,
CurrentSelectionArea
};

LayerSelection layerSelection() const;

BoundsSelection boundsSelection() const;
void setBoundsSelection(BoundsSelection boundsSelection);

Ui::OffsetMapDialog *mUi;
Expand Down

0 comments on commit 6b66aa4

Please sign in to comment.