Skip to content

Commit 915fd32

Browse files
committed
Added support for flat-top hexagonal (staggering the X axis)
This also adds support for staggering the X axis at either odd or even indexes for staggered isometric maps.
1 parent da2c2e0 commit 915fd32

14 files changed

+483
-220
lines changed

src/libtiled/hexagonalrenderer.cpp

+315-133
Large diffs are not rendered by default.

src/libtiled/hexagonalrenderer.h

+26-6
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,35 @@ class TILEDSHARED_EXPORT HexagonalRenderer : public OrthogonalRenderer
4949
{
5050
RenderParams(const Map *map);
5151

52-
bool stagger(int index) const { return (index & 1) ^ staggerEven; }
52+
bool stagger(int x, int y) const
53+
{
54+
if (staggerX)
55+
return (x & 1) ^ staggerEven;
56+
else
57+
return (y & 1) ^ staggerEven;
58+
}
59+
60+
bool stagger(const QPoint &point) const
61+
{
62+
return stagger(point.x(), point.y());
63+
}
64+
65+
bool doStaggerX(int x) const
66+
{ return staggerX && (x & 1) ^ staggerEven; }
67+
68+
bool doStaggerY(int y) const
69+
{ return !staggerX && (y & 1) ^ staggerEven; }
5370

5471
const int tileWidth;
5572
const int tileHeight;
56-
const int halfTileWidth;
57-
const int sideLength;
58-
const int sideOffset;
59-
const int rowHeight;
60-
const int staggerEven;
73+
int sideLengthX;
74+
int sideOffsetX;
75+
int sideLengthY;
76+
int sideOffsetY;
77+
int rowHeight;
78+
int columnWidth;
79+
const bool staggerX;
80+
const bool staggerEven;
6181
};
6282

6383
public:

src/libtiled/map.cpp

