Ejemplo n.º 1
0
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 {
Ejemplo n.º 2
0
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();
    }
}
Ejemplo n.º 3
0
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 {
Ejemplo n.º 4
0
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();
}
Ejemplo n.º 5
0
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;
}