src/tool/resource_manager.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002  *  Wormux is a convivial mass murder game.
00003  *  Copyright (C) 2001-2004 Lawrence Azzoug.
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
00018  ******************************************************************************
00019  * Resource Manager: Load resources (images/sprites) suitable for SDL
00020  *                    Load directly or from refernece in xml resource profile
00021  ******************************************************************************
00022  * 2005/09/21: Jean-Christophe Duberga (jcduberga@gmx.de) 
00023  *             Initial version
00024  * 
00025  * TODO:       Keep reference to resources, better exceptions
00026  *****************************************************************************/
00027 
00028 #include "resource_manager.h"
00029 #include <string>
00030 #include <iostream>
00031 #include "error.h"
00032 #include "xml_document.h"
00033 #include "string_tools.h"
00034 #include "../game/config.h"
00035 #include "../graphic/sprite.h"
00036 
00037 Profile::Profile()
00038 {
00039    doc = NULL;
00040 }
00041 
00042 Profile::~Profile()
00043 {
00044   if (doc != NULL) delete doc;
00045 }
00046 
00047 ResourceManager::ResourceManager()
00048 {
00049 }
00050 
00051 ResourceManager::~ResourceManager()
00052 {
00053 }
00054 
00055 void ResourceManager::AddDataPath( std::string base_path)
00056 {
00057   this->base_path = base_path;
00058 }
00059 
00060 Color ResourceManager::LoadColor(const Profile *profile, const std::string resource_name)
00061 {
00062   xmlpp::Element *elem = GetElement(profile, "color", resource_name);
00063   if ( elem == NULL)
00064     Error("ResourceManager: can't find color resource \""+resource_name+"\" in profile "+profile->filename);
00065 
00066   uint chanel_color[4];
00067   char * tmp[4] = { "r", "g", "b", "a" };
00068   for(int i = 0; i < 4; i++) {
00069     if (!profile->doc->ReadUintAttr( elem, tmp[i], chanel_color[i]))
00070       Error("ResourceManager: color resource \""+resource_name+"\" has no "+tmp[i]+" field in profile "+profile->filename);
00071   }
00072   return Color(chanel_color[0], chanel_color[1], chanel_color[2], chanel_color[3]);
00073 }
00074 
00075 Surface ResourceManager::LoadImage( const std::string filename, 
00076         bool alpha, bool set_colorkey, Uint32 colorkey)
00077 {
00078   Surface pre_surface = Surface( filename.c_str() );
00079   Surface end_surface;
00080 
00081   if(set_colorkey)
00082     end_surface.SetColorKey( SDL_SRCCOLORKEY, colorkey);
00083 
00084   if( !alpha )
00085     end_surface = pre_surface.DisplayFormat();
00086   else
00087     end_surface = pre_surface.DisplayFormatAlpha();
00088 
00089   return end_surface;
00090 }
00091 
00092 Profile *ResourceManager::LoadXMLProfile( const std::string xml_filename, bool relative_path)
00093 {
00094    XmlReader *doc = new XmlReader;
00095    std::string filename, path;
00096    if (!relative_path) {
00097        path = base_path;
00098        filename = path + xml_filename;
00099    } else {
00100        assert ( xml_filename.rfind(PATH_SEPARATOR) != xml_filename.npos );
00101        path = xml_filename.substr(0, xml_filename.rfind(PATH_SEPARATOR)+1);
00102        filename = xml_filename;
00103    }
00104 
00105    // Load the XML
00106    if(!doc->Load(filename))
00107    {
00108      // TODO raise an "can't load file" exception
00109      Error("ResourceManager: can't load profile "+filename);
00110      return NULL;
00111    }
00112 
00113    Profile *profile = new Profile; 
00114    profile->doc = doc;
00115    profile->filename = xml_filename;
00116    profile->relative_path = path;
00117    return profile;
00118 }
00119 
00120 void ResourceManager::UnLoadXMLProfile( Profile *profile)
00121 {
00122    delete profile;
00123 }
00124 
00125 xmlpp::Element * ResourceManager::GetElement( const Profile *profile, const std::string resource_type, const std::string resource_name)
00126 {
00127   xmlpp::Element *elem = profile->doc->Access(profile->doc->GetRoot(), resource_type, resource_name);
00128 
00129  if(elem == NULL)
00130  {
00131    std::string r_name = resource_name;
00132    xmlpp::Element *cur_elem = profile->doc->GetRoot();
00133 
00134    while ((r_name.find("/") != r_name.npos) && (cur_elem != NULL))
00135    {
00136      cur_elem = profile->doc->Access(cur_elem, "section", r_name.substr(0, r_name.find("/")));
00137      r_name = r_name.substr( r_name.find("/") + 1, r_name.length());
00138    }
00139    if(cur_elem)
00140      elem = profile->doc->Access(cur_elem, resource_type, r_name);
00141   }
00142   return elem;
00143 }
00144 
00145 Surface ResourceManager::LoadImage( const Profile *profile, const std::string resource_name)
00146 {
00147   xmlpp::Element *elem = GetElement ( profile, "surface", resource_name);
00148   if(elem == NULL)
00149     Error("ResourceManager: can't find image resource \""+resource_name+"\" in profile "+profile->filename);
00150 
00151   std::string filename; 
00152   if (!profile->doc->ReadStringAttr(elem, "file", filename))
00153     Error("ResourceManager: image resource \""+resource_name+"\" has no file field in profile "+profile->filename);
00154 
00155   // TODO load more properties in xml : alpha, colorkey....
00156   //      By now force alpha and no colorkey
00157 
00158   bool alpha = true;
00159 
00160   return LoadImage(profile->relative_path+filename, alpha);
00161 }
00162 
00163 Sprite *ResourceManager::LoadSprite( const Profile *profile, const std::string resource_name)
00164 {
00165   xmlpp::Element *elem_sprite = GetElement(profile, "sprite", resource_name);
00166   if(elem_sprite == NULL)
00167     Error("ResourceManager: can't find sprite resource \""+resource_name+"\" in profile "+profile->filename);;
00168 
00169   xmlpp::Element *elem_image = profile->doc->GetMarker(elem_sprite, "image");
00170 
00171   if(elem_image == NULL)
00172     Error("ResourceManager: can't load (sprite) resource " + resource_name);
00173 
00174   std::string image_filename; 
00175   if (!profile->doc->ReadStringAttr(elem_image, "file", image_filename) )
00176     Error("ResourceManager: can't load (sprite) resource " + resource_name);
00177 
00178   // TODO load more properties in xml : alpha, colorkey....
00179   //      By now force alpha and no colorkey
00180 
00181   bool alpha = true;
00182   Sprite *sprite = NULL;
00183 
00184   xmlpp::Element *elem_grid = profile->doc->GetMarker(elem_image, "grid");
00185 
00186   if ( elem_grid == NULL )
00187   {
00188     // No grid element, Load the Sprite like a normal image
00189     Surface surface = LoadImage(profile->relative_path+image_filename, alpha);
00190     sprite = new Sprite();
00191     sprite->Init(surface, surface.GetSize(), 1, 1);
00192   }
00193   else
00194   {
00195     Point2i frameSize;
00196     int nb_frames_x = 0;
00197     int nb_frames_y = 0;
00198     std::string size;
00199 
00200     if ( ! profile->doc->ReadStringAttr(elem_grid, "size", size) )
00201       Error("ResourceManager: can't load sprite resource \""+resource_name+"\" has no attribute size");
00202 
00203     if ( size.find(",") != size.npos)
00204     {
00205       frameSize.x = atoi((size.substr(0, size.find(","))).c_str());
00206       frameSize.y = atoi((size.substr(size.find(",") + 1, size.length())).c_str());
00207     }
00208     else
00209       Error("ResourceManager: can't load sprite resource \""+resource_name+"\" has malformed size attribute");
00210 
00211     std::string array;
00212     if ( ! profile->doc->ReadStringAttr( elem_grid, "array", array) )
00213       Error("ResourceManager: can't load sprite resource \""+resource_name+"\" has no attribute array");
00214 
00215     if ( array.find(",") != array.npos)
00216     {
00217       nb_frames_x = atoi((array.substr(0, array.find(","))).c_str());
00218       if(nb_frames_x <= 0)
00219         nb_frames_x = 1;
00220       nb_frames_y = atoi((array.substr(array.find(",") + 1, array.length() - array.find(",") - 1)).c_str());
00221       if(nb_frames_y <= 0)
00222         nb_frames_y = 1;
00223     }
00224     else
00225       Error("ResourceManager: can't load (sprite) resource "+resource_name);
00226 
00227     Surface surface = LoadImage(profile->relative_path+image_filename, alpha);
00228     sprite = new Sprite();
00229     sprite->Init(surface, frameSize, nb_frames_x, nb_frames_y);
00230   }
00231 
00232   assert(sprite != NULL);
00233 
00234   xmlpp::Element *elem = profile->doc->GetMarker(elem_sprite, "animation");
00235   if ( elem != NULL )
00236   {
00237     std::string str;
00238     // Set the frame speed
00239     if ( profile->doc->ReadStringAttr(elem, "speed", str) )
00240       sprite->SetFrameSpeed(atoi(str.c_str()));
00241 
00242     if ( profile->doc->ReadStringAttr(elem, "loop_mode", str) )
00243     {
00244       bool loop_value;
00245       if(str2bool(str, loop_value))
00246         sprite->animation.SetLoopMode(loop_value);
00247       else
00248       if(str == "pingpong")
00249         sprite->animation.SetPingPongMode(true);
00250       else
00251         std::cerr << "Unrecognized xml option loop_mode=\"" << str << "\" in resource " << resource_name;
00252     }
00253   }
00254   return sprite;
00255 }
00256 
00257 
00258 ResourceManager resource_manager;
00259 

Generated on Mon Jan 1 13:10:59 2007 for Wormux by  doxygen 1.4.7