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