FIFE
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
objectloader.cpp
Go to the documentation of this file.
1 /**************************************************************************
2 * Copyright (C) 2005-2013 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 
26 // FIFE includes
27 // These includes are split up in two parts, separated by one empty line
28 // First block: files included from the FIFE root src directory
29 // Second block: files included from the same folder
30 #include "ext/tinyxml/fife_tinyxml.h"
31 #include "util/log/logger.h"
32 #include "model/model.h"
33 #include "model/metamodel/object.h"
34 #include "model/metamodel/action.h"
36 #include "vfs/vfs.h"
37 #include "vfs/raw/rawdata.h"
38 #include "view/visual.h"
39 #include "video/imagemanager.h"
40 
41 #include "objectloader.h"
42 #include "animationloader.h"
43 
44 namespace FIFE {
48  static Logger _log(LM_NATIVE_LOADERS);
49 
50  ObjectLoader::ObjectLoader(Model* model, VFS* vfs, ImageManager* imageManager, const AnimationLoaderPtr& animationLoader)
51  : m_model(model), m_vfs(vfs), m_imageManager(imageManager) {
52  assert(m_model && m_vfs && m_imageManager);
53 
54  if (animationLoader) {
55  m_animationLoader = animationLoader;
56  }
57  else {
59  }
60  }
61 
63 
64  }
65 
67  assert(animationLoader);
68 
69  m_animationLoader = animationLoader;
70  }
71 
72  bool ObjectLoader::isLoadable(const std::string& filename) const {
73  bfs::path objectPath(filename);
74 
75  TiXmlDocument objectFile;
76 
77  try {
78  RawData* data = m_vfs->open(objectPath.string());
79 
80  if (data) {
81  if (data->getDataLength() != 0) {
82  objectFile.Parse(data->readString(data->getDataLength()).c_str());
83 
84  if (objectFile.Error()) {
85  std::ostringstream oss;
86  oss << " Failed to load"
87  << objectPath.string()
88  << " : " << __FILE__
89  << " [" << __LINE__ << "]"
90  << std::endl;
91  FL_ERR(_log, oss.str());
92 
93  return false;
94  }
95  }
96  else {
97  std::ostringstream oss;
98  oss << " Failed to load"
99  << objectPath.string()
100  << " : " << __FILE__
101  << " [" << __LINE__ << "]"
102  << std::endl;
103  FL_ERR(_log, oss.str());
104 
105  return false;
106  }
107 
108  // done with data delete resource
109  delete data;
110  data = 0;
111  }
112  else {
113  std::ostringstream oss;
114  oss << " Failed to load"
115  << objectPath.string()
116  << " : " << __FILE__
117  << " [" << __LINE__ << "]"
118  << std::endl;
119  FL_ERR(_log, oss.str());
120 
121  return false;
122  }
123  }
124  catch (NotFound&) {
125  std::ostringstream oss;
126  oss << " Failed to load"
127  << objectPath.string()
128  << " : " << __FILE__
129  << " [" << __LINE__ << "]"
130  << std::endl;
131  FL_ERR(_log, oss.str());
132 
133  // TODO - should we abort here
134  // or rethrow the exception
135  // or just keep going
136 
137  return false;
138  }
139 
140  // if we get here then loading the file went well
141  TiXmlElement* root = objectFile.RootElement();
142 
143  if (root && root->ValueStr() == "object") {
144  return true;
145  }
146  else {
147  return false;
148  }
149  }
150 
151  void ObjectLoader::load(const std::string& filename) {
152  bfs::path objectPath(filename);
153 
154  TiXmlDocument objectFile;
155 
156  try {
157  RawData* data = m_vfs->open(objectPath.string());
158 
159  if (data) {
160  if (data->getDataLength() != 0) {
161  objectFile.Parse(data->readString(data->getDataLength()).c_str());
162 
163  if (objectFile.Error()) {
164  return;
165  }
166  }
167 
168  // done with data delete resource
169  delete data;
170  data = 0;
171  }
172  }
173  catch (NotFound&) {
174  std::ostringstream oss;
175  oss << " Failed to load"
176  << objectPath.string()
177  << " : " << __FILE__
178  << " [" << __LINE__ << "]"
179  << std::endl;
180  FL_ERR(_log, oss.str());
181 
182  // TODO - should we abort here
183  // or rethrow the exception
184  // or just keep going
185 
186  return;
187  }
188 
189  // if we get here then loading the file went well
190  TiXmlElement* root = objectFile.RootElement();
191 
192  if (root && root->ValueStr() == "object") {
193  const std::string* objectId = root->Attribute(std::string("id"));
194  const std::string* namespaceId = root->Attribute(std::string("namespace"));
195 
196  Object* obj = NULL;
197  if (objectId && namespaceId) {
198  const std::string* parentId = root->Attribute(std::string("parent"));
199 
200  if (parentId) {
201  Object* parent = m_model->getObject(*parentId, *namespaceId);
202  if (parent) {
203  try {
204  obj = m_model->createObject(*objectId, *namespaceId, parent);
205  }
206  catch (NameClash&) {
207  // TODO - handle exception
208  assert(false);
209  }
210  }
211  }
212  else {
213  // this will make sure the object has not already been loaded
214  if (m_model->getObject(*objectId, *namespaceId) == NULL) {
215  try {
216  obj = m_model->createObject(*objectId, *namespaceId);
217  }
218  catch (NameClash &e) {
219  FL_ERR(_log, e.what());
220 
221  // TODO - handle exception
222  assert(false);
223  }
224  }
225  }
226  }
227 
228  if (obj) {
229  obj->setFilename(objectPath.string());
231 
232  int isBlocking = 0;
233  root->QueryIntAttribute("blocking", &isBlocking);
234  obj->setBlocking(isBlocking!=0);
235 
236  int isStatic = 0;
237  root->QueryIntAttribute("static", &isStatic);
238  obj->setStatic(isStatic!=0);
239 
240  const std::string* pather = root->Attribute(std::string("pather"));
241 
242  if (pather) {
243  obj->setPather(m_model->getPather(*pather));
244  }
245  else {
246  obj->setPather(m_model->getPather("RoutePather"));
247  }
248 
249  const std::string* costId = root->Attribute(std::string("cost_id"));
250  if (costId) {
251  obj->setCostId(*costId);
252  double cost = 1.0;
253  int success = root->QueryDoubleAttribute("cost", &cost);
254  if (success == TIXML_SUCCESS) {
255  obj->setCost(cost);
256  }
257  }
258 
259  const std::string* areaId = root->Attribute(std::string("area_id"));
260  if (areaId) {
261  obj->setArea(*areaId);
262  }
263 
264  // loop over all walkable areas
265  for (TiXmlElement* walkableElement = root->FirstChildElement("walkable_area"); walkableElement; walkableElement = walkableElement->NextSiblingElement("walkable_area")) {
266  const std::string* walkableId = walkableElement->Attribute(std::string("id"));
267  if (walkableId) {
268  obj->addWalkableArea(*walkableId);
269  }
270  }
271 
272  int cellStack = 0;
273  root->QueryIntAttribute("cellstack", &cellStack);
274  obj->setCellStackPosition(cellStack);
275 
276  double ax = 0;
277  double ay = 0;
278  double az = 0;
279 
280  int xRetVal = root->QueryValueAttribute("anchor_x", &ax);
281  int yRetVal = root->QueryValueAttribute("anchor_y", &ay);
282  if (xRetVal == TIXML_SUCCESS && yRetVal == TIXML_SUCCESS) {
283  obj->setRotationAnchor(ExactModelCoordinate(ax, ay, az));
284  }
285 
286  int isRestrictedRotation = 0;
287  root->QueryIntAttribute("restricted_rotation", &isRestrictedRotation);
288  obj->setRestrictedRotation(isRestrictedRotation!=0);
289 
290  int zStep = 0;
291  int zRetVal = root->QueryIntAttribute("z_step_limit", &zStep);
292  if (zRetVal == TIXML_SUCCESS) {
293  obj->setZStepRange(zStep);
294  }
295 
296  // loop over all multi parts
297  for (TiXmlElement* multiElement = root->FirstChildElement("multipart"); multiElement; multiElement = multiElement->NextSiblingElement("multipart")) {
298  const std::string* partId = multiElement->Attribute(std::string("id"));
299  if (partId) {
300  obj->addMultiPartId(*partId);
301  }
302  for (TiXmlElement* multiRotation = multiElement->FirstChildElement("rotation"); multiRotation; multiRotation = multiRotation->NextSiblingElement("rotation")) {
303  int rotation = 0;
304  multiRotation->QueryIntAttribute("rot", &rotation);
305  // relative coordinates which are used to position the object
306  for (TiXmlElement* multiCoordinate = multiRotation->FirstChildElement("occupied_coord"); multiCoordinate; multiCoordinate = multiCoordinate->NextSiblingElement("occupied_coord")) {
307  int x = 0;
308  int y = 0;
309  xRetVal = multiCoordinate->QueryValueAttribute("x", &x);
310  yRetVal = multiCoordinate->QueryValueAttribute("y", &y);
311  if (xRetVal == TIXML_SUCCESS && yRetVal == TIXML_SUCCESS) {
312  int z = 0;
313  multiCoordinate->QueryIntAttribute("z", &z);
314  obj->addMultiPartCoordinate(rotation, ModelCoordinate(x, y, z));
315  }
316  }
317  }
318  }
319 
320  // loop over all image tags
321  for (TiXmlElement* imageElement = root->FirstChildElement("image"); imageElement; imageElement = imageElement->NextSiblingElement("image")) {
322  const std::string* sourceId = imageElement->Attribute(std::string("source"));
323 
324  if (sourceId) {
325  bfs::path imagePath(filename);
326 
327  if (HasParentPath(imagePath)) {
328  imagePath = GetParentPath(imagePath) / *sourceId;
329  } else {
330  imagePath = bfs::path(*sourceId);
331  }
332 
333  ImagePtr imagePtr;
334  if(!m_imageManager->exists(imagePath.string())) {
335  imagePtr = m_imageManager->create(imagePath.string());
336  }
337  else {
338  imagePtr = m_imageManager->getPtr(imagePath.string());
339  }
340 
341  if (imagePtr) {
342  int xOffset = 0;
343  int success = imageElement->QueryIntAttribute("x_offset", &xOffset);
344 
345  if (success == TIXML_SUCCESS) {
346  imagePtr->setXShift(xOffset);
347  }
348 
349  int yOffset = 0;
350  success = imageElement->QueryIntAttribute("y_offset", &yOffset);
351 
352  if (success == TIXML_SUCCESS) {
353  imagePtr->setYShift(yOffset);
354  }
355 
356  int direction = 0;
357  success = imageElement->QueryIntAttribute("direction", &direction);
358 
359  if (success == TIXML_SUCCESS) {
360  ObjectVisual* objVisual = obj->getVisual<ObjectVisual>();
361 
362  if (objVisual) {
363  objVisual->addStaticImage(direction, static_cast<int32_t>(imagePtr->getHandle()));
364  }
365  }
366  }
367  }
368  }
369 
370  for (TiXmlElement* actionElement = root->FirstChildElement("action"); actionElement; actionElement = actionElement->NextSiblingElement("action")) {
371  const std::string* actionId = actionElement->Attribute(std::string("id"));
372 
373  if (actionId) {
374  Action* action = obj->createAction(*actionId);
375  ActionVisual::create(action);
376 
377  for (TiXmlElement* animElement = actionElement->FirstChildElement("animation"); animElement; animElement = animElement->NextSiblingElement("animation")) {
378  const std::string* sourceId = animElement->Attribute(std::string("atlas"));
379  if(sourceId) {
380  bfs::path atlasPath(filename);
381 
382  if (HasParentPath(atlasPath)) {
383  atlasPath = GetParentPath(atlasPath) / *sourceId;
384  } else {
385  atlasPath = bfs::path(*sourceId);
386  }
387 
388  ImagePtr atlasImgPtr;
389  // we need to load this since its shared image
390  if(!m_imageManager->exists(atlasPath.string())) {
391  atlasImgPtr = m_imageManager->create(atlasPath.string());
392  }
393  else {
394  atlasImgPtr = m_imageManager->getPtr(atlasPath.string());
395  }
396 
397  int animFrames = 0;
398  int animDelay = 0;
399  int animXoffset = 0;
400  int animYoffset = 0;
401  int frameWidth = 0;
402  int frameHeight = 0;
403 
404  animElement->QueryValueAttribute("width", &frameWidth);
405  animElement->QueryValueAttribute("height", &frameHeight);
406  animElement->QueryValueAttribute("frames", &animFrames);
407  animElement->QueryValueAttribute("delay", &animDelay);
408  animElement->QueryValueAttribute("x_offset", &animXoffset);
409  animElement->QueryValueAttribute("y_offset", &animYoffset);
410  int nDir = 0;
411 
412  for (TiXmlElement* dirElement = animElement->FirstChildElement("direction");
413  dirElement; dirElement = dirElement->NextSiblingElement("direction")) {
414  AnimationPtr animation(new Animation);
415 
416  int dir;
417  dirElement->QueryIntAttribute("dir", &dir);
418 
419  int frames;
420  int success;
421 
422  success = dirElement->QueryValueAttribute("frames", &frames);
423  if(success != TIXML_SUCCESS) {
424  frames = animFrames;
425  }
426 
427  int delay;
428  success = dirElement->QueryValueAttribute("delay", &delay);
429  if(success != TIXML_SUCCESS) {
430  delay = animDelay;
431  }
432 
433  int xoffset;
434  success = dirElement->QueryValueAttribute("x_offset", &xoffset);
435  if(success != TIXML_SUCCESS) {
436  xoffset = animXoffset;
437  }
438 
439  int yoffset;
440  success = dirElement->QueryValueAttribute("y_offset", &yoffset);
441  if(success != TIXML_SUCCESS) {
442  yoffset = animYoffset;
443  }
444 
445  int action_frame;
446  success = dirElement->QueryValueAttribute("action", &action_frame);
447  if(success == TIXML_SUCCESS) {
448  animation->setActionFrame(action_frame);
449  }
450 
451  for (int iframe = 0; iframe < frames; ++iframe) {
452  static char tmpBuf[64];
453  sprintf(tmpBuf, "%03d:%04d", dir, iframe);
454 
455  std::string frameId = *objectId + ":" + *actionId + ":" + std::string(tmpBuf);
456 
457  ImagePtr framePtr;
458  if (!m_imageManager->exists(frameId)) {
459  framePtr = m_imageManager->create(frameId);
460  Rect region(
461  frameWidth * iframe, frameHeight * nDir, frameWidth, frameHeight
462  );
463  framePtr->useSharedImage(atlasImgPtr, region);
464  framePtr->setXShift(xoffset);
465  framePtr->setYShift(yoffset);
466  }
467  else {
468  framePtr = m_imageManager->getPtr(frameId);
469  }
470  animation->addFrame(framePtr, delay);
471  }
472 
473  ActionVisual* actionVisual = action->getVisual<ActionVisual>();
474  if(actionVisual) {
475  actionVisual->addAnimation(dir, animation);
476  action->setDuration(animation->getDuration());
477  }
478  ++nDir;
479  }
480 
481  } else {
482  sourceId = animElement->Attribute(std::string("source"));
483  if (sourceId) {
484  bfs::path animPath(filename);
485 
486  if (HasParentPath(animPath)) {
487  animPath = GetParentPath(animPath) / *sourceId;
488  } else {
489  animPath = bfs::path(*sourceId);
490  }
491 
492  AnimationPtr animation;
493  if (m_animationLoader && m_animationLoader->isLoadable(animPath.string())) {
494  animation = m_animationLoader->load(animPath.string());
495  }
496 
497  int direction = 0;
498  animElement->QueryIntAttribute("direction", &direction);
499 
500  if (action && animation) {
501  ActionVisual* actionVisual = action->getVisual<ActionVisual>();
502 
503  if (actionVisual) {
504  actionVisual->addAnimation(direction, animation);
505  action->setDuration(animation->getDuration());
506  }
507  }
508  }
509  }
510  }
511  }
512  }
513  }
514  }
515  }
516 
517 }
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.
uint32_t getDataLength() const
get the complete datalength
Definition: rawdata.cpp:75
void setXShift(int32_t xshift)
Definition: image.h:114
ImageManager.
Definition: imagemanager.h:54
void setArea(const std::string &id)
Sets the area id that the instances of this object adds to their cells.
Definition: object.cpp:330
T * getVisual() const
Gets used visualization.
Definition: action.h:73
Object class.
Definition: object.h:51
void reset(T *ptr=0)
reset this pointer to a null shared pointer this can be used to lower the reference count of the shar...
Definition: sharedptr.h:164
void setRotationAnchor(const ExactModelCoordinate &anchor)
Sets the rotation anchor for this multi object.
Definition: object.cpp:296
Action visual contains data that is needed to visualize different actions on screen.
Definition: visual.h:165
uint32_t getDuration() const
Gets the total duration for the whole animation.
Definition: animation.h:129
Object * createObject(const std::string &identifier, const std::string &name_space, Object *parent=0)
Add an object to the metamodel.
Definition: model.cpp:149
void setCellStackPosition(uint8_t position)
Sets the cell stack position.
Definition: object.cpp:169
static ActionVisual * create(Action *action)
Constructs and assigns it to the passed item.
Definition: visual.cpp:147
RawData * open(const std::string &path)
Open a file.
Definition: vfs.cpp:157
virtual bool isLoadable(const std::string &filename) const
Animation.
Definition: animation.h:56
static Logger _log(LM_AUDIO)
void setZStepRange(int32_t zRange)
Sets z-step range for object.
Definition: object.cpp:322
ImageManager * m_imageManager
Definition: objectloader.h:69
void setActionFrame(int32_t num)
Sets the action frame.
Definition: animation.h:105
void setFilename(const std::string &file)
Definition: object.cpp:161
virtual ImagePtr getPtr(const std::string &name)
virtual void load(const std::string &filename)
#define FL_ERR(logger, msg)
Definition: logger.h:73
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.
T * getVisual() const
Gets used visualization.
Definition: object.h:122
Point3D ModelCoordinate
Definition: modelcoords.h:37
void setRestrictedRotation(bool restrict)
Sets the rotation to restricted.
Definition: object.cpp:304
void addMultiPartCoordinate(int32_t rotation, ModelCoordinate coord)
Adds rotationally dependent coordinates for this object part.
Definition: object.cpp:248
void addAnimation(uint32_t angle, AnimationPtr animationptr)
Adds new animation with given angle (degrees)
Definition: visual.cpp:159
virtual void setAnimationLoader(const AnimationLoaderPtr &animationLoader)
A model is a facade for everything in the model.
Definition: model.h:53
void setCost(double cost)
Sets the cost.
Definition: object.cpp:189
ObjectLoader(Model *model, VFS *vfs, ImageManager *imageManager, const AnimationLoaderPtr &animationLoader=AnimationLoaderPtr())
Action * createAction(const std::string &identifier, bool is_default=false)
Adds new action with given id.
Definition: object.cpp:69
Object visual contains data that is needed for visualizing objects.
Definition: visual.h:65
AnimationLoaderPtr m_animationLoader
Definition: objectloader.h:70
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
DoublePoint3D ExactModelCoordinate
Definition: modelcoords.h:36
void addMultiPartId(const std::string &partId)
Adds a multi part identifier.
Definition: object.cpp:201
static ObjectVisual * create(Object *object)
Constructs and assigns it to the passed item.
Definition: visual.cpp:55
void addStaticImage(uint32_t angle, int32_t image_index)
Adds new static image with given angle (degrees) Static images are used in case there are no actions ...
Definition: visual.cpp:67
void setStatic(bool stat)
Set to true, if object is such that it doesn&#39;t move.
Definition: object.h:134
void addFrame(ImagePtr image, uint32_t duration)
Adds new frame into animation Frames must be added starting from first frame.
Definition: animation.cpp:52
the main VFS (virtual file system) class
Definition: vfs.h:58
IPather * getPather(const std::string &pathername)
Returns pather corresponding given name.
Definition: model.cpp:81
virtual void useSharedImage(const ImagePtr &shared, const Rect &region)=0
After this call all image data will be taken from the given image and its subregion.
virtual AnimationPtr load(const std::string &filename)=0
responsible for loading the animation returns a shared pointer to an animation resource ...
void addWalkableArea(const std::string &id)
Adds an area id to walkable area.
Definition: object.cpp:338
Object * getObject(const std::string &id, const std::string &name_space)
Get an object by its id.
Definition: model.cpp:224
void setDuration(uint32_t duration)
Sets the duration for this action.
Definition: action.h:61
void setPather(IPather *pather)
Sets pather used by instances created out of this object.
Definition: object.cpp:137
void setBlocking(bool blocking)
Sets if object blocks movement.
Definition: object.h:126
void setYShift(int32_t yshift)
Definition: image.h:120
ResourceHandle getHandle()
Definition: resource.h:68
virtual bool isLoadable(const std::string &filename)=0
determines whether the resource is in the correct format for this loader
void setCostId(const std::string &cost)
Sets the cost id.
Definition: object.cpp:181
Used to access diffrent kinds of data.
Definition: rawdata.h:48