The Battle for Wesnoth  1.13.10+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
action.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2017 by Tomasz Sniatowski <kailoran@gmail.com>
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 
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 
59 {
60  return "Unknown action";
61 }
62 
64 {
67  return undo.release();
68 }
69 
70 IMPLEMENT_ACTION(whole_map)
71 
72 void editor_action_whole_map::perform_without_undo(map_context& mc) const
73 {
74  mc.set_map(m_);
75 }
76 
78  : editor_action()
79  , actions_()
80 {
81  for(editor_action* a : other.actions_) {
82  actions_.push_back(a->clone());
83  }
84 }
85 
87 {
88  if(this == &other) {
89  return *this;
90  }
91 
92  for(editor_action* a : actions_) {
93  delete a;
94  }
95 
96  actions_.clear();
97 
98  for(editor_action* a : other.actions_) {
99  actions_.push_back(a->clone());
100  }
101 
102  return *this;
103 }
105 {
106  for(editor_action* a : actions_) {
107  delete a;
108  }
109 }
110 
111 IMPLEMENT_ACTION(chain)
112 
113 int editor_action_chain::action_count() const
114 {
115  int count = 0;
116  for(const editor_action* a : actions_) {
117  if(a) {
118  count += a->action_count();
119  }
120  }
121 
122  return count;
123 }
124 
126 {
127  actions_.push_back(a);
128 }
129 
131 {
132  actions_.push_front(a);
133 }
134 
136 {
137  return actions_.empty();
138 }
139 
141 {
142  if(empty()) {
143  throw editor_action_exception("pop_last_action requested on an empty action_chain");
144  }
145 
146  editor_action* last = actions_.back();
147  actions_.pop_back();
148  return last;
149 }
150 
152 {
153  if(empty()) {
154  throw editor_action_exception("pop_first_action requested on an empty action_chain");
155  }
156 
157  editor_action* last = actions_.front();
158  actions_.pop_front();
159  return last;
160 }
161 
163 {
164  std::unique_ptr<editor_action_chain> undo(new editor_action_chain());
165  for(editor_action* a : actions_) {
166  if(a != nullptr) {
167  undo->append_action(a->perform(mc));
168  }
169  }
170 
171  std::reverse(undo->actions_.begin(), undo->actions_.end());
172  return undo.release();
173 }
175 {
176  for(editor_action* a : actions_) {
177  if(a != nullptr) {
178  a->perform_without_undo(mc);
179  }
180  }
181 }
182 
183 void editor_action_area::extend(const editor_map& /*map*/, const std::set<map_location>& locs)
184 {
185  area_.insert(locs.begin(), locs.end());
186 }
187 
188 IMPLEMENT_ACTION(paste)
189 
190 void editor_action_paste::extend(const editor_map& map, const std::set<map_location>& locs)
191 {
192  paste_.add_tiles(map, locs);
193 }
194 
196 {
198  std::unique_ptr<editor_action_paste> undo(new editor_action_paste(mf));
199 
201  return undo.release();
202 }
203 
205 {
209 }
210 
211 IMPLEMENT_ACTION(paint_area)
212 
214 {
215  map_fragment mf(mc.get_map(), area_);
216  std::unique_ptr<editor_action_paste> undo(new editor_action_paste(mf));
217 
218  perform_without_undo(mc);
219  return undo.release();
220 }
221 
223 {
226 }
227 
228 IMPLEMENT_ACTION(fill)
229 
231 {
232  std::set<map_location> to_fill = mc.get_map().get_contiguous_terrain_tiles(loc_);
233  std::unique_ptr<editor_action_paint_area> undo(
234  new editor_action_paint_area(to_fill, mc.get_map().get_terrain(loc_)));
235 
236  mc.draw_terrain(t_, to_fill, one_layer_);
237  mc.set_needs_terrain_rebuild();
238 
239  return undo.release();
240 }
241 
243 {
244  std::set<map_location> to_fill = mc.get_map().get_contiguous_terrain_tiles(loc_);
245  mc.draw_terrain(t_, to_fill, one_layer_);
247 }
248 
249 IMPLEMENT_ACTION(starting_position)
250 
252 {
253  editor_action_ptr undo;
254 
255  const std::string* old_loc_id = mc.get_map().is_starting_position(loc_);
256  map_location old_loc = mc.get_map().special_location(loc_id_);
257 
258  if(old_loc_id != nullptr) {
259  // If another player was starting at the location, we actually perform two actions, so the undo is an
260  // action_chain.
261  editor_action_chain* undo_chain = new editor_action_chain();
262 
263  undo_chain->append_action(new editor_action_starting_position(loc_, *old_loc_id));
264  undo_chain->append_action(new editor_action_starting_position(old_loc, loc_id_));
265 
266  undo.reset(undo_chain);
267 
268  LOG_ED << "ssp actual: " << *old_loc_id << " to " << map_location() << "\n";
269 
270  mc.get_map().set_special_location(*old_loc_id, map_location());
271  } else {
272  undo.reset(new editor_action_starting_position(old_loc, loc_id_));
273  }
274 
275  LOG_ED << "ssp actual: " << loc_id_ << " to " << loc_ << "\n";
276 
277  mc.get_map().set_special_location(loc_id_, loc_);
278  mc.set_needs_labels_reset();
279 
280  return undo.release();
281 }
282 
284 {
285  const std::string* old_id = mc.get_map().is_starting_position(loc_);
286  if(old_id != nullptr) {
287  mc.get_map().set_special_location(*old_id, map_location());
288  }
289 
292 }
293 
294 IMPLEMENT_ACTION(resize_map)
295 
296 void editor_action_resize_map::perform_without_undo(map_context& mc) const
297 {
298  mc.get_map().resize(x_size_, y_size_, x_offset_, y_offset_, fill_);
299  mc.set_needs_reload();
300 }
301 
302 IMPLEMENT_ACTION(apply_mask)
303 
304 void editor_action_apply_mask::perform_without_undo(map_context& mc) const
305 {
306  mc.get_map().overlay(mask_, config(), {0, 0});
307  mc.set_needs_terrain_rebuild();
308 }
309 
310 IMPLEMENT_ACTION(create_mask)
311 
312 void editor_action_create_mask::perform_without_undo(map_context& mc) const
313 {
314  mc.set_map(editor_map(mc.get_map().mask_to(target_)));
315  mc.set_needs_terrain_rebuild();
316 }
317 
318 IMPLEMENT_ACTION(shuffle_area)
319 
321 {
322  map_fragment mf(mc.get_map(), area_);
323  std::unique_ptr<editor_action_paste> undo(new editor_action_paste(mf));
324 
325  perform_without_undo(mc);
326  return undo.release();
327 }
328 
330 {
331  std::vector<map_location> shuffle;
332 
333  std::copy(area_.begin(), area_.end(), std::inserter(shuffle, shuffle.begin()));
334  std::shuffle(shuffle.begin(), shuffle.end(), randomness::rng::default_instance());
335 
336  std::vector<map_location>::const_iterator shuffle_it = shuffle.begin();
337  std::set<map_location>::const_iterator orig_it = area_.begin();
338 
339  while(orig_it != area_.end()) {
340  t_translation::terrain_code tmp = mc.get_map().get_terrain(*orig_it);
341 
342  mc.draw_terrain(mc.get_map().get_terrain(*shuffle_it), *orig_it);
343  mc.draw_terrain(tmp, *shuffle_it);
344 
345  ++orig_it;
346  ++shuffle_it;
347  }
348 
350 }
351 
352 } // end namespace editor
void add_changed_location(const map_location &loc)
Randomize terrain in an area.
Definition: action.hpp:441
A map fragment – a collection of locations and information abut them.
std::vector< char_t > string
virtual std::string get_description() const
A textual description of the action.
Definition: action.cpp:58
void set(CURSOR_TYPE type)
Use the default parameter to reset cursors.
Definition: cursor.cpp:154
void append_action(editor_action *a)
Add an action at the end of the chain.
Definition: action.cpp:125
std::unique_ptr< editor_action > editor_action_ptr
Action pointer typedef.
#define a
#define LOG_ED
editor_action_chain * perform(map_context &m) const
Perform all the actions in order and create a undo action chain.
Definition: action.cpp:162
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:55
void perform_without_undo(map_context &mc) const
Perform the action without creating an undo action.
Definition: action.cpp:222
Paste a map fragment into the map.
Definition: action.hpp:255
STL namespace.
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).
Container action wrapping several actions into one.
Definition: action.hpp:90
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.
Definition: action.hpp:340
void perform_without_undo(map_context &mc) const
Perform the action without creating an undo action.
Definition: action.cpp:242
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:116
void perform_without_undo(map_context &mc) const
Perform the action without creating an undo action.
Definition: action.cpp:283
virtual int action_count() const
Definition: action.cpp:53
map_location loc_
t_translation::terrain_code get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
Definition: map.cpp:301
std::set< map_location > get_offset_area(const map_location &offset) const
Get the area covered by this map fragment, shifted by an offset.
void extend(const editor_map &map, const std::set< map_location > &locs)
The crux of the extendable contract.
Definition: action.cpp:183
editor_action * pop_first_action()
Remove the first added action and return it, transferring ownership to the caller.
Definition: action.cpp:151
editor_map & get_map()
Map accessor.
Definition: map_context.hpp:92
void set_special_location(const std::string &id, const map_location &loc)
Definition: map.cpp:347
editor_action_paste * perform(map_context &mc) const
Perform the action, returning an undo action that, when performed, shall reverse any effects of this ...
Definition: action.cpp:195
Editor action classes.
std::deque< editor_action * > actions_
The action pointers owned by this action chain.
Definition: action.hpp:182
editor_action * pop_last_action()
Remove the last added action and return it, transferring ownership to the caller. ...
Definition: action.cpp:140
virtual editor_action * clone() const =0
Action cloning.
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:284
void set_needs_terrain_rebuild(bool value=true)
Setter for the terrain rebuild flag.
Encapsulates the map of the game.
Definition: location.hpp:40
virtual ~editor_action()
Definition: action.cpp:44
This class adds extra editor-specific functionality to a normal gamemap.
Definition: editor_map.hpp:69
editor_action_paste(const map_fragment &paste, const map_location &offset=map_location::ZERO())
Definition: action.hpp:258
t_translation::terrain_code t_
Definition: action.hpp:226
static int instance_count_
Base class for all editor actions.
Definition: action_base.hpp:40
void prepend_action(editor_action *a)
Add an action at the beginning of the chain.
Definition: action.cpp:130
This class wraps around a map to provide a concise interface for the editor to work with...
Definition: map_context.hpp:55
void perform_without_undo(map_context &mc) const
Perform the action without creating an undo action.
Definition: action.cpp:329
void perform_without_undo(map_context &mc) const
Perform the action without creating an undo action.
Definition: action.cpp:204
t_translation::terrain_code t_
Definition: action.hpp:306
void set_needs_labels_reset(bool value=true)
Setter for the labels reset flag.
~editor_action_chain()
The destructor deletes all the owned action pointers.
Definition: action.cpp:104
#define IMPLEMENT_ACTION(id)
Helper macro to implement common action methods.
editor_action_chain()
Create an empty action chain.
Definition: action.hpp:96
const std::string * is_starting_position(const map_location &loc) const
returns the side number of the side starting at position loc, 0 if no such side exists.
Definition: map.cpp:341
void perform_without_undo(map_context &m) const
Perform all the actions in order.
Definition: action.cpp:174
virtual void perform_without_undo(map_context &) const =0
Perform the action without creating an undo action.
static void reverse(lua_State *L, StkId from, StkId to)
Definition: lapi.cpp:193
std::vector< game_tip > shuffle(const std::vector< game_tip > &tips)
Shuffles the tips.
Definition: tips.cpp:46
virtual 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
std::set< map_location > area_
Definition: action.hpp:249
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
static rng & default_instance()
Definition: random.cpp:70