-
-
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
Supporting Infinite Maps #1635
Supporting Infinite Maps #1635
Changes from 1 commit
2d1a3c8
44c2e2c
e4f1621
3650afd
309db5c
011043d
bc1c9c4
e937a65
ea2163c
9046a38
42ec140
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 |
---|---|---|
|
@@ -271,31 +271,42 @@ void TileLayer::erase(const QRegion &area) | |
|
||
void TileLayer::flip(FlipDirection direction) | ||
{ | ||
QVector<Cell> newGrid(mWidth * mHeight); | ||
TileLayer *newLayer = new TileLayer(QLatin1String(""), 0, 0, mWidth, mHeight); | ||
|
||
Q_ASSERT(direction == FlipHorizontally || direction == FlipVertically); | ||
|
||
for (int y = 0; y < mHeight; ++y) { | ||
for (int x = 0; x < mWidth; ++x) { | ||
Cell &dest = newGrid[x + y * mWidth]; | ||
if (direction == FlipHorizontally) { | ||
const Cell &source = cellAt(mWidth - x - 1, y); | ||
dest = source; | ||
dest.setFlippedHorizontally(!source.flippedHorizontally()); | ||
} else if (direction == FlipVertically) { | ||
const Cell &source = cellAt(x, mHeight - y - 1); | ||
dest = source; | ||
dest.setFlippedVertically(!source.flippedVertically()); | ||
QHashIterator<QPoint, Chunk* > it(mChunks); | ||
while (it.hasNext()) { | ||
it.next(); | ||
for (int y = 0; y < CHUNK_SIZE; ++y) { | ||
for (int x = 0; x < CHUNK_SIZE; ++x) { | ||
int _x = it.key().x() * CHUNK_SIZE + x; | ||
int _y = it.key().y() * CHUNK_SIZE + y; | ||
|
||
if (!contains(_x, _y)) | ||
continue; | ||
|
||
const Cell &source = it.value()->cellAt(x, y); | ||
Cell dest(source); | ||
|
||
if (direction == FlipHorizontally) { | ||
dest.setFlippedHorizontally(!source.flippedHorizontally()); | ||
newLayer->setCell(mWidth - _x - 1, _y, dest); | ||
} else if (direction == FlipVertically) { | ||
dest.setFlippedVertically(!source.flippedVertically()); | ||
newLayer->setCell(_x, mHeight -y - 1, dest); | ||
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. Missing space after 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. And it should be |
||
} | ||
} | ||
} | ||
} | ||
|
||
copyGrid(newGrid); | ||
mChunks = newLayer->mChunks; | ||
delete newLayer; | ||
} | ||
|
||
void TileLayer::flipHexagonal(FlipDirection direction) | ||
{ | ||
QVector<Cell> newGrid(mWidth * mHeight); | ||
TileLayer *newLayer = new TileLayer(QLatin1String(""), 0, 0, mWidth, mHeight); | ||
|
||
Q_ASSERT(direction == FlipHorizontally || direction == FlipVertically); | ||
|
||
|
@@ -305,28 +316,40 @@ void TileLayer::flipHexagonal(FlipDirection direction) | |
|
||
const char (&flipMask)[16] = (direction == FlipHorizontally ? flipMaskH : flipMaskV); | ||
|
||
for (int y = 0; y < mHeight; ++y) { | ||
for (int x = 0; x < mWidth; ++x) { | ||
const Cell &source = (direction == FlipHorizontally ? cellAt(mWidth - x - 1, y) : cellAt(x, mHeight - y - 1)); | ||
Cell &dest = newGrid[x + y * mWidth]; | ||
dest = source; | ||
|
||
unsigned char mask = | ||
(static_cast<unsigned char>(dest.flippedHorizontally()) << 3) | | ||
(static_cast<unsigned char>(dest.flippedVertically()) << 2) | | ||
(static_cast<unsigned char>(dest.flippedAntiDiagonally()) << 1) | | ||
(static_cast<unsigned char>(dest.rotatedHexagonal120()) << 0); | ||
|
||
mask = flipMask[mask]; | ||
|
||
dest.setFlippedHorizontally((mask & 8) != 0); | ||
dest.setFlippedVertically((mask & 4) != 0); | ||
dest.setFlippedAntiDiagonally((mask & 2) != 0); | ||
dest.setRotatedHexagonal120((mask & 1) != 0); | ||
QHashIterator<QPoint, Chunk* > it(mChunks); | ||
while (it.hasNext()) { | ||
it.next(); | ||
for (int y = 0; y < CHUNK_SIZE; ++y) { | ||
for (int x = 0; x < CHUNK_SIZE; ++x) { | ||
int _x = it.key().x() * CHUNK_SIZE + x; | ||
int _y = it.key().y() * CHUNK_SIZE + y; | ||
|
||
if (!contains(_x, _y)) | ||
continue; | ||
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 think instead of doing this contains check each time, it would be better to check |
||
|
||
Cell dest(it.value()->cellAt(x, y)); | ||
|
||
unsigned char mask = | ||
(static_cast<unsigned char>(dest.flippedHorizontally()) << 3) | | ||
(static_cast<unsigned char>(dest.flippedVertically()) << 2) | | ||
(static_cast<unsigned char>(dest.flippedAntiDiagonally()) << 1) | | ||
(static_cast<unsigned char>(dest.rotatedHexagonal120()) << 0); | ||
|
||
mask = flipMask[mask]; | ||
|
||
dest.setFlippedHorizontally((mask & 8) != 0); | ||
dest.setFlippedVertically((mask & 4) != 0); | ||
dest.setFlippedAntiDiagonally((mask & 2) != 0); | ||
dest.setRotatedHexagonal120((mask & 1) != 0); | ||
|
||
(direction == FlipHorizontally) ? newLayer->setCell(mWidth - _x - 1, _y, dest) | ||
: newLayer->setCell(_x, mHeight - _y - 1, dest); | ||
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 write this as an |
||
} | ||
} | ||
} | ||
|
||
copyGrid(newGrid); | ||
mChunks = newLayer->mChunks; | ||
delete newLayer; | ||
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 realized this only worked because we were never deleting the chunks. I've fixed that leak by pushing a change where the chunk instances are managed by the QHash. Btw, instead of manual deletion, please declare the QScopedPointer<TileLayer> newLayer |
||
} | ||
|
||
void TileLayer::rotate(RotateDirection direction) | ||
|
@@ -339,34 +362,44 @@ void TileLayer::rotate(RotateDirection direction) | |
|
||
int newWidth = mHeight; | ||
int newHeight = mWidth; | ||
QVector<Cell> newGrid(newWidth * newHeight); | ||
TileLayer *newLayer = new TileLayer(QLatin1String(""), 0, 0, newWidth, newHeight); | ||
|
||
for (int y = 0; y < mHeight; ++y) { | ||
for (int x = 0; x < mWidth; ++x) { | ||
const Cell &source = cellAt(x, y); | ||
Cell dest = source; | ||
QHashIterator<QPoint, Chunk* > it(mChunks); | ||
while (it.hasNext()) { | ||
it.next(); | ||
for (int y = 0; y < CHUNK_SIZE; ++y) { | ||
for (int x = 0; x < CHUNK_SIZE; ++x) { | ||
int _x = it.key().x() * CHUNK_SIZE + x; | ||
int _y = it.key().y() * CHUNK_SIZE + y; | ||
|
||
unsigned char mask = | ||
(dest.flippedHorizontally() << 2) | | ||
(dest.flippedVertically() << 1) | | ||
(dest.flippedAntiDiagonally() << 0); | ||
if (!contains(_x, _y)) | ||
continue; | ||
|
||
mask = rotateMask[mask]; | ||
Cell dest(it.value()->cellAt(x, y)); | ||
|
||
dest.setFlippedHorizontally((mask & 4) != 0); | ||
dest.setFlippedVertically((mask & 2) != 0); | ||
dest.setFlippedAntiDiagonally((mask & 1) != 0); | ||
unsigned char mask = | ||
(dest.flippedHorizontally() << 2) | | ||
(dest.flippedVertically() << 1) | | ||
(dest.flippedAntiDiagonally() << 0); | ||
|
||
if (direction == RotateRight) | ||
newGrid[x * newWidth + (mHeight - y - 1)] = dest; | ||
else | ||
newGrid[(mWidth - x - 1) * newWidth + y] = dest; | ||
mask = rotateMask[mask]; | ||
|
||
dest.setFlippedHorizontally((mask & 4) != 0); | ||
dest.setFlippedVertically((mask & 2) != 0); | ||
dest.setFlippedAntiDiagonally((mask & 1) != 0); | ||
|
||
if (direction == RotateRight) | ||
newLayer->setCell(mHeight - _y - 1, _x, dest); | ||
else | ||
newLayer->setCell(_y, mWidth - _x - 1, dest); | ||
} | ||
} | ||
} | ||
|
||
mWidth = newWidth; | ||
mHeight = newHeight; | ||
copyGrid(newGrid); | ||
mChunks = newLayer->mChunks; | ||
delete newLayer; | ||
} | ||
|
||
void TileLayer::rotateHexagonal(RotateDirection direction, Map *map) | ||
|
@@ -386,7 +419,7 @@ void TileLayer::rotateHexagonal(RotateDirection direction, Map *map) | |
|
||
int newWidth = topRight.toStaggered(staggerIndex, staggerAxis).x() * 2 + 2; | ||
int newHeight = bottomRight.toStaggered(staggerIndex, staggerAxis).y() * 2 + 2; | ||
QVector<Cell> newGrid(newWidth * newHeight); | ||
TileLayer *newLayer = new TileLayer(QLatin1String(""), 0, 0, newWidth, newHeight); | ||
|
||
Hex newCenter(newWidth / 2, newHeight / 2, staggerIndex, staggerAxis); | ||
|
||
|
@@ -414,40 +447,48 @@ void TileLayer::rotateHexagonal(RotateDirection direction, Map *map) | |
const char (&rotateMask)[16] = | ||
(direction == RotateRight) ? rotateRightMask : rotateLeftMask; | ||
|
||
for (int y = 0; y < mHeight; ++y) { | ||
for (int x = 0; x < mWidth; ++x) { | ||
const Cell &source = cellAt(x, y); | ||
Cell dest = source; | ||
QHashIterator<QPoint, Chunk* > it(mChunks); | ||
while (it.hasNext()) { | ||
it.next(); | ||
for (int y = 0; y < CHUNK_SIZE; ++y) { | ||
for (int x = 0; x < CHUNK_SIZE; ++x) { | ||
int _x = it.key().x() * CHUNK_SIZE + x; | ||
int _y = it.key().y() * CHUNK_SIZE + y; | ||
|
||
if (!contains(_x, _y)) | ||
continue; | ||
|
||
unsigned char mask = | ||
(static_cast<unsigned char>(dest.flippedHorizontally()) << 3) | | ||
(static_cast<unsigned char>(dest.flippedVertically()) << 2) | | ||
(static_cast<unsigned char>(dest.flippedAntiDiagonally()) << 1) | | ||
(static_cast<unsigned char>(dest.rotatedHexagonal120()) << 0); | ||
Cell dest(it.value()->cellAt(x, y)); | ||
|
||
mask = rotateMask[mask]; | ||
unsigned char mask = | ||
(static_cast<unsigned char>(dest.flippedHorizontally()) << 3) | | ||
(static_cast<unsigned char>(dest.flippedVertically()) << 2) | | ||
(static_cast<unsigned char>(dest.flippedAntiDiagonally()) << 1) | | ||
(static_cast<unsigned char>(dest.rotatedHexagonal120()) << 0); | ||
|
||
dest.setFlippedHorizontally((mask & 8) != 0); | ||
dest.setFlippedVertically((mask & 4) != 0); | ||
dest.setFlippedAntiDiagonally((mask & 2) != 0); | ||
dest.setRotatedHexagonal120((mask & 1) != 0); | ||
mask = rotateMask[mask]; | ||
|
||
Hex rotatedHex(x, y, staggerIndex, staggerAxis); | ||
rotatedHex -= center; | ||
rotatedHex.rotate(direction); | ||
rotatedHex += newCenter; | ||
dest.setFlippedHorizontally((mask & 8) != 0); | ||
dest.setFlippedVertically((mask & 4) != 0); | ||
dest.setFlippedAntiDiagonally((mask & 2) != 0); | ||
dest.setRotatedHexagonal120((mask & 1) != 0); | ||
|
||
QPoint rotatedPoint = rotatedHex.toStaggered(staggerIndex, staggerAxis); | ||
Hex rotatedHex(_x, _y, staggerIndex, staggerAxis); | ||
rotatedHex -= center; | ||
rotatedHex.rotate(direction); | ||
rotatedHex += newCenter; | ||
|
||
int index = rotatedPoint.y() * newWidth + rotatedPoint.x(); | ||
QPoint rotatedPoint = rotatedHex.toStaggered(staggerIndex, staggerAxis); | ||
|
||
newGrid[index] = dest; | ||
newLayer->setCell(rotatedPoint.x(), rotatedPoint.y(), dest); | ||
} | ||
} | ||
} | ||
|
||
mWidth = newWidth; | ||
mHeight = newHeight; | ||
copyGrid(newGrid); | ||
mChunks = newLayer->mChunks; | ||
delete newLayer; | ||
|
||
QRect filledRect = region().boundingRect(); | ||
|
||
|
@@ -551,45 +592,56 @@ void TileLayer::offsetTiles(const QPoint &offset, | |
const QRect &bounds, | ||
bool wrapX, bool wrapY) | ||
{ | ||
QVector<Cell> newGrid(mWidth * mHeight); | ||
TileLayer *newLayer = clone(); | ||
|
||
for (int y = 0; y < mHeight; ++y) { | ||
for (int x = 0; x < mWidth; ++x) { | ||
// Skip out of bounds tiles | ||
if (!bounds.contains(x, y)) { | ||
newGrid[x + y * mWidth] = cellAt(x, y); | ||
continue; | ||
} | ||
QHashIterator<QPoint, Chunk* > it(newLayer->mChunks); | ||
while (it.hasNext()) { | ||
it.next(); | ||
for (int y = 0; y < CHUNK_SIZE; ++y) { | ||
for (int x = 0; x < CHUNK_SIZE; ++x) { | ||
int _x = it.key().x() * CHUNK_SIZE + x; | ||
int _y = it.key().y() * CHUNK_SIZE + y; | ||
|
||
if (!contains(_x, _y)) | ||
continue; | ||
|
||
// Skip out of bounds tiles | ||
if (!bounds.contains(_x, _y)) { | ||
newLayer->setCell(x, y, cellAt(_x, _y)); | ||
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. You don't need to do this, since the 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. That would mean iterating like this, right?
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. Yes, though you can use for (int y = bounds.top(); y <= bounds.bottom(); ++y) {
for (int x = bounds.left(); x <= bounds.right(); ++x) {
...
}
} Edit: and reversed the iteration order. |
||
continue; | ||
} | ||
|
||
// Get position to pull tile value from | ||
int oldX = x - offset.x(); | ||
int oldY = y - offset.y(); | ||
// Get position to pull tile value from | ||
int oldX = _x - offset.x(); | ||
int oldY = _y - offset.y(); | ||
|
||
// Wrap x value that will be pulled from | ||
if (wrapX && bounds.width() > 0) { | ||
while (oldX < bounds.left()) | ||
oldX += bounds.width(); | ||
while (oldX > bounds.right()) | ||
oldX -= bounds.width(); | ||
} | ||
// Wrap x value that will be pulled from | ||
if (wrapX && bounds.width() > 0) { | ||
while (oldX < bounds.left()) | ||
oldX += bounds.width(); | ||
while (oldX > bounds.right()) | ||
oldX -= bounds.width(); | ||
} | ||
|
||
// Wrap y value that will be pulled from | ||
if (wrapY && bounds.height() > 0) { | ||
while (oldY < bounds.top()) | ||
oldY += bounds.height(); | ||
while (oldY > bounds.bottom()) | ||
oldY -= bounds.height(); | ||
} | ||
// Wrap y value that will be pulled from | ||
if (wrapY && bounds.height() > 0) { | ||
while (oldY < bounds.top()) | ||
oldY += bounds.height(); | ||
while (oldY > bounds.bottom()) | ||
oldY -= bounds.height(); | ||
} | ||
|
||
// Set the new tile | ||
if (contains(oldX, oldY) && bounds.contains(oldX, oldY)) | ||
newGrid[x + y * mWidth] = cellAt(oldX, oldY); | ||
else | ||
newGrid[x + y * mWidth] = Cell(); | ||
// Set the new tile | ||
if (contains(oldX, oldY) && bounds.contains(oldX, oldY)) | ||
newLayer->setCell(x, y, cellAt(oldX, oldY)); | ||
else | ||
newLayer->setCell(x, y, Cell()); | ||
} | ||
} | ||
} | ||
|
||
copyGrid(newGrid); | ||
mChunks = newLayer->mChunks; | ||
delete newLayer; | ||
} | ||
|
||
bool TileLayer::canMergeWith(Layer *other) const | ||
|
@@ -669,12 +721,3 @@ TileLayer *TileLayer::initializeClone(TileLayer *clone) const | |
clone->mUsedTilesetsDirty = mUsedTilesetsDirty; | ||
return clone; | ||
} | ||
|
||
void TileLayer::copyGrid(const QVector<Cell> &newGrid) | ||
{ | ||
for (int y = 0; y < mHeight; ++y) { | ||
for (int x = 0; x < mWidth; ++x) { | ||
setCell(x, y, newGrid[x + y * mWidth]); | ||
} | ||
} | ||
} |
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.
The way to make an empty string is
QString()
.