+13-13
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ Map::Map(Orientation orientation,
4848
mTileWidth(tileWidth),
4949
mTileHeight(tileHeight),
5050
mHexSideLength(0),
51-
mStaggerDirection(StaggerRows),
51+
mStaggerAxis(StaggerY),
5252
mStaggerIndex(StaggerOdd),
5353
mLayerDataFormat(Base64Zlib)
5454
{
@@ -63,7 +63,7 @@ Map::Map(const Map &map):
6363
mTileWidth(map.mTileWidth),
6464
mTileHeight(map.mTileHeight),
6565
mHexSideLength(map.mHexSideLength),
66-
mStaggerDirection(map.mStaggerDirection),
66+
mStaggerAxis(map.mStaggerAxis),
6767
mStaggerIndex(map.mStaggerIndex),
6868
mBackgroundColor(map.mBackgroundColor),
6969
mDrawMargins(map.mDrawMargins),
@@ -232,25 +232,25 @@ bool Map::isTilesetUsed(Tileset *tileset) const
232232
}
233233

234234

235-
QString Tiled::staggerDirectionToString(Map::StaggerDirection staggerDirection)
235+
QString Tiled::staggerAxisToString(Map::StaggerAxis staggerAxis)
236236
{
237-
switch (staggerDirection) {
237+
switch (staggerAxis) {
238238
default:
239-
case Map::StaggerColumns:
240-
return QLatin1String("columns");
239+
case Map::StaggerY:
240+
return QLatin1String("y");
241241
break;
242-
case Map::StaggerRows:
243-
return QLatin1String("rows");
242+
case Map::StaggerX:
243+
return QLatin1String("x");
244244
break;
245245
}
246246
}
247247

248-
Map::StaggerDirection Tiled::staggerDirectionFromString(const QString &string)
248+
Map::StaggerAxis Tiled::staggerAxisFromString(const QString &string)
249249
{
250-
Map::StaggerDirection staggerDirection = Map::StaggerColumns;
251-
if (string == QLatin1String("rows"))
252-
staggerDirection = Map::StaggerRows;
253-
return staggerDirection;
250+
Map::StaggerAxis staggerAxis = Map::StaggerY;
251+
if (string == QLatin1String("x"))
252+
staggerAxis = Map::StaggerX;
253+
return staggerAxis;
254254
}
255255

256256
QString Tiled::staggerIndexToString(Map::StaggerIndex staggerIndex)

src/libtiled/map.h

+18-18
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,12 @@ class TILEDSHARED_EXPORT Map : public Object
9191
};
9292

9393
/**
94-
* Whether the tiles are staggered by rows or columns. Only used by the
95-
* isometric staggered and hexagonal map renderers.
94+
* Which axis is staggered. Only used by the isometric staggered and
95+
* hexagonal map renderers.
9696
*/
97-
enum StaggerDirection {
98-
StaggerColumns,
99-
StaggerRows
97+
enum StaggerAxis {
98+
StaggerX,
99+
StaggerY
100100
};
101101

102102
/**
@@ -149,22 +149,22 @@ class TILEDSHARED_EXPORT Map : public Object
149149
{ mRenderOrder = renderOrder; }
150150

151151
/**
152-
* Returns the width of this map.
152+
* Returns the width of this map in tiles.
153153
*/
154154
int width() const { return mWidth; }
155155

156156
/**
157-
* Sets the width of this map.
157+
* Sets the width of this map in tiles.
158158
*/
159159
void setWidth(int width) { mWidth = width; }
160160

161161
/**
162-
* Returns the height of this map.
162+
* Returns the height of this map in tiles.
163163
*/
164164
int height() const { return mHeight; }
165165

166166
/**
167-
* Sets the height of this map.
167+
* Sets the height of this map in tiles.
168168
*/
169169
void setHeight(int height) { mHeight = height; }
170170

@@ -201,8 +201,8 @@ class TILEDSHARED_EXPORT Map : public Object
201201
int hexSideLength() const;
202202
void setHexSideLength(int hexSideLength);
203203

204-
StaggerDirection staggerDirection() const;
205-
void setStaggerDirection(StaggerDirection staggerDirection);
204+
StaggerAxis staggerAxis() const;
205+
void setStaggerAxis(StaggerAxis staggerAxis);
206206

207207
StaggerIndex staggerIndex() const;
208208
void setStaggerIndex(StaggerIndex staggerIndex);
@@ -379,7 +379,7 @@ class TILEDSHARED_EXPORT Map : public Object
379379
int mTileWidth;
380380
int mTileHeight;
381381
int mHexSideLength;
382-
StaggerDirection mStaggerDirection;
382+
StaggerAxis mStaggerAxis;
383383
StaggerIndex mStaggerIndex;
384384
QColor mBackgroundColor;
385385
QMargins mDrawMargins;
@@ -399,14 +399,14 @@ inline void Map::setHexSideLength(int hexSideLength)
399399
mHexSideLength = hexSideLength;
400400
}
401401

402-
inline Map::StaggerDirection Map::staggerDirection() const
402+
inline Map::StaggerAxis Map::staggerAxis() const
403403
{
404-
return mStaggerDirection;
404+
return mStaggerAxis;
405405
}
406406

407-
inline void Map::setStaggerDirection(StaggerDirection staggerDirection)
407+
inline void Map::setStaggerAxis(StaggerAxis staggerAxis)
408408
{
409-
mStaggerDirection = staggerDirection;
409+
mStaggerAxis = staggerAxis;
410410
}
411411

412412
inline Map::StaggerIndex Map::staggerIndex() const
@@ -420,8 +420,8 @@ inline void Map::setStaggerIndex(StaggerIndex staggerIndex)
420420
}
421421

422422

423-
TILEDSHARED_EXPORT QString staggerDirectionToString(Map::StaggerDirection staggerDirection);
424-
TILEDSHARED_EXPORT Map::StaggerDirection staggerDirectionFromString(const QString &);
423+
TILEDSHARED_EXPORT QString staggerAxisToString(Map::StaggerAxis);
424+
TILEDSHARED_EXPORT Map::StaggerAxis staggerAxisFromString(const QString &);
425425

426426
TILEDSHARED_EXPORT QString staggerIndexToString(Map::StaggerIndex staggerIndex);
427427
TILEDSHARED_EXPORT Map::StaggerIndex staggerIndexFromString(const QString &);

src/libtiled/mapreader.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,10 @@ Map *MapReaderPrivate::readMap()
223223
.arg(orientationString));
224224
}
225225

226-
const QString staggerDirectionString =
227-
atts.value(QLatin1String("staggerdirection")).toString();
228-
const Map::StaggerDirection staggerDirection =
229-
staggerDirectionFromString(staggerDirectionString);
226+
const QString staggerAxisString =
227+
atts.value(QLatin1String("staggeraxis")).toString();
228+
const Map::StaggerAxis staggerAxis =
229+
staggerAxisFromString(staggerAxisString);
230230

231231
const QString staggerIndexString =
232232
atts.value(QLatin1String("staggerindex")).toString();
@@ -240,7 +240,7 @@ Map *MapReaderPrivate::readMap()
240240

