diff --git a/src/gui/widgets/minimap.cpp b/src/gui/widgets/minimap.cpp index 56bace89685a..564870919f75 100644 --- a/src/gui/widgets/minimap.cpp +++ b/src/gui/widgets/minimap.cpp @@ -52,7 +52,9 @@ minimap::minimap(const implementation::builder_minimap& builder) : styled_widget(builder, get_control_type()) , map_data_() , terrain_(nullptr) + , map_(nullptr) { + get_canvas(0).set_draw_function(std::bind(&minimap::canvas_draw_background, this, _1)); } void minimap::set_active(const bool /*active*/) @@ -70,189 +72,34 @@ unsigned minimap::get_state() const return 0; } -/** Key type for the cache. */ -struct key_type -{ - key_type(const int w, const int h, const std::string& map_data) - : w(w), h(h), map_data(map_data) - { - } - - /** Width of the image. */ - const int w; - - /** Height of the image. */ - const int h; - - /** The data used to generate the image. */ - const std::string map_data; -}; - -static bool operator<(const key_type& lhs, const key_type& rhs) -{ - return std::tie(lhs.w, lhs.h, lhs.map_data) < std::tie(rhs.w, rhs.h, rhs.map_data); -} - -/** Value type for the cache. */ -struct value_type -{ - value_type(const surface& surf) : surf(surf), age(1) - { - } - - /** The cached image. */ - const surface surf; - - /** - * The age of the image. - * - * Every time an image is used its age is increased by one. Once the cache - * is full 25% of the cache is emptied. This is done by halving the age of - * the items in the cache and then erase the 25% with the lowest age. If - * items have the same age their order is unspecified. - */ - unsigned age; -}; - -/** - * Maximum number of items in the cache (multiple of 4). - * - * No testing on the optimal number is done, just seems a nice number. - */ -static const size_t cache_max_size = 100; - -/** - * The terrain used to create the cache. - * - * If another terrain config is used the cache needs to be cleared, this - * normally doesn't happen a lot so the clearing of the cache is rather - * unusual. - */ -static const ::config* terrain = nullptr; - -/** The cache. */ -typedef std::map tcache; -static tcache cache; - -static bool compare(const std::pair& lhs, - const std::pair& rhs) -{ - return lhs.first < rhs.first; -} - -static void shrink_cache() -{ -#ifdef DEBUG_MINIMAP_CACHE - std::cerr << "\nShrink cache from " << cache.size(); -#else - DBG_GUI_D << "Shrinking the minimap cache.\n"; -#endif - - std::vector> items; - for(tcache::iterator itor = cache.begin(); itor != cache.end(); ++itor) { - - itor->second.age /= 2; - items.emplace_back(itor->second.age, itor); - } - - std::partial_sort(items.begin(), - items.begin() + cache_max_size / 4, - items.end(), - compare); - - for(std::vector>::iterator vitor - = items.begin(); - vitor < items.begin() + cache_max_size / 4; - ++vitor) { - - cache.erase(vitor->second); - } - -#ifdef DEBUG_MINIMAP_CACHE - std::cerr << " to " << cache.size() << ".\n"; -#endif -} - bool minimap::disable_click_dismiss() const { return false; } -const surface minimap::get_image(const int w, const int h) const +void minimap::set_map_data(const std::string& map_data) { - if(!terrain_) { - return nullptr; - } - - if(terrain_ != terrain) { -#ifdef DEBUG_MINIMAP_CACHE - std::cerr << "\nFlush cache.\n"; -#else - DBG_GUI_D << "Flushing the minimap cache.\n"; -#endif - terrain = terrain_; - cache.clear(); + if(map_data == map_data_) { + return; } - const key_type key(w, h, map_data_); - tcache::iterator itor = cache.find(key); + map_data_ = map_data; - if(itor != cache.end()) { -#ifdef DEBUG_MINIMAP_CACHE - std::cerr << '+'; -#endif - itor->second.age++; - return itor->second.surf; - } - - if(cache.size() >= cache_max_size) { - shrink_cache(); - } - - try - { - const gamemap map(std::make_shared(*terrain_), map_data_); - const surface surf = image::getMinimap(w, h, map, nullptr, nullptr, true); - cache.emplace(key, value_type(surf)); -#ifdef DEBUG_MINIMAP_CACHE - std::cerr << '-'; -#endif - return surf; - } - catch(incorrect_map_format_error& e) - { + try { + map_.reset(new gamemap(std::make_shared(*terrain_), map_data_)); + } catch(incorrect_map_format_error& e) { + map_.reset(nullptr); ERR_CF << "Error while loading the map: " << e.message << '\n'; -#ifdef DEBUG_MINIMAP_CACHE - std::cerr << 'X'; -#endif } - return nullptr; + + // Flag the background canvas as dirty so the minimap is redrawn. + get_canvas(0).set_is_dirty(true); } -void minimap::impl_draw_background(int x_offset, int y_offset) +void minimap::canvas_draw_background(texture& tex) { - styled_widget::impl_draw_background(x_offset, y_offset); - - if(!terrain_) - return; - assert(terrain_); - - DBG_GUI_D << LOG_HEADER << " size " - << calculate_blitting_rectangle(x_offset, y_offset) << ".\n"; - - if(map_data_.empty()) { - return; - } - - SDL_Rect rect = calculate_blitting_rectangle(x_offset, y_offset); - assert(rect.w > 0 && rect.h > 0); - - const ::surface surf = get_image(rect.w, rect.h); - if(surf) { - SDL_Rect dst {0, 0, surf->w, surf->h}; - texture txt(surf); - - CVideo::get_singleton().render_copy(txt, nullptr, &dst); + if(map_) { + image::render_minimap(tex, *map_, nullptr, nullptr, true); } } diff --git a/src/gui/widgets/minimap.hpp b/src/gui/widgets/minimap.hpp index eddb0e0c4d1c..1b16e8614e16 100644 --- a/src/gui/widgets/minimap.hpp +++ b/src/gui/widgets/minimap.hpp @@ -20,6 +20,8 @@ #include "gui/core/window_builder.hpp" class config; +class gamemap; +class texture; namespace gui2 { @@ -57,12 +59,7 @@ class minimap : public styled_widget /***** ***** ***** setters / getters for members ***** ****** *****/ - void set_map_data(const std::string& map_data) - { - if(map_data != map_data_) { - map_data_ = map_data; - } - } + void set_map_data(const std::string& map_data); std::string get_map_data() const { @@ -90,18 +87,11 @@ class minimap : public styled_widget */ const ::config* terrain_; - /** - * Gets the image for the minimap. - * - * @param w The wanted width of the image. - * @param h The wanted height of the image. - * - * @returns The image, nullptr upon error. - */ - const surface get_image(const int w, const int h) const; + /** Game map generated from the provided data. */ + std::unique_ptr map_; - /** See @ref widget::impl_draw_background. */ - virtual void impl_draw_background(int x_offset, int y_offset) override; + /** Drawing function passed to the background canvas. */ + void canvas_draw_background(texture& tex); /** Inherited from styled_widget, implemented by REGISTER_WIDGET. */ virtual const std::string& get_control_type() const override;