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 #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
00106 if(!doc->Load(filename))
00107 {
00108
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
00156
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
00179
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
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
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