FIFE  be64c707dea6b3250bd4355bf5c825d25920087d
animationloader.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005-2019 by the FIFE team *
3  * http://www.fifengine.net *
4  * This file is part of FIFE. *
5  * *
6  * FIFE is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU Lesser General Public *
8  * License as published by the Free Software Foundation; either *
9  * version 2.1 of the License, or (at your option) any later version. *
10  * *
11  * This library is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14  * Lesser General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU Lesser General Public *
17  * License along with this library; if not, write to the *
18  * Free Software Foundation, Inc., *
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 
24 // 3rd party library includes
25 #include <tinyxml.h>
26 
27 // FIFE includes
28 // These includes are split up in two parts, separated by one empty line
29 // First block: files included from the FIFE root src directory
30 // Second block: files included from the same folder
32 #include "vfs/vfs.h"
33 #include "vfs/raw/rawdata.h"
34 #include "video/imagemanager.h"
35 #include "video/animationmanager.h"
36 #include "video/image.h"
37 #include "video/animation.h"
38 #include "util/base/exception.h"
39 #include "util/log/logger.h"
40 #include "util/resource/resource.h"
42 
43 #include "animationloader.h"
44 
45 namespace FIFE {
49  static Logger _log(LM_NATIVE_LOADERS);
50 
51  AnimationLoader::AnimationLoader(VFS* vfs, ImageManager* imageManager, AnimationManager* animationManager)
52  : m_vfs(vfs), m_imageManager(imageManager), m_animationManager(animationManager) {
53 
54  }
55 
56  bool AnimationLoader::isLoadable(const std::string& filename) {
57  bfs::path animPath(filename);
58 
59  std::string animationFilename = animPath.string();
60  TiXmlDocument animFile;
61 
62  try {
63  RawData* data = m_vfs->open(animationFilename);
64 
65  if (data) {
66  if (data->getDataLength() != 0) {
67  // TODO - this could be expanded to do more checks
68  animFile.Parse(data->readString(data->getDataLength()).c_str());
69 
70  if (animFile.Error()) {
71  return false;
72  }
73  }
74 
75  // done with data delete resource
76  delete data;
77  data = 0;
78  }
79  }
80  catch (NotFound&) {
81  return false;
82  }
83 
84  // if we get here then loading the file went well
85  TiXmlElement* root = animFile.RootElement();
86 
87  if (root && root->ValueStr() == "assets") {
88  if (root->FirstChildElement("animation")) {
89  return true;
90  }
91  }
92 
93  return false;
94  }
95 
96  AnimationPtr AnimationLoader::load(const std::string& filename) {
97  bfs::path animPath(filename);
98 
99  std::string animationFilename = animPath.string();
100 
101  TiXmlDocument doc;
102 
103  AnimationPtr animation;
104 
105  try {
106  RawData* data = m_vfs->open(animationFilename);
107 
108  if (data) {
109  if (data->getDataLength() != 0) {
110  doc.Parse(data->readString(data->getDataLength()).c_str());
111 
112  if (doc.Error()) {
113  return animation;
114  }
115 
116  // done with data delete resource
117  delete data;
118  data = 0;
119  }
120  }
121  }
122  catch (NotFound& e) {
123  FL_ERR(_log, e.what());
124 
125  // TODO - should we abort here
126  // or rethrow the exception
127  // or just keep going
128 
129  return animation;
130  }
131 
132  // if we get here then everything loaded properly
133  // so we can just parse out the contents
134  TiXmlElement* root = doc.RootElement();
135 
136  if (root && root->ValueStr() == "assets") {
137  animation = loadAnimation(filename, root->FirstChildElement("animation"));
138  }
139 
140  return animation;
141  }
142 
143  std::vector<AnimationPtr> AnimationLoader::loadMultiple(const std::string& filename) {
144  bfs::path animPath(filename);
145 
146  std::string animationFilename = animPath.string();
147 
148  TiXmlDocument doc;
149 
150  std::vector<AnimationPtr> animationVector;
151 
152  try {
153  RawData* data = m_vfs->open(animationFilename);
154 
155  if (data) {
156  if (data->getDataLength() != 0) {
157  doc.Parse(data->readString(data->getDataLength()).c_str());
158 
159  if (doc.Error()) {
160  return animationVector;
161  }
162 
163  // done with data delete resource
164  delete data;
165  data = 0;
166  }
167  }
168  }
169  catch (NotFound& e) {
170  FL_ERR(_log, e.what());
171 
172  // TODO - should we abort here
173  // or rethrow the exception
174  // or just keep going
175 
176  return animationVector;
177  }
178 
179  // if we get here then everything loaded properly
180  // so we can just parse out the contents
181  TiXmlElement* root = doc.RootElement();
182 
183  if (root && root->ValueStr() == "assets") {
184  for (TiXmlElement* animationElem = root->FirstChildElement("animation"); animationElem; animationElem = animationElem->NextSiblingElement("animation")) {
185  AnimationPtr animation = loadAnimation(filename, animationElem);
186  if (animation) {
187  animationVector.push_back(animation);
188  }
189  }
190  }
191 
192  return animationVector;
193  }
194 
195  AnimationPtr AnimationLoader::loadAnimation(const std::string& filename, TiXmlElement* animationElem) {
196  AnimationPtr animation;
197  if (!animationElem) {
198  return animation;
199  }
200 
201  bfs::path animPath(filename);
202  std::string animationFilename = animPath.string();
203 
204  bool alreadyLoaded = false;
205  // first try to use the id, if no id exists it use the filename as fallback
206  const std::string* animationId = animationElem->Attribute(std::string("id"));
207  if (animationId) {
208  if (!m_animationManager->exists(*animationId)) {
209  animation = m_animationManager->create(*animationId);
210  } else {
211  animation = m_animationManager->getPtr(*animationId);
212  alreadyLoaded = animation->getFrameCount() != 0;
213  }
214  } else {
215  if (HasParentPath(animPath)) {
216  animPath= GetParentPath(animPath) / animationFilename;
217  } else {
218  animPath = bfs::path(animationFilename);
219  }
220  if (!m_animationManager->exists(animPath.string())) {
221  animation = m_animationManager->create(animPath.string());
222  } else {
223  animation = m_animationManager->getPtr(animPath.string());
224  alreadyLoaded = animation->getFrameCount() != 0;
225  }
226  }
227 
228  if (alreadyLoaded) {
229  return animation;
230  }
231 
232  int direction = 0;
233  int actionFrame = -1;
234  int animDelay = 0;
235  int animXoffset = 0;
236  int animYoffset = 0;
237 
238  int success = animationElem->QueryValueAttribute("direction", &direction);
239  if (success == TIXML_SUCCESS) {
240  animation->setDirection(direction);
241  }
242  success = animationElem->QueryValueAttribute("action_frame", &actionFrame);
243  if (success == TIXML_SUCCESS) {
244  animation->setActionFrame(actionFrame);
245  }
246  animationElem->QueryValueAttribute("delay", &animDelay);
247  animationElem->QueryValueAttribute("x_offset", &animXoffset);
248  animationElem->QueryValueAttribute("y_offset", &animYoffset);
249 
250  for (TiXmlElement* frameElement = animationElem->FirstChildElement("frame"); frameElement; frameElement = frameElement->NextSiblingElement("frame")) {
251  const std::string* sourceId = frameElement->Attribute(std::string("source"));
252  if (sourceId) {
253  bfs::path framePath(filename);
254 
255  if (HasParentPath(framePath)) {
256  framePath = GetParentPath(framePath) / *sourceId;
257  if (!bfs::exists(framePath)) {
258  framePath = bfs::path(*sourceId);
259  }
260  } else {
261  framePath = bfs::path(*sourceId);
262  }
263 
264  ImagePtr imagePtr;
265  if (!m_imageManager->exists(framePath.string())) {
266  imagePtr = m_imageManager->create(framePath.string());
267  } else {
268  imagePtr = m_imageManager->getPtr(framePath.string());
269  }
270 
271  if (imagePtr) {
272  int frameXoffset = 0;
273  success = frameElement->QueryValueAttribute("x_offset", &frameXoffset);
274  if (success == TIXML_SUCCESS) {
275  imagePtr->setXShift(frameXoffset);
276  } else {
277  imagePtr->setXShift(animXoffset);
278  }
279 
280  int frameYoffset = 0;
281  success = frameElement->QueryValueAttribute("y_offset", &frameYoffset);
282  if (success == TIXML_SUCCESS) {
283  imagePtr->setYShift(frameYoffset);
284  } else {
285  imagePtr->setYShift(animYoffset);
286  }
287 
288  int frameDelay = 0;
289  success = frameElement->QueryValueAttribute("delay", &frameDelay);
290  if (success == TIXML_SUCCESS) {
291  animation->addFrame(imagePtr, frameDelay);
292  } else {
293  animation->addFrame(imagePtr, animDelay);
294  }
295  }
296  }
297  }
298 
299  return animation;
300  }
301 }
virtual ImagePtr create(IResourceLoader *loader=0)
Creates a blank Image but does not load it immediately.
virtual bool exists(const std::string &name)
Checks to see if an Image exists.
virtual std::vector< AnimationPtr > loadMultiple(const std::string &filename)
void setXShift(int32_t xshift)
Definition: image.h:119
ImageManager.
Definition: imagemanager.h:54
AnimationLoader(VFS *vfs, ImageManager *imageManager, AnimationManager *animationManager)
AnimationManager * m_animationManager
void setDirection(uint32_t direction)
Animation direction tells how this animation is associated with movement when played starting from fr...
Definition: animation.cpp:182
RawData * open(const std::string &path)
Open a file.
Definition: vfs.cpp:172
static Logger _log(LM_AUDIO)
virtual AnimationPtr getPtr(const std::string &name)
void setActionFrame(int32_t num)
Sets the action frame.
Definition: animation.h:114
virtual ImagePtr getPtr(const std::string &name)
#define FL_ERR(logger, msg)
Definition: logger.h:73
uint32_t getDataLength() const
get the complete datalength
Definition: rawdata.cpp:75
virtual AnimationPtr create(IResourceLoader *loader=0)
Creates a blank Animation but does not load it immediately.
AnimationManager.
bool HasParentPath(const bfs::path &path)
Helper function to determine if a path object has a parent path.
bfs::path GetParentPath(const bfs::path &path)
Helper function to retrieve a parent path object from a path object.
virtual AnimationPtr load(const std::string &filename)
std::string readString(size_t len)
read a string with len bytes, not assuming a terminating 0 Appends a null terminator character to the...
Definition: rawdata.cpp:128
void addFrame(ImagePtr image, uint32_t duration)
Adds new frame into animation Frames must be added starting from first frame.
Definition: animation.cpp:104
the main VFS (virtual file system) class
Definition: vfs.h:58
virtual bool exists(const std::string &name)
Checks to see if an Animation exists.
uint32_t getFrameCount() const
Get the number of frames.
Definition: animation.cpp:178
void setYShift(int32_t yshift)
Definition: image.h:125
AnimationPtr loadAnimation(const std::string &filename, TiXmlElement *animationElem)
ImageManager * m_imageManager
virtual bool isLoadable(const std::string &filename)
Used to access diffrent kinds of data.
Definition: rawdata.h:48