The Battle for Wesnoth  1.17.0-dev
map_context.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2021
3  by Tomasz Sniatowski <kailoran@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #define GETTEXT_DOMAIN "wesnoth-editor"
17 
19 
20 #include "display.hpp"
21 #include "editor/action/action.hpp"
22 #include "filesystem.hpp"
23 #include "formula/string_utils.hpp"
24 #include "game_board.hpp"
25 #include "gettext.hpp"
26 #include "map/exception.hpp"
27 #include "map/label.hpp"
28 #include "preferences/editor.hpp"
30 #include "serialization/parser.hpp"
31 #include "team.hpp"
32 #include "units/unit.hpp"
33 #include "game_config_view.hpp"
34 
35 #include <boost/regex.hpp>
36 
37 namespace editor
38 {
40  : side(t.side())
41  , id(t.team_name())
42  , name(t.user_team_name())
43  , gold(t.gold())
44  , income(t.base_income())
47  , fog(t.uses_fog())
48  , shroud(t.uses_shroud())
49  , share_vision(t.share_vision())
50  , controller(t.controller())
51  , no_leader(t.no_leader())
52  , hidden(t.hidden())
53 {
54 }
55 
56 const std::size_t map_context::max_action_stack_size_ = 100;
57 
58 map_context::map_context(const editor_map& map, bool pure_map, const config& schedule)
59  : filename_()
60  , map_data_key_()
61  , embedded_(false)
62  , pure_map_(pure_map)
63  , map_(map)
64  , undo_stack_()
65  , redo_stack_()
66  , actions_since_save_(0)
67  , starting_position_label_locs_()
68  , needs_reload_(false)
69  , needs_terrain_rebuild_(false)
70  , needs_labels_reset_(false)
71  , changed_locations_()
72  , everything_changed_(false)
73  , scenario_id_()
74  , scenario_name_()
75  , scenario_description_()
76  , xp_mod_()
77  , victory_defeated_(true)
78  , random_time_(false)
79  , active_area_(-1)
80  , labels_(nullptr)
81  , units_()
82  , teams_()
83  , tod_manager_(new tod_manager(schedule))
84  , mp_settings_()
85  , game_classification_()
86  , music_tracks_()
87 {
88 }
89 
90 map_context::map_context(const game_config_view& game_config, const std::string& filename)
91  : filename_(filename)
92  , map_data_key_()
93  , embedded_(false)
94  , pure_map_(false)
95  , map_()
96  , undo_stack_()
97  , redo_stack_()
100  , needs_reload_(false)
101  , needs_terrain_rebuild_(false)
102  , needs_labels_reset_(false)
104  , everything_changed_(false)
105  , scenario_id_()
106  , scenario_name_()
108  , xp_mod_()
109  , victory_defeated_(true)
110  , random_time_(false)
111  , active_area_(-1)
112  , labels_(nullptr)
113  , units_()
114  , teams_()
115  , tod_manager_(new tod_manager(game_config.find_child("editor_times", "id", "empty")))
116  , mp_settings_()
118  , music_tracks_()
119 {
120  /*
121  * Overview of situations possibly found in the file:
122  *
123  * 0. Not a scenario or map file.
124  * 0.1 File not found
125  * 0.2 Map file empty
126  * 0.3 No valid data
127  * 1. It's a file containing only pure map data.
128  * * embedded_ = false
129  * * pure_map_ = true
130  * 2. A scenario embedding the map
131  * * embedded_ = true
132  * * pure_map_ = true
133  * The data/scenario-test.cfg for example.
134  * The map is written back to the file.
135  * 3. The map file is referenced by map_data={MACRO_ARGUEMENT}.
136  * * embedded_ = false
137  * * pure_map_ = true
138  * 4. The file contains an editor generated scenario file.
139  * * embedded_ = false
140  * * pure_map_ = false
141  */
142 
143  log_scope2(log_editor, "Loading file " + filename);
144 
145  // 0.1 File not found
146  if(!filesystem::file_exists(filename) || filesystem::is_directory(filename)) {
147  throw editor_map_load_exception(filename, _("File not found"));
148  }
149 
150  std::string file_string = filesystem::read_file(filename);
151 
152  // 0.2 Map file empty
153  if(file_string.empty()) {
154  std::string message = _("Empty file");
155  throw editor_map_load_exception(filename, message);
156  }
157 
158  // 1.0 Pure map data
159  boost::regex rexpression_map_data(R"""(map_data\s*=\s*"(.+?)")""");
160  boost::smatch matched_map_data;
161 
162  if(!boost::regex_search(
163  file_string, matched_map_data, rexpression_map_data, boost::regex_constants::match_not_dot_null)
164  ) {
165  map_ = editor_map::from_string(file_string); // throws on error
166  pure_map_ = true;
167 
169  return;
170  }
171 
172  // 2.0 Embedded map
173  const std::string& map_data = matched_map_data[1];
174 
175  boost::regex rexpression_macro(R"""(\{(.+?)\})""");
176  boost::smatch matched_macro;
177 
178  if(!boost::regex_search(map_data, matched_macro, rexpression_macro)) {
179  // We have a map_data string but no macro ---> embedded or scenario
180 
181  boost::regex rexpression_scenario(R"""(\[(scenario|test|multiplayer|tutorial)\])""");
182  if(!boost::regex_search(file_string, rexpression_scenario)) {
183  LOG_ED << "Loading generated scenario file" << std::endl;
184  // 4.0 editor generated scenario
185  try {
186  load_scenario();
187  } catch(const config::error& e) {
188  // We already caught and rethrew this exception in load_scenario
189  throw editor_map_load_exception("load_scenario", e.message);
190  }
191  } else {
192  LOG_ED << "Loading embedded map file" << std::endl;
193  embedded_ = true;
194  pure_map_ = true;
195  map_ = editor_map::from_string(map_data);
196  }
197 
199  return;
200  }
201 
202  // 3.0 Macro referenced pure map
203  const std::string& macro_argument = matched_macro[1];
204  LOG_ED << "Map looks like a scenario, trying {" << macro_argument << "}" << std::endl;
205 
206  std::string new_filename = filesystem::get_wml_location(macro_argument,
208 
209  if(new_filename.empty()) {
210  std::string message = _("The map file looks like a scenario, "
211  "but the map_data value does not point to an existing file")
212  + std::string("\n") + macro_argument;
213  throw editor_map_load_exception(filename, message);
214  }
215 
216  LOG_ED << "New filename is: " << new_filename << std::endl;
217 
218  filename_ = new_filename;
219  file_string = filesystem::read_file(filename_);
220  map_ = editor_map::from_string(file_string);
221  pure_map_ = true;
222 
224 }
225 
227 {
228  undo_stack_.clear();
229  redo_stack_.clear();
230 }
231 
233 {
234  teams_.emplace_back();
235 
236  config cfg;
237  cfg["side"] = teams_.size(); // side is 1-indexed, so we can just use size()
238  cfg["hidden"] = false;
239 
240  // TODO: build might be slight overkill here just to set the side...
241  teams_.back().build(cfg, map());
242 
244 }
245 
247 {
248  assert(teams_.size() >= static_cast<unsigned int>(info.side));
249 
250  team& t = teams_[info.side - 1];
251  // t.set_save_id(id);
252  // t.set_name(name);
253  t.change_team(info.id, info.name);
254  t.have_leader(!info.no_leader);
256  t.set_gold(info.gold);
257  t.set_base_income(info.income);
258  t.set_hidden(info.hidden);
259  t.set_fog(info.fog);
260  t.set_shroud(info.shroud);
264 
266 }
267 
268 void map_context::set_scenario_setup(const std::string& id,
269  const std::string& name,
270  const std::string& description,
271  int turns,
272  int xp_mod,
273  bool victory_defeated,
274  bool random_time)
275 {
276  scenario_id_ = id;
277  scenario_name_ = name;
278  scenario_description_ = description;
279  random_time_ = random_time;
281  tod_manager_->set_number_of_turns(turns);
282  xp_mod_ = xp_mod;
284 }
285 
287 {
288  tod_manager_->set_current_time(time);
289  if(!pure_map_) {
291  }
292 }
293 
295 {
296  tod_manager_->remove_time_area(index);
297  active_area_--;
299 }
300 
301 void map_context::replace_schedule(const std::vector<time_of_day>& schedule)
302 {
303  tod_manager_->replace_schedule(schedule);
304  if(!pure_map_) {
306  }
307 }
308 
309 void map_context::replace_local_schedule(const std::vector<time_of_day>& schedule)
310 {
311  tod_manager_->replace_local_schedule(schedule, active_area_);
312  if(!pure_map_) {
314  }
315 }
316 
318 {
319  config scenario;
320 
321  try {
322  read(scenario, *(preprocess_file(filename_)));
323  } catch(const config::error& e) {
324  LOG_ED << "Caught a config error while parsing file: '" << filename_ << "'\n" << e.message << std::endl;
325  throw;
326  }
327 
328  scenario_id_ = scenario["id"].str();
329  scenario_name_ = scenario["name"].str();
330  scenario_description_ = scenario["description"].str();
331 
332  if(const config::attribute_value* experience_modifier = scenario.get("experience_modifier")) {
333  xp_mod_ = experience_modifier->to_int();
334  }
335  victory_defeated_ = scenario["victory_when_enemies_defeated"].to_bool(true);
336  random_time_ = scenario["random_start_time"].to_bool(false);
337 
338  map_ = editor_map::from_string(scenario["map_data"]); // throws on error
339 
340  labels_.read(scenario);
341 
342  tod_manager_.reset(new tod_manager(scenario));
343  for(const config& time_area : scenario.child_range("time_area")) {
344  tod_manager_->add_time_area(map_, time_area);
345  }
346 
347  for(const config& item : scenario.child_range("item")) {
348  const map_location loc(item);
349  overlays_[loc].push_back(overlay(item));
350  }
351 
352  for(const config& music : scenario.child_range("music")) {
353  music_tracks_.emplace(music["name"], sound::music_track(music));
354  }
355 
356  int i = 1;
357  for(config& side : scenario.child_range("side")) {
358  teams_.emplace_back();
359 
360  side["side"] = i;
361  teams_.back().build(side, map_);
362 
363  for(config& a_unit : side.child_range("unit")) {
364  a_unit["side"] = i;
365 
366  units_.insert(unit::create(a_unit, true));
367  }
368 
369  ++i;
370  }
371 }
372 
374 {
375  return map_.set_selection(tod_manager_->get_area_by_index(index));
376 }
377 
378 void map_context::draw_terrain(const t_translation::terrain_code& terrain, const map_location& loc, bool one_layer_only)
379 {
380  t_translation::terrain_code full_terrain = one_layer_only
381  ? terrain
383 
384  draw_terrain_actual(full_terrain, loc, one_layer_only);
385 }
386 
388  const t_translation::terrain_code& terrain, const map_location& loc, bool one_layer_only)
389 {
390  if(!map_.on_board_with_border(loc)) {
391  // requests for painting off the map are ignored in set_terrain anyway,
392  // but ideally we should not have any
393  LOG_ED << "Attempted to draw terrain off the map (" << loc << ")\n";
394  return;
395  }
396 
397  t_translation::terrain_code old_terrain = map_.get_terrain(loc);
398 
399  if(terrain != old_terrain) {
400  if(terrain.base == t_translation::NO_LAYER) {
402  } else if(one_layer_only) {
404  } else {
405  map_.set_terrain(loc, terrain);
406  }
407 
409  }
410 }
411 
413  const t_translation::terrain_code& terrain, const std::set<map_location>& locs, bool one_layer_only)
414 {
415  t_translation::terrain_code full_terrain = one_layer_only
416  ? terrain
418 
419  for(const map_location& loc : locs) {
420  draw_terrain_actual(full_terrain, loc, one_layer_only);
421  }
422 }
423 
425 {
426  everything_changed_ = false;
427  changed_locations_.clear();
428 }
429 
431 {
432  if(!everything_changed()) {
433  changed_locations_.insert(loc);
434  }
435 }
436 
437 void map_context::add_changed_location(const std::set<map_location>& locs)
438 {
439  if(!everything_changed()) {
440  changed_locations_.insert(locs.begin(), locs.end());
441  }
442 }
443 
445 {
446  everything_changed_ = true;
447 }
448 
450 {
451  return everything_changed_;
452 }
453 
455 {
456  disp.labels().clear_all();
458 }
459 
461 {
462  std::set<map_location> new_label_locs = map_.set_starting_position_labels(disp);
463  starting_position_label_locs_.insert(new_label_locs.begin(), new_label_locs.end());
464 }
465 
467 {
470  set_needs_labels_reset(false);
471 }
472 
474 {
475  config scenario;
476 
477  scenario["id"] = scenario_id_;
478  scenario["name"] = t_string(scenario_name_);
479  scenario["description"] = scenario_description_;
480 
481  if(xp_mod_) {
482  scenario["experience_modifier"] = *xp_mod_;
483  }
484  if(victory_defeated_) {
485  scenario["victory_when_enemies_defeated"] = *victory_defeated_;
486  }
487  scenario["random_start_time"] = random_time_;
488 
489  scenario.append(tod_manager_->to_config());
490  scenario.remove_attribute("turn_at");
491  scenario.remove_attribute("it_is_a_new_turn");
492  if(scenario["turns"].to_int() == -1) {
493  scenario.remove_attribute("turns");
494  }
495 
496  scenario["map_data"] = map_.write();
497 
498  labels_.write(scenario);
499 
500  for(const auto& overlay_pair : overlays_) {
501  for(const overlay& o : overlay_pair.second) {
502  config& item = scenario.add_child("item");
503 
504  // Write x,y location
505  overlay_pair.first.write(item);
506 
507  // These should always have a value
508  item["image"] = o.image;
509  item["visible_in_fog"] = o.visible_in_fog;
510 
511  // Optional keys
512  item["id"].write_if_not_empty(o.id);
513  item["name"].write_if_not_empty(o.name);
514  item["team_name"].write_if_not_empty(o.team_name);
515  item["halo"].write_if_not_empty(o.halo);
516  }
517  }
518 
519  for(const music_map::value_type& track : music_tracks_) {
520  track.second.write(scenario, true);
521  }
522 
523  for(std::vector<team>::const_iterator t = teams_.begin(); t != teams_.end(); ++t) {
524  int side_num = t - teams_.begin() + 1;
525 
526  config& side = scenario.add_child("side");
527 
528  side["side"] = side_num;
529  side["hidden"] = t->hidden();
530 
531  side["controller"] = t->controller();
532  side["no_leader"] = t->no_leader();
533 
534  side["team_name"] = t->team_name();
535  side["user_team_name"].write_if_not_empty(t->user_team_name());
536 
537  // TODO
538  // side["allow_player"] = "yes";
539 
540  side["fog"] = t->uses_fog();
541  side["shroud"] = t->uses_shroud();
542  side["share_vision"] = t->share_vision();
543 
544  side["gold"] = t->gold();
545  side["income"] = t->base_income();
546 
547  for(const map_location& village : t->villages()) {
548  village.write(side.add_child("village"));
549  }
550 
551  // current visible units
552  for(unit_map::const_iterator i = units_.begin(); i != units_.end(); ++i) {
553  if(i->side() == side_num) {
554  config& u = side.add_child("unit");
555 
556  i->get_location().write(u);
557 
558  u["type"] = i->type_id();
559  u["name"].write_if_not_empty(i->name());
560  u["facing"] = map_location::write_direction(i->facing());
561 
562  if(!boost::regex_match(i->id(), boost::regex(".*-[0-9]+"))) {
563  u["id"] = i->id();
564  }
565 
566  if(i->can_recruit()) {
567  u["canrecruit"] = i->can_recruit();
568  }
569 
570  if(i->unrenamable()) {
571  u["unrenamable"] = i->unrenamable();
572  }
573 
574  if(!i->recruits().empty()) {
575  u["extra_recruit"] = utils::join(i->recruits());
576  }
577  }
578  }
579  }
580 
581  return scenario;
582 }
583 
585 {
586  assert(!is_embedded());
587 
588  if(scenario_id_.empty()) {
590  }
591 
592  if(scenario_name_.empty()) {
594  }
595 
596  try {
597  std::stringstream wml_stream;
598  wml_stream
599  << "# This file was generated using the scenario editor.\n"
600  << "#\n"
601  << "# If you edit this file by hand, then you shouldn't use the\n"
602  << "# scenario editor on it afterwards. The editor completely\n"
603  << "# rewrites the file when it saves it, which will lose any WML\n"
604  << "# that the editor doesn't support.\n"
605  << "\n";
606  {
607  config_writer out(wml_stream, false);
608  out.write(to_config());
609  }
610 
611  if(!wml_stream.str().empty()) {
612  filesystem::write_file(get_filename(), wml_stream.str());
613  }
614 
615  clear_modified();
616  } catch(const filesystem::io_exception& e) {
617  utils::string_map symbols;
618  symbols["msg"] = e.what();
619  const std::string msg = VGETTEXT("Could not save the scenario: $msg", symbols);
620 
621  throw editor_map_save_exception(msg);
622  }
623 
624  // After saving the map as a scenario, it's no longer a pure map.
625  pure_map_ = false;
626 
627  // TODO the return value of this method does not need to be boolean.
628  // We either return true or there is an exception thrown.
629  return true;
630 }
631 
633 {
634  std::string map_data = map_.write();
635 
636  try {
637  if(!is_embedded()) {
639  } else {
640  std::string map_string = filesystem::read_file(get_filename());
641 
642  boost::regex rexpression_map_data(R"""((.*map_data\s*=\s*")(.+?)(".*))""");
643  boost::smatch matched_map_data;
644 
645  if(boost::regex_search(map_string, matched_map_data, rexpression_map_data,
646  boost::regex_constants::match_not_dot_null)) {
647  std::stringstream ss;
648  ss << matched_map_data[1];
649  ss << map_data;
650  ss << matched_map_data[3];
651 
653  } else {
654  throw editor_map_save_exception(_("Could not save into scenario"));
655  }
656  }
657 
659 
660  clear_modified();
661  } catch(const filesystem::io_exception& e) {
662  utils::string_map symbols;
663  symbols["msg"] = e.what();
664  const std::string msg = VGETTEXT("Could not save the map: $msg", symbols);
665 
666  throw editor_map_save_exception(msg);
667  }
668 
669  // TODO the return value of this method does not need to be boolean.
670  // We either return true or there is an exception thrown.
671  return true;
672 }
673 
675 {
676  if(map_.h() != map.h() || map_.w() != map.w()) {
678  } else {
680  }
681 
682  map_ = map;
683 }
684 
686 {
687  LOG_ED << "Performing action " << action.get_id() << ": " << action.get_name() << ", actions count is "
688  << action.get_instance_count() << std::endl;
689  auto undo = action.perform(*this);
690  if(actions_since_save_ < 0) {
691  // set to a value that will make it impossible to get to zero, as at this point
692  // it is no longer possible to get back the original map state using undo/redo
693  actions_since_save_ = 1 + undo_stack_.size();
694  }
695 
697 
698  undo_stack_.emplace_back(std::move(undo));
699 
701 
702  redo_stack_.clear();
703 }
704 
706 {
707  LOG_ED << "Performing (partial) action " << action.get_id() << ": " << action.get_name() << ", actions count is "
708  << action.get_instance_count() << std::endl;
709  if(!can_undo()) {
710  throw editor_logic_exception("Empty undo stack in perform_partial_action()");
711  }
712 
713  editor_action_chain* undo_chain = dynamic_cast<editor_action_chain*>(last_undo_action());
714  if(undo_chain == nullptr) {
715  throw editor_logic_exception("Last undo action not a chain in perform_partial_action()");
716  }
717 
718  auto undo = action.perform(*this);
719 
720  // actions_since_save_ += action.action_count();
721  undo_chain->prepend_action(std::move(undo));
722 
723  redo_stack_.clear();
724 }
725 
727 {
728  return actions_since_save_ != 0;
729 }
730 
732 {
734 }
735 
737 {
739 }
740 
742 {
743  return !undo_stack_.empty();
744 }
745 
747 {
748  return !redo_stack_.empty();
749 }
750 
752 {
753  return undo_stack_.empty() ? nullptr : undo_stack_.back().get();
754 }
755 
757 {
758  return redo_stack_.empty() ? nullptr : redo_stack_.back().get();
759 }
760 
762 {
763  return undo_stack_.empty() ? nullptr : undo_stack_.back().get();
764 }
765 
767 {
768  return redo_stack_.empty() ? nullptr : redo_stack_.back().get();
769 }
770 
772 {
773  LOG_ED << "undo() beg, undo stack is " << undo_stack_.size() << ", redo stack " << redo_stack_.size() << std::endl;
774 
775  if(can_undo()) {
778  } else {
779  WRN_ED << "undo() called with an empty undo stack" << std::endl;
780  }
781 
782  LOG_ED << "undo() end, undo stack is " << undo_stack_.size() << ", redo stack " << redo_stack_.size() << std::endl;
783 }
784 
786 {
787  LOG_ED << "redo() beg, undo stack is " << undo_stack_.size() << ", redo stack " << redo_stack_.size() << std::endl;
788 
789  if(can_redo()) {
792  } else {
793  WRN_ED << "redo() called with an empty redo stack" << std::endl;
794  }
795 
796  LOG_ED << "redo() end, undo stack is " << undo_stack_.size() << ", redo stack " << redo_stack_.size() << std::endl;
797 }
798 
800 {
801  // callers should check for these conditions
802  if(!can_undo()) {
803  throw editor_logic_exception("Empty undo stack in partial_undo()");
804  }
805 
806  editor_action_chain* undo_chain = dynamic_cast<editor_action_chain*>(last_undo_action());
807  if(undo_chain == nullptr) {
808  throw editor_logic_exception("Last undo action not a chain in partial undo");
809  }
810 
811  // a partial undo performs the first action form the current action's action_chain that would be normally performed
812  // i.e. the *first* one.
813  const auto first_action_in_chain = undo_chain->pop_first_action();
814  if(undo_chain->empty()) {
816  undo_stack_.pop_back();
817  }
818 
819  redo_stack_.emplace_back(first_action_in_chain->perform(*this));
820  // actions_since_save_ -= last_redo_action()->action_count();
821 }
822 
824 {
825  undo_stack_.clear();
826  redo_stack_.clear();
827 }
828 
830 {
831  if(stack.size() > max_action_stack_size_) {
832  stack.pop_front();
833  }
834 }
835 
837 {
838  assert(!from.empty());
839 
840  std::unique_ptr<editor_action> action;
841  action.swap(from.back());
842 
843  from.pop_back();
844 
845  auto reverse_action = action->perform(*this);
846  to.emplace_back(std::move(reverse_action));
847 
848  trim_stack(to);
849 }
850 
852 {
853  return is_pure_map() ? _("New Map") : _("New Scenario");
854 }
855 
856 } // 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:30
void set_shroud(bool shroud)
Definition: team.hpp:338
game_classification game_classification_
unit_iterator end()
Definition: map.hpp:429
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:55
std::map< std::string, t_string > string_map
int village_support
Definition: game_config.cpp:56
void set_terrain(const map_location &loc, const terrain_code &terrain, const terrain_type_data::merge_mode mode=terrain_type_data::BOTH, bool replace_if_failed=false) override
Clobbers over the terrain at location &#39;loc&#39;, with the given terrain.
Definition: map.cpp:397
void append(const config &cfg)
Append data from another config object to this one.
Definition: config.cpp:269
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:59
team::SHARE_VISION share_vision
Definition: map_context.hpp:47
std::set< map_location > set_starting_position_labels(display &disp)
Set labels for staring positions in the given display object.
Definition: editor_map.cpp:136
umap_retval_pair_t insert(unit_ptr p)
Inserts the unit pointed to by p into the map.
Definition: map.cpp:134
virtual const std::string & get_name() const
Definition: action_base.hpp:75
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:89
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:142
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:344
#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:780
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:419
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
const terrain_type & get_terrain_info(const t_translation::terrain_code &terrain) const
Definition: map.cpp:98
static int get_instance_count()
Debugging aid.
const ter_layer NO_LAYER
Definition: translation.hpp:41
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:110
lg::log_domain log_editor
Container action wrapping several actions into one.
Definition: action.hpp:87
static std::string _(const char *str)
Definition: gettext.hpp:93
void change_controller(const std::string &new_controller)
Definition: team.hpp:287
void set_share_vision(const std::string &vision_status)
Definition: team.hpp:406
void set_hidden(bool value)
Definition: team.hpp:361
void remove_attribute(config_key_type key)
Definition: config.cpp:217
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:190
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)
void set_map(const editor_map &map)
std::string filename_
Definition: action_wml.cpp:564
bool modified() const
std::string id
Definition: overlay.hpp:56
#define WRN_ED
bool fog()
Definition: game.cpp:539
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:72
void have_leader(bool value=true)
Definition: team.hpp:359
std::unique_ptr< tod_manager > tod_manager_
std::vector< team > teams_
editor_team_info(const team &t)
Definition: map_context.cpp:39
int w() const
Effective map width.
Definition: map.hpp:50
void read(config &cfg, std::istream &in, abstract_validator *validator)
Definition: parser.cpp:627
Class for writing a config out to a file in pieces.
terrain_code get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
Definition: map.cpp:302
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.
bool on_board_with_border(const map_location &loc) const
Definition: map.cpp:390
int get_id() const
Debugging aid.
Definition: action_base.hpp:93
void prepend_action(std::unique_ptr< editor_action > a)
Add an action at the beginning of the chain.
Definition: action.cpp:121
void replace_schedule(const std::vector< time_of_day > &schedule)
t_string name
Definition: overlay.hpp:55
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:80
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:213
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:219
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:665
Manage the empty-palette in the editor.
Definition: action.cpp:30
void perform_action(const editor_action &action)
Performs an action (thus modifying the map).
const char * what() const noexcept
Definition: exceptions.hpp:36
void set_fog(bool fog)
Definition: team.hpp:339
std::string read_file(const std::string &fname)
Basic disk I/O - read file.
Definition: filesystem.cpp:998
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:38
void set_village_gold(int income)
Definition: team.hpp:206
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:549
std::string id
Text to match against addon_info.tags()
Definition: manager.cpp:215
void set_starting_position_labels(display &disp)
This class adds extra editor-specific functionality to a normal gamemap.
Definition: editor_map.hpp:70
std::size_t i
Definition: function.cpp:967
void set_gold(int amount)
Definition: team.hpp:218
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:59
map_context(const map_context &)=delete
int village_income
Definition: game_config.cpp:55
t_translation::terrain_code terrain_with_default_base() const
Definition: terrain.cpp:297
An exception object used when an IO error occurs.
Definition: filesystem.hpp:48
Base class for all editor actions.
Definition: action_base.hpp:41
Internal representation of music tracks.
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:72
#define VGETTEXT(msgid,...)
Handy wrappers around interpolate_variables_into_string and gettext.
config & add_child(config_key_type key)
Definition: config.cpp:514
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:64
std::string halo
Definition: overlay.hpp:53
bool victory_defeated() const
void read(const config &cfg)
Definition: label.cpp:92
int turns()
Definition: game.cpp:559
double t
Definition: astarsearch.cpp:65
virtual const editor_map & map() const override
Const map accessor.
team::CONTROLLER controller
Definition: map_context.hpp:48
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:30
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:618
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:2536
#define e
void set_base_income(int amount)
Definition: team.hpp:221
void add_recent_files_entry(const std::string &path)
Adds an entry to the recent files list.
Definition: editor.cpp:124
void clear_all()
Definition: label.cpp:240
std::set< map_location > changed_locations_
std::string team_name
Definition: overlay.hpp:54
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:61
filesystem::scoped_istream preprocess_file(const std::string &fname, preproc_map *defines)
Function to use the WML preprocessor on a file.
int h() const
Effective map height.
Definition: map.hpp:53
static std::string write_direction(DIRECTION dir)
Definition: location.cpp:141
mp_game_settings mp_settings_
bool set_selection(const std::set< map_location > &area)
Select the given area.
Definition: editor_map.cpp:168
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:410
const t_string get_default_context_name() const
bool select_area(int index)
Select the nth tod area.
std::string image
Definition: overlay.hpp:52
bool everything_changed() const