The Battle for Wesnoth  1.19.0-dev
map_context.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2024
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 #pragma once
17 
18 #include "display_context.hpp"
20 #include "game_classification.hpp"
21 #include "map/label.hpp"
22 #include "mp_game_settings.hpp"
23 #include "overlay.hpp"
24 #include "side_controller.hpp"
25 #include "sound_music_track.hpp"
26 #include "team.hpp"
27 #include "tod_manager.hpp"
28 #include "units/map.hpp"
29 
30 #include <optional>
31 #include <vector>
32 class game_config_view;
33 
34 namespace editor {
35 
37  editor_team_info(const team& t);
38 
39  int side;
40  std::string id;
41  std::string name;
42  std::string recruit_list;
43  int gold;
44  int income;
47  bool fog;
48  bool shroud;
51  bool no_leader;
52  bool hidden;
53 };
54 
55 /**
56  * This class wraps around a map to provide a concise interface for the editor to work with.
57  * The actual map object can change rapidly (be assigned to), the map context persists
58  * data (like the undo stacks) in this case. The functionality is here, not in editor_controller
59  * as e.g. the undo stack is part of the map, not the editor as a whole. This might allow many
60  * maps to be open at the same time.
61  */
63 {
64 public:
65  map_context(const map_context&) = delete;
66  map_context& operator=(const map_context&) = delete;
67 
68  /**
69  * Create a map context from an existing map. The filename is set to be
70  * empty, indicating a new map.
71  * Marked "explicit" to avoid automatic conversions.
72  */
73  explicit map_context(const editor_map& map, bool pure_map, const config& schedule, const std::string& addon_id);
74 
75  /**
76  * Create map_context from a map file. If the map cannot be loaded, an
77  * exception will be thrown and the object will not be constructed. If the
78  * map file is a scenario, the map specified in its map_data key will be
79  * loaded, and the stored filename updated accordingly. Maps embedded
80  * inside scenarios do not change the filename, but set the "embedded" flag
81  * instead.
82  */
83  map_context(const game_config_view& game_config, const std::string& filename, const std::string& addon_id);
84 
85  /**
86  * Map context destructor
87  */
88  virtual ~map_context();
89 
90  /**
91  * Select the nth tod area.
92  * @param index of the tod area to select.
93  */
94  bool select_area(int index);
95 
96  /** Adds a new side to the map */
97  void new_side();
98 
99  /** removes the last side from the scenario */
100  void remove_side() {
101  teams_.pop_back();
103  }
104 
105  void save_area(const std::set<map_location>& area) {
106  tod_manager_->replace_area_locations(active_area_, area);
107  }
108 
109  void new_area(const std::set<map_location>& area) {
110  tod_manager_->add_time_area("", area, config());
111  active_area_ = tod_manager_->get_area_ids().size() -1;
113  }
114 
115  void remove_area(int index);
116 
118  return labels_;
119  }
120 
121  void replace_schedule(const std::vector<time_of_day>& schedule);
122 
123  // Import symbols from base class.
126  using display_context::map;
127 
128  /** Const units accessor. */
129  virtual const unit_map& units() const override
130  {
131  return units_;
132  }
133 
134  /** Local non-const overload of @ref units */
136  {
137  return units_;
138  }
139 
140  /** Const teams accessor. */
141  virtual const std::vector<team>& teams() const override
142  {
143  return teams_;
144  }
145 
146  /** Local non-const overload of @ref teams */
147  std::vector<team>& teams()
148  {
149  return teams_;
150  }
151 
152  /** Const map accessor. */
153  virtual const editor_map& map() const override
154  {
155  return map_;
156  }
157 
158  /** Local non-const overload of @ref map */
160  {
161  return map_;
162  }
163 
164  virtual const std::vector<std::string>& hidden_label_categories() const override
165  {
166  return lbl_categories_;
167  }
168 
169  virtual std::vector<std::string>& hidden_label_categories() override
170  {
171  return lbl_categories_;
172  }
173 
174  /**
175  * Replace the [time]s of the currently active area.
176  */
177  void replace_local_schedule(const std::vector<time_of_day>& schedule);
178 
179  void set_starting_time(int time);
180 
181  void set_local_starting_time(int time) {
182  tod_manager_->set_current_time(time, active_area_);
184  }
185 
186  const tod_manager* get_time_manager() const {
187  return tod_manager_.get();
188  }
189 
191  return tod_manager_.get();
192  }
193 
195  return mp_settings_;
196  }
198  return game_classification_;
199  }
200 
201  /**
202  * @return the index of the currently active area.
203  */
204  int get_active_area() const {
205  return active_area_;
206  }
207 
208  void set_active_area(int index) {
210  }
211 
212  bool is_in_playlist(std::string track_id) {
213  return music_tracks_.find(track_id) != music_tracks_.end();
214  }
215 
216  void add_to_playlist(const sound::music_track& track) {
217 
218  if (music_tracks_.find(track.id()) == music_tracks_.end())
219  music_tracks_.emplace(track.id(), track);
220  else music_tracks_.erase(track.id());
221  }
222 
223  /**
224  * Draw a terrain on a single location on the map.
225  * Sets the refresh flags accordingly.
226  */
227  void draw_terrain(const t_translation::terrain_code & terrain, const map_location& loc,
228  bool one_layer_only = false);
229 
230  /**
231  * Actual drawing function used by both overloaded variants of draw_terrain.
232  */
233  void draw_terrain_actual(const t_translation::terrain_code & terrain, const map_location& loc,
234  bool one_layer_only = false);
235 
236  /**
237  * Draw a terrain on a set of locations on the map.
238  * Sets the refresh flags accordingly.
239  */
240  void draw_terrain(const t_translation::terrain_code & terrain, const std::set<map_location>& locs,
241  bool one_layer_only = false);
242 
243  /**
244  * Getter for the reload flag. Reload is the highest level of required refreshing,
245  * set when the map size has changed or the map was reassigned.
246  */
247  bool needs_reload() const { return needs_reload_; }
248 
249  /**
250  * Setter for the reload flag
251  */
252  void set_needs_reload(bool value=true) { needs_reload_ = value; }
253 
254  /**
255  * Getter for the terrain rebuild flag. Set whenever any terrain has changed.
256  */
258 
259  /**
260  * Setter for the terrain rebuild flag
261  */
262  void set_needs_terrain_rebuild(bool value=true) { needs_terrain_rebuild_ = value; }
263 
264  void set_scenario_setup(const std::string& id, const std::string& name, const std::string& description,
265  int turns, int xp_mod, bool victory_defeated, bool random_time);
266 
268 
269  /**
270  * Getter for the labels reset flag. Set when the labels need to be refreshed.
271  */
272  bool needs_labels_reset() const { return needs_labels_reset_; }
273 
274  /**
275  * Setter for the labels reset flag
276  */
277  void set_needs_labels_reset(bool value=true) { needs_labels_reset_ = value; }
278 
279  const std::set<map_location> changed_locations() const { return changed_locations_; }
281  void add_changed_location(const map_location& loc);
282  void add_changed_location(const std::set<map_location>& locs);
283  void set_everything_changed();
284  bool everything_changed() const;
285 
286  void set_labels(display& disp);
287 
289 
291 
293 
294  const std::string& get_filename() const { return filename_; }
295 
296  void set_filename(const std::string& fn) { filename_ = fn; }
297 
298  const std::string& get_id() const { return scenario_id_; }
299  const std::string& get_description() const { return scenario_description_; }
300  const std::string& get_name() const { return scenario_name_; }
301 
302  const t_string get_default_context_name() const;
303 
304  std::optional<int> get_xp_mod() const { return xp_mod_; }
305 
306  bool random_start_time() const { return random_time_; }
308 
309  bool is_embedded() const { return embedded_; }
310 
311  bool is_pure_map() const { return pure_map_; }
312 
313  void set_embedded(bool v) { embedded_ = v; }
314 
315  /**
316  * Saves the map under the current filename. Filename must be valid.
317  * May throw an exception on failure.
318  */
319  void save_map();
320 
321  /**
322  * Saves the scenario under the current filename. Filename must be valid.
323  * May throw an exception on failure.
324  */
325  void save_scenario();
326 
327  /**
328  * Save custom time of day schedule in the utils directory.
329  */
330  void save_schedule(const std::string& schedule_id, const std::string& schedule_name);
331 
332  /**
333  * Convert an old-style editor scenario config to a config with a top level [multiplayer] tag.
334  *
335  * @param old_scenario the original scenario config
336  * @return the converted scenario config
337  */
338  config convert_scenario(const config& old_scenario);
339  void load_scenario();
340 
341  config to_config();
342 
343  void set_map(const editor_map& map);
344 
345  /**
346  * Performs an action (thus modifying the map). An appropriate undo action is added to
347  * the undo stack. The redo stack is cleared. Note that this may throw, use caution
348  * when calling this with a dereferenced pointer that you own (i.e. use a smart pointer).
349  */
350  void perform_action(const editor_action& action);
351 
352  /**
353  * Performs a partial action, assumes that the top undo action has been modified to
354  * maintain coherent state of the undo stacks, and so a new undo action is not
355  * created.
356  */
357  void perform_partial_action(const editor_action& action);
358 
359  /** @return whether the map was modified since the last save */
360  bool modified() const;
361 
362  /** Clear the modified state */
363  void clear_modified();
364 
365  /** Adds the map to the editor's recent files list. */
366  void add_to_recent_files();
367 
368  /** @return true when undo can be performed, false otherwise */
369  bool can_undo() const;
370 
371  /** @return true when redo can be performed, false otherwise */
372  bool can_redo() const;
373 
374  /** @return a pointer to the last undo action or nullptr if the undo stack is empty */
376 
377  /** @return a pointer to the last redo action or nullptr if the undo stack is empty */
379 
380  /** const version of last_undo_action */
381  const editor_action* last_undo_action() const;
382 
383  /** const version of last_redo_action */
384  const editor_action* last_redo_action() const;
385 
386  /** Un-does the last action, and puts it in the redo stack for a possible redo */
387  void undo();
388 
389  /** Re-does a previously undid action, and puts it back in the undo stack. */
390  void redo();
391 
392  /**
393  * Un-does a single step from a undo action chain. The action is separated
394  * from the chain and it's undo (the redo) is added as a stand-alone action
395  * to the redo stack.
396  * Precondition: the last undo action has to actually be an action chain.
397  */
398  void partial_undo();
399 
400  /**
401  * Clear the undo and redo stacks
402  */
403  void clear_undo_redo();
404 
405  void set_addon_id(const std::string& addon_id)
406  {
407  addon_id_ = addon_id;
408  }
409 
410 protected:
411  /**
412  * The actual filename of this map. An empty string indicates a new map.
413  */
414  std::string filename_;
415 
416  /**
417  * When a scenario file is loaded, the referenced map is loaded instead.
418  * The verbatim form of the reference is kept here.
419  */
420  std::string map_data_key_;
421 
422  /**
423  * Whether the map context refers to a map embedded in a scenario file.
424  * This distinction is important in order to avoid overwriting the scenario.
425  */
426  bool embedded_;
427 
428  /**
429  * Whether the map context refers to a file containing only the pure map data.
430  */
431  bool pure_map_;
432 
433  /**
434  * The map object of this map_context.
435  */
437 
438  /**
439  * Checks if an action stack reached its capacity and removes the front element if so.
440  */
441  void trim_stack(action_stack& stack);
442 
443  /**
444  * Perform an action at the back of one stack, and then move it to the back of the other stack.
445  * This is the implementation of both undo and redo which only differ in the direction.
446  */
448 
449  /**
450  * The undo stack. A double-ended queues due to the need to add items to one end,
451  * and remove from both when performing the undo or when trimming the size. This container owns
452  * all contents, i.e. no action in the stack shall be deleted, and unless otherwise noted the contents
453  * could be deleted at an time during normal operation of the stack. To work on an action, either
454  * remove it from the container or make a copy. Actions are inserted at the back of the container
455  * and disappear from the front when the capacity is exceeded.
456  * @todo Use boost's pointer-owning container?
457  */
459 
460  /**
461  * The redo stack. @see undo_stack_
462  */
464 
465  /**
466  * Action stack (i.e. undo and redo) maximum size
467  */
468  static const std::size_t max_action_stack_size_;
469 
470  /**
471  * Number of actions performed since the map was saved. Zero means the map was not modified.
472  */
474 
475  /**
476  * Cache of set starting position labels. Necessary for removing them.
477  */
478  std::set<map_location> starting_position_label_locs_;
479 
480  /**
481  * Refresh flag indicating the map in this context should be completely reloaded by the display
482  */
484 
485  /**
486  * Refresh flag indicating the terrain in the map has changed and requires a rebuild
487  */
489 
490  /**
491  * Refresh flag indicating the labels in the map have changed
492  */
494 
495  std::set<map_location> changed_locations_;
497 
498 private:
499  std::string addon_id_;
500  std::optional<config> previous_cfg_;
502 
503  std::optional<int> xp_mod_;
504  std::optional<bool> victory_defeated_;
506 
508 
511  std::vector<team> teams_;
512  std::vector<std::string> lbl_categories_;
513  std::unique_ptr<tod_manager> tod_manager_;
516 
517  typedef std::map<std::string, sound::music_track> music_map;
519 
520  typedef std::map<map_location, std::vector<overlay>> overlay_map;
522 
523 public:
524 
526 
527 };
528 
529 
530 } //end namespace editor
double t
Definition: astarsearch.cpp:63
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:159
Abstract class for exposing game data that doesn't depend on the GUI, however which for historical re...
virtual const gamemap & map() const =0
virtual const std::vector< team > & teams() const =0
virtual const unit_map & units() const =0
Sort-of-Singleton that many classes, both GUI and non-GUI, use to access the game data.
Definition: display.hpp:81
Base class for all editor actions.
Definition: action_base.hpp:42
This class adds extra editor-specific functionality to a normal gamemap.
Definition: editor_map.hpp:70
This class wraps around a map to provide a concise interface for the editor to work with.
Definition: map_context.hpp:63
game_classification game_classification_
overlay_map & get_overlays()
std::set< map_location > starting_position_label_locs_
Cache of set starting position labels.
std::string filename_
The actual filename of this map.
void save_area(const std::set< map_location > &area)
void new_area(const std::set< map_location > &area)
void perform_partial_action(const editor_action &action)
Performs a partial action, assumes that the top undo action has been modified to maintain coherent st...
void remove_side()
removes the last side from the scenario
std::optional< int > xp_mod_
mp_game_settings mp_settings_
void set_active_area(int index)
bool modified() const
bool pure_map_
Whether the map context refers to a file containing only the pure map data.
void set_labels(display &disp)
bool needs_terrain_rebuild_
Refresh flag indicating the terrain in the map has changed and requires a rebuild.
virtual const unit_map & units() const override
Const units accessor.
action_stack redo_stack_
The redo stack.
std::unique_ptr< tod_manager > tod_manager_
void set_local_starting_time(int time)
bool embedded_
Whether the map context refers to a map embedded in a scenario file.
int get_active_area() const
void set_needs_labels_reset(bool value=true)
Setter for the labels reset flag.
void set_needs_reload(bool value=true)
Setter for the reload flag.
std::string scenario_name_
bool needs_labels_reset_
Refresh flag indicating the labels in the map have changed.
void clear_starting_position_labels(display &disp)
std::vector< std::string > lbl_categories_
editor_map map_
The map object of this map_context.
void new_side()
Adds a new side to the map.
const std::string & get_id() const
static const std::size_t max_action_stack_size_
Action stack (i.e.
action_stack undo_stack_
The undo stack.
editor_action * last_undo_action()
std::optional< config > previous_cfg_
std::string map_data_key_
When a scenario file is loaded, the referenced map is loaded instead.
void redo()
Re-does a previously undid action, and puts it back in the undo stack.
std::set< map_location > changed_locations_
void set_starting_time(int time)
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.
bool random_start_time() const
void set_map(const editor_map &map)
bool select_area(int index)
Select the nth tod area.
bool can_redo() const
void set_side_setup(editor_team_info &info)
std::vector< team > & teams()
Local non-const overload of teams.
void trim_stack(action_stack &stack)
Checks if an action stack reached its capacity and removes the front element if so.
bool can_undo() const
int actions_since_save_
Number of actions performed since the map was saved.
std::string scenario_description_
void save_scenario()
Saves the scenario under the current filename.
bool needs_reload_
Refresh flag indicating the map in this context should be completely reloaded by the display.
editor_map & map()
Local non-const overload of map.
std::vector< team > teams_
void perform_action_between_stacks(action_stack &from, action_stack &to)
Perform an action at the back of one stack, and then move it to the back of the other stack.
void perform_action(const editor_action &action)
Performs an action (thus modifying the map).
void undo()
Un-does the last action, and puts it in the redo stack for a possible redo.
const std::string & get_description() const
void replace_schedule(const std::vector< time_of_day > &schedule)
bool is_in_playlist(std::string track_id)
void remove_area(int index)
void set_addon_id(const std::string &addon_id)
void clear_undo_redo()
Clear the undo and redo stacks.
bool is_embedded() const
virtual ~map_context()
Map context destructor.
unit_map & units()
Local non-const overload of units.
tod_manager * get_time_manager()
virtual const std::vector< std::string > & hidden_label_categories() const override
void draw_terrain_actual(const t_translation::terrain_code &terrain, const map_location &loc, bool one_layer_only=false)
Actual drawing function used by both overloaded variants of draw_terrain.
void clear_changed_locations()
map_context(const map_context &)=delete
bool needs_labels_reset() const
Getter for the labels reset flag.
void add_to_recent_files()
Adds the map to the editor's recent files list.
std::map< map_location, std::vector< overlay > > overlay_map
std::map< std::string, sound::music_track > music_map
std::string scenario_id_
void replace_local_schedule(const std::vector< time_of_day > &schedule)
Replace the [time]s of the currently active area.
const tod_manager * get_time_manager() const
void save_map()
Saves the map under the current filename.
std::optional< int > get_xp_mod() const
void reset_starting_position_labels(display &disp)
void set_embedded(bool v)
editor_action * last_redo_action()
void partial_undo()
Un-does a single step from a undo action chain.
bool needs_reload() const
Getter for the reload flag.
virtual const editor_map & map() const override
Const map accessor.
void add_to_playlist(const sound::music_track &track)
virtual std::vector< std::string > & hidden_label_categories() override
void set_needs_terrain_rebuild(bool value=true)
Setter for the terrain rebuild flag.
map_context & operator=(const map_context &)=delete
config convert_scenario(const config &old_scenario)
Convert an old-style editor scenario config to a config with a top level [multiplayer] tag.
bool everything_changed() const
const t_string get_default_context_name() const
const std::string & get_filename() const
void set_starting_position_labels(display &disp)
mp_game_settings & get_mp_settings()
map_labels & get_labels()
bool needs_terrain_rebuild() const
Getter for the terrain rebuild flag.
std::optional< bool > victory_defeated_
void clear_modified()
Clear the modified state.
virtual const std::vector< team > & teams() const override
Const teams accessor.
overlay_map overlays_
game_classification & get_classification()
bool is_pure_map() const
bool victory_defeated() const
void set_filename(const std::string &fn)
const std::set< map_location > changed_locations() const
std::string addon_id_
void set_scenario_setup(const std::string &id, const std::string &name, const std::string &description, int turns, int xp_mod, bool victory_defeated, bool random_time)
void add_changed_location(const map_location &loc)
const std::string & get_name() const
void save_schedule(const std::string &schedule_id, const std::string &schedule_name)
Save custom time of day schedule in the utils directory.
A class grating read only view to a vector of config objects, viewed as one config with all children ...
Internal representation of music tracks.
const std::string & id() const
This class stores all the data for a single 'side' (in game nomenclature).
Definition: team.hpp:74
Container associating units to locations.
Definition: map.hpp:98
Manage the empty-palette in the editor.
Definition: action.cpp:31
std::deque< std::unique_ptr< editor_action > > action_stack
Action stack typedef.
Game configuration data as global variables.
Definition: build_info.cpp:60
logger & info()
Definition: log.cpp:314
int turns()
Definition: game.cpp:542
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:70
editor_team_info(const team &t)
Definition: map_context.cpp:39
side_controller::type controller
Definition: map_context.hpp:50
team_shared_vision::type share_vision
Definition: map_context.hpp:49
Encapsulates the map of the game.
Definition: location.hpp:38
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