void StampBrush::endCapture() { if (mBrushBehavior != Capture) return; mBrushBehavior = Free; TileLayer *tileLayer = currentTileLayer(); Q_ASSERT(tileLayer); // Intersect with the layer and translate to layer coordinates QRect captured = capturedArea(); captured &= QRect(tileLayer->x(), tileLayer->y(), tileLayer->width(), tileLayer->height()); if (captured.isValid()) { captured.translate(-tileLayer->x(), -tileLayer->y()); Map *map = tileLayer->map(); TileLayer *capture = tileLayer->copy(captured); Map *stamp = new Map(map->orientation(), capture->width(), capture->height(), map->tileWidth(), map->tileHeight()); // Add tileset references to map foreach (const SharedTileset &tileset, capture->usedTilesets()) stamp->addTileset(tileset); stamp->addLayer(capture); emit stampCaptured(TileStamp(stamp)); } else {
void StampBrush::endCapture() { if (mBrushBehavior != Capture) return; mBrushBehavior = Free; TileLayer *tileLayer = currentTileLayer(); Q_ASSERT(tileLayer); // Intersect with the layer and translate to layer coordinates QRect captured = capturedArea(); captured.intersect(QRect(tileLayer->x(), tileLayer->y(), tileLayer->width(), tileLayer->height())); if (captured.isValid()) { captured.translate(-tileLayer->x(), -tileLayer->y()); TileLayer *capture = tileLayer->copy(captured); emit currentTilesChanged(capture); // A copy will have been created, so delete this version delete capture; } else { updatePosition(); } }
void StampBrush::endCapture() { if (mBrushBehavior != Capture) return; mBrushBehavior = Free; TileLayer *tileLayer = currentTileLayer(); Q_ASSERT(tileLayer); // Intersect with the layer and translate to layer coordinates QRect captured = capturedArea(); captured &= QRect(tileLayer->x(), tileLayer->y(), tileLayer->width(), tileLayer->height()); if (captured.isValid()) { captured.translate(-tileLayer->x(), -tileLayer->y()); Map *map = tileLayer->map(); TileLayer *capture = tileLayer->copy(captured); Map *stamp = new Map(map->orientation(), capture->width(), capture->height(), map->tileWidth(), map->tileHeight()); //gets if the relative stagger should be the same as the base layer int staggerIndexOffSet; if (tileLayer->map()->staggerAxis() == Map::StaggerX) staggerIndexOffSet = captured.x() % 2; else staggerIndexOffSet = captured.y() % 2; stamp->setStaggerAxis(map->staggerAxis()); stamp->setStaggerIndex((Map::StaggerIndex)((map->staggerIndex() + staggerIndexOffSet) % 2)); // Add tileset references to map foreach (const SharedTileset &tileset, capture->usedTilesets()) stamp->addTileset(tileset); stamp->addLayer(capture); emit stampCaptured(TileStamp(stamp)); } else {
void BucketFillTool::tilePositionChanged(const QPoint &tilePos) { bool shiftPressed = QApplication::keyboardModifiers() & Qt::ShiftModifier; // Optimization: we don't need to recalculate the fill area // if the new mouse position is still over the filled region // and the shift modifier hasn't changed. if (mFillRegion.contains(tilePos) && shiftPressed == mLastShiftStatus) return; // Cache information about how the fill region was created mLastShiftStatus = shiftPressed; // Clear overlay to make way for a new one // This also clears the connections so we don't get callbacks clearOverlay(); // Skip filling if the stamp is empty if (!mStamp || mStamp->isEmpty()) return; // Make sure that a tile layer is selected TileLayer *tileLayer = currentTileLayer(); if (!tileLayer) return; // Get the new fill region if (!shiftPressed) { // If not holding shift, a region is generated from the current pos TilePainter regionComputer(mapDocument(), tileLayer); // If the stamp is a single tile, ignore it when making the region if (mStamp->width() == 1 && mStamp->height() == 1 && mStamp->cellAt(0, 0) == regionComputer.cellAt(tilePos.x(), tilePos.y())) return; mFillRegion = regionComputer.computeFillRegion(tilePos); } else { // If holding shift, the region is the selection bounds mFillRegion = mapDocument()->tileSelection(); // Fill region is the whole map is there is no selection if (mFillRegion.isEmpty()) mFillRegion = tileLayer->bounds(); // The mouse needs to be in the region if (!mFillRegion.contains(tilePos)) mFillRegion = QRegion(); } // Ensure that a fill region was created before making an overlay layer if (mFillRegion.isEmpty()) return; // Create a new overlay region mFillOverlay = new TileLayer(QString(), tileLayer->x(), tileLayer->y(), tileLayer->width(), tileLayer->height()); // Paint the new overlay TilePainter tilePainter(mapDocument(), mFillOverlay); tilePainter.drawStamp(mStamp, mFillRegion); // Crop the overlay to the smallest possible size const QRect fillBounds = mFillRegion.boundingRect(); mFillOverlay->resize(fillBounds.size(), -fillBounds.topLeft()); mFillOverlay->setX(fillBounds.x()); mFillOverlay->setY(fillBounds.y()); // Update the brush item to draw the overlay brushItem()->setTileLayer(mFillOverlay); // Create connections to know when the overlay should be cleared makeConnections(); }
TileLayer *WangFiller::fillRegion(const TileLayer &back, const QRegion &fillRegion) const { Q_ASSERT(mWangSet); QRect boundingRect = fillRegion.boundingRect(); TileLayer *tileLayer = new TileLayer(QString(), boundingRect.x(), boundingRect.y(), boundingRect.width(), boundingRect.height()); QVector<WangId> wangIds(tileLayer->width() * tileLayer->height(), 0); for (const QRect &rect : fillRegion.rects()) { for (int x = rect.left(); x <= rect.right(); ++x) { int index = x - tileLayer->x() + (rect.top() - tileLayer->y()) * tileLayer->width(); wangIds[index] = wangIdFromSurroundings(back, fillRegion, QPoint(x, rect.top())); index = x - tileLayer->x() + (rect.bottom() - tileLayer->y())*tileLayer->width(); wangIds[index] = wangIdFromSurroundings(back, fillRegion, QPoint(x, rect.bottom())); } for (int y = rect.top() + 1; y < rect.bottom(); ++y) { int index = rect.left() - tileLayer->x() + (y - tileLayer->y())*tileLayer->width(); wangIds[index] = wangIdFromSurroundings(back, fillRegion, QPoint(rect.left(), y)); index = rect.right() - tileLayer->x() + (y - tileLayer->y())*tileLayer->width(); wangIds[index] = wangIdFromSurroundings(back, fillRegion, QPoint(rect.right(), y)); } } for (const QRect &rect : fillRegion.rects()) { for (int y = rect.top(); y <= rect.bottom(); ++y) { for (int x = rect.left(); x <= rect.right(); ++x) { QPoint currentPoint(x, y); int currentIndex = (currentPoint.y() - tileLayer->y()) * tileLayer->width() + (currentPoint.x() - tileLayer->x()); QList<WangTile> wangTilesList = mWangSet->findMatchingWangTiles(wangIds[currentIndex]); RandomPicker<WangTile> wangTiles; for (const WangTile &wangTile : wangTilesList) wangTiles.add(wangTile, mWangSet->wangTileProbability(wangTile)); while (!wangTiles.isEmpty()) { WangTile wangTile = wangTiles.take(); bool fill = true; if (!mWangSet->isComplete()) { QPoint adjacentPoints[8]; getSurroundingPoints(currentPoint, mStaggeredRenderer, mStaggerAxis, adjacentPoints); for (int i = 0; i < 8; ++i) { QPoint p = adjacentPoints[i]; if (!fillRegion.contains(p) || !tileLayer->cellAt(p - tileLayer->position()).isEmpty()) continue; p -= tileLayer->position(); int index = p.y() * tileLayer->width() + p.x(); WangId adjacentWangId = wangIds[index]; adjacentWangId.updateToAdjacent(wangTile.wangId(), (i + 4) % 8); if (!mWangSet->wildWangIdIsUsed(adjacentWangId)) { fill = wangTiles.isEmpty(); break; } } } if (fill) { tileLayer->setCell(currentPoint.x() - tileLayer->x(), currentPoint.y() - tileLayer->y(), wangTile.makeCell()); QPoint adjacentPoints[8]; getSurroundingPoints(currentPoint, mStaggeredRenderer, mStaggerAxis, adjacentPoints); for (int i = 0; i < 8; ++i) { QPoint p = adjacentPoints[i]; if (!fillRegion.contains(p) || !tileLayer->cellAt(p - tileLayer->position()).isEmpty()) continue; p -= tileLayer->position(); int index = p.y() * tileLayer->width() + p.x(); wangIds[index].updateToAdjacent(wangTile.wangId(), (i + 4) % 8); } break; } } } } } return tileLayer; }