Freeciv21
Develop your civilization from humble roots to a global empire
layer_grid.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_grid.h"
7 
8 #include "citydlg_g.h"
9 #include "client_main.h"
10 #include "climap.h"
11 #include "control.h"
12 #include "movement.h"
13 #include "sprite_g.h"
14 #include "tilespec.h"
15 #include "views/view_map_common.h" // mapdeco
16 
17 #include <QPixmap>
18 
19 namespace freeciv {
20 
21 layer_grid::layer_grid(struct tileset *ts, mapview_layer layer)
22  : freeciv::layer(ts, layer)
23 {
24 }
25 
27 {
28  // This must correspond to enum edge_type.
29  const auto edge_name =
30  std::array{QStringLiteral("ns"), QStringLiteral("we"),
31  QStringLiteral("ud"), QStringLiteral("lr")};
32 
33  m_unavailable = load_sprite({"grid.unavailable"}, true);
34  m_nonnative = load_sprite({"grid.nonnative"}, false);
35 
36  for (int i = 0; i < EDGE_COUNT; i++) {
37  int be;
38 
39  if (i == EDGE_UD && tileset_hex_width(tileset()) == 0) {
40  continue;
41  } else if (i == EDGE_LR && tileset_hex_height(tileset()) == 0) {
42  continue;
43  }
44 
45  auto name = QStringLiteral("grid.main.%1").arg(edge_name[i]);
46  m_main[i] = load_sprite({name}, true);
47 
48  name = QStringLiteral("grid.city.%1").arg(edge_name[i]);
49  m_city[i] = load_sprite({name}, true);
50 
51  name = QStringLiteral("grid.worked.%1").arg(edge_name[i]);
52  m_worked[i] = load_sprite({name}, true);
53 
54  name = QStringLiteral("grid.selected.%1").arg(edge_name[i]);
55  m_selected[i] = load_sprite({name}, true);
56 
57  for (be = 0; be < 2; be++) {
58  name = QStringLiteral("grid.borders.%1").arg(edge_name[i][be]);
59  m_basic_borders[i][be] = load_sprite({name}, true);
60  }
61  }
62 }
63 
68 {
69  // Get the color. In pregame, players have no color so we just use red.
70  const auto c = player_has_color(tileset(), player)
72  : Qt::red;
73 
74  QPixmap color(tileset_tile_width(tileset()),
76  color.fill(c);
77 
78  for (int i = 0; i < EDGE_COUNT; i++) {
79  for (int j = 0; j < 2; j++) {
80  if (m_basic_borders[i][j]) {
82  &color, 0, 0, tileset_tile_width(tileset()),
84  }
85  }
86  }
87 }
88 
92 void layer_grid::free_player(int player_id)
93 {
94  for (auto &edge : m_borders.at(player_id)) {
95  for (auto &pix : edge) {
96  pix = nullptr;
97  }
98  }
99 }
100 
104 std::vector<drawn_sprite>
105 layer_grid::fill_sprite_array(const tile *ptile, const tile_edge *pedge,
106  const tile_corner *pcorner,
107  const unit *punit) const
108 {
109  // LAYER_GRID1 is used for isometric tilesets only
110  if (tileset_is_isometric(tileset()) && type() != LAYER_GRID1) {
111  return {};
112  }
113 
114  // LAYER_GRID2 is used for non-isometric tilesets only
115  if (!tileset_is_isometric(tileset()) && type() != LAYER_GRID2) {
116  return {};
117  }
118 
119  const auto citymode = is_any_city_dialog_open();
120 
121  std::vector<drawn_sprite> sprs;
122 
123  if (pedge) {
124  bool known[NUM_EDGE_TILES], city[NUM_EDGE_TILES];
125  bool unit[NUM_EDGE_TILES], worked[NUM_EDGE_TILES];
126 
127  for (int i = 0; i < NUM_EDGE_TILES; i++) {
128  int dummy_x, dummy_y;
129  const struct tile *tile = pedge->tile[i];
130  struct player *powner = tile ? tile_owner(tile) : nullptr;
131 
132  known[i] = tile && client_tile_get_known(tile) != TILE_UNKNOWN;
133  unit[i] = false;
134  if (tile && !citymode) {
135  for (const auto pfocus_unit : get_units_in_focus()) {
136  if (unit_drawn_with_city_outline(pfocus_unit, false)) {
137  struct tile *utile = unit_tile(pfocus_unit);
138  int radius = game.info.init_city_radius_sq
140  nullptr, unit_owner(pfocus_unit), nullptr,
141  nullptr, nullptr, utile, nullptr, nullptr,
142  nullptr, nullptr, nullptr, EFT_CITY_RADIUS_SQ);
143 
144  if (city_tile_to_city_map(&dummy_x, &dummy_y, radius, utile,
145  tile)) {
146  unit[i] = true;
147  break;
148  }
149  }
150  }
151  }
152  worked[i] = false;
153 
154  city[i] = (tile
155  && (powner == nullptr || client_player() == nullptr
156  || powner == client.conn.playing)
158  if (city[i]) {
159  if (citymode) {
160  /* In citymode, we only draw worked tiles for this city - other
161  * tiles may be marked as unavailable. */
162  worked[i] = (tile_worked(tile) == citymode);
163  } else {
164  worked[i] = (nullptr != tile_worked(tile));
165  }
166  }
167  // Draw city grid for main citymap
168  if (tile && citymode
169  && city_base_to_city_map(&dummy_x, &dummy_y, citymode, tile)) {
170  sprs.emplace_back(tileset(), m_selected[pedge->type]);
171  }
172  }
173  if (mapdeco_is_highlight_set(pedge->tile[0])
174  || mapdeco_is_highlight_set(pedge->tile[1])) {
175  sprs.emplace_back(tileset(), m_selected[pedge->type]);
176  } else {
177  if (gui_options->draw_map_grid) {
178  if (worked[0] || worked[1]) {
179  sprs.emplace_back(tileset(), m_worked[pedge->type]);
180  } else if (city[0] || city[1]) {
181  sprs.emplace_back(tileset(), m_city[pedge->type]);
182  } else if (known[0] || known[1]) {
183  sprs.emplace_back(tileset(), m_main[pedge->type]);
184  }
185  }
187  if (XOR(city[0], city[1])) {
188  sprs.emplace_back(tileset(), m_city[pedge->type]);
189  }
190  if (XOR(unit[0], unit[1])) {
191  sprs.emplace_back(tileset(), m_worked[pedge->type]);
192  }
193  }
194  }
195 
197  && known[0] && known[1]) {
198  struct player *owner0 = tile_owner(pedge->tile[0]);
199  struct player *owner1 = tile_owner(pedge->tile[1]);
200 
201  if (owner0 != owner1) {
202  if (owner0) {
203  int plrid = player_index(owner0);
204  sprs.emplace_back(tileset(),
205  m_borders[plrid][pedge->type][0].get());
206  }
207  if (owner1) {
208  int plrid = player_index(owner1);
209  sprs.emplace_back(tileset(),
210  m_borders[plrid][pedge->type][1].get());
211  }
212  }
213  }
214  } else if (nullptr != ptile
215  && TILE_UNKNOWN != client_tile_get_known(ptile)) {
216  int cx, cy;
217 
218  if (citymode
219  // test to ensure valid coordinates?
220  && city_base_to_city_map(&cx, &cy, citymode, ptile)
221  && !client_city_can_work_tile(citymode, ptile)) {
222  sprs.emplace_back(tileset(), m_unavailable);
223  }
224 
225  if (gui_options->draw_native && citymode == nullptr) {
226  bool native = true;
227  for (const auto pfocus : get_units_in_focus()) {
228  if (!is_native_tile(unit_type_get(pfocus), ptile)) {
229  native = false;
230  break;
231  }
232  }
233 
234  if (!native) {
235  if (m_nonnative != nullptr) {
236  sprs.emplace_back(tileset(), m_nonnative);
237  } else {
238  sprs.emplace_back(tileset(), m_unavailable);
239  }
240  }
241  }
242  }
243 
244  return sprs;
245 }
246 
247 } // namespace freeciv
QPixmap crop_sprite(const QPixmap *sprite)
Helper function to crop a sprite.
Definition: canvas.cpp:115
bool city_base_to_city_map(int *city_map_x, int *city_map_y, const struct city *const pcity, const struct tile *map_tile)
Finds the city map coordinate for a given map position and a city.
Definition: city.cpp:274
bool city_tile_to_city_map(int *city_map_x, int *city_map_y, const int city_radius_sq, const struct tile *city_center, const struct tile *map_tile)
Finds the city map coordinate for a given map position and a city center.
Definition: city.cpp:257
struct city * is_any_city_dialog_open()
Definition: citydlg.cpp:2315
void load_sprites() override
Loads all sprites that do not depend on the ruleset.
Definition: layer_grid.cpp:26
QPixmap * m_unavailable
Definition: layer_grid.h:37
std::array< QPixmap *, EDGE_COUNT > m_selected
Definition: layer_grid.h:35
void initialize_player(const player *player) override
Initializes border data for a player.
Definition: layer_grid.cpp:67
std::array< std::array< unique_edge_data, EDGE_COUNT >, MAX_NUM_PLAYER_SLOTS > m_borders
Indices: [player][edge][in/out].
Definition: layer_grid.h:48
QPixmap * m_nonnative
Definition: layer_grid.h:37
void free_player(int player_id) override
Frees border data for a player.
Definition: layer_grid.cpp:92
std::array< edge_data, EDGE_COUNT > m_basic_borders
Definition: layer_grid.h:41
std::vector< drawn_sprite > fill_sprite_array(const tile *ptile, const tile_edge *pedge, const tile_corner *pcorner, const unit *punit) const override
Fill in the grid sprites for the given tile, city, and unit.
Definition: layer_grid.cpp:105
std::array< QPixmap *, EDGE_COUNT > m_main
Definition: layer_grid.h:34
std::array< QPixmap *, EDGE_COUNT > m_worked
Definition: layer_grid.h:36
std::array< QPixmap *, EDGE_COUNT > m_city
Definition: layer_grid.h:34
layer_grid(struct tileset *ts, mapview_layer layer)
Definition: layer_grid.cpp:21
A layer when drawing the map.
Definition: layer.h:153
mapview_layer type() const
Definition: layer.h:238
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
struct tileset * tileset() const
Definition: layer.h:241
struct player * client_player()
Either controlling or observing.
struct civclient client
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
bool client_city_can_work_tile(const struct city *pcity, const struct tile *ptile)
Returns TRUE when a tile is available to be worked, or the city itself is currently working the tile ...
Definition: climap.cpp:114
bool player_has_color(const struct tileset *t, const struct player *pplayer)
Return whether the player has a color assigned yet.
QColor get_player_color(const struct tileset *t, const struct player *pplayer)
Return the color of the player.
std::vector< unit * > & get_units_in_focus()
Returns list of units currently in focus.
Definition: control.cpp:169
int get_target_bonus_effects(struct effect_list *plist, const struct player *target_player, const struct player *other_player, const struct city *target_city, const struct impr_type *target_building, const struct tile *target_tile, const struct unit *target_unit, const struct unit_type *target_unittype, const struct output_type *target_output, const struct specialist *target_specialist, const struct action *target_action, enum effect_type effect_type, enum vision_layer vision_layer, enum national_intelligence nintel)
Returns the effect bonus of a given type for any target.
Definition: effects.cpp:611
@ BORDERS_DISABLED
Definition: fc_types.h:863
struct civ_game game
Definition: game.cpp:47
const char * name
Definition: inputfile.cpp:118
#define NUM_EDGE_TILES
Definition: layer.h:41
@ EDGE_UD
Definition: layer.h:34
@ EDGE_LR
Definition: layer.h:35
@ EDGE_COUNT
Definition: layer.h:36
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
This tile is native to unit.
Definition: movement.cpp:279
Definition: path.cpp:10
client_options * gui_options
Definition: options.cpp:74
bool player_in_city_map(const struct player *pplayer, const struct tile *ptile)
Return true iff x,y is inside any of the player's city map.
Definition: player.cpp:1159
int player_index(const struct player *pplayer)
Return the player index.
Definition: player.cpp:748
#define XOR(p, q)
Definition: shared.h:64
Definition: city.h:291
struct packet_game_info info
Definition: game.h:80
struct connection conn
Definition: client_main.h:89
bool draw_native
Definition: options.h:141
bool draw_borders
Definition: options.h:140
bool draw_map_grid
Definition: options.h:122
bool draw_city_outlines
Definition: options.h:120
struct player * playing
Definition: connection.h:142
Definition: player.h:231
const struct tile * tile[NUM_EDGE_TILES]
Definition: layer.h:42
edge_type type
Definition: layer.h:40
Definition: tile.h:42
struct city * worked
Definition: tile.h:51
Definition: unit.h:134
#define tile_worked(_tile)
Definition: tile.h:97
@ TILE_UNKNOWN
Definition: tile.h:29
#define tile_owner(_tile)
Definition: tile.h:78
int tileset_hex_width(const struct tileset *t)
Return the hex_width of the current tileset.
Definition: tilespec.cpp:345
bool unit_drawn_with_city_outline(const struct unit *punit, bool check_focus)
Indicate whether a unit is to be drawn with a surrounding city outline under current conditions.
Definition: tilespec.cpp:3116
bool tileset_is_isometric(const struct tileset *t)
Return whether the current tileset is isometric.
Definition: tilespec.cpp:336
int tileset_tile_height(const struct tileset *t)
Return the tile height of the current tileset.
Definition: tilespec.cpp:383
int tileset_hex_height(const struct tileset *t)
Return the hex_height of the current tileset.
Definition: tilespec.cpp:351
int tileset_tile_width(const struct tileset *t)
Return the tile width of the current tileset.
Definition: tilespec.cpp:371
#define unit_tile(_pu)
Definition: unit.h:371
#define unit_owner(_pu)
Definition: unit.h:370
const struct unit_type * unit_type_get(const struct unit *punit)
Return the unit type for this unit.
Definition: unittype.cpp:114
bool mapdeco_is_highlight_set(const struct tile *ptile)
Return TRUE if the given tile is highlighted.