00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "global.hpp"
00016
00017 #include "display.hpp"
00018 #include "font.hpp"
00019 #include "language.hpp"
00020 #include "map_label.hpp"
00021
00022 #include <cassert>
00023 #include <vector>
00024
00025 namespace {
00026 const size_t max_label_size = 32;
00027 }
00028
00029
00030
00031
00032
00033 static bool is_shrouded(const display& disp, const gamemap::location& loc)
00034 {
00035 return disp.shrouded(loc) || disp.shrouded(gamemap::location(loc.x,loc.y+1));
00036 }
00037
00038 map_labels::map_labels(const display& disp,
00039 const gamemap& map,
00040 const team* team) :
00041 disp_(disp),
00042 team_(team),
00043 map_(map)
00044 {
00045 }
00046
00047 map_labels::map_labels(const display& disp,
00048 const config& cfg,
00049 const gamemap& map,
00050 const team* team,
00051 const variable_set *variables) :
00052 disp_(disp),
00053 team_(team),
00054 map_(map)
00055 {
00056 read(cfg, variables);
00057 }
00058
00059 map_labels::~map_labels()
00060 {
00061 clear_all();
00062 }
00063
00064 void map_labels::write(config& res) const
00065 {
00066 for (team_label_map::const_iterator labs = labels_.begin(); labs != labels_.end(); ++labs)
00067 {
00068 for(label_map::const_iterator i = labs->second.begin(); i != labs->second.end(); ++i) {
00069 config item;
00070 i->second->write(item);
00071
00072
00073 res.add_child("label",item);
00074 }
00075 }
00076 }
00077
00078 void map_labels::read(const config& cfg, const variable_set *variables)
00079 {
00080 clear_all();
00081
00082 const config::child_list& items = cfg.get_children("label");
00083 for(config::child_list::const_iterator i = items.begin(); i != items.end(); ++i) {
00084 const gamemap::location loc(**i, variables);
00085 terrain_label* label = new terrain_label(*this, **i, variables);
00086 add_label(loc, label);
00087 }
00088 recalculate_labels();
00089 }
00090
00091
00092 size_t map_labels::get_max_chars()
00093 {
00094 return max_label_size;
00095 }
00096
00097 const terrain_label* map_labels::get_label(const gamemap::location& loc, const std::string& team_name)
00098 {
00099 team_label_map::const_iterator label_map = labels_.find(team_name);
00100 if (label_map != labels_.end()) {
00101 map_labels::label_map::const_iterator itor = label_map->second.find(loc);;
00102 if (itor != label_map->second.end())
00103 return itor->second;
00104 }
00105 return NULL;
00106 }
00107
00108 const terrain_label* map_labels::get_label(const gamemap::location& loc)
00109 {
00110 const terrain_label* res = get_label(loc, team_name());
00111
00112
00113 if (res == NULL && team_name() != "") {
00114 return get_label(loc, "");
00115 }
00116 return res;
00117 }
00118
00119
00120 const display& map_labels::disp() const
00121 {
00122 return disp_;
00123 }
00124
00125 const std::string& map_labels::team_name() const
00126 {
00127 if (team_)
00128 {
00129 return team_->team_name();
00130 }
00131 static const std::string empty;
00132 return empty;
00133 }
00134
00135 void map_labels::set_team(const team* team)
00136 {
00137 if ( team_ != team )
00138 {
00139 team_ = team;
00140 }
00141 }
00142
00143
00144 const terrain_label* map_labels::set_label(const gamemap::location& loc,
00145 const std::string& text,
00146 const std::string team_name,
00147 const SDL_Color colour)
00148 {
00149 terrain_label* res = 0;
00150 const team_label_map::const_iterator current_label_map = labels_.find(team_name);
00151 label_map::const_iterator current_label;
00152
00153 if ( current_label_map != labels_.end()
00154 && (current_label = current_label_map->second.find(loc)) != current_label_map->second.end() )
00155 {
00156
00157 if(text.empty())
00158 {
00159 const_cast<terrain_label*>(current_label->second)->set_text("");
00160 res = new terrain_label("",team_name,loc,*this,colour);
00161 delete current_label->second;
00162 const_cast<label_map&>(current_label_map->second).erase(loc);
00163
00164 team_label_map::iterator global_label_map = labels_.find("");
00165 label_map::iterator itor;
00166 bool update = false;
00167 if(global_label_map != labels_.end()) {
00168 itor = global_label_map->second.find(loc);
00169 update = itor != global_label_map->second.end();
00170 }
00171 if (update)
00172 {
00173 const_cast<terrain_label*>(itor->second)->recalculate();
00174 }
00175
00176 }
00177 else
00178 {
00179 const_cast<terrain_label*>(current_label->second)->update_info(text,
00180 team_name,
00181 colour);
00182 res = const_cast<terrain_label*>(current_label->second);
00183 }
00184 }
00185 else if(!text.empty())
00186 {
00187 team_label_map::iterator global_label_map = labels_.find("");
00188 label_map::iterator itor;
00189 bool update = false;
00190 if(global_label_map != labels_.end()) {
00191 itor = global_label_map->second.find(loc);
00192 update = itor != global_label_map->second.end();
00193 }
00194
00195 terrain_label* label = new terrain_label(text,
00196 team_name,
00197 loc,
00198 *this,
00199 colour);
00200 add_label(loc,label);
00201
00202 res = label;
00203
00204 if (update)
00205 {
00206 const_cast<terrain_label*>(itor->second)->recalculate();
00207 }
00208
00209 }
00210 return res;
00211 }
00212
00213 void map_labels::add_label(const gamemap::location& loc,
00214 const terrain_label* new_label)
00215 {
00216 team_label_map::const_iterator labs = labels_.find(new_label->team_name());
00217 if(labs == labels_.end())
00218 {
00219 labels_.insert(std::pair<std::string,label_map>(new_label->team_name(), label_map()));
00220 labs = labels_.find(new_label->team_name());
00221
00222 assert(labs != labels_.end());
00223 }
00224
00225 const_cast<label_map&>(labs->second).insert(std::pair<gamemap::location,const terrain_label*>(loc,new_label));
00226 }
00227
00228 void map_labels::clear(const std::string& team_name)
00229 {
00230 team_label_map::iterator i = labels_.find(team_name);
00231 if (i != labels_.end())
00232 {
00233 clear_map(i->second);
00234 }
00235
00236 i = labels_.find("");
00237 if (i != labels_.end())
00238 {
00239 clear_map(i->second);
00240 }
00241 }
00242
00243 void map_labels::clear_map(const label_map& m)
00244 {
00245 for (label_map::const_iterator j = m.begin(); j != m.end(); ++j)
00246 {
00247 delete j->second;
00248 }
00249 const_cast<label_map&>(m).clear();
00250 }
00251
00252 void map_labels::clear_all()
00253 {
00254 for(team_label_map::const_iterator i = labels_.begin(); i != labels_.end(); ++i)
00255 {
00256 clear_map(i->second);
00257 }
00258 labels_.clear();
00259 }
00260
00261 void map_labels::scroll(double xmove, double ymove)
00262 {
00263 for(team_label_map::const_iterator i = labels_.begin(); i != labels_.end(); ++i)
00264 {
00265 for (label_map::const_iterator j = i->second.begin(); j != i->second.end(); ++j)
00266 {
00267 j->second->scroll(xmove, ymove);
00268 }
00269 }
00270 }
00271
00272 void map_labels::recalculate_labels()
00273 {
00274 for(team_label_map::const_iterator i = labels_.begin(); i != labels_.end(); ++i)
00275 {
00276 for (label_map::const_iterator j = i->second.begin(); j != i->second.end(); ++j)
00277 {
00278 const_cast<terrain_label*>(j->second)->recalculate();
00279 }
00280 }
00281 }
00282
00283 bool map_labels::visible_global_label(const gamemap::location& loc) const
00284 {
00285 const team_label_map::const_iterator glabels = labels_.find(team_name());
00286 return glabels == labels_.end()
00287 || glabels->second.find(loc) == glabels->second.end();
00288 }
00289
00290 void map_labels::recalculate_shroud()
00291 {
00292 for(team_label_map::const_iterator i = labels_.begin(); i != labels_.end(); ++i)
00293 {
00294 for (label_map::const_iterator j = i->second.begin(); j != i->second.end(); ++j)
00295 {
00296 const_cast<terrain_label*>(j->second)->calculate_shroud();
00297 }
00298 }
00299 }
00300
00301
00302
00303 terrain_label::terrain_label(const std::string& text,
00304 const std::string& team_name,
00305 const gamemap::location& loc,
00306 const map_labels& parent,
00307 const SDL_Color colour) :
00308 handle_(0),
00309 text_(text),
00310 team_name_(team_name),
00311 colour_(colour),
00312 parent_(&parent),
00313 loc_(loc)
00314 {
00315 check_text_length();
00316 draw();
00317 }
00318
00319 terrain_label::terrain_label(const map_labels& parent) :
00320 handle_(0),
00321 text_(),
00322 team_name_(),
00323 colour_(),
00324 parent_(&parent),
00325 loc_()
00326 {
00327 }
00328
00329
00330
00331 terrain_label::terrain_label(const map_labels& parent,
00332 const config& cfg,
00333 const variable_set *variables) :
00334 handle_(0),
00335 parent_(&parent)
00336 {
00337 read(cfg, variables);
00338 check_text_length();
00339 }
00340
00341
00342 terrain_label::~terrain_label()
00343 {
00344 clear();
00345 }
00346
00347 void terrain_label::read(const config& cfg, const variable_set *variables)
00348 {
00349 loc_ = gamemap::location(cfg, variables);
00350 SDL_Color colour = font::LABEL_COLOUR;
00351 std::string tmp_colour = cfg["colour"];
00352
00353 text_ = cfg["text"];
00354 team_name_ = cfg["team_name"];
00355
00356 if (variables)
00357 {
00358 text_ = utils::interpolate_variables_into_string(
00359 text_, *variables);
00360 team_name_ = utils::interpolate_variables_into_string(
00361 team_name_, *variables);
00362 tmp_colour = utils::interpolate_variables_into_string(
00363 tmp_colour, *variables);
00364 }
00365
00366 if(!tmp_colour.empty()) {
00367 std::vector<Uint32> temp_rgb;
00368 try {
00369 temp_rgb = string2rgb(tmp_colour);
00370 } catch(bad_lexical_cast&) {
00371
00372 }
00373 if(!temp_rgb.empty()) {
00374 colour = int_to_color(temp_rgb[0]);
00375 }
00376 }
00377 colour_ = colour;
00378 }
00379
00380 void terrain_label::write(config& cfg) const
00381 {
00382 loc_.write(cfg);
00383 cfg["text"] = text();
00384 cfg["team_name"] = (this->team_name());
00385 cfg["colour"] = cfg_colour();
00386
00387 }
00388
00389 const std::string& terrain_label::text() const
00390 {
00391 return text_;
00392 }
00393
00394 const std::string& terrain_label::team_name() const
00395 {
00396 return team_name_;
00397 }
00398
00399 const gamemap::location& terrain_label::location() const
00400 {
00401 return loc_;
00402 }
00403
00404 const SDL_Colour& terrain_label::colour() const
00405 {
00406 return colour_;
00407 }
00408
00409 const std::string terrain_label::cfg_colour() const
00410 {
00411 std::stringstream buf;
00412 const unsigned int red = static_cast<unsigned int>(colour_.r);
00413 const unsigned int green = static_cast<unsigned int>(colour_.g);
00414 const unsigned int blue = static_cast<unsigned int>(colour_.b);
00415 const unsigned int alpha = static_cast<unsigned int>(colour_.unused);
00416 buf << red << ","
00417 << green << ","
00418 << blue << ","
00419 << alpha;
00420 return buf.str();
00421 }
00422
00423 void terrain_label::set_text(const std::string& text)
00424 {
00425 text_ = text;
00426 }
00427
00428 void terrain_label::update_info(const std::string& text,
00429 const std::string& team_name,
00430 const SDL_Color colour)
00431 {
00432 colour_ = colour;
00433 text_ = text;
00434 check_text_length();
00435 team_name_ = team_name;
00436 draw();
00437 }
00438
00439 void terrain_label::scroll(const double xmove,
00440 const double ymove) const
00441 {
00442 if(handle_)
00443 {
00444 font::move_floating_label(handle_,
00445 xmove,
00446 ymove);
00447 }
00448 }
00449
00450 void terrain_label::recalculate()
00451 {
00452 draw();
00453 }
00454
00455 void terrain_label::calculate_shroud() const
00456 {
00457
00458 if (handle_)
00459 {
00460 font::show_floating_label(handle_,
00461 !is_shrouded(parent_->disp(),
00462 loc_));
00463 }
00464 }
00465
00466 void terrain_label::draw()
00467 {
00468 clear();
00469 if (visible())
00470 {
00471
00472 const gamemap::location loc_nextx(loc_.x+1,loc_.y);
00473 const gamemap::location loc_nexty(loc_.x,loc_.y+1);
00474 const int xloc = (parent_->disp().get_location_x(loc_) +
00475 parent_->disp().get_location_x(loc_nextx)*2)/3;
00476 const int yloc = parent_->disp().get_location_y(loc_nexty) - font::SIZE_NORMAL;
00477
00478 cfg_colour();
00479
00480 handle_ = font::add_floating_label(text_,
00481 font::SIZE_NORMAL,
00482 colour_,
00483 xloc, yloc,
00484 0,0,
00485 -1,
00486 parent_->disp().map_outside_area());
00487
00488 calculate_shroud();
00489 }
00490 }
00491
00492 bool terrain_label::visible() const
00493 {
00494 return parent_->team_name() == team_name_
00495 || (team_name_.empty() && parent_->visible_global_label(loc_));
00496 }
00497
00498 void terrain_label::check_text_length()
00499 {
00500
00501
00502
00503 utils::truncate_as_wstring(text_, parent_->get_max_chars());
00504 }
00505
00506 void terrain_label::clear()
00507 {
00508 if (handle_)
00509 {
00510 font::remove_floating_label(handle_);
00511 handle_ = 0;
00512 }
00513 }