From e6f2526afee594eb8d7319114f0c990afeab8d04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Tue, 23 Jan 2024 18:07:17 +0100 Subject: [PATCH] Scripting: Added tiled.load to load assets without opening an editor Still WIP, has known issues are likely also undiscovered ones. --- src/libtiled/object.h | 2 ++ src/tiled/document.cpp | 13 -------- src/tiled/document.h | 8 +---- src/tiled/editableasset.cpp | 23 ++++++++++---- src/tiled/editableasset.h | 17 +++++----- src/tiled/editablemap.cpp | 59 ++++++++++++++++++++++------------- src/tiled/editablemap.h | 10 ++++++ src/tiled/editableobject.h | 2 +- src/tiled/editableproject.cpp | 15 ++++++++- src/tiled/editableproject.h | 8 +++++ src/tiled/editabletileset.cpp | 31 +++++++++++------- src/tiled/editabletileset.h | 3 ++ src/tiled/editableworld.cpp | 15 ++++++++- src/tiled/editableworld.h | 8 +++++ src/tiled/mapdocument.cpp | 9 ++---- src/tiled/mapdocument.h | 3 +- src/tiled/projectdocument.cpp | 4 +-- src/tiled/projectdocument.h | 2 +- src/tiled/scriptmodule.cpp | 25 +++++++++++++-- src/tiled/scriptmodule.h | 1 + src/tiled/tilesetdocument.cpp | 27 +++++++--------- src/tiled/tilesetdocument.h | 10 +----- src/tiled/worlddocument.cpp | 12 +++++-- src/tiled/worlddocument.h | 8 +++-- 24 files changed, 199 insertions(+), 116 deletions(-) diff --git a/src/libtiled/object.h b/src/libtiled/object.h index 2f9e8e9486..0e57c740f7 100644 --- a/src/libtiled/object.h +++ b/src/libtiled/object.h @@ -150,6 +150,8 @@ class TILEDSHARED_EXPORT Object static void setPropertyTypes(const SharedPropertyTypes &propertyTypes); static const PropertyTypes &propertyTypes(); + QObject *editable() const { return mEditable; } + private: const TypeId mTypeId; QString mClassName; diff --git a/src/tiled/document.cpp b/src/tiled/document.cpp index a014f02181..fdb68f43a2 100644 --- a/src/tiled/document.cpp +++ b/src/tiled/document.cpp @@ -64,19 +64,6 @@ Document::~Document() } } -EditableAsset *Document::editable() -{ - if (!mEditable) - mEditable = createEditable(); - return mEditable.get(); -} - -void Document::setEditable(std::unique_ptr editable) -{ - mEditable = std::move(editable); - mEditable->setDocument(this); -} - void Document::setFileName(const QString &fileName) { if (mFileName == fileName) diff --git a/src/tiled/document.h b/src/tiled/document.h index 5adfd9930c..c435a7f844 100644 --- a/src/tiled/document.h +++ b/src/tiled/document.h @@ -28,8 +28,6 @@ #include #include -#include - class QUndoStack; namespace Tiled { @@ -95,8 +93,7 @@ class Document : public QObject, QUndoStack *undoStack() const; bool isModified() const; - EditableAsset *editable(); - void setEditable(std::unique_ptr editable); + virtual EditableAsset *editable() = 0; Object *currentObject() const { return mCurrentObject; } void setCurrentObject(Object *object); @@ -149,7 +146,6 @@ class Document : public QObject, void ignoreBrokenLinksChanged(bool ignoreBrokenLinks); protected: - virtual std::unique_ptr createEditable() = 0; virtual bool isModifiedImpl() const; void updateIsModified(); @@ -163,8 +159,6 @@ class Document : public QObject, Object *mCurrentObject = nullptr; /**< Current properties object. */ Document *mCurrentObjectDocument = nullptr; - std::unique_ptr mEditable; - private: void currentObjectDocumentChanged(const ChangeEvent &change); void currentObjectDocumentDestroyed(); diff --git a/src/tiled/editableasset.cpp b/src/tiled/editableasset.cpp index 757dec7d6a..b9323723a2 100644 --- a/src/tiled/editableasset.cpp +++ b/src/tiled/editableasset.cpp @@ -28,14 +28,16 @@ namespace Tiled { -EditableAsset::EditableAsset(Document *document, Object *object, QObject *parent) +EditableAsset::EditableAsset(Object *object, QObject *parent) : EditableObject(this, object, parent) - , mDocument(document) { - if (document) { - connect(document, &Document::modifiedChanged, - this, &EditableAsset::modifiedChanged); - } +} + +EditableAsset::~EditableAsset() +{ + // Prevent owned object from trying to delete us again + if (mDocument) + setObject(nullptr); } QString EditableAsset::fileName() const @@ -126,6 +128,15 @@ void EditableAsset::redo() ScriptManager::instance().throwError(QCoreApplication::translate("Script Errors", "Undo system not available for this asset")); } +void EditableAsset::setDocument(Document *document) +{ + Q_ASSERT(!mDocument && document); + + mDocument = document->sharedFromThis(); + connect(document, &Document::modifiedChanged, + this, &EditableAsset::modifiedChanged); +} + } // namespace Tiled #include "moc_editableasset.cpp" diff --git a/src/tiled/editableasset.h b/src/tiled/editableasset.h index a99c8727df..551b3ee6b8 100644 --- a/src/tiled/editableasset.h +++ b/src/tiled/editableasset.h @@ -21,6 +21,7 @@ #pragma once #include "editableobject.h" +#include "document.h" #include #include @@ -57,7 +58,8 @@ class EditableAsset : public EditableObject Q_PROPERTY(AssetType::Value assetType READ assetType CONSTANT) public: - EditableAsset(Document *document, Object *object, QObject *parent = nullptr); + EditableAsset(Object *object, QObject *parent = nullptr); + ~EditableAsset() override; QString fileName() const; bool isReadOnly() const override = 0; @@ -88,22 +90,17 @@ public slots: void modifiedChanged(); void fileNameChanged(const QString &fileName, const QString &oldFileName); -private: - friend class Document; +protected: void setDocument(Document *document); - Document *mDocument; +private: + DocumentPtr mDocument; }; inline Document *EditableAsset::document() const { - return mDocument; -} - -inline void EditableAsset::setDocument(Document *document) -{ - mDocument = document; + return mDocument.get(); } } // namespace Tiled diff --git a/src/tiled/editablemap.cpp b/src/tiled/editablemap.cpp index c126681a2a..e4472d633f 100644 --- a/src/tiled/editablemap.cpp +++ b/src/tiled/editablemap.cpp @@ -49,25 +49,14 @@ namespace Tiled { EditableMap::EditableMap(QObject *parent) - : EditableAsset(nullptr, new Map(), parent) + : EditableMap(std::make_unique(), parent) { - mDetachedMap.reset(map()); } EditableMap::EditableMap(MapDocument *mapDocument, QObject *parent) - : EditableAsset(mapDocument, mapDocument->map(), parent) - , mSelectedArea(new EditableSelectedArea(mapDocument, this)) + : EditableAsset(mapDocument->map(), parent) { - connect(mapDocument, &Document::fileNameChanged, this, &EditableAsset::fileNameChanged); - connect(mapDocument, &Document::changed, this, &EditableMap::documentChanged); - connect(mapDocument, &MapDocument::layerAdded, this, &EditableMap::attachLayer); - connect(mapDocument, &MapDocument::layerRemoved, this, &EditableMap::detachLayer); - - connect(mapDocument, &MapDocument::currentLayerChanged, this, &EditableMap::currentLayerChanged); - connect(mapDocument, &MapDocument::selectedLayersChanged, this, &EditableMap::selectedLayersChanged); - connect(mapDocument, &MapDocument::selectedObjectsChanged, this, &EditableMap::selectedObjectsChanged); - - connect(mapDocument, &MapDocument::regionEdited, this, &EditableMap::onRegionEdited); + setDocument(mapDocument); } /** @@ -76,14 +65,13 @@ EditableMap::EditableMap(MapDocument *mapDocument, QObject *parent) * The map's lifetime must exceed that of the EditableMap instance. */ EditableMap::EditableMap(const Map *map, QObject *parent) - : EditableAsset(nullptr, const_cast(map), parent) + : EditableAsset(const_cast(map), parent) , mReadOnly(true) - , mSelectedArea(nullptr) { } EditableMap::EditableMap(std::unique_ptr map, QObject *parent) - : EditableAsset(nullptr, map.get(), parent) + : EditableAsset(map.get(), parent) , mDetachedMap(std::move(map)) { } @@ -671,15 +659,26 @@ void EditableMap::setSelectedObjects(const QList &objects) QSharedPointer EditableMap::createDocument() { Q_ASSERT(mDetachedMap); + Q_ASSERT(!document()); auto document = MapDocumentPtr::create(std::move(mDetachedMap)); - document->setEditable(std::unique_ptr(this)); + setDocument(document.data()); + + return document; +} - mSelectedArea = new EditableSelectedArea(document.data(), this); +EditableMap *EditableMap::get(MapDocument *mapDocument) +{ + if (!mapDocument) + return nullptr; - QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership); + auto editable = EditableMap::find(mapDocument->map()); + if (editable) + return editable; - return document; + editable = new EditableMap(mapDocument); + // editable->moveOwnershipToCpp(); + return editable; } void EditableMap::documentChanged(const ChangeEvent &change) @@ -759,6 +758,24 @@ MapRenderer *EditableMap::renderer() const return mRenderer.get(); } +void EditableMap::setDocument(MapDocument *mapDocument) +{ + EditableAsset::setDocument(mapDocument); + + mSelectedArea = new EditableSelectedArea(mapDocument, this); + + connect(mapDocument, &Document::fileNameChanged, this, &EditableAsset::fileNameChanged); + connect(mapDocument, &Document::changed, this, &EditableMap::documentChanged); + connect(mapDocument, &MapDocument::layerAdded, this, &EditableMap::attachLayer); + connect(mapDocument, &MapDocument::layerRemoved, this, &EditableMap::detachLayer); + + connect(mapDocument, &MapDocument::currentLayerChanged, this, &EditableMap::currentLayerChanged); + connect(mapDocument, &MapDocument::selectedLayersChanged, this, &EditableMap::selectedLayersChanged); + connect(mapDocument, &MapDocument::selectedObjectsChanged, this, &EditableMap::selectedObjectsChanged); + + connect(mapDocument, &MapDocument::regionEdited, this, &EditableMap::onRegionEdited); +} + } // namespace Tiled #include "moc_editablemap.cpp" diff --git a/src/tiled/editablemap.h b/src/tiled/editablemap.h index e01e70890b..b96080887b 100644 --- a/src/tiled/editablemap.h +++ b/src/tiled/editablemap.h @@ -202,6 +202,9 @@ class EditableMap final : public EditableAsset QSharedPointer createDocument() override; + static EditableMap *find(Map *map); + static EditableMap *get(MapDocument *mapDocument); + signals: void currentLayerChanged(); void selectedLayersChanged(); @@ -221,6 +224,8 @@ class EditableMap final : public EditableAsset MapRenderer *renderer() const; + void setDocument(MapDocument *mapDocument); + std::unique_ptr mDetachedMap; mutable std::unique_ptr mRenderer; bool mReadOnly = false; @@ -380,6 +385,11 @@ inline MapDocument *EditableMap::mapDocument() const return static_cast(document()); } +inline EditableMap *EditableMap::find(Map *map) +{ + return static_cast(EditableObject::find(map)); +} + } // namespace Tiled Q_DECLARE_METATYPE(Tiled::EditableMap*) diff --git a/src/tiled/editableobject.h b/src/tiled/editableobject.h index b8aedd215f..6a3986760e 100644 --- a/src/tiled/editableobject.h +++ b/src/tiled/editableobject.h @@ -154,7 +154,7 @@ inline void EditableObject::setAsset(EditableAsset *asset) inline EditableObject *EditableObject::find(Object *object) { - return object ? static_cast(object->mEditable.data()) + return object ? static_cast(object->editable()) : nullptr; } diff --git a/src/tiled/editableproject.cpp b/src/tiled/editableproject.cpp index 77033d5d8a..1d8ef04527 100644 --- a/src/tiled/editableproject.cpp +++ b/src/tiled/editableproject.cpp @@ -26,8 +26,9 @@ namespace Tiled { EditableProject::EditableProject(ProjectDocument *projectDocument, QObject *parent) - : EditableAsset(projectDocument, &projectDocument->project(), parent) + : EditableAsset(&projectDocument->project(), parent) { + setDocument(projectDocument); } QString EditableProject::extensionsPath() const @@ -62,6 +63,18 @@ QSharedPointer EditableProject::createDocument() return nullptr; } +EditableProject *EditableProject::get(ProjectDocument *projectDocument) +{ + if (!projectDocument) + return nullptr; + + auto editable = find(&projectDocument->project()); + if (editable) + return editable; + + return new EditableProject(projectDocument); +} + } // namespace Tiled #include "moc_editableproject.cpp" diff --git a/src/tiled/editableproject.h b/src/tiled/editableproject.h index 6d309f4538..c52b0128ed 100644 --- a/src/tiled/editableproject.h +++ b/src/tiled/editableproject.h @@ -53,6 +53,9 @@ class EditableProject final : public EditableAsset Project *project() const; QSharedPointer createDocument() override; + + static EditableProject *find(Project *project); + static EditableProject *get(ProjectDocument *projectDocument); }; inline Project *EditableProject::project() const @@ -60,6 +63,11 @@ inline Project *EditableProject::project() const return static_cast(object()); } +inline EditableProject *EditableProject::find(Project *project) +{ + return static_cast(EditableObject::find(project)); +} + } // namespace Tiled Q_DECLARE_METATYPE(Tiled::EditableProject*) diff --git a/src/tiled/editabletileset.cpp b/src/tiled/editabletileset.cpp index 7ea471b098..f8efe20176 100644 --- a/src/tiled/editabletileset.cpp +++ b/src/tiled/editabletileset.cpp @@ -35,14 +35,14 @@ namespace Tiled { EditableTileset::EditableTileset(const QString &name, QObject *parent) - : EditableAsset(nullptr, nullptr, parent) + : EditableAsset(nullptr, parent) , mTileset(Tileset::create(name, 0, 0)) { setObject(mTileset.data()); } EditableTileset::EditableTileset(const Tileset *tileset, QObject *parent) - : EditableAsset(nullptr, const_cast(tileset), parent) + : EditableAsset(const_cast(tileset), parent) , mReadOnly(true) , mTileset(const_cast(tileset)->sharedFromThis()) // keep alive { @@ -50,14 +50,9 @@ EditableTileset::EditableTileset(const Tileset *tileset, QObject *parent) EditableTileset::EditableTileset(TilesetDocument *tilesetDocument, QObject *parent) - : EditableAsset(tilesetDocument, tilesetDocument->tileset().data(), parent) + : EditableAsset(tilesetDocument->tileset().data(), parent) { - connect(tilesetDocument, &Document::fileNameChanged, this, &EditableAsset::fileNameChanged); - connect(tilesetDocument, &TilesetDocument::tilesAdded, this, &EditableTileset::attachTiles); - connect(tilesetDocument, &TilesetDocument::tilesRemoved, this, &EditableTileset::detachTiles); - connect(tilesetDocument, &TilesetDocument::tileObjectGroupChanged, this, &EditableTileset::tileObjectGroupChanged); - connect(tilesetDocument->wangSetModel(), &TilesetWangSetModel::wangSetAdded, this, &EditableTileset::wangSetAdded); - connect(tilesetDocument->wangSetModel(), &TilesetWangSetModel::wangSetRemoved, this, &EditableTileset::wangSetRemoved); + setDocument(tilesetDocument); } EditableTileset::~EditableTileset() @@ -225,13 +220,13 @@ EditableTileset *EditableTileset::get(Tileset *tileset) if (!tileset) return nullptr; - if (auto document = TilesetDocument::findDocumentForTileset(tileset->sharedFromThis())) - return document->editable(); - auto editable = EditableTileset::find(tileset); if (editable) return editable; + if (auto document = TilesetDocument::findDocumentForTileset(tileset->sharedFromThis())) + return new EditableTileset(document); + editable = new EditableTileset(tileset); editable->moveOwnershipToCpp(); return editable; @@ -432,6 +427,18 @@ void EditableTileset::wangSetRemoved(WangSet *wangSet) detachWangSets({ wangSet }); } +void EditableTileset::setDocument(TilesetDocument *tilesetDocument) +{ + EditableAsset::setDocument(tilesetDocument); + + connect(tilesetDocument, &Document::fileNameChanged, this, &EditableAsset::fileNameChanged); + connect(tilesetDocument, &TilesetDocument::tilesAdded, this, &EditableTileset::attachTiles); + connect(tilesetDocument, &TilesetDocument::tilesRemoved, this, &EditableTileset::detachTiles); + connect(tilesetDocument, &TilesetDocument::tileObjectGroupChanged, this, &EditableTileset::tileObjectGroupChanged); + connect(tilesetDocument->wangSetModel(), &TilesetWangSetModel::wangSetAdded, this, &EditableTileset::wangSetAdded); + connect(tilesetDocument->wangSetModel(), &TilesetWangSetModel::wangSetRemoved, this, &EditableTileset::wangSetRemoved); +} + } // namespace Tiled #include "moc_editabletileset.cpp" diff --git a/src/tiled/editabletileset.h b/src/tiled/editabletileset.h index ce9e01579c..59295499aa 100644 --- a/src/tiled/editabletileset.h +++ b/src/tiled/editabletileset.h @@ -182,6 +182,9 @@ public slots: void wangSetAdded(Tileset *tileset, int index); void wangSetRemoved(WangSet *wangSet); + friend class TilesetDocument; + void setDocument(TilesetDocument *tilesetDocument); + bool mReadOnly = false; SharedTileset mTileset; }; diff --git a/src/tiled/editableworld.cpp b/src/tiled/editableworld.cpp index 92426c563a..32e9df05d8 100644 --- a/src/tiled/editableworld.cpp +++ b/src/tiled/editableworld.cpp @@ -31,8 +31,9 @@ namespace Tiled { EditableWorld::EditableWorld(WorldDocument *worldDocument, QObject *parent) - : EditableAsset(worldDocument, nullptr, parent) + : EditableAsset(nullptr, parent) { + setDocument(worldDocument); setObject(WorldManager::instance().worlds().value(worldDocument->fileName())); } @@ -154,6 +155,18 @@ QSharedPointer EditableWorld::createDocument() return nullptr; } +EditableWorld *EditableWorld::get(WorldDocument *worldDocument) +{ + if (!worldDocument) + return nullptr; + + auto editable = find(worldDocument->world()); + if (editable) + return editable; + + return new EditableWorld(worldDocument); +} + } // namespace Tiled #include "moc_editableworld.cpp" diff --git a/src/tiled/editableworld.h b/src/tiled/editableworld.h index e7f9a6d681..952b78507b 100644 --- a/src/tiled/editableworld.h +++ b/src/tiled/editableworld.h @@ -59,6 +59,9 @@ class EditableWorld final : public EditableAsset Q_INVOKABLE void removeMap(EditableMap *map); QSharedPointer createDocument() override; + + static EditableWorld *find(World *world); + static EditableWorld *get(WorldDocument *worldDocument); }; inline World *EditableWorld::world() const @@ -66,6 +69,11 @@ inline World *EditableWorld::world() const return static_cast(object()); } +inline EditableWorld *EditableWorld::find(World *world) +{ + return static_cast(EditableObject::find(world)); +} + } // namespace Tiled Q_DECLARE_METATYPE(Tiled::EditableWorld*) diff --git a/src/tiled/mapdocument.cpp b/src/tiled/mapdocument.cpp index d8bb893f7a..a1c448807e 100644 --- a/src/tiled/mapdocument.cpp +++ b/src/tiled/mapdocument.cpp @@ -114,11 +114,6 @@ MapDocument::~MapDocument() { // Clear any previously found issues in this document IssuesModel::instance().removeIssuesWithContext(this); - - // Needs to be deleted before the Map instance is deleted, because it may - // cause script values to detach from the map, in which case they'll need - // to be able to copy the data. - mEditable.reset(); } bool MapDocument::save(const QString &fileName, QString *error) @@ -235,9 +230,9 @@ QString MapDocument::displayName() const return displayName; } -std::unique_ptr MapDocument::createEditable() +EditableAsset *MapDocument::editable() { - return std::make_unique(this, this); + return EditableMap::get(this); } /** diff --git a/src/tiled/mapdocument.h b/src/tiled/mapdocument.h index 2589e298f4..6663686f43 100644 --- a/src/tiled/mapdocument.h +++ b/src/tiled/mapdocument.h @@ -92,6 +92,8 @@ class TILED_EDITOR_EXPORT MapDocument : public Document bool save(const QString &fileName, QString *error = nullptr) override; + EditableAsset *editable() override; + /** * Loads a map and returns a MapDocument instance on success. Returns null * on error and sets the \a error message. @@ -373,7 +375,6 @@ public slots: void deselectObjects(const QList &objects); protected: - std::unique_ptr createEditable() override; private: void onChanged(const ChangeEvent &change); diff --git a/src/tiled/projectdocument.cpp b/src/tiled/projectdocument.cpp index 26849d85f4..7fbdeba208 100644 --- a/src/tiled/projectdocument.cpp +++ b/src/tiled/projectdocument.cpp @@ -72,9 +72,9 @@ void ProjectDocument::setLastExportFileName(const QString &/* fileName */) // do nothing } -std::unique_ptr ProjectDocument::createEditable() +EditableAsset *ProjectDocument::editable() { - return std::make_unique(this, this); + return EditableProject::get(this); } } // namespace Tiled diff --git a/src/tiled/projectdocument.h b/src/tiled/projectdocument.h index 310bd83c22..476e3478d5 100644 --- a/src/tiled/projectdocument.h +++ b/src/tiled/projectdocument.h @@ -40,7 +40,7 @@ class ProjectDocument : public Document FileFormat *exportFormat() const override; QString lastExportFileName() const override; void setLastExportFileName(const QString &fileName) override; - std::unique_ptr createEditable() override; + EditableAsset *editable() override; Project &project() { return *mProject; } diff --git a/src/tiled/scriptmodule.cpp b/src/tiled/scriptmodule.cpp index 148bcf1f8a..24834081ea 100644 --- a/src/tiled/scriptmodule.cpp +++ b/src/tiled/scriptmodule.cpp @@ -198,8 +198,11 @@ bool ScriptModule::setActiveAsset(EditableAsset *asset) const if (asset->checkReadOnly()) return false; - if (auto document = asset->document()) - return documentManager->switchToDocument(document); + if (auto document = asset->document()) { + if (!documentManager->switchToDocument(document)) + documentManager->addDocument(document->sharedFromThis()); + return true; + } if (auto document = asset->createDocument()) { documentManager->addDocument(document); @@ -274,6 +277,24 @@ bool ScriptModule::versionLessThan(const QString &a, const QString &b) return QVersionNumber::fromString(a) < QVersionNumber::fromString(b); } +EditableAsset *ScriptModule::load(const QString &fileName) const +{ + auto documentManager = DocumentManager::maybeInstance(); + if (!documentManager) { + ScriptManager::instance().throwError(QCoreApplication::translate("Script Errors", "Editor not available")); + return nullptr; + } + + QString error; + if (auto document = documentManager->loadDocument(fileName, nullptr, &error)) { + return document->editable(); + } else { + ScriptManager::instance().throwError(error); + } + + return nullptr; +} + EditableAsset *ScriptModule::open(const QString &fileName) const { auto documentManager = DocumentManager::maybeInstance(); diff --git a/src/tiled/scriptmodule.h b/src/tiled/scriptmodule.h index 5b56296165..759ef66abf 100644 --- a/src/tiled/scriptmodule.h +++ b/src/tiled/scriptmodule.h @@ -111,6 +111,7 @@ class ScriptModule : public QObject Q_INVOKABLE bool versionLessThan(const QString &a); Q_INVOKABLE bool versionLessThan(const QString &a, const QString &b); + Q_INVOKABLE Tiled::EditableAsset *load(const QString &fileName) const; Q_INVOKABLE Tiled::EditableAsset *open(const QString &fileName) const; Q_INVOKABLE bool close(Tiled::EditableAsset *asset) const; Q_INVOKABLE Tiled::EditableAsset *reload(Tiled::EditableAsset *asset) const; diff --git a/src/tiled/tilesetdocument.cpp b/src/tiled/tilesetdocument.cpp index 3f5123576b..e097fce915 100644 --- a/src/tiled/tilesetdocument.cpp +++ b/src/tiled/tilesetdocument.cpp @@ -67,12 +67,10 @@ TilesetDocument::TilesetDocument(const SharedTileset &tileset) Q_ASSERT(!sTilesetToDocument.contains(tileset)); sTilesetToDocument.insert(tileset, this); - // If there already happens to be an editable for this tileset, take - // ownership of it. - if (auto editable = EditableTileset::find(tileset.data())) { - setEditable(std::unique_ptr(editable)); - QQmlEngine::setObjectOwnership(editable, QQmlEngine::CppOwnership); - } + // If there already happens to be an editable for this tileset, make sure + // it knows about us. + if (auto editable = EditableTileset::find(tileset.data())) + editable->setDocument(this); mCurrentObject = tileset.data(); @@ -95,11 +93,6 @@ TilesetDocument::~TilesetDocument() IssuesModel::instance().removeIssuesWithContext(this); sTilesetToDocument.remove(mTileset); - - // Needs to be deleted before the Tileset instance is deleted, because it - // may cause script values to detach from the map, in which case they'll - // need to be able to copy the data. - mEditable.reset(); } bool TilesetDocument::save(const QString &fileName, QString *error) @@ -258,18 +251,20 @@ void TilesetDocument::swapTileset(SharedTileset &tileset) // Bring pointers to safety setSelectedTiles(QList()); setCurrentObject(mTileset.data()); - mEditable.reset(); - sTilesetToDocument.remove(mTileset); + // Delete the editable and have it deal with any child editables that were + // created, because their document and object references would no longer be + // valid after the swap. + delete mTileset->editable(); + mTileset->swap(*tileset); - sTilesetToDocument.insert(mTileset, this); emit tilesetChanged(mTileset.data()); } -std::unique_ptr TilesetDocument::createEditable() +EditableTileset *TilesetDocument::editable() { - return std::make_unique(this, this); + return EditableTileset::get(mTileset.data()); } /** diff --git a/src/tiled/tilesetdocument.h b/src/tiled/tilesetdocument.h index 05f54db726..b9740f8567 100644 --- a/src/tiled/tilesetdocument.h +++ b/src/tiled/tilesetdocument.h @@ -84,7 +84,7 @@ class TilesetDocument : public Document void swapTileset(SharedTileset &tileset); const SharedTileset &tileset() const; - EditableTileset *editable(); + EditableTileset *editable() override; bool isEmbedded() const; void setClean(); @@ -164,9 +164,6 @@ class TilesetDocument : public Document */ void selectedTilesChanged(); -protected: - std::unique_ptr createEditable() override; - private: void onPropertyAdded(Object *object, const QString &name); void onPropertyRemoved(Object *object, const QString &name); @@ -192,11 +189,6 @@ inline const SharedTileset &TilesetDocument::tileset() const return mTileset; } -inline EditableTileset *TilesetDocument::editable() -{ - return static_cast(Document::editable()); -} - inline bool TilesetDocument::isEmbedded() const { return fileName().isEmpty() && mMapDocuments.count() == 1; diff --git a/src/tiled/worlddocument.cpp b/src/tiled/worlddocument.cpp index d61c232dd0..5222e2deb0 100644 --- a/src/tiled/worlddocument.cpp +++ b/src/tiled/worlddocument.cpp @@ -80,14 +80,20 @@ void WorldDocument::onWorldSaved(const QString &fileName) bool WorldDocument::isModifiedImpl() const { - const World *world = WorldManager::instance().worlds().value(fileName()); + const World *world = this->world(); return Document::isModifiedImpl() || (world && world->hasUnsavedChanges); } -std::unique_ptr WorldDocument::createEditable() +EditableAsset *WorldDocument::editable() { - return std::make_unique(this, this); + return EditableWorld::get(this); } + +World *WorldDocument::world() const +{ + return WorldManager::instance().worlds().value(fileName()); +} + } // namespace Tiled #include "moc_worlddocument.cpp" diff --git a/src/tiled/worlddocument.h b/src/tiled/worlddocument.h index 01fd491816..72a2ac4eb0 100644 --- a/src/tiled/worlddocument.h +++ b/src/tiled/worlddocument.h @@ -24,10 +24,10 @@ #include "document.h" #include "editableasset.h" -class WorldManager; - namespace Tiled { +class World; + /** * Represents an editable world document. */ @@ -44,7 +44,7 @@ class WorldDocument : public Document FileFormat *writerFormat() const override { return nullptr; } - std::unique_ptr createEditable() override; + EditableAsset *editable() override; // Exporting not supported for worlds QString lastExportFileName() const override { return QString(); } @@ -52,6 +52,8 @@ class WorldDocument : public Document FileFormat *exportFormat() const override { return nullptr; } void setExportFormat(FileFormat *) override {} + World *world() const; + private: void onWorldsChanged(); void onWorldReloaded(const QString &filename);