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; }
void TileStampManager::newStamp() { TileStamp stamp = stampFromContext(mToolManager.selectedTool()); if (stamp.isEmpty()) return; mTileStampModel->addStamp(stamp); }
void TileStampManager::createQuickStamp(int index) { TileStamp stamp = stampFromContext(mToolManager.selectedTool()); if (stamp.isEmpty()) return; setQuickStamp(index, stamp); }
void TileStampManager::extendQuickStamp(int index) { TileStamp quickStamp = mQuickStamps[index]; if (quickStamp.isEmpty()) createQuickStamp(index); else addVariation(quickStamp); }
void TileStampManager::eraseQuickStamp(int index) { const TileStamp stamp = mQuickStamps.at(index); if (!stamp.isEmpty()) { mQuickStamps[index] = TileStamp(); if (!mQuickStamps.contains(stamp)) mTileStampModel->removeStamp(stamp); } }
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; }
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); }
void StampBrush::endCapture() { if (mBrushBehavior != Capture) return; mBrushBehavior = Free; TileStamp stamp = mCaptureStampHelper.endCapture(*mapDocument(), tilePosition()); if (!stamp.isEmpty()) emit stampChanged(TileStamp(stamp)); else updatePreview(); }
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()); }
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); } } }
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(); }
/** * 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; }
/** * 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; } }
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); }
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; }