1 /*
2 * erasetiles.cpp
3 * Copyright 2009, Thorbjørn Lindeijer <thorbjorn@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 "erasetiles.h"
22
23 #include "tilelayer.h"
24 #include "tilepainter.h"
25
26 #include <QCoreApplication>
27
28 using namespace Tiled;
29
EraseTiles(MapDocument * mapDocument,TileLayer * tileLayer,const QRegion & region)30 EraseTiles::EraseTiles(MapDocument *mapDocument,
31 TileLayer *tileLayer,
32 const QRegion ®ion)
33 : mMapDocument(mapDocument)
34 , mMergeable(false)
35 {
36 setText(QCoreApplication::translate("Undo Commands", "Erase"));
37
38 auto &data = mLayerData[tileLayer];
39 data.mRegion = region;
40
41 // Store the tiles that are to be erased
42 const QRegion r = region.translated(-tileLayer->position());
43 data.mErasedCells = tileLayer->copy(r).release();
44 }
45
~EraseTiles()46 EraseTiles::~EraseTiles()
47 {
48 for (LayerData &data : mLayerData)
49 delete data.mErasedCells;
50 }
51
undo()52 void EraseTiles::undo()
53 {
54 QHashIterator<TileLayer*, LayerData> it(mLayerData);
55 while (it.hasNext()) {
56 const LayerData &data = it.next().value();
57 const QRect bounds = data.mRegion.boundingRect();
58 TilePainter painter(mMapDocument, it.key());
59 painter.drawCells(bounds.x(), bounds.y(), data.mErasedCells);
60 }
61 }
62
redo()63 void EraseTiles::redo()
64 {
65 QHashIterator<TileLayer*, LayerData> it(mLayerData);
66 while (it.hasNext()) {
67 const LayerData &data = it.next().value();
68 TilePainter painter(mMapDocument, it.key());
69 painter.erase(data.mRegion);
70 }
71 }
72
mergeWith(const EraseTiles::LayerData & o)73 void EraseTiles::LayerData::mergeWith(const EraseTiles::LayerData &o)
74 {
75 if (!mErasedCells) {
76 mErasedCells = o.mErasedCells->clone();
77 mRegion = o.mRegion;
78 return;
79 }
80
81 const QRegion combinedRegion = mRegion.united(o.mRegion);
82 if (mRegion != combinedRegion) {
83 const QRect bounds = mRegion.boundingRect();
84 const QRect combinedBounds = combinedRegion.boundingRect();
85
86 // Resize the erased tiles layer when necessary
87 if (bounds != combinedBounds) {
88 const QPoint shift = bounds.topLeft() - combinedBounds.topLeft();
89 mErasedCells->resize(combinedBounds.size(), shift);
90 }
91
92 // Copy the newly erased tiles over
93 const QRect otherBounds = o.mRegion.boundingRect();
94 const QPoint pos = otherBounds.topLeft() - combinedBounds.topLeft();
95 mErasedCells->merge(pos, o.mErasedCells);
96
97 mRegion = combinedRegion;
98 }
99 }
100
mergeWith(const QUndoCommand * other)101 bool EraseTiles::mergeWith(const QUndoCommand *other)
102 {
103 const EraseTiles *o = static_cast<const EraseTiles*>(other);
104 if (!(mMapDocument == o->mMapDocument && o->mMergeable))
105 return false;
106 if (!cloneChildren(other, this))
107 return false;
108
109 QHashIterator<TileLayer*, LayerData> it(o->mLayerData);
110 while (it.hasNext()) {
111 it.next();
112 mLayerData[it.key()].mergeWith(it.value());
113 }
114
115 return true;
116 }
117