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