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