The Battle for Wesnoth  1.17.12+dev
map_context.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2022
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 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";
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";
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 << "}";
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;
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;
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 << ")";
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  if(o.submerge) {
517  item["submerge"] = o.submerge;
518  }
519  }
520  }
521 
522  for(const music_map::value_type& track : music_tracks_) {
523  track.second.write(scenario, true);
524  }
525 
526  for(std::vector<team>::const_iterator t = teams_.begin(); t != teams_.end(); ++t) {
527  int side_num = t - teams_.begin() + 1;
528 
529  config& side = scenario.add_child("side");
530 
531  side["side"] = side_num;
532  side["hidden"] = t->hidden();
533 
534  side["controller"] = side_controller::get_string(t->controller());
535  side["no_leader"] = t->no_leader();
536 
537  side["team_name"] = t->team_name();
538  side["user_team_name"].write_if_not_empty(t->user_team_name());
539 
540  // TODO
541  // side["allow_player"] = "yes";
542 
543  side["fog"] = t->uses_fog();
544  side["shroud"] = t->uses_shroud();
545  side["share_vision"] = team_shared_vision::get_string(t->share_vision());
546 
547  side["gold"] = t->gold();
548  side["income"] = t->base_income();
549 
550  for(const map_location& village : t->villages()) {
551  village.write(side.add_child("village"));
552  }
553 
554  // current visible units
555  for(unit_map::const_iterator i = units_.begin(); i != units_.end(); ++i) {
556  if(i->side() == side_num) {
557  config& u = side.add_child("unit");
558 
559  i->get_location().write(u);
560 
561  u["type"] = i->type_id();
562  u["name"].write_if_not_empty(i->name());
563  u["facing"] = map_location::write_direction(i->facing());
564 
565  if(!boost::regex_match(i->id(), boost::regex(".*-[0-9]+"))) {
566  u["id"] = i->id();
567  }
568 
569  if(i->can_recruit()) {
570  u["canrecruit"] = i->can_recruit();
571  }
572 
573  if(i->unrenamable()) {
574  u["unrenamable"] = i->unrenamable();
575  }
576 
577  if(!i->recruits().empty()) {
578  u["extra_recruit"] = utils::join(i->recruits());
579  }
580  }
581  }
582  }
583 
584  return scenario;
585 }
586 
588 {
589  assert(!is_embedded());
590 
591  if(scenario_id_.empty()) {
593  }
594 
595  if(scenario_name_.empty()) {
597  }
598 
599  try {
600  std::stringstream wml_stream;
601  wml_stream
602  << "# This file was generated using the scenario editor.\n"
603  << "#\n"
604  << "# If you edit this file by hand, then you shouldn't use the\n"
605  << "# scenario editor on it afterwards. The editor completely\n"
606  << "# rewrites the file when it saves it, which will lose any WML\n"
607  << "# that the editor doesn't support.\n"
608  << "\n";
609  {
610  config_writer out(wml_stream, false);
611  out.write(to_config());
612  }
613 
614  if(!wml_stream.str().empty()) {
615  filesystem::write_file(get_filename(), wml_stream.str());
616  }
617 
618  clear_modified();
619  } catch(const filesystem::io_exception& e) {
620  utils::string_map symbols;
621  symbols["msg"] = e.what();
622  const std::string msg = VGETTEXT("Could not save the scenario: $msg", symbols);
623 
624  throw editor_map_save_exception(msg);
625  }
626 
627  // After saving the map as a scenario, it's no longer a pure map.
628  pure_map_ = false;
629 
630  // TODO the return value of this method does not need to be boolean.
631  // We either return true or there is an exception thrown.
632  return true;
633 }
634 
636 {
637  std::string map_data = map_.write();
638 
639  try {
640  if(!is_embedded()) {
642  } else {
643  std::string map_string = filesystem::read_file(get_filename());
644 
645  boost::regex rexpression_map_data(R"""((.*map_data\s*=\s*")(.+?)(".*))""");
646  boost::smatch matched_map_data;
647 
648  if(boost::regex_search(map_string, matched_map_data, rexpression_map_data,
649  boost::regex_constants::match_not_dot_null)) {
650  std::stringstream ss;
651  ss << matched_map_data[1];
652  ss << map_data;
653  ss << matched_map_data[3];
654 
656  } else {
657  throw editor_map_save_exception(_("Could not save into scenario"));
658  }
659  }
660 
662 
663  clear_modified();
664  } catch(const filesystem::io_exception& e) {
665  utils::string_map symbols;
666  symbols["msg"] = e.what();
667  const std::string msg = VGETTEXT("Could not save the map: $msg", symbols);
668 
669  throw editor_map_save_exception(msg);
670  }
671 
672  // TODO the return value of this method does not need to be boolean.
673  // We either return true or there is an exception thrown.
674  return true;
675 }
676 
678 {
679  if(map_.h() != map.h() || map_.w() != map.w()) {
681  } else {
683  }
684 
685  map_ = map;
686 }
687 
689 {
690  LOG_ED << "Performing action " << action.get_id() << ": " << action.get_name() << ", actions count is "
691  << action.get_instance_count();
692  auto undo = action.perform(*this);
693  if(actions_since_save_ < 0) {
694  // set to a value that will make it impossible to get to zero, as at this point
695  // it is no longer possible to get back the original map state using undo/redo
696  actions_since_save_ = 1 + undo_stack_.size();
697  }
698 
700 
701  undo_stack_.emplace_back(std::move(undo));
702 
704 
705  redo_stack_.clear();
706 }
707 
709 {
710  LOG_ED << "Performing (partial) action " << action.get_id() << ": " << action.get_name() << ", actions count is "
711  << action.get_instance_count();
712  if(!can_undo()) {
713  throw editor_logic_exception("Empty undo stack in perform_partial_action()");
714  }
715 
716  editor_action_chain* undo_chain = dynamic_cast<editor_action_chain*>(last_undo_action());
717  if(undo_chain == nullptr) {
718  throw editor_logic_exception("Last undo action not a chain in perform_partial_action()");
719  }
720 
721  auto undo = action.perform(*this);
722 
723  // actions_since_save_ += action.action_count();
724  undo_chain->prepend_action(std::move(undo));
725 
726  redo_stack_.clear();
727 }
728 
730 {
731  return actions_since_save_ != 0;
732 }
733 
735 {
737 }
738 
740 {
742 }
743 
745 {
746  return !undo_stack_.empty();
747 }
748 
750 {
751  return !redo_stack_.empty();
752 }
753 
755 {
756  return undo_stack_.empty() ? nullptr : undo_stack_.back().get();
757 }
758 
760 {
761  return redo_stack_.empty() ? nullptr : redo_stack_.back().get();
762 }
763 
765 {
766  return undo_stack_.empty() ? nullptr : undo_stack_.back().get();
767 }
768 
770 {
771  return redo_stack_.empty() ? nullptr : redo_stack_.back().get();
772 }
773 
775 {
776  LOG_ED << "undo() beg, undo stack is " << undo_stack_.size() << ", redo stack " << redo_stack_.size();
777 
778  if(can_undo()) {
781  } else {
782  WRN_ED << "undo() called with an empty undo stack";
783  }
784 
785  LOG_ED << "undo() end, undo stack is " << undo_stack_.size() << ", redo stack " << redo_stack_.size();
786 }
787 
789 {
790  LOG_ED << "redo() beg, undo stack is " << undo_stack_.size() << ", redo stack " << redo_stack_.size();
791 
792  if(can_redo()) {
795  } else {
796  WRN_ED << "redo() called with an empty redo stack";
797  }
798 
799  LOG_ED << "redo() end, undo stack is " << undo_stack_.size() << ", redo stack " << redo_stack_.size();
800 }
801 
803 {
804  // callers should check for these conditions
805  if(!can_undo()) {
806  throw editor_logic_exception("Empty undo stack in partial_undo()");
807  }
808 
809  editor_action_chain* undo_chain = dynamic_cast<editor_action_chain*>(last_undo_action());
810  if(undo_chain == nullptr) {
811  throw editor_logic_exception("Last undo action not a chain in partial undo");
812  }
813 
814  // a partial undo performs the first action form the current action's action_chain that would be normally performed
815  // i.e. the *first* one.
816  const auto first_action_in_chain = undo_chain->pop_first_action();
817  if(undo_chain->empty()) {
819  undo_stack_.pop_back();
820  }
821 
822  redo_stack_.emplace_back(first_action_in_chain->perform(*this));
823  // actions_since_save_ -= last_redo_action()->action_count();
824 }
825 
827 {
828  undo_stack_.clear();
829  redo_stack_.clear();
830 }
831 
833 {
834  if(stack.size() > max_action_stack_size_) {
835  stack.pop_front();
836  }
837 }
838 
840 {
841  assert(!from.empty());
842 
843  std::unique_ptr<editor_action> action;
844  action.swap(from.back());
845 
846  from.pop_back();
847 
848  auto reverse_action = action->perform(*this);
849  to.emplace_back(std::move(reverse_action));
850 
851  trim_stack(to);
852 }
853 
855 {
856  return is_pure_map() ? _("New Map") : _("New Scenario");
857 }
858 
859 } // 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:313
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:62
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:182
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:264
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:49
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:40
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:263
void set_share_vision(const std::string &vision_status)
Definition: team.hpp:381
void set_hidden(bool value)
Definition: team.hpp:336
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:202
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:565
bool modified() const
std::string id
Definition: overlay.hpp:59
#define WRN_ED
bool fog()
Definition: game.cpp:525
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:75
void have_leader(bool value=true)
Definition: team.hpp:334
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
side_controller::type controller
Definition: map_context.hpp:49
void reset_starting_position_labels(display &disp)
float submerge
Definition: overlay.hpp:63
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:58
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:189
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:238
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:651
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:314
std::string read_file(const std::string &fname)
Basic disk I/O - read file.
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:182
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:535
std::string id
Text to match against addon_info.tags()
Definition: manager.cpp:215
void set_starting_position_labels(display &disp)
void write_file(const std::string &fname, const std::string &data, std::ios_base::openmode mode)
Throws io_exception if an error occurs.
This class adds extra editor-specific functionality to a normal gamemap.
Definition: editor_map.hpp:70
std::size_t i
Definition: function.cpp:968
void set_gold(int amount)
Definition: team.hpp:194
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:60
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:56
bool victory_defeated() const
void read(const config &cfg)
Definition: label.cpp:92
int turns()
Definition: game.cpp:545
team_shared_vision::type share_vision
Definition: map_context.hpp:48
double t
Definition: astarsearch.cpp:65
virtual const editor_map & map() const override
Const map accessor.
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:614
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:2619
#define e
void set_base_income(int amount)
Definition: team.hpp:197
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:57
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.
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:414
const t_string get_default_context_name() const
bool select_area(int index)
Select the nth tod area.
static std::string get_string(enum_type key)
Converts a enum to its string equivalent.
Definition: enum_base.hpp:46
std::string image
Definition: overlay.hpp:55
bool everything_changed() const