From fb65a96c1c3806c73944b414e9edd8a934f64b0f Mon Sep 17 00:00:00 2001 From: Robert Maupin <34535+Chase-san@users.noreply.github.com> Date: Tue, 4 Oct 2022 21:48:27 -0400 Subject: [PATCH 1/7] Add tile draw offset --- src/libtiled/mapreader.cpp | 9 +++++++++ src/libtiled/mapwriter.cpp | 5 +++++ src/libtiled/tile.cpp | 23 +++++++++++++++++++++-- src/libtiled/tile.h | 3 +++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/libtiled/mapreader.cpp b/src/libtiled/mapreader.cpp index 6dbb9c0ce1..73e2c35240 100644 --- a/src/libtiled/mapreader.cpp +++ b/src/libtiled/mapreader.cpp @@ -537,6 +537,15 @@ void MapReaderPrivate::readTilesetTile(Tileset &tileset) if (!probability.isEmpty()) tile->setProbability(probability.toDouble()); + // Read local tile offset + const auto drawOffsetX = atts.value(QLatin1String("drawx")); + const auto drawOffsetY = atts.value(QLatin1String("drawy")); + if(!drawOffsetX.isEmpty() || !drawOffsetY.isEmpty()) { + //toInt() defaults to 0 if conversion fails, which is exactly what we want + QPoint drawOffset(drawOffsetX.toInt(), drawOffsetY.toInt()); + tile->setDrawOffset(drawOffset); + } + while (xml.readNextStartElement()) { if (xml.name() == QLatin1String("properties")) { tile->mergeProperties(readProperties()); diff --git a/src/libtiled/mapwriter.cpp b/src/libtiled/mapwriter.cpp index 1aa13aaa9e..4407ae2903 100644 --- a/src/libtiled/mapwriter.cpp +++ b/src/libtiled/mapwriter.cpp @@ -452,6 +452,11 @@ void MapWriterPrivate::writeTileset(QXmlStreamWriter &w, const Tileset &tileset, } if (tile->probability() != 1.0) w.writeAttribute(QStringLiteral("probability"), QString::number(tile->probability())); + const QPoint &localOffset = tile->drawOffset(); + if (localOffset.x() != 0) + w.writeAttribute(QStringLiteral("drawx"), QString::number(localOffset.x())); + if (localOffset.y() != 0) + w.writeAttribute(QStringLiteral("drawy"), QString::number(localOffset.y())); if (!tile->properties().isEmpty()) writeProperties(w, tile->properties()); if (isCollection) { diff --git a/src/libtiled/tile.cpp b/src/libtiled/tile.cpp index 3f81b097ba..0e918f1efc 100644 --- a/src/libtiled/tile.cpp +++ b/src/libtiled/tile.cpp @@ -41,6 +41,7 @@ Tile::Tile(int id, Tileset *tileset): mTileset(tileset), mImageStatus(LoadingReady), mProbability(1.0), + mDrawOffset(0, 0), mCurrentFrameIndex(0), mUnusedTime(0) {} @@ -52,6 +53,7 @@ Tile::Tile(const QPixmap &image, int id, Tileset *tileset): mImage(image), mImageStatus(image.isNull() ? LoadingError : LoadingReady), mProbability(1.0), + mDrawOffset(0, 0), mCurrentFrameIndex(0), mUnusedTime(0) {} @@ -150,11 +152,28 @@ void Tile::setImageRect(const QRect &imageRect) } /** - * Returns the drawing offset of the tile (in pixels). + * Returns the total drawing offset of the tile (in pixels). */ QPoint Tile::offset() const { - return mTileset->tileOffset(); + return mTileset->tileOffset() + this->mDrawOffset; +} + +/** + * Returns the local draw offset of the tile (in pixels). + */ +const QPoint &Tile::drawOffset() const +{ + return this->mDrawOffset; +} + +/** + * Sets the local draw offset of the tile (in pixels). + */ +void Tile::setDrawOffset(QPoint &offset) +{ + this->mDrawOffset.setX(offset.x()); + this->mDrawOffset.setY(offset.y()); } /** diff --git a/src/libtiled/tile.h b/src/libtiled/tile.h index 9c7556317f..907918d79d 100644 --- a/src/libtiled/tile.h +++ b/src/libtiled/tile.h @@ -90,6 +90,8 @@ class TILEDSHARED_EXPORT Tile : public Object QSize size() const; QPoint offset() const; + const QPoint &drawOffset() const; + void setDrawOffset(QPoint &offset); // For Python API compatibility const QString &type() const { return className(); } @@ -124,6 +126,7 @@ class TILEDSHARED_EXPORT Tile : public Object LoadingStatus mImageStatus; qreal mProbability; std::unique_ptr mObjectGroup; + QPoint mDrawOffset; QVector mFrames; int mCurrentFrameIndex; From e8242f7e68d1d5d402e0401daeaf07e4b6a29d40 Mon Sep 17 00:00:00 2001 From: Robert Maupin <34535+Chase-san@users.noreply.github.com> Date: Tue, 4 Oct 2022 22:44:09 -0400 Subject: [PATCH 2/7] Add tile draw offset property editing. --- src/libtiled/tile.cpp | 2 +- src/libtiled/tile.h | 2 +- src/tiled/changetile.cpp | 37 +++++++++++++++++++++++++++++++++++ src/tiled/changetile.h | 21 ++++++++++++++++++++ src/tiled/propertybrowser.cpp | 15 ++++++++++++++ src/tiled/propertybrowser.h | 1 + src/tiled/undocommands.h | 1 + 7 files changed, 77 insertions(+), 2 deletions(-) diff --git a/src/libtiled/tile.cpp b/src/libtiled/tile.cpp index 0e918f1efc..f6f5e4fc4c 100644 --- a/src/libtiled/tile.cpp +++ b/src/libtiled/tile.cpp @@ -170,7 +170,7 @@ const QPoint &Tile::drawOffset() const /** * Sets the local draw offset of the tile (in pixels). */ -void Tile::setDrawOffset(QPoint &offset) +void Tile::setDrawOffset(const QPoint &offset) { this->mDrawOffset.setX(offset.x()); this->mDrawOffset.setY(offset.y()); diff --git a/src/libtiled/tile.h b/src/libtiled/tile.h index 907918d79d..e40aba3d10 100644 --- a/src/libtiled/tile.h +++ b/src/libtiled/tile.h @@ -91,7 +91,7 @@ class TILEDSHARED_EXPORT Tile : public Object QPoint offset() const; const QPoint &drawOffset() const; - void setDrawOffset(QPoint &offset); + void setDrawOffset(const QPoint &offset); // For Python API compatibility const QString &type() const { return className(); } diff --git a/src/tiled/changetile.cpp b/src/tiled/changetile.cpp index d0519aef70..b48a61f0b1 100644 --- a/src/tiled/changetile.cpp +++ b/src/tiled/changetile.cpp @@ -84,4 +84,41 @@ void ChangeTileImageRect::setValue(Tile *tile, const QRect &rect) const emit mapDocument->tileImageSourceChanged(tile); } + +ChangeTileDrawOffset::ChangeTileDrawOffset(TilesetDocument *tilesetDocument, + const QList &tiles, + const QPoint &offsets, + QUndoCommand *parent) + : ChangeValue(tilesetDocument, tiles, offsets, parent) +{ + setText(QCoreApplication::translate("Undo Commands", + "Change Image Draw Offset")); +} + +ChangeTileDrawOffset::ChangeTileDrawOffset(TilesetDocument *tilesetDocument, + const QList &tiles, + const QVector &offsets, + QUndoCommand *parent) + : ChangeValue(tilesetDocument, tiles, offsets, parent) +{ + setText(QCoreApplication::translate("Undo Commands", + "Change Image Draw Offset")); +} + +QPoint ChangeTileDrawOffset::getValue(const Tile *tile) const +{ + return tile->drawOffset(); +} + +void ChangeTileDrawOffset::setValue(Tile *tile, const QPoint &offset) const +{ + tile->setDrawOffset(offset); + + //since we changed the offset we need to tell it to update any maps + emit static_cast(document())->tileImageSourceChanged(tile); + + for (MapDocument *mapDocument : static_cast(document())->mapDocuments()) + emit mapDocument->tileImageSourceChanged(tile); +} + } // namespace Tiled diff --git a/src/tiled/changetile.h b/src/tiled/changetile.h index bbebc36f7d..b1a97cff74 100644 --- a/src/tiled/changetile.h +++ b/src/tiled/changetile.h @@ -24,6 +24,7 @@ #include "undocommands.h" #include +#include namespace Tiled { @@ -66,4 +67,24 @@ class ChangeTileImageRect : public ChangeValue void setValue(Tile *tile, const QRect &rect) const override; }; +class ChangeTileDrawOffset : public ChangeValue +{ +public: + ChangeTileDrawOffset(TilesetDocument *tilesetDocument, + const QList &tiles, + const QPoint &offsets, + QUndoCommand *parent = nullptr); + + ChangeTileDrawOffset(TilesetDocument *tilesetDocument, + const QList &tiles, + const QVector &offsets, + QUndoCommand *parent = nullptr); + + int id() const override { return Cmd_ChangeTileDrawOffset; } + +protected: + QPoint getValue(const Tile *tile) const override; + void setValue(Tile *tile, const QPoint &offset) const override; +}; + } // namespace Tiled diff --git a/src/tiled/propertybrowser.cpp b/src/tiled/propertybrowser.cpp index b0a865cb0a..54b8183d28 100644 --- a/src/tiled/propertybrowser.cpp +++ b/src/tiled/propertybrowser.cpp @@ -1063,6 +1063,13 @@ void PropertyBrowser::addTileProperties() imageRectProperty->setEnabled(mTilesetDocument && tile->tileset()->isCollection()); imageRectProperty->setAttribute(QLatin1String("constraint"), tile->image().rect()); + QtVariantProperty *drawOffsetProperty = addProperty(TileDrawOffsetProperty, + QMetaType::QPoint, + tr("Draw Offset"), + groupProperty); + drawOffsetProperty->setAttribute(QLatin1String("singleStep"), 1); + drawOffsetProperty->setEnabled(mTilesetDocument); + addProperty(groupProperty); } @@ -1614,6 +1621,13 @@ void PropertyBrowser::applyTileValue(PropertyId id, const QVariant &val) tile, filePath.url)); break; } + case TileDrawOffsetProperty: { + undoStack->push(new ChangeTileDrawOffset(mTilesetDocument, + mTilesetDocument->selectedTiles(), + val.toPoint())); + + break; + } default: break; } @@ -1992,6 +2006,7 @@ void PropertyBrowser::updateProperties() if (QtVariantProperty *imageSourceProperty = mIdToProperty.value(ImageSourceProperty)) imageSourceProperty->setValue(QVariant::fromValue(FilePath { tile->imageSource() })); mIdToProperty[ImageRectProperty]->setValue(tile->imageRect()); + mIdToProperty[TileDrawOffsetProperty]->setValue(tile->drawOffset()); break; } case Object::WangSetType: { diff --git a/src/tiled/propertybrowser.h b/src/tiled/propertybrowser.h index ead7b6f2aa..06e66578dd 100644 --- a/src/tiled/propertybrowser.h +++ b/src/tiled/propertybrowser.h @@ -157,6 +157,7 @@ class PropertyBrowser : public QtTreePropertyBrowser AllowFlipVerticallyProperty, AllowRotateProperty, PreferUntransformedProperty, + TileDrawOffsetProperty, }; void addMapProperties(); diff --git a/src/tiled/undocommands.h b/src/tiled/undocommands.h index 3af2985d35..991cd1e15b 100644 --- a/src/tiled/undocommands.h +++ b/src/tiled/undocommands.h @@ -52,6 +52,7 @@ enum UndoCommands { Cmd_EraseTiles, Cmd_PaintTileLayer, Cmd_SetProperty, + Cmd_ChangeTileDrawOffset, }; /** From e9eb9598d04b1e3c856b452980ffad9a268948f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Fri, 4 Nov 2022 17:27:17 +0100 Subject: [PATCH 3/7] Renamed drawOffset to origin (and reversed its value) I think this should be more intuitive, especially when we later make this property visually editable. --- src/libtiled/mapreader.cpp | 10 +++------- src/libtiled/mapwriter.cpp | 10 +++++----- src/libtiled/tile.cpp | 29 ++++++----------------------- src/libtiled/tile.h | 23 ++++++++++++++++------- src/tiled/changetile.cpp | 28 ++++++++++++++-------------- src/tiled/changetile.h | 24 ++++++++++++------------ src/tiled/propertybrowser.cpp | 21 ++++++++++----------- src/tiled/propertybrowser.h | 2 +- src/tiled/undocommands.h | 2 +- 9 files changed, 68 insertions(+), 81 deletions(-) diff --git a/src/libtiled/mapreader.cpp b/src/libtiled/mapreader.cpp index 73e2c35240..a0009b5633 100644 --- a/src/libtiled/mapreader.cpp +++ b/src/libtiled/mapreader.cpp @@ -538,13 +538,9 @@ void MapReaderPrivate::readTilesetTile(Tileset &tileset) tile->setProbability(probability.toDouble()); // Read local tile offset - const auto drawOffsetX = atts.value(QLatin1String("drawx")); - const auto drawOffsetY = atts.value(QLatin1String("drawy")); - if(!drawOffsetX.isEmpty() || !drawOffsetY.isEmpty()) { - //toInt() defaults to 0 if conversion fails, which is exactly what we want - QPoint drawOffset(drawOffsetX.toInt(), drawOffsetY.toInt()); - tile->setDrawOffset(drawOffset); - } + const QPoint origin(atts.value(QLatin1String("originx")).toInt(), + atts.value(QLatin1String("originy")).toInt()); + tile->setOrigin(origin); while (xml.readNextStartElement()) { if (xml.name() == QLatin1String("properties")) { diff --git a/src/libtiled/mapwriter.cpp b/src/libtiled/mapwriter.cpp index 4407ae2903..f073b07f7d 100644 --- a/src/libtiled/mapwriter.cpp +++ b/src/libtiled/mapwriter.cpp @@ -452,11 +452,11 @@ void MapWriterPrivate::writeTileset(QXmlStreamWriter &w, const Tileset &tileset, } if (tile->probability() != 1.0) w.writeAttribute(QStringLiteral("probability"), QString::number(tile->probability())); - const QPoint &localOffset = tile->drawOffset(); - if (localOffset.x() != 0) - w.writeAttribute(QStringLiteral("drawx"), QString::number(localOffset.x())); - if (localOffset.y() != 0) - w.writeAttribute(QStringLiteral("drawy"), QString::number(localOffset.y())); + const QPoint origin = tile->origin(); + if (origin.x() != 0) + w.writeAttribute(QStringLiteral("originx"), QString::number(origin.x())); + if (origin.y() != 0) + w.writeAttribute(QStringLiteral("originy"), QString::number(origin.y())); if (!tile->properties().isEmpty()) writeProperties(w, tile->properties()); if (isCollection) { diff --git a/src/libtiled/tile.cpp b/src/libtiled/tile.cpp index f6f5e4fc4c..cdc94c4912 100644 --- a/src/libtiled/tile.cpp +++ b/src/libtiled/tile.cpp @@ -39,11 +39,7 @@ Tile::Tile(int id, Tileset *tileset): Object(TileType), mId(id), mTileset(tileset), - mImageStatus(LoadingReady), - mProbability(1.0), - mDrawOffset(0, 0), - mCurrentFrameIndex(0), - mUnusedTime(0) + mImageStatus(LoadingReady) {} Tile::Tile(const QPixmap &image, int id, Tileset *tileset): @@ -51,11 +47,7 @@ Tile::Tile(const QPixmap &image, int id, Tileset *tileset): mId(id), mTileset(tileset), mImage(image), - mImageStatus(image.isNull() ? LoadingError : LoadingReady), - mProbability(1.0), - mDrawOffset(0, 0), - mCurrentFrameIndex(0), - mUnusedTime(0) + mImageStatus(image.isNull() ? LoadingError : LoadingReady) {} Tile::~Tile() @@ -156,24 +148,15 @@ void Tile::setImageRect(const QRect &imageRect) */ QPoint Tile::offset() const { - return mTileset->tileOffset() + this->mDrawOffset; + return mTileset->tileOffset() - mOrigin; } /** - * Returns the local draw offset of the tile (in pixels). + * Sets the origin of this tile (in pixels). */ -const QPoint &Tile::drawOffset() const +void Tile::setOrigin(QPoint offset) { - return this->mDrawOffset; -} - -/** - * Sets the local draw offset of the tile (in pixels). - */ -void Tile::setDrawOffset(const QPoint &offset) -{ - this->mDrawOffset.setX(offset.x()); - this->mDrawOffset.setY(offset.y()); + mOrigin = offset; } /** diff --git a/src/libtiled/tile.h b/src/libtiled/tile.h index e40aba3d10..ecb97c0c61 100644 --- a/src/libtiled/tile.h +++ b/src/libtiled/tile.h @@ -90,12 +90,13 @@ class TILEDSHARED_EXPORT Tile : public Object QSize size() const; QPoint offset() const; - const QPoint &drawOffset() const; - void setDrawOffset(const QPoint &offset); + + QPoint origin() const; + void setOrigin(QPoint offset); // For Python API compatibility const QString &type() const { return className(); } - void setType(const QString &type) { setClassName(type); }; + void setType(const QString &type) { setClassName(type); } qreal probability() const; void setProbability(qreal probability); @@ -123,14 +124,14 @@ class TILEDSHARED_EXPORT Tile : public Object mutable std::optional mImageShape; // cache QUrl mImageSource; QRect mImageRect; + QPoint mOrigin; LoadingStatus mImageStatus; - qreal mProbability; + qreal mProbability = 1.0; std::unique_ptr mObjectGroup; - QPoint mDrawOffset; QVector mFrames; - int mCurrentFrameIndex; - int mUnusedTime; + int mCurrentFrameIndex = 0; + int mUnusedTime = 0; friend class Tileset; // To allow changing the tile id }; @@ -198,6 +199,14 @@ inline QSize Tile::size() const return mImageRect.size(); } +/** + * Returns the origin of the tile (in pixels). + */ +inline QPoint Tile::origin() const +{ + return mOrigin; +} + /** * Returns the relative probability of this tile appearing while painting. */ diff --git a/src/tiled/changetile.cpp b/src/tiled/changetile.cpp index b48a61f0b1..a5229b4c6d 100644 --- a/src/tiled/changetile.cpp +++ b/src/tiled/changetile.cpp @@ -85,34 +85,34 @@ void ChangeTileImageRect::setValue(Tile *tile, const QRect &rect) const } -ChangeTileDrawOffset::ChangeTileDrawOffset(TilesetDocument *tilesetDocument, - const QList &tiles, - const QPoint &offsets, - QUndoCommand *parent) - : ChangeValue(tilesetDocument, tiles, offsets, parent) +ChangeTileOrigin::ChangeTileOrigin(TilesetDocument *tilesetDocument, + const QList &tiles, + const QPoint &origins, + QUndoCommand *parent) + : ChangeValue(tilesetDocument, tiles, origins, parent) { setText(QCoreApplication::translate("Undo Commands", - "Change Image Draw Offset")); + "Change Tile Origin")); } -ChangeTileDrawOffset::ChangeTileDrawOffset(TilesetDocument *tilesetDocument, +ChangeTileOrigin::ChangeTileOrigin(TilesetDocument *tilesetDocument, const QList &tiles, - const QVector &offsets, + const QVector &origins, QUndoCommand *parent) - : ChangeValue(tilesetDocument, tiles, offsets, parent) + : ChangeValue(tilesetDocument, tiles, origins, parent) { setText(QCoreApplication::translate("Undo Commands", - "Change Image Draw Offset")); + "Change Tile Origin")); } -QPoint ChangeTileDrawOffset::getValue(const Tile *tile) const +QPoint ChangeTileOrigin::getValue(const Tile *tile) const { - return tile->drawOffset(); + return tile->origin(); } -void ChangeTileDrawOffset::setValue(Tile *tile, const QPoint &offset) const +void ChangeTileOrigin::setValue(Tile *tile, const QPoint &origin) const { - tile->setDrawOffset(offset); + tile->setOrigin(origin); //since we changed the offset we need to tell it to update any maps emit static_cast(document())->tileImageSourceChanged(tile); diff --git a/src/tiled/changetile.h b/src/tiled/changetile.h index b1a97cff74..3481afe07d 100644 --- a/src/tiled/changetile.h +++ b/src/tiled/changetile.h @@ -67,24 +67,24 @@ class ChangeTileImageRect : public ChangeValue void setValue(Tile *tile, const QRect &rect) const override; }; -class ChangeTileDrawOffset : public ChangeValue +class ChangeTileOrigin : public ChangeValue { public: - ChangeTileDrawOffset(TilesetDocument *tilesetDocument, - const QList &tiles, - const QPoint &offsets, - QUndoCommand *parent = nullptr); - - ChangeTileDrawOffset(TilesetDocument *tilesetDocument, - const QList &tiles, - const QVector &offsets, - QUndoCommand *parent = nullptr); + ChangeTileOrigin(TilesetDocument *tilesetDocument, + const QList &tiles, + const QPoint &origins, + QUndoCommand *parent = nullptr); + + ChangeTileOrigin(TilesetDocument *tilesetDocument, + const QList &tiles, + const QVector &origins, + QUndoCommand *parent = nullptr); - int id() const override { return Cmd_ChangeTileDrawOffset; } + int id() const override { return Cmd_ChangeTileOrigin; } protected: QPoint getValue(const Tile *tile) const override; - void setValue(Tile *tile, const QPoint &offset) const override; + void setValue(Tile *tile, const QPoint &origin) const override; }; } // namespace Tiled diff --git a/src/tiled/propertybrowser.cpp b/src/tiled/propertybrowser.cpp index 54b8183d28..d592060a1c 100644 --- a/src/tiled/propertybrowser.cpp +++ b/src/tiled/propertybrowser.cpp @@ -1063,12 +1063,11 @@ void PropertyBrowser::addTileProperties() imageRectProperty->setEnabled(mTilesetDocument && tile->tileset()->isCollection()); imageRectProperty->setAttribute(QLatin1String("constraint"), tile->image().rect()); - QtVariantProperty *drawOffsetProperty = addProperty(TileDrawOffsetProperty, - QMetaType::QPoint, - tr("Draw Offset"), - groupProperty); - drawOffsetProperty->setAttribute(QLatin1String("singleStep"), 1); - drawOffsetProperty->setEnabled(mTilesetDocument); + QtVariantProperty *originProperty = addProperty(TileOriginProperty, + QMetaType::QPoint, + tr("Origin"), + groupProperty); + originProperty->setEnabled(mTilesetDocument); addProperty(groupProperty); } @@ -1621,10 +1620,10 @@ void PropertyBrowser::applyTileValue(PropertyId id, const QVariant &val) tile, filePath.url)); break; } - case TileDrawOffsetProperty: { - undoStack->push(new ChangeTileDrawOffset(mTilesetDocument, - mTilesetDocument->selectedTiles(), - val.toPoint())); + case TileOriginProperty: { + undoStack->push(new ChangeTileOrigin(mTilesetDocument, + mTilesetDocument->selectedTiles(), + val.toPoint())); break; } @@ -2006,7 +2005,7 @@ void PropertyBrowser::updateProperties() if (QtVariantProperty *imageSourceProperty = mIdToProperty.value(ImageSourceProperty)) imageSourceProperty->setValue(QVariant::fromValue(FilePath { tile->imageSource() })); mIdToProperty[ImageRectProperty]->setValue(tile->imageRect()); - mIdToProperty[TileDrawOffsetProperty]->setValue(tile->drawOffset()); + mIdToProperty[TileOriginProperty]->setValue(tile->origin()); break; } case Object::WangSetType: { diff --git a/src/tiled/propertybrowser.h b/src/tiled/propertybrowser.h index 06e66578dd..fdb642842d 100644 --- a/src/tiled/propertybrowser.h +++ b/src/tiled/propertybrowser.h @@ -139,6 +139,7 @@ class PropertyBrowser : public QtTreePropertyBrowser TileRenderSizeProperty, FillModeProperty, TileOffsetProperty, + TileOriginProperty, MarginProperty, SpacingProperty, TileProbabilityProperty, @@ -157,7 +158,6 @@ class PropertyBrowser : public QtTreePropertyBrowser AllowFlipVerticallyProperty, AllowRotateProperty, PreferUntransformedProperty, - TileDrawOffsetProperty, }; void addMapProperties(); diff --git a/src/tiled/undocommands.h b/src/tiled/undocommands.h index 991cd1e15b..e5cf6b3b44 100644 --- a/src/tiled/undocommands.h +++ b/src/tiled/undocommands.h @@ -43,6 +43,7 @@ enum UndoCommands { Cmd_ChangeMapObjectTransform, Cmd_ChangeSelectedArea, Cmd_ChangeTileImageRect, + Cmd_ChangeTileOrigin, Cmd_ChangeTileProbability, Cmd_ChangeTileWangId, Cmd_ChangeTilesetName, @@ -52,7 +53,6 @@ enum UndoCommands { Cmd_EraseTiles, Cmd_PaintTileLayer, Cmd_SetProperty, - Cmd_ChangeTileDrawOffset, }; /** From 4fc57f1069bd03e7785d2db3f5d44cafc104e652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Fri, 4 Nov 2022 22:20:18 +0100 Subject: [PATCH 4/7] Fixed writing out of tile origin If a tile only had its origin customized, it would still fail to get written out. --- src/libtiled/mapwriter.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libtiled/mapwriter.cpp b/src/libtiled/mapwriter.cpp index f073b07f7d..3bf13637e2 100644 --- a/src/libtiled/mapwriter.cpp +++ b/src/libtiled/mapwriter.cpp @@ -288,6 +288,8 @@ static bool includeTile(const Tile *tile) return true; if (tile->isAnimated()) return true; + if (!tile->origin().isNull()) + return true; if (tile->probability() != 1.0) return true; From 489a859f84f9133402508490325af99c945a2ed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Thu, 23 Feb 2023 20:46:16 +0100 Subject: [PATCH 5/7] Fixed painting issues caused by tile origin The tile origin changes where the tiles are rendered, so it needs to be taken into account when calculating the draw margins. These are used when determining which area to repaint, and which tiles to render in a certain area. The draw margins are cached per map and now also per tileset. They are invalidated when the "tile offset" or a tileset is changed as well as when the "origin" of a tile is changed. --- src/libtiled/map.cpp | 19 +++++++---------- src/libtiled/mapobject.cpp | 14 ++++++------- src/libtiled/qtcompat_p.h | 8 ++++++++ src/libtiled/tile.cpp | 3 +++ src/libtiled/tiled.h | 13 ------------ src/libtiled/tilelayer.cpp | 10 +++------ src/libtiled/tileset.cpp | 32 +++++++++++++++++++++++++++++ src/libtiled/tileset.h | 13 +++++++----- src/libtiledquick/tilelayeritem.cpp | 4 ++-- src/tiled/changetile.cpp | 12 ++++++++--- src/tiled/mapobjectitem.cpp | 2 +- 11 files changed, 80 insertions(+), 50 deletions(-) diff --git a/src/libtiled/map.cpp b/src/libtiled/map.cpp index 28cb37fc11..7fa89c499e 100644 --- a/src/libtiled/map.cpp +++ b/src/libtiled/map.cpp @@ -35,11 +35,12 @@ #include "mapobject.h" #include "objectgroup.h" #include "objecttemplate.h" -#include "tile.h" #include "tilelayer.h" #include +#include "qtcompat_p.h" + using namespace Tiled; Map::Map() @@ -101,11 +102,10 @@ void Map::adjustBoundingRectForOffsetsAndImageLayers(QRect &boundingRect) const // rect. More precise would be to take into account their // contents. const QPointF offset = layer->totalOffset(); - offsetMargins = maxMargins(QMargins(qCeil(-offset.x()), - qCeil(-offset.y()), - qCeil(offset.x()), - qCeil(offset.y())), - offsetMargins); + offsetMargins = offsetMargins | QMargins(qCeil(-offset.x()), + qCeil(-offset.y()), + qCeil(offset.x()), + qCeil(offset.y())); break; } case Layer::ImageLayerType: { @@ -151,12 +151,7 @@ void Map::recomputeDrawMargins() const maxTileSize = std::max(maxTileSize, std::max(tileSize.width(), tileSize.height())); - const QPoint offset = tileset->tileOffset(); - offsetMargins = maxMargins(QMargins(-offset.x(), - -offset.y(), - offset.x(), - offset.y()), - offsetMargins); + offsetMargins = offsetMargins | tileset->drawMargins(); } // We subtract the tile size of the map, since that part does not diff --git a/src/libtiled/mapobject.cpp b/src/libtiled/mapobject.cpp index d25b5a7b76..e0ba92436b 100644 --- a/src/libtiled/mapobject.cpp +++ b/src/libtiled/mapobject.cpp @@ -267,16 +267,16 @@ Alignment MapObject::alignment(const Map *map) const if (Tileset *tileset = mCell.tileset()) alignment = tileset->objectAlignment(); - if (!map && mObjectGroup) - map = mObjectGroup->map(); - if (alignment == Unspecified) { + if (!map && mObjectGroup) + map = mObjectGroup->map(); + if (mCell.isEmpty()) - return TopLeft; + alignment = TopLeft; else if (map && map->orientation() == Map::Isometric) - return Bottom; - - return BottomLeft; + alignment = Bottom; + else + alignment = BottomLeft; } return alignment; diff --git a/src/libtiled/qtcompat_p.h b/src/libtiled/qtcompat_p.h index 3b46dc1be7..73ae65185c 100644 --- a/src/libtiled/qtcompat_p.h +++ b/src/libtiled/qtcompat_p.h @@ -30,3 +30,11 @@ using ::endl; #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) using QStringRef = QStringView; #endif + +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) +constexpr inline QMargins operator|(const QMargins &m1, const QMargins &m2) noexcept +{ + return QMargins(qMax(m1.left(), m2.left()), qMax(m1.top(), m2.top()), + qMax(m1.right(), m2.right()), qMax(m1.bottom(), m2.bottom())); +} +#endif diff --git a/src/libtiled/tile.cpp b/src/libtiled/tile.cpp index cdc94c4912..695336813e 100644 --- a/src/libtiled/tile.cpp +++ b/src/libtiled/tile.cpp @@ -157,6 +157,9 @@ QPoint Tile::offset() const void Tile::setOrigin(QPoint offset) { mOrigin = offset; + + if (mTileset) + mTileset->invalidateDrawMargins(); } /** diff --git a/src/libtiled/tiled.h b/src/libtiled/tiled.h index ea5dbaf081..17259b4f6c 100644 --- a/src/libtiled/tiled.h +++ b/src/libtiled/tiled.h @@ -112,19 +112,6 @@ inline QString colorToString(const QColor &color) return color.name(); } -inline QMargins maxMargins(const QMargins &a, - const QMargins &b) -{ -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - return QMargins(qMax(a.left(), b.left()), - qMax(a.top(), b.top()), - qMax(a.right(), b.right()), - qMax(a.bottom(), b.bottom())); -#else - return a | b; -#endif -} - TILEDSHARED_EXPORT QString alignmentToString(Alignment); TILEDSHARED_EXPORT Alignment alignmentFromString(const QString &); diff --git a/src/libtiled/tilelayer.cpp b/src/libtiled/tilelayer.cpp index e18df9a6d1..ee3164c38c 100644 --- a/src/libtiled/tilelayer.cpp +++ b/src/libtiled/tilelayer.cpp @@ -38,6 +38,8 @@ #include +#include "qtcompat_p.h" + using namespace Tiled; Cell Cell::empty; @@ -147,19 +149,13 @@ static QMargins computeDrawMargins(const QSet &tilesets) QMargins offsetMargins; for (const SharedTileset &tileset : tilesets) { - const QPoint offset = tileset->tileOffset(); - if (tileset->tileRenderSize() == Tileset::TileSize) { const QSize tileSize = tileset->tileSize(); maxTileSize = std::max(maxTileSize, std::max(tileSize.width(), tileSize.height())); } - offsetMargins = maxMargins(QMargins(-offset.x(), - -offset.y(), - offset.x(), - offset.y()), - offsetMargins); + offsetMargins = offsetMargins | tileset->drawMargins(); } // Adding maxTileSize to top-right of the margins assumes a bottom-left tile diff --git a/src/libtiled/tileset.cpp b/src/libtiled/tileset.cpp index 0193325f47..29e7488688 100644 --- a/src/libtiled/tileset.cpp +++ b/src/libtiled/tileset.cpp @@ -36,6 +36,8 @@ #include +#include "qtcompat_p.h" + namespace Tiled { Tileset::Tileset(QString name, int tileWidth, int tileHeight, @@ -103,6 +105,36 @@ void Tileset::setMargin(int margin) mMargin = margin; } +/** + * @see tileOffset + */ +void Tileset::setTileOffset(QPoint offset) +{ + if (mTileOffset == offset) + return; + + mTileOffset = offset; + mDrawMarginsDirty = true; +} + +QMargins Tileset::drawMargins() const +{ + if (mDrawMarginsDirty) { + QMargins margins; + + for (const Tile *tile : mTiles) { + const auto offset = mTileOffset - tile->origin(); + margins = margins | QMargins(-offset.x(), -offset.y(), + offset.x(), offset.y()); + } + + mDrawMargins = margins; + mDrawMarginsDirty = false; + } + + return mDrawMargins; +} + /** * Returns the location of the tile with the given ID. */ diff --git a/src/libtiled/tileset.h b/src/libtiled/tileset.h index 4e74e5ce0d..46bca264eb 100644 --- a/src/libtiled/tileset.h +++ b/src/libtiled/tileset.h @@ -162,6 +162,9 @@ class TILEDSHARED_EXPORT Tileset : public Object, public QEnableSharedFromThis mOriginalTileset; }; @@ -453,12 +459,9 @@ inline QPoint Tileset::tileOffset() const return mTileOffset; } -/** - * @see tileOffset - */ -inline void Tileset::setTileOffset(QPoint offset) +inline void Tileset::invalidateDrawMargins() { - mTileOffset = offset; + mDrawMarginsDirty = true; } /** diff --git a/src/libtiledquick/tilelayeritem.cpp b/src/libtiledquick/tilelayeritem.cpp index 5235c236b4..756414ebd8 100644 --- a/src/libtiledquick/tilelayeritem.cpp +++ b/src/libtiledquick/tilelayeritem.cpp @@ -178,8 +178,8 @@ QSGNode *TileLayerItem::updatePaintNode(QSGNode *node, // return; // } - const auto offset = tileset->tileOffset(); const auto tile = tileset->findTile(cell.tileId()); + const auto offset = tile ? tile->offset() : tileset->tileOffset(); const QSize size = (tile && !tile->image().isNull()) ? tile->size() : mRenderer->map()->tileSize(); TileData data; @@ -272,7 +272,7 @@ QSGNode *TileItem::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeDat const int tileHeight = map->tileHeight(); const QSize size = tile->size(); - const QPoint offset = tileset->tileOffset(); + const QPoint offset = tile->offset(); QVector data(1); data[0].x = mPosition.x() * tileWidth + offset.x(); diff --git a/src/tiled/changetile.cpp b/src/tiled/changetile.cpp index a5229b4c6d..9f88ad6974 100644 --- a/src/tiled/changetile.cpp +++ b/src/tiled/changetile.cpp @@ -114,10 +114,16 @@ void ChangeTileOrigin::setValue(Tile *tile, const QPoint &origin) const { tile->setOrigin(origin); - //since we changed the offset we need to tell it to update any maps - emit static_cast(document())->tileImageSourceChanged(tile); + auto tilesetDocument = static_cast(document()); - for (MapDocument *mapDocument : static_cast(document())->mapDocuments()) + // Invalidate the draw margins of the maps using this tileset + for (MapDocument *mapDocument : tilesetDocument->mapDocuments()) + mapDocument->map()->invalidateDrawMargins(); + + // Since we changed the offset we need to tell it to update any maps + emit tilesetDocument->tileImageSourceChanged(tile); + + for (MapDocument *mapDocument : tilesetDocument->mapDocuments()) emit mapDocument->tileImageSourceChanged(tile); } diff --git a/src/tiled/mapobjectitem.cpp b/src/tiled/mapobjectitem.cpp index 27fad062f3..29ba68659d 100644 --- a/src/tiled/mapobjectitem.cpp +++ b/src/tiled/mapobjectitem.cpp @@ -231,7 +231,7 @@ QTransform MapObjectItem::tileCollisionObjectsTransform(const Tile &tile) const if (mMapDocument->map()->orientation() == Map::Isometric) tileTransform.translate(-tile.width() / 2, 0.0); - tileTransform.translate(tileset->tileOffset().x(), tileset->tileOffset().y()); + tileTransform.translate(tile.offset().x(), tile.offset().y()); if (mObject->cell().flippedVertically()) { tileTransform.scale(1, -1); From f2cd5735505a8bc635a5097a942af8c8c8b1efa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Thu, 23 Feb 2023 21:30:17 +0100 Subject: [PATCH 6/7] Lua plugin: Write out the tile origin --- src/plugins/lua/luaplugin.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/plugins/lua/luaplugin.cpp b/src/plugins/lua/luaplugin.cpp index e8d53b2d37..00d7bc2f86 100644 --- a/src/plugins/lua/luaplugin.cpp +++ b/src/plugins/lua/luaplugin.cpp @@ -305,6 +305,8 @@ static bool includeTile(const Tile *tile) return true; if (tile->isAnimated()) return true; + if (!tile->origin().isNull()) + return true; if (tile->probability() != 1.0) return true; @@ -434,6 +436,14 @@ void LuaWriter::writeTileset(const Tileset &tileset, } } + const QPoint origin = tile->origin(); + if (!origin.isNull()) { + mWriter.writeStartTable("origin"); + mWriter.writeKeyAndValue("x", origin.x()); + mWriter.writeKeyAndValue("y", origin.y()); + mWriter.writeEndTable(); + } + if (tile->probability() != 1.0) mWriter.writeKeyAndValue("probability", tile->probability()); From d3860b28a7c26c8c5c13e291614f38f50bac0d58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Fri, 24 Feb 2023 15:33:30 +0100 Subject: [PATCH 7/7] Fixed copying of tile origin in Tile::clone --- src/libtiled/tile.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libtiled/tile.cpp b/src/libtiled/tile.cpp index 695336813e..fbe9755354 100644 --- a/src/libtiled/tile.cpp +++ b/src/libtiled/tile.cpp @@ -250,6 +250,7 @@ Tile *Tile::clone(Tileset *tileset) const c->mImageSource = mImageSource; c->mImageRect = mImageRect; + c->mOrigin = mOrigin; c->mImageStatus = mImageStatus; c->mProbability = mProbability;