00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "exploder_cutter.hpp"
00016 #include "filesystem.hpp"
00017 #include "sdl_utils.hpp"
00018 #include "serialization/parser.hpp"
00019 #include "serialization/preprocessor.hpp"
00020 #include "serialization/string_utils.hpp"
00021 #include "SDL_image.h"
00022
00023 cutter::cutter() : verbose_(false)
00024 {
00025
00026 }
00027
00028 const config cutter::load_config(const std::string &filename)
00029 {
00030 const std::string conf_string = find_configuration(filename);
00031
00032 config res;
00033
00034 try {
00035 scoped_istream stream = preprocess_file(conf_string);
00036 read(res, *stream);
00037 } catch(config::error err) {
00038 throw exploder_failure("Unable to load the configuration for the file " + filename + ": "+ err.message);
00039 }
00040
00041 return res;
00042 }
00043
00044
00045 void cutter::load_masks(const config& conf)
00046 {
00047 const config::child_list& masks = conf.get_children("mask");
00048
00049 for(config::child_list::const_iterator itor = masks.begin();
00050 itor != masks.end(); ++itor) {
00051
00052 const std::string name = (**itor)["name"];
00053 const std::string image = get_mask_dir() + "/" + (**itor)["image"];
00054
00055 if(verbose_) {
00056 std::cerr << "Adding mask " << name << "\n";
00057 }
00058
00059 if(image.empty())
00060 throw exploder_failure("Missing image for mask " + name);
00061
00062 const exploder_point shift((**itor)["shift"]);
00063 const exploder_rect cut((**itor)["cut"]);
00064
00065 if(masks_.find(name) != masks_.end() && masks_[name].filename != image) {
00066 throw exploder_failure("Mask " + name +
00067 " correspond to two different files: " +
00068 name + " and " +
00069 masks_.find(name)->second.filename);
00070 }
00071
00072 if(masks_.find(name) == masks_.end()) {
00073 mask& cur_mask = masks_[name];
00074
00075 cur_mask.name = name;
00076 cur_mask.shift = shift;
00077 cur_mask.cut = cut;
00078 cur_mask.filename = image;
00079 surface tmp(IMG_Load(image.c_str()));
00080 if(tmp == NULL)
00081 throw exploder_failure("Unable to load mask image " + image);
00082
00083 cur_mask.image = surface(make_neutral_surface(tmp));
00084 }
00085
00086 if(masks_[name].image == NULL)
00087 throw exploder_failure("Unable to load mask image " + image);
00088 }
00089 }
00090
00091
00092 cutter::surface_map cutter::cut_surface(surface surf, const config& conf)
00093 {
00094 surface_map res;
00095
00096 const config::child_list& config_parts = conf.get_children("part");
00097 config::child_list::const_iterator itor;
00098
00099 for(itor = config_parts.begin(); itor != config_parts.end(); ++itor) {
00100 add_sub_image(surf, res, *itor);
00101 }
00102
00103 return res;
00104 }
00105
00106
00107 std::string cutter::find_configuration(const std::string &file)
00108 {
00109
00110 const std::string fname = file_name(file);
00111 const std::string::size_type dotpos = fname.rfind('.');
00112
00113 std::string basename;
00114 if(dotpos == std::string::npos) {
00115 basename = fname;
00116 } else {
00117 basename = fname.substr(0, dotpos);
00118 }
00119
00120 return get_exploder_dir() + "/" + basename + ".cfg";
00121 }
00122
00123
00124 void cutter::add_sub_image(const surface &surf, surface_map &map, const config* config)
00125 {
00126 const std::string name = (*config)["name"];
00127 if(name.empty())
00128 throw exploder_failure("Un-named sub-image");
00129
00130 if(masks_.find(name) == masks_.end())
00131 throw exploder_failure("Unable to find mask corresponding to " + name);
00132
00133 const cutter::mask& mask = masks_[name];
00134
00135 std::vector<std::string> pos = utils::split((*config)["pos"]);
00136 if(pos.size() != 2)
00137 throw exploder_failure("Invalid position " + (*config)["pos"]);
00138
00139 int x = atoi(pos[0].c_str());
00140 int y = atoi(pos[1].c_str());
00141
00142 const SDL_Rect cut = {x - mask.shift.x, y - mask.shift.y, mask.image->w, mask.image->h};
00143
00144 typedef std::pair<std::string, positioned_surface> sme;
00145
00146 positioned_surface ps;
00147 ps.image = surface(::cut_surface(surf, cut));
00148 if(ps.image == NULL)
00149 throw exploder_failure("Unable to cut surface!");
00150 ps.name = name;
00151 ps.mask = mask;
00152 ps.pos.x = x - mask.shift.x;
00153 ps.pos.y = y - mask.shift.y;
00154 map.insert(sme(name, ps));
00155
00156 if(verbose_) {
00157 std::cerr << "Extracting sub-image " << name << ", position (" << x << ", " << y << ")\n";
00158 }
00159 }
00160
00161 void cutter::set_verbose(bool value)
00162 {
00163 verbose_ = value;
00164 }
00165