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