1 /*
2 * tilelayeredit.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 "tilelayeredit.h"
22
23 #include "addremovetileset.h"
24 #include "editablemap.h"
25 #include "editabletile.h"
26 #include "editabletilelayer.h"
27 #include "painttilelayer.h"
28 #include "scriptmanager.h"
29
30 namespace Tiled {
31
TileLayerEdit(EditableTileLayer * tileLayer,QObject * parent)32 TileLayerEdit::TileLayerEdit(EditableTileLayer *tileLayer, QObject *parent)
33 : QObject(parent)
34 , mTargetLayer(tileLayer)
35 {
36 mTargetLayer->mActiveEdits.append(this);
37 }
38
~TileLayerEdit()39 TileLayerEdit::~TileLayerEdit()
40 {
41 mTargetLayer->mActiveEdits.removeOne(this);
42 }
43
setTile(int x,int y,EditableTile * tile,int flags)44 void TileLayerEdit::setTile(int x, int y, EditableTile *tile, int flags)
45 {
46 Cell cell(tile ? tile->tile() : nullptr);
47 cell.setChecked(true); // Used to find painted region later (allows erasing)
48
49 if (flags & EditableTile::FlippedHorizontally)
50 cell.setFlippedHorizontally(true);
51 if (flags & EditableTile::FlippedVertically)
52 cell.setFlippedVertically(true);
53 if (flags & EditableTile::FlippedAntiDiagonally)
54 cell.setFlippedAntiDiagonally(true);
55 if (flags & EditableTile::RotatedHexagonal120)
56 cell.setRotatedHexagonal120(true);
57
58 mChanges.setCell(x, y, cell);
59 }
60
apply()61 void TileLayerEdit::apply()
62 {
63 // Applying an edit automatically makes it mergeable, so that further
64 // changes made through the same edit are merged by default.
65 bool mergeable = std::exchange(mMergeable, true);
66
67 // Determine painted region and normalize the changes layer
68 auto paintedRegion = mChanges.region([] (const Cell &cell) { return cell.checked(); });
69
70 // If the painted region is empty there's nothing else to do
71 if (paintedRegion.isEmpty())
72 return;
73
74 auto rect = paintedRegion.boundingRect();
75 mChanges.resize(rect.size(), -rect.topLeft());
76
77 if (mTargetLayer->mapDocument()) {
78 // Apply the change using an undo command
79 auto mapDocument = mTargetLayer->map()->mapDocument();
80 auto paint = new PaintTileLayer(mapDocument,
81 mTargetLayer->tileLayer(),
82 rect.x(), rect.y(),
83 &mChanges,
84 paintedRegion);
85 paint->setMergeable(mergeable);
86
87 // Add any used tilesets that aren't yet part of the target map
88 const auto tilesets = mChanges.usedTilesets();
89 const auto existingTilesets = mapDocument->map()->tilesets();
90 for (const SharedTileset &tileset : tilesets)
91 if (!existingTilesets.contains(tileset))
92 new AddTileset(mapDocument, tileset, paint);
93
94 mTargetLayer->map()->push(paint);
95 } else {
96 // Apply the change directly
97 mTargetLayer->tileLayer()->setCells(rect.x(), rect.y(), &mChanges, paintedRegion);
98 }
99
100 mChanges.clear();
101 }
102
103 } // namespace Tiled
104
105 #include "moc_tilelayeredit.cpp"
106