animationloader.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2005-2011 by the FIFE team                              *
00003  *   http://www.fifengine.net                                              *
00004  *   This file is part of FIFE.                                            *
00005  *                                                                         *
00006  *   FIFE is free software; you can redistribute it and/or                 *
00007  *   modify it under the terms of the GNU Lesser General Public            *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2.1 of the License, or (at your option) any later version.    *
00010  *                                                                         *
00011  *   This library is distributed in the hope that it will be useful,       *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00014  *   Lesser General Public License for more details.                       *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Lesser General Public      *
00017  *   License along with this library; if not, write to the                 *
00018  *   Free Software Foundation, Inc.,                                       *
00019  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
00020  ***************************************************************************/
00021 
00022 // Standard C++ library includes
00023 
00024 // 3rd party library includes
00025 
00026 // FIFE includes
00027 // These includes are split up in two parts, separated by one empty line
00028 // First block: files included from the FIFE root src directory
00029 // Second block: files included from the same folder
00030 #include "ext/tinyxml/fife_tinyxml.h"
00031 #include "vfs/fife_boost_filesystem.h"
00032 #include "vfs/vfs.h"
00033 #include "vfs/raw/rawdata.h"
00034 #include "video/imagemanager.h"
00035 #include "video/image.h"
00036 #include "video/animation.h"
00037 #include "util/base/exception.h"
00038 #include "util/log/logger.h"
00039 #include "util/resource/resource.h"
00040 #include "util/resource/resourcemanager.h"
00041 
00042 #include "animationloader.h"
00043 
00044 namespace FIFE {
00045     static Logger _log(LM_NATIVE_LOADERS);
00046 
00047     AnimationLoader::AnimationLoader(VFS* vfs, ImageManager* imageManager)
00048     : m_vfs(vfs), m_imageManager(imageManager) {
00049 
00050     }
00051 
00052     bool AnimationLoader::isLoadable(const std::string& filename) {
00053         bfs::path animPath(filename);
00054 
00055         std::string animationFilename = animPath.string();
00056 
00057         try {
00058             RawData* data = m_vfs->open(animationFilename);
00059 
00060             if (data) {
00061                 if (data->getDataLength() != 0) {
00062                     // TODO - this could be expanded to do more checks
00063                     TiXmlDocument doc;
00064                     doc.Parse(data->readString(data->getDataLength()).c_str());
00065 
00066                     if (doc.Error()) {
00067                         return false;
00068                     }
00069                 }
00070 
00071                 // done with data delete resource
00072                 delete data;
00073                 data = 0;
00074             }
00075         }
00076         catch (NotFound&) {
00077             return false;
00078         }
00079 
00080         return true;
00081     }
00082 
00083     AnimationPtr AnimationLoader::load(const std::string& filename) {
00084         bfs::path animPath(filename);
00085 
00086         std::string animationFilename = animPath.string();
00087 
00088         TiXmlDocument doc;
00089 
00090         AnimationPtr animation;
00091 
00092         try {
00093             RawData* data = m_vfs->open(animationFilename);
00094 
00095             if (data) {
00096                 if (data->getDataLength() != 0) {
00097                     doc.Parse(data->readString(data->getDataLength()).c_str());
00098 
00099                     if (doc.Error()) {
00100                         return animation;
00101                     }
00102 
00103                     // done with data delete resource
00104                     delete data;
00105                     data = 0;
00106                 }
00107             }
00108         }
00109         catch (NotFound& e) {
00110             FL_ERR(_log, e.what());
00111 
00112             // TODO - should we abort here
00113             //        or rethrow the exception
00114             //        or just keep going
00115 
00116             return animation;
00117         }
00118 
00119         // if we get here then everything loaded properly
00120         // so we can just parse out the contents
00121         TiXmlElement* root = doc.RootElement();
00122 
00123         if (root) {
00124             animation.reset(new Animation());
00125 
00126             int animDelay = 0;
00127             root->QueryValueAttribute("delay", &animDelay);
00128 
00129             int animXoffset = 0;
00130             int animYoffset = 0;
00131             int action = -1;
00132             root->QueryValueAttribute("x_offset", &animXoffset);
00133             root->QueryValueAttribute("y_offset", &animYoffset);
00134             root->QueryValueAttribute("action", &action);
00135 
00136             for (TiXmlElement* frameElement = root->FirstChildElement("frame"); frameElement; frameElement = frameElement->NextSiblingElement("frame")) {
00137                 if (animation) {
00138                     animation->setActionFrame(action);
00139 
00140                     const std::string* sourceId = frameElement->Attribute(std::string("source"));
00141 
00142                     if (sourceId) {
00143                         bfs::path framePath(filename);
00144 
00145                         if (HasParentPath(framePath)) {
00146                             framePath = GetParentPath(framePath) / *sourceId;
00147                         } else {
00148                             framePath = bfs::path(*sourceId);
00149                         }
00150 
00151                         ImagePtr imagePtr;
00152                         if(!m_imageManager->exists(framePath.string())) {
00153                             imagePtr = m_imageManager->create(framePath.string());
00154                         }
00155                         else {
00156                             imagePtr = m_imageManager->getPtr(framePath.string());
00157                         }
00158 
00159                         if (imagePtr) {
00160                             int frameXoffset = 0;
00161                             int frameYoffset = 0;
00162 
00163                             int success = root->QueryValueAttribute("x_offset", &frameXoffset);
00164 
00165                             if (success == TIXML_SUCCESS) {
00166                                 imagePtr->setXShift(frameXoffset);
00167                             }
00168                             else {
00169                                 imagePtr->setXShift(animXoffset);
00170                             }
00171 
00172                             success = root->QueryValueAttribute("y_offset", &frameYoffset);
00173 
00174                             if (success == TIXML_SUCCESS) {
00175                                 imagePtr->setYShift(frameYoffset);
00176                             }
00177                             else {
00178                                 imagePtr->setYShift(animYoffset);
00179                             }
00180 
00181                             int frameDelay = 0;
00182                             success = root->QueryValueAttribute("delay", &frameDelay);
00183 
00184                             if (success == TIXML_SUCCESS) {
00185                                 animation->addFrame(imagePtr, frameDelay);
00186                             }
00187                             else {
00188                                 animation->addFrame(imagePtr, animDelay);
00189                             }
00190                         }
00191                     }
00192                 }
00193             }
00194         }
00195 
00196         return animation;
00197     }
00198 }