Freeciv21
Develop your civilization from humble roots to a global empire
layer_water.cpp
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPLv3-or-later
2 // SPDX-FileCopyrightText: Freeciv authors
3 // SPDX-FileCopyrightText: Freeciv21 authors
4 // SPDX-FileCopyrightText: Louis Moureaux <m_louis30@yahoo.com>
5 
6 #include "layer_water.h"
7 
8 #include "colors_common.h"
9 #include "extras.h"
10 #include "fc_types.h"
11 #include "tilespec.h"
12 
13 namespace freeciv {
14 
16  : freeciv::layer(ts, LAYER_WATER)
17 {
18 }
19 
25  const QString &tag, extrastyle_id style)
26 {
27  if (style == ESTYLE_CARDINALS) {
28  extra_data data;
29  data.extra = extra;
30 
32  {
34 
35  // We use direction-specific irrigation and farmland graphics, if they
36  // are available. If not, we just fall back to the basic irrigation
37  // graphics.
38  QStringList alt_tags = make_tag_terrain_list(tag, "", terrain);
39  for (int i = 0; i < tileset_num_index_cardinals(tileset()); i++) {
40  QStringList tags = make_tag_terrain_list(
41  tag, cardinal_index_str(tileset(), i), terrain);
42  sprites[i] = load_sprite(tags + alt_tags, true);
43  }
44 
45  data.sprites.push_back(sprites);
46  }
48 
49  m_cardinals.push_back(data);
50  } else if (style == ESTYLE_RIVER) {
51  extra_data outlet, river;
52  river.extra = extra;
53  outlet.extra = extra;
54 
56  {
57  extra_data::terrain_data outlet_sprites;
58  extra_data::terrain_data river_sprites;
59 
60  for (int i = 0; i < tileset_num_index_cardinals(tileset()); i++) {
61  auto suffix =
62  QStringLiteral("_s_%1").arg(cardinal_index_str(tileset(), i));
63  river_sprites[i] =
64  load_sprite(make_tag_terrain_list(tag, suffix, terrain), true);
65  }
66 
67  for (int i = 0; i < tileset_num_cardinal_dirs(tileset()); i++) {
68  auto suffix = QStringLiteral("_outlet_%1")
71  outlet_sprites[i] =
72  load_sprite(make_tag_terrain_list(tag, suffix, terrain), true);
73  }
74 
75  outlet.sprites.push_back(outlet_sprites);
76  river.sprites.push_back(river_sprites);
77  }
79 
80  m_outlets.emplace_back(outlet);
81  m_rivers.emplace_back(river);
82  }
83 }
84 
85 namespace /* anonymous */ {
95 static int get_irrigation_index(const struct tileset *t,
96  const extra_type *pextra,
97  bv_extras *textras_near)
98 {
99  int tileno = 0, i;
100 
101  for (i = 0; i < tileset_num_cardinal_dirs(t); i++) {
102  enum direction8 dir = tileset_cardinal_dirs(t)[i];
103 
104  if (BV_ISSET(textras_near[dir], extra_index(pextra))) {
105  tileno |= 1 << i;
106  }
107  }
108 
109  return tileno;
110 }
111 } // anonymous namespace
112 
117  const struct tileset *t, std::vector<drawn_sprite> &sprs,
118  bv_extras textras, bv_extras *textras_near, const terrain *pterrain,
119  const city *pcity) const
120 {
121  // We don't draw the irrigation if there's a city (it just gets overdrawn
122  // anyway, and ends up looking bad).
123  if (!(pcity && gui_options->draw_cities)) {
124  for (auto cdata : m_cardinals) {
125  if (is_extra_drawing_enabled(cdata.extra)) {
126  int eidx = extra_index(cdata.extra);
127 
128  if (BV_ISSET(textras, eidx)) {
129  bool hidden = false;
130 
131  extra_type_list_iterate(cdata.extra->hiders, phider)
132  {
133  if (BV_ISSET(textras, extra_index(phider))) {
134  hidden = true;
135  break;
136  }
137  }
139 
140  if (!hidden) {
141  int idx = get_irrigation_index(t, cdata.extra, textras_near);
142 
143  sprs.emplace_back(t,
144  cdata.sprites[terrain_index(pterrain)][idx]);
145  }
146  }
147  }
148  }
149  }
150 }
151 
152 std::vector<drawn_sprite>
153 layer_water::fill_sprite_array(const tile *ptile, const tile_edge *pedge,
154  const tile_corner *pcorner,
155  const unit *punit) const
156 {
157  if (!ptile) {
158  return {};
159  }
160 
161  const auto terrain = tile_terrain(ptile);
162  if (!terrain) {
163  return {};
164  }
165 
166  const auto pcity = tile_city(ptile);
167  const auto extras = *tile_extras(ptile);
168 
169  struct terrain *terrain_near[8] = {nullptr}; // dummy
170  bv_extras extras_near[8];
171  build_tile_data(ptile, terrain, terrain_near, extras_near);
172 
173  std::vector<drawn_sprite> sprs;
174 
175  if (!solid_background(ptile, punit, pcity)
176  && terrain_type_terrain_class(terrain) == TC_OCEAN) {
177  for (int dir = 0; dir < tileset_num_cardinal_dirs(tileset()); dir++) {
178  int didx = tileset_cardinal_dirs(tileset())[dir];
179 
180  for (auto outlet : m_outlets) {
181  int idx = extra_index(outlet.extra);
182 
183  if (BV_ISSET(extras_near[didx], idx)) {
184  sprs.emplace_back(tileset(),
185  outlet.sprites[terrain_index(terrain)][dir]);
186  }
187  }
188  }
189  }
190 
191  fill_irrigation_sprite_array(tileset(), sprs, extras, extras_near, terrain,
192  pcity);
193 
194  if (!solid_background(ptile, punit, pcity)) {
195  for (const auto &river : m_rivers) {
196  int idx = extra_index(river.extra);
197 
198  if (BV_ISSET(extras, idx)) {
199  // Draw rivers on top of irrigation.
200  int tileno = 0;
201  for (int i = 0; i < tileset_num_cardinal_dirs(tileset()); i++) {
202  enum direction8 cdir = tileset_cardinal_dirs(tileset())[i];
203 
204  if (terrain_near[cdir] == nullptr
205  || terrain_type_terrain_class(terrain_near[cdir]) == TC_OCEAN
206  || BV_ISSET(extras_near[cdir], idx)) {
207  tileno |= 1 << i;
208  }
209  }
210 
211  sprs.emplace_back(tileset(),
212  river.sprites[terrain_index(terrain)][tileno]);
213  }
214  }
215  }
216 
217  return sprs;
218 }
219 
221 {
222  m_cardinals.clear();
223  m_outlets.clear();
224  m_rivers.clear();
225 }
226 
227 } // namespace freeciv
bool BV_ISSET(const BV &bv, int bit)
Definition: bitvector.h:37
std::vector< extra_data > m_cardinals
Definition: layer_water.h:45
void reset_ruleset() override
Resets cached data that depends on the ruleset.
layer_water(struct tileset *ts)
Definition: layer_water.cpp:15
void initialize_extra(const extra_type *extra, const QString &tag, extrastyle_id style) override
Collects all extras to be drawn (the ones with ESTYLE_CARDINALS or ESTYLE_RIVER).
Definition: layer_water.cpp:24
void fill_irrigation_sprite_array(const struct tileset *t, std::vector< drawn_sprite > &sprs, bv_extras textras, bv_extras *textras_near, const terrain *pterrain, const city *pcity) const
Fill in the farmland/irrigation sprite for the tile.
std::vector< extra_data > m_outlets
Definition: layer_water.h:45
std::vector< drawn_sprite > fill_sprite_array(const tile *ptile, const tile_edge *pedge, const tile_corner *pcorner, const unit *punit) const override
Returns the list of sprites drawn by this layer somewhere on the map.
std::vector< extra_data > m_rivers
Definition: layer_water.h:45
A layer when drawing the map.
Definition: layer.h:153
QPixmap * load_sprite(const QStringList &possible_names, bool required=false, bool verbose=true) const
Shortcut to load a sprite from the tileset.
Definition: layer.cpp:79
bool solid_background(const tile *ptile, const unit *punit, const city *pcity) const
Whether a solid background should be drawn on a tile instead of its terrain.
Definition: layer.cpp:65
struct tileset * tileset() const
Definition: layer.h:241
char * extras
Definition: comments.cpp:34
#define extra_type_list_iterate(extralist, pextra)
Definition: extras.h:145
#define extra_index(_e_)
Definition: extras.h:163
#define extra_type_list_iterate_end
Definition: extras.h:147
Definition: path.cpp:10
client_options * gui_options
Definition: options.cpp:74
Definition: city.h:291
bool draw_cities
Definition: options.h:136
std::vector< terrain_data > sprites
Definition: layer_water.h:20
std::array< QPixmap *, MAX_INDEX_CARDINAL > terrain_data
Definition: layer_water.h:17
Definition: tile.h:42
struct named_sprites sprites
Definition: tilespec.cpp:271
Definition: unit.h:134
Terrain_type_id terrain_index(const struct terrain *pterrain)
Return the terrain index.
Definition: terrain.cpp:110
enum terrain_class terrain_type_terrain_class(const struct terrain *pterrain)
What terrain class terrain type belongs to.
Definition: terrain.cpp:464
#define terrain_type_iterate(_p)
Definition: terrain.h:331
#define terrain_type_iterate_end
Definition: terrain.h:337
struct city * tile_city(const struct tile *ptile)
Return the city on this tile (or nullptr), checking for city center.
Definition: tile.cpp:72
#define tile_terrain(_tile)
Definition: tile.h:93
static const bv_extras * tile_extras(const struct tile *ptile)
Definition: tile.h:102
int tileset_num_cardinal_dirs(const struct tileset *t)
Returns the number of cardinal directions used by the tileset.
Definition: tilespec.cpp:554
std::array< direction8, 8 > tileset_cardinal_dirs(const struct tileset *t)
Returns the cardinal directions used by the tileset.
Definition: tilespec.cpp:574
void build_tile_data(const struct tile *ptile, struct terrain *pterrain, struct terrain **tterrain_near, bv_extras *textras_near)
Assemble some data that is used in building the tile sprite arrays.
Definition: tilespec.cpp:3080
QString cardinal_index_str(const struct tileset *t, int idx)
Return a directional string for the cardinal directions.
Definition: tilespec.cpp:2233
int tileset_num_index_cardinals(const struct tileset *t)
Returns the number of cardinal indices used by the tileset.
Definition: tilespec.cpp:564
bool is_extra_drawing_enabled(const extra_type *pextra)
Should the given extra be drawn FIXME: Some extras can not be switched.
Definition: tilespec.cpp:3133
QStringList make_tag_terrain_list(const QString &prefix, const QString &suffix, const struct terrain *pterrain)
Make the list of possible tag names for the extras which may vary depending on the terrain they're on...
Definition: tilespec.cpp:2914
QString dir_get_tileset_name(enum direction8 dir)
Return the tileset name of the direction.
Definition: tilespec.cpp:613