The Battle for Wesnoth  1.15.12+dev
map_context.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2018 by Tomasz Sniatowski <kailoran@gmail.com>
3  Part of the Battle for Wesnoth Project https://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 #pragma once
16 
17 #include "display_context.hpp"
19 #include "game_classification.hpp"
20 #include "map/label.hpp"
21 #include "mp_game_settings.hpp"
22 #include "overlay.hpp"
23 #include "sound_music_track.hpp"
24 #include "team.hpp"
25 #include "tod_manager.hpp"
26 #include "units/map.hpp"
27 #include <optional>
28 
29 #include <vector>
30 class game_config_view;
31 
32 namespace editor {
33 
35  editor_team_info(const team& t);
36 
37  int side;
38  std::string id;
39  std::string name;
40  int gold;
41  int income;
44  bool fog;
45  bool shroud;
46  team::SHARE_VISION share_vision;
47  team::CONTROLLER controller;
48  bool no_leader;
49  bool hidden;
50 };
51 
52 /**
53  * This class wraps around a map to provide a concise interface for the editor to work with.
54  * The actual map object can change rapidly (be assigned to), the map context persists
55  * data (like the undo stacks) in this case. The functionality is here, not in editor_controller
56  * as e.g. the undo stack is part of the map, not the editor as a whole. This might allow many
57  * maps to be open at the same time.
58  */
60 {
61 public:
62  map_context(const map_context&) = delete;
63  map_context& operator=(const map_context&) = delete;
64 
65  /**
66  * Create a map context from an existing map. The filename is set to be
67  * empty, indicating a new map.
68  * Marked "explicit" to avoid automatic conversions.
69  */
70  explicit map_context(const editor_map& map, bool pure_map, const config& schedule);
71 
72  /**
73  * Create map_context from a map file. If the map cannot be loaded, an
74  * exception will be thrown and the object will not be constructed. If the
75  * map file is a scenario, the map specified in its map_data key will be
76  * loaded, and the stored filename updated accordingly. Maps embedded
77  * inside scenarios do not change the filename, but set the "embedded" flag
78  * instead.
79  */
80  map_context(const game_config_view& game_config, const std::string& filename);
81 
82  /**
83  * Map context destructor
84  */
85  virtual ~map_context();
86 
87  /**
88  * Select the nth tod area.
89  * @param index of the tod area to select.
90  */
91  bool select_area(int index);
92 
93  /** Adds a new side to the map */
94  void new_side();
95 
96  /** removes the last side from the scenario */
97  void remove_side() {
98  teams_.pop_back();
99  ++actions_since_save_;
100  }
101 
102  void save_area(const std::set<map_location>& area) {
103  tod_manager_->replace_area_locations(active_area_, area);
104  }
105 
106  void new_area(const std::set<map_location>& area) {
107  tod_manager_->add_time_area("", area, config());
108  active_area_ = tod_manager_->get_area_ids().size() -1;
109  ++actions_since_save_;
110  }
111 
112  void remove_area(int index);
113 
115  return labels_;
116  }
117 
118  void replace_schedule(const std::vector<time_of_day>& schedule);
119 
120  // Import symbols from base class.
123  using display_context::map;
124 
125  /** Const units accessor. */
126  virtual const unit_map& units() const override
127  {
128  return units_;
129  }
130 
131  /** Local non-const overload of @ref units */
133  {
134  return units_;
135  }
136 
137  /** Const teams accessor. */
138  virtual const std::vector<team>& teams() const override
139  {
140  return teams_;
141  }
142 
143  /** Local non-const overload of @ref teams */
144  std::vector<team>& teams()
145  {
146  return teams_;
147  }
148 
149  /** Const map accessor. */
150  virtual const editor_map& map() const override
151  {
152  return map_;
153  }
154 
155  /** Local non-const overload of @ref map */
157  {
158  return map_;
159  }
160 
161  virtual const std::vector<std::string>& hidden_label_categories() const override
162  {
163  return lbl_categories_;
164  }
165 
166  virtual std::vector<std::string>& hidden_label_categories() override
167  {
168  return lbl_categories_;
169  }
170 
171  /**
172  * Replace the [time]s of the currently active area.
173  */
174  void replace_local_schedule(const std::vector<time_of_day>& schedule);
175 
176  /**
177  * TODO
178  */
179  void set_starting_time(int time);
180 
181  /**
182  * TODO
183  */
184  void set_local_starting_time(int time) {
185  tod_manager_->set_current_time(time, active_area_);
186  ++actions_since_save_;
187  }
188 
189  const tod_manager* get_time_manager() const {
190  return tod_manager_.get();
191  }
192 
194  return tod_manager_.get();
195  }
196 
198  return mp_settings_;
199  }
201  return game_classification_;
202  }
203 
204  /**
205  *
206  * @return the index of the currently active area.
207  */
208  int get_active_area() const {
209  return active_area_;
210  }
211 
212  void set_active_area(int index) {
213  active_area_ = index;
214  }
215 
216  bool is_in_playlist(std::string track_id) {
217  return music_tracks_.find(track_id) != music_tracks_.end();
218  }
219 
220  void add_to_playlist(const sound::music_track& track) {
221 
222  if (music_tracks_.find(track.id()) == music_tracks_.end())
223  music_tracks_.emplace(track.id(), track);
224  else music_tracks_.erase(track.id());
225  }
226 
227  /**
228  * Draw a terrain on a single location on the map.
229  * Sets the refresh flags accordingly.
230  */
231  void draw_terrain(const t_translation::terrain_code & terrain, const map_location& loc,
232  bool one_layer_only = false);
233 
234  /**
235  * Actual drawing function used by both overloaded variants of draw_terrain.
236  */
237  void draw_terrain_actual(const t_translation::terrain_code & terrain, const map_location& loc,
238  bool one_layer_only = false);
239 
240  /**
241  * Draw a terrain on a set of locations on the map.
242  * Sets the refresh flags accordingly.
243  */
244  void draw_terrain(const t_translation::terrain_code & terrain, const std::set<map_location>& locs,
245  bool one_layer_only = false);
246 
247  /**
248  * Getter for the reload flag. Reload is the highest level of required refreshing,
249  * set when the map size has changed or the map was reassigned.
250  */
251  bool needs_reload() const { return needs_reload_; }
252 
253  /**
254  * Setter for the reload flag
255  */
256  void set_needs_reload(bool value=true) { needs_reload_ = value; }
257 
258  /**
259  * Getter for the terrain rebuild flag. Set whenever any terrain has changed.
260  */
261  bool needs_terrain_rebuild() const { return needs_terrain_rebuild_; }
262 
263  /**
264  * Setter for the terrain rebuild flag
265  */
266  void set_needs_terrain_rebuild(bool value=true) { needs_terrain_rebuild_ = value; }
267 
268  /**
269  * TODO
270  */
271  void set_scenario_setup(const std::string& id, const std::string& name, const std::string& description,
272  int turns, int xp_mod, bool victory_defeated, bool random_time);
273 
274  /**
275  * TODO
276  */
277  void set_side_setup(editor_team_info& info);
278 
279  /**
280  * Getter for the labels reset flag. Set when the labels need to be refreshed.
281  */
282  bool needs_labels_reset() const { return needs_labels_reset_; }
283 
284  /**
285  * Setter for the labels reset flag
286  */
287  void set_needs_labels_reset(bool value=true) { needs_labels_reset_ = value; }
288 
289  const std::set<map_location> changed_locations() const { return changed_locations_; }
290  void clear_changed_locations();
291  void add_changed_location(const map_location& loc);
292  void add_changed_location(const std::set<map_location>& locs);
293  void set_everything_changed();
294  bool everything_changed() const;
295 
296  void set_labels(display& disp);
297 
298  void clear_starting_position_labels(display& disp);
299 
300  void set_starting_position_labels(display& disp);
301 
302  void reset_starting_position_labels(display& disp);
303 
304  const std::string& get_filename() const { return filename_; }
305 
306  void set_filename(const std::string& fn) { filename_ = fn; }
307 
308  const std::string& get_map_data_key() const { return map_data_key_; }
309 
310  const std::string& get_id() const { return scenario_id_; }
311  const std::string& get_description() const { return scenario_description_; }
312  const std::string& get_name() const { return scenario_name_; }
313 
314  const t_string get_default_context_name() const;
315 
316  std::optional<int> get_xp_mod() const { return xp_mod_; }
317 
318  bool random_start_time() const { return random_time_; }
319  bool victory_defeated() const { return !victory_defeated_ || *victory_defeated_; }
320 
321  bool is_embedded() const { return embedded_; }
322 
323  bool is_pure_map() const { return pure_map_; }
324 
325  void set_embedded(bool v) { embedded_ = v; }
326 
327  /**
328  * Saves the map under the current filename. Filename must be valid.
329  * May throw an exception on failure.
330  */
331  bool save_map();
332 
333  /**
334  * Saves the scenario under the current filename. Filename must be valid.
335  * May throw an exception on failure.
336  */
337  bool save_scenario();
338 
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 */
375  editor_action* last_undo_action();
376 
377  /** @return a pointer to the last redo action or nullptr if the undo stack is empty */
378  editor_action* last_redo_action();
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 protected:
406  /**
407  * The actual filename of this map. An empty string indicates a new map.
408  */
409  std::string filename_;
410 
411  /**
412  * When a scenario file is loaded, the referenced map is loaded instead.
413  * The verbatim form of the reference is kept here.
414  */
415  std::string map_data_key_;
416 
417  /**
418  * Whether the map context refers to a map embedded in a scenario file.
419  * This distinction is important in order to avoid overwriting the scenario.
420  */
421  bool embedded_;
422 
423  /**
424  * Whether the map context refers to a file containing only the pure map data.
425  */
426  bool pure_map_;
427 
428  /**
429  * The map object of this map_context.
430  */
432 
433  /**
434  * Checks if an action stack reached its capacity and removes the front element if so.
435  */
436  void trim_stack(action_stack& stack);
437 
438  /**
439  * Perform an action at the back of one stack, and then move it to the back of the other stack.
440  * This is the implementation of both undo and redo which only differ in the direction.
441  */
442  void perform_action_between_stacks(action_stack& from, action_stack& to);
443 
444  /**
445  * The undo stack. A double-ended queues due to the need to add items to one end,
446  * and remove from both when performing the undo or when trimming the size. This container owns
447  * all contents, i.e. no action in the stack shall be deleted, and unless otherwise noted the contents
448  * could be deleted at an time during normal operation of the stack. To work on an action, either
449  * remove it from the container or make a copy. Actions are inserted at the back of the container
450  * and disappear from the front when the capacity is exceeded.
451  * @todo Use boost's pointer-owning container?
452  */
454 
455  /**
456  * The redo stack. @see undo_stack_
457  */
459 
460  /**
461  * Action stack (i.e. undo and redo) maximum size
462  */
463  static const std::size_t max_action_stack_size_;
464 
465  /**
466  * Number of actions performed since the map was saved. Zero means the map was not modified.
467  */
469 
470  /**
471  * Cache of set starting position labels. Necessary for removing them.
472  */
473  std::set<map_location> starting_position_label_locs_;
474 
475  /**
476  * Refresh flag indicating the map in this context should be completely reloaded by the display
477  */
479 
480  /**
481  * Refresh flag indicating the terrain in the map has changed and requires a rebuild
482  */
484 
485  /**
486  * Refresh flag indicating the labels in the map have changed
487  */
489 
490  std::set<map_location> changed_locations_;
492 
493 private:
494 
495  std::string scenario_id_, scenario_name_, scenario_description_;
496 
497  std::optional<int> xp_mod_;
498  std::optional<bool> victory_defeated_;
500 
502 
505  std::vector<team> teams_;
506  std::vector<std::string> lbl_categories_;
507  std::unique_ptr<tod_manager> tod_manager_;
510 
511  typedef std::map<std::string, sound::music_track> music_map;
512  music_map music_tracks_;
513 
514  typedef std::map<map_location, std::vector<overlay>> overlay_map;
515  overlay_map overlays_;
516 
517 public:
518 
519  overlay_map& get_overlays() { return overlays_; }
520 
521 };
522 
523 
524 } //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.
team::SHARE_VISION share_vision
Definition: map_context.hpp:46
void save_area(const std::set< map_location > &area)
logger & info()
Definition: log.cpp:88
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:562
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:44
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:37
void remove_side()
removes the last side from the scenario
Definition: map_context.hpp:97
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:29
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:37
const std::string & get_description() const
This class adds extra editor-specific functionality to a normal gamemap.
Definition: editor_map.hpp:69
virtual const std::vector< team > & teams() const =0
Game configuration data as global variables.
Definition: build_info.cpp:58
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:40
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:59
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:71
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:553
double t
Definition: astarsearch.cpp:64
virtual const editor_map & map() const override
Const map accessor.
team::CONTROLLER controller
Definition: map_context.hpp:47
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:97
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:59
virtual const std::vector< team > & teams() const override
Const teams accessor.
mp_game_settings mp_settings_