The Battle for Wesnoth  1.17.0-dev
terrain_palettes.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2021
3  by David White <dave@whitevine.net>
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 /**
17  * Terrain-palette in the editor.
18  */
19 
20 #define GETTEXT_DOMAIN "wesnoth-editor"
21 
23 
24 #include "gettext.hpp"
26 #include "game_config_view.hpp"
27 
28 namespace {
29  static t_translation::terrain_code fg_terrain;
30  static t_translation::terrain_code bg_terrain;
31 }
32 
33 namespace editor {
34 
36  return bg_terrain;
37 }
38 
40  return fg_terrain;
41 }
42 
45 
46 
49 }
50 
51 void terrain_palette::select_bg_item(const std::string& item_id) {
52  bg_terrain = item_map_[item_id];
54 }
55 
56 void terrain_palette::select_fg_item(const std::string& item_id) {
57  fg_terrain = item_map_[item_id];
59 }
60 
62  bg_terrain = terrain;
64 }
65 
67  fg_terrain = terrain;
69 }
70 
71 
73 {
74  // Get the available terrains temporary in items
76 
77  //move "invalid" items to the end
78  std::stable_partition(items.begin(), items.end(), is_valid_terrain);
79 
80  // Get the available groups and add them to the structure
81  std::set<std::string> group_names;
82  for(const config &group : cfg.child_range("terrain_group")) {
83  if(group_names.count(group["id"]) == 0) {
84  config group_cfg;
85  group_cfg["id"] = group["id"];
86  group_cfg["name"] = group["name"];
87 
88  group_cfg["icon"] = group["icon"].str();
89  group_cfg["core"] = group["core"];
90  groups_.emplace_back(group_cfg);
91 
92  group_names.insert(groups_.back().id);
93  }
94  }
95  for(const config &group : cfg.child_range("editor_group")) {
96  if(group_names.count(group["id"]) == 0) {
97  config group_cfg;
98  group_cfg["id"] = group["id"];
99  group_cfg["name"] = group["name"];
100 
101  group_cfg["icon"] = "icons/terrain/terrain_" + group["icon"].str();
102  group_cfg["core"] = group["core"];
103  groups_.emplace_back(group_cfg);
104 
105  group_names.insert(groups_.back().id);
106  }
107  }
108 
109  std::map<std::string, item_group*> id_to_group;
110  for (item_group& group : groups_) {
111  id_to_group.emplace(group.id, &group);
112  }
113 
114  // add the groups for all terrains to the map
115  for (const t_translation::terrain_code& t : items) {
116 
117  const terrain_type& t_info = map().get_terrain_info(t);
118  DBG_ED << "Palette: processing terrain " << t_info.name()
119  << "(editor name: '" << t_info.editor_name() << "') "
120  << "(" << t_info.number() << ")"
121  << ": " << t_info.editor_group() << "\n";
122 
123  // don't display terrains that were automatically created from base+overlay
124  if (t_info.is_combined()) continue;
125  // nor display terrains that have hide_in_editor=true
126  if (t_info.hide_in_editor()) continue;
127 
128  // add the terrain to the requested groups
129  const std::vector<std::string>& keys = utils::split(t_info.editor_group());
130  bool core = false;
131 
132  item_map_[get_id(t)] = t;
133 
134  for (const std::string& k : keys) {
135  group_map_[k].push_back(get_id(t));
136  nmax_items_ = std::max<int>(nmax_items_, group_map_[k].size());
137  std::map<std::string, item_group*>::iterator i = id_to_group.find(k);
138  if (i != id_to_group.end()) {
139  if (i->second->core) {
140  core = true;
141  }
142  }
143  }
144 
145  // A terrain is considered core iff it appears in at least
146  // one core terrain group
147  if (core) {
148  // Add the terrain to the default group
149  group_map_["all"].push_back(get_id(t));
150  nmax_items_ = std::max<int>(nmax_items_, group_map_["all"].size());
151  } else {
152  non_core_items_.insert(get_id(t));
153  }
154 
155  }
156 
157  // Set the default terrain
158  select_fg_item("regular_mountains");
159  select_bg_item("grassland");
160 
161  // Set the default group
162  set_group("all");
163 
164  if(active_group().empty()) {
165  ERR_ED << "No items found." << std::endl;
166  }
167 }
168 
170  surface& image, std::stringstream& tooltip_text) {
171 
172  const t_translation::terrain_code base_terrain = map().get_terrain_info(terrain).default_base();
173 
174  //Draw default base for overlay terrains
175  if(base_terrain != t_translation::NONE_TERRAIN) {
176  const std::string base_filename = map().get_terrain_info(base_terrain).editor_image();
177  surface base_image(image::get_image(base_filename));
178 
179  if(base_image == nullptr) {
180  tooltip_text << "BASE IMAGE NOT FOUND\n";
181  ERR_ED << "image for terrain : '" << base_filename << "' not found" << std::endl;
183  if(base_image == nullptr) {
184  ERR_ED << "Placeholder image not found" << std::endl;
185  return;
186  }
187  }
188 
189  if(base_image->w != item_size_ || base_image->h != item_size_) {
190  base_image = scale_surface(base_image,
192  }
193  }
194 
195  const std::string filename = map().get_terrain_info(terrain).editor_image();
196  image = image::get_image(filename);
197  if(image == nullptr) {
198  tooltip_text << "IMAGE NOT FOUND\n";
199  ERR_ED << "image for terrain: '" << filename << "' not found" << std::endl;
201  if(image == nullptr) {
202  ERR_ED << "Placeholder image not found" << std::endl;
203  return;
204  }
205  }
206 
207  if(image->w != item_size_ || image->h != item_size_) {
208  image = scale_surface(image, item_size_, item_size_);
209  }
210 
211  tooltip_text << map().get_terrain_editor_string(terrain);
213  tooltip_text << " " + font::unicode_em_dash + " " << terrain;
214  }
215 }
216 
218 //TODO avoid magic numbers
219  : editor_palette<t_translation::terrain_code>(gui, cfg, 36, 4, toolkit)
220 {
221 }
222 
223 const std::string& terrain_palette::get_id(const t_translation::terrain_code& terrain)
224 {
225  const terrain_type& t_info = map().get_terrain_info(terrain);
226  return t_info.id();
227 }
228 
230 {
231  std::ostringstream msg;
232  msg << _("Left-click: ") << map().get_terrain_editor_string(selected_fg_item()) << " | "
233  << _("Right-click: ") << map().get_terrain_editor_string(selected_bg_item()) << "\n";
235  // TRANSLATORS: Similar behavior applies to shift + right-click. This message specifies left-click
236  // because the logic of whether to show the "overlay only" or "base only" version depends on the
237  // terrain currently selected for the left button.
238  msg << _("Shift + left-click: paint overlay layer only") << " | ";
239  } else {
240  msg << _("Shift + left-click: paint base layer only") << " | ";
241  }
242 #ifdef __APPLE__
243  msg << _("Cmd + click: copy terrain") << std::endl;
244 #else
245  msg << _("Ctrl + click: copy terrain") << std::endl;
246 #endif
247  return msg.str();
248 }
249 
250 
251 }
surface get_image(const image::locator &i_locator, TYPE type)
Caches and returns an image.
Definition: picture.cpp:816
virtual const std::string & get_id(const t_translation::terrain_code &terrain)
const t_translation::terrain_code & get_selected_bg_terrain()
terrain_palette(editor_display &gui, const game_config_view &cfg, editor_toolkit &toolkit)
const terrain_code NONE_TERRAIN
Definition: translation.hpp:59
virtual void select_fg_item(const std::string &item_id) override
Select a foreground item.
const gamemap & map() const
Stores the info about the groups in a nice format.
virtual void select_bg_item(const std::string &item_id) override
config_array_view child_range(config_key_type key) const
const t_translation::ter_list & get_terrain_list() const
Gets the list of terrains.
Definition: map.cpp:44
General purpose widgets.
const t_translation::terrain_code & selected_bg_item() const
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
const std::vector< std::string > & active_group()
const ter_layer NO_LAYER
Definition: translation.hpp:41
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:110
const std::vector< std::string > items
surface scale_surface(const surface &surf, int w, int h)
Scale a surface using alpha-weighted modified bilinear filtering Note: causes artifacts with alpha gr...
Definition: utils.cpp:197
const std::string & editor_image() const
Definition: terrain.hpp:47
static std::string _(const char *str)
Definition: gettext.hpp:93
const t_translation::terrain_code & get_selected_fg_terrain()
const terrain_code VOID_TERRAIN
VOID_TERRAIN is used for shrouded hexes.
void select_bg_item(const t_translation::terrain_code &terrain)
virtual std::string get_help_string()
const t_string & editor_name() const
Definition: terrain.hpp:49
t_translation::terrain_code default_base() const
Definition: terrain.hpp:169
bool is_combined() const
True for instances created by the terrain_code(base, overlay) constructor.
Definition: terrain.hpp:167
const terrain_code FOGGED
std::map< std::string, std::vector< std::string > > group_map_
Manage the empty-palette in the editor.
Definition: action.cpp:30
void select_fg_item(const t_translation::terrain_code &terrain)
std::size_t i
Definition: function.cpp:967
std::string get_terrain_editor_string(const map_location &loc) const
Definition: map.cpp:63
t_translation::terrain_code number() const
Definition: terrain.hpp:66
static bool is_valid_terrain(const t_translation::terrain_code &c)
bool hide_in_editor() const
Definition: terrain.hpp:62
const t_string & name() const
Definition: terrain.hpp:48
virtual void setup(const game_config_view &cfg)
Setup the internal data structure.
double t
Definition: astarsearch.cpp:65
std::vector< std::string > split(const config_attribute_value &val)
const std::string unicode_em_dash
Definition: constants.cpp:44
#define ERR_ED
Functions to load and save images from/to disk.
const std::string & id() const
Definition: terrain.hpp:52
std::vector< terrain_code > ter_list
Definition: translation.hpp:78
virtual void draw_item(const t_translation::terrain_code &terrain, surface &item_image, std::stringstream &tooltip_text)
const t_translation::terrain_code & selected_fg_item() const
std::vector< item_group > groups_
The editor_groups as defined in editor-groups.cfg.
bool get_draw_terrain_codes() const
Getter for the terrain code debug overlay on tiles.
Definition: display.hpp:363
#define DBG_ED
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:61
mock_char c
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
const std::string & editor_group() const
Definition: terrain.hpp:152