The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
terrain_palettes.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2003 - 2025
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
28namespace {
29 static t_translation::terrain_code fg_terrain;
30 static t_translation::terrain_code bg_terrain;
31}
32
33namespace editor {
34
36 return bg_terrain;
37}
38
40 return fg_terrain;
41}
42
45
46
50
51void terrain_palette::select_bg_item(const std::string& item_id) {
52 bg_terrain = item_map_[item_id];
54}
55
56void terrain_palette::select_fg_item(const std::string& item_id) {
57 fg_terrain = item_map_[item_id];
59}
60
65
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
215const 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
A config object defines a single node in a WML file, with access to child nodes.
Definition config.hpp:157
void insert(std::string_view key, T &&value)
Inserts an attribute into the config.
Definition config.hpp:519
child_itors child_range(std::string_view key)
Definition config.cpp:268
@ DEBUG_TERRAIN_CODES
Overlays terrain codes on tiles.
Definition display.hpp:901
bool debug_flag_set(DEBUG_FLAG flag) const
Definition display.hpp:916
const editor_map & get_map() const
std::vector< item_group > groups_
The editor_groups as defined in terrain-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 ...
const t_translation::ter_list & get_terrain_list() const
Gets the list of terrains.
Definition map.cpp:42
std::string get_terrain_editor_string(const map_location &loc) const
Definition map.cpp:55
const terrain_type & get_terrain_info(const t_translation::terrain_code &terrain) const
Definition map.cpp:78
bool is_combined() const
True for instances created by the terrain_code(base, overlay) constructor.
Definition terrain.hpp:177
const std::string & id() const
Definition terrain.hpp:52
const t_string & name() const
Definition terrain.hpp:48
const std::string & editor_group() const
Definition terrain.hpp:162
bool hide_in_editor() const
Definition terrain.hpp:62
t_translation::terrain_code number() const
Definition terrain.hpp:66
const t_string & editor_name() const
Definition terrain.hpp:49
Wrapper class to encapsulate creation and management of an SDL_Texture.
Definition texture.hpp:33
#define ERR_ED
#define DBG_ED
const config * cfg
static std::string _(const char *str)
Definition gettext.hpp:100
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:955
const terrain_code VOID_TERRAIN
VOID_TERRAIN is used for shrouded hexes.
std::vector< terrain_code > ter_list
constexpr ter_layer NO_LAYER
const terrain_code FOGGED
std::vector< std::string > split(const config_attribute_value &val)
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...
#define i
#define c