PageRenderTime 53ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/fife_0.3.3r3/engine/core/loaders/native/map/atlasloader.cpp

#
C++ | 388 lines | 268 code | 68 blank | 52 comment | 68 complexity | 787bfb873840060e1976169e6916916c MD5 | raw file
Possible License(s): LGPL-2.0
  1. /***************************************************************************
  2. * Copyright (C) 2005-2011 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. // Standard C++ library includes
  22. // 3rd party library includes
  23. // FIFE includes
  24. // These includes are split up in two parts, separated by one empty line
  25. // First block: files included from the FIFE root src directory
  26. // Second block: files included from the same folder
  27. #include "ext/tinyxml/fife_tinyxml.h"
  28. #include "model/model.h"
  29. #include "model/structures/layer.h"
  30. #include "vfs/fife_boost_filesystem.h"
  31. #include "vfs/vfs.h"
  32. #include "vfs/raw/rawdata.h"
  33. #include "util/base/exception.h"
  34. #include "util/log/logger.h"
  35. #include "util/resource/resource.h"
  36. #include "util/resource/resourcemanager.h"
  37. #include "view/visual.h"
  38. #include "atlasloader.h"
  39. namespace FIFE {
  40. static Logger _log(LM_NATIVE_LOADERS);
  41. size_t Atlas::getImageCount() const {
  42. return m_subimages.size();
  43. }
  44. ImagePtr& Atlas::getPackedImage() {
  45. return m_image;
  46. }
  47. ImagePtr Atlas::getImage(const std::string& id) {
  48. SubimageMap::iterator iter = m_subimages.find(id);
  49. if(iter == m_subimages.end())
  50. return ImagePtr();
  51. return iter->second.image;
  52. }
  53. ImagePtr Atlas::getImage(uint32_t index) {
  54. if(index > getImageCount())
  55. return ImagePtr();
  56. SubimageMap::iterator iter = m_subimages.begin();
  57. for(uint32_t i = 0; i < index; ++i, ++iter);
  58. return iter->second.image;
  59. }
  60. bool Atlas::addImage(const std::string& imagename, const AtlasData& data) {
  61. return m_subimages.insert(std::pair<std::string, AtlasData>(imagename, data)).second;
  62. }
  63. void Atlas::setPackedImage(const ImagePtr& image) {
  64. m_image = image;
  65. }
  66. const std::string& Atlas::getName() const {
  67. return m_name;
  68. }
  69. AtlasLoader::AtlasLoader(Model* model, VFS* vfs, ImageManager* imageManager)
  70. : m_model(model), m_vfs(vfs), m_imageManager(imageManager) {
  71. }
  72. AtlasLoader::~AtlasLoader() {
  73. }
  74. bool AtlasLoader::isLoadable(const std::string& filename) {
  75. bfs::path atlasPath(filename);
  76. std::string atlasFilename = atlasPath.string();
  77. TiXmlDocument atlasFile;
  78. try {
  79. RawData* data = m_vfs->open(atlasFilename);
  80. if (data) {
  81. if (data->getDataLength() != 0) {
  82. atlasFile.Parse(data->readString(data->getDataLength()).c_str());
  83. if (atlasFile.Error()) {
  84. return false;
  85. }
  86. } else {
  87. return false;
  88. }
  89. // done with data delete resource
  90. delete data;
  91. data = 0;
  92. }
  93. } catch (NotFound&) {
  94. return false;
  95. }
  96. // if we get here then loading the file went well
  97. TiXmlElement* root = atlasFile.RootElement();
  98. if (root && root->ValueStr() == "atlas") {
  99. return true;
  100. }
  101. else {
  102. return false;
  103. }
  104. }
  105. AtlasPtr AtlasLoader::load(const std::string& filename) {
  106. bfs::path atlasPath(filename);
  107. bfs::path atlasPathDirectory;
  108. m_atlasFilename = atlasPath.string();
  109. if (HasParentPath(atlasPath)) {
  110. // save the directory where the atlas file is located
  111. atlasPathDirectory = GetParentPath(atlasPath);
  112. }
  113. TiXmlDocument doc;
  114. AtlasPtr atlas;
  115. try {
  116. RawData* data = m_vfs->open(m_atlasFilename);
  117. if (data) {
  118. if (data->getDataLength() != 0) {
  119. doc.Parse(data->readString(data->getDataLength()).c_str());
  120. if (doc.Error()) {
  121. return atlas;
  122. }
  123. // done with data delete resource
  124. delete data;
  125. data = 0;
  126. }
  127. }
  128. }
  129. catch (NotFound& e) {
  130. FL_ERR(_log, e.what());
  131. // TODO - should we abort here
  132. // or rethrow the exception
  133. // or just keep going
  134. return atlas;
  135. }
  136. // if we get here then everything loaded properly
  137. // so we can just parse out the contents
  138. TiXmlElement* root = doc.RootElement();
  139. if (root && root->ValueStr() == "atlas") {
  140. const std::string* atlasName = root->Attribute(std::string("name"));
  141. if(atlasName) {
  142. const std::string* namespaceId = root->Attribute(std::string("namespace"));
  143. if(!namespaceId) {
  144. namespaceId = atlasName;
  145. }
  146. // Atlas itself doesn't have appended namespace
  147. bfs::path atlasImagePath = atlasPathDirectory / *atlasName;
  148. atlas.reset(new Atlas(atlasImagePath.string()));
  149. // End-user could create the same atlas for the second time.
  150. // Since we don't hold any data for Atlases like ImageManager we need to recreate
  151. // atlas parameters (to return proper AtlasPtr) but don't reload pixel data (they are held by ImageManager).
  152. bool atlasExists = m_imageManager->exists(atlas->getName());
  153. if(!atlasExists) {
  154. atlas->setPackedImage(m_imageManager->create(atlas->getName()));
  155. }
  156. else {
  157. atlas->setPackedImage(m_imageManager->getPtr(atlas->getName()));
  158. }
  159. // We don't really need this now, though we could use it to assert if the loaded atlas is the same sized as these
  160. //int atlasWidth, atlasHeight;
  161. //root->QueryValueAttribute("width", &atlasWidth);
  162. //root->QueryValueAttribute("height", &atlasHeight);
  163. bool subsExists = true;
  164. for (TiXmlElement* imageElem = root->FirstChildElement("image");
  165. imageElem != 0; imageElem = imageElem->NextSiblingElement("image")) {
  166. Rect region;
  167. imageElem->QueryValueAttribute("xpos", &region.x);
  168. imageElem->QueryValueAttribute("ypos", &region.y);
  169. imageElem->QueryValueAttribute("width", &region.w);
  170. imageElem->QueryValueAttribute("height", &region.h);
  171. const std::string* subimageName = imageElem->Attribute(std::string("source"));
  172. if (subimageName) {
  173. std::string finalname = *namespaceId + ":" +*subimageName;
  174. ImagePtr subImage;
  175. bool subExists = m_imageManager->exists(finalname);
  176. if (!subExists) {
  177. subsExists = false;
  178. subImage = m_imageManager->create(finalname);
  179. }
  180. else {
  181. subImage = m_imageManager->getPtr(finalname);
  182. }
  183. subImage->useSharedImage(atlas->getPackedImage(), region);
  184. AtlasData atlas_data = {region, subImage};
  185. atlas->addImage(finalname, atlas_data);
  186. }
  187. }
  188. subsExists = subsExists && atlasExists;
  189. // Now parse object definition
  190. for(TiXmlElement* objElem = root->NextSiblingElement("object");
  191. objElem != 0; objElem = objElem->NextSiblingElement("object"))
  192. {
  193. // sanity check
  194. if(objElem->ValueStr() == "object") {
  195. parseObject(atlas.get(), objElem, subsExists);
  196. }
  197. }
  198. }
  199. }
  200. return atlas;
  201. }
  202. void AtlasLoader::parseObject(Atlas* atlas, TiXmlElement* root, bool exists) {
  203. const std::string* objectId = root->Attribute(std::string("id"));
  204. const std::string* namespaceId = root->Attribute(std::string("namespace"));
  205. Object* obj = NULL;
  206. if (objectId && namespaceId) {
  207. const std::string* parentId = root->Attribute(std::string("parent"));
  208. if (parentId) {
  209. Object* parent = m_model->getObject(*parentId, *namespaceId);
  210. if (parent) {
  211. try {
  212. obj = m_model->createObject(*objectId, *namespaceId, parent);
  213. }
  214. catch (NameClash&) {
  215. // TODO - handle exception
  216. assert(false);
  217. }
  218. }
  219. }
  220. else {
  221. // this will make sure the object has not already been loaded
  222. if (m_model->getObject(*objectId, *namespaceId) == NULL) {
  223. try {
  224. obj = m_model->createObject(*objectId, *namespaceId);
  225. }
  226. catch (NameClash&) {
  227. // TODO - handle exception
  228. assert(false);
  229. }
  230. // if atlas or subimage was recreated then we have to update the ObjectVisual
  231. } else if (!exists) {
  232. obj = m_model->getObject(*objectId, *namespaceId);
  233. ObjectVisual* objVisual = obj->getVisual<ObjectVisual>();
  234. // make sure obj have visual
  235. if (!objVisual) {
  236. objVisual = ObjectVisual::create(obj);
  237. }
  238. for (TiXmlElement* imageElement = root->FirstChildElement("image"); imageElement; imageElement = imageElement->NextSiblingElement("image")) {
  239. const std::string* sourceId = imageElement->Attribute(std::string("source"));
  240. if (sourceId) {
  241. std::string source = *namespaceId + ":" + *sourceId;
  242. if(!m_imageManager->exists(source)) {
  243. throw NotFound(source + " couldn't be found.");
  244. }
  245. ImagePtr imagePtr = m_imageManager->getPtr(source);
  246. int xOffset = 0;
  247. int success = imageElement->QueryIntAttribute("x_offset", &xOffset);
  248. if (success == TIXML_SUCCESS) {
  249. imagePtr->setXShift(xOffset);
  250. }
  251. int yOffset = 0;
  252. success = imageElement->QueryIntAttribute("y_offset", &yOffset);
  253. if (success == TIXML_SUCCESS) {
  254. imagePtr->setYShift(yOffset);
  255. }
  256. int direction = 0;
  257. success = imageElement->QueryIntAttribute("direction", &direction);
  258. if (success == TIXML_SUCCESS) {
  259. if (objVisual) {
  260. objVisual->addStaticImage(direction, static_cast<int32_t>(imagePtr->getHandle()));
  261. }
  262. }
  263. }
  264. }
  265. return;
  266. }
  267. }
  268. }
  269. if (obj) {
  270. //obj->setFilename(atlas->getName());
  271. obj->setFilename(m_atlasFilename);
  272. ObjectVisual::create(obj);
  273. int isBlocking = 0;
  274. root->QueryIntAttribute("blocking", &isBlocking);
  275. obj->setBlocking(isBlocking!=0);
  276. int isStatic = 0;
  277. root->QueryIntAttribute("static", &isStatic);
  278. obj->setStatic(isStatic!=0);
  279. const std::string* pather = root->Attribute(std::string("pather"));
  280. if (pather) {
  281. obj->setPather(m_model->getPather(*pather));
  282. }
  283. else {
  284. obj->setPather(m_model->getPather("RoutePather"));
  285. }
  286. // loop over all image tags
  287. for (TiXmlElement* imageElement = root->FirstChildElement("image"); imageElement; imageElement = imageElement->NextSiblingElement("image")) {
  288. const std::string* sourceId = imageElement->Attribute(std::string("source"));
  289. if (sourceId) {
  290. std::string source = *namespaceId + ":" + *sourceId;
  291. if(!m_imageManager->exists(source)) {
  292. throw NotFound(source + " couldn't be found.");
  293. }
  294. ImagePtr imagePtr = m_imageManager->getPtr(source);
  295. int xOffset = 0;
  296. int success = imageElement->QueryIntAttribute("x_offset", &xOffset);
  297. if (success == TIXML_SUCCESS) {
  298. imagePtr->setXShift(xOffset);
  299. }
  300. int yOffset = 0;
  301. success = imageElement->QueryIntAttribute("y_offset", &yOffset);
  302. if (success == TIXML_SUCCESS) {
  303. imagePtr->setYShift(yOffset);
  304. }
  305. int direction = 0;
  306. success = imageElement->QueryIntAttribute("direction", &direction);
  307. if (success == TIXML_SUCCESS) {
  308. ObjectVisual* objVisual = obj->getVisual<ObjectVisual>();
  309. if (objVisual) {
  310. objVisual->addStaticImage(direction, static_cast<int32_t>(imagePtr->getHandle()));
  311. }
  312. }
  313. }
  314. }
  315. }
  316. }
  317. AtlasLoader* createDefaultAtlasLoader(Model* model, VFS* vfs, ImageManager* imageManager) {
  318. return new AtlasLoader(model, vfs, imageManager);
  319. }
  320. }