Ejemplo n.º 1
0
void ShapeFillTool::mouseReleased(QGraphicsSceneMouseEvent *event)
{
    AbstractTileFillTool::mouseReleased(event);

    if (mToolBehavior != MakingShape)
        return;

    if (event->button() == Qt::LeftButton) {
        mToolBehavior = Free;

        TileLayer *tileLayer = currentTileLayer();
        if (!tileLayer)
            return;

        if (!brushItem()->isVisible() || !tileLayer->isUnlocked())
            return;

        const TileLayer *preview = mFillOverlay.data();
        if (!preview)
            return;

        PaintTileLayer *paint = new PaintTileLayer(mapDocument(),
                                                   tileLayer,
                                                   preview->x(),
                                                   preview->y(),
                                                   preview);

        paint->setText(QCoreApplication::translate("Undo Commands", "Shape Fill"));

        if (!mMissingTilesets.isEmpty()) {
            for (const SharedTileset &tileset : mMissingTilesets) {
                if (!mapDocument()->map()->tilesets().contains(tileset))
                    new AddTileset(mapDocument(), tileset, paint);
            }

            mMissingTilesets.clear();
        }

        QRegion fillRegion(mFillRegion);
        mapDocument()->undoStack()->push(paint);
        emit mapDocument()->regionEdited(fillRegion, currentTileLayer());

        mFillRegion = QRegion();
        mFillOverlay.clear();
        brushItem()->clear();
    }
}
Ejemplo n.º 2
0
/**
 * Paints the tile layers present in the given \a map onto this map. Matches
 * layers by name and creates new layers when they could not be found.
 *
 * In case the \a map only contains a single tile layer, it is always painted
 * into the current tile layer. This happens also for unnamed layers. In these
 * cases, the layers are skipped when the current layer isn't a tile layer.
 *
 * If the matched target layer is locked it is also skipped.
 *
 * \a mergeable indicates whether the paint operations performed by this
 * function are mergeable with previous compatible paint operations.
 *
 * If \a missingTilesets is given, the listed tilesets will be added to the map
 * on the first paint operation. The list will then be cleared.
 *
 * If \a paintedRegions is given, then no regionEdited signal is emitted.
 * In this case it is the responsibility of the caller to emit this signal for
 * each affected tile layer.
 */
void MapDocument::paintTileLayers(const Map *map, bool mergeable,
                                  QVector<SharedTileset> *missingTilesets,
                                  QHash<TileLayer*, QRegion> *paintedRegions)
{
    TileLayer *currentTileLayer = mCurrentLayer ? mCurrentLayer->asTileLayer() : nullptr;

    LayerIterator it(map, Layer::TileLayerType);
    const bool isMultiLayer = it.next() && it.next();

    it.toFront();
    while (auto tileLayer = static_cast<TileLayer*>(it.next())) {
        TileLayer *targetLayer = currentTileLayer;
        bool addLayer = false;

        // When the map contains only a single layer, always paint it into
        // the current layer. This makes sure you can still take pieces from
        // one layer and draw them into another.
        if (isMultiLayer && !tileLayer->name().isEmpty()) {
            targetLayer = static_cast<TileLayer*>(mMap->findLayer(tileLayer->name(), Layer::TileLayerType));
            if (!targetLayer) {
                // Create a layer with this name
                targetLayer = new TileLayer(tileLayer->name(), 0, 0,
                                            mMap->width(),
                                            mMap->height());
                addLayer = true;
            }
        }

        if (!targetLayer)
            continue;
        if (!targetLayer->isUnlocked())
            continue;
        if (!mMap->infinite() && !targetLayer->rect().intersects(tileLayer->bounds()))
            continue;

        PaintTileLayer *paint = new PaintTileLayer(this,
                                                   targetLayer,
                                                   tileLayer->x(),
                                                   tileLayer->y(),
                                                   tileLayer);

        if (missingTilesets && !missingTilesets->isEmpty()) {
            for (const SharedTileset &tileset : *missingTilesets) {
                if (!mMap->tilesets().contains(tileset))
                    new AddTileset(this, tileset, paint);
            }

            missingTilesets->clear();
        }

        if (addLayer) {
            new AddLayer(this,
                         mMap->layerCount(), targetLayer, nullptr,
                         paint);
        }

        paint->setMergeable(mergeable);
        undoStack()->push(paint);

        const QRegion editedRegion = tileLayer->region();
        if (paintedRegions)
            (*paintedRegions)[targetLayer] |= editedRegion;
        else
            emit regionEdited(editedRegion, targetLayer);

        mergeable = true; // further paints are always mergeable
    }
}