The Battle for Wesnoth  1.15.6+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 
18 #include "game_classification.hpp"
19 #include "map/label.hpp"
20 #include "mp_game_settings.hpp"
21 #include "sound_music_track.hpp"
22 #include "team.hpp"
23 #include "tod_manager.hpp"
24 #include "units/map.hpp"
25 #include "overlay.hpp"
26 #include "display_context.hpp"
27 
28 #include <boost/optional.hpp>
29 
30 #include <vector>
31 class game_config_view;
32 
33 namespace editor {
34 
36  editor_team_info(const team& t);
37 
38  int side;
41  int gold;
42  int income;
45  bool fog;
46  bool shroud;
47  team::SHARE_VISION share_vision;
48  team::CONTROLLER controller;
49  bool no_leader;
50  bool hidden;
51 };
52 
53 /**
54  * This class wraps around a map to provide a concise interface for the editor to work with.
55  * The actual map object can change rapidly (be assigned to), the map context persists
56  * data (like the undo stacks) in this case. The functionality is here, not in editor_controller
57  * as e.g. the undo stack is part of the map, not the editor as a whole. This might allow many
58  * maps to be open at the same time.
59  */
61 {
62 public:
63  map_context(const map_context&) = delete;
64  map_context& operator=(const map_context&) = delete;
65 
66  /**
67  * Create a map context from an existing map. The filename is set to be
68  * empty, indicating a new map.
69  * Marked "explicit" to avoid automatic conversions.
70  */
71  explicit map_context(const editor_map& map, bool pure_map, const config& schedule);
72 
73  /**
74  * Create map_context from a map file. If the map cannot be loaded, an
75  * exception will be thrown and the object will not be constructed. If the
76  * map file is a scenario, the map specified in its map_data key will be
77  * loaded, and the stored filename updated accordingly. Maps embedded
78  * inside scenarios do not change the filename, but set the "embedded" flag
79  * instead.
80  */
81  map_context(const game_config_view& game_config, const std::string& filename);
82 
83  /**
84  * Map context destructor
85  */
86  virtual ~map_context();
87 
88  /**
89  * Select the nth tod area.
90  * @param index of the tod area to select.
91  */
92  bool select_area(int index);
93 
94  /** Adds a new side to the map */
95  void new_side();
96 
97  /** removes the last side from the scenario */
98  void remove_side() {
99  teams_.pop_back();
100  ++actions_since_save_;
101  }
102 
103  void save_area(const std::set<map_location>& area) {
104  tod_manager_->replace_area_locations(active_area_, area);
105  }
106 
107  void new_area(const std::set<map_location>& area) {
108  tod_manager_->add_time_area("", area, config());
109  active_area_ = tod_manager_->get_area_ids().size() -1;
110  ++actions_since_save_;
111  }
112 
113  void remove_area(int index);
114 
116  return labels_;
117  }
118 
119  void replace_schedule(const std::vector<time_of_day>& schedule);
120 
121  // Import symbols from base class.
124  using display_context::map;
125 
126  /** Const units accessor. */
127  virtual const unit_map& units() const override
128  {
129  return units_;
130  }
131 
132  /** Local non-const overload of @ref units */
134  {
135  return units_;
136  }
137 
138  /** Const teams accessor. */
139  virtual const std::vector<team>& teams() const override
140  {
141  return teams_;
142  }
143 
144  /** Local non-const overload of @ref teams */
145  std::vector<team>& teams()
146  {
147  return teams_;
148  }
149 
150  /** Const map accessor. */
151  virtual const editor_map& map() const override
152  {
153  return map_;
154  }
155 
156  /** Local non-const overload of @ref map */
158  {
159  return map_;
160  }
161 
162  virtual const std::vector<std::string>& hidden_label_categories() const override
163  {
164  return lbl_categories_;
165  }
166 
167  virtual std::vector<std::string>& hidden_label_categories() override
168  {
169  return lbl_categories_;
170  }
171 
172  /**
173  * Replace the [time]s of the currently active area.
174  */
175  void replace_local_schedule(const std::vector<time_of_day>& schedule);
176 
177  /**
178  * TODO
179  */
180  void set_starting_time(int time);
181 
182  /**
183  * TODO
184  */
185  void set_local_starting_time(int time) {
186  tod_manager_->set_current_time(time, active_area_);
187  ++actions_since_save_;
188  }
189 
190  const tod_manager* get_time_manager() const {
191  return tod_manager_.get();
192  }
193 
195  return tod_manager_.get();
196  }
197 
199  return mp_settings_;
200  }
202  return game_classification_;
203  }
204 
205  /**
206  *
207  * @return the index of the currently active area.
208  */
209  int get_active_area() const {
210  return active_area_;
211  }
212 
213  void set_active_area(int index) {
214  active_area_ = index;
215  }
216 
217  bool is_in_playlist(std::string track_id) {
218  return music_tracks_.find(track_id) != music_tracks_.end();
219  }
220 
221  void add_to_playlist(const sound::music_track& track) {
222 
223  if (music_tracks_.find(track.id()) == music_tracks_.end())
224  music_tracks_.emplace(track.id(), track);
225  else music_tracks_.erase(track.id());
226  }
227 
228  /**
229  * Draw a terrain on a single location on the map.
230  * Sets the refresh flags accordingly.
231  */
232  void draw_terrain(const t_translation::terrain_code & terrain, const map_location& loc,
233  bool one_layer_only = false);
234 
235  /**
236  * Actual drawing function used by both overloaded variants of draw_terrain.
237  */
238  void draw_terrain_actual(const t_translation::terrain_code & terrain, const map_location& loc,
239  bool one_layer_only = false);
240 
241  /**
242  * Draw a terrain on a set of locations on the map.
243  * Sets the refresh flags accordingly.
244  */
245  void draw_terrain(const t_translation::terrain_code & terrain, const std::set<map_location>& locs,
246  bool one_layer_only = false);
247 
248  /**
249  * Getter for the reload flag. Reload is the highest level of required refreshing,
250  * set when the map size has changed or the map was reassigned.
251  */
252  bool needs_reload() const { return needs_reload_; }
253 
254  /**
255  * Setter for the reload flag
256  */
257  void set_needs_reload(bool value=true) { needs_reload_ = value; }
258 
259  /**
260  * Getter for the terrain rebuild flag. Set whenever any terrain has changed.
261  */
262  bool needs_terrain_rebuild() const { return needs_terrain_rebuild_; }
263 
264  /**
265  * Setter for the terrain rebuild flag
266  */
267  void set_needs_terrain_rebuild(bool value=true) { needs_terrain_rebuild_ = value; }
268 
269  /**
270  * TODO
271  */
272  void set_scenario_setup(const std::string& id, const std::string& name, const std::string& description,
273  int turns, int xp_mod, bool victory_defeated, bool random_time);
274 
275  /**
276  * TODO
277  */
278  void set_side_setup(editor_team_info& info);
279 
280  /**
281  * Getter for the labels reset flag. Set when the labels need to be refreshed.
282  */
283  bool needs_labels_reset() const { return needs_labels_reset_; }
284 
285  /**
286  * Setter for the labels reset flag
287  */
288  void set_needs_labels_reset(bool value=true) { needs_labels_reset_ = value; }
289 
290  const std::set<map_location> changed_locations() const { return changed_locations_; }
291  void clear_changed_locations();
292  void add_changed_location(const map_location& loc);
293  void add_changed_location(const std::set<map_location>& locs);
294  void set_everything_changed();
295  bool everything_changed() const;
296 
297  void set_labels(display& disp);
298 
299  void clear_starting_position_labels(display& disp);
300 
301  void set_starting_position_labels(display& disp);
302 
303  void reset_starting_position_labels(display& disp);
304 
305  const std::string& get_filename() const { return filename_; }
306 
307  void set_filename(const std::string& fn) { filename_ = fn; }
308 
309  const std::string& get_map_data_key() const { return map_data_key_; }
310 
311  const std::string& get_id() const { return scenario_id_; }
312  const std::string& get_description() const { return scenario_description_; }
313  const std::string& get_name() const { return scenario_name_; }
314 
315  const t_string get_default_context_name() const;
316 
317  boost::optional<int> get_xp_mod() const { return xp_mod_; }
318 
319  bool random_start_time() const { return random_time_; }
320  bool victory_defeated() const { return !victory_defeated_ || *victory_defeated_; }
321 
322  bool is_embedded() const { return embedded_; }
323 
324  bool is_pure_map() const { return pure_map_; }
325 
326  void set_embedded(bool v) { embedded_ = v; }
327 
328  /**
329  * Saves the map under the current filename. Filename must be valid.
330  * May throw an exception on failure.
331  */
332  bool save_map();
333 
334  /**
335  * Saves the scenario under the current filename. Filename must be valid.
336  * May throw an exception on failure.
337  */
338  bool save_scenario();
339 
340 
341  void load_scenario(const game_config_view& game_config);
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  */
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  */
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  boost::optional<int> xp_mod_;
500  boost::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
boost::optional< int > get_xp_mod() const
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:47
void save_area(const std::set< map_location > &area)
logger & info()
Definition: log.cpp:91
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:50
bool needs_reload() const
Getter for the reload flag.
mp_game_settings & get_mp_settings()
-file sdl_utils.hpp
std::deque< editor_action_ptr > action_stack
Action stack typedef.
std::string scenario_name_
virtual const gamemap & map() const =0
void set_needs_reload(bool value=true)
Setter for the reload flag.
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:558
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:38
static const ::game_config_view * terrain
The terrain used to create the cache.
Definition: minimap.cpp:130
void remove_side()
removes the last side from the scenario
Definition: map_context.hpp:98
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
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:42
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:55
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.
boost::optional< int > xp_mod_
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:60
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:572
double t
Definition: astarsearch.cpp:64
virtual const editor_map & map() const override
Const map accessor.
team::CONTROLLER controller
Definition: map_context.hpp:48
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)
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:99
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:68
boost::optional< bool > victory_defeated_
virtual const std::vector< team > & teams() const override
Const teams accessor.
mp_game_settings mp_settings_