Skip to content

Commit 0e7a8cd

Browse files
committed
Use grid span instead of drawing everything directly
Works way better with QT Signed-off-by: Tomas Slusny <[email protected]>
1 parent 5dc367b commit 0e7a8cd

File tree

4 files changed

+94
-92
lines changed

4 files changed

+94
-92
lines changed

src/tiled/tilesetmodel.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,19 @@ int TilesetModel::rowCount(const QModelIndex &parent) const
4949
if (parent.isValid())
5050
return 0;
5151

52+
if (tileset()->isAtlas()) {
53+
// Calculate total rows needed based on the furthest tile
54+
int maxRow = 0;
55+
const int gridSize = 16; // Or calculate based on tiles
56+
57+
for (Tile *tile : tileset()->tiles()) {
58+
QRect rect = tile->imageRect();
59+
int bottomRow = (rect.y() + rect.height() + gridSize - 1) / gridSize;
60+
maxRow = std::max(maxRow, bottomRow);
61+
}
62+
return maxRow;
63+
}
64+
5265
const int tileCount = mTileIds.size();
5366
const int columns = columnCount();
5467

@@ -285,4 +298,29 @@ void TilesetModel::refreshTileIds()
285298
mTileIds.append(tile->id());
286299
}
287300

301+
QSize TilesetModel::tileSpanSize(const QModelIndex &index) const
302+
{
303+
if (!tileset()->isAtlas())
304+
return QSize(1, 1);
305+
306+
if (Tile *tile = tileAt(index)) {
307+
const int gridSize = 16; // Same as used in rowCount
308+
QRect rect = tile->imageRect();
309+
return QSize((rect.width() + gridSize - 1) / gridSize,
310+
(rect.height() + gridSize - 1) / gridSize);
311+
}
312+
return QSize(1, 1);
313+
}
314+
315+
QPoint TilesetModel::tileGridPosition(const Tile *tile) const
316+
{
317+
if (!tileset()->isAtlas())
318+
return QPoint(0, 0);
319+
320+
const int gridSize = 16;
321+
QRect rect = tile->imageRect();
322+
return QPoint(rect.x() / gridSize,
323+
rect.y() / gridSize);
324+
}
325+
288326
#include "moc_tilesetmodel.cpp"

src/tiled/tilesetmodel.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,17 @@ class TilesetModel : public QAbstractListModel
104104

105105
void setColumnCountOverride(int columnCount);
106106

