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  double speed = 1.0;
260  int success = root->QueryDoubleAttribute("speed", &speed);
261  if (success == TIXML_SUCCESS) {
262  obj->setSpeed(speed);
263  }
264 
265  const std::string* areaId = root->Attribute(std::string("area_id"));
266  if (areaId) {
267  obj->setArea(*areaId);
268  }
269 
270  // loop over all walkable areas
271  for (TiXmlElement* walkableElement = root->FirstChildElement("walkable_area"); walkableElement; walkableElement = walkableElement->NextSiblingElement("walkable_area")) {
272  const std::string* walkableId = walkableElement->Attribute(std::string("id"));
273  if (walkableId) {
274  obj->addWalkableArea(*walkableId);
275  }
276  }
277 
278  int cellStack = 0;
279  root->QueryIntAttribute("cellstack", &cellStack);
280  obj->setCellStackPosition(cellStack);
281 
282  double ax = 0;
283  double ay = 0;
284  double az = 0;
285 
286  int xRetVal = root->QueryValueAttribute("anchor_x", &ax);
287  int yRetVal = root->QueryValueAttribute("anchor_y", &ay);
288  if (xRetVal == TIXML_SUCCESS && yRetVal == TIXML_SUCCESS) {
289  obj->setRotationAnchor(ExactModelCoordinate(ax, ay, az));
290  }
291 
292  int isRestrictedRotation = 0;
293  root->QueryIntAttribute("restricted_rotation", &isRestrictedRotation);
294  obj->setRestrictedRotation(isRestrictedRotation!=0);
295 
296  int zStep = 0;
297  int zRetVal = root->QueryIntAttribute("z_step_limit", &zStep);
298  if (zRetVal == TIXML_SUCCESS) {
299  obj->setZStepRange(zStep);
300  }
301 
302  // loop over all multi parts
303  for (TiXmlElement* multiElement = root->FirstChildElement("multipart"); multiElement; multiElement = multiElement->NextSiblingElement("multipart")) {
304  const std::string* partId = multiElement->Attribute(std::string("id"));
305  if (partId) {
306  obj->addMultiPartId(*partId);
307  }
308  for (TiXmlElement* multiRotation = multiElement->FirstChildElement("rotation"); multiRotation; multiRotation = multiRotation->NextSiblingElement("rotation")) {
309  int rotation = 0;
310  multiRotation->QueryIntAttribute("rot", &rotation);
311  // relative coordinates which are used to position the object
312  for (TiXmlElement* multiCoordinate = multiRotation->FirstChildElement("occupied_coord"); multiCoordinate; multiCoordinate = multiCoordinate->NextSiblingElement("occupied_coord")) {
313  int x = 0;
314  int y = 0;
315  xRetVal = multiCoordinate->QueryValueAttribute("x", &x);
316  yRetVal = multiCoordinate->QueryValueAttribute("y", &y);
317  if (xRetVal == TIXML_SUCCESS && yRetVal == TIXML_SUCCESS) {
318  int z = 0;
319  multiCoordinate->QueryIntAttribute("z", &z);
320  obj->addMultiPartCoordinate(rotation, ModelCoordinate(x, y, z));
321  }
322  }
323  }
324  }
325 
326  // loop over all image tags
327  for (TiXmlElement* imageElement = root->FirstChildElement("image"); imageElement; imageElement = imageElement->NextSiblingElement("image")) {
328  const std::string* sourceId = imageElement->Attribute(std::string("source"));
329 
330  if (sourceId) {
331  bfs::path imagePath(filename);
332 
333  if (HasParentPath(imagePath)) {
334  imagePath = GetParentPath(imagePath) / *sourceId;
335  } else {
336  imagePath = bfs::path(*sourceId);
337  }
338 
339  ImagePtr imagePtr;
340  if(!m_imageManager->exists(imagePath.string())) {
341  imagePtr = m_imageManager->create(imagePath.string());
342  }
343  else {
344  imagePtr = m_imageManager->getPtr(imagePath.string());
345  }
346 
347  if (imagePtr) {
348  int xOffset = 0;
349  int success = imageElement->QueryIntAttribute("x_offset", &xOffset);
350 
351  if (success == TIXML_SUCCESS) {
352  imagePtr->setXShift(xOffset);
353  }
354 
355  int yOffset = 0;
356  success = imageElement->QueryIntAttribute("y_offset", &yOffset);
357 
358  if (success == TIXML_SUCCESS) {
359  imagePtr->setYShift(yOffset);
360  }
361 
362  int direction = 0;
363  success = imageElement->QueryIntAttribute("direction", &direction);
364 
365  if (success == TIXML_SUCCESS) {
366  ObjectVisual* objVisual = obj->getVisual<ObjectVisual>();
367 
368  if (objVisual) {
369  objVisual->addStaticImage(direction, static_cast<int32_t>(imagePtr->getHandle()));
370  }
371  }
372  }
373  }
374  }
375 
376  for (TiXmlElement* actionElement = root->FirstChildElement("action"); actionElement; actionElement = actionElement->NextSiblingElement("action")) {
377  const std::string* actionId = actionElement->Attribute(std::string("id"));
378 
379  if (actionId) {
380  Action* action = obj->createAction(*actionId);
381  ActionVisual::create(action);
382 
383  for (TiXmlElement* animElement = actionElement->FirstChildElement("animation"); animElement; animElement = animElement->NextSiblingElement("animation")) {
384  const std::string* sourceId = animElement->Attribute(std::string("atlas"));
385  if(sourceId) {
386  bfs::path atlasPath(filename);
387 
388  if (HasParentPath(atlasPath)) {
389  atlasPath = GetParentPath(atlasPath) / *sourceId;
390  } else {
391  atlasPath = bfs::path(*sourceId);
392  }
393 
394  ImagePtr atlasImgPtr;
395  // we need to load this since its shared image
396  if(!m_imageManager->exists(atlasPath.string())) {
397  atlasImgPtr = m_imageManager->create(atlasPath.string());
398  }
399  else {
400  atlasImgPtr = m_imageManager->getPtr(atlasPath.string());
401  }
402 
403  int animFrames = 0;
404  int animDelay = 0;
405  int animXoffset = 0;
406  int animYoffset = 0;
407  int frameWidth = 0;
408  int frameHeight = 0;
409 
410  animElement->QueryValueAttribute("width", &frameWidth);
411  animElement->QueryValueAttribute("height", &frameHeight);
412  animElement->QueryValueAttribute("frames", &animFrames);
413  animElement->QueryValueAttribute("delay", &animDelay);
414  animElement->QueryValueAttribute("x_offset", &animXoffset);
415  animElement->QueryValueAttribute("y_offset", &animYoffset);
416  int nDir = 0;
417 
418  for (TiXmlElement* dirElement = animElement->FirstChildElement("direction");
419  dirElement; dirElement = dirElement->NextSiblingElement("direction")) {
420  AnimationPtr animation(new Animation);
421 
422  int dir;
423  dirElement->QueryIntAttribute("dir", &dir);
424 
425  int frames;
426  int success;
427 
428  success = dirElement->QueryValueAttribute("frames", &frames);
429  if(success != TIXML_SUCCESS) {
430  frames = animFrames;
431  }
432 
433  int delay;
434  success = dirElement->QueryValueAttribute("delay", &delay);
435  if(success != TIXML_SUCCESS) {
436  delay = animDelay;
437  }
438 
439  int xoffset;
440  success = dirElement->QueryValueAttribute("x_offset", &xoffset);
441  if(success != TIXML_SUCCESS) {
442  xoffset = animXoffset;
443  }
444 
445  int yoffset;
446  success = dirElement->QueryValueAttribute("y_offset", &yoffset);
447  if(success != TIXML_SUCCESS) {
448  yoffset = animYoffset;
449  }
450 
451  int action_frame;
452  success = dirElement->QueryValueAttribute("action", &action_frame);
453  if(success == TIXML_SUCCESS) {
454  animation->setActionFrame(action_frame);
455  }
456 
457  for (int iframe = 0; iframe < frames; ++iframe) {
458  static char tmpBuf[64];
459  sprintf(tmpBuf, "%03d:%04d", dir, iframe);
460 
461  std::string frameId = *objectId + ":" + *actionId + ":" + std::string(tmpBuf);
462 
463  ImagePtr framePtr;
464  if (!m_imageManager->exists(frameId)) {
465  framePtr = m_imageManager->create(frameId);
466  Rect region(
467  frameWidth * iframe, frameHeight * nDir, frameWidth, frameHeight
468  );
469  framePtr->useSharedImage(atlasImgPtr, region);
470  framePtr->setXShift(xoffset);
471  framePtr->setYShift(yoffset);
472  }
473  else {
474  framePtr = m_imageManager->getPtr(frameId);
475  }
476  animation->addFrame(framePtr, delay);
477  }
478 
479  ActionVisual* actionVisual = action->getVisual<ActionVisual>();
480  if(actionVisual) {
481  actionVisual->addAnimation(dir, animation);
482  action->setDuration(animation->getDuration());
483  }
484  ++nDir;
485  }
486 
487  } else {
488  sourceId = animElement->Attribute(std::string("source"));
489  if (sourceId) {
490  bfs::path animPath(filename);
491 
492  if (HasParentPath(animPath)) {
493  animPath = GetParentPath(animPath) / *sourceId;
494  } else {
495  animPath = bfs::path(*sourceId);
496  }
497 
498  AnimationPtr animation;
499  if (m_animationLoader && m_animationLoader->isLoadable(animPath.string())) {
500  animation = m_animationLoader->load(animPath.string());
501  }
502 
503  int direction = 0;
504  animElement->QueryIntAttribute("direction", &direction);
505 
506  if (action && animation) {
507  ActionVisual* actionVisual = action->getVisual<ActionVisual>();
508 
509  if (actionVisual) {
510  actionVisual->addAnimation(direction, animation);
511  action->setDuration(animation->getDuration());
512  }
513  }
514  }
515  }
516  }
517  }
518  }
519  }
520  }
521  }
522 
523 }
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:118
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:573
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:508
Action visual contains data that is needed to visualize different actions on screen.
Definition: visual.h:212
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:158
void setCellStackPosition(uint8_t position)
Sets the cell stack position.
Definition: object.cpp:258
static ActionVisual * create(Action *action)
Constructs and assigns it to the passed item.
Definition: visual.cpp:228
RawData * open(const std::string &path)
Open a file.
Definition: vfs.cpp:172
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:556
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:250
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:525
void addMultiPartCoordinate(int32_t rotation, ModelCoordinate coord)
Adds rotationally dependent coordinates for this object part.
Definition: object.cpp:442
void addAnimation(uint32_t angle, AnimationPtr animationptr)
Adds new animation with given angle (degrees)
Definition: visual.cpp:240
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:302
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:92
Object visual contains data that is needed for visualizing objects.
Definition: visual.h:91
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:356
static ObjectVisual * create(Object *object)
Constructs and assigns it to the passed item.
Definition: visual.cpp:101
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:113
void setStatic(bool stat)
Set to true, if object is such that it doesn't move.
Definition: object.cpp:233
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:590
Object * getObject(const std::string &id, const std::string &name_space)
Get an object by its id.
Definition: model.cpp:233
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:188
void setBlocking(bool blocking)
Sets if object blocks movement.
Definition: object.cpp:216
void setYShift(int32_t yshift)
Definition: image.h:124
ResourceHandle getHandle()
Definition: resource.h:68
void setSpeed(double cost)
Sets the speed modifier.
Definition: object.cpp:329
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:285
Used to access diffrent kinds of data.
Definition: rawdata.h:48