The Battle for Wesnoth  1.15.9+dev
map_context.cpp
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 #define GETTEXT_DOMAIN "wesnoth-editor"
15 
17 
18 #include "display.hpp"
19 #include "editor/action/action.hpp"
20 #include "filesystem.hpp"
21 #include "formula/string_utils.hpp"
22 #include "game_board.hpp"
23 #include "gettext.hpp"
24 #include "map/exception.hpp"
25 #include "map/label.hpp"
26 #include "preferences/editor.hpp"
28 #include "serialization/parser.hpp"
29 #include "team.hpp"
30 #include "units/unit.hpp"
31 #include "game_config_view.hpp"
32 
33 #include <boost/regex.hpp>
34 
35 namespace editor
36 {
38  : side(t.side())
39  , id(t.team_name())
40  , name(t.user_team_name())
41  , gold(t.gold())
42  , income(t.base_income())
45  , fog(t.uses_fog())
46  , shroud(t.uses_shroud())
47  , share_vision(t.share_vision())
48  , controller(t.controller())
49  , no_leader(t.no_leader())
50  , hidden(t.hidden())
51 {
52 }
53 
54 const std::size_t map_context::max_action_stack_size_ = 100;
55 
56 map_context::map_context(const editor_map& map, bool pure_map, const config& schedule)
57  : filename_()
58  , map_data_key_()
59  , embedded_(false)
60  , pure_map_(pure_map)
61  , map_(map)
62  , undo_stack_()
63  , redo_stack_()
64  , actions_since_save_(0)
65  , starting_position_label_locs_()
66  , needs_reload_(false)
67  , needs_terrain_rebuild_(false)
68  , needs_labels_reset_(false)
69  , changed_locations_()
70  , everything_changed_(false)
71  , scenario_id_()
72  , scenario_name_()
73  , scenario_description_()
74  , xp_mod_()
75  , victory_defeated_(true)
76  , random_time_(false)
77  , active_area_(-1)
78  , labels_(nullptr)
79  , units_()
80  , teams_()
81  , tod_manager_(new tod_manager(schedule))
82  , mp_settings_()
83  , game_classification_()
84  , music_tracks_()
85 {
86 }
87 
88 map_context::map_context(const game_config_view& game_config, const std::string& filename)
89  : filename_(filename)
90  , map_data_key_()
91  , embedded_(false)
92  , pure_map_(false)
93  , map_()
94  , undo_stack_()
95  , redo_stack_()
98  , needs_reload_(false)
99  , needs_terrain_rebuild_(false)
100  , needs_labels_reset_(false)
102  , everything_changed_(false)
103  , scenario_id_()
104  , scenario_name_()
106  , xp_mod_()
107  , victory_defeated_(true)
108  , random_time_(false)
109  , active_area_(-1)
110  , labels_(nullptr)
111  , units_()
112  , teams_()
113  , tod_manager_(new tod_manager(game_config.find_child("editor_times", "id", "empty")))
114  , mp_settings_()
116  , music_tracks_()
117 {
118  /*
119  * Overview of situations possibly found in the file:
120  *
121  * 0. Not a scenario or map file.
122  * 0.1 File not found
123  * 0.2 Map file empty
124  * 0.3 No valid data
125  * 1. It's a file containing only pure map data.
126  * * embedded_ = false
127  * * pure_map_ = true
128  * 2. A scenario embedding the map
129  * * embedded_ = true
130  * * pure_map_ = true
131  * The data/scenario-test.cfg for example.
132  * The map is written back to the file.
133  * 3. The map file is referenced by map_data={MACRO_ARGUEMENT}.
134  * * embedded_ = false
135  * * pure_map_ = true
136  * 4. The file contains an editor generated scenario file.
137  * * embedded_ = false
138  * * pure_map_ = false
139  */
140 
141  log_scope2(log_editor, "Loading file " + filename);
142 
143  // 0.1 File not found
144  if(!filesystem::file_exists(filename) || filesystem::is_directory(filename)) {
145  throw editor_map_load_exception(filename, _("File not found"));
146  }
147 
148  std::string file_string = filesystem::read_file(filename);
149 
150  // 0.2 Map file empty
151  if(file_string.empty()) {
152  std::string message = _("Empty file");
153  throw editor_map_load_exception(filename, message);
154  }
155 
156  // 1.0 Pure map data
157  boost::regex rexpression_map_data(R"""(map_data\s*=\s*"(.+?)")""");
158  boost::smatch matched_map_data;
159 
160  if(!boost::regex_search(
161  file_string, matched_map_data, rexpression_map_data, boost::regex_constants::match_not_dot_null)
162  ) {
163  map_ = editor_map::from_string(file_string); // throws on error
164  pure_map_ = true;
165 
167  return;
168  }
169 
170  // 2.0 Embedded map
171  const std::string& map_data = matched_map_data[1];
172 
173  boost::regex rexpression_macro(R"""(\{(.+?)\})""");
174  boost::smatch matched_macro;
175 
176  if(!boost::regex_search(map_data, matched_macro, rexpression_macro)) {
177  // We have a map_data string but no macro ---> embedded or scenario
178 
179  boost::regex rexpression_scenario(R"""(\[(scenario|test|multiplayer|tutorial)\])""");
180  if(!boost::regex_search(file_string, rexpression_scenario)) {
181  LOG_ED << "Loading generated scenario file" << std::endl;
182  // 4.0 editor generated scenario
183  try {
184  load_scenario();
185  } catch(const config::error& e) {
186  // We already caught and rethrew this exception in load_scenario
187  throw editor_map_load_exception("load_scenario", e.message);
188  }
189  } else {
190  LOG_ED << "Loading embedded map file" << std::endl;
191  embedded_ = true;
192  pure_map_ = true;
193  map_ = editor_map::from_string(map_data);
194  }
195 
197  return;
198  }
199 
200  // 3.0 Macro referenced pure map
201  const std::string& macro_argument = matched_macro[1];
202  LOG_ED << "Map looks like a scenario, trying {" << macro_argument << "}" << std::endl;
203 
204  std::string new_filename = filesystem::get_wml_location(macro_argument,
206 
207  if(new_filename.empty()) {
208  std::string message = _("The map file looks like a scenario, "
209  "but the map_data value does not point to an existing file")
210  + std::string("\n") + macro_argument;
211  throw editor_map_load_exception(filename, message);
212  }
213 
214  LOG_ED << "New filename is: " << new_filename << std::endl;
215 
216  filename_ = new_filename;
217  file_string = filesystem::read_file(filename_);
218  map_ = editor_map::from_string(file_string);
219  pure_map_ = true;
220 
222 }
223 
225 {
226  undo_stack_.clear();
227  redo_stack_.clear();
228 }
229 
231 {
232  teams_.emplace_back();
233 
234  config cfg;
235  cfg["side"] = teams_.size(); // side is 1-indexed, so we can just use size()
236  cfg["hidden"] = false;
237 
238  // TODO: build might be slight overkill here just to set the side...
239  teams_.back().build(cfg, map());
240 
242 }
243 
245 {
246  assert(teams_.size() >= static_cast<unsigned int>(info.side));
247 
248  team& t = teams_[info.side - 1];
249  // t.set_save_id(id);
250  // t.set_name(name);
251  t.change_team(info.id, info.name);
252  t.have_leader(!info.no_leader);
254  t.set_gold(info.gold);
255  t.set_base_income(info.income);
256  t.set_hidden(info.hidden);
257  t.set_fog(info.fog);
258  t.set_shroud(info.shroud);
262 
264 }
265 
266 void map_context::set_scenario_setup(const std::string& id,
267  const std::string& name,
268  const std::string& description,
269  int turns,
270  int xp_mod,
271  bool victory_defeated,
272  bool random_time)
273 {
274  scenario_id_ = id;
276  scenario_description_ = description;
277  random_time_ = random_time;
279  tod_manager_->set_number_of_turns(turns);
280  xp_mod_ = xp_mod;
282 }
283 
285 {
286  tod_manager_->set_current_time(time);
287  if(!pure_map_) {
289  }
290 }
291 
293 {
294  tod_manager_->remove_time_area(index);
295  active_area_--;
297 }
298 
299 void map_context::replace_schedule(const std::vector<time_of_day>& schedule)
300 {
301  tod_manager_->replace_schedule(schedule);
302  if(!pure_map_) {
304  }
305 }
306 
307 void map_context::replace_local_schedule(const std::vector<time_of_day>& schedule)
308 {
309  tod_manager_->replace_local_schedule(schedule, active_area_);
310  if(!pure_map_) {
312  }
313 }
314 
316 {
317  config scenario;
318 
319  try {
320  read(scenario, *(preprocess_file(filename_)));
321  } catch(const config::error& e) {
322  LOG_ED << "Caught a config error while parsing file: '" << filename_ << "'\n" << e.message << std::endl;
323  throw;
324  }
325 
326  scenario_id_ = scenario["id"].str();
327  scenario_name_ = scenario["name"].str();
328  scenario_description_ = scenario["description"].str();
329 
330  if(const config::attribute_value* experience_modifier = scenario.get("experience_modifier")) {
331  xp_mod_ = experience_modifier->to_int();
332  }
333  victory_defeated_ = scenario["victory_when_enemies_defeated"].to_bool(true);
334  random_time_ = scenario["random_start_time"].to_bool(false);
335 
336  map_ = editor_map::from_string(scenario["map_data"]); // throws on error
337 
338  labels_.read(scenario);
339 
340  tod_manager_.reset(new tod_manager(scenario));
341  for(const config& time_area : scenario.child_range("time_area")) {
342  tod_manager_->add_time_area(map_, time_area);
343  }
344 
345  for(const config& item : scenario.child_range("item")) {
346  const map_location loc(item);
347  overlays_[loc].push_back(overlay(item));
348  }
349 
350  for(const config& music : scenario.child_range("music")) {
351  music_tracks_.emplace(music["name"], sound::music_track(music));
352  }
353 
354  int i = 1;
355  for(config& side : scenario.child_range("side")) {
356  teams_.emplace_back();
357 
358  side["side"] = i;
359  teams_.back().build(side, map_);
360 
361  for(config& a_unit : side.child_range("unit")) {
362  a_unit["side"] = i;
363 
364  units_.insert(unit::create(a_unit, true));
365  }
366 
367  ++i;
368  }
369 }
370 
372 {
373  return map_.set_selection(tod_manager_->get_area_by_index(index));
374 }
375 
376 void map_context::draw_terrain(const t_translation::terrain_code& terrain, const map_location& loc, bool one_layer_only)
377 {
378  t_translation::terrain_code full_terrain = one_layer_only
379  ? terrain
381 
382  draw_terrain_actual(full_terrain, loc, one_layer_only);
383 }
384 
386  const t_translation::terrain_code& terrain, const map_location& loc, bool one_layer_only)
387 {
388  if(!map_.on_board_with_border(loc)) {
389  // requests for painting off the map are ignored in set_terrain anyway,
390  // but ideally we should not have any
391  LOG_ED << "Attempted to draw terrain off the map (" << loc << ")\n";
392  return;
393  }
394 
395  t_translation::terrain_code old_terrain = map_.get_terrain(loc);
396 
397  if(terrain != old_terrain) {
398  if(terrain.base == t_translation::NO_LAYER) {
400  } else if(one_layer_only) {
402  } else {
403  map_.set_terrain(loc, terrain);
404  }
405 
407  }
408 }
409 
411  const t_translation::terrain_code& terrain, const std::set<map_location>& locs, bool one_layer_only)
412 {
413  t_translation::terrain_code full_terrain = one_layer_only
414  ? terrain
416 
417  for(const map_location& loc : locs) {
418  draw_terrain_actual(full_terrain, loc, one_layer_only);
419  }
420 }
421 
423 {
424  everything_changed_ = false;
425  changed_locations_.clear();
426 }
427 
429 {
430  if(!everything_changed()) {
431  changed_locations_.insert(loc);
432  }
433 }
434 
435 void map_context::add_changed_location(const std::set<map_location>& locs)
436 {
437  if(!everything_changed()) {
438  changed_locations_.insert(locs.begin(), locs.end());
439  }
440 }
441 
443 {
444  everything_changed_ = true;
445 }
446 
448 {
449  return everything_changed_;
450 }
451 
453 {
454  disp.labels().clear_all();
456 }
457 
459 {
460  std::set<map_location> new_label_locs = map_.set_starting_position_labels(disp);
461  starting_position_label_locs_.insert(new_label_locs.begin(), new_label_locs.end());
462 }
463 
465 {
468  set_needs_labels_reset(false);
469 }
470 
472 {
473  config scenario;
474 
475  scenario["id"] = scenario_id_;
476  scenario["name"] = t_string(scenario_name_);
477  scenario["description"] = scenario_description_;
478 
479  if(xp_mod_) {
480  scenario["experience_modifier"] = *xp_mod_;
481  }
482  if(victory_defeated_) {
483  scenario["victory_when_enemies_defeated"] = *victory_defeated_;
484  }
485  scenario["random_start_time"] = random_time_;
486 
487  scenario.append(tod_manager_->to_config());
488  scenario.remove_attribute("turn_at");
489  scenario.remove_attribute("it_is_a_new_turn");
490  if(scenario["turns"].to_int() == -1) {
491  scenario.remove_attribute("turns");
492  }
493 
494  scenario["map_data"] = map_.write();
495 
496  labels_.write(scenario);
497 
498  for(const auto& overlay_pair : overlays_) {
499  for(const overlay& o : overlay_pair.second) {
500  config& item = scenario.add_child("item");
501 
502  // Write x,y location
503  overlay_pair.first.write(item);
504 
505  // These should always have a value
506  item["image"] = o.image;
507  item["visible_in_fog"] = o.visible_in_fog;
508 
509  // Optional keys
510  item["id"].write_if_not_empty(o.id);
511  item["name"].write_if_not_empty(o.name);
512  item["team_name"].write_if_not_empty(o.team_name);
513  item["halo"].write_if_not_empty(o.halo);
514  }
515  }
516 
517  for(const music_map::value_type& track : music_tracks_) {
518  track.second.write(scenario, true);
519  }
520 
521  for(std::vector<team>::const_iterator t = teams_.begin(); t != teams_.end(); ++t) {
522  int side_num = t - teams_.begin() + 1;
523 
524  config& side = scenario.add_child("side");
525 
526  side["side"] = side_num;
527  side["hidden"] = t->hidden();
528 
529  side["controller"] = t->controller();
530  side["no_leader"] = t->no_leader();
531 
532  side["team_name"] = t->team_name();
533  side["user_team_name"].write_if_not_empty(t->user_team_name());
534 
535  // TODO
536  // side["allow_player"] = "yes";
537 
538  side["fog"] = t->uses_fog();
539  side["shroud"] = t->uses_shroud();
540  side["share_vision"] = t->share_vision();
541 
542  side["gold"] = t->gold();
543  side["income"] = t->base_income();
544 
545  for(const map_location& village : t->villages()) {
546  village.write(side.add_child("village"));
547  }
548 
549  // current visible units
550  for(unit_map::const_iterator i = units_.begin(); i != units_.end(); ++i) {
551  if(i->side() == side_num) {
552  config& u = side.add_child("unit");
553 
554  i->get_location().write(u);
555 
556  u["type"] = i->type_id();
557  u["name"].write_if_not_empty(i->name());
558  u["facing"] = map_location::write_direction(i->facing());
559 
560  if(!boost::regex_match(i->id(), boost::regex(".*-[0-9]+"))) {
561  u["id"] = i->id();
562  }
563 
564  if(i->can_recruit()) {
565  u["canrecruit"] = i->can_recruit();
566  }
567 
568  if(i->unrenamable()) {
569  u["unrenamable"] = i->unrenamable();
570  }
571 
572  if(!i->recruits().empty()) {
573  u["extra_recruit"] = utils::join(i->recruits());
574  }
575  }
576  }
577  }
578 
579  return scenario;
580 }
581 
583 {
584  assert(!is_embedded());
585 
586  if(scenario_id_.empty()) {
588  }
589 
590  if(scenario_name_.empty()) {
592  }
593 
594  try {
595  std::stringstream wml_stream;
596  wml_stream
597  << "# This file was generated using the scenario editor.\n"
598  << "#\n"
599  << "# If you edit this file by hand, then you shouldn't use the\n"
600  << "# scenario editor on it afterwards. The editor completely\n"
601  << "# rewrites the file when it saves it, which will lose any WML\n"
602  << "# that the editor doesn't support.\n"
603  << "\n";
604  {
605  config_writer out(wml_stream, false);
606  out.write(to_config());
607  }
608 
609  if(!wml_stream.str().empty()) {
610  filesystem::write_file(get_filename(), wml_stream.str());
611  }
612 
613  clear_modified();
614  } catch(const filesystem::io_exception& e) {
615  utils::string_map symbols;
616  symbols["msg"] = e.what();
617  const std::string msg = VGETTEXT("Could not save the scenario: $msg", symbols);
618 
619  throw editor_map_save_exception(msg);
620  }
621 
622  // After saving the map as a scenario, it's no longer a pure map.
623  pure_map_ = false;
624 
625  // TODO the return value of this method does not need to be boolean.
626  // We either return true or there is an exception thrown.
627  return true;
628 }
629 
631 {
632  std::string map_data = map_.write();
633 
634  try {
635  if(!is_embedded()) {
637  } else {
638  std::string map_string = filesystem::read_file(get_filename());
639 
640  boost::regex rexpression_map_data(R"""((.*map_data\s*=\s*")(.+?)(".*))""");
641  boost::smatch matched_map_data;
642 
643  if(boost::regex_search(map_string, matched_map_data, rexpression_map_data,
644  boost::regex_constants::match_not_dot_null)) {
645  std::stringstream ss;
646  ss << matched_map_data[1];
647  ss << map_data;
648  ss << matched_map_data[3];
649 
651  } else {
652  throw editor_map_save_exception(_("Could not save into scenario"));
653  }
654  }
655 
657 
658  clear_modified();
659  } catch(const filesystem::io_exception& e) {
660  utils::string_map symbols;
661  symbols["msg"] = e.what();
662  const std::string msg = VGETTEXT("Could not save the map: $msg", symbols);
663 
664  throw editor_map_save_exception(msg);
665  }
666 
667  // TODO the return value of this method does not need to be boolean.
668  // We either return true or there is an exception thrown.
669  return true;
670 }
671 
673 {
674  if(map_.h() != map.h() || map_.w() != map.w()) {
676  } else {
678  }
679 
680  map_ = map;
681 }
682 
684 {
685  LOG_ED << "Performing action " << action.get_id() << ": " << action.get_name() << ", actions count is "
686  << action.get_instance_count() << std::endl;
687  auto undo = action.perform(*this);
688  if(actions_since_save_ < 0) {
689  // set to a value that will make it impossible to get to zero, as at this point
690  // it is no longer possible to get back the original map state using undo/redo
691  actions_since_save_ = 1 + undo_stack_.size();
692  }
693 
695 
696  undo_stack_.emplace_back(std::move(undo));
697 
699 
700  redo_stack_.clear();
701 }
702 
704 {
705  LOG_ED << "Performing (partial) action " << action.get_id() << ": " << action.get_name() << ", actions count is "
706  << action.get_instance_count() << std::endl;
707  if(!can_undo()) {
708  throw editor_logic_exception("Empty undo stack in perform_partial_action()");
709  }
710 
711  editor_action_chain* undo_chain = dynamic_cast<editor_action_chain*>(last_undo_action());
712  if(undo_chain == nullptr) {
713  throw editor_logic_exception("Last undo action not a chain in perform_partial_action()");
714  }
715 
716  auto undo = action.perform(*this);
717 
718  // actions_since_save_ += action.action_count();
719  undo_chain->prepend_action(std::move(undo));
720 
721  redo_stack_.clear();
722 }
723 
725 {
726  return actions_since_save_ != 0;
727 }
728 
730 {
732 }
733 
735 {
737 }
738 
740 {
741  return !undo_stack_.empty();
742 }
743 
745 {
746  return !redo_stack_.empty();
747 }
748 
750 {
751  return undo_stack_.empty() ? nullptr : undo_stack_.back().get();
752 }
753 
755 {
756  return redo_stack_.empty() ? nullptr : redo_stack_.back().get();
757 }
758 
760 {
761  return undo_stack_.empty() ? nullptr : undo_stack_.back().get();
762 }
763 
765 {
766  return redo_stack_.empty() ? nullptr : redo_stack_.back().get();
767 }
768 
770 {
771  LOG_ED << "undo() beg, undo stack is " << undo_stack_.size() << ", redo stack " << redo_stack_.size() << std::endl;
772 
773  if(can_undo()) {
776  } else {
777  WRN_ED << "undo() called with an empty undo stack" << std::endl;
778  }
779 
780  LOG_ED << "undo() end, undo stack is " << undo_stack_.size() << ", redo stack " << redo_stack_.size() << std::endl;
781 }
782 
784 {
785  LOG_ED << "redo() beg, undo stack is " << undo_stack_.size() << ", redo stack " << redo_stack_.size() << std::endl;
786 
787  if(can_redo()) {
790  } else {
791  WRN_ED << "redo() called with an empty redo stack" << std::endl;
792  }
793 
794  LOG_ED << "redo() end, undo stack is " << undo_stack_.size() << ", redo stack " << redo_stack_.size() << std::endl;
795 }
796 
798 {
799  // callers should check for these conditions
800  if(!can_undo()) {
801  throw editor_logic_exception("Empty undo stack in partial_undo()");
802  }
803 
804  editor_action_chain* undo_chain = dynamic_cast<editor_action_chain*>(last_undo_action());
805  if(undo_chain == nullptr) {
806  throw editor_logic_exception("Last undo action not a chain in partial undo");
807  }
808 
809  // a partial undo performs the first action form the current action's action_chain that would be normally performed
810  // i.e. the *first* one.
811  const auto first_action_in_chain = undo_chain->pop_first_action();
812  if(undo_chain->empty()) {
814  undo_stack_.pop_back();
815  }
816 
817  redo_stack_.emplace_back(first_action_in_chain->perform(*this));
818  // actions_since_save_ -= last_redo_action()->action_count();
819 }
820 
822 {
823  undo_stack_.clear();
824  redo_stack_.clear();
825 }
826 
828 {
829  if(stack.size() > max_action_stack_size_) {
830  stack.pop_front();
831  }
832 }
833 
835 {
836  assert(!from.empty());
837 
838  std::unique_ptr<editor_action> action;
839  action.swap(from.back());
840 
841  from.pop_back();
842 
843  auto reverse_action = action->perform(*this);
844  to.emplace_back(std::move(reverse_action));
845 
846  trim_stack(to);
847 }
848 
850 {
851  return is_pure_map() ? _("New Map") : _("New Scenario");
852 }
853 
854 } // end namespace editor
void add_changed_location(const map_location &loc)
void set_side_setup(editor_team_info &info)
TODO.
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.
editor_action * last_redo_action()
void undo()
Un-does the last action, and puts it in the redo stack for a possible redo.
editor_map map_
The map object of this map_context.
::tod_manager * tod_manager
Definition: resources.cpp:29
int h() const
Effective map height, in hexes.
Definition: map.hpp:124
void set_shroud(bool shroud)
Definition: team.hpp:334
game_classification game_classification_
unit_iterator end()
Definition: map.hpp:428
std::set< map_location > starting_position_label_locs_
Cache of set starting position labels.
bool needs_terrain_rebuild_
Refresh flag indicating the terrain in the map has changed and requires a rebuild.
void write(const config &cfg)
static editor_map from_string(const std::string &data)
Wrapper around editor_map(cfg, data) that catches possible exceptions and wraps them in a editor_map_...
Definition: editor_map.cpp:53
std::map< std::string, t_string > string_map
int village_support
Definition: game_config.cpp:55
void append(const config &cfg)
Append data from another config object to this one.
Definition: config.cpp:287
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...
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
bool visible_in_fog
Definition: overlay.hpp:58
team::SHARE_VISION share_vision
Definition: map_context.hpp:46
std::set< map_location > set_starting_position_labels(display &disp)
Set labels for staring positions in the given display object.
Definition: editor_map.cpp:134
umap_retval_pair_t insert(unit_ptr p)
Inserts the unit pointed to by p into the map.
Definition: map.cpp:133
virtual const std::string & get_name() const
Definition: action_base.hpp:74
Variant for storing WML attributes.
void new_side()
Adds a new side to the map.
bool save_scenario()
Saves the scenario under the current filename.
logger & info()
Definition: log.cpp:91
virtual ~map_context()
Map context destructor.
std::unique_ptr< editor_action > pop_first_action()
Remove the first added action and return it, transferring ownership to the caller.
Definition: action.cpp:141
static bool file_exists(const bfs::path &fpath)
Definition: filesystem.cpp:263
const std::string & get_filename() const
child_itors child_range(config_key_type key)
Definition: config.cpp:362
#define LOG_ED
bool needs_reload_
Refresh flag indicating the map in this context should be completely reloaded by the display...
const attribute_value * get(config_key_type key) const
Returns a pointer to the attribute with the given key or nullptr if it does not exist.
Definition: config.cpp:742
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.
unit_iterator begin()
Definition: map.hpp:418
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:48
const terrain_type & get_terrain_info(const t_translation::terrain_code &terrain) const
Definition: map.cpp:96
static int get_instance_count()
Debugging aid.
const ter_layer NO_LAYER
Definition: translation.hpp:39
void redo()
Re-does a previously undid action, and puts it back in the undo stack.
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
lg::log_domain log_editor
Container action wrapping several actions into one.
Definition: action.hpp:86
static std::string _(const char *str)
Definition: gettext.hpp:92
void change_controller(const std::string &new_controller)
Definition: team.hpp:283
void set_share_vision(const std::string &vision_status)
Definition: team.hpp:401
void set_hidden(bool value)
Definition: team.hpp:356
void remove_attribute(config_key_type key)
Definition: config.cpp:235
std::string scenario_description_
std::string scenario_name_
void set_needs_reload(bool value=true)
Setter for the reload flag.
std::deque< std::unique_ptr< editor_action > > action_stack
Action stack typedef.
void clear_modified()
Clear the modified state.
void partial_undo()
Un-does a single step from a undo action chain.
std::optional< int > xp_mod_
static unit_ptr create(const config &cfg, bool use_traits=false, const vconfig *vcfg=nullptr)
Initializes a unit from a config.
Definition: unit.hpp:188
bool embedded_
Whether the map context refers to a map embedded in a scenario file.
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)
TODO.
void remove_area(int index)
t_translation::terrain_code get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
Definition: map.cpp:314
void set_terrain(const map_location &loc, const t_translation::terrain_code &terrain, const terrain_type_data::merge_mode mode=terrain_type_data::BOTH, bool replace_if_failed=false)
Clobbers over the terrain at location &#39;loc&#39;, with the given terrain.
Definition: map.cpp:394
void set_map(const editor_map &map)
std::string filename_
Definition: action_wml.cpp:562
bool modified() const
std::string id
Definition: overlay.hpp:55
#define WRN_ED
bool fog()
Definition: game.cpp:533
bool pure_map_
Whether the map context refers to a file containing only the pure map data.
std::string write() const
Definition: map.cpp:210
This class stores all the data for a single &#39;side&#39; (in game nomenclature).
Definition: team.hpp:44
void have_leader(bool value=true)
Definition: team.hpp:354
std::unique_ptr< tod_manager > tod_manager_
std::vector< team > teams_
editor_team_info(const team &t)
Definition: map_context.cpp:37
bool on_board_with_border(const map_location &loc) const
Definition: map.cpp:387
void read(config &cfg, std::istream &in, abstract_validator *validator)
Definition: parser.cpp:625
Class for writing a config out to a file in pieces.
void reset_starting_position_labels(display &disp)
void write_file(const std::string &fname, const std::string &data)
Throws io_exception if an error occurs.
int get_id() const
Debugging aid.
Definition: action_base.hpp:92
void prepend_action(std::unique_ptr< editor_action > a)
Add an action at the beginning of the chain.
Definition: action.cpp:120
void replace_schedule(const std::vector< time_of_day > &schedule)
t_string name
Definition: overlay.hpp:54
void add_to_recent_files()
Adds the map to the editor&#39;s recent files list.
bool is_directory(const std::string &fname)
Returns true if the given file is a directory.
void write(config &res) const
Definition: label.cpp:79
Editor action classes.
void set_starting_time(int time)
TODO.
bool save_map()
Saves the map under the current filename.
void set_village_support(int support)
Definition: team.hpp:209
std::string get_short_wml_path(const std::string &filename)
Returns a short path to filename, skipping the (user) data directory.
#define log_scope2(domain, description)
Definition: log.hpp:209
std::optional< bool > victory_defeated_
map_display and display: classes which take care of displaying the map and game-data on the screen...
editor_action * last_undo_action()
bool is_pure_map() const
int village_gold()
Definition: game.cpp:659
Manage the empty-palette in the editor.
Definition: action.cpp:29
void perform_action(const editor_action &action)
Performs an action (thus modifying the map).
const char * what() const noexcept
Definition: exceptions.hpp:37
void set_fog(bool fog)
Definition: team.hpp:335
std::string read_file(const std::string &fname)
Basic disk I/O - read file.
Definition: filesystem.cpp:997
bool can_redo() const
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.
std::string scenario_id_
Encapsulates the map of the game.
Definition: location.hpp:37
void set_village_gold(int income)
Definition: team.hpp:202
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 clear_changed_locations()
bool shroud()
Definition: game.cpp:543
void set_starting_position_labels(display &disp)
int w() const
Effective map width, in hexes.
Definition: map.hpp:121
This class adds extra editor-specific functionality to a normal gamemap.
Definition: editor_map.hpp:69
std::size_t i
Definition: function.cpp:933
void set_gold(int amount)
Definition: team.hpp:214
std::string get_wml_location(const std::string &filename, const std::string &current_dir)
Returns a complete path to the actual WML file or directory or an empty string if the file isn&#39;t pres...
Game configuration data as global variables.
Definition: build_info.cpp:56
map_context(const map_context &)=delete
int village_income
Definition: game_config.cpp:54
t_translation::terrain_code terrain_with_default_base() const
Definition: terrain.cpp:296
An exception object used when an IO error occurs.
Definition: filesystem.hpp:45
Base class for all editor actions.
Definition: action_base.hpp:40
Internal representation of music tracks.
std::string name
Definition: sdl_ttf.cpp:70
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.
Declarations for File-IO.
overlay_map overlays_
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
#define VGETTEXT(msgid,...)
Handy wrappers around interpolate_variables_into_string and gettext.
config & add_child(config_key_type key)
Definition: config.cpp:476
action_stack redo_stack_
The redo stack.
bool can_undo() const
std::string base_name(const std::string &file, const bool remove_extension)
Returns the base filename of a file, with directory name stripped.
virtual std::unique_ptr< editor_action > perform(map_context &) const
Perform the action, returning an undo action that, when performed, shall reverse any effects of this ...
Definition: action.cpp:63
std::string halo
Definition: overlay.hpp:52
bool victory_defeated() const
void read(const config &cfg)
Definition: label.cpp:91
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
void clear_undo_redo()
Clear the undo and redo stacks.
void set_needs_labels_reset(bool value=true)
Setter for the labels reset flag.
static const std::size_t max_action_stack_size_
Action stack (i.e.
std::string message
Definition: exceptions.hpp:31
void replace_local_schedule(const std::vector< time_of_day > &schedule)
Replace the [time]s of the currently active area.
std::string filename_
The actual filename of this map.
void change_team(const std::string &name, const t_string &user_name)
Definition: team.cpp:619
void trim_stack(action_stack &stack)
Checks if an action stack reached its capacity and removes the front element if so.
map_labels & labels()
Definition: display.cpp:2537
#define e
void set_base_income(int amount)
Definition: team.hpp:217
void add_recent_files_entry(const std::string &path)
Adds an entry to the recent files list.
Definition: editor.cpp:123
void clear_all()
Definition: label.cpp:239
std::set< map_location > changed_locations_
std::string team_name
Definition: overlay.hpp:53
void clear_starting_position_labels(display &disp)
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:60
filesystem::scoped_istream preprocess_file(const std::string &fname, preproc_map *defines)
Function to use the WML preprocessor on a file.
static std::string write_direction(DIRECTION dir)
Definition: location.cpp:140
mp_game_settings mp_settings_
bool set_selection(const std::set< map_location > &area)
Select the given area.
Definition: editor_map.cpp:166
std::string directory_name(const std::string &file)
Returns the directory name of a file, with filename stripped.
std::pair< std::string, unsigned > item
Definition: help_impl.hpp:407
const t_string get_default_context_name() const
bool select_area(int index)
Select the nth tod area.
std::string image
Definition: overlay.hpp:51
bool everything_changed() const