1 /*
2  * editablemanager.cpp
3  * Copyright 2019, Thorbjørn Lindeijer <bjorn@lindeijer.nl>
4  *
5  * This file is part of Tiled.
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the Free
9  * Software Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along with
18  * this program. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "editablemanager.h"
22 
23 #include "editablegrouplayer.h"
24 #include "editableimagelayer.h"
25 #include "editablemap.h"
26 #include "editableobjectgroup.h"
27 #include "editabletile.h"
28 #include "editabletilelayer.h"
29 #include "editabletileset.h"
30 #include "editablewangset.h"
31 #include "scriptmanager.h"
32 #include "wangset.h"
33 
34 #include <QQmlEngine>
35 
36 namespace Tiled {
37 
becomesNullValue(QObject * object)38 static bool becomesNullValue(QObject *object)
39 {
40     return ScriptManager::instance().engine()->newQObject(object).isNull();
41 }
42 
43 std::unique_ptr<EditableManager> EditableManager::mInstance;
44 
EditableManager(QObject * parent)45 EditableManager::EditableManager(QObject *parent)
46     : QObject(parent)
47 {
48 }
49 
instance()50 EditableManager &EditableManager::instance()
51 {
52     if (!mInstance)
53         mInstance.reset(new EditableManager);
54     return *mInstance;
55 }
56 
deleteInstance()57 void EditableManager::deleteInstance()
58 {
59     mInstance.reset();
60 }
61 
release(Layer * layer)62 void EditableManager::release(Layer *layer)
63 {
64     if (EditableLayer *editable = find(layer))
65         editable->hold();
66     else
67         delete layer;
68 }
69 
release(MapObject * mapObject)70 void EditableManager::release(MapObject *mapObject)
71 {
72     if (EditableMapObject *editable = find(mapObject))
73         editable->hold();
74     else
75         delete mapObject;
76 }
77 
78 /**
79  * Releases the WangSet by either finding an EditableWangSet instance to take
80  * ownership of it or deleting it.
81  */
release(std::unique_ptr<WangSet> wangSet)82 void EditableManager::release(std::unique_ptr<WangSet> wangSet)
83 {
84     if (EditableWangSet *editable = find(wangSet.get())) {
85         editable->hold();
86         wangSet.release();
87     }
88 }
89 
editableLayer(EditableMap * map,Layer * layer)90 EditableLayer *EditableManager::editableLayer(EditableMap *map, Layer *layer)
91 {
92     if (!layer)
93         return nullptr;
94 
95     Q_ASSERT(!map || layer->map() == map->map());
96 
97     EditableLayer* &editableLayer = mEditableLayers[layer];
98     if (becomesNullValue(editableLayer)) {
99         switch (layer->layerType()) {
100         case Layer::TileLayerType:
101             editableLayer = new EditableTileLayer(map, static_cast<TileLayer*>(layer));
102             break;
103         case Layer::ObjectGroupType:
104             editableLayer = new EditableObjectGroup(map, static_cast<ObjectGroup*>(layer));
105             break;
106         case Layer::ImageLayerType:
107             editableLayer = new EditableImageLayer(map, static_cast<ImageLayer*>(layer));
108             break;
109         case Layer::GroupLayerType:
110             editableLayer = new EditableGroupLayer(map, static_cast<GroupLayer*>(layer));
111             break;
112         }
113         QQmlEngine::setObjectOwnership(editableLayer, QQmlEngine::JavaScriptOwnership);
114     }
115 
116     return editableLayer;
117 }
118 
editableObjectGroup(EditableAsset * asset,ObjectGroup * objectGroup)119 EditableObjectGroup *EditableManager::editableObjectGroup(EditableAsset *asset, ObjectGroup *objectGroup)
120 {
121     if (!objectGroup)
122         return nullptr;
123 
124     EditableLayer* &editableLayer = mEditableLayers[objectGroup];
125     if (becomesNullValue(editableLayer)) {
126         editableLayer = new EditableObjectGroup(asset, objectGroup);
127         QQmlEngine::setObjectOwnership(editableLayer, QQmlEngine::JavaScriptOwnership);
128     }
129 
130     return static_cast<EditableObjectGroup*>(editableLayer);
131 }
132 
editableMapObject(EditableAsset * asset,MapObject * mapObject)133 EditableMapObject *EditableManager::editableMapObject(EditableAsset *asset, MapObject *mapObject)
134 {
135     if (!mapObject)
136         return nullptr;
137 
138     Q_ASSERT(mapObject->objectGroup());
139 
140     EditableMapObject* &editableMapObject = mEditableMapObjects[mapObject];
141     if (becomesNullValue(editableMapObject)) {
142         editableMapObject = new EditableMapObject(asset, mapObject);
143         QQmlEngine::setObjectOwnership(editableMapObject, QQmlEngine::JavaScriptOwnership);
144     }
145 
146     return editableMapObject;
147 }
148 
editableTileset(Tileset * tileset)149 EditableTileset *EditableManager::editableTileset(Tileset *tileset)
150 {
151     if (!tileset)
152         return nullptr;
153 
154     EditableTileset* &editableTileset = mEditableTilesets[tileset];
155     if (becomesNullValue(editableTileset)) {
156         editableTileset = new EditableTileset(tileset);
157         QQmlEngine::setObjectOwnership(editableTileset, QQmlEngine::JavaScriptOwnership);
158     }
159 
160     return editableTileset;
161 }
162 
editableTile(EditableTileset * tileset,Tile * tile)163 EditableTile *EditableManager::editableTile(EditableTileset *tileset, Tile *tile)
164 {
165     if (!tile)
166         return nullptr;
167 
168     Q_ASSERT(tile->tileset() == tileset->tileset());
169 
170     EditableTile* &editableTile = mEditableTiles[tile];
171     if (becomesNullValue(editableTile)) {
172         editableTile = new EditableTile(tileset, tile);
173         QQmlEngine::setObjectOwnership(editableTile, QQmlEngine::JavaScriptOwnership);
174     }
175 
176     return editableTile;
177 }
178 
editableWangSet(EditableTileset * tileset,WangSet * wangSet)179 EditableWangSet *EditableManager::editableWangSet(EditableTileset *tileset, WangSet *wangSet)
180 {
181     if (!wangSet)
182         return nullptr;
183 
184     Q_ASSERT(wangSet->tileset() == tileset->tileset());
185 
186     EditableWangSet* &editableWangSet = mEditableWangSets[wangSet];
187     if (becomesNullValue(editableWangSet)) {
188         editableWangSet = new EditableWangSet(tileset, wangSet);
189         QQmlEngine::setObjectOwnership(editableWangSet, QQmlEngine::JavaScriptOwnership);
190     }
191 
192     return editableWangSet;
193 }
194 
195 } // namespace Tiled
196 
197 #include "moc_editablemanager.cpp"
198