void TilesetDock::removeTiles() { TilesetView *view = currentTilesetView(); if (!view) return; if (!view->selectionModel()->hasSelection()) return; const QModelIndexList indexes = view->selectionModel()->selectedIndexes(); const TilesetModel *model = view->tilesetModel(); QList<Tile*> tiles; for (const QModelIndex &index : indexes) if (Tile *tile = model->tileAt(index)) tiles.append(tile); auto matchesAnyTile = [&tiles] (const Cell &cell) { if (Tile *tile = cell.tile) return tiles.contains(tile); return false; }; const bool inUse = hasTileReferences(mMapDocument, matchesAnyTile); // If the tileset is in use, warn the user and confirm removal if (inUse) { QMessageBox warning(QMessageBox::Warning, tr("Remove Tiles"), tr("One or more of the tiles to be removed are " "still in use by the map!"), QMessageBox::Yes | QMessageBox::No, this); warning.setDefaultButton(QMessageBox::Yes); warning.setInformativeText(tr("Remove all references to these tiles?")); if (warning.exec() != QMessageBox::Yes) return; } QUndoStack *undoStack = mMapDocument->undoStack(); undoStack->beginMacro(tr("Remove Tiles")); if (inUse) removeTileReferences(mMapDocument, matchesAnyTile); Tileset *tileset = view->tilesetModel()->tileset(); undoStack->push(new RemoveTiles(mMapDocument, tileset, tiles)); undoStack->endMacro(); // Clear the current tiles, will be referencing the removed tiles setCurrentTiles(nullptr); setCurrentTile(nullptr); }
/** * 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; } }
void TilesetDock::tileImageSourceChanged(Tile *tile) { int tilesetIndex = mTilesets.indexOf(tile->tileset()->sharedPointer()); if (tilesetIndex != -1) { TilesetView *view = tilesetViewAt(tilesetIndex); if (TilesetModel *model = view->tilesetModel()) model->tileChanged(tile); } }
void TilesetDock::tilesetChanged(Tileset *tileset) { // Update the affected tileset model, if it exists const int index = indexOf(mTilesets, tileset); if (index < 0) return; TilesetView *view = tilesetViewAt(index); if (TilesetModel *model = view->tilesetModel()) { view->updateBackgroundColor(); model->tilesetChanged(); } }
void TilesetEditor::removeTiles() { TilesetView *view = currentTilesetView(); if (!view) return; if (!view->selectionModel()->hasSelection()) return; const QModelIndexList indexes = view->selectionModel()->selectedIndexes(); const TilesetModel *model = view->tilesetModel(); QList<Tile*> tiles; for (const QModelIndex &index : indexes) if (Tile *tile = model->tileAt(index)) tiles.append(tile); auto matchesAnyTile = [&tiles] (const Cell &cell) { if (Tile *tile = cell.tile()) return tiles.contains(tile); return false; }; QList<MapDocument *> mapsUsingTiles; for (MapDocument *mapDocument : mCurrentTilesetDocument->mapDocuments()) if (hasTileReferences(mapDocument, matchesAnyTile)) mapsUsingTiles.append(mapDocument); // If the tileset is in use, warn the user and confirm removal if (!mapsUsingTiles.isEmpty()) { QMessageBox warning(QMessageBox::Warning, tr("Remove Tiles"), tr("Tiles to be removed are in use by open maps!"), QMessageBox::Yes | QMessageBox::No, mMainWindow->window()); warning.setDefaultButton(QMessageBox::Yes); warning.setInformativeText(tr("Remove all references to these tiles?")); if (warning.exec() != QMessageBox::Yes) return; } for (MapDocument *mapDocument : mapsUsingTiles) removeTileReferences(mapDocument, matchesAnyTile); mCurrentTilesetDocument->undoStack()->push(new RemoveTiles(mCurrentTilesetDocument, tiles)); // todo: make sure any current brushes are no longer referring to removed tiles setCurrentTile(nullptr); }
void TilesetDock::updateActions() { bool external = false; TilesetView *view = 0; const int index = mTabBar->currentIndex(); if (index > -1) { view = tilesetViewAt(index); if (view) { mViewStack->setCurrentWidget(view); external = view->tilesetModel()->tileset()->isExternal(); } } mRenameTileset->setEnabled(view && !external); mImportTileset->setEnabled(view && external); mExportTileset->setEnabled(view && !external); mPropertiesTileset->setEnabled(view && !external); mDeleteTileset->setEnabled(view); }
void TilesetDock::updateCurrentTiles() { TilesetView *view = currentTilesetView(); if (!view) return; const QItemSelectionModel *s = view->selectionModel(); if (!s) return; const QModelIndexList indexes = s->selection().indexes(); if (indexes.isEmpty()) return; const QModelIndex &first = indexes.first(); int minX = first.column(); int maxX = first.column(); int minY = first.row(); int maxY = first.row(); for (const QModelIndex &index : indexes) { if (minX > index.column()) minX = index.column(); if (maxX < index.column()) maxX = index.column(); if (minY > index.row()) minY = index.row(); if (maxY < index.row()) maxY = index.row(); } // Create a tile layer from the current selection TileLayer *tileLayer = new TileLayer(QString(), 0, 0, maxX - minX + 1, maxY - minY + 1); const TilesetModel *model = view->tilesetModel(); for (const QModelIndex &index : indexes) { tileLayer->setCell(index.column() - minX, index.row() - minY, Cell(model->tileAt(index))); } setCurrentTiles(tileLayer); }
void TilesetEditor::selectionChanged() { TilesetView *view = currentTilesetView(); if (!view) return; updateAddRemoveActions(); const QItemSelectionModel *s = view->selectionModel(); const QModelIndexList indexes = s->selection().indexes(); if (indexes.isEmpty()) return; const TilesetModel *model = view->tilesetModel(); QList<Tile*> selectedTiles; for (const QModelIndex &index : indexes) if (Tile *tile = model->tileAt(index)) selectedTiles.append(tile); mCurrentTilesetDocument->setSelectedTiles(selectedTiles); }
void TilesetEditor::indexPressed(const QModelIndex &index) { TilesetView *view = currentTilesetView(); if (Tile *tile = view->tilesetModel()->tileAt(index)) mCurrentTilesetDocument->setCurrentObject(tile); }