Freeciv21
Develop your civilization from humble roots to a global empire
tilespec.cpp
Go to the documentation of this file.
1 /*__ ___ ***************************************
2 / \ / \ Copyright (c) 1996-2023 Freeciv21 and Freeciv
3 \_ \ / __/ contributors. 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 
20 #include <QApplication>
21 #include <QHash>
22 #include <QImageReader>
23 #include <QPixmap>
24 #include <QSet>
25 #include <QString>
26 #include <QVector>
27 #include <cstdarg>
28 #include <cstdlib> // exit
29 #include <cstring>
30 
31 #include "astring.h"
32 #include "bitvector.h"
33 #include "capability.h"
34 #include "city.h"
35 #include "fcintl.h"
36 #include "log.h"
37 #include "registry.h"
38 #include "registry_ini.h"
39 #include "shared.h"
40 #include "support.h"
41 
42 // common
43 #include "game.h" // game.control.styles_count
44 #include "government.h"
45 #include "helpdata.h"
46 #include "nation.h"
47 #include "specialist.h"
48 
49 /* client/include */
50 #include "mapview_g.h" // for update_map_canvas_visible
51 #include "menu_g.h"
52 #include "sprite_g.h"
53 // client
54 #include "citybar.h"
55 #include "citydlg_common.h" // for generate_citydlg_dimensions()
56 #include "client_main.h"
57 #include "climap.h" // for client_tile_get_known()
58 #include "climisc.h"
59 #include "colors_common.h"
60 #include "control.h" // for fill_xxx
61 #include "helpdlg.h"
62 #include "layer_background.h"
63 #include "layer_base_flags.h"
64 #include "layer_city.h"
65 #include "layer_city_size.h"
66 #include "layer_darkness.h"
67 #include "layer_editor.h"
68 #include "layer_fog.h"
69 #include "layer_goto.h"
70 #include "layer_grid.h"
71 #include "layer_infrawork.h"
72 #include "layer_overlays.h"
73 #include "layer_roads.h"
74 #include "layer_special.h"
75 #include "layer_terrain.h"
76 #include "layer_units.h"
77 #include "layer_water.h"
78 #include "layer_workertask.h"
79 #include "options.h" // for fill_xxx, tileset options
80 #include "page_game.h"
81 #include "tilespec.h"
82 #include "utils/colorizer.h"
83 #include "views/view_map.h"
84 
85 Q_LOGGING_CATEGORY(tileset_category, "freeciv.tileset");
86 
87 #define TILESPEC_CAPSTR \
88  "+Freeciv-tilespec-Devel-2019-Jul-03 duplicates_ok precise-hp-bars " \
89  "unlimited-unit-select-frames unlimited-upkeep-sprites hex_corner " \
90  "terrain-specific-extras options"
91 /*
92  * Tilespec capabilities acceptable to this program:
93  *
94  * +Freeciv-3.1-tilespec
95  * - basic format for Freeciv versions 3.1.x; required
96  *
97  * +Freeciv-tilespec-Devel-YYYY.MMM.DD
98  * - tilespec of the development version at the given data
99  *
100  * duplicates_ok
101  * - we can handle existence of duplicate tags (lattermost tag which
102  * appears is used; tilesets which have duplicates should specify
103  * "duplicates_ok")
104  * precise-hp-bars
105  * - HP bars can use up to 100 sprites (unit.hp_*)
106  * unlimited-unit-select-frames
107  * - The "selected unit" animation can have as many frames as is desired
108  * (unit.select*)
109  * unlimited-upkeep-sprites
110  * - There is no limitation on the number of upkeep sprites
111  * (upkeep.unhappy*, upkeep.output*)
112  * hex_corner
113  * - The sprite type "hex_corner" is supported
114  * options
115  * - Signals that tileset options are supported
116  */
117 
118 #define SPEC_CAPSTR "+Freeciv-spec-Devel-2019-Jul-03 options"
119 /*
120  * Individual spec file capabilities acceptable to this program:
121  *
122  * +Freeciv-3.1-spec
123  * - basic format for Freeciv versions 3.1.x; required
124  * options
125  * - Signals that tileset options are supported
126  */
127 
128 #define TILESPEC_SUFFIX ".tilespec"
129 #define TILE_SECTION_PREFIX "tile_"
130 
132 const static char *const OPTION_SECTION_PREFIX = "option_";
133 
134 #define MAX_NUM_LAYERS 3
135 
137  /* Each citizen type has up to MAX_NUM_CITIZEN_SPRITES different
138  * sprites, as defined by the tileset. */
139  int count;
141 };
142 
145  *treaty_thumb[2], // 0=disagree, 1=agree
146  *arrow[ARROW_LAST], // 0=right arrow, 1=plus, 2=minus
147 
148  *events[E_COUNT],
149 
150  // The panel sprites for showing tax % allocations.
152  *dither_tile; // only used for isometric view
153 
154  struct {
155  QPixmap *tile;
156  } mask;
157 
158  const QPixmap *tech[A_LAST];
159  const QPixmap *building[B_LAST];
160  const QPixmap *government[G_LAST];
161 
162  struct {
163  std::unique_ptr<freeciv::colorizer> icon[U_LAST];
164  std::unique_ptr<freeciv::colorizer> facing[U_LAST][DIR8_MAGIC_MAX];
165  } units;
166 
167  std::vector<QPixmap *> nation_flag;
168  std::vector<QPixmap *> nation_shield;
169 
172  struct {
173  int hot_x, hot_y;
176  struct {
177  std::vector<QPixmap *> unit;
178  QPixmap *nuke;
180  struct {
181  std::vector<QPixmap *> unhappy, output[O_LAST];
183  struct citybar_sprites citybar;
184  struct editor_sprites editor;
185  struct {
186  QPixmap *attention;
187  } user;
188  struct {
189  QPixmap *activity, *rmact;
191  struct {
192  QPixmap *borders[EDGE_COUNT][2];
193  } grid;
194 };
195 
196 struct specfile {
197  QPixmap *big_sprite;
198  char *file_name;
199 };
200 
206 struct small_sprite {
208 
209  // The sprite is in this file.
210  char *file;
211 
212  // Or, the sprite is in this file at the location.
213  struct specfile *sf;
214  int x, y, width, height;
215 
216  // A little more (optional) data.
217  int hot_x, hot_y;
218 
219  QPixmap *sprite;
220 };
221 
222 struct tileset {
223  char name[512];
226  int priority;
227 
228  char *summary;
229  char *description;
230 
231  std::vector<tileset_log_entry> log;
232 
233  std::map<QString, tileset_option> options;
234 
235  std::vector<std::unique_ptr<freeciv::layer>> layers;
236  std::array<freeciv::layer_terrain *, MAX_NUM_LAYERS> terrain_layers;
238 
239  enum ts_type type;
242 
245 
247 
248  enum direction8 unit_default_orientation;
249 
250  freeciv::darkness_style darkness_style;
251  freeciv::fog_style fogstyle;
252 
255 
259  int select_step_ms = 100;
262 
265  std::array<direction8, 8> valid_tileset_dirs, cardinal_tileset_dirs;
266  QSet<specfile *> *specfiles;
267  QSet<struct small_sprite *> *small_sprites;
268  // This hash table maps tilespec tags to struct small_sprites.
269  QHash<QString, struct small_sprite *> *sprite_hash;
270  QHash<QString, extrastyle_id> *estyle_hash;
271  struct named_sprites sprites;
272  int replaced_hue; // -1 means no replacement
274 };
275 
276 struct tileset *tileset;
277 
278 static bool tileset_update = false;
279 
280 static struct tileset *tileset_read_toplevel(const QString &tileset_name,
281  bool verbose, int topology_id);
282 
283 static bool tileset_setup_options(struct tileset *t,
284  const section_file *file);
285 
286 static void tileset_player_free(struct tileset *t, int plrid);
287 
291 void tileset_error(struct tileset *t, QtMsgType level, const char *format,
292  ...)
293 {
294  va_list args;
295 
296  va_start(args, format);
297  auto buf = QString::vasprintf(format, args);
298  va_end(args);
299 
300  if (t != nullptr) {
301  t->log.push_back(tileset_log_entry{level, buf});
302  }
303 
304  switch (level) {
305  case QtFatalMsg:
306  qFatal("%s", qUtf8Printable(buf));
307  break;
308  case QtCriticalMsg:
309  qCCritical(tileset_category).noquote() << buf;
310  break;
311  case QtWarningMsg:
312  qCWarning(tileset_category).noquote() << buf;
313  break;
314  case QtInfoMsg:
315  qCInfo(tileset_category).noquote() << buf;
316  break;
317  case QtDebugMsg:
318  qCDebug(tileset_category).noquote() << buf;
319  break;
320  }
321 }
322 
326 struct tileset *get_tileset() { return tileset; }
327 
331 const char *tileset_basename(const struct tileset *t) { return t->name; }
332 
336 bool tileset_is_isometric(const struct tileset *t)
337 {
338  return t->type == TS_ISOMETRIC;
339 }
340 
345 int tileset_hex_width(const struct tileset *t) { return t->hex_width; }
346 
351 int tileset_hex_height(const struct tileset *t) { return t->hex_height; }
352 
371 int tileset_tile_width(const struct tileset *t)
372 {
373  return t->normal_tile_size.width();
374 }
375 
383 int tileset_tile_height(const struct tileset *t)
384 {
385  return t->normal_tile_size.height();
386 }
387 
394 int tileset_full_tile_width(const struct tileset *t)
395 {
396  return t->full_tile_size.width();
397 }
398 
407 int tileset_full_tile_height(const struct tileset *t)
408 {
409  return t->full_tile_size.height();
410 }
411 
416 QPoint tileset_full_tile_offset(const struct tileset *t)
417 {
418  return QPoint((t->normal_tile_size.width() - t->full_tile_size.width())
419  / 2,
420  t->normal_tile_size.height() - t->full_tile_size.height());
421 }
422 
426 int tileset_unit_width(const struct tileset *t)
427 {
428  return t->unit_tile_size.width();
429 }
430 
434 int tileset_unit_height(const struct tileset *t)
435 {
436  return t->unit_tile_size.height();
437 }
438 
442 static int calculate_max_upkeep_height(const struct tileset *t)
443 {
444  int max = 0;
445 
446  for (const auto sprite : t->sprites.upkeep.unhappy) {
447  max = std::max(max, sprite->height());
448  }
449 
451  {
452  for (const auto sprite : t->sprites.upkeep.output[o]) {
453  max = std::max(max, sprite->height());
454  }
455  }
457 
458  return max;
459 }
460 
464 static int tileset_upkeep_height(const struct tileset *t)
465 {
466  // Return cached value
467  return t->max_upkeep_height;
468 }
469 
474 {
475  int uk_bottom =
477  int u_bottom = tileset_unit_height(tileset);
478 
479  return MAX(uk_bottom, u_bottom);
480 }
481 
486 {
487  return t->unit_upkeep_offset_y;
488 }
489 
496 {
497  return t->small_sprite_size.width();
498 }
499 
504 int tileset_citybar_offset_y(const struct tileset *t)
505 {
506  return t->citybar_offset_y;
507 }
508 
514 {
515  return t->tilelabel_offset_y;
516 }
517 
524 {
525  return t->small_sprite_size.height();
526 }
527 
531 bool tileset_use_hard_coded_fog(const struct tileset *t)
532 {
533  return t->fogstyle == freeciv::FOG_AUTO;
534 }
535 
539 double tileset_preferred_scale(const struct tileset *t)
540 {
541  return t->preferred_scale;
542 }
543 
548 int tileset_replaced_hue(const struct tileset *t) { return t->replaced_hue; }
549 
554 int tileset_num_cardinal_dirs(const struct tileset *t)
555 {
556  return t->num_cardinal_tileset_dirs;
557 }
558 
565 {
566  return t->num_index_cardinal;
567 }
568 
574 std::array<direction8, 8> tileset_cardinal_dirs(const struct tileset *t)
575 {
576  return t->cardinal_tileset_dirs;
577 }
578 
582 int tileset_num_valid_dirs(const struct tileset *t)
583 {
584  return t->num_valid_tileset_dirs;
585 }
586 
592 std::array<direction8, 8> tileset_valid_dirs(const struct tileset *t)
593 {
594  return t->valid_tileset_dirs;
595 }
596 
600 static struct tileset *tileset_new()
601 {
602  struct tileset *t = new struct tileset[1]();
603 
604  t->specfiles = new QSet<specfile *>;
605  t->small_sprites = new QSet<struct small_sprite *>;
606  return t;
607 }
608 
613 QString dir_get_tileset_name(enum direction8 dir)
614 {
615  switch (dir) {
616  case DIR8_NORTH:
617  return QStringLiteral("n");
618  case DIR8_NORTHEAST:
619  return QStringLiteral("ne");
620  case DIR8_EAST:
621  return QStringLiteral("e");
622  case DIR8_SOUTHEAST:
623  return QStringLiteral("se");
624  case DIR8_SOUTH:
625  return QStringLiteral("s");
626  case DIR8_SOUTHWEST:
627  return QStringLiteral("sw");
628  case DIR8_WEST:
629  return QStringLiteral("w");
630  case DIR8_NORTHWEST:
631  return QStringLiteral("nw");
632  }
633  qCCritical(tileset_category, "Wrong direction8 variant: %d.", dir);
634  return QLatin1String("");
635 }
636 
640 static enum direction8 dir_by_tileset_name(const QString &str)
641 {
642  enum direction8 dir;
643 
644  for (dir = direction8_begin(); dir != direction8_end();
645  dir = direction8_next(dir)) {
646  if (dir_get_tileset_name(dir) == str) {
647  return dir;
648  }
649  }
650 
651  return direction8_invalid();
652 }
653 
657 static bool is_valid_tileset_dir(const struct tileset *t,
658  enum direction8 dir)
659 {
660  if (t->hex_width > 0) {
661  return dir != DIR8_NORTHEAST && dir != DIR8_SOUTHWEST;
662  } else if (t->hex_height > 0) {
663  return dir != DIR8_NORTHWEST && dir != DIR8_SOUTHEAST;
664  } else {
665  return true;
666  }
667 }
668 
675 bool is_cardinal_tileset_dir(const struct tileset *t, enum direction8 dir)
676 {
677  if (t->hex_width > 0 || t->hex_height > 0) {
678  return is_valid_tileset_dir(t, dir);
679  } else {
680  return (dir == DIR8_NORTH || dir == DIR8_EAST || dir == DIR8_SOUTH
681  || dir == DIR8_WEST);
682  }
683 }
684 
689 static int ts_topology_index(int actual_topology)
690 {
691  int idx;
692 
693  if ((actual_topology & TF_HEX) && (actual_topology & TF_ISO)) {
694  idx = TS_TOPO_ISOHEX;
695  } else if (actual_topology & TF_ISO) {
696  idx = TS_TOPO_SQUARE;
697  } else if (actual_topology & TF_HEX) {
698  idx = TS_TOPO_HEX;
699  } else {
700  idx = TS_TOPO_SQUARE;
701  }
702 
703  return idx;
704 }
705 
710 {
711  const auto type = QEvent::registerEventType();
712  fc_assert(type != -1);
713  TilesetChanged = static_cast<QEvent::Type>(type);
714 }
715 
719 QEvent::Type TilesetChanged;
720 
725 const QVector<QString> *get_tileset_list(const struct option *poption)
726 {
727  static QVector<QString> *tilesets[3] = {
729  int topo = option_get_cb_data(poption);
730  int idx;
731 
732  idx = ts_topology_index(topo);
733 
734  fc_assert_ret_val(idx < ARRAY_SIZE(tilesets), nullptr);
735 
737  tilesets[idx]->clear();
738  for (const auto &file : qAsConst(*list)) {
739  struct tileset *t =
740  tileset_read_toplevel(qUtf8Printable(file), false, topo);
741  if (t) {
742  tilesets[idx]->append(file);
743  tileset_free(t);
744  }
745  }
746  delete list;
747 
748  return tilesets[idx];
749 }
750 
758 static char *tilespec_fullname(QString tileset_name)
759 {
760  if (!tileset_name.isEmpty()) {
761  QString dname;
762  QString fname =
763  QStringLiteral("%1%2").arg(tileset_name, TILESPEC_SUFFIX);
764 
765  dname = fileinfoname(get_data_dirs(), qUtf8Printable(fname));
766 
767  if (!dname.isEmpty()) {
768  return fc_strdup(qUtf8Printable(dname));
769  }
770  }
771 
772  return nullptr;
773 }
774 
780 static bool check_tilespec_capabilities(struct section_file *file,
781  const char *which,
782  const char *us_capstr,
783  const char *filename, bool verbose)
784 {
785  QtMsgType level = verbose ? LOG_ERROR : LOG_DEBUG;
786 
787  const char *file_capstr = secfile_lookup_str(file, "%s.options", which);
788 
789  if (nullptr == file_capstr) {
790  log_base(level, "\"%s\": %s file doesn't have a capability string",
791  filename, which);
792  return false;
793  }
794  if (!has_capabilities(us_capstr, file_capstr)) {
795  log_base(level, "\"%s\": %s file appears incompatible:", filename,
796  which);
797  log_base(level, " datafile options: %s", file_capstr);
798  log_base(level, " supported options: %s", us_capstr);
799  return false;
800  }
801  if (!has_capabilities(file_capstr, us_capstr)) {
802  log_base(level,
803  "\"%s\": %s file requires option(s) "
804  "that client doesn't support:",
805  filename, which);
806  log_base(level, " datafile options: %s", file_capstr);
807  log_base(level, " supported options: %s", us_capstr);
808  return false;
809  }
810 
811  return true;
812 }
813 
819 static void tileset_free_toplevel(struct tileset *t)
820 {
821  if (t->estyle_hash) {
822  delete t->estyle_hash;
823  t->estyle_hash = nullptr;
824  }
825 
826  if (t->color_system) {
828  t->color_system = nullptr;
829  }
830 
831  delete[] t->summary;
832  delete[] t->description;
833  t->summary = nullptr;
834  t->description = nullptr;
835 }
836 
840 void tileset_free(struct tileset *t)
841 {
844  for (int i = 0; i < MAX_NUM_PLAYER_SLOTS; i++) {
845  tileset_player_free(t, i);
846  }
847  delete t->specfiles;
848  delete t->small_sprites;
849  delete[] t;
850 }
851 
860 bool tilespec_try_read(const QString &tileset_name, bool verbose,
861  int topo_id)
862 {
863  bool original;
864 
865  if (tileset_name.isEmpty()
866  || !(tileset =
867  tileset_read_toplevel(tileset_name, verbose, topo_id))) {
869 
870  original = false;
871  for (const auto &file : qAsConst(*list)) {
872  struct tileset *t =
873  tileset_read_toplevel(qUtf8Printable(file), false, topo_id);
874 
875  if (t) {
876  if (!tileset) {
877  tileset = t;
878  } else if (t->priority > tileset->priority
879  || (topo_id >= 0
881  != tileset_topo_index(t))) {
883  tileset = t;
884  } else {
885  tileset_free(t);
886  }
887  }
888  }
889  delete list;
890 
891  if (!tileset) {
892  tileset_error(nullptr, LOG_FATAL,
893  _("No usable default tileset found, aborting!"));
894  }
895 
896  qCDebug(tileset_category, "Trying tileset \"%s\".", tileset->name);
897  } else {
898  original = true;
899  }
900 
901  return original;
902 }
903 
916 bool tilespec_reread(const QString &name, bool game_fully_initialized)
917 {
918  int id;
919  enum client_states state = client_state();
920  bool new_tileset_in_use;
921 
922  qCInfo(tileset_category, _("Loading tileset \"%s\"."),
923  qUtf8Printable(name));
924 
925  /* Step 0: Record old data.
926  *
927  * We record the current mapcanvas center, etc.
928  */
929  auto center_tile = tileset ? get_center_tile_mapcanvas() : nullptr;
930 
931  /* Step 1: Cleanup.
932  *
933  * Free old tileset.
934  */
935  const char *old_name = nullptr;
936  if (tileset) {
937  old_name = tileset->name;
939  }
940 
941  /* Step 2: Read.
942  *
943  * We read in the new tileset. This should be pretty straightforward.
944  */
945  tileset = tileset_read_toplevel(name, false, -1);
946  if (tileset != nullptr) {
947  new_tileset_in_use = true;
948  } else {
949  new_tileset_in_use = false;
950 
951  if (old_name
952  && !(tileset = tileset_read_toplevel(old_name, false, -1))) {
953  // Always fails.
954  fc_assert_exit_msg(nullptr != tileset,
955  "Failed to re-read the currently loaded tileset.");
956  }
957  }
959 
960  if (game_fully_initialized) {
961  players_iterate(pplayer) { tileset_player_init(tileset, pplayer); }
963 
964  // "About Current Tileset"
967  }
968 
969  /* Step 3: Setup
970  *
971  * This is a seriously sticky problem. On startup, we build a hash
972  * from all the sprite data. Then, when we connect to a server, the
973  * server sends us ruleset data a piece at a time and we use this data
974  * to assemble the sprite structures. But if we change while connected
975  * we have to reassemble all of these. This should just involve
976  * calling tilespec_setup_*** on everything. But how do we tell what
977  * "everything" is?
978  *
979  * The below code just does things straightforwardly, by setting up
980  * each possible sprite again. Hopefully it catches everything, and
981  * doesn't mess up too badly if we change tilesets while not connected
982  * to a server.
983  */
984  if (!game.client.ruleset_ready) {
985  // The ruleset data is not sent until this point.
986  return new_tileset_in_use;
987  }
988 
990  == TOPO_INCOMP_HARD) {
992  _("Map topology and tileset incompatible."));
993  }
994 
995  terrain_type_iterate(pterrain)
996  {
997  tileset_setup_tile_type(tileset, pterrain);
998  }
1000  unit_type_iterate(punittype)
1001  {
1002  tileset_setup_unit_type(tileset, punittype);
1003  }
1005  for (auto &gov : governments) {
1007  }
1008  extra_type_iterate(pextra) { tileset_setup_extra(tileset, pextra); }
1010  for (auto &pnation : nations) {
1012  } // iterate over nations - pnation
1013  improvement_iterate(pimprove)
1014  {
1015  tileset_setup_impr_type(tileset, pimprove);
1016  }
1018  advance_iterate(A_FIRST, padvance)
1019  {
1020  tileset_setup_tech_type(tileset, padvance);
1021  }
1025 
1026  for (id = 0; id < game.control.styles_count; id++) {
1028  }
1029 
1030  if (state < C_S_RUNNING) {
1031  // Below redraws do not apply before this.
1032  return new_tileset_in_use;
1033  }
1034 
1035  /* Step 4: Draw.
1036  *
1037  * Do any necessary redraws.
1038  */
1039  // Old style notifications
1041  tileset_changed();
1042  /* update_map_canvas_visible forces a full redraw. Otherwise with fast
1043  * drawing we might not get one. Of course this is slower. */
1045  queen()->mapview_wdg->center_on_tile(center_tile, false);
1046 
1047  // New style notifications. See QApplication::setStyle for inspiration
1048  auto widgets = QApplication::allWidgets();
1049  for (auto *w : qAsConst(widgets)) {
1050  if (w->windowType() != Qt::Desktop) {
1051  QEvent e(TilesetChanged);
1052  QApplication::sendEvent(w, &e);
1053  }
1054  }
1055 
1056  return new_tileset_in_use;
1057 }
1058 
1063 void tilespec_reread_callback(struct option *poption)
1064 {
1065  const char *tileset_name;
1066  enum client_states state = client_state();
1067 
1068  if ((state == C_S_RUNNING || state == C_S_OVER)
1069  && wld.map.topology_id & TF_HEX
1070  && option_get_cb_data(poption)
1071  != (wld.map.topology_id & (TF_ISO | TF_HEX))) {
1072  // Changed option was not for current topology
1073  return;
1074  }
1075 
1076  tileset_name = option_str_get(poption);
1077 
1078  fc_assert_ret(nullptr != tileset_name && tileset_name[0] != '\0');
1079  tileset_update = true;
1080  tilespec_reread(tileset_name, client.conn.established);
1081  tileset_update = false;
1082  menus_init();
1083 }
1084 
1092 {
1093  tileset_update = true;
1094  tilespec_reread(name, true);
1095  tileset_update = false;
1096  menus_init();
1097 }
1098 
1102 static QPixmap *make_error_pixmap()
1103 {
1104  auto s = new QPixmap(20, 20);
1105  s->fill(Qt::red);
1106  return s;
1107 }
1108 
1113 static QPixmap *load_gfx_file(const char *gfx_filename)
1114 {
1115  // Try out all supported file extensions to find one that works.
1116  auto supported = QImageReader::supportedImageFormats();
1117 
1118  // Make sure we try png first (it's the most common and Qt always supports
1119  // it). This dramatically improves tileset loading performance on Windows.
1120  supported.prepend("png");
1121 
1122  for (auto gfx_fileext : qAsConst(supported)) {
1123  QString real_full_name;
1124  QString full_name =
1125  QStringLiteral("%1.%2").arg(gfx_filename, gfx_fileext.data());
1126 
1127  real_full_name =
1128  fileinfoname(get_data_dirs(), qUtf8Printable(full_name));
1129  if (!real_full_name.isEmpty()) {
1130  log_debug("trying to load gfx file \"%s\".",
1131  qUtf8Printable(real_full_name));
1132  if (const auto s = load_gfxfile(qUtf8Printable(real_full_name)); s) {
1133  return s;
1134  }
1135  }
1136  }
1137 
1138  qCCritical(tileset_category, "Could not load gfx file \"%s\".",
1139  gfx_filename);
1140  return make_error_pixmap();
1141 }
1142 
1146 static void ensure_big_sprite(struct tileset *t, struct specfile *sf)
1147 {
1148  struct section_file *file;
1149  const char *gfx_filename;
1150 
1151  if (sf->big_sprite) {
1152  // Looks like it's already loaded.
1153  return;
1154  }
1155 
1156  /* Otherwise load it. The big sprite will sometimes be freed and will have
1157  * to be reloaded, but most of the time it's just loaded once, the small
1158  * sprites are extracted, and then it's freed. */
1159  if (!(file = secfile_load(sf->file_name, true))) {
1160  tileset_error(t, LOG_FATAL, _("Could not open '%s':\n%s"), sf->file_name,
1161  secfile_error());
1162  }
1163 
1164  if (!check_tilespec_capabilities(file, "spec", SPEC_CAPSTR, sf->file_name,
1165  true)) {
1166  tileset_error(t, LOG_FATAL, _("Incompatible tileset capabilities"));
1167  }
1168 
1169  gfx_filename = secfile_lookup_str(file, "file.gfx");
1170 
1171  sf->big_sprite = load_gfx_file(gfx_filename);
1172 
1173  if (!sf->big_sprite) {
1175  _("Could not load gfx file for the spec file \"%s\"."),
1176  sf->file_name);
1177  }
1178  secfile_destroy(file);
1179 }
1180 
1186 static void scan_specfile(struct tileset *t, struct specfile *sf,
1187  bool duplicates_ok)
1188 {
1189  struct section_file *file;
1190  struct section_list *sections;
1191  int i;
1192 
1193  if (!(file = secfile_load(sf->file_name, true))) {
1194  tileset_error(t, LOG_FATAL, _("Could not open '%s':\n%s"), sf->file_name,
1195  secfile_error());
1196  }
1197  if (!check_tilespec_capabilities(file, "spec", SPEC_CAPSTR, sf->file_name,
1198  true)) {
1200  _("Specfile %s has incompatible capabilities"),
1201  sf->file_name);
1202  }
1203 
1204  // Currently unused
1205  (void) secfile_entry_lookup(file, "info.artists");
1206 
1207  // Not used here
1208  (void) secfile_entry_lookup(file, "file.gfx");
1209 
1210  if ((sections = secfile_sections_by_name_prefix(file, "grid_"))) {
1211  section_list_iterate(sections, psection)
1212  {
1213  int j, k;
1214  int x_top_left, y_top_left, dx, dy;
1215  int pixel_border_x;
1216  int pixel_border_y;
1217  const char *sec_name = section_name(psection);
1218 
1219  pixel_border_x =
1220  secfile_lookup_int_default(file, 0, "%s.pixel_border", sec_name);
1221  pixel_border_y = secfile_lookup_int_default(
1222  file, pixel_border_x, "%s.pixel_border_y", sec_name);
1223  pixel_border_x = secfile_lookup_int_default(
1224  file, pixel_border_x, "%s.pixel_border_x", sec_name);
1225  if (!secfile_lookup_int(file, &x_top_left, "%s.x_top_left", sec_name)
1226  || !secfile_lookup_int(file, &y_top_left, "%s.y_top_left",
1227  sec_name)
1228  || !secfile_lookup_int(file, &dx, "%s.dx", sec_name)
1229  || !secfile_lookup_int(file, &dy, "%s.dy", sec_name)) {
1230  qCCritical(tileset_category, "Grid \"%s\" invalid: %s", sec_name,
1231  secfile_error());
1232  continue;
1233  }
1234 
1235  j = -1;
1236  while (
1237  nullptr
1238  != secfile_entry_lookup(file, "%s.tiles%d.tag", sec_name, ++j)) {
1239  struct small_sprite *ss;
1240  int row, column;
1241  int xr, yb;
1242  const char **tags;
1243  size_t num_tags;
1244  int hot_x, hot_y;
1245 
1246  if (!secfile_lookup_int(file, &row, "%s.tiles%d.row", sec_name, j)
1247  || !secfile_lookup_int(file, &column, "%s.tiles%d.column",
1248  sec_name, j)
1249  || !(tags = secfile_lookup_str_vec(
1250  file, &num_tags, "%s.tiles%d.tag", sec_name, j))) {
1251  qCCritical(tileset_category,
1252  "Small sprite \"%s.tiles%d\" invalid: %s", sec_name, j,
1253  secfile_error());
1254  continue;
1255  }
1256 
1257  // Cursor pointing coordinates
1258  hot_x = secfile_lookup_int_default(file, 0, "%s.tiles%d.hot_x",
1259  sec_name, j);
1260  hot_y = secfile_lookup_int_default(file, 0, "%s.tiles%d.hot_y",
1261  sec_name, j);
1262 
1263  // User-configured options
1264  auto option = QString::fromUtf8(secfile_lookup_str_default(
1265  file, "", "%s.tiles%d.option", sec_name, j));
1266  if (!option.isEmpty()) {
1267  if (!tileset_has_option(t, option)) {
1268  // Ignore unknown options
1269  tileset_error(
1270  t, QtWarningMsg, "%s: unknown option %s for sprite %s",
1271  tileset_basename(t), qUtf8Printable(option), tags[0]);
1272  } else if (!tileset_option_is_enabled(t, option)) {
1273  // Skip sprites that correspond to disabled options
1274  continue;
1275  }
1276  }
1277 
1278  // there must be at least 1 because of the while():
1279  fc_assert_action(num_tags > 0, continue);
1280 
1281  xr = x_top_left + (dx + pixel_border_x) * column;
1282  yb = y_top_left + (dy + pixel_border_y) * row;
1283 
1284  ss = new small_sprite;
1285  ss->ref_count = 0;
1286  ss->file = nullptr;
1287  ss->x = xr;
1288  ss->y = yb;
1289  ss->width = dx;
1290  ss->height = dy;
1291  ss->sf = sf;
1292  ss->sprite = nullptr;
1293  ss->hot_x = hot_x;
1294  ss->hot_y = hot_y;
1295 
1296  t->small_sprites->insert(ss);
1297 
1298  if (!duplicates_ok) {
1299  for (k = 0; k < num_tags; k++) {
1300  if (t->sprite_hash->contains(tags[k]) && !option.isEmpty()) {
1301  // Warn about duplicated sprites, except if it was enabled by
1302  // a user option (to override the default).
1303  qCCritical(tileset_category,
1304  "warning: %s: already have a sprite for \"%s\".",
1305  t->name, tags[k]);
1306  }
1307  t->sprite_hash->insert(tags[k], ss);
1308  }
1309  } else {
1310  for (k = 0; k < num_tags; k++) {
1311  t->sprite_hash->insert(tags[k], ss);
1312  }
1313  }
1314 
1315  delete[] tags;
1316  tags = nullptr;
1317  }
1318  }
1320  section_list_destroy(sections);
1321  }
1322 
1323  // Load "extra" sprites. Each sprite is one file.
1324  i = -1;
1325  while (nullptr != secfile_entry_lookup(file, "extra.sprites%d.tag", ++i)) {
1326  struct small_sprite *ss;
1327  const char **tags;
1328  const char *filename;
1329  size_t num_tags, k;
1330  int hot_x, hot_y;
1331 
1332  if (!(tags = secfile_lookup_str_vec(file, &num_tags,
1333  "extra.sprites%d.tag", i))
1334  || !(filename =
1335  secfile_lookup_str(file, "extra.sprites%d.file", i))) {
1336  qCCritical(tileset_category,
1337  "Extra sprite \"extra.sprites%d\" invalid: %s", i,
1338  secfile_error());
1339  continue;
1340  }
1341 
1342  // Cursor pointing coordinates
1343  hot_x = secfile_lookup_int_default(file, 0, "extra.sprites%d.hot_x", i);
1344  hot_y = secfile_lookup_int_default(file, 0, "extra.sprites%d.hot_y", i);
1345 
1346  // User-configured options
1347  auto option = QString::fromUtf8(
1348  secfile_lookup_str_default(file, "", "extras.sprites%d.option", i));
1349  if (!option.isEmpty()) {
1350  if (!tileset_has_option(t, option)) {
1351  // Ignore unknown options
1352  tileset_error(t, QtWarningMsg, "%s: unknown option %s for sprite %s",
1353  tileset_basename(t), qUtf8Printable(option), tags[0]);
1354  } else if (!tileset_option_is_enabled(t, option)) {
1355  // Skip sprites that correspond to disabled options
1356  continue;
1357  }
1358  }
1359 
1360  ss = new small_sprite;
1361  ss->ref_count = 0;
1362  ss->file = fc_strdup(filename);
1363  ss->sf = nullptr;
1364  ss->sprite = nullptr;
1365  ss->hot_x = hot_x;
1366  ss->hot_y = hot_y;
1367 
1368  t->small_sprites->insert(ss);
1369 
1370  if (!duplicates_ok) {
1371  for (k = 0; k < num_tags; k++) {
1372  if (t->sprite_hash->contains(tags[k])) {
1373  qCWarning(tileset_category,
1374  "%s: already have a sprite for \"%s\".", t->name,
1375  tags[k]);
1376  }
1377  t->sprite_hash->insert(tags[k], ss);
1378  }
1379  } else {
1380  for (k = 0; k < num_tags; k++) {
1381  t->sprite_hash->insert(tags[k], ss);
1382  }
1383  }
1384  delete[] tags;
1385  }
1386 
1389 }
1390 
1395 check_sprite_type(const char *sprite_type, const char *tile_section)
1396 {
1397  if (fc_strcasecmp(sprite_type, "corner") == 0) {
1399  }
1400  if (fc_strcasecmp(sprite_type, "hex_corner") == 0) {
1402  }
1403  if (fc_strcasecmp(sprite_type, "single") == 0) {
1405  }
1406  if (fc_strcasecmp(sprite_type, "whole") == 0) {
1408  }
1409  qCCritical(tileset_category, "[%s] unknown sprite_type \"%s\".",
1410  tile_section, sprite_type);
1412 }
1413 
1414 static bool tileset_invalid_offsets(struct tileset *t,
1415  struct section_file *file)
1416 {
1417  return !secfile_lookup_int(file, &t->unit_flag_offset.rx(),
1418  "tilespec.unit_flag_offset_x")
1420  "tilespec.unit_flag_offset_y")
1422  "tilespec.city_flag_offset_x")
1424  "tilespec.city_flag_offset_y")
1425  || !secfile_lookup_int(file, &t->unit_offset.rx(),
1426  "tilespec.unit_offset_x")
1427  || !secfile_lookup_int(file, &t->unit_offset.ry(),
1428  "tilespec.unit_offset_y")
1429  || !secfile_lookup_int(file, &t->activity_offset.rx(),
1430  "tilespec.activity_offset_x")
1431  || !secfile_lookup_int(file, &t->activity_offset.ry(),
1432  "tilespec.activity_offset_y")
1433  || !secfile_lookup_int(file, &t->select_offset.rx(),
1434  "tilespec.select_offset_x")
1435  || !secfile_lookup_int(file, &t->select_offset.ry(),
1436  "tilespec.select_offset_y")
1437  || !secfile_lookup_int(file, &t->city_offset.rx(),
1438  "tilespec.city_offset_x")
1439  || !secfile_lookup_int(file, &t->city_offset.ry(),
1440  "tilespec.city_offset_y")
1442  "tilespec.city_size_offset_x")
1444  "tilespec.city_size_offset_y")
1446  "tilespec.citybar_offset_y")
1448  "tilespec.tilelabel_offset_y")
1449  || !secfile_lookup_int(file, &t->occupied_offset.rx(),
1450  "tilespec.occupied_offset_x")
1451  || !secfile_lookup_int(file, &t->occupied_offset.ry(),
1452  "tilespec.occupied_offset_y");
1453 }
1454 
1455 static void tileset_set_offsets(struct tileset *t, struct section_file *file)
1456 {
1458  file, tileset_tile_height(t), "tilespec.unit_upkeep_offset_y");
1460  file, t->unit_upkeep_offset_y, "tilespec.unit_upkeep_small_offset_y");
1461 }
1462 
1463 static void tileset_stop_read(struct tileset *t, struct section_file *file,
1464  char *fname, struct section_list *sections,
1465  const char **layer_order)
1466 {
1468  delete[] fname;
1469  delete[] layer_order;
1470  delete[] t;
1471  if (nullptr != sections) {
1472  section_list_destroy(sections);
1473  }
1474 }
1475 
1480 static void tileset_add_layer(struct tileset *t, mapview_layer layer)
1481 {
1482  switch (layer) {
1483  case LAYER_BACKGROUND:
1484  t->layers.push_back(std::make_unique<freeciv::layer_background>(t));
1485  break;
1486  case LAYER_CITY1: {
1487  t->layers.emplace_back(std::make_unique<freeciv::layer_city>(
1489  } break;
1490  case LAYER_CITY2: {
1491  t->layers.emplace_back(std::make_unique<freeciv::layer_city_size>(
1493  } break;
1494  case LAYER_DARKNESS: {
1495  t->layers.emplace_back(
1496  std::make_unique<freeciv::layer_darkness>(t, t->darkness_style));
1497  } break;
1498  case LAYER_EDITOR: {
1499  t->layers.emplace_back(std::make_unique<freeciv::layer_editor>(t));
1500  } break;
1501  case LAYER_FOG: {
1502  t->layers.emplace_back(std::make_unique<freeciv::layer_fog>(
1503  t, t->fogstyle, t->darkness_style));
1504  } break;
1505  case LAYER_GOTO: {
1506  t->layers.emplace_back(std::make_unique<freeciv::layer_goto>(t));
1507  } break;
1508  case LAYER_GRID1:
1509  case LAYER_GRID2: {
1510  t->layers.emplace_back(std::make_unique<freeciv::layer_grid>(t, layer));
1511  } break;
1512  case LAYER_INFRAWORK: {
1513  t->layers.emplace_back(
1514  std::make_unique<freeciv::layer_infrawork>(t, t->activity_offset));
1515  } break;
1516  case LAYER_OVERLAYS: {
1517  t->layers.emplace_back(std::make_unique<freeciv::layer_overlays>(t));
1518  } break;
1519  case LAYER_TERRAIN1: {
1520  auto l = std::make_unique<freeciv::layer_terrain>(t, 0);
1521  t->terrain_layers[0] = l.get();
1522  t->layers.emplace_back(std::move(l));
1523  } break;
1524  case LAYER_TERRAIN2: {
1525  auto l = std::make_unique<freeciv::layer_terrain>(t, 1);
1526  t->terrain_layers[1] = l.get();
1527  t->layers.emplace_back(std::move(l));
1528  } break;
1529  case LAYER_TERRAIN3: {
1530  auto l = std::make_unique<freeciv::layer_terrain>(t, 2);
1531  t->terrain_layers[2] = l.get();
1532  t->layers.emplace_back(std::move(l));
1533  } break;
1534  case LAYER_SPECIAL1:
1535  case LAYER_SPECIAL2:
1536  case LAYER_SPECIAL3: {
1537  t->layers.emplace_back(
1538  std::make_unique<freeciv::layer_special>(t, layer));
1539  } break;
1540  case LAYER_ROADS: {
1541  t->layers.emplace_back(std::make_unique<freeciv::layer_roads>(t));
1542  } break;
1543  case LAYER_BASE_FLAGS: {
1544  auto l = std::make_unique<freeciv::layer_base_flags>(
1546  t->layers.emplace_back(std::move(l));
1547  } break;
1548  case LAYER_UNIT: {
1549  t->layers.emplace_back(std::make_unique<freeciv::layer_units>(
1550  t, layer, t->activity_offset, t->select_offset, t->unit_offset,
1551  t->unit_flag_offset));
1552  } break;
1553  case LAYER_FOCUS_UNIT: {
1554  auto l = std::make_unique<freeciv::layer_units>(
1555  t, layer, t->activity_offset, t->select_offset, t->unit_offset,
1556  t->unit_flag_offset);
1557  t->focus_units_layer = l.get();
1558  t->layers.emplace_back(move(l));
1559  } break;
1560  case LAYER_WATER: {
1561  t->layers.emplace_back(std::make_unique<freeciv::layer_water>(t));
1562  } break;
1563  case LAYER_WORKERTASK: {
1564  t->layers.emplace_back(
1565  std::make_unique<freeciv::layer_workertask>(t, t->activity_offset));
1566  } break;
1567  default:
1568  t->layers.push_back(std::make_unique<freeciv::layer>(t, layer));
1569  break;
1570  }
1571 }
1572 
1579 static struct tileset *tileset_read_toplevel(const QString &tileset_name,
1580  bool verbose, int topology_id)
1581 {
1582  struct section_file *file;
1583  char *fname;
1584  const char *c;
1585  int i;
1586  size_t num_spec_files;
1587  const char **spec_filenames;
1588  size_t num_layers;
1589  const char **layer_order = nullptr;
1590  struct section_list *sections = nullptr;
1591  const char *file_capstr;
1592  bool duplicates_ok, is_hex;
1593  enum direction8 dir;
1594  struct tileset *t = nullptr;
1595  const char *extraname;
1596  const char *tstr;
1597  int topo;
1598 
1599  fname = tilespec_fullname(tileset_name);
1600  if (!fname) {
1601  if (verbose) {
1602  qCCritical(tileset_category, "Can't find tileset \"%s\".",
1603  qUtf8Printable(tileset_name));
1604  }
1605  return nullptr;
1606  }
1607  qCDebug(tileset_category, "tilespec file is \"%s\".", fname);
1608 
1609  if (!(file = secfile_load(fname, true))) {
1610  qCCritical(tileset_category, "Could not open '%s':\n%s", fname,
1611  secfile_error());
1612  delete[] fname;
1613  return nullptr;
1614  }
1615 
1616  if (!check_tilespec_capabilities(file, "tilespec", TILESPEC_CAPSTR, fname,
1617  verbose)) {
1618  secfile_destroy(file);
1619  delete[] fname;
1620  return nullptr;
1621  }
1622 
1623  t = tileset_new();
1624 
1625  file_capstr = secfile_lookup_str(file, "%s.options", "tilespec");
1626  duplicates_ok = (nullptr != file_capstr
1627  && has_capabilities("+duplicates_ok", file_capstr));
1628 
1629  tstr = secfile_lookup_str(file, "tilespec.name");
1630  // Tileset name found
1631  sz_strlcpy(t->given_name, tstr);
1632  tstr = secfile_lookup_str_default(file, "", "tilespec.version");
1633  if (tstr[0] != '\0') {
1634  // Tileset version found
1635  sz_strlcpy(t->version, tstr);
1636  } else {
1637  // No version information
1638  t->version[0] = '\0';
1639  }
1640 
1641  tstr = secfile_lookup_str_default(file, "", "tilespec.summary");
1642  if (tstr[0] != '\0') {
1643  int len;
1644 
1645  // Tileset summary found
1646  len = qstrlen(tstr);
1647  t->summary = new char[len + 1];
1648  fc_strlcpy(t->summary, tstr, len + 1);
1649  } else {
1650  // No summary
1651  delete[] t->summary;
1652  t->summary = nullptr;
1653  }
1654 
1655  tstr = secfile_lookup_str_default(file, "", "tilespec.description");
1656  if (tstr[0] != '\0') {
1657  int len;
1658 
1659  // Tileset description found
1660  len = qstrlen(tstr);
1661  t->description = new char[len + 1];
1662  fc_strlcpy(t->description, tstr, len + 1);
1663  } else {
1664  // No description
1665  if (t->description != nullptr) {
1666  delete[] t->description;
1667  t->description = nullptr;
1668  }
1669  }
1670 
1671  sz_strlcpy(t->name, tileset_name.toUtf8().data());
1672  if (!secfile_lookup_int(file, &t->priority, "tilespec.priority")
1673  || !secfile_lookup_bool(file, &is_hex, "tilespec.is_hex")) {
1674  qCCritical(tileset_category, "Tileset \"%s\" invalid: %s", t->name,
1675  secfile_error());
1676  tileset_stop_read(t, file, fname, sections, layer_order);
1677  return nullptr;
1678  }
1679 
1680  tstr = secfile_lookup_str(file, "tilespec.type");
1681  if (tstr == nullptr) {
1682  qCCritical(tileset_category, "Tileset \"%s\": no tileset type", t->name);
1683  tileset_stop_read(t, file, fname, sections, layer_order);
1684  return nullptr;
1685  }
1686 
1687  t->type = ts_type_by_name(tstr, fc_strcasecmp);
1688  if (!ts_type_is_valid(t->type)) {
1689  qCCritical(tileset_category,
1690  "Tileset \"%s\": unknown tileset type \"%s\"", t->name, tstr);
1691  tileset_stop_read(t, file, fname, sections, layer_order);
1692  return nullptr;
1693  }
1694 
1695  topo = 0;
1696  if (t->type == TS_ISOMETRIC) {
1697  topo = TF_ISO;
1698  }
1699 
1700  // Read hex-tileset information.
1701  t->hex_width = t->hex_height = 0;
1702  if (is_hex) {
1703  int hex_side;
1704 
1705  if (!secfile_lookup_int(file, &hex_side, "tilespec.hex_side")) {
1706  qCCritical(tileset_category, "Tileset \"%s\" invalid: %s", t->name,
1707  secfile_error());
1708  tileset_stop_read(t, file, fname, sections, layer_order);
1709  return nullptr;
1710  }
1711  if (t->type == TS_ISOMETRIC) {
1712  t->hex_width = hex_side;
1713  } else {
1714  t->hex_height = hex_side;
1715  }
1716 
1717  topo |= TF_HEX;
1718 
1719  // Hex tilesets are drawn the same as isometric.
1720  /* FIXME: There will be other legal values to be used with hex
1721  * tileset in the future, and this would just overwrite it. */
1722  t->type = TS_ISOMETRIC;
1723  }
1724 
1725  if (topology_id >= 0) {
1726  if (((topology_id & TF_HEX) && topology_id != (topo & (TF_ISO | TF_HEX)))
1727  || (!(topology_id & TF_HEX) && (topo & TF_HEX))) {
1728  // Not of requested topology
1729  tileset_stop_read(t, file, fname, sections, layer_order);
1730  return nullptr;
1731  }
1732  }
1733 
1734  t->ts_topo_idx = ts_topology_index(topo);
1735 
1736  /* Create arrays of valid and cardinal tileset dirs. These depend
1737  * entirely on the tileset, not the topology. They are also in clockwise
1738  * rotational ordering. */
1740  dir = DIR8_NORTH;
1741  do {
1742  if (is_valid_tileset_dir(t, dir)) {
1745  }
1746  if (is_cardinal_tileset_dir(t, dir)) {
1749  }
1750 
1751  dir = dir_cw(dir);
1752  } while (dir != DIR8_NORTH);
1753  fc_assert(t->num_valid_tileset_dirs % 2 == 0); // Assumed elsewhere.
1756 
1757  if (!secfile_lookup_int(file, &t->normal_tile_size.rwidth(),
1758  "tilespec.normal_tile_width")
1759  || !secfile_lookup_int(file, &t->normal_tile_size.rheight(),
1760  "tilespec.normal_tile_height")) {
1761  qCCritical(tileset_category, "Tileset \"%s\" invalid: %s", t->name,
1762  secfile_error());
1763  tileset_stop_read(t, file, fname, sections, layer_order);
1764  return nullptr;
1765  }
1766  if (t->type == TS_ISOMETRIC) {
1767  t->full_tile_size.rwidth() = t->normal_tile_size.width();
1768  if (tileset_hex_height(t) > 0) {
1769  t->full_tile_size.rheight() = t->normal_tile_size.height();
1770  } else {
1771  t->full_tile_size.rheight() = 3 * t->normal_tile_size.height() / 2;
1772  }
1773  } else {
1775  }
1777  file, t->full_tile_size.width(), "tilespec.unit_width");
1779  file, t->full_tile_size.height(), "tilespec.unit_height");
1780  // Hue to be replaced in unit graphics
1781  t->replaced_hue =
1782  secfile_lookup_int_default(file, -1, "tilespec.replaced_hue");
1783 
1784  if (!secfile_lookup_int(file, &t->small_sprite_size.rwidth(),
1785  "tilespec.small_tile_width")
1786  || !secfile_lookup_int(file, &t->small_sprite_size.rheight(),
1787  "tilespec.small_tile_height")) {
1788  qCCritical(tileset_category, "Tileset \"%s\" invalid: %s", t->name,
1789  secfile_error());
1790  tileset_stop_read(t, file, fname, sections, layer_order);
1791  return nullptr;
1792  }
1793  qCDebug(tileset_category, "tile sizes %dx%d, %dx%d unit, %dx%d small",
1794  t->normal_tile_size.width(), t->normal_tile_size.height(),
1795  t->full_tile_size.width(), t->full_tile_size.height(),
1796  t->small_sprite_size.width(), t->small_sprite_size.height());
1797 
1798  tstr = secfile_lookup_str(file, "tilespec.fog_style");
1799  if (tstr == nullptr) {
1800  qCCritical(tileset_category, "Tileset \"%s\": no fog_style", t->name);
1801  tileset_stop_read(t, file, fname, sections, layer_order);
1802  return nullptr;
1803  }
1804 
1805  t->fogstyle = freeciv::fog_style_by_name(tstr, fc_strcasecmp);
1806  if (!fog_style_is_valid(t->fogstyle)) {
1807  qCCritical(tileset_category, "Tileset \"%s\": unknown fog_style \"%s\"",
1808  t->name, tstr);
1809  tileset_stop_read(t, file, fname, sections, layer_order);
1810  return nullptr;
1811  }
1812 
1814  file, 100, 1, 1000, "tilespec.preferred_scale")
1815  / 100.;
1816 
1818  file, 100, 1, 10000, "tilespec.select_step_ms");
1819 
1820  if (tileset_invalid_offsets(t, file)) {
1821  qCCritical(tileset_category, "Tileset \"%s\" invalid: %s", t->name,
1822  secfile_error());
1823  tileset_stop_read(t, file, fname, sections, layer_order);
1824  return nullptr;
1825  }
1826  tileset_set_offsets(t, file);
1827 
1828  c = secfile_lookup_str_default(file, nullptr,
1829  "tilespec.unit_default_orientation");
1830  if (!c) {
1831  // This is valid, but tileset must specify icon for every unit
1832  t->unit_default_orientation = direction8_invalid();
1833  } else {
1834  dir = dir_by_tileset_name(c);
1835 
1836  if (!direction8_is_valid(dir)) {
1838  "Tileset \"%s\": unknown "
1839  "unit_default_orientation \"%s\"",
1840  t->name, c);
1841  tileset_stop_read(t, file, fname, sections, layer_order);
1842  return nullptr;
1843  } else {
1844  /* Default orientation is allowed to not be a valid one for the
1845  * tileset */
1846  t->unit_default_orientation = dir;
1847  }
1848  }
1849 
1850  tstr = secfile_lookup_str(file, "tilespec.darkness_style");
1851  if (tstr == nullptr) {
1852  qCCritical(tileset_category, "Tileset \"%s\": no darkness_style",
1853  t->name);
1854  tileset_stop_read(t, file, fname, sections, layer_order);
1855  return nullptr;
1856  }
1857 
1858  t->darkness_style = freeciv::darkness_style_by_name(tstr, fc_strcasecmp);
1859  if (!darkness_style_is_valid(t->darkness_style)) {
1860  qCCritical(tileset_category,
1861  "Tileset \"%s\": unknown darkness_style \"%s\"", t->name,
1862  tstr);
1863  tileset_stop_read(t, file, fname, sections, layer_order);
1864  return nullptr;
1865  }
1866 
1867  if (t->darkness_style == freeciv::DARKNESS_ISORECT
1868  && (t->type == TS_OVERHEAD || t->hex_width > 0 || t->hex_height > 0)) {
1869  qCCritical(tileset_category,
1870  "Invalid darkness style set in tileset \"%s\".", t->name);
1871  tileset_stop_read(t, file, fname, sections, layer_order);
1872  return nullptr;
1873  }
1874 
1875  // Layer order
1876  num_layers = 0;
1877  layer_order =
1878  secfile_lookup_str_vec(file, &num_layers, "tilespec.layer_order");
1879  if (layer_order != nullptr) {
1880  mapview_layer order[LAYER_COUNT];
1881  for (i = 0; i < num_layers; i++) {
1882  int j;
1883  enum mapview_layer layer =
1884  mapview_layer_by_name(layer_order[i], fc_strcasecmp);
1885 
1886  // Check for wrong layer names.
1887  if (!mapview_layer_is_valid(layer)) {
1888  qCCritical(tileset_category, "layer_order: Invalid layer \"%s\"",
1889  layer_order[i]);
1890  tileset_stop_read(t, file, fname, sections, layer_order);
1891  return nullptr;
1892  }
1893  // Check for duplicates.
1894  for (j = 0; j < i; j++) {
1895  if (order[j] == layer) {
1896  qCCritical(tileset_category, "layer_order: Duplicate layer \"%s\"",
1897  layer_order[i]);
1898  tileset_stop_read(t, file, fname, sections, layer_order);
1899  return nullptr;
1900  }
1901  }
1902  order[i] = layer;
1903  }
1904 
1905  /* Now check that all layers are present. Doing it now allows for a
1906  * more comprehensive error message. */
1907  for (i = 0; i < LAYER_COUNT; i++) {
1908  int j;
1909  bool found = false;
1910 
1911  for (j = 0; j < num_layers; j++) {
1912  if (i == order[j]) {
1913  found = true;
1914  break;
1915  }
1916  }
1917  if (!found) {
1918  qCCritical(tileset_category, "layer_order: Missing layer \"%s\"",
1919  mapview_layer_name(static_cast<mapview_layer>(i)));
1920  tileset_stop_read(t, file, fname, sections, layer_order);
1921  return nullptr;
1922  }
1923  }
1924 
1925  for (auto layer : order) {
1926  tileset_add_layer(t, layer);
1927  }
1928  } else {
1929  // There is no layer_order tag in the specfile -> use the default
1930  for (i = 0; i < LAYER_COUNT; ++i) {
1931  tileset_add_layer(t, static_cast<mapview_layer>(i));
1932  }
1933  }
1934 
1935  // Terrain layer info.
1936  for (i = 0; i < MAX_NUM_LAYERS; i++) {
1937  std::size_t count = 0;
1938  auto match_types =
1939  secfile_lookup_str_vec(file, &count, "layer%d.match_types", i);
1940  for (int j = 0; j < count; j++) {
1941  if (!t->terrain_layers[i]->create_matching_group(match_types[j])) {
1942  tileset_stop_read(t, file, fname, sections, layer_order);
1943  return nullptr;
1944  }
1945  }
1946  }
1947 
1948  // Tile drawing info.
1950  if (nullptr == sections || 0 == section_list_size(sections)) {
1952  _("No [%s] sections supported by tileset \"%s\"."),
1953  TILE_SECTION_PREFIX, fname);
1954  tileset_stop_read(t, file, fname, sections, layer_order);
1955  return nullptr;
1956  }
1957 
1958  section_list_iterate(sections, psection)
1959  {
1960  auto sec_name = section_name(psection);
1961 
1962  QString tag;
1963  {
1964  auto c_tag = secfile_lookup_str(file, "%s.tag", sec_name);
1965  if (c_tag != nullptr) {
1966  tag = c_tag;
1967  } else {
1969  _("No terrain tag given in section [%s]."), sec_name);
1970  tileset_stop_read(t, file, fname, sections, layer_order);
1971  return nullptr;
1972  }
1973  }
1974 
1975  {
1976  auto num_layers =
1977  secfile_lookup_int_default(file, 0, "%s.num_layers", sec_name);
1978  num_layers = CLIP(1, num_layers, MAX_NUM_LAYERS);
1979 
1980  for (int l = 0; l < num_layers; l++) {
1981  if (!t->terrain_layers[l]->add_tag(
1982  tag, QString(sec_name).mid(strlen(TILE_SECTION_PREFIX)))) {
1983  tileset_stop_read(t, file, fname, sections, layer_order);
1984  return nullptr;
1985  }
1986 
1987  // Offsets
1988  {
1989  auto is_tall = secfile_lookup_bool_default(
1990  file, false, "%s.layer%d_is_tall", sec_name, l);
1991 
1992  auto offset_x = secfile_lookup_int_default(
1993  file, 0, "%s.layer%d_offset_x", sec_name, l);
1994  if (is_tall) {
1995  offset_x += tileset_full_tile_offset(t).x();
1996  }
1997 
1998  auto offset_y = secfile_lookup_int_default(
1999  file, 0, "%s.layer%d_offset_y", sec_name, l);
2000  if (is_tall) {
2001  offset_y += tileset_full_tile_offset(t).y();
2002  }
2003 
2004  if (!t->terrain_layers[l]->set_tag_offsets(tag, offset_x,
2005  offset_y)) {
2006  tileset_stop_read(t, file, fname, sections, layer_order);
2007  return nullptr;
2008  }
2009  }
2010 
2011  // Sprite type
2012  {
2013  auto type_str = secfile_lookup_str_default(
2014  file, "whole", "%s.layer%d_sprite_type", sec_name, l);
2015  if (!t->terrain_layers[l]->set_tag_sprite_type(
2016  tag, check_sprite_type(type_str, sec_name))) {
2017  tileset_stop_read(t, file, fname, sections, layer_order);
2018  return nullptr;
2019  }
2020  }
2021 
2022  // Matching
2023  {
2024  auto matching_group = secfile_lookup_str_default(
2025  file, nullptr, "%s.layer%d_match_type", sec_name, l);
2026 
2027  if (matching_group) {
2028  if (!t->terrain_layers[l]->set_tag_matching_group(
2029  tag, matching_group)) {
2030  tileset_stop_read(t, file, fname, sections, layer_order);
2031  return nullptr;
2032  }
2033  }
2034 
2035  std::size_t count = 0;
2036  auto match_with = secfile_lookup_str_vec(
2037  file, &count, "%s.layer%d_match_with", sec_name, l);
2038  if (match_with) {
2039  for (std::size_t j = 0; j < count; ++j) {
2040  if (!t->terrain_layers[l]->set_tag_matches_with(
2041  tag, match_with[j])) {
2042  tileset_stop_read(t, file, fname, sections, layer_order);
2043  return nullptr;
2044  }
2045  }
2046  }
2047  }
2048  }
2049  {
2050  auto blending =
2051  secfile_lookup_int_default(file, 0, "%s.blend_layer", sec_name);
2052  if (blending > 0) {
2053  t->terrain_layers[CLIP(0, blending - 1, MAX_NUM_LAYERS - 1)]
2054  ->enable_blending(tag);
2055  }
2056  }
2057  }
2058  }
2060  section_list_destroy(sections);
2061  sections = nullptr;
2062 
2063  if (!tileset_setup_options(t, file)) {
2064  return nullptr;
2065  }
2066 
2067  t->estyle_hash = new QHash<QString, extrastyle_id>;
2068 
2069  for (i = 0; (extraname = secfile_lookup_str_default(
2070  file, nullptr, "extras.styles%d.name", i));
2071  i++) {
2072  const char *style_name;
2073 
2074  style_name = secfile_lookup_str_default(file, "Single1",
2075  "extras.styles%d.style", i);
2076  auto style = extrastyle_id_by_name(style_name, fc_strcasecmp);
2077 
2078  if (t->estyle_hash->contains(extraname)) {
2079  qCCritical(tileset_category,
2080  "warning: duplicate extrastyle entry [%s].", extraname);
2081  tileset_stop_read(t, file, fname, sections, layer_order);
2082  return nullptr;
2083  }
2084  t->estyle_hash->insert(extraname, style);
2085  }
2086 
2087  spec_filenames =
2088  secfile_lookup_str_vec(file, &num_spec_files, "tilespec.files");
2089  if (nullptr == spec_filenames || 0 == num_spec_files) {
2090  qCCritical(tileset_category,
2091  "No tile graphics files specified in \"%s\"", fname);
2092  tileset_stop_read(t, file, fname, sections, layer_order);
2093  return nullptr;
2094  }
2095 
2096  fc_assert(t->sprite_hash == nullptr);
2097  t->sprite_hash = new QHash<QString, struct small_sprite *>;
2098  for (i = 0; i < num_spec_files; i++) {
2099  struct specfile *sf = new specfile();
2100  QString dname;
2101 
2102  log_debug("spec file %s", spec_filenames[i]);
2103 
2104  sf->big_sprite = nullptr;
2105  dname = fileinfoname(get_data_dirs(), spec_filenames[i]);
2106  if (dname.isEmpty()) {
2107  if (verbose) {
2108  qCCritical(tileset_category, "Can't find spec file \"%s\".",
2109  spec_filenames[i]);
2110  }
2111  delete sf;
2112  tileset_stop_read(t, file, fname, sections, layer_order);
2113  return nullptr;
2114  }
2115  sf->file_name = fc_strdup(qUtf8Printable(dname));
2116  scan_specfile(t, sf, duplicates_ok);
2117 
2118  t->specfiles->insert(sf);
2119  }
2120  delete[] spec_filenames;
2121 
2122  t->color_system = color_system_read(file);
2123 
2124  secfile_check_unused(file);
2125  secfile_destroy(file);
2126  qCDebug(tileset_category, "finished reading \"%s\".", fname);
2127  delete[] fname;
2128  delete[] layer_order;
2129 
2130  return t;
2131 }
2132 
2139 static bool tileset_setup_options(struct tileset *t,
2140  const section_file *file)
2141 {
2142  // First load options from the tilespec file.
2143  auto sections =
2145  if (!sections) {
2146  return true;
2147  }
2148 
2149  std::set<QString> all_names;
2150 
2151  section_list_iterate(sections, psection)
2152  {
2153  // Mandatory fields: name, description. Optional: enabled_by_default.
2154  const auto sec_name = section_name(psection);
2155 
2157 
2158  auto name = secfile_lookup_str_default(file, "", "%s.name", sec_name);
2159  if (qstrlen(name) == 0) {
2160  tileset_error(t, QtCriticalMsg, "Option \"%s\" has no name", sec_name);
2161  continue; // Skip instead of erroring out: options are optional
2162  }
2163 
2164  // Check for duplicates
2165  if (all_names.count(name)) {
2166  tileset_error(t, QtCriticalMsg, "Duplicated option name \"%s\"", name);
2167  continue; // Skip instead of erroring out: options are optional
2168  }
2169  all_names.insert(name);
2170 
2171  auto description =
2172  secfile_lookup_str_default(file, "", "%s.description", sec_name);
2173  if (qstrlen(description) == 0) {
2174  tileset_error(t, QtCriticalMsg, "Option \"%s\" has no description",
2175  name);
2176  continue; // Skip instead of erroring out: options are optional
2177  }
2178  option.description = QString::fromUtf8(description);
2179 
2180  option.enabled_by_default =
2181  secfile_lookup_bool_default(file, false, "%s.default", sec_name);
2182  option.enabled = option.enabled_by_default;
2183 
2184  t->options[name] = std::move(option);
2185  }
2187 
2188  // Then apply client options. They override any default value we may have
2189  // set.
2190  const auto tileset_name = tileset_basename(t);
2191  if (gui_options->tileset_options.count(tileset_name)) {
2192  for (const auto &[name, value] :
2193  gui_options->tileset_options[tileset_name]) {
2194  if (tileset_has_option(t, name)) {
2195  t->options[name].enabled = value;
2196  }
2197  // Silently ignore options that do not exist.
2198  }
2199  }
2200 
2201  return true;
2202 }
2203 
2207 static const char *citizen_rule_name(enum citizen_category citizen)
2208 {
2209  /* These strings are used in reading the tileset. Do not
2210  * translate. */
2211  switch (citizen) {
2212  case CITIZEN_HAPPY:
2213  return "happy";
2214  case CITIZEN_CONTENT:
2215  return "content";
2216  case CITIZEN_UNHAPPY:
2217  return "unhappy";
2218  case CITIZEN_ANGRY:
2219  return "angry";
2220  default:
2221  break;
2222  }
2223  qCCritical(tileset_category, "Unknown citizen type: %d.",
2224  static_cast<int>(citizen));
2225  return nullptr;
2226 }
2227 
2233 QString cardinal_index_str(const struct tileset *t, int idx)
2234 {
2235  auto c = QString();
2236  for (int i = 0; i < t->num_cardinal_tileset_dirs; i++) {
2237  int value = (idx >> i) & 1;
2238 
2239  c += QStringLiteral("%1%2").arg(
2241  QString::number(value));
2242  }
2243 
2244  return c;
2245 }
2246 
2251 QString valid_index_str(const struct tileset *t, int idx)
2252 {
2253  auto c = QString();
2254  for (int i = 0; i < t->num_valid_tileset_dirs; i++) {
2255  int value = (idx >> i) & 1;
2256 
2257  c += QStringLiteral("%1%2").arg(
2259  QString::number(value));
2260  }
2261 
2262  return c;
2263 }
2264 
2270 static QPixmap *load_sprite(struct tileset *t, const QString &tag_name)
2271 {
2272  struct small_sprite *ss;
2273 
2274  log_debug("load_sprite(tag='%s')", qUtf8Printable(tag_name));
2275  // Lookup information about where the sprite is found.
2276  if (!(ss = t->sprite_hash->value(tag_name, nullptr))) {
2277  return nullptr;
2278  }
2279 
2280  fc_assert(ss->ref_count >= 0);
2281 
2282  if (!ss->sprite) {
2283  // If the sprite hasn't been loaded already, then load it.
2284  fc_assert(ss->ref_count == 0);
2285  if (ss->file) {
2286  ss->sprite = load_gfx_file(ss->file);
2287  if (!ss->sprite) {
2289  _("Couldn't load gfx file \"%s\" for sprite '%s'."),
2290  ss->file, qUtf8Printable(tag_name));
2291  return nullptr;
2292  }
2293  } else {
2294  ensure_big_sprite(t, ss->sf);
2295 
2296  auto sf_w = ss->sf->big_sprite->width();
2297  auto sf_h = ss->sf->big_sprite->height();
2298  if (ss->x < 0 || ss->x + ss->width > sf_w || ss->y < 0
2299  || ss->y + ss->height > sf_h) {
2300  tileset_error(
2301  t, LOG_ERROR,
2302  _("Sprite '%s' in file \"%s\" isn't within the image!"),
2303  qUtf8Printable(tag_name), ss->sf->file_name);
2304  return nullptr;
2305  }
2306  ss->sprite = crop_sprite(ss->sf->big_sprite, ss->x, ss->y, ss->width,
2307  ss->height, nullptr, -1, -1);
2308  }
2309  }
2310 
2311  // Track the reference count so we know when to free the sprite.
2312  ss->ref_count++;
2313 
2314  return ss->sprite;
2315 }
2316 
2322 QPixmap *load_sprite(struct tileset *t, const QStringList &possible_names,
2323  bool required, bool verbose)
2324 {
2325  // go through the list of possible names until
2326  // you find a sprite that exists.
2327  for (const auto &name : possible_names) {
2328  auto sprite = load_sprite(t, name);
2329  if (sprite) {
2330  return sprite;
2331  }
2332  }
2333 
2334  if (verbose) {
2335  // TODO Qt6
2336  // We should be able to remove the line below and
2337  // update the tileset_errors in the if statement.
2338  QVector<QString> names_vec(possible_names.begin(), possible_names.end());
2339  // if sprite couldn't be found and it is required, crash, else warn.
2340  if (required) {
2342  _("Could not find required sprite matching %s"),
2343  qUtf8Printable(strvec_to_or_list(names_vec)));
2344  } else {
2346  _("Could not find optional sprite matching %s"),
2347  qUtf8Printable(strvec_to_or_list(names_vec)));
2348  }
2349  }
2350 
2351  return nullptr;
2352 }
2353 
2358 static void unload_sprite(struct tileset *t, const QString &tag_name)
2359 {
2360  struct small_sprite *ss = t->sprite_hash->value(tag_name);
2361  fc_assert_ret(ss);
2362  fc_assert_ret(ss->ref_count >= 1);
2363  fc_assert_ret(ss->sprite);
2364 
2365  ss->ref_count--;
2366 
2367  if (ss->ref_count == 0) {
2368  /* Nobody's using the sprite anymore, so we should free it. We know
2369  * where to find it if we need it again. */
2370  // log_debug("freeing sprite '%s'.", tag_name);
2371  delete ss->sprite;
2372  ss->sprite = nullptr;
2373  }
2374 }
2375 
2380 static void assign_sprite(struct tileset *t, QPixmap *&field,
2381  const QStringList &possible_names, bool required)
2382 {
2383  field = load_sprite(t, possible_names, required);
2384 }
2385 
2390 static void assign_digit_sprites_helper(struct tileset *t,
2391  QPixmap *sprites[NUM_TILES_DIGITS],
2392  const QStringList &patterns,
2393  const QString &suffix, bool required)
2394 {
2395  for (int i = 0; i < NUM_TILES_DIGITS; i++) {
2396  QStringList names;
2397  for (const auto &pattern : patterns) {
2398  names.append(pattern.arg(QString::number(i)) + suffix);
2399  }
2400  assign_sprite(t, sprites[i], {names}, required);
2401  }
2402 }
2403 
2409  QPixmap *units[NUM_TILES_DIGITS],
2410  QPixmap *tens[NUM_TILES_DIGITS],
2411  QPixmap *hundreds[NUM_TILES_DIGITS],
2412  const QStringList &patterns)
2413 {
2414  assign_digit_sprites_helper(t, units, patterns, QStringLiteral(), true);
2415  assign_digit_sprites_helper(t, tens, patterns, QStringLiteral("0"), true);
2416  assign_digit_sprites_helper(t, hundreds, patterns, QStringLiteral("00"),
2417  false);
2418 }
2419 
2424 {
2425  // Load the specialist sprite graphics.
2426  QString buffer;
2427  int j;
2428  struct specialist *spe = specialist_by_number(id);
2429  const char *tag = spe->graphic_str;
2430  const char *graphic_alt = spe->graphic_alt;
2431 
2432  for (j = 0; j < MAX_NUM_CITIZEN_SPRITES; j++) {
2433  // Try tag name + index number
2434  buffer = QStringLiteral("%1_%2").arg(tag, QString::number(j));
2435  t->sprites.specialist[id].sprite[j] = load_sprite(t, buffer);
2436 
2437  // Break if no more index specific sprites are defined
2438  if (!t->sprites.specialist[id].sprite[j]) {
2439  break;
2440  }
2441  }
2442 
2443  if (j == 0) {
2444  // Try non-indexed
2445  t->sprites.specialist[id].sprite[j] = load_sprite(t, tag);
2446 
2447  if (t->sprites.specialist[id].sprite[j]) {
2448  j = 1;
2449  }
2450  }
2451 
2452  if (j == 0) {
2453  // Try the alt tag
2454  for (j = 0; j < MAX_NUM_CITIZEN_SPRITES; j++) {
2455  // Try alt tag name + index number
2456  buffer = QStringLiteral("%1_%2").arg(graphic_alt, QString::number(j));
2457  t->sprites.specialist[id].sprite[j] = load_sprite(t, buffer);
2458 
2459  // Break if no more index specific sprites are defined
2460  if (!t->sprites.specialist[id].sprite[j]) {
2461  break;
2462  }
2463  }
2464  }
2465 
2466  if (j == 0) {
2467  // Try alt tag non-indexed
2469 
2470  if (t->sprites.specialist[id].sprite[j]) {
2471  j = 1;
2472  }
2473  }
2474 
2475  t->sprites.specialist[id].count = j;
2476 
2477  // Still nothing? Give up.
2478  if (j == 0) {
2479  tileset_error(t, LOG_FATAL, _("No graphics for specialist \"%s\"."),
2480  tag);
2481  }
2482 }
2483 
2487 static void tileset_setup_citizen_types(struct tileset *t)
2488 {
2489  int i, j;
2490  QString buffer;
2491 
2492  // Load the citizen sprite graphics, no specialist.
2493  for (i = 0; i < CITIZEN_LAST; i++) {
2494  const char *name = citizen_rule_name(static_cast<citizen_category>(i));
2495 
2496  for (j = 0; j < MAX_NUM_CITIZEN_SPRITES; j++) {
2497  buffer = QStringLiteral("citizen.%1_%2").arg(name, QString::number(j));
2498  t->sprites.citizen[i].sprite[j] = load_sprite(t, buffer);
2499  if (!t->sprites.citizen[i].sprite[j]) {
2500  break;
2501  }
2502  }
2503  t->sprites.citizen[i].count = j;
2504  if (j == 0) {
2505  tileset_error(t, LOG_FATAL, _("No graphics for citizen \"%s\"."),
2506  name);
2507  }
2508  }
2509 }
2510 
2515 static void tileset_lookup_sprite_tags(struct tileset *t)
2516 {
2517  QString buffer, buffer2;
2518  int i, j, f;
2519 
2520  fc_assert_ret(t->sprite_hash != nullptr);
2521 
2523  {"treaty.disagree_thumb_down"}, true);
2524  assign_sprite(t, t->sprites.treaty_thumb[1], {"treaty.agree_thumb_up"},
2525  true);
2526 
2527  for (j = 0; j < INDICATOR_COUNT; j++) {
2528  const char *names[] = {"science_bulb", "warming_sun", "cooling_flake"};
2529 
2530  for (i = 0; i < NUM_TILES_PROGRESS; i++) {
2531  buffer = QStringLiteral("s.%1_%2").arg(names[j], QString::number(i));
2532  assign_sprite(t, t->sprites.indicator[j][i], {buffer}, true);
2533  }
2534  }
2535 
2536  assign_sprite(t, t->sprites.arrow[ARROW_RIGHT], {"s.right_arrow"}, true);
2537  assign_sprite(t, t->sprites.arrow[ARROW_PLUS], {"s.plus"}, true);
2538  assign_sprite(t, t->sprites.arrow[ARROW_MINUS], {"s.minus"}, true);
2539  if (t->type == TS_ISOMETRIC) {
2540  assign_sprite(t, t->sprites.dither_tile, {"t.dither_tile"}, true);
2541  }
2542 
2544  assign_sprite(t, t->sprites.mask.tile, {"mask.tile"}, true);
2545  } else {
2546  assign_sprite(t, t->sprites.mask.tile, {"mask.tile"}, true);
2547  }
2548 
2549  assign_sprite(t, t->sprites.tax_luxury, {"s.tax_luxury"}, true);
2550  assign_sprite(t, t->sprites.tax_science, {"s.tax_science"}, true);
2551  assign_sprite(t, t->sprites.tax_gold, {"s.tax_gold"}, true);
2552 
2554 
2555  for (i = 0; i < SPACESHIP_COUNT; i++) {
2556  const char *names[SPACESHIP_COUNT] = {
2557  "solar_panels", "life_support", "habitation", "structural",
2558  "fuel", "propulsion", "exhaust"};
2559 
2560  buffer = QStringLiteral("spaceship.%1").arg(names[i]);
2561  assign_sprite(t, t->sprites.spaceship[i], {buffer}, true);
2562  }
2563 
2564  for (i = 0; i < CURSOR_LAST; i++) {
2565  for (f = 0; f < NUM_CURSOR_FRAMES; f++) {
2566  const char *names[CURSOR_LAST] = {
2567  "goto", "patrol", "paradrop", "nuke", "select",
2568  "invalid", "attack", "edit_paint", "edit_add", "wait"};
2569  struct small_sprite *ss;
2570 
2571  fc_assert(ARRAY_SIZE(names) == CURSOR_LAST);
2572  buffer =
2573  QStringLiteral("cursor.%1%2").arg(names[i], QString::number(f));
2574  assign_sprite(t, t->sprites.cursor[i].frame[f], {buffer}, true);
2575  ss = t->sprite_hash->value(buffer, nullptr);
2576  if (ss) {
2577  t->sprites.cursor[i].hot_x = ss->hot_x;
2578  t->sprites.cursor[i].hot_y = ss->hot_y;
2579  }
2580  }
2581  }
2582 
2583  for (i = 0; i < E_COUNT; i++) {
2584  const char *tag = get_event_tag(static_cast<event_type>(i));
2585  assign_sprite(t, t->sprites.events[i], {tag}, true);
2586  }
2587 
2588  assign_sprite(t, t->sprites.explode.nuke, {"explode.nuke"}, true);
2589 
2590  for (i = 0;; i++) {
2591  QPixmap *sprite;
2592 
2593  buffer = QStringLiteral("explode.unit_%1").arg(QString::number(i));
2594  sprite = load_sprite(t, buffer);
2595  if (!sprite) {
2596  break;
2597  }
2598  t->sprites.explode.unit.push_back(sprite);
2599  }
2600 
2601  assign_sprite(t, t->sprites.citybar.shields, {"citybar.shields"}, true);
2602  assign_sprite(t, t->sprites.citybar.food, {"citybar.food"}, true);
2603  assign_sprite(t, t->sprites.citybar.trade, {"citybar.trade"}, true);
2604  assign_sprite(t, t->sprites.citybar.occupied, {"citybar.occupied"}, true);
2605  assign_sprite(t, t->sprites.citybar.background, {"citybar.background"},
2606  true);
2607  for (i = 0;; i++) {
2608  QPixmap *sprite;
2609 
2610  buffer = QStringLiteral("citybar.occupancy_%1").arg(QString::number(i));
2611  sprite = load_sprite(t, buffer);
2612  if (!sprite) {
2613  break;
2614  }
2615  t->sprites.citybar.occupancy.push_back(sprite);
2616  }
2617  if (t->sprites.citybar.occupancy.size() < 2) {
2619  _("Missing necessary citybar.occupancy_N sprites."));
2620  }
2621 
2622  assign_sprite(t, t->sprites.editor.erase, {"editor.erase"}, true);
2623  assign_sprite(t, t->sprites.editor.brush, {"editor.brush"}, true);
2624  assign_sprite(t, t->sprites.editor.copy, {"editor.copy"}, true);
2625  assign_sprite(t, t->sprites.editor.paste, {"editor.paste"}, true);
2626  assign_sprite(t, t->sprites.editor.copypaste, {"editor.copypaste"}, true);
2627  assign_sprite(t, t->sprites.editor.startpos, {"editor.startpos"}, true);
2628  assign_sprite(t, t->sprites.editor.terrain, {"editor.terrain"}, true);
2630  {"editor.terrain_resource"}, true);
2632  {"editor.terrain_special"}, true);
2633  assign_sprite(t, t->sprites.editor.unit, {"editor.unit"}, true);
2634  assign_sprite(t, t->sprites.editor.city, {"editor.city"}, true);
2635  assign_sprite(t, t->sprites.editor.vision, {"editor.vision"}, true);
2636  assign_sprite(t, t->sprites.editor.territory, {"editor.territory"}, true);
2637  assign_sprite(t, t->sprites.editor.properties, {"editor.properties"},
2638  true);
2639  assign_sprite(t, t->sprites.editor.road, {"editor.road"}, true);
2640  assign_sprite(t, t->sprites.editor.military_base, {"editor.military_base"},
2641  true);
2642 
2643  // Must have at least one upkeep sprite per output type (and unhappy)
2644  // The rest are optional.
2645  buffer = QStringLiteral("upkeep.unhappy");
2646  t->sprites.upkeep.unhappy.push_back(load_sprite(t, buffer));
2647  if (!t->sprites.upkeep.unhappy.back()) {
2648  tileset_error(t, LOG_FATAL, "Missing sprite upkeep.unhappy");
2649  }
2650  // Start from "upkeep.unhappy2"; there is no "upkeep.unhappy1"
2651  for (i = 2;; i++) {
2652  buffer = QStringLiteral("upkeep.unhappy%1").arg(QString::number(i));
2653  auto sprite = load_sprite(t, buffer);
2654  if (!sprite) {
2655  break;
2656  }
2657  t->sprites.upkeep.unhappy.push_back(sprite);
2658  }
2660  {
2661  buffer = QStringLiteral("upkeep.%1")
2662  .arg(get_output_identifier(static_cast<Output_type_id>(o)));
2663  auto sprite = load_sprite(t, buffer);
2664  if (sprite) {
2665  t->sprites.upkeep.output[o].push_back(sprite);
2666  // Start from "upkeep.food2"; there is no "upkeep.food1"
2667  for (i = 2;; i++) {
2668  buffer =
2669  QStringLiteral("upkeep.%1%2")
2670  .arg(get_output_identifier(static_cast<Output_type_id>(o)),
2671  QString::number(i));
2672  auto sprite = load_sprite(t, buffer);
2673  if (!sprite) {
2674  break;
2675  }
2676  t->sprites.upkeep.output[o].push_back(sprite);
2677  }
2678  }
2679  }
2681 
2683 
2684  assign_sprite(t, t->sprites.user.attention, {"user.attention"}, true);
2685 
2686  // Initialize all class-based layers
2687  for (auto &layer : t->layers) {
2688  layer->load_sprites();
2689  }
2690 }
2691 
2699 {
2700  for (auto *sf : qAsConst(*t->specfiles)) {
2701  if (sf->big_sprite) {
2702  delete sf->big_sprite;
2703  sf->big_sprite = nullptr;
2704  }
2705  }
2706 }
2707 
2715 {
2718 }
2719 
2724 QPixmap *tiles_lookup_sprite_tag_alt(struct tileset *t, QtMsgType level,
2725  const char *tag, const char *alt,
2726  const char *what, const char *name,
2727  bool scale)
2728 {
2729  QPixmap *sp;
2730 
2731  // (should get sprite_hash before connection)
2732  fc_assert_ret_val_msg(nullptr != t->sprite_hash, nullptr,
2733  "attempt to lookup for %s \"%s\" before "
2734  "sprite_hash setup",
2735  what, name);
2736 
2737  sp = load_sprite(t, tag);
2738  if (sp) {
2739  return sp;
2740  }
2741 
2742  sp = load_sprite(t, alt);
2743  if (sp) {
2744  qCDebug(tileset_category,
2745  "Using alternate graphic \"%s\" "
2746  "(instead of \"%s\") for %s \"%s\".",
2747  alt, tag, what, name);
2748  return sp;
2749  }
2750 
2751  tileset_error(
2752  t, level,
2753  _("Don't have graphics tags \"%s\" or \"%s\" for %s \"%s\"."), tag,
2754  alt, what, name);
2755 
2756  return nullptr;
2757 }
2758 
2763 static bool tileset_setup_unit_direction(struct tileset *t, int uidx,
2764  const char *base_str,
2765  enum direction8 dir, bool has_icon)
2766 {
2767  QString buf;
2768  enum direction8 loaddir = dir;
2769 
2770  /*
2771  * There may be more orientations available in this tileset than are
2772  * needed, if an oriented unit set has been re-used between tilesets.
2773  *
2774  * Don't bother loading unused ones, unless they might be used by
2775  * unit_default_orientation (logic here mirrors get_unittype_sprite()).
2776  */
2777  if (!(dir == t->unit_default_orientation && !has_icon)
2778  && !is_valid_tileset_dir(t, dir)) {
2779  /* Instead we copy a nearby valid dir's sprite, so we're not caught
2780  * out in case this tileset is used with an incompatible topology,
2781  * although it'll be ugly. */
2782  do {
2783  loaddir = dir_cw(loaddir);
2784  // This loop _should_ terminate...
2785  fc_assert_ret_val(loaddir != dir, false);
2786  } while (!is_valid_tileset_dir(t, loaddir));
2787  }
2788 
2789  buf = QStringLiteral("%1_%2").arg(base_str, dir_get_tileset_name(loaddir));
2790 
2791  /* We don't use _alt graphics here, as that could lead to loading
2792  * real icon gfx, but alternative orientation gfx. Tileset author
2793  * probably meant icon gfx to be used as fallback for all orientations */
2794  auto sprite = load_sprite(t, buf);
2795  if (!sprite) {
2796  return false;
2797  }
2798 
2799  t->sprites.units.facing[uidx][dir] =
2800  std::make_unique<freeciv::colorizer>(*sprite, t->replaced_hue);
2801  return true;
2802 }
2803 
2807 static bool tileset_setup_unit_type_from_tag(struct tileset *t, int uidx,
2808  const char *tag)
2809 {
2810  bool has_icon, facing_sprites = true;
2811 
2812  auto icon = load_sprite(t, tag);
2813  has_icon = icon != nullptr;
2814  if (has_icon) {
2815  t->sprites.units.icon[uidx] =
2816  std::make_unique<freeciv::colorizer>(*icon, t->replaced_hue);
2817  }
2818 
2819 #define LOAD_FACING_SPRITE(dir) \
2820  if (!tileset_setup_unit_direction(t, uidx, tag, dir, has_icon)) { \
2821  facing_sprites = false; \
2822  }
2823 
2824  LOAD_FACING_SPRITE(DIR8_NORTHWEST);
2825  LOAD_FACING_SPRITE(DIR8_NORTH);
2826  LOAD_FACING_SPRITE(DIR8_NORTHEAST);
2827  LOAD_FACING_SPRITE(DIR8_WEST);
2828  LOAD_FACING_SPRITE(DIR8_EAST);
2829  LOAD_FACING_SPRITE(DIR8_SOUTHWEST);
2830  LOAD_FACING_SPRITE(DIR8_SOUTH);
2831  LOAD_FACING_SPRITE(DIR8_SOUTHEAST);
2832 
2833  if (!has_icon && !facing_sprites) {
2834  // Neither icon gfx or orientation sprites
2835  return false;
2836  }
2837 
2838  return true;
2839 
2840 #undef LOAD_FACING_SPRITE
2841 }
2842 
2847 void tileset_setup_unit_type(struct tileset *t, struct unit_type *ut)
2848 {
2849  int uidx = utype_index(ut);
2850 
2852  && !tileset_setup_unit_type_from_tag(t, uidx, ut->graphic_alt)) {
2854  _("Missing %s unit sprite for tags \"%s\" and "
2855  "alternative \"%s\"."),
2856  utype_rule_name(ut), ut->graphic_str, ut->graphic_alt);
2857  }
2858 
2859  if (!t->sprites.units.icon[uidx]) {
2860  if (!direction8_is_valid(t->unit_default_orientation)) {
2862  "Unit type %s has no unoriented sprite and "
2863  "tileset has no unit_default_orientation.",
2864  utype_rule_name(ut));
2865  } else {
2866  /* We're guaranteed to have an oriented sprite corresponding to
2867  * unit_default_orientation, because
2868  * tileset_setup_unit_type_from_tag() checked for this. */
2870  != nullptr);
2871  }
2872  }
2873 }
2874 
2879 void tileset_setup_impr_type(struct tileset *t, struct impr_type *pimprove)
2880 {
2881  t->sprites.building[improvement_index(pimprove)] =
2883  pimprove->graphic_alt, "improvement",
2884  improvement_rule_name(pimprove), false);
2885 
2886  if (!t->sprites.building[improvement_index(pimprove)]) {
2888  }
2889 }
2890 
2895 void tileset_setup_tech_type(struct tileset *t, struct advance *padvance)
2896 {
2897  if (valid_advance(padvance)) {
2899  t, LOG_VERBOSE, padvance->graphic_str, padvance->graphic_alt,
2900  "technology", advance_rule_name(padvance), false);
2901 
2902  if (!t->sprites.tech[advance_index(padvance)]) {
2903  t->sprites.tech[advance_index(padvance)] = make_error_pixmap();
2904  }
2905  } else {
2906  t->sprites.tech[advance_index(padvance)] = nullptr;
2907  }
2908 }
2909 
2914 QStringList make_tag_terrain_list(const QString &prefix,
2915  const QString &suffix,
2916  const struct terrain *pterrain)
2917 {
2918  if (!strlen(pterrain->graphic_alt)
2919  || pterrain->graphic_alt == QStringLiteral("-")) {
2920  return {
2921  QStringLiteral("%1_%2%3").arg(prefix, pterrain->graphic_str, suffix),
2922  QStringLiteral("%1%2").arg(prefix, suffix),
2923  };
2924  } else {
2925  return {
2926  QStringLiteral("%1_%2%3").arg(prefix, pterrain->graphic_str, suffix),
2927  QStringLiteral("%1_%2%3").arg(prefix, pterrain->graphic_alt, suffix),
2928  QStringLiteral("%1%2").arg(prefix, suffix),
2929  };
2930  }
2931 }
2932 
2937 void tileset_setup_extra(struct tileset *t, struct extra_type *pextra)
2938 {
2939  const int id = extra_index(pextra);
2940 
2941  if (!fc_strcasecmp(pextra->graphic_str, "none")) {
2942  // Extra without graphics; nothing to do
2943  } else {
2944  const char *tag;
2945 
2946  tag = pextra->graphic_str;
2947  if (!t->estyle_hash->contains(tag)) {
2948  tag = pextra->graphic_alt;
2949  if (!t->estyle_hash->contains(tag)) {
2951  _("No extra style for \"%s\" or \"%s\"."),
2952  pextra->graphic_str, pextra->graphic_alt);
2953  } else {
2954  qCDebug(tileset_category,
2955  "Using alternate graphic \"%s\" "
2956  "(instead of \"%s\") for extra \"%s\".",
2957  pextra->graphic_alt, pextra->graphic_str,
2958  extra_rule_name(pextra));
2959  }
2960  }
2961  auto extrastyle = t->estyle_hash->value(tag);
2962 
2963  // Also init modern class-based layers
2964  for (auto &layer : t->layers) {
2965  layer->initialize_extra(pextra, tag, extrastyle);
2966  }
2967  }
2968 
2969  if (!fc_strcasecmp(pextra->activity_gfx, "none")) {
2970  t->sprites.extras[id].activity = nullptr;
2971  } else {
2972  QStringList tags = {
2973  pextra->activity_gfx,
2974  pextra->act_gfx_alt,
2975  pextra->act_gfx_alt2,
2976  };
2977  assign_sprite(t, t->sprites.extras[id].activity, tags, true);
2978  }
2979 
2980  if (!fc_strcasecmp(pextra->rmact_gfx, "none")) {
2981  t->sprites.extras[id].rmact = nullptr;
2982  } else {
2983  QStringList tags = {
2984  pextra->rmact_gfx,
2985  pextra->rmact_gfx_alt,
2986  };
2987  assign_sprite(t, t->sprites.extras[id].rmact, tags, true);
2988  }
2989 }
2990 
2996  const struct terrain *pterrain)
2997 {
2998  for (auto &layer : t->layers) {
2999  layer->initialize_terrain(pterrain);
3000  }
3001 }
3002 
3007 void tileset_setup_government(struct tileset *t, struct government *gov)
3008 {
3010  t, LOG_FATAL, gov->graphic_str, gov->graphic_alt, "government",
3011  government_rule_name(gov), false);
3012 
3013  // should probably do something if nullptr, eg generic default?
3014 }
3015 
3020 void tileset_setup_nation_flag(struct tileset *t, struct nation_type *nation)
3021 {
3022  const char *tags[] = {nation->flag_graphic_str, nation->flag_graphic_alt,
3023  "unknown", nullptr};
3024  int i;
3025  QPixmap *flag = nullptr, *shield = nullptr;
3026  QString buf;
3027 
3028  for (i = 0; tags[i] && !flag; i++) {
3029  buf = QStringLiteral("f.%1").arg(tags[i]);
3030  flag = load_sprite(t, buf);
3031  }
3032  for (i = 0; tags[i] && !shield; i++) {
3033  buf = QStringLiteral("f.shield.%1").arg(tags[i]);
3034  shield = load_sprite(t, buf);
3035  }
3036  if (!flag || !shield) {
3037  // Should never get here because of the f.unknown fallback.
3038  tileset_error(t, LOG_FATAL, _("Nation %s: no national flag."),
3039  nation_rule_name(nation));
3040  }
3041 
3042  t->sprites.nation_flag.resize(game.control.nation_count);
3043  t->sprites.nation_flag[nation_index(nation)] = flag;
3044 
3045  t->sprites.nation_shield.resize(game.control.nation_count);
3046  t->sprites.nation_shield[nation_index(nation)] = shield;
3047 }
3048 
3052 const QPixmap *get_city_flag_sprite(const struct tileset *t,
3053  const struct city *pcity)
3054 {
3055  return get_nation_flag_sprite(t, nation_of_city(pcity));
3056 }
3057 
3061 QPixmap *get_unit_nation_flag_sprite(const struct tileset *t,
3062  const struct unit *punit)
3063 {
3064  struct nation_type *pnation = nation_of_unit(punit);
3065 
3067  return t->sprites.nation_shield[nation_index(pnation)];
3068  } else {
3069  return t->sprites.nation_flag[nation_index(pnation)];
3070  }
3071 }
3072 
3080 void build_tile_data(const struct tile *ptile, struct terrain *pterrain,
3081  struct terrain **tterrain_near, bv_extras *textras_near)
3082 {
3083  int dir;
3084 
3085  // Loop over all adjacent tiles. We should have an iterator for this.
3086  for (dir = 0; dir < 8; dir++) {
3087  struct tile *tile1 =
3088  mapstep(&(wld.map), ptile, static_cast<direction8>(dir));
3089 
3090  if (tile1 && client_tile_get_known(tile1) != TILE_UNKNOWN) {
3091  struct terrain *terrain1 = tile_terrain(tile1);
3092 
3093  if (nullptr != terrain1) {
3094  tterrain_near[dir] = terrain1;
3095  textras_near[dir] = *tile_extras(tile1);
3096  continue;
3097  }
3098  qCCritical(tileset_category,
3099  "build_tile_data() tile (%d,%d) has no terrain!",
3100  TILE_XY(tile1));
3101  }
3102  /* At the edges of the (known) map, pretend the same terrain continued
3103  * past the edge of the map. */
3104  tterrain_near[dir] = pterrain;
3105  BV_CLR_ALL(textras_near[dir]);
3106  }
3107 }
3108 
3116 bool unit_drawn_with_city_outline(const struct unit *punit, bool check_focus)
3117 {
3118  /* Display an outline for city-builder type units if they are selected,
3119  * and on a tile where a city can be built.
3120  * But suppress the outline if the unit has orders (likely it is in
3121  * transit to somewhere else and this will just slow down redraws). */
3123  && !unit_has_orders(punit)
3125  && city_can_be_built_here(unit_tile(punit), punit))
3126  && (!check_focus || unit_is_in_focus(punit));
3127 }
3128 
3134 {
3135  bool no_disable = true; // Draw if matches no cause
3136 
3137  if (is_extra_caused_by(pextra, EC_IRRIGATION)) {
3139  return true;
3140  }
3141  no_disable = false;
3142  }
3143  if (is_extra_caused_by(pextra, EC_POLLUTION)
3144  || is_extra_caused_by(pextra, EC_FALLOUT)) {
3145  if (gui_options->draw_pollution) {
3146  return true;
3147  }
3148  no_disable = false;
3149  }
3150  if (is_extra_caused_by(pextra, EC_MINE)) {
3151  if (gui_options->draw_mines) {
3152  return true;
3153  }
3154  no_disable = false;
3155  }
3156  if (is_extra_caused_by(pextra, EC_RESOURCE)) {
3157  if (gui_options->draw_specials) {
3158  return true;
3159  }
3160  no_disable = false;
3161  }
3162  if (is_extra_removed_by(pextra, ERM_ENTER)) {
3163  if (gui_options->draw_huts) {
3164  return true;
3165  }
3166  no_disable = false;
3167  }
3168  if (is_extra_caused_by(pextra, EC_BASE)) {
3170  return true;
3171  }
3172  no_disable = false;
3173  }
3174  if (is_extra_caused_by(pextra, EC_ROAD)) {
3176  return true;
3177  }
3178  no_disable = false;
3179  }
3180 
3181  return no_disable;
3182 }
3183 
3188 void tileset_setup_city_tiles(struct tileset *t, int style)
3189 {
3190  for (auto &&layer : t->layers) {
3191  layer->initialize_city_style(city_styles[style], style);
3192  }
3193 }
3194 
3201 {
3202  if (t->focus_units_layer->focus_unit_state_count() == 0) {
3203  return 100;
3204  } else {
3205  return t->select_step_ms;
3206  }
3207 }
3208 
3214 {
3216 }
3217 
3222 {
3223  if (t->focus_units_layer->focus_unit_state_count() == 0) {
3225  }
3226 }
3227 
3233 {
3235  if (t->focus_units_layer->focus_unit_state_count() == 0) {
3237  } else {
3240  }
3241 }
3242 
3246 struct unit *get_drawable_unit(const struct tileset *t, const ::tile *ptile)
3247 {
3248  struct unit *punit = find_visible_unit(ptile);
3249 
3250  if (punit == nullptr) {
3251  return nullptr;
3252  }
3253 
3254  if (!unit_is_in_focus(punit)
3256  || t->focus_units_layer->focus_unit_state() == 0) {
3257  return punit;
3258  } else {
3259  return nullptr;
3260  }
3261 }
3262 
3267 static void unload_all_sprites(struct tileset *t)
3268 {
3269  if (t->sprite_hash) {
3270  QHash<QString, small_sprite *>::const_iterator i =
3271  t->sprite_hash->constBegin();
3272  while (i != t->sprite_hash->constEnd()) {
3273  QByteArray qba = i.key().toLocal8Bit();
3274  while (i.value()->ref_count > 0) {
3275  unload_sprite(t, qba.data());
3276  }
3277  i++;
3278  }
3279  }
3280 }
3281 
3286 {
3287  log_debug("tileset_free_tiles()");
3288 
3289  unload_all_sprites(t);
3290 
3291  if (t->sprite_hash) {
3292  delete t->sprite_hash;
3293  t->sprite_hash = nullptr;
3294  }
3295 
3296  for (auto *ss : qAsConst(*t->small_sprites)) {
3297  if (ss->file) {
3298  delete[] ss->file;
3299  }
3300  fc_assert(ss->sprite == nullptr);
3301  delete ss;
3302  }
3303  t->small_sprites->clear();
3304 
3305  for (auto *sf : qAsConst(*t->specfiles)) {
3306  delete[] sf->file_name;
3307  if (sf->big_sprite) {
3308  delete sf->big_sprite;
3309  sf->big_sprite = nullptr;
3310  }
3311  delete sf;
3312  }
3313  t->specfiles->clear();
3314 
3315  t->sprites.explode.unit.clear();
3316  t->sprites.nation_flag.clear();
3317  t->sprites.nation_shield.clear();
3318  t->sprites.citybar.occupancy.clear();
3319 }
3320 
3324 const QPixmap *get_spaceship_sprite(const struct tileset *t,
3325  enum spaceship_part part)
3326 {
3327  return t->sprites.spaceship[part];
3328 }
3329 
3337 const QPixmap *get_citizen_sprite(const struct tileset *t,
3338  enum citizen_category type,
3339  int citizen_index,
3340  const struct city *pcity)
3341 {
3342  const struct citizen_graphic *graphic;
3343  int gfx_index = citizen_index;
3344 
3345  if (pcity != nullptr) {
3346  gfx_index += pcity->client.first_citizen_index;
3347  }
3348 
3349  if (type < CITIZEN_SPECIALIST) {
3350  fc_assert(type >= 0);
3351  graphic = &t->sprites.citizen[type];
3352  } else {
3353  fc_assert(type < (CITIZEN_SPECIALIST + SP_MAX));
3354  graphic = &t->sprites.specialist[type - CITIZEN_SPECIALIST];
3355  }
3356 
3357  if (graphic->count == 0) {
3358  return nullptr;
3359  }
3360 
3361  return graphic->sprite[gfx_index % graphic->count];
3362 }
3363 
3367 const QPixmap *get_nation_flag_sprite(const struct tileset *t,
3368  const struct nation_type *pnation)
3369 {
3370  return t->sprites.nation_flag[nation_index(pnation)];
3371 }
3372 
3376 const QPixmap *get_nation_shield_sprite(const struct tileset *t,
3377  const struct nation_type *pnation)
3378 {
3379  return t->sprites.nation_shield[nation_index(pnation)];
3380 }
3381 
3385 const QPixmap *get_tech_sprite(const struct tileset *t, Tech_type_id tech)
3386 {
3387  fc_assert_ret_val(0 <= tech && tech < advance_count(), nullptr);
3388  return t->sprites.tech[tech];
3389 }
3390 
3394 const QPixmap *get_building_sprite(const struct tileset *t,
3395  const struct impr_type *pimprove)
3396 {
3397  fc_assert_ret_val(nullptr != pimprove, nullptr);
3398  return t->sprites.building[improvement_index(pimprove)];
3399 }
3400 
3404 const QPixmap *get_government_sprite(const struct tileset *t,
3405  const struct government *gov)
3406 {
3407  fc_assert_ret_val(nullptr != gov, nullptr);
3408  return t->sprites.government[government_index(gov)];
3409 }
3410 
3416 const QPixmap *get_unittype_sprite(const struct tileset *t,
3417  const struct unit_type *punittype,
3418  enum direction8 facing,
3419  const QColor &replace)
3420 {
3421  int uidx = utype_index(punittype);
3422  bool icon = !direction8_is_valid(facing);
3423 
3424  fc_assert_ret_val(nullptr != punittype, nullptr);
3425 
3426  if (!direction8_is_valid(facing) || !is_valid_dir(facing)) {
3427  facing = t->unit_default_orientation;
3428  /* May not have been specified, but it only matters if we don't
3429  * turn out to have an icon sprite */
3430  }
3431 
3432  if (t->sprites.units.icon[uidx]
3433  && (icon || t->sprites.units.facing[uidx][facing] == nullptr)) {
3434  // Has icon sprite, and we prefer to (or must) use it
3435  return t->sprites.units.icon[uidx]->pixmap(replace);
3436  } else {
3437  /* We should have a valid orientation by now. Failure to have either
3438  * an icon sprite or default orientation should have been caught at
3439  * tileset load. */
3440  fc_assert_ret_val(direction8_is_valid(facing), nullptr);
3441  return t->sprites.units.facing[uidx][facing]->pixmap(replace);
3442  }
3443 }
3444 
3448 const QPixmap *get_tax_sprite(const struct tileset *t, Output_type_id otype)
3449 {
3450  switch (otype) {
3451  case O_SCIENCE:
3452  return t->sprites.tax_science;
3453  case O_GOLD:
3454  return t->sprites.tax_gold;
3455  case O_LUXURY:
3456  return t->sprites.tax_luxury;
3457  case O_TRADE:
3458  case O_FOOD:
3459  case O_SHIELD:
3460  case O_LAST:
3461  break;
3462  }
3463  return nullptr;
3464 }
3465 
3469 const QPixmap *get_event_sprite(const struct tileset *t,
3470  enum event_type event)
3471 {
3472  return t->sprites.events[event];
3473 }
3474 
3478 const QPixmap *get_dither_sprite(const struct tileset *t)
3479 {
3480  return t->sprites.dither_tile;
3481 }
3482 
3486 const QPixmap *get_mask_sprite(const struct tileset *t)
3487 {
3488  return t->sprites.mask.tile;
3489 }
3490 
3495 const QPixmap *get_treaty_thumb_sprite(const struct tileset *t, bool on_off)
3496 {
3497  return t->sprites.treaty_thumb[on_off ? 1 : 0];
3498 }
3499 
3504 const std::vector<QPixmap *> &
3506 {
3507  return t->sprites.explode.unit;
3508 }
3509 
3515 const QPixmap *get_nuke_explode_sprite(const struct tileset *t)
3516 {
3517  return t->sprites.explode.nuke;
3518 }
3519 
3523 const struct citybar_sprites *get_citybar_sprites(const struct tileset *t)
3524 {
3525  return &t->sprites.citybar;
3526 }
3527 
3531 const struct editor_sprites *get_editor_sprites(const struct tileset *t)
3532 {
3533  return &t->sprites.editor;
3534 }
3535 
3542 const QPixmap *get_cursor_sprite(const struct tileset *t,
3543  enum cursor_type cursor, int *hot_x,
3544  int *hot_y, int frame)
3545 {
3546  *hot_x = t->sprites.cursor[cursor].hot_x;
3547  *hot_y = t->sprites.cursor[cursor].hot_y;
3548  return t->sprites.cursor[cursor].frame[frame];
3549 }
3550 
3557 const QPixmap *get_attention_crosshair_sprite(const struct tileset *t)
3558 {
3559  return t->sprites.user.attention;
3560 }
3561 
3566 const QPixmap *get_indicator_sprite(const struct tileset *t,
3567  enum indicator_type indicator, int idx)
3568 {
3569  idx = CLIP(0, idx, NUM_TILES_PROGRESS - 1);
3570 
3571  fc_assert_ret_val(indicator >= 0 && indicator < INDICATOR_COUNT, nullptr);
3572 
3573  return t->sprites.indicator[indicator][idx];
3574 }
3575 
3582 const QPixmap *get_unit_unhappy_sprite(const struct tileset *t,
3583  const struct unit *punit,
3584  int happy_cost)
3585 {
3586  Q_UNUSED(punit)
3587  const int unhappy =
3588  CLIP(0, happy_cost, t->sprites.upkeep.unhappy.size() - 1);
3589 
3590  if (unhappy > 0) {
3591  return t->sprites.upkeep.unhappy[unhappy - 1];
3592  } else {
3593  return nullptr;
3594  }
3595 }
3596 
3603 const QPixmap *get_unit_upkeep_sprite(const struct tileset *t,
3604  Output_type_id otype,
3605  const struct unit *punit,
3606  const int *upkeep_cost)
3607 {
3608  Q_UNUSED(punit)
3609  const int upkeep =
3610  CLIP(0, upkeep_cost[otype], t->sprites.upkeep.output[otype].size());
3611 
3612  if (upkeep > 0) {
3613  return t->sprites.upkeep.output[otype][upkeep - 1];
3614  } else {
3615  return nullptr;
3616  }
3617 }
3618 
3622 struct color_system *get_color_system(const struct tileset *t)
3623 {
3624  return t->color_system;
3625 }
3626 
3630 void tileset_init(struct tileset *t) { t->max_upkeep_height = 0; }
3631 
3641 std::vector<drawn_sprite>
3643  struct terrain *pterrain)
3644 {
3645  // We create a virtual tile with only the requested terrain, then collect
3646  // sprites from every layer.
3647  auto tile = tile_virtual_new(nullptr);
3649  tile->terrain = pterrain;
3650 
3651  auto sprs = std::vector<drawn_sprite>();
3652  for (const auto &layer : t->layers) {
3653  const auto lsprs =
3654  layer->fill_sprite_array(tile, nullptr, nullptr, nullptr);
3655  sprs.insert(sprs.end(), lsprs.begin(), lsprs.end());
3656  }
3657 
3659  return sprs;
3660 }
3661 
3666 {
3667  for (const auto &layer : t->layers) {
3668  if (auto lc = dynamic_cast<const freeciv::layer_city *>(layer.get())) {
3669  return lc;
3670  }
3671  }
3672  fc_assert_ret_val(false, nullptr);
3673 }
3674 
3678 std::vector<drawn_sprite>
3680  const struct extra_type *pextra)
3681 {
3682  // We create a virtual tile with only the requested extra, then collect
3683  // sprites from every layer.
3684  auto tile = tile_virtual_new(nullptr);
3686  BV_SET(tile->extras, pextra->id);
3687 
3688  auto sprs = std::vector<drawn_sprite>();
3689  for (const auto &layer : t->layers) {
3690  const auto lsprs =
3691  layer->fill_sprite_array(tile, nullptr, nullptr, nullptr);
3692  sprs.insert(sprs.end(), lsprs.begin(), lsprs.end());
3693  }
3694 
3696  return sprs;
3697 }
3698 
3699 const std::vector<std::unique_ptr<freeciv::layer>> &
3700 tileset_get_layers(const struct tileset *t)
3701 {
3702  return t->layers;
3703 }
3704 
3708 void tileset_player_init(struct tileset *t, struct player *pplayer)
3709 {
3710  fc_assert_ret(pplayer != nullptr);
3711 
3712  auto plrid = player_index(pplayer);
3713  fc_assert_ret(plrid >= 0);
3715 
3716  // Free all data before recreating it.
3717  tileset_player_free(t, plrid);
3718 
3719  for (auto &&layer : t->layers) {
3720  layer->initialize_player(pplayer);
3721  }
3722 }
3723 
3727 static void tileset_player_free(struct tileset *t, int plrid)
3728 {
3729  fc_assert_ret(plrid >= 0);
3731 
3732  for (auto &&layer : t->layers) {
3733  layer->free_player(plrid);
3734  }
3735 }
3736 
3741 {
3742  for (auto &layer : t->layers) {
3743  layer->reset_ruleset();
3744  }
3745 }
3746 
3751 
3755 std::vector<tileset_log_entry> tileset_log(const struct tileset *t)
3756 {
3757  return t->log;
3758 }
3759 
3763 bool tileset_has_error(const struct tileset *t)
3764 {
3765  return std::any_of(t->log.begin(), t->log.end(),
3766  [](auto &entry) { return entry.level == LOG_ERROR; });
3767 }
3768 
3772 bool tileset_has_options(const struct tileset *t)
3773 {
3774  return !t->options.empty();
3775 }
3776 
3780 bool tileset_has_option(const struct tileset *t, const QString &option)
3781 {
3782  return t->options.count(option);
3783 }
3784 
3788 std::map<QString, tileset_option>
3790 {
3791  return t->options;
3792 }
3793 
3799 bool tileset_option_is_enabled(const struct tileset *t, const QString &name)
3800 {
3801  return t->options.at(name).enabled;
3802 }
3803 
3812 bool tileset_set_option(struct tileset *t, const QString &name, bool enabled)
3813 {
3814  auto it = t->options.find(name);
3815  fc_assert_ret_val(it != t->options.end(), false);
3816 
3817  if (it->second.enabled != enabled) {
3818  // Change the value in the client settings
3821  }
3822  return true;
3823 }
3824 
3828 const char *tileset_name_get(const struct tileset *t)
3829 {
3830  return t->given_name;
3831 }
3832 
3836 const char *tileset_version(const struct tileset *t) { return t->version; }
3837 
3841 const char *tileset_summary(const struct tileset *t) { return t->summary; }
3842 
3846 const char *tileset_description(const struct tileset *t)
3847 {
3848  return t->description;
3849 }
3850 
3854 int tileset_topo_index(const struct tileset *t) { return t->ts_topo_idx; }
3855 
3859 help_item *tileset_help(const struct tileset *t)
3860 {
3861  if (t == nullptr) {
3862  return nullptr;
3863  }
3864 
3865  int desc_len;
3866  int len;
3867 
3868  const char *ts_name = tileset_name_get(t);
3869  const char *version = tileset_version(t);
3870  const char *summary = tileset_summary(t);
3871  const char *description = tileset_description(t);
3872 
3873  auto pitem = new_help_item(HELP_TILESET);
3874  if (description != nullptr) {
3875  desc_len = qstrlen("\n\n") + qstrlen(description);
3876  } else {
3877  desc_len = 0;
3878  }
3879  if (summary != nullptr) {
3880  if (version[0] != '\0') {
3881  len = qstrlen(_(ts_name)) + qstrlen(" ") + qstrlen(version)
3882  + qstrlen("\n\n") + qstrlen(_(summary)) + 1;
3883 
3884  pitem->text = new char[len + desc_len];
3885  fc_snprintf(pitem->text, len, "%s %s\n\n%s", _(ts_name), version,
3886  _(summary));
3887  } else {
3888  len = qstrlen(_(ts_name)) + qstrlen("\n\n") + qstrlen(_(summary)) + 1;
3889 
3890  pitem->text = new char[len + desc_len];
3891  fc_snprintf(pitem->text, len, "%s\n\n%s", _(ts_name), _(summary));
3892  }
3893  } else {
3894  const char *nodesc = _("Current tileset contains no summary.");
3895 
3896  if (version[0] != '\0') {
3897  len = qstrlen(_(ts_name)) + qstrlen(" ") + qstrlen(version)
3898  + qstrlen("\n\n") + qstrlen(nodesc) + 1;
3899 
3900  pitem->text = new char[len + desc_len];
3901  fc_snprintf(pitem->text, len, "%s %s\n\n%s", _(ts_name), version,
3902  nodesc);
3903  } else {
3904  len = qstrlen(_(ts_name)) + qstrlen("\n\n") + qstrlen(nodesc) + 1;
3905 
3906  pitem->text = new char[len + desc_len];
3907  fc_snprintf(pitem->text, len, "%s\n\n%s", _(ts_name), nodesc);
3908  }
3909  }
3910  if (description != nullptr) {
3911  fc_strlcat(pitem->text, "\n\n", len + desc_len);
3912  fc_strlcat(pitem->text, description, len + desc_len);
3913  }
3914  return pitem;
3915 }
QString strvec_to_or_list(const QVector< QString > &psv)
Definition: astring.cpp:20
#define BV_CLR_ALL(bv)
Definition: bitvector.h:62
#define BV_SET(bv, bit)
Definition: bitvector.h:44
QPixmap crop_sprite(const QPixmap *sprite)
Helper function to crop a sprite.
Definition: canvas.cpp:115
bool has_capabilities(const char *us, const char *them)
This routine returns true if all the mandatory capabilities in us appear in them.
Definition: capability.cpp:80
struct citystyle * city_styles
Definition: city.cpp:78
bool city_can_be_built_here(const struct tile *ptile, const struct unit *punit)
Returns TRUE if the given unit can build a city at the given map coordinates.
Definition: city.cpp:1423
const char * get_output_identifier(Output_type_id output)
Return an id string for the output type.
Definition: city.cpp:592
citizen_category
Definition: city.h:239
@ CITIZEN_LAST
Definition: city.h:244
@ CITIZEN_SPECIALIST
Definition: city.h:245
@ CITIZEN_ANGRY
Definition: city.h:243
@ CITIZEN_HAPPY
Definition: city.h:240
@ CITIZEN_CONTENT
Definition: city.h:241
@ CITIZEN_UNHAPPY
Definition: city.h:242
#define output_type_iterate(output)
Definition: city.h:764
#define output_type_iterate_end
Definition: city.h:771
void generate_citydlg_dimensions()
Calculate the citydlg width and height.
sprite_type
Indicates how many sprites are used to draw a tile.
Definition: layer_terrain.h:30
@ CELL_WHOLE
One sprite for the entire tile.
Definition: layer_terrain.h:31
@ CELL_HEX_CORNER
One sprite for each hexagonal corner of the tile.
Definition: layer_terrain.h:33
@ CELL_CORNER
One sprite for each corner of the tile.
Definition: layer_terrain.h:32
Draws units on the map.
Definition: layer_units.h:17
int focus_unit_state() const
Returns the current state of the focused unit animation.
Definition: layer_units.h:44
auto focus_unit_state_count() const
Returns the number of steps in the focused unit animation.
Definition: layer_units.h:39
void center_on_tile(tile *tile, bool animate=true)
Centers the view on a tile.
Definition: view_map.cpp:197
map_view * mapview_wdg
Definition: page_game.h:81
enum client_states client_state()
Return current client state.
struct civclient client
client_states
Definition: client_main.h:39
@ C_S_RUNNING
Definition: client_main.h:43
@ C_S_OVER
Definition: client_main.h:44
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
struct nation_set * client_current_nation_set()
Returns the nation set in use.
Definition: climisc.cpp:1190
void color_system_free(struct color_system *colors)
Called when the client first starts to free any allocated colors.
struct color_system * color_system_read(struct section_file *file)
Called when the client first starts to allocate the default colors.
bool unit_is_in_focus(const struct unit *punit)
Return TRUE iff this unit is in focus.
Definition: control.cpp:364
unit * find_visible_unit(const ::tile *ptile)
Return a pointer to a visible unit, if there is one.
Definition: control.cpp:749
enum event_type event
Definition: events.cpp:68
const char * get_event_tag(enum event_type event)
Returns a string for the sound to be used for this message type.
Definition: events.cpp:268
char * tag_name
Definition: events.cpp:64
bool is_extra_removed_by(const struct extra_type *pextra, enum extra_rmcause rmcause)
Is given cause one of the removal causes for the given extra?
Definition: extras.cpp:307
const char * extra_rule_name(const struct extra_type *pextra)
Return the (untranslated) rule name of the extra type.
Definition: extras.cpp:174
#define extra_type_iterate(_p)
Definition: extras.h:279
#define extra_type_iterate_end
Definition: extras.h:285
#define is_extra_caused_by(e, c)
Definition: extras.h:182
#define extra_index(_e_)
Definition: extras.h:163
#define DIR8_MAGIC_MAX
Definition: fc_types.h:386
int Tech_type_id
Definition: fc_types.h:294
#define SP_MAX
Definition: fc_types.h:324
int Specialist_type_id
Definition: fc_types.h:292
#define MAX_NUM_PLAYER_SLOTS
Definition: fc_types.h:24
#define MAX_EXTRA_TYPES
Definition: fc_types.h:42
#define MAX_LEN_NAME
Definition: fc_types.h:61
@ O_SHIELD
Definition: fc_types.h:86
@ O_FOOD
Definition: fc_types.h:85
@ O_TRADE
Definition: fc_types.h:87
@ O_SCIENCE
Definition: fc_types.h:90
@ O_LUXURY
Definition: fc_types.h:89
@ O_GOLD
Definition: fc_types.h:88
@ O_LAST
Definition: fc_types.h:91
enum output_type_id Output_type_id
Definition: fc_types.h:295
#define _(String)
Definition: fcintl.h:50
struct civ_game game
Definition: game.cpp:47
struct world wld
Definition: game.cpp:48
const char * government_rule_name(const struct government *pgovern)
Return the (untranslated) rule name of the government.
Definition: government.cpp:126
std::vector< government > governments
Definition: government.cpp:28
Government_type_id government_index(const struct government *pgovern)
Return the government index.
Definition: government.cpp:75
#define G_LAST
Definition: government.h:31
struct help_item * new_help_item(help_page_type type)
Allocate and initialize new help item.
Definition: helpdata.cpp:656
void boot_help_texts(const nation_set *nations_to_show, help_item *tileset_help)
pplayer may be nullptr.
Definition: helpdata.cpp:682
@ HELP_TILESET
Definition: helpdata.h:33
void popdown_help_dialog(void)
Close the help dialog.
Definition: helpdlg.cpp:75
const char * improvement_rule_name(const struct impr_type *pimprove)
Return the (untranslated) rule name of the improvement.
Impr_type_id improvement_index(const struct impr_type *pimprove)
Return the improvement index.
#define improvement_iterate_end
Definition: improvement.h:199
#define improvement_iterate(_p)
Definition: improvement.h:193
#define B_LAST
Definition: improvement.h:33
const char * name
Definition: inputfile.cpp:118
#define NUM_TILES_DIGITS
Definition: layer.h:78
@ EDGE_COUNT
Definition: layer.h:36
constexpr auto LOG_DEBUG
Definition: log.h:27
#define fc_assert_ret(condition)
Definition: log.h:112
constexpr auto LOG_ERROR
Definition: log.h:23
#define fc_assert_exit_msg(condition, message,...)
Definition: log.h:135
constexpr auto LOG_VERBOSE
Definition: log.h:26
#define fc_assert(condition)
Definition: log.h:89
constexpr auto LOG_NORMAL
Definition: log.h:25
#define fc_assert_ret_val(condition, val)
Definition: log.h:114
#define fc_assert_action(condition, action)
Definition: log.h:104
#define log_debug(message,...)
Definition: log.h:65
#define log_base(level, message,...)
Definition: log.h:41
constexpr auto LOG_FATAL
Definition: log.h:22
#define fc_assert_ret_val_msg(condition, val, message,...)
Definition: log.h:132
bool is_valid_dir(enum direction8 dir)
Returns TRUE iff the given direction is a valid one.
Definition: map.cpp:1199
enum direction8 dir_cw(enum direction8 dir)
Returns the next direction clock-wise.
Definition: map.cpp:1112
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
void tileset_changed(void)
This function is called when the tileset is changed.
Definition: view_map.cpp:554
void menus_init()
struct nation_type * nation_of_city(const struct city *pcity)
Return the nation of the player who owns the city.
Definition: nation.cpp:429
const char * nation_rule_name(const struct nation_type *pnation)
Return the (untranslated) rule name of the nation (adjective form).
Definition: nation.cpp:115
std::vector< nation_type > nations
Definition: nation.cpp:38
struct nation_type * nation_of_unit(const struct unit *punit)
Return the nation of the player who owns the unit.
Definition: nation.cpp:438
Nation_type_id nation_index(const struct nation_type *pnation)
Return the nation index.
Definition: nation.cpp:464
const char * option_str_get(const struct option *poption)
Returns the current value of this string option.
Definition: options.cpp:553
client_options * gui_options
Definition: options.cpp:74
int option_get_cb_data(const struct option *poption)
Returns the callback data of this option.
Definition: options.cpp:447
int len
Definition: packhand.cpp:127
pageGame * queen()
Return game instandce.
Definition: page_game.cpp:557
int player_index(const struct player *pplayer)
Return the player index.
Definition: player.cpp:748
#define players_iterate_end
Definition: player.h:520
#define players_iterate(_pplayer)
Definition: player.h:514
struct section_file * secfile_load(const QString &filename, bool allow_duplicates)
Create a section file from a file.
Definition: registry.cpp:21
const char * secfile_error()
Returns the last error which occurred in a string.
const char * section_name(const struct section *psection)
Returns the section name.
void secfile_destroy(struct section_file *secfile)
Free a section file.
void secfile_check_unused(const struct section_file *secfile)
Print log messages for any entries in the file which have not been looked up – ie,...
bool secfile_lookup_int(const struct section_file *secfile, int *ival, const char *path,...)
Lookup a integer value in the secfile.
struct entry * secfile_entry_lookup(const struct section_file *secfile, const char *path,...)
Returns the entry at "fullpath" or nullptr if not matched.
const char * secfile_lookup_str(const struct section_file *secfile, const char *path,...)
Lookup a string value in the secfile.
const char ** secfile_lookup_str_vec(const struct section_file *secfile, size_t *dim, const char *path,...)
Lookup a string vector in the secfile.
bool secfile_lookup_bool_default(const struct section_file *secfile, bool def, const char *path,...)
Lookup a boolean value in the secfile.
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
Lookup a string value in the secfile.
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
Lookup a integer value in the secfile.
struct section_list * secfile_sections_by_name_prefix(const struct section_file *secfile, const char *prefix)
Returns the list of sections which match the name prefix.
bool secfile_lookup_bool(const struct section_file *secfile, bool *bval, const char *path,...)
Lookup a boolean value in the secfile.
int secfile_lookup_int_def_min_max(const struct section_file *secfile, int defval, int minval, int maxval, const char *path,...)
Lookup a integer value in the secfile.
#define section_list_iterate(seclist, psection)
Definition: registry_ini.h:46
#define section_list_iterate_end
Definition: registry_ini.h:48
struct setting_list * level[OLEVELS_NUM]
Definition: settings.cpp:167
const QStringList & get_data_dirs()
Returns a list of data directory paths, in the order in which they should be searched.
Definition: shared.cpp:533
QString fileinfoname(const QStringList &dirs, const QString &filename)
Returns a filename to access the specified file from a directory by searching all specified directori...
Definition: shared.cpp:661
QVector< QString > * fileinfolist(const QStringList &dirs, const char *suffix)
Returns a string vector storing the filenames in the data directories matching the given suffix.
Definition: shared.cpp:623
#define CLIP(lower, current, upper)
Definition: shared.h:51
#define ARRAY_SIZE(x)
Definition: shared.h:79
#define MAX(x, y)
Definition: shared.h:48
struct specialist * specialist_by_number(const Specialist_type_id id)
Return the specialist pointer for the given number.
Definition: specialist.cpp:92
#define specialist_type_iterate_end
Definition: specialist.h:73
#define specialist_type_iterate(sp)
Definition: specialist.h:67
QPixmap * load_gfxfile(const char *filename)
Load the given graphics file into a sprite.
Definition: sprite.cpp:25
Definition: tech.h:113
char graphic_str[MAX_LEN_NAME]
Definition: tech.h:116
char graphic_alt[MAX_LEN_NAME]
Definition: tech.h:117
QPixmap * sprite[MAX_NUM_CITIZEN_SPRITES]
Definition: tilespec.cpp:140
Definition: city.h:291
struct city::@15::@18 client
QPixmap * trade
Definition: tilespec.h:190
QPixmap * occupied
Definition: tilespec.h:190
std::vector< QPixmap * > occupancy
Definition: tilespec.h:191
QPixmap * shields
Definition: tilespec.h:190
QPixmap * food
Definition: tilespec.h:190
QPixmap * background
Definition: tilespec.h:190
struct packet_ruleset_control control
Definition: game.h:74
struct civ_game::@28::@31 client
int topology_id
Definition: map_types.h:68
struct connection conn
Definition: client_main.h:89
bool draw_specials
Definition: options.h:133
std::map< QString, std::map< QString, bool > > tileset_options
Saved tileset options.
Definition: options.h:183
bool draw_mines
Definition: options.h:131
bool draw_fortress_airbase
Definition: options.h:132
bool draw_irrigation
Definition: options.h:130
bool draw_unit_shields
Definition: options.h:142
bool draw_huts
Definition: options.h:134
bool draw_city_outlines
Definition: options.h:120
bool draw_roads_rails
Definition: options.h:129
bool draw_pollution
Definition: options.h:135
bool established
Definition: connection.h:131
QPixmap * vision
Definition: tilespec.h:196
QPixmap * terrain
Definition: tilespec.h:195
QPixmap * properties
Definition: tilespec.h:197
QPixmap * copy
Definition: tilespec.h:195
QPixmap * copypaste
Definition: tilespec.h:195
QPixmap * unit
Definition: tilespec.h:196
QPixmap * brush
Definition: tilespec.h:195
QPixmap * paste
Definition: tilespec.h:195
QPixmap * road
Definition: tilespec.h:197
QPixmap * terrain_resource
Definition: tilespec.h:196
QPixmap * startpos
Definition: tilespec.h:195
QPixmap * terrain_special
Definition: tilespec.h:196
QPixmap * city
Definition: tilespec.h:196
QPixmap * military_base
Definition: tilespec.h:197
QPixmap * territory
Definition: tilespec.h:196
QPixmap * erase
Definition: tilespec.h:195
char rmact_gfx[MAX_LEN_NAME]
Definition: extras.h:87
char act_gfx_alt[MAX_LEN_NAME]
Definition: extras.h:85
char rmact_gfx_alt[MAX_LEN_NAME]
Definition: extras.h:88
int id
Definition: extras.h:75
char graphic_alt[MAX_LEN_NAME]
Definition: extras.h:83
char activity_gfx[MAX_LEN_NAME]
Definition: extras.h:84
char act_gfx_alt2[MAX_LEN_NAME]
Definition: extras.h:86
char graphic_str[MAX_LEN_NAME]
Definition: extras.h:82
char graphic_alt[MAX_LEN_NAME]
Definition: government.h:40
char graphic_str[MAX_LEN_NAME]
Definition: government.h:39
char graphic_str[MAX_LEN_NAME]
Definition: improvement.h:64
char graphic_alt[MAX_LEN_NAME]
Definition: improvement.h:65
std::vector< QPixmap * > unit
Definition: tilespec.cpp:177
const QPixmap * government[G_LAST]
Definition: tilespec.cpp:160
QPixmap * activity
Definition: tilespec.cpp:189
struct citizen_graphic specialist[SP_MAX]
Definition: tilespec.cpp:170
QPixmap * attention
Definition: tilespec.cpp:186
struct named_sprites::@149 upkeep
QPixmap * nuke
Definition: tilespec.cpp:178
QPixmap * tax_gold
Definition: tilespec.cpp:151
const QPixmap * tech[A_LAST]
Definition: tilespec.cpp:158
struct citizen_graphic citizen[CITIZEN_LAST]
Definition: tilespec.cpp:170
QPixmap * frame[NUM_CURSOR_FRAMES]
Definition: tilespec.cpp:174
QPixmap * events[E_COUNT]
Definition: tilespec.cpp:148
std::vector< QPixmap * > nation_shield
Definition: tilespec.cpp:168
struct named_sprites::@147 cursor[CURSOR_LAST]
struct named_sprites::@151 extras[MAX_EXTRA_TYPES]
QPixmap * tile
Definition: tilespec.cpp:155
QPixmap * rmact
Definition: tilespec.cpp:189
const QPixmap * building[B_LAST]
Definition: tilespec.cpp:159
QPixmap * tax_luxury
Definition: tilespec.cpp:151
QPixmap * spaceship[SPACESHIP_COUNT]
Definition: tilespec.cpp:171
std::vector< QPixmap * > nation_flag
Definition: tilespec.cpp:167
QPixmap * borders[EDGE_COUNT][2]
Definition: tilespec.cpp:192
QPixmap * dither_tile
Definition: tilespec.cpp:152
struct citybar_sprites citybar
Definition: tilespec.cpp:183
std::vector< QPixmap * > output[O_LAST]
Definition: tilespec.cpp:181
struct named_sprites::@150 user
QPixmap * tax_science
Definition: tilespec.cpp:151
struct named_sprites::@152 grid
std::unique_ptr< freeciv::colorizer > facing[U_LAST][DIR8_MAGIC_MAX]
Definition: tilespec.cpp:164
QPixmap * treaty_thumb[2]
Definition: tilespec.cpp:145
struct named_sprites::@146 units
struct editor_sprites editor
Definition: tilespec.cpp:184
std::vector< QPixmap * > unhappy
Definition: tilespec.cpp:181
struct named_sprites::@145 mask
struct named_sprites::@148 explode
QPixmap * indicator[INDICATOR_COUNT][NUM_TILES_PROGRESS]
Definition: tilespec.cpp:144
QPixmap * arrow[ARROW_LAST]
Definition: tilespec.cpp:146
std::unique_ptr< freeciv::colorizer > icon[U_LAST]
Definition: tilespec.cpp:163
char flag_graphic_str[MAX_LEN_NAME]
Definition: nation.h:82
char flag_graphic_alt[MAX_LEN_NAME]
Definition: nation.h:83
The base class for options.
Definition: options.cpp:209
Definition: player.h:231
Information about an individual sprite.
Definition: tilespec.cpp:206
QPixmap * sprite
Definition: tilespec.cpp:219
struct specfile * sf
Definition: tilespec.cpp:213
char * file
Definition: tilespec.cpp:210
QPixmap * big_sprite
Definition: tilespec.cpp:197
char * file_name
Definition: tilespec.cpp:198
char graphic_alt[MAX_LEN_NAME]
Definition: specialist.h:30
char graphic_str[MAX_LEN_NAME]
Definition: specialist.h:29
char graphic_alt[MAX_LEN_NAME]
Definition: terrain.h:175
char graphic_str[MAX_LEN_NAME]
Definition: terrain.h:174
Definition: tile.h:42
bv_extras extras
Definition: tile.h:47
struct terrain * terrain
Definition: tile.h:49
Definition: tilespec.h:56
Tileset options allow altering the behavior of a tileset.
Definition: tilespec.h:64
char given_name[MAX_LEN_NAME]
Definition: tilespec.cpp:224
int num_cardinal_tileset_dirs
Definition: tilespec.cpp:263
std::vector< std::unique_ptr< freeciv::layer > > layers
Definition: tilespec.cpp:235
struct named_sprites sprites
Definition: tilespec.cpp:271
int ts_topo_idx
Definition: tilespec.cpp:241
int hex_height
Definition: tilespec.cpp:240
std::array< freeciv::layer_terrain *, MAX_NUM_LAYERS > terrain_layers
Definition: tilespec.cpp:236
enum ts_type type
Definition: tilespec.cpp:239
char version[MAX_LEN_NAME]
Definition: tilespec.cpp:225
freeciv::layer_units * focus_units_layer
Definition: tilespec.cpp:237
QPoint unit_offset
Definition: tilespec.cpp:253
QSize unit_tile_size
Definition: tilespec.cpp:243
QHash< QString, extrastyle_id > * estyle_hash
Definition: tilespec.cpp:270
int citybar_offset_y
Definition: tilespec.cpp:256
int hex_width
Definition: tilespec.cpp:240
int select_step_ms
Definition: tilespec.cpp:259
QSet< struct small_sprite * > * small_sprites
Definition: tilespec.cpp:267
char * description
Definition: tilespec.cpp:229
QSize full_tile_size
Definition: tilespec.cpp:243
int max_upkeep_height
Definition: tilespec.cpp:246
std::map< QString, tileset_option > options
Definition: tilespec.cpp:233
QPoint unit_flag_offset
Definition: tilespec.cpp:253
QSize small_sprite_size
Definition: tilespec.cpp:243
QPoint activity_offset
Definition: tilespec.cpp:258
freeciv::fog_style fogstyle
Definition: tilespec.cpp:251
int unit_upkeep_offset_y
Definition: tilespec.cpp:260
freeciv::darkness_style darkness_style
Definition: tilespec.cpp:250
QPoint city_size_offset
Definition: tilespec.cpp:254
QSet< specfile * > * specfiles
Definition: tilespec.cpp:266
int num_index_valid
Definition: tilespec.cpp:264
int replaced_hue
Definition: tilespec.cpp:272
double preferred_scale
Definition: tilespec.cpp:244
int num_index_cardinal
Definition: tilespec.cpp:264
QPoint select_offset
Definition: tilespec.cpp:258
std::array< direction8, 8 > cardinal_tileset_dirs
Definition: tilespec.cpp:265
QPoint city_offset
Definition: tilespec.cpp:253
enum direction8 unit_default_orientation
Definition: tilespec.cpp:248
QSize normal_tile_size
Definition: tilespec.cpp:243
int unit_upkeep_small_offset_y
Definition: tilespec.cpp:261
QHash< QString, struct small_sprite * > * sprite_hash
Definition: tilespec.cpp:269
int priority
Definition: tilespec.cpp:226
struct color_system * color_system
Definition: tilespec.cpp:273
QPoint city_flag_offset
Definition: tilespec.cpp:253
char * summary
Definition: tilespec.cpp:228
char name[512]
Definition: tilespec.cpp:223
std::array< direction8, 8 > valid_tileset_dirs
Definition: tilespec.cpp:265
int num_valid_tileset_dirs
Definition: tilespec.cpp:263
int tilelabel_offset_y
Definition: tilespec.cpp:257
std::vector< tileset_log_entry > log
Definition: tilespec.cpp:231
QPoint occupied_offset
Definition: tilespec.cpp:258
char graphic_alt[MAX_LEN_NAME]
Definition: unittype.h:471
char graphic_str[MAX_LEN_NAME]
Definition: unittype.h:470
Definition: unit.h:134
struct civ_map map
Definition: world_object.h:21
int fc_snprintf(char *str, size_t n, const char *format,...)
See also fc_utf8_snprintf_trunc(), fc_utf8_snprintf_rep().
Definition: support.cpp:537
size_t fc_strlcpy(char *dest, const char *src, size_t n)
fc_strlcpy() provides utf-8 version of (non-standard) function strlcpy() It is intended as more user-...
Definition: support.cpp:412
int fc_strcasecmp(const char *str0, const char *str1)
Compare strings like strcmp(), but ignoring case.
Definition: support.cpp:89
size_t fc_strlcat(char *dest, const char *src, size_t n)
fc_strlcat() provides utf-8 version of (non-standard) function strlcat() It is intended as more user-...
Definition: support.cpp:448
#define sz_strlcpy(dest, src)
Definition: support.h:140
#define fc_strdup(str)
Definition: support.h:111
struct advance * valid_advance(struct advance *padvance)
Returns pointer when the advance "exists" in this game, returns nullptr otherwise.
Definition: tech.cpp:138
const char * advance_rule_name(const struct advance *padvance)
Return the (untranslated) rule name of the advance/technology.
Definition: tech.cpp:283
Tech_type_id advance_index(const struct advance *padvance)
Return the advance index.
Definition: tech.cpp:76
Tech_type_id advance_count()
Return the number of advances/technologies.
Definition: tech.cpp:68
#define advance_iterate(_start, _p)
Definition: tech.h:232
#define A_FIRST
Definition: tech.h:37
#define advance_iterate_end
Definition: tech.h:238
#define A_LAST
Definition: tech.h:38
#define terrain_type_iterate(_p)
Definition: terrain.h:331
#define terrain_type_iterate_end
Definition: terrain.h:337
void tile_virtual_destroy(struct tile *vtile)
Frees all memory used by the virtual tile, including freeing virtual units in the tile's unit list an...
Definition: tile.cpp:1051
struct tile * tile_virtual_new(const struct tile *ptile)
Returns a virtual tile.
Definition: tile.cpp:997
@ TILE_UNKNOWN
Definition: tile.h:29
#define tile_terrain(_tile)
Definition: tile.h:93
#define TILE_XY(ptile)
Definition: tile.h:36
static const bv_extras * tile_extras(const struct tile *ptile)
Definition: tile.h:102
void tileset_load_tiles(struct tileset *t)
Load the tiles; requires tilespec_read_toplevel() called previously.
Definition: tilespec.cpp:2714
const QPixmap * get_nuke_explode_sprite(const struct tileset *t)
Return a sprite contining the single nuke graphic.
Definition: tilespec.cpp:3515
struct tileset * tileset
Definition: tilespec.cpp:276
int tileset_hex_width(const struct tileset *t)
Return the hex_width of the current tileset.
Definition: tilespec.cpp:345
void tilespec_init()
Initializes the tilespec system.
Definition: tilespec.cpp:709
const char * tileset_name_get(const struct tileset *t)
Return tileset name.
Definition: tilespec.cpp:3828
int tileset_unit_width(const struct tileset *t)
Return the unit tile width of the current tileset.
Definition: tilespec.cpp:426
static void assign_sprite(struct tileset *t, QPixmap *&field, const QStringList &possible_names, bool required)
finds the first sprite matching a list of possible names and returns it to the field argument.
Definition: tilespec.cpp:2380
static void tileset_setup_citizen_types(struct tileset *t)
Setup the graphics for (non-specialist) citizen types.
Definition: tilespec.cpp:2487
bool tilespec_reread(const QString &name, bool game_fully_initialized)
Read a new tilespec in from scratch.
Definition: tilespec.cpp:916
std::vector< drawn_sprite > fill_basic_terrain_layer_sprite_array(struct tileset *t, int layer, struct terrain *pterrain)
Fill the sprite array with sprites that together make a representative image of the given terrain typ...
Definition: tilespec.cpp:3642
int tileset_unit_height(const struct tileset *t)
Return the unit tile height of the current tileset.
Definition: tilespec.cpp:434
const QPixmap * get_citizen_sprite(const struct tileset *t, enum citizen_category type, int citizen_index, const struct city *pcity)
Return a sprite for the given citizen.
Definition: tilespec.cpp:3337
void tileset_setup_unit_type(struct tileset *t, struct unit_type *ut)
Set unit_type sprite value; should only happen after tilespec_load_tiles().
Definition: tilespec.cpp:2847
static bool check_tilespec_capabilities(struct section_file *file, const char *which, const char *us_capstr, const char *filename, bool verbose)
Checks options in filename match what we require and support.
Definition: tilespec.cpp:780
static char * tilespec_fullname(QString tileset_name)
Gets full filename for tilespec file, based on input name.
Definition: tilespec.cpp:758
int tileset_num_cardinal_dirs(const struct tileset *t)
Returns the number of cardinal directions used by the tileset.
Definition: tilespec.cpp:554
int tileset_small_sprite_width(const struct tileset *t)
Return the small sprite width of the current tileset.
Definition: tilespec.cpp:495
const freeciv::layer_city * tileset_layer_city(const struct tileset *t)
Returns the layer_city of the tileset.
Definition: tilespec.cpp:3665
const char * tileset_basename(const struct tileset *t)
Return the name of the given tileset.
Definition: tilespec.cpp:331
const QPixmap * get_nation_flag_sprite(const struct tileset *t, const struct nation_type *pnation)
Return the sprite for the nation.
Definition: tilespec.cpp:3367
#define SPEC_CAPSTR
Definition: tilespec.cpp:118
const char * tileset_summary(const struct tileset *t)
Return tileset description summary.
Definition: tilespec.cpp:3841
const std::vector< std::unique_ptr< freeciv::layer > > & tileset_get_layers(const struct tileset *t)
Definition: tilespec.cpp:3700
void tileset_setup_government(struct tileset *t, struct government *gov)
Set government sprite value; should only happen after tilespec_load_tiles().
Definition: tilespec.cpp:3007
std::array< direction8, 8 > tileset_cardinal_dirs(const struct tileset *t)
Returns the cardinal directions used by the tileset.
Definition: tilespec.cpp:574
static bool is_valid_tileset_dir(const struct tileset *t, enum direction8 dir)
Return TRUE iff the dir is valid in this tileset.
Definition: tilespec.cpp:657
const QPixmap * get_unit_upkeep_sprite(const struct tileset *t, Output_type_id otype, const struct unit *punit, const int *upkeep_cost)
Return a sprite for the upkeep of the unit - to be shown as an overlay on the unit in the city suppor...
Definition: tilespec.cpp:3603
static QPixmap * load_sprite(struct tileset *t, const QString &tag_name)
Loads the sprite.
Definition: tilespec.cpp:2270
int tileset_full_tile_height(const struct tileset *t)
Return the full tile height of the current tileset.
Definition: tilespec.cpp:407
static bool tileset_setup_unit_type_from_tag(struct tileset *t, int uidx, const char *tag)
Try to setup all unit type sprites from single tag.
Definition: tilespec.cpp:2807
static QPixmap * make_error_pixmap()
Makes a dummy "error" pixmap to prevent crashes.
Definition: tilespec.cpp:1102
const QPixmap * get_attention_crosshair_sprite(const struct tileset *t)
Returns a sprite with the "user-attention" crosshair graphic.
Definition: tilespec.cpp:3557
void tileset_setup_specialist_type(struct tileset *t, Specialist_type_id id)
Setup the graphics for specialist types.
Definition: tilespec.cpp:2423
void tileset_setup_tile_type(struct tileset *t, const struct terrain *pterrain)
Set tile_type sprite values; should only happen after tilespec_load_tiles().
Definition: tilespec.cpp:2995
int get_focus_unit_toggle_timeout(const struct tileset *t)
Return the amount of time between calls to toggle_focus_unit_state.
Definition: tilespec.cpp:3200
void tileset_player_init(struct tileset *t, struct player *pplayer)
Setup tiles for one player using the player color.
Definition: tilespec.cpp:3708
int tileset_unit_layout_offset_y(const struct tileset *t)
Offset to layout extra unit sprites, such as upkeep.
Definition: tilespec.cpp:485
int tileset_citybar_offset_y(const struct tileset *t)
Return the offset from the origin of the city tile at which to place the city bar text.
Definition: tilespec.cpp:504
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
static int calculate_max_upkeep_height(const struct tileset *t)
Calculate the height of a unit upkeep icons.
Definition: tilespec.cpp:442
static const char * citizen_rule_name(enum citizen_category citizen)
Returns a text name for the citizen, as used in the tileset.
Definition: tilespec.cpp:2207
#define TILE_SECTION_PREFIX
Definition: tilespec.cpp:129
const QPixmap * get_indicator_sprite(const struct tileset *t, enum indicator_type indicator, int idx)
Returns a sprite for the given indicator with the given index.
Definition: tilespec.cpp:3566
void tileset_free_tiles(struct tileset *t)
Free all sprites from tileset.
Definition: tilespec.cpp:3285
void tileset_setup_impr_type(struct tileset *t, struct impr_type *pimprove)
Set improvement_type sprite value; should only happen after tilespec_load_tiles().
Definition: tilespec.cpp:2879
const QPixmap * get_city_flag_sprite(const struct tileset *t, const struct city *pcity)
Return the flag graphic to be used by the city.
Definition: tilespec.cpp:3052
int tileset_topo_index(const struct tileset *t)
Return tileset topology index.
Definition: tilespec.cpp:3854
#define TILESPEC_CAPSTR
Definition: tilespec.cpp:87
const QPixmap * get_event_sprite(const struct tileset *t, enum event_type event)
Return event icon sprite.
Definition: tilespec.cpp:3469
static void unload_all_sprites(struct tileset *t)
This patch unloads all sprites from the sprite hash (the hash itself is left intact).
Definition: tilespec.cpp:3267
QString valid_index_str(const struct tileset *t, int idx)
Do the same thing as cardinal_str, except including all valid directions.
Definition: tilespec.cpp:2251
void tileset_setup_tech_type(struct tileset *t, struct advance *padvance)
Set tech_type sprite value; should only happen after tilespec_load_tiles().
Definition: tilespec.cpp:2895
Q_LOGGING_CATEGORY(tileset_category, "freeciv.tileset")
Functions for handling the tilespec files which describe the files and contents of tilesets.
static QPixmap * load_gfx_file(const char *gfx_filename)
Loads the given graphics file (found in the data path) into a newly allocated sprite.
Definition: tilespec.cpp:1113
const std::vector< QPixmap * > & get_unit_explode_animation(const struct tileset *t)
Return a sprite_vector containing the animation sprites for a unit explosion.
Definition: tilespec.cpp:3505
const QPixmap * get_tech_sprite(const struct tileset *t, Tech_type_id tech)
Return the sprite for the technology/advance.
Definition: tilespec.cpp:3385
static void tileset_player_free(struct tileset *t, int plrid)
Free tiles for one player using the player color.
Definition: tilespec.cpp:3727
const struct citybar_sprites * get_citybar_sprites(const struct tileset *t)
Return all the sprites used for city bar drawing.
Definition: tilespec.cpp:3523
std::vector< drawn_sprite > fill_basic_extra_sprite_array(const struct tileset *t, const struct extra_type *pextra)
Return a representative sprite for the given extra type.
Definition: tilespec.cpp:3679
static bool tileset_invalid_offsets(struct tileset *t, struct section_file *file)
Definition: tilespec.cpp:1414
struct color_system * get_color_system(const struct tileset *t)
Return the tileset's color system.
Definition: tilespec.cpp:3622
bool tileset_option_is_enabled(const struct tileset *t, const QString &name)
Checks if an user-settable tileset option is enabled.
Definition: tilespec.cpp:3799
#define TILESPEC_SUFFIX
Definition: tilespec.cpp:128
bool tileset_is_isometric(const struct tileset *t)
Return whether the current tileset is isometric.
Definition: tilespec.cpp:336
bool tileset_use_hard_coded_fog(const struct tileset *t)
Return TRUE if the client will use the code to generate the fog.
Definition: tilespec.cpp:531
static bool tileset_setup_unit_direction(struct tileset *t, int uidx, const char *base_str, enum direction8 dir, bool has_icon)
Helper function to load sprite for one unit orientation.
Definition: tilespec.cpp:2763
QPoint tileset_full_tile_offset(const struct tileset *t)
Return the x and y offsets of full tiles in the tileset.
Definition: tilespec.cpp:416
void tileset_setup_city_tiles(struct tileset *t, int style)
Set city tiles sprite values; should only happen after tilespec_load_tiles().
Definition: tilespec.cpp:3188
static freeciv::layer_terrain::sprite_type check_sprite_type(const char *sprite_type, const char *tile_section)
Determine the sprite_type string.
Definition: tilespec.cpp:1395
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
const char * tileset_version(const struct tileset *t)
Return tileset version.
Definition: tilespec.cpp:3836
#define MAX_NUM_LAYERS
Definition: tilespec.cpp:134
std::map< QString, tileset_option > tileset_get_options(const struct tileset *t)
Gets the user-settable options of the tileset.
Definition: tilespec.cpp:3789
void toggle_focus_unit_state(struct tileset *t)
Toggle/increment the focus unit state.
Definition: tilespec.cpp:3232
int tileset_small_sprite_height(const struct tileset *t)
Return the small sprite height of the current tileset.
Definition: tilespec.cpp:523
void tileset_free(struct tileset *t)
Clean up.
Definition: tilespec.cpp:840
void focus_unit_in_combat(struct tileset *t)
Setup tileset for showing combat where focus unit participates.
Definition: tilespec.cpp:3221
static int tileset_upkeep_height(const struct tileset *t)
Get the height of a unit upkeep icons.
Definition: tilespec.cpp:464
bool tileset_has_option(const struct tileset *t, const QString &option)
Checks if the tileset has supports the given user-settable option.
Definition: tilespec.cpp:3780
const QPixmap * get_mask_sprite(const struct tileset *t)
Return tile mask sprite.
Definition: tilespec.cpp:3486
const QPixmap * get_dither_sprite(const struct tileset *t)
Return dither sprite.
Definition: tilespec.cpp:3478
bool is_cardinal_tileset_dir(const struct tileset *t, enum direction8 dir)
Return TRUE iff the dir is cardinal in this tileset.
Definition: tilespec.cpp:675
static bool tileset_update
Definition: tilespec.cpp:278
QEvent::Type TilesetChanged
An event type sent to all widgets when the current tileset changes.
Definition: tilespec.cpp:719
static void tileset_set_offsets(struct tileset *t, struct section_file *file)
Definition: tilespec.cpp:1455
void tileset_setup_extra(struct tileset *t, struct extra_type *pextra)
Set extra sprite values; should only happen after tilespec_load_tiles().
Definition: tilespec.cpp:2937
bool tileset_is_fully_loaded()
Is tileset in sane state?
Definition: tilespec.cpp:3750
const QPixmap * get_treaty_thumb_sprite(const struct tileset *t, bool on_off)
Return a thumbs-up/thumbs-down sprite to show treaty approval or disapproval.
Definition: tilespec.cpp:3495
void tileset_init(struct tileset *t)
Initialize tileset structure.
Definition: tilespec.cpp:3630
const QPixmap * get_unittype_sprite(const struct tileset *t, const struct unit_type *punittype, enum direction8 facing, const QColor &replace)
Return the sprite for the unit type (the base "unit" sprite).
Definition: tilespec.cpp:3416
int tileset_tile_height(const struct tileset *t)
Return the tile height of the current tileset.
Definition: tilespec.cpp:383
#define LOAD_FACING_SPRITE(dir)
bool tileset_set_option(struct tileset *t, const QString &name, bool enabled)
Enable or disable a user-settable tileset option.
Definition: tilespec.cpp:3812
struct tileset * get_tileset()
Returns the tileset.
Definition: tilespec.cpp:326
void assign_digit_sprites(struct tileset *t, QPixmap *units[NUM_TILES_DIGITS], QPixmap *tens[NUM_TILES_DIGITS], QPixmap *hundreds[NUM_TILES_DIGITS], const QStringList &patterns)
Assigns the digits for city or go-to orders, for units, tens, and hundreds (i.e.
Definition: tilespec.cpp:2408
int tileset_unit_with_upkeep_height(const struct tileset *t)
Suitable canvas height for a unit icon that includes upkeep sprites.
Definition: tilespec.cpp:473
static struct tileset * tileset_new()
Initialize.
Definition: tilespec.cpp:600
static void tileset_free_toplevel(struct tileset *t)
Frees the tilespec toplevel data, in preparation for re-reading it.
Definition: tilespec.cpp:819
int tileset_replaced_hue(const struct tileset *t)
Returns the hue (color) that should be replaced with the player color in player-dependent sprites.
Definition: tilespec.cpp:548
const QPixmap * get_government_sprite(const struct tileset *t, const struct government *gov)
Return the sprite for the government.
Definition: tilespec.cpp:3404
int tileset_hex_height(const struct tileset *t)
Return the hex_height of the current tileset.
Definition: tilespec.cpp:351
void reset_focus_unit_state(struct tileset *t)
Reset the focus unit state.
Definition: tilespec.cpp:3213
static const char *const OPTION_SECTION_PREFIX
The prefix for option sections in the tilespec file.
Definition: tilespec.cpp:132
const QVector< QString > * get_tileset_list(const struct option *poption)
Returns a static list of tilesets available on the system by searching all data directories for files...
Definition: tilespec.cpp:725
static void tileset_lookup_sprite_tags(struct tileset *t)
Initialize 'sprites' structure based on hardwired tags which freeciv always requires.
Definition: tilespec.cpp:2515
QPixmap * tiles_lookup_sprite_tag_alt(struct tileset *t, QtMsgType level, const char *tag, const char *alt, const char *what, const char *name, bool scale)
Lookup sprite to match tag, or else to match alt if don't find, or else return nullptr,...
Definition: tilespec.cpp:2724
bool tileset_has_options(const struct tileset *t)
Checks if the tileset has any user-settable options.
Definition: tilespec.cpp:3772
void finish_loading_sprites(struct tileset *t)
Frees any internal buffers which are created by load_sprite.
Definition: tilespec.cpp:2698
const QPixmap * get_unit_unhappy_sprite(const struct tileset *t, const struct unit *punit, int happy_cost)
Return a sprite for the unhappiness of the unit - to be shown as an overlay on the unit in the city s...
Definition: tilespec.cpp:3582
int tileset_num_valid_dirs(const struct tileset *t)
Returns the number of valid directions in the tileset.
Definition: tilespec.cpp:582
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
void tilespec_reread_callback(struct option *poption)
This is merely a wrapper for tilespec_reread (above) for use in options.c and the client local option...
Definition: tilespec.cpp:1063
const char * tileset_description(const struct tileset *t)
Return tileset description body.
Definition: tilespec.cpp:3846
static bool tileset_setup_options(struct tileset *t, const section_file *file)
Loads tileset options.
Definition: tilespec.cpp:2139
static void assign_digit_sprites_helper(struct tileset *t, QPixmap *sprites[NUM_TILES_DIGITS], const QStringList &patterns, const QString &suffix, bool required)
Goes through the possible digits and assigns them.
Definition: tilespec.cpp:2390
static void tileset_add_layer(struct tileset *t, mapview_layer layer)
Creates a layer object for the given enumerated type and appends it to the layers of t.
Definition: tilespec.cpp:1480
int tileset_full_tile_width(const struct tileset *t)
Return the full tile width of the current tileset.
Definition: tilespec.cpp:394
QString cardinal_index_str(const struct tileset *t, int idx)
Return a directional string for the cardinal directions.
Definition: tilespec.cpp:2233
help_item * tileset_help(const struct tileset *t)
Creates the help item for the given tileset.
Definition: tilespec.cpp:3859
int tileset_num_index_cardinals(const struct tileset *t)
Returns the number of cardinal indices used by the tileset.
Definition: tilespec.cpp:564
const QPixmap * get_spaceship_sprite(const struct tileset *t, enum spaceship_part part)
Return the sprite for drawing the given spaceship part.
Definition: tilespec.cpp:3324
const QPixmap * get_tax_sprite(const struct tileset *t, Output_type_id otype)
Return a tax sprite for the given output type (usually gold/lux/sci).
Definition: tilespec.cpp:3448
const QPixmap * get_cursor_sprite(const struct tileset *t, enum cursor_type cursor, int *hot_x, int *hot_y, int frame)
Returns a sprite for the given cursor.
Definition: tilespec.cpp:3542
QPixmap * get_unit_nation_flag_sprite(const struct tileset *t, const struct unit *punit)
Return a sprite for the national flag for this unit.
Definition: tilespec.cpp:3061
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
void tilespec_reread_frozen_refresh(const QString &name)
Read a new tilespec in from scratch.
Definition: tilespec.cpp:1091
std::array< direction8, 8 > tileset_valid_dirs(const struct tileset *t)
Returns the valid directions for the tileset.
Definition: tilespec.cpp:592
static int ts_topology_index(int actual_topology)
Convert properties of the actual topology to an index of different tileset topology types.
Definition: tilespec.cpp:689
double tileset_preferred_scale(const struct tileset *t)
Returns the preferred scale (zoom level) of the tileset.
Definition: tilespec.cpp:539
struct unit * get_drawable_unit(const struct tileset *t, const ::tile *ptile)
Find unit that we can display from given tile.
Definition: tilespec.cpp:3246
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
static enum direction8 dir_by_tileset_name(const QString &str)
Parse a direction name as a direction8.
Definition: tilespec.cpp:640
const QPixmap * get_building_sprite(const struct tileset *t, const struct impr_type *pimprove)
Return the sprite for the building/improvement.
Definition: tilespec.cpp:3394
QString dir_get_tileset_name(enum direction8 dir)
Return the tileset name of the direction.
Definition: tilespec.cpp:613
bool tileset_has_error(const struct tileset *t)
Checks if the tileset had any error message (LOG_ERROR).
Definition: tilespec.cpp:3763
int tileset_tile_width(const struct tileset *t)
Return the tile width of the current tileset.
Definition: tilespec.cpp:371
int tileset_tilelabel_offset_y(const struct tileset *t)
Return the offset from the origin of the tile at which to place the label text.
Definition: tilespec.cpp:513
static void tileset_stop_read(struct tileset *t, struct section_file *file, char *fname, struct section_list *sections, const char **layer_order)
Definition: tilespec.cpp:1463
const struct editor_sprites * get_editor_sprites(const struct tileset *t)
Return all the sprites used for editor icons, images, etc.
Definition: tilespec.cpp:3531
static void unload_sprite(struct tileset *t, const QString &tag_name)
Unloads the sprite.
Definition: tilespec.cpp:2358
bool tilespec_try_read(const QString &tileset_name, bool verbose, int topo_id)
Read a new tilespec in when first starting the game.
Definition: tilespec.cpp:860
static void ensure_big_sprite(struct tileset *t, struct specfile *sf)
Ensure that the big sprite of the given spec file is loaded.
Definition: tilespec.cpp:1146
std::vector< tileset_log_entry > tileset_log(const struct tileset *t)
Get tileset log (warnings, errors, etc.)
Definition: tilespec.cpp:3755
const QPixmap * get_nation_shield_sprite(const struct tileset *t, const struct nation_type *pnation)
Return the shield sprite for the nation.
Definition: tilespec.cpp:3376
void tileset_setup_nation_flag(struct tileset *t, struct nation_type *nation)
Set nation flag sprite value; should only happen after tilespec_load_tiles().
Definition: tilespec.cpp:3020
void tileset_ruleset_reset(struct tileset *t)
Reset tileset data specific to ruleset.
Definition: tilespec.cpp:3740
static struct tileset * tileset_read_toplevel(const QString &tileset_name, bool verbose, int topology_id)
Finds and reads the toplevel tilespec file based on given name.
Definition: tilespec.cpp:1579
static void scan_specfile(struct tileset *t, struct specfile *sf, bool duplicates_ok)
Scan all sprites declared in the given specfile.
Definition: tilespec.cpp:1186
#define NUM_CURSOR_FRAMES
Definition: tilespec.h:169
indicator_type
Definition: tilespec.h:171
@ INDICATOR_COUNT
Definition: tilespec.h:175
@ ARROW_LAST
Definition: tilespec.h:48
@ ARROW_MINUS
Definition: tilespec.h:48
@ ARROW_RIGHT
Definition: tilespec.h:48
@ ARROW_PLUS
Definition: tilespec.h:48
#define TS_TOPO_ISOHEX
Definition: tilespec.h:307
#define NUM_TILES_PROGRESS
Definition: tilespec.h:43
#define MAX_NUM_CITIZEN_SPRITES
Definition: tilespec.h:46
#define TS_TOPO_HEX
Definition: tilespec.h:306
#define TS_TOPO_SQUARE
Definition: tilespec.h:305
spaceship_part
Definition: tilespec.h:178
@ SPACESHIP_COUNT
Definition: tilespec.h:186
cursor_type
Definition: tilespec.h:154
@ CURSOR_LAST
Definition: tilespec.h:165
bool unit_is_cityfounder(const struct unit *punit)
Is a cityfounder unit?
Definition: unit.cpp:2389
bool unit_has_orders(const struct unit *punit)
Return TRUE iff the unit is following client-side orders.
Definition: unit.cpp:195
#define unit_tile(_pu)
Definition: unit.h:371
const char * utype_rule_name(const struct unit_type *punittype)
Return the (untranslated) rule name of the unit type.
Definition: unittype.cpp:1274
Unit_type_id utype_index(const struct unit_type *punittype)
Return the unit type index.
Definition: unittype.cpp:82
#define unit_type_iterate(_p)
Definition: unittype.h:785
#define U_LAST
Definition: unittype.h:31
#define unit_type_iterate_end
Definition: unittype.h:791
struct tile * get_center_tile_mapcanvas()
Finds the current center tile of the mapcanvas.
enum topo_comp_lvl tileset_map_topo_compatible(int topology_id, struct tileset *tset)
Are the topology and tileset compatible?
void update_map_canvas_visible()
Schedules an update of (only) the visible part of the map at the next unqueue_mapview_update().
@ TOPO_INCOMP_HARD