00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "ext/tinyxml/fife_tinyxml.h"
00031 #include "model/model.h"
00032 #include "model/structures/layer.h"
00033 #include "vfs/fife_boost_filesystem.h"
00034 #include "vfs/vfs.h"
00035 #include "vfs/raw/rawdata.h"
00036 #include "util/base/exception.h"
00037 #include "util/log/logger.h"
00038 #include "util/resource/resource.h"
00039 #include "util/resource/resourcemanager.h"
00040 #include "view/visual.h"
00041
00042 #include "atlasloader.h"
00043
00044 namespace FIFE {
00045 static Logger _log(LM_NATIVE_LOADERS);
00046
00047
00048 size_t Atlas::getImageCount() const {
00049 return m_subimages.size();
00050 }
00051
00052 ImagePtr& Atlas::getPackedImage() {
00053 return m_image;
00054 }
00055
00056 ImagePtr Atlas::getImage(const std::string& id) {
00057 SubimageMap::iterator iter = m_subimages.find(id);
00058 if(iter == m_subimages.end())
00059 return ImagePtr();
00060 return iter->second.image;
00061 }
00062
00063 ImagePtr Atlas::getImage(uint32_t index) {
00064 if(index > getImageCount())
00065 return ImagePtr();
00066
00067 SubimageMap::iterator iter = m_subimages.begin();
00068 for(uint32_t i = 0; i < index; ++i, ++iter);
00069 return iter->second.image;
00070 }
00071
00072 bool Atlas::addImage(const std::string& imagename, const AtlasData& data) {
00073 return m_subimages.insert(std::pair<std::string, AtlasData>(imagename, data)).second;
00074 }
00075
00076 void Atlas::setPackedImage(const ImagePtr& image) {
00077 m_image = image;
00078 }
00079
00080 const std::string& Atlas::getName() const {
00081 return m_name;
00082 }
00083
00084 AtlasLoader::AtlasLoader(Model* model, VFS* vfs, ImageManager* imageManager)
00085 : m_model(model), m_vfs(vfs), m_imageManager(imageManager) {
00086 }
00087
00088 AtlasLoader::~AtlasLoader() {
00089 }
00090
00091 bool AtlasLoader::isLoadable(const std::string& filename) {
00092 bfs::path atlasPath(filename);
00093 std::string atlasFilename = atlasPath.string();
00094 TiXmlDocument atlasFile;
00095
00096 try {
00097 RawData* data = m_vfs->open(atlasFilename);
00098
00099 if (data) {
00100 if (data->getDataLength() != 0) {
00101 atlasFile.Parse(data->readString(data->getDataLength()).c_str());
00102
00103 if (atlasFile.Error()) {
00104 return false;
00105 }
00106 } else {
00107 return false;
00108 }
00109
00110
00111 delete data;
00112 data = 0;
00113 }
00114 } catch (NotFound&) {
00115 return false;
00116 }
00117
00118
00119 TiXmlElement* root = atlasFile.RootElement();
00120
00121 if (root && root->ValueStr() == "atlas") {
00122 return true;
00123 }
00124 else {
00125 return false;
00126 }
00127 }
00128
00129 AtlasPtr AtlasLoader::load(const std::string& filename) {
00130 bfs::path atlasPath(filename);
00131 bfs::path atlasPathDirectory;
00132 m_atlasFilename = atlasPath.string();
00133
00134 if (HasParentPath(atlasPath)) {
00135
00136 atlasPathDirectory = GetParentPath(atlasPath);
00137 }
00138
00139 TiXmlDocument doc;
00140 AtlasPtr atlas;
00141
00142 try {
00143 RawData* data = m_vfs->open(m_atlasFilename);
00144
00145 if (data) {
00146 if (data->getDataLength() != 0) {
00147 doc.Parse(data->readString(data->getDataLength()).c_str());
00148
00149 if (doc.Error()) {
00150 return atlas;
00151 }
00152
00153
00154 delete data;
00155 data = 0;
00156 }
00157 }
00158 }
00159 catch (NotFound& e) {
00160 FL_ERR(_log, e.what());
00161
00162
00163
00164
00165
00166 return atlas;
00167 }
00168
00169
00170
00171 TiXmlElement* root = doc.RootElement();
00172
00173 if (root && root->ValueStr() == "atlas") {
00174 const std::string* atlasName = root->Attribute(std::string("name"));
00175 if(atlasName) {
00176 const std::string* namespaceId = root->Attribute(std::string("namespace"));
00177 if(!namespaceId) {
00178 namespaceId = atlasName;
00179 }
00180
00181
00182 bfs::path atlasImagePath = atlasPathDirectory / *atlasName;
00183 atlas.reset(new Atlas(atlasImagePath.string()));
00184
00185
00186
00187
00188
00189 bool atlasExists = m_imageManager->exists(atlas->getName());
00190
00191 if(!atlasExists) {
00192 atlas->setPackedImage(m_imageManager->create(atlas->getName()));
00193 }
00194 else {
00195 atlas->setPackedImage(m_imageManager->getPtr(atlas->getName()));
00196 }
00197
00198
00199
00200
00201
00202 bool subsExists = true;
00203 for (TiXmlElement* imageElem = root->FirstChildElement("image");
00204 imageElem != 0; imageElem = imageElem->NextSiblingElement("image")) {
00205
00206 Rect region;
00207 imageElem->QueryValueAttribute("xpos", ®ion.x);
00208 imageElem->QueryValueAttribute("ypos", ®ion.y);
00209 imageElem->QueryValueAttribute("width", ®ion.w);
00210 imageElem->QueryValueAttribute("height", ®ion.h);
00211
00212 const std::string* subimageName = imageElem->Attribute(std::string("source"));
00213
00214 if (subimageName) {
00215 std::string finalname = *namespaceId + ":" +*subimageName;
00216 ImagePtr subImage;
00217
00218 bool subExists = m_imageManager->exists(finalname);
00219 if (!subExists) {
00220 subsExists = false;
00221 subImage = m_imageManager->create(finalname);
00222 }
00223 else {
00224 subImage = m_imageManager->getPtr(finalname);
00225 }
00226 subImage->useSharedImage(atlas->getPackedImage(), region);
00227
00228 AtlasData atlas_data = {region, subImage};
00229 atlas->addImage(finalname, atlas_data);
00230 }
00231 }
00232 subsExists = subsExists && atlasExists;
00233
00234
00235 for(TiXmlElement* objElem = root->NextSiblingElement("object");
00236 objElem != 0; objElem = objElem->NextSiblingElement("object"))
00237 {
00238
00239 if(objElem->ValueStr() == "object") {
00240 parseObject(atlas.get(), objElem, subsExists);
00241 }
00242 }
00243 }
00244 }
00245
00246 return atlas;
00247 }
00248
00249 void AtlasLoader::parseObject(Atlas* atlas, TiXmlElement* root, bool exists) {
00250 const std::string* objectId = root->Attribute(std::string("id"));
00251 const std::string* namespaceId = root->Attribute(std::string("namespace"));
00252
00253 Object* obj = NULL;
00254 if (objectId && namespaceId) {
00255 const std::string* parentId = root->Attribute(std::string("parent"));
00256
00257 if (parentId) {
00258 Object* parent = m_model->getObject(*parentId, *namespaceId);
00259 if (parent) {
00260 try {
00261 obj = m_model->createObject(*objectId, *namespaceId, parent);
00262 }
00263 catch (NameClash&) {
00264
00265 assert(false);
00266 }
00267 }
00268 }
00269 else {
00270
00271 if (m_model->getObject(*objectId, *namespaceId) == NULL) {
00272 try {
00273 obj = m_model->createObject(*objectId, *namespaceId);
00274 }
00275 catch (NameClash&) {
00276
00277 assert(false);
00278 }
00279
00280 } else if (!exists) {
00281 obj = m_model->getObject(*objectId, *namespaceId);
00282 ObjectVisual* objVisual = obj->getVisual<ObjectVisual>();
00283
00284 if (!objVisual) {
00285 objVisual = ObjectVisual::create(obj);
00286 }
00287
00288 for (TiXmlElement* imageElement = root->FirstChildElement("image"); imageElement; imageElement = imageElement->NextSiblingElement("image")) {
00289 const std::string* sourceId = imageElement->Attribute(std::string("source"));
00290
00291 if (sourceId) {
00292 std::string source = *namespaceId + ":" + *sourceId;
00293 if(!m_imageManager->exists(source)) {
00294 throw NotFound(source + " couldn't be found.");
00295 }
00296 ImagePtr imagePtr = m_imageManager->getPtr(source);
00297
00298 int xOffset = 0;
00299 int success = imageElement->QueryIntAttribute("x_offset", &xOffset);
00300 if (success == TIXML_SUCCESS) {
00301 imagePtr->setXShift(xOffset);
00302 }
00303
00304 int yOffset = 0;
00305 success = imageElement->QueryIntAttribute("y_offset", &yOffset);
00306 if (success == TIXML_SUCCESS) {
00307 imagePtr->setYShift(yOffset);
00308 }
00309
00310 int direction = 0;
00311 success = imageElement->QueryIntAttribute("direction", &direction);
00312 if (success == TIXML_SUCCESS) {
00313 if (objVisual) {
00314 objVisual->addStaticImage(direction, static_cast<int32_t>(imagePtr->getHandle()));
00315 }
00316 }
00317 }
00318 }
00319 return;
00320 }
00321 }
00322 }
00323
00324 if (obj) {
00325
00326 obj->setFilename(m_atlasFilename);
00327 ObjectVisual::create(obj);
00328
00329 int isBlocking = 0;
00330 root->QueryIntAttribute("blocking", &isBlocking);
00331 obj->setBlocking(isBlocking!=0);
00332
00333 int isStatic = 0;
00334 root->QueryIntAttribute("static", &isStatic);
00335 obj->setStatic(isStatic!=0);
00336
00337 const std::string* pather = root->Attribute(std::string("pather"));
00338
00339 if (pather) {
00340 obj->setPather(m_model->getPather(*pather));
00341 }
00342 else {
00343 obj->setPather(m_model->getPather("RoutePather"));
00344 }
00345
00346
00347 for (TiXmlElement* imageElement = root->FirstChildElement("image"); imageElement; imageElement = imageElement->NextSiblingElement("image")) {
00348 const std::string* sourceId = imageElement->Attribute(std::string("source"));
00349
00350 if (sourceId) {
00351 std::string source = *namespaceId + ":" + *sourceId;
00352 if(!m_imageManager->exists(source)) {
00353 throw NotFound(source + " couldn't be found.");
00354 }
00355 ImagePtr imagePtr = m_imageManager->getPtr(source);
00356 int xOffset = 0;
00357 int success = imageElement->QueryIntAttribute("x_offset", &xOffset);
00358
00359 if (success == TIXML_SUCCESS) {
00360 imagePtr->setXShift(xOffset);
00361 }
00362
00363 int yOffset = 0;
00364 success = imageElement->QueryIntAttribute("y_offset", &yOffset);
00365
00366 if (success == TIXML_SUCCESS) {
00367 imagePtr->setYShift(yOffset);
00368 }
00369
00370 int direction = 0;
00371 success = imageElement->QueryIntAttribute("direction", &direction);
00372
00373 if (success == TIXML_SUCCESS) {
00374 ObjectVisual* objVisual = obj->getVisual<ObjectVisual>();
00375
00376 if (objVisual) {
00377 objVisual->addStaticImage(direction, static_cast<int32_t>(imagePtr->getHandle()));
00378 }
00379 }
00380 }
00381 }
00382 }
00383 }
00384
00385 AtlasLoader* createDefaultAtlasLoader(Model* model, VFS* vfs, ImageManager* imageManager) {
00386 return new AtlasLoader(model, vfs, imageManager);
00387 }
00388 }