The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
action.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2008 - 2025
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
23
25#include "gettext.hpp"
26#include "random.hpp"
27
28#include <memory>
29
30namespace 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
60{
61 return "Unknown action";
62}
63
64std::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
71IMPLEMENT_ACTION(whole_map)
72
73void editor_action_whole_map::perform_without_undo(map_context& mc) const
74{
75 mc.set_map(m_);
76}
77
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
102IMPLEMENT_ACTION(chain)
103
104int editor_action_chain::action_count() const
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
116void editor_action_chain::append_action(std::unique_ptr<editor_action> a)
117{
118 actions_.push_back(std::move(a));
119}
120
121void 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
131std::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
142std::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
153std::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
174void editor_action_area::extend(const editor_map& /*map*/, const std::set<map_location>& locs)
175{
176 area_.insert(locs.begin(), locs.end());
177}
178
179IMPLEMENT_ACTION(paste)
180
181void editor_action_paste::extend(const editor_map& map, const std::set<map_location>& locs)
182{
183 paste_.add_tiles(map, locs);
184}
185
186std::unique_ptr<editor_action> editor_action_paste::perform(map_context& mc) const
187{
189 auto undo = std::make_unique<editor_action_paste>(mf);
190
192 return undo;
193}
194
201
202IMPLEMENT_ACTION(paint_area)
203
205{
206 map_fragment mf(mc.map(), area_);
207 auto undo = std::make_unique<editor_action_paste>(mf);
208
209 perform_without_undo(mc);
210 return undo;
211}
212
218
220
221std::unique_ptr<editor_action> editor_action_fill::perform(map_context& mc) const
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
239IMPLEMENT_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
282}
283
284IMPLEMENT_ACTION(resize_map)
285
286void editor_action_resize_map::perform_without_undo(map_context& mc) const
287{
288 mc.map().resize(x_size_, y_size_, x_offset_, y_offset_, fill_);
289 mc.set_needs_reload();
290}
291
292IMPLEMENT_ACTION(apply_mask)
293
294void editor_action_apply_mask::perform_without_undo(map_context& mc) const
295{
296 mc.map().overlay(mask_, {0, 0, wml_loc()});
297 mc.set_needs_terrain_rebuild();
298}
299
300IMPLEMENT_ACTION(create_mask)
301
302void editor_action_create_mask::perform_without_undo(map_context& mc) const
303{
304 mc.set_map(editor_map(mc.map().mask_to(target_)));
305 mc.set_needs_terrain_rebuild();
306}
307
308IMPLEMENT_ACTION(shuffle_area)
309
311{
312 map_fragment mf(mc.map(), area_);
313 auto undo = std::make_unique<editor_action_paste>(mf);
314 perform_without_undo(mc);
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
341IMPLEMENT_ACTION(time_area_move_all)
342
344{
345 auto undo = std::make_unique<editor_action_time_area_move_all>(-x_offset_, -y_offset_);
346 perform_without_undo(mc);
347 return undo;
348}
349
354
355} // end namespace editor
#define IMPLEMENT_ACTION(id)
Helper macro to implement common action methods.
void extend(const editor_map &map, const std::set< map_location > &locs) override
The crux of the extendable contract.
Definition action.cpp:174
std::set< map_location > area_
Definition action.hpp:236
Container action wrapping several actions into one.
Definition action.hpp:88
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
editor_action_chain()
Create an empty action chain.
Definition action.hpp:93
void perform_without_undo(map_context &m) const override
Perform all the actions in order.
Definition action.cpp:165
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
editor_action_chain & operator=(const editor_action_chain &other)
Definition action.cpp:87
void append_action(std::unique_ptr< editor_action > a)
Add an action at the end of the chain.
Definition action.cpp:116
int action_count() const override
Go through the chain and add up all the action counts.
Definition action.cpp:104
std::deque< std::unique_ptr< editor_action > > actions_
The action pointers owned by this action chain.
Definition action.hpp:169
void prepend_action(std::unique_ptr< editor_action > a)
Add an action at the beginning of the chain.
Definition action.cpp:121
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
void perform_without_undo(map_context &mc) const override
Perform the action without creating an undo action.
Definition action.cpp:232
t_translation::terrain_code t_
Definition action.hpp:213
Paint the same terrain on a number of locations on the map.
Definition action.hpp:266
void perform_without_undo(map_context &mc) const override
Perform the action without creating an undo action.
Definition action.cpp:213
t_translation::terrain_code t_
Definition action.hpp:282
Paste a map fragment into the map.
Definition action.hpp:243
void perform_without_undo(map_context &mc) const override
Perform the action without creating an undo action.
Definition action.cpp:195
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
Randomize terrain in an area.
Definition action.hpp:399
void perform_without_undo(map_context &mc) const override
Perform the action without creating an undo action.
Definition action.cpp:318
Set starting position action, sets location ids (both for starting locations and for non-starting loc...
Definition action.hpp:313
void perform_without_undo(map_context &mc) const override
Perform the action without creating an undo action.
Definition action.cpp:273
void perform_without_undo(map_context &mc) const override
Perform the action without creating an undo action.
Definition action.cpp:350
Replace contents of the entire map, Useful as a fallback undo method when something else would be imp...
Definition action.hpp:39
Base class for all editor actions.
virtual void perform_without_undo(map_context &) const =0
Perform the action without creating an undo action.
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 ~editor_action()
Definition action.cpp:45
virtual std::string get_description() const
A textual description of the action.
Definition action.cpp:59
virtual int action_count() const
Definition action.cpp:54
This class adds extra editor-specific functionality to a normal gamemap.
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.
This class wraps around a map to provide a concise interface for the editor to work with.
void set_needs_labels_reset(bool value=true)
Setter for the labels reset flag.
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.
virtual const editor_map & map() const override
Const map accessor.
const tod_manager * get_time_manager() const
void set_needs_terrain_rebuild(bool value=true)
Setter for the terrain rebuild flag.
void add_changed_location(const map_location &loc)
A map fragment – a collection of locations and information abut them.
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 paste_into(gamemap &map, const map_location &loc) const
Paste the map fragment into the map, treating loc as the (0,0) point (offset).
terrain_code get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
Definition map.cpp:265
void set_special_location(const std::string &id, const map_location &loc)
Definition map.cpp:325
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:319
static rng & default_instance()
Definition random.cpp:73
void move_all_areas(int x_offset, int y_offset)
Shift all hex locations for all time areas by the given x/y offsets.
Editor action classes.
#define LOG_ED
const gui2::tracked_drawable & target_
The drawable whose render calls we are tracking.
Manage the empty-palette in the editor.
Definition action.cpp:31
STL namespace.
Encapsulates the map of the game.
Definition location.hpp:46
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...