map_label.cpp

Go to the documentation of this file.
00001 /* $Id: map_label.cpp 53490 2012-03-10 13:29:33Z mordante $ */
00002 /*
00003    Copyright (C) 2003 - 2012 by David White <dave@whitevine.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
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 //our definition of map labels being obscured is if the tile is obscured,
00026 //or the tile below is obscured. This is because in the case where the tile
00027 //itself is visible, but the tile below is obscured, the bottom half of the
00028 //tile will still be shrouded, and the label being drawn looks weird
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     // no such team label, we try global label, except if it's what we just did
00106     // NOTE: This also avoid infinite recursion
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         // Found old checking if need to erase it
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 /// creating new label
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 /// Load label from config
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); // Not moved to rendering, as that would depend on variables at render-time
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     // If a color is specified don't allow to override it with markup. (prevents faking map labels for example)
00458     // FIXME: @todo Better detect if it's team label and not provided by
00459     // the scenario.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:05 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs