The Battle for Wesnoth  1.19.5+dev
terrain_palettes.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2024
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 = gui_.get_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();
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  std::map<std::string, item_group*>::iterator i = id_to_group.find(k);
137  if (i != id_to_group.end()) {
138  if (i->second->core) {
139  core = true;
140  }
141  }
142  }
143 
144  // A terrain is considered core iff it appears in at least
145  // one core terrain group
146  if (core) {
147  // Add the terrain to the default group
148  group_map_["all"].push_back(get_id(t));
149  } else {
150  non_core_items_.insert(get_id(t));
151  }
152 
153  }
154 
155  // Set the default terrain
156  select_fg_item("regular_mountains");
157  select_bg_item("grassland");
158 
159  // Set the default group
160  set_group("all");
161 
162  if(active_group().empty()) {
163  ERR_ED << "No items found.";
164  }
165 }
166 
168  const t_translation::terrain_code& terrain,
169  texture& base_image,
170  texture& overlay_image,
171  std::stringstream& tooltip_text)
172 {
173  const auto& info = gui_.get_map().get_terrain_info(terrain);
174 
175  //Draw default base for overlay terrains
176  if(info.has_default_base()) {
177  const std::string base_filename = info.editor_image();
178  base_image = image::get_texture(base_filename);
179 
180  if(!base_image) {
181  tooltip_text << "BASE IMAGE NOT FOUND\n";
182  ERR_ED << "image for terrain : '" << base_filename << "' not found";
184  if(!base_image) {
185  ERR_ED << "Placeholder image not found";
186  return;
187  }
188  }
189  }
190 
191  const std::string filename = info.editor_image();
192  overlay_image = image::get_texture(filename);
193  if(!overlay_image) {
194  tooltip_text << "IMAGE NOT FOUND\n";
195  ERR_ED << "image for terrain: '" << filename << "' not found";
197  if(!overlay_image) {
198  ERR_ED << "Placeholder image not found";
199  return;
200  }
201  }
202 
203  tooltip_text << gui_.get_map().get_terrain_editor_string(terrain);
205  tooltip_text << " " + font::unicode_em_dash + " " << terrain;
206  }
207 }
208 
210 //TODO avoid magic numbers
211  : editor_palette<t_translation::terrain_code>(gui, 36, 4, toolkit)
212 {
213 }
214 
215 const std::string& terrain_palette::get_id(const t_translation::terrain_code& terrain)
216 {
217  const terrain_type& t_info = gui_.get_map().get_terrain_info(terrain);
218  return t_info.id();
219 }
220 
222 {
223  std::ostringstream msg;
224  msg << _("Left-click: ") << gui_.get_map().get_terrain_editor_string(selected_fg_item()) << " | "
225  << _("Right-click: ") << gui_.get_map().get_terrain_editor_string(selected_bg_item()) << "\n";
227  // TRANSLATORS: Similar behavior applies to shift + right-click. This message specifies left-click
228  // because the logic of whether to show the "overlay only" or "base only" version depends on the
229  // terrain currently selected for the left button.
230  msg << _("Shift + left-click: paint overlay layer only") << " | ";
231  } else {
232  msg << _("Shift + left-click: paint base layer only") << " | ";
233  }
234 #ifdef __APPLE__
235  msg << _("Cmd + click: copy terrain") << std::endl;
236 #else
237  msg << _("Ctrl + click: copy terrain") << std::endl;
238 #endif
239  return msg.str();
240 }
241 
242 
243 }
double t
Definition: astarsearch.cpp:63
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:172
@ DEBUG_TERRAIN_CODES
Overlays terrain codes on tiles.
Definition: display.hpp:922
bool debug_flag_set(DEBUG_FLAG flag) const
Definition: display.hpp:937
const editor_map & get_map() const
std::vector< item_group > groups_
The editor_groups as defined in editor-groups.cfg.
virtual void select_bg_item(const std::string &item_id) override
const std::vector< std::string > & active_group()
std::map< std::string, std::vector< std::string > > group_map_
virtual void select_fg_item(const std::string &item_id) override
Select a foreground item.
terrain_palette(editor_display &gui, editor_toolkit &toolkit)
void select_fg_item(const t_translation::terrain_code &terrain)
virtual void setup_item(const t_translation::terrain_code &item, texture &item_base_image, texture &item_overlay_image, std::stringstream &tooltip) override
Setup item image and tooltip.
virtual void setup(const game_config_view &cfg) override
Setup the internal data structure.
const t_translation::terrain_code & selected_bg_item() const
virtual const std::string & get_id(const t_translation::terrain_code &terrain) override
virtual std::string get_help_string() const override
const t_translation::terrain_code & selected_fg_item() const
void select_bg_item(const t_translation::terrain_code &terrain)
A class grating read only view to a vector of config objects, viewed as one config with all children ...
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
std::string get_terrain_editor_string(const map_location &loc) const
Definition: map.cpp:63
const terrain_type & get_terrain_info(const t_translation::terrain_code &terrain) const
Definition: map.cpp:98
const std::string & editor_group() const
Definition: terrain.hpp:152
const t_string & name() const
Definition: terrain.hpp:48
bool is_combined() const
True for instances created by the terrain_code(base, overlay) constructor.
Definition: terrain.hpp:167
const std::string & id() const
Definition: terrain.hpp:52
const t_string & editor_name() const
Definition: terrain.hpp:49
bool hide_in_editor() const
Definition: terrain.hpp:62
t_translation::terrain_code number() const
Definition: terrain.hpp:66
Wrapper class to encapsulate creation and management of an SDL_Texture.
Definition: texture.hpp:33
#define ERR_ED
#define DBG_ED
std::size_t i
Definition: function.cpp:1028
static std::string _(const char *str)
Definition: gettext.hpp:93
Manage the empty-palette in the editor.
Definition: action.cpp:31
static bool is_valid_terrain(const t_translation::terrain_code &c)
const t_translation::terrain_code & get_selected_bg_terrain()
const t_translation::terrain_code & get_selected_fg_terrain()
const std::string unicode_em_dash
Definition: constants.cpp:44
General purpose widgets.
texture get_texture(const image::locator &i_locator, TYPE type, bool skip_cache)
Returns an image texture suitable for hardware-accelerated rendering.
Definition: picture.cpp:920
logger & info()
Definition: log.cpp:319
const terrain_code VOID_TERRAIN
VOID_TERRAIN is used for shrouded hexes.
const ter_layer NO_LAYER
Definition: translation.hpp:40
std::vector< terrain_code > ter_list
Definition: translation.hpp:77
const terrain_code FOGGED
std::vector< std::string > split(const config_attribute_value &val)
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
std::string filename
Filename.
Stores the info about the groups in a nice format.
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
mock_char c