diff --git a/src/game/engine/src/autoloads/theme_assets.gd b/src/game/engine/src/autoloads/theme_assets.gd index b3175647..8f3351f6 100644 --- a/src/game/engine/src/autoloads/theme_assets.gd +++ b/src/game/engine/src/autoloads/theme_assets.gd @@ -43,7 +43,14 @@ func resolve(relative_path: String) -> String: return "%s/%s" % [_base_path, relative_path] -func load_sprite(relative_path: String) -> Texture2D: +func load_sprite(relative_path: String, warn_on_miss: bool = true) -> Texture2D: + ## `warn_on_miss` defaults to true so genuinely-required assets (terrain, + ## city, resource, UI sprites with no procedural backstop) still surface a + ## warning. Callers that probe a *speculative* path with a guaranteed + ## fallback — e.g. the unit renderer's race×sex variant + generic lookup, + ## which always backstops via the ProceduralRenderer — pass false to avoid + ## noise on expected misses. Authored-sprite coverage is enforced by + ## `test_standin_sprite_coverage.gd`, not by this runtime warning. var full_path: String = resolve(relative_path) if full_path.is_empty(): return null @@ -92,7 +99,7 @@ func load_sprite(relative_path: String) -> Texture2D: # Cache both positive and negative results to avoid repeated I/O _texture_cache[full_path] = texture - if texture == null: + if texture == null and warn_on_miss: push_warning("ThemeAssets: FAILED to load '%s'" % full_path) return texture diff --git a/src/game/engine/src/rendering/unit_renderer_draw.gd b/src/game/engine/src/rendering/unit_renderer_draw.gd index 97387708..f6a93a9c 100644 --- a/src/game/engine/src/rendering/unit_renderer_draw.gd +++ b/src/game/engine/src/rendering/unit_renderer_draw.gd @@ -174,13 +174,17 @@ static func cache_unit_sprites( var pr_force: Node = _get_procedural_renderer() if pr_force != null and pr_force.call("is_force_procedural"): return + # Both lookups are speculative: get_unit_sprite() backstops any miss via the + # ProceduralRenderer, so an absent authored PNG is by-design, not an error. + # Pass warn_on_miss=false to keep the log clean; authored coverage is gated + # by test_standin_sprite_coverage.gd, not this runtime warning. if race_id != "" and sex != "": var variant_path: String = race_sex_fmt % [type_id, race_id, sex] if not cache.has(variant_path): - cache[variant_path] = ThemeAssets.load_sprite(variant_path) + cache[variant_path] = ThemeAssets.load_sprite(variant_path, false) var generic_path: String = generic_fmt % type_id if not cache.has(generic_path): - cache[generic_path] = ThemeAssets.load_sprite(generic_path) + cache[generic_path] = ThemeAssets.load_sprite(generic_path, false) ## Return best available sprite from cache: race/sex variant first, generic