From 4281657cf19ea892bdb5721e48dd9f5a51f55baa Mon Sep 17 00:00:00 2001 From: Relintai Date: Wed, 28 Jun 2023 13:47:29 +0200 Subject: [PATCH] Ported from godot: move autotile fallback helper functions + fix comments and docs - wareya https://github.com/godotengine/godot/commit/a40ecc71e65eaf00895b4bd01db0495664be4274 --- modules/tile_map/doc_classes/TileSet.xml | 2 + modules/tile_map/tile_set.cpp | 52 ++++++++++++------------ modules/tile_map/tile_set.h | 3 ++ 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/modules/tile_map/doc_classes/TileSet.xml b/modules/tile_map/doc_classes/TileSet.xml index a1e5690f7..173edd2cb 100644 --- a/modules/tile_map/doc_classes/TileSet.xml +++ b/modules/tile_map/doc_classes/TileSet.xml @@ -505,8 +505,10 @@ + Autotiles will automatically find a best match for missing tiles if they're incomplete. + Autotiles will use the icon tile for missing tiles if they're incomplete. diff --git a/modules/tile_map/tile_set.cpp b/modules/tile_map/tile_set.cpp index e4159fc3e..e75261895 100644 --- a/modules/tile_map/tile_set.cpp +++ b/modules/tile_map/tile_set.cpp @@ -623,45 +623,46 @@ List TileSet::_autotile_get_subtile_candidates_for_bitmask(int p_id, ui return coords; } -uint32_t _count_bitmask_bits(uint32_t bitmask) { +uint32_t TileSet::_count_bitmask_bits(uint32_t p_bitmask) { uint32_t ret = 0; for (uint32_t i = 1; i <= 256; i <<= 1) { - if (bitmask & i) { + if (p_bitmask & i) { ret++; } } return ret; } -uint32_t _score_bitmask_difference(uint32_t bitmask, uint32_t ref_bitmask) { - // low = less difference, high = more difference +uint32_t TileSet::_score_bitmask_difference(uint32_t p_bitmask, uint32_t p_ref_bitmask) { + // Low value means less difference, high value means more difference. uint32_t ret = 0; - bitmask ^= ref_bitmask; - // add one to the score for each non-matching bit + p_bitmask ^= p_ref_bitmask; + // Add one to the score for each non-matching bit. for (uint32_t i = 1; i <= 256; i <<= 1) { - if (bitmask & i) { + if (p_bitmask & i) { ret += 1; - // make axial edge mismatches cost four times as much + // Make axial edge mismatches cost four times as much if (i & (TileSet::BIND_TOP | TileSet::BIND_LEFT | TileSet::BIND_RIGHT | TileSet::BIND_BOTTOM)) { ret += 3; } } } - bitmask ^= ref_bitmask; - // artificially reduce difference for all-filled and all-but-center-empty bitmasks + p_bitmask ^= p_ref_bitmask; + // Artificially reduce difference for all-filled and all-but-center-empty bitmasks // (511 is the non-IGNORE bitmasks all or'd together; 0x1FF) - if (ret > 0 && (bitmask == 511 || bitmask == TileSet::BIND_CENTER)) { + if (ret > 0 && (p_bitmask == 511 || p_bitmask == TileSet::BIND_CENTER)) { ret -= 1; } - // artificially increase difference for non-symmetric bitmasks if testing against all-filled or all-but-center-empty bitmask - // (need to cast the bit tests from int to bool before comparing) - if ((ref_bitmask == 511 || ref_bitmask == TileSet::BIND_CENTER) && - (bool(bitmask & TileSet::BIND_LEFT) != bool(bitmask & TileSet::BIND_RIGHT) || - bool(bitmask & TileSet::BIND_TOP) != bool(bitmask & TileSet::BIND_BOTTOM) || - bool(bitmask & TileSet::BIND_TOPRIGHT) != bool(bitmask & TileSet::BIND_BOTTOMLEFT) || - bool(bitmask & TileSet::BIND_TOPLEFT) != bool(bitmask & TileSet::BIND_BOTTOMRIGHT))) { + // Artificially increase difference for non-symmetric bitmasks if testing against all-filled or all-but-center-empty bitmask. + // This fixes some edge cases for certain common incomplete tilesheet layouts. + // (We only care about the truthiness of the bit tests, not their exact value, hence the bool casts.) + if ((p_ref_bitmask == 511 || p_ref_bitmask == TileSet::BIND_CENTER) && + (bool(p_bitmask & TileSet::BIND_LEFT) != bool(p_bitmask & TileSet::BIND_RIGHT) || + bool(p_bitmask & TileSet::BIND_TOP) != bool(p_bitmask & TileSet::BIND_BOTTOM) || + bool(p_bitmask & TileSet::BIND_TOPRIGHT) != bool(p_bitmask & TileSet::BIND_BOTTOMLEFT) || + bool(p_bitmask & TileSet::BIND_TOPLEFT) != bool(p_bitmask & TileSet::BIND_BOTTOMRIGHT))) { ret += 16; } return ret; @@ -681,13 +682,13 @@ Vector2 TileSet::autotile_get_subtile_for_bitmask(int p_id, uint16_t p_bitmask, } } - // if no forward-selected tile, look for a matching tile + // If we found no forward-selected tile, look for a matching tile. List coords = _autotile_get_subtile_candidates_for_bitmask(p_id, p_bitmask); - // if we didn't find anything, and auto fallback is enagled, try falling back to a tile with a similar bitmask instead of the default tile + // If we didn't find anything, and auto fallback is enabled, try falling back to a tile with a similar bitmask instead of the default tile. if (tile_map[p_id].autotile_data.fallback_mode == FALLBACK_AUTO && coords.size() == 0) { - uint32_t best_match_cost = 100000; // main point of comparison, general difference between bitmasks - uint32_t best_match_bitcount = 0; // bit count, as a tie breaker + uint32_t best_match_cost = 100000; // Main point of comparison, general difference between bitmasks. + uint32_t best_match_bitcount = 0; // Bit count, as a tie breaker. uint16_t best_match_bitmask = 0; for (RBMap::Element *E = tile_map[p_id].autotile_data.flags.front(); E; E = E->next()) { @@ -701,15 +702,16 @@ Vector2 TileSet::autotile_get_subtile_for_bitmask(int p_id, uint16_t p_bitmask, mask_low &= ~mask_ignore; mask_low |= p_bitmask & mask_ignore; - // always skip bitmasks with no center bit, or that have already been matched as the best + // Always skip bitmasks with no center bit, or that have already been matched as the best if ((mask_low & BIND_CENTER) == 0 || mask_low == best_match_bitmask) { continue; } uint32_t cost = _score_bitmask_difference(mask_low, p_bitmask); - uint32_t bitcount = _count_bitmask_bits(mask_low); // to break ties, pick the bitmask with more set bits + // To break ties, pick the bitmask with more set bits. + uint32_t bitcount = _count_bitmask_bits(mask_low); - // if more similar, confirm match + // If more similar, confirm match. if (cost < best_match_cost || (cost == best_match_cost && bitcount > best_match_bitcount)) { best_match_cost = cost; best_match_bitcount = bitcount; diff --git a/modules/tile_map/tile_set.h b/modules/tile_map/tile_set.h index 1923e6b8b..67882898a 100644 --- a/modules/tile_map/tile_set.h +++ b/modules/tile_map/tile_set.h @@ -157,6 +157,9 @@ protected: void _decompose_convex_shape(Ref p_shape); List _autotile_get_subtile_candidates_for_bitmask(int p_id, uint16_t p_bitmask) const; + uint32_t _count_bitmask_bits(uint32_t p_bitmask); + uint32_t _score_bitmask_difference(uint32_t p_bitmask, uint32_t p_ref_bitmask); + static void _bind_methods(); public: