GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/resources/animation/simpleanimation.cpp Lines: 13 94 13.8 %
Date: 2017-11-29 Branches: 5 142 3.5 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2004-2009  The Mana World Development Team
4
 *  Copyright (C) 2009-2010  The Mana Developers
5
 *  Copyright (C) 2011-2017  The ManaPlus Developers
6
 *
7
 *  This file is part of The ManaPlus Client.
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or
12
 *  any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
#include "resources/animation/simpleanimation.h"
24
25
#include "const/resources/map/map.h"
26
27
#include "render/graphics.h"
28
29
#include "resources/imageset.h"
30
31
#include "resources/animation/animation.h"
32
33
#include "resources/dye/dye.h"
34
35
#include "resources/loaders/imagesetloader.h"
36
37
#include "utils/checkutils.h"
38
#include "utils/delete2.h"
39
40
#include "debug.h"
41
42
2
SimpleAnimation::SimpleAnimation(Animation *const animation) :
43
    mAnimation(animation),
44
    mAnimationTime(0),
45
    mAnimationPhase(0),
46
2
    mCurrentFrame(mAnimation != nullptr ? &mAnimation->mFrames[0] : nullptr),
47
    mInitialized(true),
48
4
    mImageSet(nullptr)
49
{
50
2
}
51
52
SimpleAnimation::SimpleAnimation(XmlNodeConstPtr animationNode,
53
                                 const std::string& dyePalettes) :
54
    mAnimation(new Animation("simple animation")),
55
    mAnimationTime(0),
56
    mAnimationPhase(0),
57
    mCurrentFrame(nullptr),
58
    mInitialized(false),
59
    mImageSet(nullptr)
60
{
61
    initializeAnimation(animationNode, dyePalettes);
62
    if (mAnimation != nullptr)
63
        mCurrentFrame = &mAnimation->mFrames[0];
64
    else
65
        mCurrentFrame = nullptr;
66
}
67
68
4
SimpleAnimation::~SimpleAnimation()
69
{
70
4
    delete2(mAnimation);
71
2
    if (mImageSet != nullptr)
72
    {
73
        mImageSet->decRef();
74
        mImageSet = nullptr;
75
    }
76
2
}
77
78
2
void SimpleAnimation::draw(Graphics *const graphics,
79
                           const int posX, const int posY) const
80
{
81
    FUNC_BLOCK("SimpleAnimation::draw", 1)
82

2
    if ((mCurrentFrame == nullptr) || (mCurrentFrame->image == nullptr))
83
        return;
84
85
4
    graphics->drawImage(mCurrentFrame->image,
86
2
        posX + mCurrentFrame->offsetX,
87
2
        posY + mCurrentFrame->offsetY);
88
}
89
90
void SimpleAnimation::reset()
91
{
92
    mAnimationTime = 0;
93
    mAnimationPhase = 0;
94
}
95
96
void SimpleAnimation::setFrame(int frame)
97
{
98
    if (mAnimation == nullptr)
99
        return;
100
101
    if (frame < 0)
102
        frame = 0;
103
    const unsigned int len = CAST_U32(mAnimation->getLength());
104
    if (CAST_U32(frame) >= len)
105
        frame = len - 1;
106
    mAnimationPhase = frame;
107
    mCurrentFrame = &mAnimation->mFrames[frame];
108
}
109
110
bool SimpleAnimation::update(const int timePassed)
111
{
112
    if ((mCurrentFrame == nullptr) || (mAnimation == nullptr) || !mInitialized)
113
        return false;
114
115
    bool updated(false);
116
    mAnimationTime += timePassed;
117
118
    while (mAnimationTime > mCurrentFrame->delay && mCurrentFrame->delay > 0)
119
    {
120
        updated = true;
121
        mAnimationTime -= mCurrentFrame->delay;
122
        mAnimationPhase++;
123
124
        if (CAST_SIZE(mAnimationPhase) >= mAnimation->getLength())
125
            mAnimationPhase = 0;
126
127
        mCurrentFrame = &mAnimation->mFrames[mAnimationPhase];
128
    }
129
    return updated;
130
}
131
132
int SimpleAnimation::getLength() const
133
{
134
    if (mAnimation == nullptr)
135
        return 0;
136
137
    return CAST_S32(mAnimation->getLength());
138
}
139
140
Image *SimpleAnimation::getCurrentImage() const
141
{
142
    if (mCurrentFrame != nullptr)
143
        return mCurrentFrame->image;
144
    return nullptr;
145
}
146
147
void SimpleAnimation::initializeAnimation(XmlNodeConstPtr animationNode,
148
                                          const std::string &dyePalettes)
149
{
150
    mInitialized = false;
151
152
    if (animationNode == nullptr)
153
        return;
154
155
    std::string imagePath = XML::getProperty(
156
        animationNode, "imageset", "");
157
158
    // Instanciate the dye coloration.
159
    if (!imagePath.empty() && !dyePalettes.empty())
160
        Dye::instantiate(imagePath, dyePalettes);
161
162
    const ImageSet *const imageset = Loader::getImageSet(
163
        XML::getProperty(animationNode, "imageset", ""),
164
        XML::getProperty(animationNode, "width", 0),
165
        XML::getProperty(animationNode, "height", 0));
166
167
    if (imageset == nullptr)
168
        return;
169
170
    const int x1 = imageset->getWidth() / 2 - mapTileSize / 2;
171
    const int y1 = imageset->getHeight() - mapTileSize;
172
173
    // Get animation frames
174
    for_each_xml_child_node (frameNode, animationNode)
175
    {
176
        const int delay = XML::getIntProperty(
177
            frameNode, "delay", 0, 0, 100000);
178
        const int offsetX = XML::getProperty(frameNode, "offsetX", 0) - x1;
179
        const int offsetY = XML::getProperty(frameNode, "offsetY", 0) - y1;
180
        const int rand = XML::getIntProperty(frameNode, "rand", 100, 0, 100);
181
182
        if (xmlNameEqual(frameNode, "frame"))
183
        {
184
            const int index = XML::getProperty(frameNode, "index", -1);
185
186
            if (index < 0)
187
            {
188
                reportAlways("No valid value for 'index'");
189
                continue;
190
            }
191
192
            Image *const img = imageset->get(index);
193
194
            if (img == nullptr)
195
            {
196
                reportAlways("No image at index %d", index);
197
                continue;
198
            }
199
200
            if (mAnimation != nullptr)
201
                mAnimation->addFrame(img, delay, offsetX, offsetY, rand);
202
        }
203
        else if (xmlNameEqual(frameNode, "sequence"))
204
        {
205
            int start = XML::getProperty(frameNode, "start", -1);
206
            const int end = XML::getProperty(frameNode, "end", -1);
207
208
            if (start < 0 || end < 0)
209
            {
210
                reportAlways("No valid value for 'start' or 'end'");
211
                continue;
212
            }
213
214
            while (end >= start)
215
            {
216
                Image *const img = imageset->get(start);
217
218
                if (img == nullptr)
219
                {
220
                    reportAlways("No image at index %d", start);
221
                    continue;
222
                }
223
224
                if (mAnimation != nullptr)
225
                    mAnimation->addFrame(img, delay, offsetX, offsetY, rand);
226
                start++;
227
            }
228
        }
229
        else if (xmlNameEqual(frameNode, "end"))
230
        {
231
            if (mAnimation != nullptr)
232
                mAnimation->addTerminator(rand);
233
        }
234
    }
235
236
    mInitialized = true;
237
}