Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #define GETTEXT_DOMAIN "wesnoth-lib"
00017
00018 #include "gui/widgets/minimap.hpp"
00019
00020 #include "gui/auxiliary/log.hpp"
00021 #include "gui/auxiliary/widget_definition/minimap.hpp"
00022 #include "gui/auxiliary/window_builder/minimap.hpp"
00023 #include "gui/widgets/settings.hpp"
00024 #include "map.hpp"
00025 #include "map_exception.hpp"
00026 #include "../../minimap.hpp"
00027
00028 #include <boost/bind.hpp>
00029
00030 #include <algorithm>
00031
00032 static lg::log_domain log_config("config");
00033 #define ERR_CF LOG_STREAM_INDENT(err, log_config)
00034
00035 #define LOG_SCOPE_HEADER get_control_type() + " [" + id() + "] " + __func__
00036 #define LOG_HEADER LOG_SCOPE_HEADER + ':'
00037
00038
00039
00040
00041 namespace gui2 {
00042
00043 REGISTER_WIDGET(minimap)
00044
00045
00046 struct tkey
00047 {
00048 tkey(const int w, const int h, const std::string& map_data)
00049 : w(w)
00050 , h(h)
00051 , map_data(map_data)
00052 {
00053 }
00054
00055
00056 const int w;
00057
00058
00059 const int h;
00060
00061
00062 const std::string map_data;
00063 };
00064
00065 static bool operator<(const tkey& lhs, const tkey& rhs)
00066 {
00067 return lhs.w < rhs.w || (lhs.w == rhs.w
00068 && (lhs.h < rhs.h || (lhs.h == rhs.h
00069 && lhs.map_data < rhs.map_data)));
00070 }
00071
00072
00073 struct tvalue
00074 {
00075 tvalue(const surface& surf)
00076 : surf(surf)
00077 , age(1)
00078 {
00079 }
00080
00081
00082 const surface surf;
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 unsigned age;
00093 };
00094
00095 #ifdef LOW_MEM
00096
00097
00098
00099
00100
00101 static const size_t cache_max_size = 4;
00102 #else
00103
00104
00105
00106
00107
00108 static const size_t cache_max_size = 100;
00109 #endif
00110
00111
00112
00113
00114
00115
00116
00117
00118 static const ::config* terrain = NULL;
00119
00120
00121 typedef std::map<tkey, tvalue> tcache;
00122 static tcache cache;
00123
00124 static bool compare(const std::pair<unsigned, tcache::iterator>& lhs
00125 , const std::pair<unsigned, tcache::iterator>& rhs)
00126 {
00127 return lhs.first < rhs.first;
00128 }
00129
00130 static void shrink_cache()
00131 {
00132 #ifdef DEBUG_MINIMAP_CACHE
00133 std::cerr << "\nShrink cache from " << cache.size();
00134 #else
00135 DBG_GUI_D << "Shrinking the minimap cache.\n";
00136 #endif
00137
00138 std::vector<std::pair<unsigned, tcache::iterator> > items;
00139 for(tcache::iterator itor = cache.begin(); itor != cache.end(); ++itor) {
00140
00141 itor->second.age /= 2;
00142 items.push_back(std::make_pair(itor->second.age, itor));
00143 }
00144
00145 std::partial_sort(items.begin()
00146 , items.begin() + cache_max_size / 4
00147 , items.end()
00148 , compare);
00149
00150 for(std::vector<std::pair<unsigned, tcache::iterator> >::iterator
00151 vitor = items.begin()
00152 ; vitor < items.begin() + cache_max_size / 4
00153 ; ++vitor) {
00154
00155 cache.erase(vitor->second);
00156 }
00157
00158 #ifdef DEBUG_MINIMAP_CACHE
00159 std::cerr << " to " << cache.size() << ".\n";
00160 #endif
00161 }
00162
00163 const surface tminimap::get_image(const int w, const int h) const
00164 {
00165 if(!terrain_) {
00166 return NULL;
00167 }
00168
00169 if(terrain_ != terrain) {
00170 #ifdef DEBUG_MINIMAP_CACHE
00171 std::cerr << "\nFlush cache.\n";
00172 #else
00173 DBG_GUI_D << "Flushing the minimap cache.\n";
00174 #endif
00175 terrain = terrain_;
00176 cache.clear();
00177
00178 }
00179
00180 const tkey key(w, h, map_data_);
00181 tcache::iterator itor = cache.find(key);
00182
00183 if(itor != cache.end()) {
00184 #ifdef DEBUG_MINIMAP_CACHE
00185 std::cerr << '+';
00186 #endif
00187 itor->second.age++;
00188 return itor->second.surf;
00189 }
00190
00191 if(cache.size() >= cache_max_size) {
00192 shrink_cache();
00193 }
00194
00195 try {
00196 const gamemap map(*terrain_, map_data_);
00197 const surface surf = image::getMinimap(w, h, map, NULL);
00198 cache.insert(std::make_pair(key, tvalue(surf)));
00199 #ifdef DEBUG_MINIMAP_CACHE
00200 std::cerr << '-';
00201 #endif
00202 return surf;
00203
00204 } catch (incorrect_map_format_error& e) {
00205 ERR_CF << "Error while loading the map: " << e.message << '\n';
00206 #ifdef DEBUG_MINIMAP_CACHE
00207 std::cerr << 'X';
00208 #endif
00209 }
00210 return NULL;
00211 }
00212
00213 void tminimap::impl_draw_background(surface& frame_buffer)
00214 {
00215 if (!terrain_) return;
00216 assert(terrain_);
00217
00218 DBG_GUI_D << LOG_HEADER
00219 << " size " << get_rect()
00220 << ".\n";
00221
00222 if(map_data_.empty()) {
00223 return;
00224 }
00225
00226 SDL_Rect rect = get_rect();
00227 assert(rect.w > 0 && rect.h > 0);
00228
00229 const ::surface surf = get_image(rect.w, rect.h);
00230 if(surf) {
00231 sdl_blit(surf, NULL, frame_buffer, &rect);
00232 }
00233 }
00234
00235 void tminimap::impl_draw_background(
00236 surface& frame_buffer
00237 , int x_offset
00238 , int y_offset)
00239 {
00240 if (!terrain_) return;
00241 assert(terrain_);
00242
00243 DBG_GUI_D << LOG_HEADER
00244 << " size " << calculate_blitting_rectangle(x_offset, y_offset)
00245 << ".\n";
00246
00247 if(map_data_.empty()) {
00248 return;
00249 }
00250
00251 SDL_Rect rect = calculate_blitting_rectangle(x_offset, y_offset);
00252 assert(rect.w > 0 && rect.h > 0);
00253
00254 const ::surface surf = get_image(rect.w, rect.h);
00255 if(surf) {
00256 sdl_blit(surf, NULL, frame_buffer, &rect);
00257 }
00258 }
00259
00260 const std::string& tminimap::get_control_type() const
00261 {
00262 static const std::string type = "minimap";
00263 return type;
00264 }
00265
00266 }
00267