예제 #1
0
파일: tilestamp.cpp 프로젝트: bjorn/tiled
TileStamp TileStamp::fromJson(const QJsonObject &json, const QDir &mapDir)
{
    TileStamp stamp;

    stamp.setName(json.value(QLatin1String("name")).toString());
    stamp.setQuickStampIndex(static_cast<int>(json.value(QLatin1String("quickStampIndex")).toDouble(-1)));

    const QJsonArray variations = json.value(QLatin1String("variations")).toArray();
    for (const QJsonValue value : variations) {
        QJsonObject variationJson = value.toObject();

        QVariant mapVariant = variationJson.value(QLatin1String("map")).toVariant();
        VariantToMapConverter converter;
        auto map = converter.toMap(mapVariant, mapDir);
        if (!map) {
            qDebug() << "Failed to load map for stamp:" << converter.errorString();
            continue;
        }

        qreal probability = variationJson.value(QLatin1String("probability")).toDouble(1);

        stamp.addVariation(std::move(map), probability);
    }

    return stamp;
}
예제 #2
0
void TileStampManager::newStamp()
{
    TileStamp stamp = stampFromContext(mToolManager.selectedTool());
    if (stamp.isEmpty())
        return;

    mTileStampModel->addStamp(stamp);
}
예제 #3
0
void TileStampManager::createQuickStamp(int index)
{
    TileStamp stamp = stampFromContext(mToolManager.selectedTool());
    if (stamp.isEmpty())
        return;

    setQuickStamp(index, stamp);
}
예제 #4
0
void TileStampManager::extendQuickStamp(int index)
{
    TileStamp quickStamp = mQuickStamps[index];

    if (quickStamp.isEmpty())
        createQuickStamp(index);
    else
        addVariation(quickStamp);
}
예제 #5
0
void TileStampManager::eraseQuickStamp(int index)
{
    const TileStamp stamp = mQuickStamps.at(index);
    if (!stamp.isEmpty()) {
        mQuickStamps[index] = TileStamp();

        if (!mQuickStamps.contains(stamp))
            mTileStampModel->removeStamp(stamp);
    }
}
예제 #6
0
void TileStampManager::setQuickStamp(int index, TileStamp stamp)
{
    stamp.setName(tr("Quickstamp %1").arg(index + 1));
    stamp.setQuickStampIndex(index);

    // make sure existing quickstamp is removed from stamp model
    eraseQuickStamp(index);

    mTileStampModel->addStamp(stamp);

    mQuickStamps[index] = stamp;
}
예제 #7
0
void TileStampManager::addVariation(const TileStamp &targetStamp)
{
    TileStamp stamp = stampFromContext(mToolManager.selectedTool());
    if (stamp.isEmpty())
        return;

    if (stamp == targetStamp) // avoid easy mistake of adding duplicates
        return;

    foreach (const TileStampVariation &variation, stamp.variations())
        mTileStampModel->addVariation(targetStamp, variation);
}
예제 #8
0
void StampBrush::endCapture()
{
    if (mBrushBehavior != Capture)
        return;

    mBrushBehavior = Free;

    TileStamp stamp = mCaptureStampHelper.endCapture(*mapDocument(), tilePosition());
    if (!stamp.isEmpty())
        emit stampChanged(TileStamp(stamp));
    else
        updatePreview();
}
예제 #9
0
void TileStampsDock::duplicate()
{
    const QModelIndex index = mTileStampView->currentIndex();
    if (!index.isValid())
        return;

    const QModelIndex sourceIndex = mProxyModel->mapToSource(index);
    if (!mTileStampModel->isStamp(sourceIndex))
        return;

    TileStamp stamp = mTileStampModel->stampAt(sourceIndex);
    mTileStampModel->addStamp(stamp.clone());
}
예제 #10
0
void TileStampsDock::newStamp()
{
    TileStamp stamp = mTileStampManager->createStamp();

    if (isVisible() && !stamp.isEmpty()) {
        QModelIndex stampIndex = mTileStampModel->index(stamp);
        if (stampIndex.isValid()) {
            QModelIndex viewIndex = mProxyModel->mapFromSource(stampIndex);
            mTileStampView->setCurrentIndex(viewIndex);
            mTileStampView->edit(viewIndex);
        }
    }
}
예제 #11
0
void AbstractTileFillTool::mouseReleased(QGraphicsSceneMouseEvent *event)
{
    if (event->button() == Qt::RightButton && mCaptureStampHelper.isActive()) {
        clearOverlay();

        TileStamp stamp = mCaptureStampHelper.endCapture(*mapDocument(), tilePosition());
        if (!stamp.isEmpty())
            emit stampChanged(stamp);

        return;
    }

    event->ignore();
}
예제 #12
0
/**
 * A helper method that returns the possible target layers of a given \a stamp.
 */
