Skip to content

Commit

Permalink
GUI2/Minimap: make use of render_minimap, throw out weird cache
Browse files Browse the repository at this point in the history
I didn't take too close a look at what that weird cache was doing, but I recall last time
I did this concluding it didn't do much of anything at all.
  • Loading branch information
Vultraz committed Jun 3, 2022
1 parent 3470b94 commit db17177
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 153 deletions.
148 changes: 11 additions & 137 deletions src/gui/widgets/minimap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,157 +69,31 @@ 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 texture& tex) : tex(tex), age(1)
{
}

/** The cached image. */
const texture tex;

/**
* 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 cache. */
typedef std::map<key_type, value_type> tcache;
static tcache cache;

static bool compare(const std::pair<unsigned, tcache::iterator>& lhs,
const std::pair<unsigned, tcache::iterator>& 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<std::pair<unsigned, tcache::iterator>> 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<std::pair<unsigned, tcache::iterator>>::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 texture minimap::get_image(const int w, const int h) const
void minimap::set_map_data(const std::string& map_data)
{
const key_type key(w, h, map_data_);
tcache::iterator itor = cache.find(key);

if(itor != cache.end()) {
#ifdef DEBUG_MINIMAP_CACHE
std::cerr << '+';
#endif
itor->second.age++;
return itor->second.tex;
if(map_data == map_data_) {
return;
}

if(cache.size() >= cache_max_size) {
shrink_cache();
}
map_data_ = map_data;

try
{
const gamemap map(map_data_);
const texture tex = texture(image::getMinimap(w, h, map, nullptr, nullptr, true));
cache.emplace(key, value_type(tex));
#ifdef DEBUG_MINIMAP_CACHE
std::cerr << '-';
#endif
return tex;
}
catch(const incorrect_map_format_error& e)
{
try {
map_ = std::make_unique<gamemap>(map_data_);
} catch(const 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 texture();
}

void minimap::impl_draw_background(int x_offset, int y_offset)
void minimap::impl_draw_background(int /*x_offset*/, int /*y_offset*/)
{
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 texture tex = get_image(rect.w, rect.h);
if(tex) {
draw::blit(tex, rect);
if(map_) {
image::render_minimap(get_width(), get_height(), *map_, nullptr, nullptr, nullptr, true);
}
}

Expand Down
21 changes: 5 additions & 16 deletions src/gui/widgets/minimap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include "gui/core/window_builder.hpp"

class config;
class gamemap;

namespace gui2
{
namespace implementation
Expand Down Expand Up @@ -61,13 +63,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;
set_is_dirty(true);
}
}
void set_map_data(const std::string& map_data);

std::string get_map_data() const
{
Expand All @@ -83,15 +79,8 @@ class minimap : public styled_widget
/** The map data to be used to generate the map. */
std::string map_data_;

/**
* 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 texture get_image(const int w, const int h) const;
/** Game map generated from the provided data. */
std::unique_ptr<gamemap> map_;

/** See @ref widget::impl_draw_background. */
virtual void impl_draw_background(int x_offset, int y_offset) override;
Expand Down

0 comments on commit db17177

Please sign in to comment.