The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
editor_map.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2016 by Tomasz Sniatowski <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 #define GETTEXT_DOMAIN "wesnoth-editor"
15 
17 #include "editor_map.hpp"
18 #include "formula/string_utils.hpp"
19 
20 #include "display.hpp"
21 #include "formula/string_utils.hpp"
22 #include "gettext.hpp"
23 #include "map/exception.hpp"
24 #include "map/label.hpp"
25 #include "wml_exception.hpp"
26 
27 #include "terrain/type_data.hpp"
28 
29 #include <boost/make_shared.hpp>
30 #include <boost/shared_ptr.hpp>
31 
32 namespace editor {
33 
34 editor_map_load_exception wrap_exc(const char* type, const std::string& e_msg, const std::string& filename)
35 {
36  WRN_ED << type << " error in load map " << filename << ": " << e_msg << std::endl;
37  utils::string_map symbols;
38  symbols["type"] = type;
39  const char* error_msg = "There was an error ($type) while loading the file:";
40  std::string msg = vgettext(error_msg, symbols);
41  msg += "\n";
42  msg += e_msg;
43  return editor_map_load_exception(filename, msg);
44 }
45 
46 editor_map::editor_map(const config& terrain_cfg)
47  : gamemap(boost::make_shared<terrain_type_data>(terrain_cfg), "")
48  , selection_()
49 {
50 }
51 
52 editor_map::editor_map(const config& terrain_cfg, const std::string& data)
53  : gamemap(boost::make_shared<terrain_type_data>(terrain_cfg), data)
54  , selection_()
55 {
56  sanity_check();
57 }
58 
60 {
61  try {
62  return editor_map(terrain_cfg, data);
63  } catch (incorrect_map_format_error& e) {
64  throw wrap_exc("format", e.message, "");
65  } catch (twml_exception& e) {
66  throw wrap_exc("wml", e.user_message, "");
67  } catch (config::error& e) {
68  throw wrap_exc("config", e.message, "");
69  }
70 }
71 
72 editor_map::editor_map(const config& terrain_cfg, size_t width, size_t height, const t_translation::t_terrain & filler)
73  : gamemap(boost::make_shared<terrain_type_data>(terrain_cfg), t_translation::write_game_map(
74  t_translation::t_map(width + 2, t_translation::t_list(height + 2, filler))))
75  , selection_()
76 {
77  sanity_check();
78 }
79 
81  : gamemap(map)
82  , selection_()
83 {
84  sanity_check();
85 }
86 
88 {
89 }
90 
92 {
93  int errors = 0;
94  if (total_width() != static_cast<int>(tiles_.size())) {
95  ERR_ED << "total_width is " << total_width() << " but tiles_.size() is " << tiles_.size() << std::endl;
96  ++errors;
97  }
98  if (total_height() != static_cast<int>(tiles_[0].size())) {
99  ERR_ED << "total_height is " << total_height() << " but tiles_[0].size() is " << tiles_.size() << std::endl;
100  ++errors;
101  }
102  if (w() + 2 * border_size() != total_width()) {
103  ERR_ED << "h is " << h_ << " and border_size is " << border_size() << " but total_width is " << total_width() << std::endl;
104  ++errors;
105  }
106  if (h() + 2 * border_size() != total_height()) {
107  ERR_ED << "w is " << w_ << " and border_size is " << border_size() << " but total_height is " << total_height() << std::endl;
108  ++errors;
109  }
110  for (size_t i = 1; i < tiles_.size(); ++i) {
111  if (tiles_[i].size() != tiles_[0].size()) {
112  ERR_ED << "tiles_[ " << i << "] has size() " << tiles_[i].size() << " but tiles[0] has size() " << tiles_[0].size() << std::endl;
113  ++errors;
114  }
115  }
116  for (const map_location& loc : selection_) {
117  if (!on_board_with_border(loc)) {
118  ERR_ED << "Off-map tile in selection: " << loc << std::endl;
119  }
120  }
121  if (errors) {
123  }
124 }
125 
126 std::set<map_location> editor_map::get_contiguous_terrain_tiles(const map_location& start) const
127 {
129  std::set<map_location> result;
130  std::deque<map_location> queue;
131  result.insert(start);
132  queue.push_back(start);
133  //this is basically a breadth-first search along adjacent hexes
134  do {
135  map_location adj[6];
136  get_adjacent_tiles(queue.front(), adj);
137  for (int i = 0; i < 6; ++i) {
138  if (on_board_with_border(adj[i]) && get_terrain(adj[i]) == terrain
139  && result.find(adj[i]) == result.end()) {
140  result.insert(adj[i]);
141  queue.push_back(adj[i]);
142  }
143  }
144  queue.pop_front();
145  } while (!queue.empty());
146  return result;
147 }
148 
150 {
151  std::set<map_location> label_locs;
152  std::string label;
153 
154 
155  for (const auto& pair : starting_positions_.left) {
156 
157  bool is_number = std::find_if(pair.first.begin(), pair.first.end(), [](char c) { return !std::isdigit(c); }) == pair.first.end();
158  if (is_number) {
159  label = vgettext("Player $side_num", utils::string_map{ { "side_num", pair.first } });
160  }
161  else {
162  label = pair.first;
163  }
164 
165  disp.labels().set_label(map_location(pair.second.x, pair.second.y), label);
166  label_locs.insert(map_location(pair.second.x, pair.second.y));
167  }
168  return label_locs;
169 }
170 
172 {
173  return selection_.find(loc) != selection_.end();
174 }
175 
177 {
178  return on_board_with_border(loc) ? selection_.insert(loc).second : false;
179 }
180 
181 bool editor_map::set_selection(const std::set<map_location>& area)
182 {
183  clear_selection();
184  for (const map_location& loc : area) {
185  if (!add_to_selection(loc))
186  return false;
187  }
188  return true;
189 }
190 
192 {
193  return selection_.erase(loc) != 0;
194 }
195 
197 {
198  selection_.clear();
199 }
200 
202 {
203  std::set<map_location> new_selection;
204  for (int x = -1; x < w() + 1; ++x) {
205  for (int y = -1; y < h() + 1; ++y) {
206  if (selection_.find(map_location(x, y)) == selection_.end()) {
207  new_selection.insert(map_location(x, y));
208  }
209  }
210  }
211  selection_.swap(new_selection);
212 }
213 
215 {
216  clear_selection();
218 }
219 
221 {
222  LOG_ED << selection_.size() << " " << total_width() * total_height() << "\n";
223  return static_cast<int>(selection_.size()) == total_width() * total_height();
224 }
225 
226 void editor_map::resize(int width, int height, int x_offset, int y_offset,
227  const t_translation::t_terrain & filler)
228 {
229  int old_w = w();
230  int old_h = h();
231  if (old_w == width && old_h == height && x_offset == 0 && y_offset == 0) {
232  return;
233  }
234 
235  // Determine the amount of resizing is required
236  const int left_resize = -x_offset;
237  const int right_resize = (width - old_w) + x_offset;
238  const int top_resize = -y_offset;
239  const int bottom_resize = (height - old_h) + y_offset;
240 
241  if(right_resize > 0) {
242  expand_right(right_resize, filler);
243  } else if(right_resize < 0) {
244  shrink_right(-right_resize);
245  }
246  if(bottom_resize > 0) {
247  expand_bottom(bottom_resize, filler);
248  } else if(bottom_resize < 0) {
249  shrink_bottom(-bottom_resize);
250  }
251  if(left_resize > 0) {
252  expand_left(left_resize, filler);
253  } else if(left_resize < 0) {
254  shrink_left(-left_resize);
255  }
256  if(top_resize > 0) {
257  expand_top(top_resize, filler);
258  } else if(top_resize < 0) {
259  shrink_top(-top_resize);
260  }
261 
262  // fix the starting positions
263  if(x_offset || y_offset) {
264  for (auto it = starting_positions_.left.begin(); it != starting_positions_.left.end(); ++it) {
265  starting_positions_.left.modify_data(it, [=](t_translation::coordinate & loc) { loc.x -= x_offset; loc.y -= y_offset;});
266  }
267  }
268  sanity_check();
269 }
270 
272 {
273  if (target.w() != w() || target.h() != h()) {
274  throw editor_action_exception(_("The size of the target map is different from the current map"));
275  }
276  gamemap mask(target);
277  map_location iter;
278  for (iter.x = -border_size(); iter.x < w() + border_size(); ++iter.x) {
279  for (iter.y = -border_size(); iter.y < h() + border_size(); ++iter.y) {
280  if (target.get_terrain(iter) == get_terrain(iter)) {
282  }
283  }
284  }
285  return mask;
286 }
287 
288 bool editor_map::same_size_as(const gamemap& other) const
289 {
290  return h() == other.h()
291  && w() == other.w();
292 }
293 
295 {
296  int h = tiles_[1].size();
298  for (int y = 0; y < h; ++y) {
299  column[y] =
300  filler != t_translation::NONE_TERRAIN ?
301  filler :
302  tiles_[x][y];
303  assert(column[y] != t_translation::NONE_TERRAIN);
304  }
305  return column;
306 }
307 
309 {
310  int w = tiles_.size();
311  for (int x = 0; x < count; ++x) {
312  tiles_.push_back(clone_column(w - 1 , filler));
313  }
314  w_ += count;
315  total_width_ += count;
316 }
317 
319 {
320  for (int x = 0; x < count; ++x) {
321  tiles_.insert(tiles_.begin(), 1, clone_column(0, filler));
323  }
324  w_ += count;
325  total_width_ += count;
326 }
327 
329 {
330  for (int y = 0; y < count; ++y) {
331  for (int x = 0; x < static_cast<int>(tiles_.size()); ++x) {
333  filler != t_translation::NONE_TERRAIN ?
334  filler :
335  tiles_[x][0];
336  assert(terrain != t_translation::NONE_TERRAIN);
337  tiles_[x].insert(tiles_[x].begin(), 1, terrain);
339  }
340  }
341  h_ += count;
342  total_height_ += count;
343 }
344 
346 {
347  int h = tiles_[1].size();
348  for (int y = 0; y < count; ++y) {
349  for (int x = 0; x < static_cast<int>(tiles_.size()); ++x) {
351  filler != t_translation::NONE_TERRAIN ?
352  filler :
353  tiles_[x][h - 1];
354  assert(terrain != t_translation::NONE_TERRAIN);
355  tiles_[x].push_back(terrain);
356  }
357  }
358  h_ += count;
359  total_height_ += count;
360 }
361 
363 {
364  if(count < 0 || count > static_cast<int>(tiles_.size())) {
366  }
367  tiles_.resize(tiles_.size() - count);
368  w_ -= count;
369  total_width_ -= count;
370 }
371 
373 {
374  if(count < 0 || count > static_cast<int>(tiles_.size())) {
376  }
377  tiles_.erase(tiles_.begin(), tiles_.begin() + count);
378  w_ -= count;
379  total_width_ -= count;
380 }
381 
383 {
384  if(count < 0 || count > static_cast<int>(tiles_[0].size())) {
386  }
387  for (size_t x = 0; x < tiles_.size(); ++x) {
388  tiles_[x].erase(tiles_[x].begin(), tiles_[x].begin() + count);
389  }
390  h_ -= count;
391  total_height_ -= count;
392 }
393 
395 {
396  if(count < 0 || count > static_cast<int>(tiles_[0].size())) {
398  }
399  for (size_t x = 0; x < tiles_.size(); ++x) {
400  tiles_[x].erase(tiles_[x].end() - count, tiles_[x].end());
401  }
402  h_ -= count;
403  total_height_ -= count;
404 }
405 
406 
407 
408 } //end namespace editor
int total_width() const
Real width of the map, including borders.
Definition: map.hpp:114
bool on_board_with_border(const map_location &loc) const
Definition: map.cpp:472
Contains an x and y coordinate used for starting positions in maps.
Definition: translation.hpp:97
void resize(int width, int height, int x_offset, int y_offset, const t_translation::t_terrain &filler=t_translation::NONE_TERRAIN)
Resize the map.
Definition: editor_map.cpp:226
std::set< map_location > selection_
The selected hexes.
Definition: editor_map.hpp:207
std::string write_game_map(const t_map &map, const tstarting_positions &starting_positions, coordinate border_offset)
Write a gamemap in to a vector string.
const GLfloat * c
Definition: glew.h:12741
std::set< map_location > set_starting_position_labels(display &disp)
Set labels for staring positions in the given display object.
Definition: editor_map.cpp:149
void shrink_top(int count)
Definition: editor_map.cpp:382
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
GLuint GLuint GLsizei GLenum type
Definition: glew.h:1221
const t_terrain NONE_TERRAIN
Definition: translation.hpp:56
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
Definition: location.hpp:274
#define LOG_ED
void sanity_check()
Debugging aid.
Definition: editor_map.cpp:91
Base class for editor actions.
const t_terrain FOGGED
GLint GLint GLint GLint GLint GLint y
Definition: glew.h:1220
void expand_top(int count, const t_translation::t_terrain &filler)
Definition: editor_map.cpp:328
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
Definition: glew.h:1347
void expand_left(int count, const t_translation::t_terrain &filler)
Definition: editor_map.cpp:318
t_translation::t_list clone_column(int x, const t_translation::t_terrain &filler)
Definition: editor_map.cpp:294
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:126
~editor_map()
editor_map destructor
Definition: editor_map.cpp:87
std::string user_message
The message for the user explaining what went wrong.
int total_height() const
Real height of the map, including borders.
Definition: map.hpp:117
const terrain_label * set_label(const map_location &loc, const t_string &text, const int creator=-1, const std::string &team="", const SDL_Color color=font::NORMAL_COLOR, const bool visible_in_fog=true, const bool visible_in_shroud=false, const bool immutable=false, const std::string &category="", const t_string &tooltip="")
Definition: label.cpp:145
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:34
#define WRN_ED
std::vector< std::vector< t_terrain > > t_map
Definition: translation.hpp:76
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:82
GLuint GLuint end
Definition: glew.h:1221
GLuint64EXT * result
Definition: glew.h:10727
std::map< std::string, t_string > string_map
bool everything_selected() const
Definition: editor_map.cpp:220
gamemap mask_to(const gamemap &target) const
A sort-of diff operation returning a mask that, when applied to the current editor_map, will transform it into the target map.
Definition: editor_map.cpp:271
bool in_selection(const map_location &loc) const
Definition: editor_map.cpp:171
void invert_selection()
Invert the selection, i.e.
Definition: editor_map.cpp:201
GLubyte GLubyte GLubyte GLubyte w
Definition: glew.h:1858
bool same_size_as(const gamemap &other) const
A precondition to several map operations.
Definition: editor_map.cpp:288
int w() const
Effective map width.
Definition: map.hpp:105
GLuint start
Definition: glew.h:1221
Encapsulates the map of the game.
Definition: map.hpp:37
int border_size() const
Size of the map border.
Definition: map.hpp:111
map_display and display: classes which take care of displaying the map and game-data on the screen...
int w_
Sizes of the map area.
Definition: map.hpp:245
Manage the empty-palette in the editor.
Definition: action.cpp:28
void shrink_left(int count)
Definition: editor_map.cpp:372
static const ::config * terrain
The terrain used to create the cache.
Definition: minimap.cpp:135
GLuint GLuint GLsizei count
Definition: glew.h:1221
void expand_bottom(int count, const t_translation::t_terrain &filler)
Definition: editor_map.cpp:345
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:47
bool add_to_selection(const map_location &loc)
Add a location to the selection.
Definition: editor_map.cpp:176
Encapsulates the map of the game.
Definition: location.hpp:38
GLenum GLenum GLvoid GLvoid * column
Definition: glew.h:3805
static editor_map from_string(const config &terrain_cfg, const std::string &data)
Wrapper around editor_map(cfg, data) that catches possible exceptions and wraps them in a editor_map_...
Definition: editor_map.cpp:59
void expand_right(int count, const t_translation::t_terrain &filler)
Definition: editor_map.cpp:308
This class adds extra editor-specific functionality to a normal gamemap.
Definition: editor_map.hpp:70
int h() const
Effective map height.
Definition: map.hpp:108
editor_map(const config &terrain_cfg)
Empty map constructor.
Definition: editor_map.cpp:46
void clear_selection()
Clear the selection.
Definition: editor_map.cpp:196
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:5910
size_t i
Definition: function.cpp:1057
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:112
GLint GLint GLint GLint GLint x
Definition: glew.h:1220
void set_terrain(const map_location &loc, const t_translation::t_terrain &terrain, const terrain_type_data::tmerge_mode mode=terrain_type_data::BOTH, bool replace_if_failed=false)
Clobbers over the terrain at location 'loc', with the given terrain.
Definition: map.cpp:479
std::string vgettext(const char *msgid, const utils::string_map &symbols)
GLint GLint GLint GLint GLint GLint GLsizei GLsizei height
Definition: glew.h:1220
t_translation::t_terrain get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
Definition: map.cpp:341
GLsizeiptr size
Definition: glew.h:1649
void select_all()
Select all map hexes.
Definition: editor_map.cpp:214
tstarting_positions starting_positions_
The size of the starting positions array is MAX_PLAYERS + 1, because the positions themselves are num...
Definition: map.hpp:216
#define ERR_ED
int total_width_
Sizes of the map including the borders.
Definition: map.hpp:249
std::string message
Definition: exceptions.hpp:29
#define c
Definition: glew.h:12743
GLint GLint GLint GLint GLint GLint GLsizei width
Definition: glew.h:1220
map_labels & labels()
Definition: display.cpp:2773
#define e
#define mask(n)
Definition: lbitlib.cpp:28
t_translation::t_map tiles_
Definition: map.hpp:210
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
Helper class, don't construct this directly.
int h_
Definition: map.hpp:246
void shrink_right(int count)
Definition: editor_map.cpp:362
GLsizei const GLcharARB ** string
Definition: glew.h:4503
void clear_border_cache()
Clears the border cache, needed for the editor.
Definition: map.hpp:221
bool set_selection(const std::set< map_location > &area)
Select the given area.
Definition: editor_map.cpp:181
int total_height_
Definition: map.hpp:250
GLenum target
Definition: glew.h:5190
bool remove_from_selection(const map_location &loc)
Remove a location to the selection.
Definition: editor_map.cpp:191
std::vector< t_terrain > t_list
Definition: translation.hpp:75
void shrink_bottom(int count)
Definition: editor_map.cpp:394