1 /*
2 * tile.cpp
3 * Copyright 2012-2014, Thorbjørn Lindeijer <thorbjorn@lindeijer.nl>
4 *
5 * This file is part of libtiled.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20 * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "tile.h"
30
31 #include "objectgroup.h"
32 #include "tileset.h"
33
34 using namespace Tiled;
35
Tile(int id,Tileset * tileset)36 Tile::Tile(int id, Tileset *tileset):
37 Object(TileType),
38 mId(id),
39 mTileset(tileset),
40 mImageStatus(LoadingReady),
41 mProbability(1.0),
42 mCurrentFrameIndex(0),
43 mUnusedTime(0)
44 {}
45
Tile(const QPixmap & image,int id,Tileset * tileset)46 Tile::Tile(const QPixmap &image, int id, Tileset *tileset):
47 Object(TileType),
48 mId(id),
49 mTileset(tileset),
50 mImage(image),
51 mImageStatus(image.isNull() ? LoadingError : LoadingReady),
52 mProbability(1.0),
53 mCurrentFrameIndex(0),
54 mUnusedTime(0)
55 {}
56
~Tile()57 Tile::~Tile()
58 {
59 }
60
61 /**
62 * Returns the tileset that this tile is part of as a shared pointer.
63 */
sharedTileset() const64 QSharedPointer<Tileset> Tile::sharedTileset() const
65 {
66 return mTileset->sharedPointer();
67 }
68
69 /**
70 * Returns the tile to render when taking into account tile animations.
71 *
72 * \warning May return null when the tileset is invalid or the image could
73 * not be loaded.
74 */
currentFrameTile() const75 const Tile *Tile::currentFrameTile() const
76 {
77 if (isAnimated()) {
78 const Frame &frame = mFrames.at(mCurrentFrameIndex);
79 return mTileset->findTile(frame.tileId);
80 }
81 return this;
82 }
83
84 /**
85 * Returns the drawing offset of the tile (in pixels).
86 */
offset() const87 QPoint Tile::offset() const
88 {
89 return mTileset->tileOffset();
90 }
91
92 /**
93 * Sets \a objectGroup to be the group of objects associated with this tile.
94 * The Tile takes ownership over the ObjectGroup and it can't also be part of
95 * a map.
96 */
setObjectGroup(std::unique_ptr<ObjectGroup> objectGroup)97 void Tile::setObjectGroup(std::unique_ptr<ObjectGroup> objectGroup)
98 {
99 Q_ASSERT(!objectGroup || !objectGroup->map());
100
101 if (mObjectGroup == objectGroup)
102 return;
103
104 mObjectGroup = std::move(objectGroup);
105 }
106
107 /**
108 * Swaps the object group of this tile with \a objectGroup. The tile releases
109 * ownership over its existing object group and takes ownership over the new
110 * one.
111 */
swapObjectGroup(std::unique_ptr<ObjectGroup> & objectGroup)112 void Tile::swapObjectGroup(std::unique_ptr<ObjectGroup> &objectGroup)
113 {
114 std::swap(mObjectGroup, objectGroup);
115 }
116
117 /**
118 * Sets the animation frames to be used by this tile. Resets any currently
119 * running animation.
120 */
setFrames(const QVector<Frame> & frames)121 void Tile::setFrames(const QVector<Frame> &frames)
122 {
123 resetAnimation();
124 mFrames = frames;
125 }
126
127 /**
128 * Resets the tile animation. Returns whether this caused the current tileId to
129 * change.
130 */
resetAnimation()131 bool Tile::resetAnimation()
132 {
133 if (!isAnimated())
134 return false;
135
136 Frame previousFrame = mFrames.at(mCurrentFrameIndex);
137 Frame currentFrame = mFrames.at(0);
138
139 mCurrentFrameIndex = 0;
140 mUnusedTime = 0;
141
142 return previousFrame.tileId != currentFrame.tileId;
143 }
144
145 /**
146 * Advances this tile animation by the given amount of milliseconds. Returns
147 * whether this caused the current tileId to change.
148 */
advanceAnimation(int ms)149 bool Tile::advanceAnimation(int ms)
150 {
151 if (!isAnimated())
152 return false;
153
154 mUnusedTime += ms;
155
156 Frame frame = mFrames.at(mCurrentFrameIndex);
157 const int previousTileId = frame.tileId;
158
159 while (frame.duration > 0 && mUnusedTime > frame.duration) {
160 mUnusedTime -= frame.duration;
161 mCurrentFrameIndex = (mCurrentFrameIndex + 1) % mFrames.size();
162
163 frame = mFrames.at(mCurrentFrameIndex);
164 }
165
166 return previousTileId != frame.tileId;
167 }
168
169 /**
170 * Returns a duplicate of this tile, to be added to the given \a tileset.
171 */
clone(Tileset * tileset) const172 Tile *Tile::clone(Tileset *tileset) const
173 {
174 Tile *c = new Tile(mImage, mId, tileset);
175 c->setProperties(properties());
176
177 c->mImageSource = mImageSource;
178 c->mImageStatus = mImageStatus;
179 c->mType = mType;
180 c->mProbability = mProbability;
181
182 if (mObjectGroup)
183 c->mObjectGroup.reset(mObjectGroup->clone());
184
185 c->mFrames = mFrames;
186 c->mCurrentFrameIndex = mCurrentFrameIndex;
187 c->mUnusedTime = mUnusedTime;
188
189 return c;
190 }
191