The Battle for Wesnoth  1.15.12+dev
action.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2018 by Tomasz Sniatowski <kailoran@gmail.com>
3  Part of the Battle for Wesnoth Project https://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 
15 /**
16  * @file
17  * Editor action classes
18  */
19 #define GETTEXT_DOMAIN "wesnoth-editor"
20 
21 #include "editor/action/action.hpp"
22 
24 #include "gettext.hpp"
25 #include "random.hpp"
26 
27 #include <memory>
28 
29 namespace editor
30 {
33 
35  : id_(next_id_++)
36 {
38 
39 #ifdef EDITOR_DEBUG_ACTION_LIFETIME
40  LOG_ED << "Action " << std::setw(2) << id_ << " ctor " << this << " (count is " << instance_count << "\n";
41 #endif
42 }
43 
45 {
47 
48 #ifdef EDITOR_DEBUG_ACTION_LIFETIME
49  LOG_ED << "Action " << std::setw(2) << id_ << " dtor " << this << " (count is " << instance_count << "\n";
50 #endif
51 }
52 
54 {
55  return 1;
56 }
57 
58 std::string editor_action::get_description() const
59 {
60  return "Unknown action";
61 }
62 
63 std::unique_ptr<editor_action> editor_action::perform(map_context& mc) const
64 {
65  auto undo = std::make_unique<editor_action_whole_map>(mc.map());
67  return undo;
68 }
69 
70 IMPLEMENT_ACTION(whole_map)
71 
73 {
74  mc.set_map(m_);
75 }
76 
78  : editor_action()
79  , actions_()
80 {
81  for(const auto& a : other.actions_) {
82  actions_.push_back(a->clone());
83  }
84 }
85 
87 {
88  if(this == &other) {
89  return *this;
90  }
91 
92  actions_.clear();
93 
94  for(const auto& a : other.actions_) {
95  actions_.push_back(a->clone());
96  }
97 
98  return *this;
99 }
100 
101 IMPLEMENT_ACTION(chain)
102 
104 {
105  int count = 0;
106  for(const auto& a : actions_) {
107  if(a) {
108  count += a->action_count();
109  }
110  }
111 
112  return count;
113 }
114 
115 void editor_action_chain::append_action(std::unique_ptr<editor_action> a)
116 {
117  actions_.push_back(std::move(a));
118 }
119 
120 void editor_action_chain::prepend_action(std::unique_ptr<editor_action> a)
121 {
122  actions_.push_front(std::move(a));
123 }
124 
126 {
127  return actions_.empty();
128 }
129 
130 std::unique_ptr<editor_action> editor_action_chain::pop_last_action()
131 {
132  if(empty()) {
133  throw editor_action_exception("pop_last_action requested on an empty action_chain");
134  }
135 
136  auto last = std::move(actions_.back());
137  actions_.pop_back();
138  return last;
139 }
140 
141 std::unique_ptr<editor_action> editor_action_chain::pop_first_action()
142 {
143  if(empty()) {
144  throw editor_action_exception("pop_first_action requested on an empty action_chain");
145  }
146 
147  auto first = std::move(actions_.front());
148  actions_.pop_front();
149  return first;
150 }
151 
152 std::unique_ptr<editor_action> editor_action_chain::perform(map_context& mc) const
153 {
154  auto undo = std::make_unique<editor_action_chain>();
155  for(auto& a : actions_) {
156  if(a != nullptr) {
157  undo->append_action(a->perform(mc));
158  }
159  }
160 
161  std::reverse(undo->actions_.begin(), undo->actions_.end());
162  return undo;
163 }
165 {
166  for(const auto& a : actions_) {
167  if(a != nullptr) {
168  a->perform_without_undo(mc);
169  }
170  }
171 }
172 
173 void editor_action_area::extend(const editor_map& /*map*/, const std::set<map_location>& locs)
174 {
175  area_.insert(locs.begin(), locs.end());
176 }
177 
178 IMPLEMENT_ACTION(paste)
179 
180 void editor_action_paste::extend(const editor_map& map, const std::set<map_location>& locs)
181 {
182  paste_.add_tiles(map, locs);
183 }
184 
185 std::unique_ptr<editor_action> editor_action_paste::perform(map_context& mc) const
186 {
187  map_fragment mf(mc.map(), paste_.get_offset_area(offset_));
188  auto undo = std::make_unique<editor_action_paste>(mf);
189 
191  return undo;
192 }
193 
195 {
196  paste_.paste_into(mc.map(), offset_);
197  mc.add_changed_location(paste_.get_offset_area(offset_));
199 }
200 
201 IMPLEMENT_ACTION(paint_area)
202 
204 {
205  map_fragment mf(mc.map(), area_);
206  auto undo = std::make_unique<editor_action_paste>(mf);
207 
209  return undo;
210 }
211 
213 {
214  mc.draw_terrain(t_, area_, one_layer_);
216 }
217 
218 IMPLEMENT_ACTION(fill)
219 
221 {
222  std::set<map_location> to_fill = mc.map().get_contiguous_terrain_tiles(loc_);
223  auto undo = std::make_unique<editor_action_paint_area>(to_fill, mc.map().get_terrain(loc_));
224 
225  mc.draw_terrain(t_, to_fill, one_layer_);
226  mc.set_needs_terrain_rebuild();
227 
228  return undo;
229 }
230 
232 {
233  std::set<map_location> to_fill = mc.map().get_contiguous_terrain_tiles(loc_);
234  mc.draw_terrain(t_, to_fill, one_layer_);
236 }
237 
238 IMPLEMENT_ACTION(starting_position)
239 
241 {
242  std::unique_ptr<editor_action> undo;
243 
244  const std::string* old_loc_id = mc.map().is_special_location(loc_);
245  map_location old_loc = mc.map().special_location(loc_id_);
246 
247  if(old_loc_id != nullptr) {
248  // If another player was starting at the location, we actually perform two actions, so the undo is an
249  // action_chain.
250  auto undo_chain = std::make_unique<editor_action_chain>();
251 
252  undo_chain->append_action(std::make_unique<editor_action_starting_position>(loc_, *old_loc_id));
253  undo_chain->append_action(std::make_unique<editor_action_starting_position>(old_loc, loc_id_));
254 
255  undo = std::move(undo_chain);
256 
257  LOG_ED << "ssp actual: " << *old_loc_id << " to " << map_location() << "\n";
258 
259  mc.map().set_special_location(*old_loc_id, map_location());
260  } else {
261  undo = std::make_unique<editor_action_starting_position>(old_loc, loc_id_);
262  }
263 
264  LOG_ED << "ssp actual: " << loc_id_ << " to " << loc_ << "\n";
265 
266  mc.map().set_special_location(loc_id_, loc_);
267  mc.set_needs_labels_reset();
268 
269  return undo;
270 }
271 
273 {
274  const std::string* old_id = mc.map().is_special_location(loc_);
275  if(old_id != nullptr) {
276  mc.map().set_special_location(*old_id, map_location());
277  }
278 
279  mc.map().set_special_location(loc_id_, loc_);
281 }
282 
283 IMPLEMENT_ACTION(resize_map)
284 
286 {
287  mc.map().resize(x_size_, y_size_, x_offset_, y_offset_, fill_);
288  mc.set_needs_reload();
289 }
290 
291 IMPLEMENT_ACTION(apply_mask)
292 
294 {
295  mc.map().overlay(mask_, {0, 0, wml_loc()});
296  mc.set_needs_terrain_rebuild();
297 }
298 
299 IMPLEMENT_ACTION(create_mask)
300 
302 {
303  mc.set_map(editor_map(mc.map().mask_to(target_)));
304  mc.set_needs_terrain_rebuild();
305 }
306 
307 IMPLEMENT_ACTION(shuffle_area)
308 
310 {
311  map_fragment mf(mc.map(), area_);
312  auto undo = std::make_unique<editor_action_paste>(mf);
314  return undo;
315 }
316 
318 {
319  std::vector<map_location> shuffle;
320 
321  std::copy(area_.begin(), area_.end(), std::inserter(shuffle, shuffle.begin()));
322  std::shuffle(shuffle.begin(), shuffle.end(), randomness::rng::default_instance());
323 
324  std::vector<map_location>::const_iterator shuffle_it = shuffle.begin();
325  std::set<map_location>::const_iterator orig_it = area_.begin();
326 
327  while(orig_it != area_.end()) {
328  t_translation::terrain_code tmp = mc.map().get_terrain(*orig_it);
329 
330  mc.draw_terrain(mc.map().get_terrain(*shuffle_it), *orig_it);
331  mc.draw_terrain(tmp, *shuffle_it);
332 
333  ++orig_it;
334  ++shuffle_it;
335  }
336 
338 }
339 
340 } // end namespace editor
void add_changed_location(const map_location &loc)
Randomize terrain in an area.
Definition: action.hpp:397
std::unique_ptr< editor_action > pop_last_action()
Remove the last added action and return it, transferring ownership to the caller. ...
Definition: action.cpp:130
A map fragment – a collection of locations and information abut them.
void perform_without_undo(map_context &m) const override
Perform all the actions in order.
Definition: action.cpp:164
void set(CURSOR_TYPE type)
Use the default parameter to reset cursors.
Definition: cursor.cpp:175
const std::string * is_special_location(const map_location &loc) const
returns the name of the special location at position loc, null if no such location exists...
Definition: map.cpp:352
void perform_without_undo(map_context &mc) const override
Perform the action without creating an undo action.
Definition: action.cpp:231
#define a
std::unique_ptr< editor_action > pop_first_action()
Remove the first added action and return it, transferring ownership to the caller.
Definition: action.cpp:141
#define LOG_ED
void extend(const editor_map &map, const std::set< map_location > &locs) override
The crux of the extendable contract.
Definition: action.cpp:173
void draw_terrain(const t_translation::terrain_code &terrain, const map_location &loc, bool one_layer_only=false)
Draw a terrain on a single location on the map.
editor_action_chain & operator=(const editor_action_chain &other)
Definition: action.cpp:86
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
Paste a map fragment into the map.
Definition: action.hpp:241
STL namespace.
Container action wrapping several actions into one.
Definition: action.hpp:86
void perform_without_undo(map_context &mc) const override
Perform the action without creating an undo action.
Definition: action.cpp:212
Replace contents of the entire map, Useful as a fallback undo method when something else would be imp...
Definition: action.hpp:37
Set starting position action, sets location ids (both for starting locations and for non-starting loc...
Definition: action.hpp:311
void append_action(std::unique_ptr< editor_action > a)
Add an action at the end of the chain.
Definition: action.cpp:115
void set_special_location(const std::string &id, const map_location &loc)
Definition: map.cpp:358
map_location loc_
std::deque< std::unique_ptr< editor_action > > actions_
The action pointers owned by this action chain.
Definition: action.hpp:168
terrain_code get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
Definition: map.cpp:297
void prepend_action(std::unique_ptr< editor_action > a)
Add an action at the beginning of the chain.
Definition: action.cpp:120
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:113
Editor action classes.
int action_count() const override
Go through the chain and add up all the action counts.
Definition: action.cpp:103
std::unique_ptr< editor_action > perform(map_context &m) const override
Perform all the actions in order and create a undo action chain.
Definition: action.cpp:152
Manage the empty-palette in the editor.
Definition: action.cpp:29
Paint the same terrain on a number of locations on the map.
Definition: action.hpp:264
void set_needs_terrain_rebuild(bool value=true)
Setter for the terrain rebuild flag.
Encapsulates the map of the game.
Definition: location.hpp:37
virtual ~editor_action()
Definition: action.cpp:44
virtual int action_count() const
Definition: action.cpp:53
This class adds extra editor-specific functionality to a normal gamemap.
Definition: editor_map.hpp:69
void perform_without_undo(map_context &mc) const override
Perform the action without creating an undo action.
Definition: action.cpp:317
static int instance_count_
void perform_without_undo(map_context &mc) const override
Perform the action without creating an undo action.
Definition: action.cpp:194
Base class for all editor actions.
Definition: action_base.hpp:40
std::unique_ptr< editor_action > perform(map_context &mc) const override
Perform the action, returning an undo action that, when performed, shall reverse any effects of this ...
Definition: action.cpp:185
This class wraps around a map to provide a concise interface for the editor to work with...
Definition: map_context.hpp:59
virtual std::unique_ptr< editor_action > perform(map_context &) const
Perform the action, returning an undo action that, when performed, shall reverse any effects of this ...
Definition: action.cpp:63
virtual const editor_map & map() const override
Const map accessor.
void set_needs_labels_reset(bool value=true)
Setter for the labels reset flag.
#define IMPLEMENT_ACTION(id)
Helper macro to implement common action methods.
editor_action_chain()
Create an empty action chain.
Definition: action.hpp:92
virtual void perform_without_undo(map_context &) const =0
Perform the action without creating an undo action.
virtual std::string get_description() const
A textual description of the action.
Definition: action.cpp:58
static void reverse(lua_State *L, StkId from, StkId to)
Definition: lapi.cpp:203
std::vector< game_tip > shuffle(const std::vector< game_tip > &tips)
Shuffles the tips.
Definition: tips.cpp:46
static rng & default_instance()
Definition: random.cpp:73
void perform_without_undo(map_context &mc) const override
Perform the action without creating an undo action.
Definition: action.cpp:272