-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support rotate hexagonal tiles 60 degrees #1447
Changes from 7 commits
1d181fd
8d1ebb5
8d93b33
c56a634
d981fd2
1de648f
9313dbc
f5af112
663e1d5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<map version="1.0" orientation="hexagonal" renderorder="right-down" width="20" height="20" tilewidth="60" tileheight="60" hexsidelength="30" staggeraxis="x" staggerindex="odd" nextobjectid="1"> | ||
<tileset firstgid="1" name="test_hexagonal_tile_60x60x30" tilewidth="60" tileheight="60" tilecount="1" columns="1"> | ||
<image source="test_hexagonal_tile_60x60x30.png" width="60" height="60"/> | ||
</tileset> | ||
<layer name="Tile Layer 1" width="20" height="20"> | ||
<data encoding="csv"> | ||
1,536870913,268435457,3221225473,3758096385,3489660929,1,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
2147483649,2684354561,2415919105,1073741825,1610612737,1342177281,2147483649,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 | ||
</data> | ||
</layer> | ||
</map> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -106,10 +106,11 @@ static bool hasOpenGLEngine(const QPainter *painter) | |
type == QPaintEngine::OpenGL2); | ||
} | ||
|
||
CellRenderer::CellRenderer(QPainter *painter) | ||
CellRenderer::CellRenderer(QPainter *painter, const CellType cellType) | ||
: mPainter(painter) | ||
, mTile(nullptr) | ||
, mIsOpenGL(hasOpenGLEngine(painter)) | ||
, mCellType(cellType) | ||
{ | ||
} | ||
|
||
|
@@ -164,7 +165,16 @@ void CellRenderer::render(const Cell &cell, const QPointF &pos, const QSizeF &si | |
if (origin == BottomCenter) | ||
fragment.x -= sizeHalf.x(); | ||
|
||
if (cell.flippedAntiDiagonally()) { | ||
qreal rotation = 0; | ||
if (mCellType == HexagonalCells) { | ||
if (cell.rotatedHexagonal60()) { | ||
fragment.rotation += 60; | ||
} | ||
if (cell.rotatedHexagonal120()) { | ||
fragment.rotation += 120; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Coding style: please leave out the superfluous |
||
} else if (cell.flippedAntiDiagonally()) { | ||
Q_ASSERT(mCellType == OrthogonalCells); | ||
fragment.rotation = 90; | ||
|
||
flippedHorizontally = cell.flippedVertically(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -258,7 +258,12 @@ class CellRenderer | |
BottomCenter | ||
}; | ||
|
||
explicit CellRenderer(QPainter *painter); | ||
enum CellType { | ||
OrthogonalCells, | ||
HexagonalCells | ||
}; | ||
|
||
explicit CellRenderer(QPainter *painter, const CellType cellType = OrthogonalCells); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please leave out the |
||
|
||
~CellRenderer() { flush(); } | ||
|
||
|
@@ -270,6 +275,7 @@ class CellRenderer | |
const Tile *mTile; | ||
QVector<QPainter::PixmapFragment> mFragments; | ||
const bool mIsOpenGL; | ||
const CellType mCellType; | ||
}; | ||
|
||
} // namespace Tiled | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -58,15 +58,19 @@ class Cell | |
_tileId(-1), | ||
_flippedHorizontally(false), | ||
_flippedVertically(false), | ||
_flippedAntiDiagonally(false) | ||
_flippedAntiDiagonally(false), | ||
_rotatedHexagonal60(false), | ||
_rotatedHexagonal120(false) | ||
{} | ||
|
||
explicit Cell(Tile *tile) : | ||
_tileset(tile ? tile->tileset() : nullptr), | ||
_tileId(tile ? tile->id() : -1), | ||
_flippedHorizontally(false), | ||
_flippedVertically(false), | ||
_flippedAntiDiagonally(false) | ||
_flippedAntiDiagonally(false), | ||
_rotatedHexagonal60(false), | ||
_rotatedHexagonal120(false) | ||
{} | ||
|
||
bool isEmpty() const { return _tileset == nullptr; } | ||
|
@@ -77,7 +81,9 @@ class Cell | |
&& _tileId == other._tileId | ||
&& _flippedHorizontally == other._flippedHorizontally | ||
&& _flippedVertically == other._flippedVertically | ||
&& _flippedAntiDiagonally == other._flippedAntiDiagonally; | ||
&& _flippedAntiDiagonally == other._flippedAntiDiagonally | ||
&& _rotatedHexagonal60 == other._rotatedHexagonal60 | ||
&& _rotatedHexagonal120 == other._rotatedHexagonal120; | ||
} | ||
|
||
bool operator != (const Cell &other) const | ||
|
@@ -86,7 +92,9 @@ class Cell | |
|| _tileId != other._tileId | ||
|| _flippedHorizontally != other._flippedHorizontally | ||
|| _flippedVertically != other._flippedVertically | ||
|| _flippedAntiDiagonally != other._flippedAntiDiagonally; | ||
|| _flippedAntiDiagonally != other._flippedAntiDiagonally | ||
|| _rotatedHexagonal60 != other._rotatedHexagonal60 | ||
|| _rotatedHexagonal120 != other._rotatedHexagonal120; | ||
} | ||
|
||
Tileset *tileset() const { return _tileset; } | ||
|
@@ -96,10 +104,16 @@ class Cell | |
bool flippedVertically() const { return _flippedVertically; } | ||
bool flippedAntiDiagonally() const { return _flippedAntiDiagonally; } | ||
|
||
bool rotatedHexagonal60() const { return _rotatedHexagonal60; } | ||
bool rotatedHexagonal120() const { return _rotatedHexagonal120; } | ||
|
||
void setFlippedHorizontally(bool f) { _flippedHorizontally = f; } | ||
void setFlippedVertically(bool f) { _flippedVertically = f; } | ||
void setFlippedAntiDiagonally(bool f) { _flippedAntiDiagonally = f; } | ||
|
||
void setRotatedHexagonal60(bool f) { _rotatedHexagonal60 = f; } | ||
void setRotatedHexagonal120(bool f) { _rotatedHexagonal120 = f; } | ||
|
||
Tile *tile() const; | ||
void setTile(Tile *tile); | ||
void setTile(Tileset *tileset, int tileId); | ||
|
@@ -111,6 +125,9 @@ class Cell | |
bool _flippedHorizontally; | ||
bool _flippedVertically; | ||
bool _flippedAntiDiagonally; | ||
|
||
bool _rotatedHexagonal60; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this is just an alias for |
||
bool _rotatedHexagonal120; | ||
}; | ||
|
||
inline Tile *Cell::tile() const | ||
|
@@ -237,13 +254,27 @@ class TILEDSHARED_EXPORT TileLayer : public Layer | |
*/ | ||
void flip(FlipDirection direction); | ||
|
||
/** | ||
* Hexagonal flip this tile layer in the given \a direction. Direction must be | ||
* horizontal or vertical. This doesn't change the dimensions of the | ||
* tile layer. | ||
*/ | ||
void flipHexagonal(FlipDirection direction); | ||
|
||
/** | ||
* Rotate this tile layer by 90 degrees left or right. The tile positions | ||
* are rotated within the layer, and the tiles themselves are rotated. The | ||
* dimensions of the tile layer are swapped. | ||
*/ | ||
void rotate(RotateDirection direction); | ||
|
||
/** | ||
* Hexagonal rotate this tile layer by 90 degrees left or right. The tile positions | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Documentation should mention 60 degrees here. |
||
* are rotated within the layer, and the tiles themselves are rotated. The | ||
* dimensions of the tile layer are swapped. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just realized that swapping the dimensions of the layer really makes no sense at all, and indeed the rotation of multiple tiles by 60 degrees doesn't really do anything useful. Essentially, the layer is rotated by 90 degrees while the tile graphics are getting rotated by 60 degrees. Is this something you have considered, and do you see a good solution to this? Of course, it doesn't help that trying to paint with a bigger stamp on a hex map doesn't work properly half the time due to the staggering. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. May be this documentation helps http://www.redblobgames.com/grids/hexagons/#rotation A bird in the hand is worth two in the bush ) Rotate group tile is good feature, but now it rather rotate a single tile for purposes in my application. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, so we can finish the basic feature first for single-tiles, and I can keep an issue open for making the rotation of groups work properly. That documentation definitely helps. |
||
*/ | ||
void rotateHexagonal(RotateDirection direction); | ||
|
||
/** | ||
* Computes and returns the set of tilesets used by this tile layer. | ||
*/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -232,7 +232,11 @@ TileStamp TileStamp::flipped(FlipDirection direction) const | |
|
||
for (const TileStampVariation &variation : flipped.variations()) { | ||
TileLayer *layer = variation.tileLayer(); | ||
layer->flip(direction); | ||
if (variation.map->orientation() != Map::Hexagonal) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer if |
||
layer->flip(direction); | ||
} else { | ||
layer->flipHexagonal(direction); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Coding style: please leave out the superfluous |
||
} | ||
|
||
return flipped; | ||
|
@@ -249,7 +253,11 @@ TileStamp TileStamp::rotated(RotateDirection direction) const | |
|
||
for (const TileStampVariation &variation : rotated.variations()) { | ||
TileLayer *layer = variation.tileLayer(); | ||
layer->rotate(direction); | ||
if (variation.map->orientation() != Map::Hexagonal) { | ||
layer->rotate(direction); | ||
} else { | ||
layer->rotateHexagonal(direction); | ||
} | ||
|
||
variation.map->setWidth(layer->width()); | ||
variation.map->setHeight(layer->height()); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had noted earlier that this variable didn't actually need to exist in this file, since it is just an alias for
FlippedAntiDiagonallyFlag
. As such it's also only causing duplicated processing below. OnlyRotatedHexagonal120Flag
needs to be added here.