The Battle for Wesnoth  1.17.0-dev
map_fragment.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2021
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 #define GETTEXT_DOMAIN "wesnoth-editor"
17 
19 
20 namespace editor {
21 
23  : items_()
24  , area_()
25 {
26 }
27 
28 map_fragment::map_fragment(const gamemap& map, const std::set<map_location>& area)
29  : items_()
30  , area_()
31 {
32  add_tiles(map, area);
33 }
34 
35 void map_fragment::add_tile(const gamemap& map, const map_location& loc)
36 {
37  if (area_.find(loc) == area_.end()) {
38  items_.emplace_back(map, loc);
39  area_.insert(loc);
40  }
41 }
42 
43 void map_fragment::add_tiles(const gamemap& map, const std::set<map_location>& locs)
44 {
45  for (const map_location& loc : locs) {
46  add_tile(map, loc);
47  }
48 }
49 
50 std::set<map_location> map_fragment::get_area() const
51 {
52  return area_;
53 }
54 
55 std::set<map_location> map_fragment::get_offset_area(const map_location& loc) const
56 {
57  std::set<map_location> result;
58  for (const tile_info& i : items_) {
59  result.insert(i.offset.vector_sum(loc));
60  }
61  return result;
62 }
63 
64 void map_fragment::paste_into(gamemap& map, const map_location& loc) const
65 {
66  for (const tile_info& i : items_) {
67  map.set_terrain(i.offset.vector_sum(loc), i.terrain);
68  }
69 }
70 
71 void map_fragment::shift(const map_location& offset)
72 {
73  for (tile_info& ti : items_) {
74  ti.offset.vector_sum_assign(offset);
75  }
76 }
77 
79 {
80  map_location sum(0, 0);
81  for (const tile_info& ti : items_) {
82  sum.vector_sum_assign(ti.offset);
83  }
84  if (items_.size() > 0) {
85  sum.x /= static_cast<int>(items_.size());
86  sum.y /= static_cast<int>(items_.size());
87  }
88  return sum;
89 }
90 
92 {
93  shift(center_of_mass().vector_negation());
94  area_.clear();
95  for (tile_info& ti : items_) {
96  area_.insert(ti.offset);
97  }
98 }
99 
101 {
102  area_.clear();
103  for (tile_info& ti : items_) {
105  int x = ti.offset.x;
106  int y = ti.offset.y;
107  // rotate the X-Y axes to SOUTH/SOUTH_EAST - SOUTH_WEST axes
108  // but if x is odd, simply using x/2 + x/2 will lack a step
109  l = l.get_direction(map_location::SOUTH, (x+is_odd(x))/2);
112  ti.offset = l;
113  area_.insert(l);
114  }
115  if (get_area().size() != items_.size()) {
116  throw editor_exception("Map fragment rotation resulted in duplicate entries");
117  }
118 }
119 
121 {
122  area_.clear();
123  for (tile_info& ti : items_) {
125  int x = ti.offset.x;
126  int y = ti.offset.y;
127  // rotate the X-Y axes to NORTH/NORTH_EAST - SOUTH_EAST axes'
128  // reverse of what the cw rotation does
129  l = l.get_direction(map_location::NORTH, (x-is_odd(x))/2);
132  ti.offset = l;
133  area_.insert(l);
134  }
135  if (get_area().size() != items_.size()) {
136  throw editor_exception("Map fragment rotation resulted in duplicate entries");
137  }
138 }
139 
141 {
142  for (tile_info& ti : items_) {
143  ti.offset.x = -ti.offset.x;
144  }
145  center_by_mass();
146 }
147 
149 {
150  for (tile_info& ti : items_) {
151  ti.offset.y = -ti.offset.y;
152  if (ti.offset.x % 2) {
153  ti.offset.y--;
154  }
155  }
156  center_by_mass();
157 }
158 
159 
161 {
162  return items_.empty();
163 }
164 
165 std::string map_fragment::dump() const
166 {
167  std::stringstream ss;
168  ss << "MF: ";
169  for (const tile_info& ti : items_) {
170  ss << "(" << ti.offset << ")";
171  }
172  ss << " -- ";
173  for (const map_location& loc : area_) {
174  ss << "(" << loc << ")";
175  }
176  return ss.str();
177 }
178 
179 } //end namespace editor
map_location & vector_sum_assign(const map_location &a)
Definition: location.hpp:121
bool is_odd(T num)
Definition: math.hpp:36
std::string dump() const
Debug dump to a string.
void set_terrain(const map_location &loc, const terrain_code &terrain, const terrain_type_data::merge_mode mode=terrain_type_data::BOTH, bool replace_if_failed=false) override
Clobbers over the terrain at location &#39;loc&#39;, with the given terrain.
Definition: map.cpp:397
static const map_location & ZERO()
Definition: location.hpp:75
void flip_horizontal()
Flip the map fragment horizontally.
void rotate_60_ccw()
Rotate the map fragment 60 degrees counter-clockwise around (0,0)
map_location center_of_mass() const
Get the center of the map fragment, mass-wise.
map_location get_direction(DIRECTION dir, unsigned int n=1u) const
Definition: location.cpp:360
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:87
Encapsulates the map of the game.
Definition: map.hpp:171
Manage the empty-palette in the editor.
Definition: action.cpp:30
Encapsulates the map of the game.
Definition: location.hpp:38
std::size_t i
Definition: function.cpp:967
void paste_into(gamemap &map, const map_location &loc) const
Paste the map fragment into the map, treating loc as the (0,0) point (offset).
void flip_vertical()
Flip the map fragment vertically.
void shift(const map_location &offset)
Shift all tiles in the map fragment by the specified offset.
This represents a tile along with information about it, namely the terrain, possibly other informatio...
void add_tiles(const gamemap &map, const std::set< map_location > &loc)
Add many locations and pull their info from the map.
map_fragment()
Create an empty map fragment.
std::set< map_location > get_offset_area(const map_location &offset) const
Get the area covered by this map fragment, shifted by an offset.
std::set< map_location > area_
std::set< map_location > get_area() const
Get the area covered by this map fragment.
std::vector< tile_info > items_
The data of this map_fragment.
void center_by_mass()
Shift the map fragment so it is roughly centered around the (0,0) point, mass-wise.
void add_tile(const gamemap &map, const map_location &loc)
Add a single location and pull its info from the map.
void rotate_60_cw()
Rotate the map fragment 60 degrees clockwise around (0,0)