QList<Layer *> AbstractTileTool::targetLayersForStamp(const TileStamp &stamp) const
{
    QList<Layer*> layers;

    if (!mapDocument())
        return layers;

    const Map &map = *mapDocument()->map();

    for (const TileStampVariation &variation : stamp.variations()) {
        LayerIterator it(variation.map, Layer::TileLayerType);
        const Layer *firstLayer = it.next();
        const bool isMultiLayer = firstLayer && it.next();

        if (isMultiLayer && !firstLayer->name().isEmpty()) {
            for (Layer *layer : variation.map->tileLayers()) {
                TileLayer *target = static_cast<TileLayer*>(map.findLayer(layer->name(), Layer::TileLayerType));
                if (!layers.contains(target))
                    layers.append(target);
            }
        } else {
            if (TileLayer *tileLayer = currentTileLayer())
                if (!layers.contains(tileLayer))
                    layers.append(tileLayer);
        }
    }

    return layers;
}
예제 #13
0
/**
 * Synchronizes the selection with the given stamp. Ignored when the stamp is
 * changing because of a selection change in the TilesetDock.
 */
void TilesetDock::selectTilesInStamp(const TileStamp &stamp)
{
    if (mEmittingStampCaptured)
        return;

    QSet<Tile*> processed;
    QMap<QItemSelectionModel*, QItemSelection> selections;

    for (const TileStampVariation &variation : stamp.variations()) {
        const TileLayer &tileLayer = *variation.tileLayer();
        for (const Cell &cell : tileLayer) {
            if (Tile *tile = cell.tile) {
                if (processed.contains(tile))
                    continue;

                processed.insert(tile); // avoid spending time on duplicates

                Tileset *tileset = tile->tileset();
                int tilesetIndex = mTilesets.indexOf(tileset->sharedPointer());
                if (tilesetIndex != -1) {
                    TilesetView *view = tilesetViewAt(tilesetIndex);
                    if (!view->model()) // Lazily set up the model
                        setupTilesetModel(view, tileset);

                    const TilesetModel *model = view->tilesetModel();
                    const QModelIndex modelIndex = model->tileIndex(tile);
                    QItemSelectionModel *selectionModel = view->selectionModel();
                    selections[selectionModel].select(modelIndex, modelIndex);
                }
            }
        }
    }

    if (!selections.isEmpty()) {
        mSynchronizingSelection = true;

        // Mark captured tiles as selected
        for (auto i = selections.constBegin(); i != selections.constEnd(); ++i) {
            QItemSelectionModel *selectionModel = i.key();
            const QItemSelection &selection = i.value();
            selectionModel->select(selection, QItemSelectionModel::SelectCurrent);
        }

        // Show/edit properties of all captured tiles
        mMapDocument->setSelectedTiles(processed.toList());

        // Update the current tile (useful for animation and collision editors)
        auto first = selections.begin();
        QItemSelectionModel *selectionModel = first.key();
        const QItemSelection &selection = first.value();
        const QModelIndex currentIndex = selection.first().topLeft();
        if (selectionModel->currentIndex() != currentIndex)
            selectionModel->setCurrentIndex(currentIndex, QItemSelectionModel::NoUpdate);
        else
            currentChanged(currentIndex);

        mSynchronizingSelection = false;
    }
}
예제 #14
0
static void fillWithStamp(TileLayer &layer,
                          const TileStamp &stamp,
                          const QRegion &mask)
{
    const QSize size = stamp.maxSize();

    // Fill the entire layer with random variations of the stamp
    for (int y = 0; y < layer.height(); y += size.height()) {
        for (int x = 0; x < layer.width(); x += size.width()) {
            const TileStampVariation variation = stamp.randomVariation();
            layer.setCells(x, y, variation.tileLayer());
        }
    }

    // Erase tiles outside of the masked region. This can easily be faster than
    // avoiding to place tiles outside of the region in the first place.
    layer.erase(QRegion(0, 0, layer.width(), layer.height()) - mask);
}
예제 #15
0
static TileStamp stampFromContext(AbstractTool *selectedTool)
{
    TileStamp stamp;

    if (StampBrush *stampBrush = dynamic_cast<StampBrush*>(selectedTool)) {
        // take the stamp from the stamp brush
        stamp = stampBrush->stamp();
    } else if (BucketFillTool *fillTool = dynamic_cast<BucketFillTool*>(selectedTool)) {
        // take the stamp from the fill tool
        stamp = fillTool->stamp();
    } else if (MapDocument *mapDocument = DocumentManager::instance()->currentDocument()) {
        // try making a stamp from the current tile selection
        const TileLayer *tileLayer =
                dynamic_cast<TileLayer*>(mapDocument->currentLayer());
        if (!tileLayer)
            return stamp;

        QRegion selection = mapDocument->selectedArea();
        if (selection.isEmpty())
            return stamp;

        selection.translate(-tileLayer->position());
        QScopedPointer<TileLayer> copy(tileLayer->copy(selection));

        if (copy->size().isEmpty())
            return stamp;

        const Map *map = mapDocument->map();
        Map *copyMap = new Map(map->orientation(),
                               copy->width(), copy->height(),
                               map->tileWidth(), map->tileHeight());

        // Add tileset references to map
        foreach (const SharedTileset &tileset, copy->usedTilesets())
            copyMap->addTileset(tileset);

        copyMap->setRenderOrder(map->renderOrder());
        copyMap->addLayer(copy.take());

        stamp.addVariation(copyMap);
    }

    return stamp;
}