241241
mMap = new Map(orientation, mapWidth, mapHeight, tileWidth, tileHeight);
242242
mMap->setHexSideLength(hexSideLength);
243-
mMap->setStaggerDirection(staggerDirection);
243+
mMap->setStaggerAxis(staggerAxis);
244244
mMap->setStaggerIndex(staggerIndex);
245245
mMap->setRenderOrder(renderOrder);
246246
mCreatedTilesets.clear();

src/libtiled/mapwriter.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@ void MapWriterPrivate::writeMap(QXmlStreamWriter &w, const Map *map)
186186
if (map->orientation() == Map::Hexagonal) {
187187
w.writeAttribute(QLatin1String("hexsidelength"),
188188
QString::number(map->hexSideLength()));
189-
w.writeAttribute(QLatin1String("staggerdirection"),
190-
staggerDirectionToString(map->staggerDirection()));
189+
w.writeAttribute(QLatin1String("staggeraxis"),
190+
staggerAxisToString(map->staggerAxis()));
191191
}
192192

193193
if (map->orientation() == Map::Staggered || map->orientation() == Map::Hexagonal) {

src/libtiled/staggeredrenderer.cpp

+25-15
Original file line numberDiff line numberDiff line change
@@ -43,26 +43,36 @@ QPointF StaggeredRenderer::screenToTileCoords(qreal x, qreal y) const
4343
{
4444
const RenderParams p(map());
4545

46-
const int halfTileHeight = p.tileHeight / 2;
47-
const qreal ratio = (qreal) p.tileHeight / p.tileWidth;
46+
if (p.staggerX)
47+
x -= p.staggerEven ? p.sideOffsetX : 0;
48+
else
49+
y -= p.staggerEven ? p.sideOffsetY : 0;
4850

4951
// Start with the coordinates of a grid-aligned tile
50-
const int tileX = qFloor(x / p.tileWidth);
51-
const int tileY = qFloor(y / p.tileHeight) * 2;
52+
QPoint referencePoint = QPoint(qFloor(x / p.tileWidth),
53+
qFloor(y / p.tileHeight));
5254

5355
// Relative x and y position on the base square of the grid-aligned tile
54-
const qreal relX = x - tileX * p.tileWidth;
55-
const qreal relY = y - (tileY / 2) * p.tileHeight;
56+
const QPointF rel(x - referencePoint.x() * p.tileWidth,
57+
y - referencePoint.y() * p.tileHeight);
58+
59+
// Adjust the reference point to the correct tile coordinates
60+
int &staggerAxisIndex = p.staggerX ? referencePoint.rx() : referencePoint.ry();
61+
staggerAxisIndex *= 2;
62+
if (p.staggerEven)
63+
++staggerAxisIndex;
64+
65+
const qreal y_pos = rel.x() * ((qreal) p.tileHeight / p.tileWidth);
5666

5767
// Check whether the cursor is in any of the corners (neighboring tiles)
58-
if (halfTileHeight - relX * ratio > relY)
59-
return topLeft(tileX, tileY);
60-
if (-halfTileHeight + relX * ratio > relY)
61-
return topRight(tileX, tileY);
62-
if (halfTileHeight + relX * ratio < relY)
63-
return bottomLeft(tileX, tileY);
64-
if (halfTileHeight * 3 - relX * ratio < relY)
65-
return bottomRight(tileX, tileY);
68+
if (p.sideOffsetY - y_pos > rel.y())
69+
return topLeft(referencePoint.x(), referencePoint.y());
70+
if (-p.sideOffsetY + y_pos > rel.y())
71+
return topRight(referencePoint.x(), referencePoint.y());
72+
if (p.sideOffsetY + y_pos < rel.y())
73+
return bottomLeft(referencePoint.x(), referencePoint.y());
74+
if (p.sideOffsetY * 3 - y_pos < rel.y())
75+
return bottomRight(referencePoint.x(), referencePoint.y());
6676

67-
return QPoint(tileX, tileY);
77+
return referencePoint;
6878
}

src/libtiled/tilelayer.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,7 @@ class TILEDSHARED_EXPORT TileLayer : public Layer
149149
* Returns a read-only reference to the cell at the given coordinates. The
150150
* coordinates have to be within this layer.
151151
*/
152-
const Cell &cellAt(int x, int y) const
153-
{ return mGrid.at(x + y * mWidth); }
152+
const Cell &cellAt(int x, int y) const;
154153

155154
const Cell &cellAt(const QPoint &point) const
156155
{ return cellAt(point.x(), point.y()); }
@@ -318,6 +317,12 @@ inline QRegion TileLayer::region() const
318317
return region(cellInUse);
319318
}
320319

