ManaPlus
simpleanimation.cpp
Go to the documentation of this file.
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-2019 The ManaPlus Developers
6  * Copyright (C) 2019-2021 Andrei Karas
7  *
8  * This file is part of The ManaPlus Client.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <http://www.gnu.org/licenses/>.
22  */
23 
25 
27 
28 #include "render/graphics.h"
29 
30 #include "resources/imageset.h"
31 
33 
34 #include "resources/dye/dye.h"
35 
37 
38 #include "utils/checkutils.h"
39 #include "utils/delete2.h"
40 
41 #include "debug.h"
42 
44  mAnimation(animation),
45  mAnimationTime(0),
46  mAnimationPhase(0),
47  mCurrentFrame(mAnimation != nullptr ? &mAnimation->mFrames[0] : nullptr),
48  mInitialized(true),
49  mImageSet(nullptr)
50 {
51 }
52 
53 SimpleAnimation::SimpleAnimation(XmlNodeConstPtr animationNode,
54  const std::string& dyePalettes) :
55  mAnimation(new Animation("simple animation")),
56  mAnimationTime(0),
57  mAnimationPhase(0),
58  mCurrentFrame(nullptr),
59  mInitialized(false),
60  mImageSet(nullptr)
61 {
62  initializeAnimation(animationNode, dyePalettes);
63  if (mAnimation != nullptr)
65  else
66  mCurrentFrame = nullptr;
67 }
68 
70 {
72  if (mImageSet != nullptr)
73  {
74  mImageSet->decRef();
75  mImageSet = nullptr;
76  }
77 }
78 
79 void SimpleAnimation::draw(Graphics *const graphics,
80  const int posX, const int posY) const
81 {
82  FUNC_BLOCK("SimpleAnimation::draw", 1)
83  if ((mCurrentFrame == nullptr) || (mCurrentFrame->image == nullptr))
84  return;
85 
86  graphics->drawImage(mCurrentFrame->image,
87  posX + mCurrentFrame->offsetX,
88  posY + mCurrentFrame->offsetY);
89 }
90 
92 {
93  mAnimationTime = 0;
94  mAnimationPhase = 0;
95 }
96 
98 {
99  if (mAnimation == nullptr)
100  return;
101 
102  if (frame < 0)
103  frame = 0;
104  const unsigned int len = CAST_U32(mAnimation->getLength());
105  if (CAST_U32(frame) >= len)
106  frame = len - 1;
107  mAnimationPhase = frame;
108  mCurrentFrame = &mAnimation->mFrames[frame];
109 }
110 
111 bool SimpleAnimation::update(const int timePassed)
112 {
113  if ((mCurrentFrame == nullptr) || (mAnimation == nullptr) || !mInitialized)
114  return false;
115 
116  bool updated(false);
117  mAnimationTime += timePassed;
118 
120  {
121  updated = true;
123  mAnimationPhase++;
124 
126  mAnimationPhase = 0;
127 
129  }
130  return updated;
131 }
132 
134 {
135  if (mAnimation == nullptr)
136  return 0;
137 
138  return CAST_S32(mAnimation->getLength());
139 }
140 
142 {
143  if (mCurrentFrame != nullptr)
144  return mCurrentFrame->image;
145  return nullptr;
146 }
147 
148 void SimpleAnimation::initializeAnimation(XmlNodeConstPtr animationNode,
149  const std::string &dyePalettes)
150 {
151  mInitialized = false;
152 
153  if (animationNode == nullptr)
154  return;
155 
156  std::string imagePath = XML::getProperty(
157  animationNode, "imageset", "");
158 
159  // Instanciate the dye coloration.
160  if (!imagePath.empty() && !dyePalettes.empty())
161  Dye::instantiate(imagePath, dyePalettes);
162 
163  const ImageSet *const imageset = Loader::getImageSet(
164  XML::getProperty(animationNode, "imageset", ""),
165  XML::getProperty(animationNode, "width", 0),
166  XML::getProperty(animationNode, "height", 0));
167 
168  if (imageset == nullptr)
169  return;
170 
171  const int x1 = imageset->getWidth() / 2 - mapTileSize / 2;
172  const int y1 = imageset->getHeight() - mapTileSize;
173 
174  // Get animation frames
175  for_each_xml_child_node (frameNode, animationNode)
176  {
177  const int delay = XML::getIntProperty(
178  frameNode, "delay", 0, 0, 100000);
179  const int offsetX = XML::getProperty(frameNode, "offsetX", 0) - x1;
180  const int offsetY = XML::getProperty(frameNode, "offsetY", 0) - y1;
181  const int rand = XML::getIntProperty(frameNode, "rand", 100, 0, 100);
182 
183  if (xmlNameEqual(frameNode, "frame"))
184  {
185  const int index = XML::getProperty(frameNode, "index", -1);
186 
187  if (index < 0)
188  {
189  reportAlways("No valid value for 'index'")
190  continue;
191  }
192 
193  Image *const img = imageset->get(index);
194 
195  if (img == nullptr)
196  {
197  reportAlways("No image at index %d", index)
198  continue;
199  }
200 
201  if (mAnimation != nullptr)
202  mAnimation->addFrame(img, delay, offsetX, offsetY, rand);
203  }
204  else if (xmlNameEqual(frameNode, "sequence"))
205  {
206  int start = XML::getProperty(frameNode, "start", -1);
207  const int end = XML::getProperty(frameNode, "end", -1);
208 
209  if (start < 0 || end < 0)
210  {
211  reportAlways("No valid value for 'start' or 'end'")
212  continue;
213  }
214 
215  while (end >= start)
216  {
217  Image *const img = imageset->get(start);
218 
219  if (img == nullptr)
220  {
221  reportAlways("No image at index %d", start)
222  continue;
223  }
224 
225  if (mAnimation != nullptr)
226  mAnimation->addFrame(img, delay, offsetX, offsetY, rand);
227  start++;
228  }
229  }
230  else if (xmlNameEqual(frameNode, "end"))
231  {
232  if (mAnimation != nullptr)
233  mAnimation->addTerminator(rand);
234  }
235  }
236 
237  mInitialized = true;
238 }
#define CAST_S32
Definition: cast.h:30
#define CAST_U32
Definition: cast.h:31
#define CAST_SIZE
Definition: cast.h:34
#define reportAlways(...)
Definition: checkutils.h:253
Frames mFrames
Definition: animation.h:99
void addTerminator(const int rand)
Definition: animation.cpp:56
void addFrame(Image *const image, const int delay, const int offsetX, const int offsetY, const int rand)
Definition: animation.cpp:46
size_t getLength() const
Definition: animation.h:70
static void instantiate(std::string &target, const std::string &palettes)
Definition: dye.cpp:97
virtual void drawImage(const Image *const image, int dstX, int dstY)=0
int getWidth() const
Definition: imageset.h:60
Image * get(const size_type i) const
Definition: imageset.cpp:67
int getHeight() const
Definition: imageset.h:66
virtual void decRef()
Definition: resource.cpp:50
bool update(const int timePassed)
Animation * mAnimation
const Frame * mCurrentFrame
ImageSet * mImageSet
int getLength() const
Image * getCurrentImage() const
void setFrame(int frame)
void draw(Graphics *const graphics, const int posX, const int posY) const
void initializeAnimation(const xmlNodePtr animationNode, const std::string &dyePalettes)
SimpleAnimation(Animation *const animation)
static const int mapTileSize
Definition: map.h:27
#define new
Definition: debug_new.h:147
#define delete2(var)
Definition: delete2.h:25
#define for_each_xml_child_node(var, parent)
Definition: libxml.h:161
#define nullptr
Definition: localconsts.h:45
ImageSet * getImageSet(const std::string &imagePath, const int w, const int h)
int getProperty(const xmlNodePtr node, const char *const name, int def)
Definition: libxml.cpp:174
int getIntProperty(const xmlNodePtr node, const char *const name, int def, const int min, const int max)
Definition: libxml.cpp:190
#define FUNC_BLOCK(name, id)
Definition: perfomance.h:81
Image * image
Definition: frame.h:42
int delay
Definition: frame.h:43
int offsetX
Definition: frame.h:44
int offsetY
Definition: frame.h:45