Freeciv21
Develop your civilization from humble roots to a global empire
layer_darkness.cpp
Go to the documentation of this file.
1 /*__ ___ ***************************************
2 / \ / \ Copyright (c) 2021-2023 Freeciv21 contributors.
3 \_ \ / __/ This file is part of Freeciv21.
4  _\ \ / /__ Freeciv21 is free software: you can redistribute it
5  \___ \____/ __/ and/or modify it under the terms of the GNU General
6  \_ _/ Public License as published by the Free Software
7  | @ @ \_ Foundation, either version 3 of the License,
8  | or (at your option) any later version.
9  _/ /\ You should have received a copy of the GNU
10  /o) (o/\ \_ General Public License along with Freeciv21.
11  \_____/ / If not, see https://www.gnu.org/licenses/.
12  \____/ ********************************************************/
13 
14 #include "layer_darkness.h"
15 
16 #include "climap.h"
17 #include "game.h"
18 #include "map.h"
19 #include "sprite_g.h"
20 #include "tilespec.h"
21 
22 namespace freeciv {
23 
24 layer_darkness::layer_darkness(struct tileset *ts, darkness_style style)
25  : freeciv::layer(ts, LAYER_DARKNESS), m_style(style), m_sprites{}
26 {
27 }
28 
30 {
31  switch (m_style) {
32  case freeciv::DARKNESS_NONE:
33  // Nothing.
34  break;
35  case freeciv::DARKNESS_ISORECT: {
36  // Isometric: take a single tx.darkness tile and split it into 4.
37  QPixmap *darkness = load_sprite({QStringLiteral("tx.darkness")});
38  const int ntw = tileset_tile_width(tileset()),
40  int offsets[4][2] = {
41  {ntw / 2, 0}, {0, nth / 2}, {ntw / 2, nth / 2}, {0, 0}};
42 
43  if (!darkness) {
44  tileset_error(tileset(), LOG_FATAL, _("Sprite tx.darkness missing."));
45  }
46  for (int i = 0; i < 4; i++) {
47  const auto sprite = std::unique_ptr<QPixmap>(
48  crop_sprite(darkness, offsets[i][0], offsets[i][1], ntw / 2,
49  nth / 2, nullptr, 0, 0));
50  set_sprite(i, *sprite);
51  }
52  } break;
53  case freeciv::DARKNESS_CARD_SINGLE:
54  for (int i = 0; i < tileset_num_cardinal_dirs(tileset()); i++) {
55  enum direction8 dir = tileset_cardinal_dirs(tileset())[i];
56 
57  auto buffer =
58  QStringLiteral("tx.darkness_%1").arg(dir_get_tileset_name(dir));
59 
60  const auto sprite = load_sprite({buffer});
61  if (sprite) {
62  set_sprite(i, *sprite);
63  } else {
65  _("Sprite for tag '%s' missing."),
66  qUtf8Printable(buffer));
67  }
68  }
69  break;
70  case freeciv::DARKNESS_CARD_FULL:
71  for (int i = 1; tileset_num_index_cardinals(tileset()); i++) {
72  auto buffer = QStringLiteral("tx.darkness_%1")
73  .arg(cardinal_index_str(tileset(), i));
74 
75  const auto sprite = load_sprite({buffer});
76  if (sprite) {
77  set_sprite(i, *sprite);
78  } else {
80  _("Sprite for tag '%s' missing."),
81  qUtf8Printable(buffer));
82  }
83  }
84  break;
85  case freeciv::DARKNESS_CORNER:
86  // Handled in LAYER_FOG.
87  break;
88  };
89 }
90 
91 std::vector<drawn_sprite>
93  const tile_corner *pcorner,
94  const unit *punit) const
95 {
96  Q_UNUSED(pedge);
97  Q_UNUSED(pcorner);
98 
99  if (!ptile) {
100  return {};
101  }
102 
103  // Don't draw darkness when the solid background is used
104  if (solid_background(ptile, punit, tile_city(ptile))) {
105  return {};
106  }
107 
108  auto sprites = std::vector<drawn_sprite>();
109 
110  int i, tileno;
111  struct tile *adjc_tile;
112 
113  const auto is_unknown = [&](direction8 dir) {
114  return ((adjc_tile = mapstep(&(wld.map), ptile, (dir)))
115  && client_tile_get_known(adjc_tile) == TILE_UNKNOWN);
116  };
117 
118  switch (m_style) {
119  case DARKNESS_NONE:
120  break;
121  case DARKNESS_ISORECT:
122  for (i = 0; i < 4; i++) {
123  const int W = tileset_tile_width(tileset()),
125  int offsets[4][2] = {{W / 2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}};
126 
127  if (is_unknown(DIR4_TO_DIR8[i])) {
128  sprites.emplace_back(tileset(), &m_sprites[i], true, offsets[i][0],
129  offsets[i][1]);
130  }
131  }
132  break;
133  case DARKNESS_CARD_SINGLE:
134  for (i = 0; i < tileset_num_cardinal_dirs(tileset()); i++) {
135  if (is_unknown(tileset_cardinal_dirs(tileset())[i])) {
136  sprites.emplace_back(tileset(), &m_sprites[i]);
137  }
138  }
139  break;
140  case DARKNESS_CARD_FULL:
141  /* We're looking to find the INDEX_NSEW for the directions that
142  * are unknown. We want to mark unknown tiles so that an unreal
143  * tile will be given the same marking as our current tile - that
144  * way we won't get the "unknown" dither along the edge of the
145  * map. */
146  tileno = 0;
147  for (i = 0; i < tileset_num_cardinal_dirs(tileset()); i++) {
148  if (is_unknown(tileset_cardinal_dirs(tileset())[i])) {
149  tileno |= 1 << i;
150  }
151  }
152 
153  if (tileno != 0) {
154  sprites.emplace_back(tileset(), &m_sprites[tileno]);
155  }
156  break;
157  case DARKNESS_CORNER:
158  // Handled in LAYER_FOG.
159  break;
160  };
161 
162  return sprites;
163 }
164 
165 } // namespace freeciv
QPixmap crop_sprite(const QPixmap *sprite)
Helper function to crop a sprite.
Definition: canvas.cpp:115
std::array< QPixmap, MAX_INDEX_CARDINAL > m_sprites
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.
void set_sprite(std::size_t index, const QPixmap &p)
Sets one of the sprites used to draw the darkness.
darkness_style m_style
layer_darkness(struct tileset *ts, darkness_style style)
void load_sprites() override
Loads all the sprites needed to draw the darkness.
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
enum known_type client_tile_get_known(const struct tile *ptile)
A tile's "known" field is used by the server to store whether each player knows the tile.
Definition: climap.cpp:29
#define _(String)
Definition: fcintl.h:50
struct world wld
Definition: game.cpp:48
constexpr auto LOG_FATAL
Definition: log.h:22
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Step from the given tile in the given direction.
Definition: map.cpp:342
Definition: path.cpp:10
Definition: tile.h:42
Definition: unit.h:134
struct civ_map map
Definition: world_object.h:21
struct city * tile_city(const struct tile *ptile)
Return the city on this tile (or nullptr), checking for city center.
Definition: tile.cpp:72
@ TILE_UNKNOWN
Definition: tile.h:29
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
int tileset_tile_height(const struct tileset *t)
Return the tile height of the current tileset.
Definition: tilespec.cpp:383
void tileset_error(struct tileset *t, QtMsgType level, const char *format,...)
Called when ever there's problem in ruleset/tileset compatibility.
Definition: tilespec.cpp:291
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
QString dir_get_tileset_name(enum direction8 dir)
Return the tileset name of the direction.
Definition: tilespec.cpp:613
int tileset_tile_width(const struct tileset *t)
Return the tile width of the current tileset.
Definition: tilespec.cpp:371
constexpr direction8 DIR4_TO_DIR8[4]
Definition: tilespec.h:53