107+
/**
108+
* Returns the size of cells spanned by the tile at given index.
109+
* Used for atlas tilesets to allow tiles to span multiple cells.
110+
*/
111+
QSize tileSpanSize(const QModelIndex &index) const;
112+
113+
/**
114+
* Returns grid position for the tile. Used for atlas tilesets.
115+
*/
116+
QPoint tileGridPosition(const Tile *tile) const;
117+
107118
public slots:
108119
/**
109120
* Should be called when anything changes about the given \a tiles that

src/tiled/tilesetview.cpp

Lines changed: 45 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -114,42 +114,37 @@ void TileDelegate::paint(QPainter *painter,
114114
return;
115115

116116
const QPixmap &tileImage = tile->image();
117-
const bool isAtlas = tile->tileset()->isAtlas();
118117
const int extra = mTilesetView->drawGrid() ? 1 : 0;
119118
const qreal zoom = mTilesetView->scale();
119+
const bool wrapping = mTilesetView->dynamicWrapping();
120120

121-
QRect imageRect = tile->imageRect();
122-
QSize tileSize = imageRect.size().isValid() ? imageRect.size() : tile->size();
121+
QSize tileSize = tile->size();
122+
if (tileImage.isNull()) {
123+
Tileset *tileset = model->tileset();
124+
if (tileset->isCollection()) {
125+
tileSize = QSize(32, 32);
126+
} else {
127+
int max = std::max(tileset->tileWidth(), tileset->tileHeight());
128+
int min = std::min(max, 32);
129+
tileSize = QSize(min, min);
130+
}
131+
}
123132

124-
// For atlas tilesets, use the actual position from imageRect
125-
QRect targetRect;
126-
if (isAtlas) {
127-
// Account for scrollbar positions
128-
const QPoint scrollOffset(mTilesetView->horizontalScrollBar()->value(),
129-
mTilesetView->verticalScrollBar()->value());
133+
// Compute rectangle to draw the image in: bottom- and left-aligned
134+
QRect targetRect = option.rect.adjusted(0, 0, -extra, -extra);
130135

131-
// Convert atlas coordinates to view coordinates
132-
QPoint viewPos = (imageRect.topLeft() * zoom) - scrollOffset;
133-
targetRect = QRect(viewPos, imageRect.size() * zoom);
136+
if (wrapping) {
137+
qreal scale = std::min(static_cast<qreal>(targetRect.width()) / tileSize.width(),
138+
static_cast<qreal>(targetRect.height()) / tileSize.height());
139+
tileSize *= scale;
134140

135-
// Offset by the view's margin/padding if any
136-
// targetRect = targetRect.adjusted(0, 0, -extra, -extra);
141+
auto center = targetRect.center();
142+
targetRect.setSize(tileSize);
143+
targetRect.moveCenter(center);
137144
} else {
138-
// Original grid-based positioning for non-atlas tilesets
139-
targetRect = option.rect.adjusted(0, 0, -extra, -extra);
140-
141-
if (mTilesetView->dynamicWrapping()) {
142-
qreal scale = std::min(static_cast<qreal>(targetRect.width()) / tileSize.width(),
143-
static_cast<qreal>(targetRect.height()) / tileSize.height());
144-
tileSize *= scale;
145-
146-
auto center = targetRect.center();
147-
targetRect.setSize(tileSize);
148-
targetRect.moveCenter(center);
149-
} else {
150-
tileSize *= zoom;
151-
targetRect.setSize(tileSize);
152-
}
145+
tileSize *= zoom;
146+
targetRect.setTop(targetRect.bottom() - tileSize.height() + 1);
147+
targetRect.setRight(targetRect.left() + tileSize.width() - 1);
153148
}
154149

155150
// Draw the tile image
@@ -158,10 +153,11 @@ void TileDelegate::paint(QPainter *painter,
158153
painter->setRenderHint(QPainter::SmoothPixmapTransform);
159154

160155
if (!tileImage.isNull())
161-
painter->drawPixmap(targetRect, tileImage, imageRect);
156+
painter->drawPixmap(targetRect, tileImage, tile->imageRect());
162157
else
163158
mTilesetView->imageMissingIcon().paint(painter, targetRect, Qt::AlignBottom | Qt::AlignLeft);
164159

160+
165161
// Overlay with film strip when animated
166162
if (mTilesetView->markAnimatedTiles() && tile->isAnimated())
167163
drawFilmStrip(painter, targetRect);
@@ -356,11 +352,6 @@ int TilesetView::sizeHintForColumn(int column) const
356352
const TilesetModel *model = tilesetModel();
357353
if (!model)
358354
return -1;
359-
if (model->tileset()->isAtlas()) {
360-
// Get the tile at this column and use its width
361-
if (Tile *tile = model->tileAt(model->index(0, column)))
362-
return tile->imageRect().width() * scale();
363-
}
364355
if (model->tileset()->isCollection())
365356
return QTableView::sizeHintForColumn(column);
366357

@@ -378,11 +369,6 @@ int TilesetView::sizeHintForRow(int row) const
378369
const TilesetModel *model = tilesetModel();
379370
if (!model)
380371
return -1;
381-
if (model->tileset()->isAtlas()) {
382-
// Get the tile at this row and use its height
383-
if (Tile *tile = model->tileAt(model->index(row, 0)))
384-
return tile->imageRect().height() * scale();
385-
}
386372
if (model->tileset()->isCollection())
387373
return QTableView::sizeHintForRow(row);
388374

@@ -431,8 +417,25 @@ bool TilesetView::dynamicWrapping() const
431417
void TilesetView::setModel(QAbstractItemModel *model)
432418
{
433419
QTableView::setModel(model);
420+
421+
if (TilesetModel *tilesetModel = qobject_cast<TilesetModel*>(model)) {
422+
if (tilesetModel->tileset()->isAtlas()) {
423+
// Set up spans for atlas tiles
424+
for (Tile *tile : tilesetModel->tileset()->tiles()) {
425+
QModelIndex index = tilesetModel->tileIndex(tile);
426+
if (index.isValid()) {
427+
QSize span = tilesetModel->tileSpanSize(index);
428+
if (span != QSize(1, 1))
429+
setSpan(index.row(), index.column(),
430+
span.height(), span.width());
431+
}
432+
}
433+
}
434+
}
435+
434436
updateBackgroundColor();
435-
setVerticalScrollBarPolicy(dynamicWrapping() ? Qt::ScrollBarAlwaysOn : Qt::ScrollBarAsNeeded);
437+
setVerticalScrollBarPolicy(dynamicWrapping() ? Qt::ScrollBarAlwaysOn
438+
: Qt::ScrollBarAsNeeded);
436439
refreshColumnCount();
437440
}
438441

@@ -511,54 +514,6 @@ void TilesetView::keyPressEvent(QKeyEvent *event)
511514
return QTableView::keyPressEvent(event);
512515
}
513516

514-
QModelIndex TilesetView::indexAt(const QPoint &point) const
515-
{
516-
if (!tilesetModel())
517-
return QModelIndex();
518-
519-
if (tilesetModel()->tileset()->isAtlas()) {
520-
// Convert view coordinates to atlas coordinates
521-
const QPoint scrollOffset(horizontalScrollBar()->value(),
522-
verticalScrollBar()->value());
523-
const QPointF atlasPos = (point + scrollOffset) / scale();
524-
525-
for (const Tile *tile : tilesetModel()->tileset()->tiles()) {
526-
if (tile->imageRect().contains(atlasPos.toPoint()))
527-
return tilesetModel()->tileIndex(tile);
528-
}
529-
530-
return QModelIndex();
531-
}
532-
533-
// Original grid-based indexAt logic
534-
return QTableView::indexAt(point);
535-
}
536-
537-
QRect TilesetView::visualRect(const QModelIndex &index) const
538-
{
539-
if (!tilesetModel())
540-
return QRect();
541-
542-
if (tilesetModel()->tileset()->isAtlas()) {
543-
if (Tile *tile = tilesetModel()->tileAt(index)) {
544-
const QRect imageRect = tile->imageRect();
545-
const QPoint scrollOffset(horizontalScrollBar()->value(),
546-
verticalScrollBar()->value());
547-
548-
// Convert atlas coordinates to view coordinates
549-
QRect rect(imageRect.topLeft() * scale() - scrollOffset,
550-
imageRect.size() * scale());
551-
552-
return rect;
553-
// const int extra = drawGrid() ? 1 : 0;
554-
// return rect.adjusted(0, 0, -extra, -extra);
555-
}
556-
return QRect();
557-
}
558-
559-
return QTableView::visualRect(index);
560-
}
561-
562517
void TilesetView::setRelocateTiles(bool enabled)
563518
{
564519
if (mRelocateTiles == enabled)
@@ -957,7 +912,7 @@ void TilesetView::refreshColumnCount()
957912
if (!tilesetModel())
958913
return;
959914

960-
if (!dynamicWrapping() || tilesetModel()->tileset()->isAtlas()) {
915+
if (!dynamicWrapping()) {
961916
tilesetModel()->setColumnCountOverride(0);
962917
return;
963918
}

src/tiled/tilesetview.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,6 @@ class TilesetView : public QTableView
117117
void wheelEvent(QWheelEvent *event) override;
118118
void contextMenuEvent(QContextMenuEvent *event) override;
119119
void resizeEvent(QResizeEvent *event) override;
120-
QModelIndex indexAt(const QPoint &point) const override;
121-
QRect visualRect(const QModelIndex &index) const override;
122120

123121
private:
124122
void onChange(const ChangeEvent &change);

0 commit comments

Comments
 (0)