The Battle for Wesnoth  1.17.0-dev
minimap.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2021
3  by Mark de Wever <koraq@xs4all.nl>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #define GETTEXT_DOMAIN "wesnoth-lib"
17 
18 #include "gui/widgets/minimap.hpp"
19 
20 #include "gui/core/log.hpp"
24 #include "gui/widgets/settings.hpp"
25 #include "map/map.hpp"
26 #include "map/exception.hpp"
27 #include "sdl/rect.hpp"
28 #include "../../minimap.hpp" // We want the file in src/
29 
30 #include <functional>
31 
32 #include <algorithm>
33 
34 static lg::log_domain log_config("config");
35 #define ERR_CF LOG_STREAM_INDENT(err, log_config)
36 
37 #define LOG_SCOPE_HEADER get_control_type() + " [" + id() + "] " + __func__
38 #define LOG_HEADER LOG_SCOPE_HEADER + ':'
39 
40 // Define this to enable debug output for the minimap cache.
41 //#define DEBUG_MINIMAP_CACHE
42 
43 namespace gui2
44 {
45 
46 // ------------ WIDGET -----------{
47 
48 REGISTER_WIDGET(minimap)
49 
50 minimap::minimap(const implementation::builder_minimap& builder)
51  : styled_widget(builder, type())
52  , map_data_()
53 {
54 }
55 
56 void minimap::set_active(const bool /*active*/)
57 {
58  /* DO NOTHING */
59 }
60 
61 bool minimap::get_active() const
62 {
63  return true;
64 }
65 
66 unsigned minimap::get_state() const
67 {
68  return 0;
69 }
70 
71 /** Key type for the cache. */
72 struct key_type
73 {
74  key_type(const int w, const int h, const std::string& map_data)
75  : w(w), h(h), map_data(map_data)
76  {
77  }
78 
79  /** Width of the image. */
80  const int w;
81 
82  /** Height of the image. */
83  const int h;
84 
85  /** The data used to generate the image. */
86  const std::string map_data;
87 };
88 
89 static bool operator<(const key_type& lhs, const key_type& rhs)
90 {
91  return std::tie(lhs.w, lhs.h, lhs.map_data) < std::tie(rhs.w, rhs.h, rhs.map_data);
92 }
93 
94 /** Value type for the cache. */
95 struct value_type
96 {
97  value_type(const surface& surf) : surf(surf), age(1)
98  {
99  }
100 
101  /** The cached image. */
102  const surface surf;
103 
104  /**
105  * The age of the image.
106  *
107  * Every time an image is used its age is increased by one. Once the cache
108  * is full 25% of the cache is emptied. This is done by halving the age of
109  * the items in the cache and then erase the 25% with the lowest age. If
110  * items have the same age their order is unspecified.
111  */
112  unsigned age;
113 };
114 
115 /**
116  * Maximum number of items in the cache (multiple of 4).
117  *
118  * No testing on the optimal number is done, just seems a nice number.
119  */
120 static const size_t cache_max_size = 100;
121 
122 /** The cache. */
123 typedef std::map<key_type, value_type> tcache;
124 static tcache cache;
125 
126 static bool compare(const std::pair<unsigned, tcache::iterator>& lhs,
127  const std::pair<unsigned, tcache::iterator>& rhs)
128 {
129  return lhs.first < rhs.first;
130 }
131 
132 static void shrink_cache()
133 {
134 #ifdef DEBUG_MINIMAP_CACHE
135  std::cerr << "\nShrink cache from " << cache.size();
136 #else
137  DBG_GUI_D << "Shrinking the minimap cache.\n";
138 #endif
139 
140  std::vector<std::pair<unsigned, tcache::iterator>> items;
141  for(tcache::iterator itor = cache.begin(); itor != cache.end(); ++itor) {
142 
143  itor->second.age /= 2;
144  items.emplace_back(itor->second.age, itor);
145  }
146 
147  std::partial_sort(items.begin(),
148  items.begin() + cache_max_size / 4,
149  items.end(),
150  compare);
151 
152  for(std::vector<std::pair<unsigned, tcache::iterator>>::iterator vitor
153  = items.begin();
154  vitor < items.begin() + cache_max_size / 4;
155  ++vitor) {
156 
157  cache.erase(vitor->second);
158  }
159 
160 #ifdef DEBUG_MINIMAP_CACHE
161  std::cerr << " to " << cache.size() << ".\n";
162 #endif
163 }
164 
166 {
167  return false;
168 }
169 
170 const surface minimap::get_image(const int w, const int h) const
171 {
172  const key_type key(w, h, map_data_);
173  tcache::iterator itor = cache.find(key);
174 
175  if(itor != cache.end()) {
176 #ifdef DEBUG_MINIMAP_CACHE
177  std::cerr << '+';
178 #endif
179  itor->second.age++;
180  return itor->second.surf;
181  }
182 
183  if(cache.size() >= cache_max_size) {
184  shrink_cache();
185  }
186 
187  try
188  {
189  const gamemap map(map_data_);
190  const surface surf = image::getMinimap(w, h, map, nullptr, nullptr, true);
191  cache.emplace(key, value_type(surf));
192 #ifdef DEBUG_MINIMAP_CACHE
193  std::cerr << '-';
194 #endif
195  return surf;
196  }
197  catch(const incorrect_map_format_error& e)
198  {
199  ERR_CF << "Error while loading the map: " << e.message << '\n';
200 #ifdef DEBUG_MINIMAP_CACHE
201  std::cerr << 'X';
202 #endif
203  }
204  return nullptr;
205 }
206 
208  int x_offset,
209  int y_offset)
210 {
211  DBG_GUI_D << LOG_HEADER << " size "
212  << calculate_blitting_rectangle(x_offset, y_offset) << ".\n";
213 
214  if(map_data_.empty()) {
215  return;
216  }
217 
218  SDL_Rect rect = calculate_blitting_rectangle(x_offset, y_offset);
219  assert(rect.w > 0 && rect.h > 0);
220 
221  const ::surface surf = get_image(rect.w, rect.h);
222  if(surf) {
223  sdl_blit(surf, nullptr, frame_buffer, &rect);
224  }
225 }
226 
227 // }---------- DEFINITION ---------{
228 
231 {
232  DBG_GUI_P << "Parsing minimap " << id << '\n';
233 
234  load_resolutions<resolution>(cfg);
235 }
236 
238  : resolution_definition(cfg)
239 {
240  // Note the order should be the same as the enum state_t in minimap.hpp.
241  state.emplace_back(cfg.child("state_enabled"));
242 }
243 
244 // }---------- BUILDER -----------{
245 
246 namespace implementation
247 {
248 
249 builder_minimap::builder_minimap(const config& cfg) : builder_styled_widget(cfg)
250 {
251 }
252 
254 {
255  minimap* widget = new minimap(*this);
256 
257  DBG_GUI_G << "Window builder: placed minimap '" << id
258  << "' with definition '" << definition << "'.\n";
259 
260  return widget;
261 }
262 
263 } // namespace implementation
264 
265 // }------------ END --------------
266 
267 } // namespace gui2
Define the common log macros for the gui toolkit.
Base class of a resolution, contains the common keys for a resolution.
static bool compare(const std::pair< unsigned, tcache::iterator > &lhs, const std::pair< unsigned, tcache::iterator > &rhs)
Definition: minimap.cpp:126
#define DBG_GUI_P
Definition: log.hpp:66
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:402
std::vector< state_definition > state
const surface get_image(const int w, const int h) const
Gets the image for the minimap.
Definition: minimap.cpp:170
SDL_Rect calculate_blitting_rectangle(const int x_offset, const int y_offset)
Calculates the blitting rectangle of the widget.
Definition: widget.cpp:352
std::string map_data_
The map data to be used to generate the map.
Definition: minimap.hpp:84
Base class for all widgets.
Definition: widget.hpp:49
const std::string & map_data() const
Definition: minimap.hpp:77
#define h
const std::vector< std::string > items
surface getMinimap(int w, int h, const gamemap &map, const team *vw, const std::map< map_location, unsigned int > *reach_map, bool ignore_terrain_disabled)
function to create the minimap for a given map the surface returned must be freed by the user ...
Definition: minimap.cpp:40
Generic file dialog.
Definition: field-fwd.hpp:23
value_type(const surface &surf)
Definition: minimap.cpp:97
static void shrink_cache()
Definition: minimap.cpp:132
#define DBG_GUI_D
Definition: log.hpp:29
virtual bool get_active() const override
See styled_widget::get_active.
Definition: minimap.cpp:61
const int h
Height of the image.
Definition: minimap.cpp:83
static lg::log_domain log_config("config")
#define ERR_CF
Definition: minimap.cpp:35
std::string definition
Parameters for the styled_widget.
unsigned age
The age of the image.
Definition: minimap.cpp:112
This file contains the settings handling of the widget library.
std::map< key_type, value_type > tcache
The cache.
Definition: minimap.cpp:123
Encapsulates the map of the game.
Definition: map.hpp:171
static bool operator<(const key_type &lhs, const key_type &rhs)
Definition: minimap.cpp:89
Value type for the cache.
Definition: minimap.cpp:95
#define REGISTER_WIDGET(id)
Wrapper for REGISTER_WIDGET3.
bool disable_click_dismiss() const override
See widget::disable_click_dismiss.
Definition: minimap.cpp:165
const std::string map_data
The data used to generate the image.
Definition: minimap.cpp:86
virtual void impl_draw_background(surface &frame_buffer, int x_offset, int y_offset) override
See widget::impl_draw_background.
Definition: minimap.cpp:207
#define LOG_HEADER
Definition: minimap.cpp:38
static tcache cache
Definition: minimap.cpp:124
minimap_definition(const config &cfg)
Definition: minimap.cpp:229
int w
Base class for all visible items.
The basic minimap class.
Definition: minimap.hpp:43
static const size_t cache_max_size
Maximum number of items in the cache (multiple of 4).
Definition: minimap.cpp:120
const int w
Width of the image.
Definition: minimap.cpp:80
Contains the SDL_Rect helper code.
virtual void set_active(const bool active) override
See styled_widget::set_active.
Definition: minimap.cpp:56
key_type(const int w, const int h, const std::string &map_data)
Definition: minimap.cpp:74
std::string message
Definition: exceptions.hpp:30
#define e
virtual unsigned get_state() const override
See styled_widget::get_state.
Definition: minimap.cpp:66
void sdl_blit(const surface &src, SDL_Rect *src_rect, surface &dst, SDL_Rect *dst_rect)
Definition: utils.hpp:32
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:61
virtual widget * build() const override
Definition: minimap.cpp:253
#define DBG_GUI_G
Definition: log.hpp:41
Key type for the cache.
Definition: minimap.cpp:72
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
Contains the implementation details for lexical_cast and shouldn&#39;t be used directly.
const surface surf
The cached image.
Definition: minimap.cpp:102