Skip to content

Commit eba4409

Browse files
committed
Allow pixel based drawing/selection on atlas tileset
Signed-off-by: Tomas Slusny <[email protected]>
1 parent 536e9f7 commit eba4409

File tree

7 files changed

+339
-429
lines changed

7 files changed

+339
-429
lines changed

src/libtiled/tileset.cpp

Lines changed: 4 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -272,16 +272,14 @@ bool Tileset::initializeTilesetTiles()
272272
tileRects.append(QRect(x, y, mTileWidth, mTileHeight));
273273

274274
for (int tileNum = 0; tileNum < tileRects.size(); ++tileNum) {
275-
QRect rect = tileRects.at(tileNum);
276-
const int tileId = tileNum;
277-
auto it = mTilesById.find(tileId);
275+
auto it = mTilesById.find(tileNum);
278276
if (it != mTilesById.end()) {
279277
it.value()->setImage(QPixmap()); // make sure it uses the tileset's image
280278
it.value()->setImageRect(tileRects.at(tileNum));
281279
} else {
282-
auto tile = new Tile(tileId, this);
283-
tile->setImageRect(rect);
284-
mTilesById.insert(tileId, tile);
280+
auto tile = new Tile(tileNum, this);
281+
tile->setImageRect(tileRects.at(tileNum));
282+
mTilesById.insert(tileNum, tile);
285283
mTiles.insert(tileNum, tile);
286284
}
287285
}
@@ -718,42 +716,6 @@ void Tileset::updateTileSize()
718716
mTileHeight = maxHeight;
719717
}
720718

721-
QPoint Tileset::pixelToGrid(const QPoint &pixelPos) const
722-
{
723-
return QPoint(
724-
(pixelPos.x() - mMargin) / (mTileWidth + mTileSpacing),
725-
(pixelPos.y() - mMargin) / (mTileHeight + mTileSpacing)
726-
);
727-
}
728-
729-
QPoint Tileset::gridToPixel(const QPoint &gridPos) const
730-
{
731-
return QPoint(
732-
mMargin + gridPos.x() * (mTileWidth + mTileSpacing),
733-
mMargin + gridPos.y() * (mTileHeight + mTileSpacing)
734-
);
735-
}
736-
737-
QRect Tileset::pixelToGrid(const QRect &pixelRect) const
738-
{
739-
const QPoint topLeft = pixelToGrid(pixelRect.topLeft());
740-
const QSize size(
741-
pixelRect.width() / mTileWidth,
742-
pixelRect.height() / mTileHeight
743-
);
744-
return QRect(topLeft, size);
745-
}
746-
747-
QRect Tileset::gridToPixel(const QRect &gridRect) const
748-
{
749-
const QPoint topLeft = gridToPixel(gridRect.topLeft());
750-
return QRect(
751-
topLeft.x(), topLeft.y(),
752-
gridRect.width() * mTileWidth,
753-
gridRect.height() * mTileHeight
754-
);
755-
}
756-
757719
QString Tileset::orientationToString(Tileset::Orientation orientation)
758720
{
759721
switch (orientation) {

src/libtiled/tileset.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -238,12 +238,6 @@ class TILEDSHARED_EXPORT Tileset : public Object, public QEnableSharedFromThis<T
238238
int nextTileId() const;
239239
int takeNextTileId();
240240

241-
// Convert between pixel and grid coordinates
242-
QPoint pixelToGrid(const QPoint &pixelPos) const;
243-
QPoint gridToPixel(const QPoint &gridPos) const;
244-
QRect pixelToGrid(const QRect &pixelRect) const;
245-
QRect gridToPixel(const QRect &gridRect) const;
246-
247241
void setTileImage(Tile *tile,
248242
const QPixmap &image,
249243
const QUrl &source = QUrl());

src/tiled/newtilesetdialog.ui

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
</item>
7272
<item>
7373
<property name="text">
74-
<string>Tileset Grid Atlas</string>
74+
<string>Tileset Atlas</string>
7575
</property>
7676
</item>
7777
<item>

src/tiled/tilesetmodel.cpp

Lines changed: 37 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,6 @@
3232

3333
using namespace Tiled;
3434

35-
inline uint qHash(const QPoint &p, uint seed = 0)
36-
{
37-
return qHash(p.x(), seed) ^ qHash(p.y(), seed);
38-
}
39-
4035
TilesetModel::TilesetModel(TilesetDocument *tilesetDocument, QObject *parent)
4136
: QAbstractListModel(parent)
4237
, mTilesetDocument(tilesetDocument)
@@ -49,37 +44,13 @@ TilesetModel::TilesetModel(TilesetDocument *tilesetDocument, QObject *parent)
4944
this, &TilesetModel::tileChanged);
5045
}
5146

