The Battle for Wesnoth  1.19.18+dev
editor_map.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2025
3  by Tomasz Sniatowski <kailoran@gmail.com>
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 #pragma once
17 
18 #include "editor/editor_common.hpp"
19 #include "map/map.hpp"
20 
21 #include <boost/dynamic_bitset.hpp>
22 
23 namespace editor {
24 
26 {
28  : editor_exception("Map operation error. Check debug log for details.")
29  {
30  }
31 };
32 
34 {
36  : editor_exception("Map integrity error. Check debug log for details.")
37  {
38  }
39 };
40 
42 {
43  editor_map_load_exception(const std::string& fn, const std::string& msg)
45  {
46  }
48  std::string filename;
49 };
50 
52 {
53  editor_map_save_exception(const std::string& msg)
55  {
56  }
58 };
59 
60 
61 /**
62  * Exception wrapping utility
63  */
64 editor_map_load_exception wrap_exc(const char* type, const std::string& e_msg, const std::string& filename);
65 
66 /**
67  * This class adds extra editor-specific functionality to a normal gamemap.
68  */
69 class editor_map : public gamemap
70 {
71 public:
72  /**
73  * Empty map constructor
74  */
75  editor_map();
76 
77  /**
78  * Create an editor map from a map data string
79  */
80  editor_map(std::string_view data);
81 
82  /**
83  * Wrapper around editor_map(cfg, data) that catches possible exceptions
84  * and wraps them in a editor_map_load_exception
85  */
86  static editor_map from_string(std::string_view data);
87 
88  /**
89  * Create an editor map with the given dimensions and filler terrain
90  */
91  editor_map(std::size_t width, std::size_t height, const t_translation::terrain_code & filler);
92 
93  /**
94  * Create an editor_map by upgrading an existing gamemap. The map data is
95  * copied. Marked "explicit" to avoid potentially harmful automatic conversions.
96  */
97  explicit editor_map(const gamemap& map);
98 
99  /**
100  * Get a contiguous set of tiles having the same terrain as the starting location.
101  * Useful for flood fill or magic wand selection
102  * @return a contiguous set of locations that will always contain at least the starting element
103  */
104  std::set<map_location> get_contiguous_terrain_tiles(const map_location& start) const;
105 
106  /**
107  * Set labels for staring positions in the given display object.
108  * @return the locations where the labels were added
109  */
110  std::set<map_location> set_starting_position_labels(display& disp);
111 
112  /**
113  * @return true when the location is part of the selection, false otherwise
114  */
115  bool in_selection(const map_location& loc) const;
116 
117  /**
118  * Add a location to the selection. The location should be valid (i.e. on the map)
119  * @return true if the selected hexes set was modified
120  */
121  bool add_to_selection(const map_location& loc);
122 
123  /**
124  * Remove a location to the selection. The location does not actually have to be selected
125  * @return true if the selected hexes set was modified
126  */
128 
129  /**
130  * Select the given area.
131  * @param area to select.
132  */
133  void set_selection(const std::set<map_location>& area);
134 
135  /**
136  * Return the selection set.
137  */
138  std::set<map_location> selection() const;
139 
140  /**
141  * Returns a set of all hexes *not* currently selected.
142  */
143  std::set<map_location> selection_inverse() const;
144 
145  /**
146  * Clear the selection
147  */
148  void clear_selection();
149 
150  /**
151  * Invert the selection, i.e. select all the map hexes that were not selected.
152  */
153  void invert_selection();
154 
155  /**
156  * Select all map hexes
157  */
158  void select_all();
159 
160  /**
161  * @return true if the entire map is selected, false otherwise
162  */
163  bool everything_selected() const;
164 
165  /**
166  * @return true if at least one location is selected, false otherwise
167  */
168  bool anything_selected() const;
169 
170  /**
171  * @return true if at no selections are selected, false otherwise
172  */
173  bool nothing_selected() const;
174 
175  /**
176  * @return the number of locations selected.
177  *
178  * @note This is more efficient than checking selection().size() since
179  * it avoids allocating a full map_location set and simply queries the
180  * number of engaged bits in the underlying bitset.
181  */
182  std::size_t num_selected() const;
183 
184  /**
185  * Resize the map. If the filler is NONE, the border terrain will be copied
186  * when expanding, otherwise the filler terrain will be inserted there
187  */
188  void resize(int width, int height, int x_offset, int y_offset,
190 
191  /**
192  * A sort-of diff operation returning a mask that, when applied to the current editor_map,
193  * will transform it into the target map.
194  */
195  gamemap mask_to(const gamemap& target) const;
196 
197  /**
198  * A precondition to several map operations
199  * @return true if this map has the same dimensions as the other map
200  */
201  bool same_size_as(const gamemap& other) const;
202 
203 private:
204  //helper functions for resizing
205  void expand_right(int count, const t_translation::terrain_code & filler);
206  void expand_left(int count, const t_translation::terrain_code & filler);
207  void expand_top(int count, const t_translation::terrain_code & filler);
208  void expand_bottom(int count, const t_translation::terrain_code & filler);
209  void shrink_right(int count);
210  void shrink_left(int count);
211  void shrink_top(int count);
212  void shrink_bottom(int count);
213 
215  {
216  public:
217  explicit selection_mask(const gamemap_base& map)
218  : stride_(map.total_width())
219  , height_(map.total_height())
220  {
221  bitset_.resize(map.total_area());
222  }
223 
224  /**
225  * Marks @a loc as selected.
226  * @returns true if the location was previously deselected.
227  */
228  bool select(const map_location& loc)
229  {
230  return bitset_.test_set(get_index(loc), true) == false;
231  }
232 
233  /**
234  * Marks @a loc as unselected.
235  * @returns true if the location was previously selected.
236  */
237  bool deselect(const map_location& loc)
238  {
239  return bitset_.test_set(get_index(loc), false) == true;
240  }
241 
242  bool selected(const map_location& loc) const
243  {
244  return bitset_.test(get_index(loc));
245  }
246 
247  void select_all()
248  {
249  bitset_.set();
250  }
251 
253  {
254  bitset_.reset();
255  }
256 
257  void invert()
258  {
259  bitset_.flip();
260  }
261 
263  {
264  auto res = selection_mask{*this};
265  res.invert();
266  return res;
267  }
268 
269  static std::set<map_location> get_locations(const selection_mask& mask)
270  {
271  std::set<map_location> res;
272 
273  for(std::size_t i = 0; i < mask.bitset_.size(); ++i) {
274  if(mask.bitset_.test(i)) {
275  res.emplace(mask.get_location(i));
276  }
277  }
278 
279  return res;
280  }
281 
282  /** Read-only access to the underlying bitset. */
283  const boost::dynamic_bitset<uint64_t>& mask() const
284  {
285  return bitset_;
286  }
287 
288  private:
289  /** Indexes @a loc to its corresponding bitflag using row-major ordering. */
290  std::size_t get_index(const map_location& loc) const
291  {
292  return static_cast<std::size_t>(loc.wml_y()) * stride_ + loc.wml_x();
293  }
294 
295  /** Gets the corresponding map_location for bit index @a i. */
296  map_location get_location(std::size_t i) const
297  {
298  auto pos = std::div(i, stride_);
299  return {pos.rem, pos.quot, wml_loc{}};
300  }
301 
302  boost::dynamic_bitset<uint64_t> bitset_;
303 
304  int stride_{0};
305  int height_{0};
306  };
307 
308  /**
309  * The selected hexes
310  */
312 };
313 
314 
315 } //end namespace editor
map_location loc
Definition: move.cpp:172
Sort-of-Singleton that many classes, both GUI and non-GUI, use to access the game data.
Definition: display.hpp:88
selection_mask(const gamemap_base &map)
Definition: editor_map.hpp:217
boost::dynamic_bitset< uint64_t > bitset_
Definition: editor_map.hpp:302
static std::set< map_location > get_locations(const selection_mask &mask)
Definition: editor_map.hpp:269
bool select(const map_location &loc)
Marks loc as selected.
Definition: editor_map.hpp:228
const boost::dynamic_bitset< uint64_t > & mask() const
Read-only access to the underlying bitset.
Definition: editor_map.hpp:283
selection_mask inverted() const
Definition: editor_map.hpp:262
map_location get_location(std::size_t i) const
Gets the corresponding map_location for bit index i.
Definition: editor_map.hpp:296
bool selected(const map_location &loc) const
Definition: editor_map.hpp:242
bool deselect(const map_location &loc)
Marks loc as unselected.
Definition: editor_map.hpp:237
std::size_t get_index(const map_location &loc) const
Indexes loc to its corresponding bitflag using row-major ordering.
Definition: editor_map.hpp:290
This class adds extra editor-specific functionality to a normal gamemap.
Definition: editor_map.hpp:70
void shrink_left(int count)
Definition: editor_map.cpp:364
bool everything_selected() const
Definition: editor_map.cpp:170
bool add_to_selection(const map_location &loc)
Add a location to the selection.
Definition: editor_map.cpp:127
bool anything_selected() const
Definition: editor_map.cpp:175
void shrink_top(int count)
Definition: editor_map.cpp:378
void expand_left(int count, const t_translation::terrain_code &filler)
Definition: editor_map.cpp:302
selection_mask selection_
The selected hexes.
Definition: editor_map.hpp:311
std::set< map_location > set_starting_position_labels(display &disp)
Set labels for staring positions in the given display object.
Definition: editor_map.cpp:100
void shrink_bottom(int count)
Definition: editor_map.cpp:392
static editor_map from_string(std::string_view data)
Wrapper around editor_map(cfg, data) that catches possible exceptions and wraps them in a editor_map_...
Definition: editor_map.cpp:54
void invert_selection()
Invert the selection, i.e.
Definition: editor_map.cpp:160
void shrink_right(int count)
Definition: editor_map.cpp:350
void select_all()
Select all map hexes.
Definition: editor_map.cpp:165
bool same_size_as(const gamemap &other) const
A precondition to several map operations.
Definition: editor_map.cpp:280
gamemap mask_to(const gamemap &target) const
A sort-of diff operation returning a mask that, when applied to the current editor_map,...
Definition: editor_map.cpp:263
std::set< map_location > selection() const
Return the selection set.
Definition: editor_map.cpp:140
bool nothing_selected() const
Definition: editor_map.cpp:180
void expand_right(int count, const t_translation::terrain_code &filler)
Definition: editor_map.cpp:286
bool in_selection(const map_location &loc) const
Definition: editor_map.cpp:122
bool remove_from_selection(const map_location &loc)
Remove a location to the selection.
Definition: editor_map.cpp:150
void expand_top(int count, const t_translation::terrain_code &filler)
Definition: editor_map.cpp:318
void set_selection(const std::set< map_location > &area)
Select the given area.
Definition: editor_map.cpp:132
std::set< map_location > get_contiguous_terrain_tiles(const map_location &start) const
Get a contiguous set of tiles having the same terrain as the starting location.
Definition: editor_map.cpp:79
void resize(int width, int height, int x_offset, int y_offset, const t_translation::terrain_code &filler=t_translation::NONE_TERRAIN)
Resize the map.
Definition: editor_map.cpp:190
std::set< map_location > selection_inverse() const
Returns a set of all hexes not currently selected.
Definition: editor_map.cpp:145
editor_map()
Empty map constructor.
Definition: editor_map.cpp:42
void clear_selection()
Clear the selection.
Definition: editor_map.cpp:155
void expand_bottom(int count, const t_translation::terrain_code &filler)
Definition: editor_map.cpp:334
std::size_t num_selected() const
Definition: editor_map.cpp:185
int total_area() const
Total square area of the map, including borders.
Definition: map.hpp:65
int total_width() const
Real width of the map, including borders.
Definition: map.hpp:59
int total_height() const
Real height of the map, including borders.
Definition: map.hpp:62
Encapsulates the map of the game.
Definition: map.hpp:176
Main (common) editor header.
std::size_t i
Definition: function.cpp:1032
Manage the empty-palette in the editor.
Definition: action.cpp:31
editor_map_load_exception wrap_exc(const char *type, const std::string &e_msg, const std::string &filename)
Exception wrapping utility.
Definition: editor_map.cpp:30
EXIT_STATUS start(bool clear_id, const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
constexpr terrain_code NONE_TERRAIN
Definition: translation.hpp:58
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
std::string_view data
Definition: picture.cpp:188
std::string filename
Filename.
editor_map_load_exception(const std::string &fn, const std::string &msg)
Definition: editor_map.hpp:43
editor_map_save_exception(const std::string &msg)
Definition: editor_map.hpp:53
Encapsulates the map of the game.
Definition: location.hpp:46
int wml_y() const
Definition: location.hpp:187
int wml_x() const
Definition: location.hpp:186
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:49