104 static const char direction4letters[5] =
"udrl";
120 if (
name.isEmpty()) {
122 _(
"[layer%d] match_types: names cannot be empty."),
130 _(
"[layer%d] match_types: \"%s\" initial ('%c') is not unique."),
154 "Multiple [tile] sections containing terrain tag \"%s\".",
155 qUtf8Printable(tag));
195 const QString &group_name)
197 if (
auto g =
group(group_name); g !=
nullptr) {
213 const QString &group_name)
215 if (
auto g =
group(group_name); g !=
nullptr) {
230 _(
"Blending is only supported for isometric tilesets"));
251 _(
"Terrain \"%s\": no graphic tile \"%s\" or \"%s\"."),
282 switch (info.
style) {
293 _(
"Not implemented CELL_WHOLE + MATCH_FULL/MATCH_PAIR."));
298 switch (info.
style) {
316 _(
"Layer %d, tag \"%s\": Sprite type \"hex_corner\" is "
317 "only supported for isometric hexagonal tilesets"),
340 for (
int i = 0;; i++) {
341 buffer = QStringLiteral(
"t.l%1.%2%3")
349 info.
sprites.push_back(sprite);
356 _(
"Missing base sprite for tag \"%s\"."),
357 qUtf8Printable(buffer));
369 auto buffer = QStringLiteral(
"t.l%1.%2_%3")
389 for (
int i = 0; i < number; i++) {
391 auto buffer = QStringLiteral(
"t.l%1.%2_cell_%3")
394 .arg(direction4letters[dir]);
411 for (
int i = 0; i < number; i++) {
415 auto buffer = QStringLiteral(
"t.l%1.%2_cell_%3%4%5%6")
418 .arg(direction4letters[dir])
420 .arg((value >> 1) & 1)
421 .arg((value >> 2) & 1);
438 for (
int i = 0; i < number; i++) {
444 auto buffer = QStringLiteral(
"t.l%1.%2_cell_%3_%4_%5_%6")
446 .arg(info.
sprite_name, QChar(direction4letters[dir]),
447 letters[value & 1], letters[(value >> 1) & 1],
448 letters[(value >> 2) & 1]);
469 for (
int i = 0; i < number; i++) {
510 auto buffer = QStringLiteral(
"t.l%1.cellgroup_%2_%3_%4_%5")
516 const int W = sprite->width();
517 const int H = sprite->height();
518 int x[4] = {W / 4, W / 4, 0, W / 2};
519 int y[4] = {H / 2, 0, H / 4, H / 4};
520 int xo[4] = {0, 0, -W / 2, W / 2};
521 int yo[4] = {H / 2, -H / 2, 0, 0};
523 sprite =
crop_sprite(sprite, x[dir], y[dir], W / 2, H / 2,
528 info.
sprites.push_back(sprite);
531 "Terrain graphics sprite for tag \"%s\" missing.",
532 qUtf8Printable(buffer));
573 const int indices[6][3] = {
574 {2, 1, 0}, {0, 1, 2}, {1, 0, 2}, {2, 0, 1}, {0, 2, 1}, {1, 2, 0},
584 for (
int idir = 0; idir < 6; ++idir) {
587 bool left = (idir % 2 == 0);
591 auto buffer = QString();
594 std::array<int, 3> present = {
600 buffer = QStringLiteral(
"t.l%1.%2_hex_cell_%3_%4_%5_%6")
603 .arg(left ? QStringLiteral(
"left")
604 : QStringLiteral(
"right"))
605 .arg(present[indices[idir][0]])
606 .arg(present[indices[idir][1]])
607 .arg(present[indices[idir][2]]);
609 std::array<matching_group *, 3> groups = {
615 buffer = QStringLiteral(
"t.l%1.hex_cell_%2_%3_%4_%5")
617 .arg(left ? QStringLiteral(
"left")
618 : QStringLiteral(
"right"))
619 .arg(groups[indices[idir][0]]->
name[0])
620 .arg(groups[indices[idir][1]]->
name[0])
621 .arg(groups[indices[idir][2]]->
name[0]);
628 std::array<int, 6> y = {H / 4, 0, 0, 0, 0, H / 4};
629 std::array<int, 6> h = {H / 4, H / 2, H / 4, H / 4, H / 2, H / 4};
630 std::array<int, 6> xo = {-W / 2, -W / 2, -W / 2, 0, 0, 0};
631 std::array<int, 6> yo = {H / 4, -H / 4, -3 * H / 4,
632 -3 * H / 4, -H / 4, H / 4};
641 info.
sprites.push_back(sprite);
644 "Terrain graphics sprite for tag \"%s\" missing.",
645 qUtf8Printable(buffer));
665 auto buffer = QStringLiteral(
"t.blend.%1").arg(info.
sprite_name);
670 if (blender ==
nullptr) {
674 buffer = QStringLiteral(
"t.l%1.%2%3")
683 if (blender ==
nullptr) {
686 "Cannot find sprite for blending terrain with tag %s on layer %d",
694 const int offsets[4][2] = {{W / 2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}};
697 for (; dir < 4; dir++) {
699 crop_sprite(blender, offsets[dir][0], offsets[dir][1], W / 2, H / 2,
707 std::vector<drawn_sprite>
710 const unit *punit)
const
712 if (ptile ==
nullptr) {
726 auto sprites = std::vector<drawn_sprite>();
732 if (QPixmap * sprite;
735 sprites.emplace_back(
tileset(), sprite);
741 struct terrain *terrain_near[8] = {
nullptr};
742 bv_extras extras_near[8];
760 qUtf8Printable(
name));
765 if (candidate->name ==
name) {
801 template <std::
size_t N>
802 int flattened_index(
int size,
const std::array<int, N> &indices,
806 for (
auto it = indices.rbegin(); it != indices.rend(); ++it) {
819 std::vector<drawn_sprite> &sprs,
const tile *ptile,
829 #define MATCH(dir) terrain_group(tterrain_near[(dir)])
833 switch (info.style) {
835 if (!info.sprites.empty()) {
839 info.sprites.size());
840 if (Q_LIKELY(info.sprites[i] !=
nullptr)) {
841 sprs.emplace_back(
tileset(), info.
sprites[i],
true, info.offset_x,
856 if (
MATCH(dir) == info.matches_with.back()->number) {
860 if (Q_LIKELY(info.sprites[tileno] !=
nullptr)) {
862 info.offset_x, info.offset_y);
883 const int iso_offsets[4][2] = {
884 {W / 4, 0}, {W / 4, H / 2}, {W / 2, H / 4}, {0, H / 4}};
885 const int noniso_offsets[4][2] = {
886 {0, 0}, {W / 2, H / 2}, {W / 2, 0}, {0, H / 2}};
890 const int count = info.matches_with.size();
893 : noniso_offsets[i][0]);
895 : noniso_offsets[i][1]);
899 switch (info.style) {
905 array_index = flattened_index<3>(2, {(m[0] != info.group->number),
906 (m[1] != info.group->number),
907 (m[2] != info.group->number)});
911 const auto that = info.matches_with.back()->number;
912 array_index = flattened_index<3>(
913 2, {(m[0] == that), (m[1] == that), (m[2] == that)});
917 std::array<int, 3> n;
918 for (
int j = 0; j < 3; j++) {
919 for (
int k = 0; k < count; k++) {
921 if (m[j] == info.matches_with[k]->number) {
926 array_index = flattened_index(count, n);
931 const auto sprite = info.sprites[array_index];
933 sprs.emplace_back(
tileset(), sprite,
true, x, y);
943 const std::array<direction8, 6> iso_dirs = {
944 DIR8_NORTH, DIR8_EAST, DIR8_SOUTHEAST,
945 DIR8_SOUTH, DIR8_WEST, DIR8_NORTHWEST,
948 const int iso_offsets[6][2] = {
949 {W / 2, 0}, {W / 2, H / 4}, {W / 2, 3 * H / 4},
950 {0, 3 * H / 4}, {0, H / 4}, {0, 0},
954 for (
int i = 0; i < 6; ++i) {
955 std::array<int, 2> matches = {
956 MATCH(iso_dirs[(i + 5) % 6]),
959 std::array<int, 2> indices = {0, 0};
960 switch (info.style) {
963 indices = {(matches[0] == info.group->number),
964 (matches[1] == info.group->number)};
970 for (
int j = 0; j < 2; ++j) {
971 if (matches[j] < 0) {
978 std::find_if(info.matches_with.begin(),
979 info.matches_with.end(), [=](
const auto &
group) {
980 return group->number == matches[j];
982 if (it == info.matches_with.end()) {
987 indices[j] = std::distance(info.matches_with.begin(), it);
993 int array_index = flattened_index<2>(info.matches_with.size(),
994 {indices[1], indices[0]}, i);
996 const auto sprite = info.sprites[array_index];
998 sprs.emplace_back(
tileset(), sprite,
true, iso_offsets[i][0],
1016 std::vector<drawn_sprite> &sprs,
const tile *ptile,
1022 const int offsets[4][2] = {{W / 2, 0}, {0, H / 2}, {W / 2, H / 2}, {0, 0}};
1035 for (
int dir = 0; dir < 4; dir++) {
1050 if (pterrain == (other = tterrain_near[
DIR4_TO_DIR8[dir]])) {
1061 if (!other_info.blend) {
1066 if (Q_LIKELY(other_info.blend_sprites.at(dir) !=
nullptr)) {
1067 sprs.emplace_back(
tileset(), other_info.blend_sprites.at(dir),
true,
1068 offsets[dir][0], offsets[dir][1]);
QPixmap crop_sprite(const QPixmap *sprite)
Helper function to crop a sprite.
bool add_tag(const QString &tag, const QString &sprite_name)
Makes a terrain tag available for use by this layer.
matching_group * group(const QString &name)
Retrieves the group structure of the provided name.
int terrain_group(const terrain *pterrain) const
Retrieves the group number for a given terrain.
void fill_blending_sprite_array(std::vector< drawn_sprite > &sprs, const tile *ptile, const terrain *pterrain, terrain **tterrain_near) const
Helper function for fill_sprite_array.
void initialize_cell_corner_match_none(const terrain *terrain, terrain_info &info)
Sets up terrain information for CELL_CORNER and MATCH_NONE.
void initialize_cell_corner_match_full(const terrain *terrain, terrain_info &info)
Sets up terrain information for CELL_CORNER and MATCH_FULL.
bool set_tag_matches_with(const QString &tag, const QString &group_name)
Sets the specified tag to be matched against a group.
std::map< int, terrain_info > m_terrain_info
Every terrain drawn in this layer appears here.
bool set_tag_offsets(const QString &tag, int offset_x, int offset_y)
Sets the offsets used to draw the specified tag.
layer_terrain(struct tileset *ts, int number)
sprite_type
Indicates how many sprites are used to draw a tile.
@ CELL_WHOLE
One sprite for the entire tile.
@ CELL_HEX_CORNER
One sprite for each hexagonal corner of the tile.
@ CELL_CORNER
One sprite for each corner of the tile.
bool set_tag_sprite_type(const QString &tag, sprite_type type)
Sets the type of sprite used to draw the specified tag.
void fill_terrain_sprite_array(std::vector< drawn_sprite > &sprs, const tile *ptile, const terrain *pterrain, terrain **tterrain_near) const
Helper function for fill_sprite_array.
void initialize_cell_whole_match_none(const terrain *terrain, terrain_info &info)
Sets up terrain information for CELL_WHOLE and MATCH_SAME.
void initialize_cell_corner_match_pair(const terrain *terrain, terrain_info &info)
Sets up terrain information for CELL_CORNER and MATCH_PAIR.
void enable_blending(const QString &tag)
Enable blending on this layer for the given terrain tag.
void initialize_cell_corner_match_same(const terrain *terrain, terrain_info &info)
Sets up terrain information for CELL_CORNER and MATCH_SAME.
std::map< QString, terrain_info > m_terrain_tag_info
Before terrains are loaded, this contains the list of available terrain tags.
std::vector< drawn_sprite > fill_sprite_array(const tile *ptile, const tile_edge *pedge, const tile_corner *pcorner, const unit *punit) const override
Returns the list of sprites drawn by this layer somewhere on the map.
void initialize_terrain(const terrain *terrain) override
Sets up the structure to draw the specified terrain.
void initialize_cell_whole_match_same(const terrain *terrain, terrain_info &info)
Sets up terrain information for CELL_WHOLE and MATCH_SAME.
std::vector< std::unique_ptr< QPixmap > > m_allocated
List of those sprites in 'cells' that are allocated by some other means than load_sprite() and thus a...
void initialize_blending(const terrain *terrain, terrain_info &info)
Initializes blending sprites.
bool set_tag_matching_group(const QString &tag, const QString &group_name)
Sets the matching group for the specified tag.
std::map< QChar, matching_group > m_matching_groups
void initialize_cell_hex_corner(const terrain *terrain, terrain_info &info)
Sets up terrain information for CELL_HEX_CORNER.
bool create_matching_group(const QString &name)
Creates a matching group with the given name.
A layer when drawing the map.
mapview_layer type() const
QPixmap * load_sprite(const QStringList &possible_names, bool required=false, bool verbose=true) const
Shortcut to load a sprite from the tileset.
bool solid_background(const tile *ptile, const unit *punit, const city *pcity) const
Whether a solid background should be drawn on a tile instead of its terrain.
struct tileset * tileset() const
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.
#define fc_assert_ret(condition)
constexpr auto LOG_VERBOSE
#define fc_assert(condition)
enum direction8 dir_ccw(enum direction8 dir)
Returns the next direction counter-clock-wise.
enum direction8 dir_cw(enum direction8 dir)
Returns the next direction clock-wise.
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Step from the given tile in the given direction.
#define fc_randomly(_seed, _size)
std::vector< matching_group * > matches_with
std::array< QPixmap *, 4 > blend_sprites
std::vector< QPixmap * > sprites
char graphic_alt[MAX_LEN_NAME]
char graphic_str[MAX_LEN_NAME]
struct named_sprites sprites
const char * terrain_rule_name(const struct terrain *pterrain)
Return the (untranslated) rule name of the terrain.
Terrain_type_id terrain_index(const struct terrain *pterrain)
Return the terrain index.
struct city * tile_city(const struct tile *ptile)
Return the city on this tile (or nullptr), checking for city center.
int tileset_num_cardinal_dirs(const struct tileset *t)
Returns the number of cardinal directions used by the tileset.
std::array< direction8, 8 > tileset_cardinal_dirs(const struct tileset *t)
Returns the cardinal directions used by the tileset.
int tileset_topo_index(const struct tileset *t)
Return tileset topology index.
bool tileset_is_isometric(const struct tileset *t)
Return whether the current tileset is isometric.
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.
const QPixmap * get_mask_sprite(const struct tileset *t)
Return tile mask sprite.
const QPixmap * get_dither_sprite(const struct tileset *t)
Return dither sprite.
int tileset_tile_height(const struct tileset *t)
Return the tile height of the current tileset.
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,...
void tileset_error(struct tileset *t, QtMsgType level, const char *format,...)
Called when ever there's problem in ruleset/tileset compatibility.
QString cardinal_index_str(const struct tileset *t, int idx)
Return a directional string for the cardinal directions.
int tileset_num_index_cardinals(const struct tileset *t)
Returns the number of cardinal indices used by the tileset.
int tileset_tile_width(const struct tileset *t)
Return the tile width of the current tileset.
constexpr direction8 DIR4_TO_DIR8[4]