52-
QPoint TilesetModel::viewToAtlasCoords(int viewCol, int viewRow) const
53-
{
54-
const int currentCols = columnCount();
55-
const int atlasCols = tileset()->columnCount();
56-
const int linearIndex = viewCol + viewRow * currentCols;
57-
return QPoint(linearIndex % atlasCols,
58-
linearIndex / atlasCols);
59-
}
60-
61-
QPoint TilesetModel::atlasToViewCoords(int atlasCol, int atlasRow) const
62-
{
63-
const int currentCols = columnCount();
64-
const int atlasCols = tileset()->columnCount();
65-
const int linearIndex = atlasRow * atlasCols + atlasCol;
66-
return QPoint(linearIndex % currentCols,
67-
linearIndex / currentCols);
68-
}
69-
7047
int TilesetModel::rowCount(const QModelIndex &parent) const
7148
{
7249
if (parent.isValid())
7350
return 0;
7451

75-
if (tileset()->isAtlas()) {
76-
const int currentCols = columnCount();
77-
if (currentCols <= 0)
78-
return 1;
79-
80-
const int totalTiles = tileset()->rowCount() * tileset()->columnCount();
81-
return (totalTiles + currentCols - 1) / currentCols;
82-
}
52+
if (tileset()->isAtlas() && mColumnCountOverride <= 0)
53+
return 1;
8354

8455
const int tileCount = mTileIds.size();
8556
const int columns = columnCount();
@@ -100,13 +71,23 @@ int TilesetModel::columnCount(const QModelIndex &parent) const
10071
return 0;
10172
if (mColumnCountOverride > 0)
10273
return mColumnCountOverride;
74+
if (tileset()->isAtlas())
75+
return 1;
10376
if (tileset()->columnCount())
10477
return tileset()->columnCount();
10578
// TODO: Non-table tilesets should use a different model.
10679
// For now use an arbitrary number of columns.
10780
return 5;
10881
}
10982

