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 "util/log/logger.h"
00032 #include "model/model.h"
00033 #include "model/metamodel/object.h"
00034 #include "model/metamodel/action.h"
00035 #include "vfs/fife_boost_filesystem.h"
00036 #include "vfs/vfs.h"
00037 #include "vfs/raw/rawdata.h"
00038 #include "view/visual.h"
00039 #include "video/imagemanager.h"
00040
00041 #include "objectloader.h"
00042 #include "animationloader.h"
00043
00044 namespace FIFE {
00045 static Logger _log(LM_NATIVE_LOADERS);
00046
00047 ObjectLoader::ObjectLoader(Model* model, VFS* vfs, ImageManager* imageManager, const AnimationLoaderPtr& animationLoader)
00048 : m_model(model), m_vfs(vfs), m_imageManager(imageManager) {
00049 assert(m_model && m_vfs && m_imageManager);
00050
00051 if (animationLoader) {
00052 m_animationLoader = animationLoader;
00053 }
00054 else {
00055 m_animationLoader.reset(new AnimationLoader(m_vfs, m_imageManager));
00056 }
00057 }
00058
00059 ObjectLoader::~ObjectLoader() {
00060
00061 }
00062
00063 void ObjectLoader::setAnimationLoader(const AnimationLoaderPtr& animationLoader) {
00064 assert(animationLoader);
00065
00066 m_animationLoader = animationLoader;
00067 }
00068
00069 bool ObjectLoader::isLoadable(const std::string& filename) const {
00070 bfs::path objectPath(filename);
00071
00072 TiXmlDocument objectFile;
00073
00074 try {
00075 RawData* data = m_vfs->open(objectPath.string());
00076
00077 if (data) {
00078 if (data->getDataLength() != 0) {
00079 objectFile.Parse(data->readString(data->getDataLength()).c_str());
00080
00081 if (objectFile.Error()) {
00082 std::ostringstream oss;
00083 oss << " Failed to load"
00084 << objectPath.string()
00085 << " : " << __FILE__
00086 << " [" << __LINE__ << "]"
00087 << std::endl;
00088 FL_ERR(_log, oss.str());
00089
00090 return false;
00091 }
00092 }
00093 else {
00094 std::ostringstream oss;
00095 oss << " Failed to load"
00096 << objectPath.string()
00097 << " : " << __FILE__
00098 << " [" << __LINE__ << "]"
00099 << std::endl;
00100 FL_ERR(_log, oss.str());
00101
00102 return false;
00103 }
00104
00105
00106 delete data;
00107 data = 0;
00108 }
00109 else {
00110 std::ostringstream oss;
00111 oss << " Failed to load"
00112 << objectPath.string()
00113 << " : " << __FILE__
00114 << " [" << __LINE__ << "]"
00115 << std::endl;
00116 FL_ERR(_log, oss.str());
00117
00118 return false;
00119 }
00120 }
00121 catch (NotFound&) {
00122 std::ostringstream oss;
00123 oss << " Failed to load"
00124 << objectPath.string()
00125 << " : " << __FILE__
00126 << " [" << __LINE__ << "]"
00127 << std::endl;
00128 FL_ERR(_log, oss.str());
00129
00130
00131
00132
00133
00134 return false;
00135 }
00136
00137
00138 TiXmlElement* root = objectFile.RootElement();
00139
00140 if (root && root->ValueStr() == "object") {
00141 return true;
00142 }
00143 else {
00144 return false;
00145 }
00146 }
00147
00148 void ObjectLoader::load(const std::string& filename) {
00149 bfs::path objectPath(filename);
00150
00151 TiXmlDocument objectFile;
00152
00153 try {
00154 RawData* data = m_vfs->open(objectPath.string());
00155
00156 if (data) {
00157 if (data->getDataLength() != 0) {
00158 objectFile.Parse(data->readString(data->getDataLength()).c_str());
00159
00160 if (objectFile.Error()) {
00161 return;
00162 }
00163 }
00164
00165
00166 delete data;
00167 data = 0;
00168 }
00169 }
00170 catch (NotFound&) {
00171 std::ostringstream oss;
00172 oss << " Failed to load"
00173 << objectPath.string()
00174 << " : " << __FILE__
00175 << " [" << __LINE__ << "]"
00176 << std::endl;
00177 FL_ERR(_log, oss.str());
00178
00179
00180
00181
00182
00183 return;
00184 }
00185
00186
00187 TiXmlElement* root = objectFile.RootElement();
00188
00189 if (root && root->ValueStr() == "object") {
00190 const std::string* objectId = root->Attribute(std::string("id"));
00191 const std::string* namespaceId = root->Attribute(std::string("namespace"));
00192
00193 Object* obj = NULL;
00194 if (objectId && namespaceId) {
00195 const std::string* parentId = root->Attribute(std::string("parent"));
00196
00197 if (parentId) {
00198 Object* parent = m_model->getObject(*parentId, *namespaceId);
00199 if (parent) {
00200 try {
00201 obj = m_model->createObject(*objectId, *namespaceId, parent);
00202 }
00203 catch (NameClash&) {
00204
00205 assert(false);
00206 }
00207 }
00208 }
00209 else {
00210
00211 if (m_model->getObject(*objectId, *namespaceId) == NULL) {
00212 try {
00213 obj = m_model->createObject(*objectId, *namespaceId);
00214 }
00215 catch (NameClash &e) {
00216 FL_ERR(_log, e.what());
00217
00218
00219 assert(false);
00220 }
00221 }
00222 }
00223 }
00224
00225 if (obj) {
00226 obj->setFilename(objectPath.string());
00227 ObjectVisual::create(obj);
00228
00229 int isBlocking = 0;
00230 root->QueryIntAttribute("blocking", &isBlocking);
00231 obj->setBlocking(isBlocking!=0);
00232
00233 int isStatic = 0;
00234 root->QueryIntAttribute("static", &isStatic);
00235 obj->setStatic(isStatic!=0);
00236
00237 const std::string* pather = root->Attribute(std::string("pather"));
00238
00239 if (pather) {
00240 obj->setPather(m_model->getPather(*pather));
00241 }
00242 else {
00243 obj->setPather(m_model->getPather("RoutePather"));
00244 }
00245
00246
00247 for (TiXmlElement* imageElement = root->FirstChildElement("image"); imageElement; imageElement = imageElement->NextSiblingElement("image")) {
00248 const std::string* sourceId = imageElement->Attribute(std::string("source"));
00249
00250 if (sourceId) {
00251 bfs::path imagePath(filename);
00252
00253 if (HasParentPath(imagePath)) {
00254 imagePath = GetParentPath(imagePath) / *sourceId;
00255 } else {
00256 imagePath = bfs::path(*sourceId);
00257 }
00258
00259 ImagePtr imagePtr;
00260 if(!m_imageManager->exists(imagePath.string())) {
00261 imagePtr = m_imageManager->create(imagePath.string());
00262 }
00263 else {
00264 imagePtr = m_imageManager->getPtr(imagePath.string());
00265 }
00266
00267 if (imagePtr) {
00268 int xOffset = 0;
00269 int success = imageElement->QueryIntAttribute("x_offset", &xOffset);
00270
00271 if (success == TIXML_SUCCESS) {
00272 imagePtr->setXShift(xOffset);
00273 }
00274
00275 int yOffset = 0;
00276 success = imageElement->QueryIntAttribute("y_offset", &yOffset);
00277
00278 if (success == TIXML_SUCCESS) {
00279 imagePtr->setYShift(yOffset);
00280 }
00281
00282 int direction = 0;
00283 success = imageElement->QueryIntAttribute("direction", &direction);
00284
00285 if (success == TIXML_SUCCESS) {
00286 ObjectVisual* objVisual = obj->getVisual<ObjectVisual>();
00287
00288 if (objVisual) {
00289 objVisual->addStaticImage(direction, static_cast<int32_t>(imagePtr->getHandle()));
00290 }
00291 }
00292 }
00293 }
00294 }
00295
00296 for (TiXmlElement* actionElement = root->FirstChildElement("action"); actionElement; actionElement = actionElement->NextSiblingElement("action")) {
00297 const std::string* actionId = actionElement->Attribute(std::string("id"));
00298
00299 if (actionId) {
00300 Action* action = obj->createAction(*actionId);
00301 ActionVisual::create(action);
00302
00303 for (TiXmlElement* animElement = actionElement->FirstChildElement("animation"); animElement; animElement = animElement->NextSiblingElement("animation")) {
00304 const std::string* sourceId = animElement->Attribute(std::string("atlas"));
00305 if(sourceId) {
00306 bfs::path atlasPath(filename);
00307
00308 if (HasParentPath(atlasPath)) {
00309 atlasPath = GetParentPath(atlasPath) / *sourceId;
00310 } else {
00311 atlasPath = bfs::path(*sourceId);
00312 }
00313
00314 ImagePtr atlasImgPtr;
00315
00316 if(!m_imageManager->exists(atlasPath.string())) {
00317 atlasImgPtr = m_imageManager->create(atlasPath.string());
00318 }
00319 else {
00320 atlasImgPtr = m_imageManager->getPtr(atlasPath.string());
00321 }
00322
00323 int animFrames = 0;
00324 int animDelay = 0;
00325 int animXoffset = 0;
00326 int animYoffset = 0;
00327 int frameWidth = 0;
00328 int frameHeight = 0;
00329
00330 animElement->QueryValueAttribute("width", &frameWidth);
00331 animElement->QueryValueAttribute("height", &frameHeight);
00332 animElement->QueryValueAttribute("frames", &animFrames);
00333 animElement->QueryValueAttribute("delay", &animDelay);
00334 animElement->QueryValueAttribute("x_offset", &animXoffset);
00335 animElement->QueryValueAttribute("y_offset", &animYoffset);
00336 int nDir = 0;
00337
00338 for (TiXmlElement* dirElement = animElement->FirstChildElement("direction");
00339 dirElement; dirElement = dirElement->NextSiblingElement("direction")) {
00340 AnimationPtr animation(new Animation);
00341
00342 int dir;
00343 dirElement->QueryIntAttribute("dir", &dir);
00344
00345 int frames;
00346 int success;
00347
00348 success = dirElement->QueryValueAttribute("frames", &frames);
00349 if(success != TIXML_SUCCESS) {
00350 frames = animFrames;
00351 }
00352
00353 int delay;
00354 success = dirElement->QueryValueAttribute("delay", &delay);
00355 if(success != TIXML_SUCCESS) {
00356 delay = animDelay;
00357 }
00358
00359 int xoffset;
00360 success = dirElement->QueryValueAttribute("x_offset", &xoffset);
00361 if(success != TIXML_SUCCESS) {
00362 xoffset = animXoffset;
00363 }
00364
00365 int yoffset;
00366 success = dirElement->QueryValueAttribute("y_offset", &yoffset);
00367 if(success != TIXML_SUCCESS) {
00368 yoffset = animYoffset;
00369 }
00370
00371 int action_frame;
00372 success = dirElement->QueryValueAttribute("action", &action_frame);
00373 if(success == TIXML_SUCCESS) {
00374 animation->setActionFrame(action_frame);
00375 }
00376
00377 for (int iframe = 0; iframe < frames; ++iframe) {
00378 static char tmpBuf[64];
00379 sprintf(tmpBuf, "%03d:%04d", dir, iframe);
00380
00381 std::string frameId = *objectId + ":" + *actionId + ":" + std::string(tmpBuf);
00382
00383 ImagePtr framePtr;
00384 if (!m_imageManager->exists(frameId)) {
00385 framePtr = m_imageManager->create(frameId);
00386 Rect region(
00387 frameWidth * iframe, frameHeight * nDir, frameWidth, frameHeight
00388 );
00389 framePtr->useSharedImage(atlasImgPtr, region);
00390 framePtr->setXShift(xoffset);
00391 framePtr->setYShift(yoffset);
00392 }
00393 else {
00394 framePtr = m_imageManager->getPtr(frameId);
00395 }
00396 animation->addFrame(framePtr, delay);
00397 }
00398
00399 ActionVisual* actionVisual = action->getVisual<ActionVisual>();
00400 if(actionVisual) {
00401 actionVisual->addAnimation(dir, animation);
00402 action->setDuration(animation->getDuration());
00403 }
00404 ++nDir;
00405 }
00406
00407 } else {
00408 sourceId = animElement->Attribute(std::string("source"));
00409 if (sourceId) {
00410 bfs::path animPath(filename);
00411
00412 if (HasParentPath(animPath)) {
00413 animPath = GetParentPath(animPath) / *sourceId;
00414 } else {
00415 animPath = bfs::path(*sourceId);
00416 }
00417
00418 AnimationPtr animation;
00419 if (m_animationLoader && m_animationLoader->isLoadable(animPath.string())) {
00420 animation = m_animationLoader->load(animPath.string());
00421 }
00422
00423 int direction = 0;
00424 int success = animElement->QueryIntAttribute("direction", &direction);
00425
00426 if (action && animation) {
00427 ActionVisual* actionVisual = action->getVisual<ActionVisual>();
00428
00429 if (actionVisual) {
00430 actionVisual->addAnimation(direction, animation);
00431 action->setDuration(animation->getDuration());
00432 }
00433 }
00434 }
00435 }
00436 }
00437 }
00438 }
00439 }
00440 }
00441 }
00442
00443 }