320+
inline const Cell &TileLayer::cellAt(int x, int y) const
321+
{
322+
Q_ASSERT(contains(x, y));
323+
return mGrid.at(x + y * mWidth);
324+
}
325+
321326
} // namespace Tiled
322327

323328
#endif // TILELAYER_H

src/plugins/json/maptovariantconverter.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ QVariant MapToVariantConverter::toVariant(const Map *map, const QDir &mapDir)
5252

5353
if (map->orientation() == Map::Hexagonal) {
5454
mapVariant["hexsidelength"] = map->hexSideLength();
55-
mapVariant["staggerdirection"] = staggerDirectionToString(map->staggerDirection());
55+
mapVariant["staggeraxis"] = staggerAxisToString(map->staggerAxis());
5656
}
5757

5858
if (map->orientation() == Map::Hexagonal || map->orientation() == Map::Staggered)

src/plugins/json/varianttomapconverter.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ Map *VariantToMapConverter::toMap(const QVariant &variant,
6060
return 0;
6161
}
6262

63-
const QString staggerDirectionString = variantMap["staggerdirection"].toString();
64-
Map::StaggerDirection staggerDirection = staggerDirectionFromString(staggerDirectionString);
63+
const QString staggerAxisString = variantMap["staggeraxis"].toString();
64+
Map::StaggerAxis staggerAxis = staggerAxisFromString(staggerAxisString);
6565

6666
const QString staggerIndexString = variantMap["staggerindex"].toString();
6767
Map::StaggerIndex staggerIndex = staggerIndexFromString(staggerIndexString);
@@ -76,7 +76,7 @@ Map *VariantToMapConverter::toMap(const QVariant &variant,
7676
variantMap["tilewidth"].toInt(),
7777
variantMap["tileheight"].toInt()));
7878
map->setHexSideLength(variantMap["hexsidelength"].toInt());
79-
map->setStaggerDirection(staggerDirection);
79+
map->setStaggerAxis(staggerAxis);
8080
map->setStaggerIndex(staggerIndex);
8181
map->setRenderOrder(renderOrder);
8282

src/tiled/changemapproperty.cpp

+23-7
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,16 @@ ChangeMapProperty::ChangeMapProperty(MapDocument *mapDocument,
6464
{
6565
}
6666

67+
ChangeMapProperty::ChangeMapProperty(MapDocument *mapDocument,
68+
Map::StaggerAxis staggerAxis)
69+
: QUndoCommand(QCoreApplication::translate("Undo Commands",
70+
"Change Stagger Axis"))
71+
, mMapDocument(mapDocument)
72+
, mProperty(StaggerAxis)
73+
, mStaggerAxis(staggerAxis)
74+
{
75+
}
76+
6777
ChangeMapProperty::ChangeMapProperty(MapDocument *mapDocument,
6878
Map::StaggerIndex staggerIndex)
6979
: QUndoCommand(QCoreApplication::translate("Undo Commands",
@@ -131,25 +141,31 @@ void ChangeMapProperty::swap()
131141
mIntValue = tileHeight;
132142
break;
133143
}
144+
case Orientation: {
145+
const Map::Orientation orientation = map->orientation();
146+
map->setOrientation(mOrientation);
147+
mOrientation = orientation;
148+
mMapDocument->createRenderer();
149+
break;
150+
}
134151
case HexSideLength: {
135152
const int hexSideLength = map->hexSideLength();
136153
map->setHexSideLength(mIntValue);
137154
mIntValue = hexSideLength;
138155
break;
139156
}
157+
case StaggerAxis: {
158+
const Map::StaggerAxis staggerAxis = map->staggerAxis();
159+
map->setStaggerAxis(mStaggerAxis);
160+
mStaggerAxis = staggerAxis;
161+
break;
162+
}
140163
case StaggerIndex: {
141164
const Map::StaggerIndex staggerIndex = map->staggerIndex();
142165
map->setStaggerIndex(mStaggerIndex);
143166
mStaggerIndex = staggerIndex;
144167
break;
145168
}
146-
case Orientation: {
147-
const Map::Orientation orientation = map->orientation();
148-
map->setOrientation(mOrientation);
149-
mOrientation = orientation;
150-
mMapDocument->createRenderer();
151-
break;
152-
}
153169
case RenderOrder: {
154170
const Map::RenderOrder renderOrder = map->renderOrder();
155171
map->setRenderOrder(mRenderOrder);

0 commit comments

Comments
 (0)