83+
QModelIndex TilesetModel::index(int row, int column, const QModelIndex &parent) const
84+
{
85+
if (tileset()->isAtlas() && mColumnCountOverride <= 0)
86+
return createIndex(row, column);
87+
88+
return QAbstractListModel::index(row, column, parent);
89+
}
90+
11091
QVariant TilesetModel::data(const QModelIndex &index, int role) const
11192
{
11293
if (role == Qt::DecorationRole) {
@@ -126,62 +107,15 @@ QVariant TilesetModel::headerData(int /* section */,
126107
return QVariant();
127108
}
128109

129-
QSize TilesetModel::tileSpanSize(const QModelIndex &index) const
130-
{
131-
if (!tileset()->isAtlas())
132-
return QSize(1, 1);
133-
134-
if (Tile *tile = tileAt(index)) {
135-
const int tileWidth = tileset()->tileWidth();
136-
const int tileHeight = tileset()->tileHeight();
137-
const QRect rect = tile->imageRect();
138-
return QSize(
139-
rect.width() / tileWidth,
140-
rect.height() / tileHeight
141-
);
142-
}
143-
144-
return QSize(1, 1);
145-
}
146-
147-
Tile *TilesetModel::findSpanningTile(const QModelIndex &index) const
148-
{
149-
if (!tileset()->isAtlas())
150-
return nullptr;
151-
152-
for (Tile *tile : tileset()->tiles()) {
153-
// Use tileIndex to get normalized grid position
154-
QModelIndex tilePos = tileIndex(tile);
155-
QSize span = tileSpanSize(tilePos);
156-
157-
if (span.width() <= 1 && span.height() <= 1)
158-
continue;
159-
160-
if (index.row() >= tilePos.row() && index.row() < tilePos.row() + span.height() &&
161-
index.column() >= tilePos.column() && index.column() < tilePos.column() + span.width()) {
162-
return tile;
163-
}
164-
}
165-
166-
return nullptr;
167-
}
168-
169110
Qt::ItemFlags TilesetModel::flags(const QModelIndex &index) const
170111
{
171112
Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index);
172113

173-
if (tileset()->isAtlas()) {
174-
if (!index.isValid())
175-
return defaultFlags;
176-
177-
// If this cell contains a tile's origin or we are relocating, it's selectable
178-
if (mRelocating || tileAt(index))
179-
return defaultFlags | Qt::ItemIsSelectable;
180-
114+
if (tileset()->isAtlas() && mColumnCountOverride <= 0 && index.column() == 0 && index.row() == 0)
181115
return defaultFlags & ~Qt::ItemIsSelectable;
182-
}
183116

184117
defaultFlags |= Qt::ItemIsDropEnabled;
118+
185119
if (index.isValid())
186120
defaultFlags |= Qt::ItemIsDragEnabled;
187121

@@ -273,26 +207,32 @@ Tile *TilesetModel::tileAt(const QModelIndex &index) const
273207
if (!index.isValid())
274208
return nullptr;
275209

276-
if (tileset()->isAtlas()) {
277-
const QPoint atlasPos = viewToAtlasCoords(index.column(), index.row());
278-
return mTileGrid.value(atlasPos);
210+
if (tileset()->isAtlas() && mColumnCountOverride <= 0) {
211+
const QPoint gridPos(index.column() - 1, index.row());
212+
for (Tile *tile : tileset()->tiles()) {
213+
const QPoint snappedPos = snapToGrid(tile->imageRect().bottomLeft());
214+
if (snappedPos == gridPos)
215+
return tile;
216+
}
217+
218+
return nullptr;
279219
}
280220

281221
const int tileIndex = index.column() + index.row() * columnCount();
282222
if (tileIndex < mTileIds.size()) {
283223
const int tileId = mTileIds.at(tileIndex);
284224
return tileset()->findTile(tileId);
285225
}
226+
286227
return nullptr;
287228
}
288229

289230
QModelIndex TilesetModel::tileIndex(const Tile *tile) const
290231
{
291232
Q_ASSERT(tile->tileset() == tileset());
292-
if (tileset()->isAtlas()) {
293-
const QPoint tilePos = tileset()->pixelToGrid(tile->imageRect().topLeft());
294-
const QPoint viewPos = atlasToViewCoords(tilePos.x(), tilePos.y());
295-
return index(viewPos.y(), viewPos.x());
233+
if (tileset()->isAtlas() && mColumnCountOverride <= 0) {
234+
const QPoint snappedPos = snapToGrid(tile->imageRect().bottomLeft());
235+
return index(snappedPos.y(), snappedPos.x() + 1);
296236
}
297237

298238
const int columnCount = TilesetModel::columnCount();
@@ -365,26 +305,24 @@ void TilesetModel::tilesChanged(const QList<Tile *> &tiles)
365305

366306
void TilesetModel::tileChanged(Tile *tile)
367307
{
368-
if (tileset()->isAtlas()) {
369-
const QPoint oldPos = mTileGrid.key(tile, QPoint(-1, -1));
370-
if (oldPos != QPoint(-1, -1))
371-
mTileGrid.remove(oldPos);
372-
const QPoint newPos = tileset()->pixelToGrid(tile->imageRect().topLeft());
373-
mTileGrid.insert(newPos, tile);
374-
}
375-
376308
const QModelIndex i = tileIndex(tile);
377309
emit dataChanged(i, i);
378310
}
379311

380312
void TilesetModel::refreshTileIds()
381313
{
382314
mTileIds.clear();
383-
for (Tile *tile : tileset()->tiles()) {
315+
for (Tile *tile : tileset()->tiles())
384316
mTileIds.append(tile->id());
385-
const QPoint pos = tileset()->pixelToGrid(tile->imageRect().topLeft());
386-
mTileGrid.insert(pos, tile);
387-
}
317+
}
318+
319+
QPoint TilesetModel::snapToGrid(const QPoint &pos) const
320+
{
321+
const int tileWidth = tileset()->tileWidth();
322+
const int tileHeight = tileset()->tileHeight();
323+
const int x = (pos.x() + tileWidth / 2) / tileWidth;
324+
const int y = (pos.y() + tileHeight / 2) / tileHeight;
325+
return QPoint(x, y);
388326
}
389327

390328
#include "moc_tilesetmodel.cpp"

src/tiled/tilesetmodel.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ class TilesetModel : public QAbstractListModel
8080
int row, int column,
8181
const QModelIndex &parent) override;
8282

83+
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
84+
8385
/**
8486
* Returns the tile at the given index.
8587
*/
@@ -104,11 +106,6 @@ class TilesetModel : public QAbstractListModel
104106

105107
void setColumnCountOverride(int columnCount);
106108

107-
void setRelocating(bool relocating) { mRelocating = relocating; }
108-
109-
QSize tileSpanSize(const QModelIndex &index) const;
110-
Tile *findSpanningTile(const QModelIndex &index) const;
111-
112109
public slots:
113110
/**
114111
* Should be called when anything changes about the given \a tiles that
@@ -133,14 +130,11 @@ public slots:
133130

134131
void refreshTileIds();
135132

136-
QPoint viewToAtlasCoords(int viewCol, int viewRow) const;
137-
QPoint atlasToViewCoords(int atlasCol, int atlasRow) const;
133+
QPoint snapToGrid(const QPoint &pos) const;
138134

139135
TilesetDocument *mTilesetDocument;
140136
QList<int> mTileIds;
141-
QHash<QPoint, Tile*> mTileGrid;
142137
int mColumnCountOverride = 0;
143-
bool mRelocating = false;
144138
};
145139

146140
} // namespace Tiled

0 commit comments

Comments
 (0)