extends SceneTree const TILESET_PATH: String = "res://assets/maps/work_zone/v13/tilesets/work_zone_road_tileset.tres" const TEXTURE_DIR: String = "res://assets/maps/work_zone/v13/tilesets" func _init() -> void: var tileset := load(TILESET_PATH) as TileSet if tileset == null: push_error("无法加载 TileSet: %s" % TILESET_PATH) quit(1) return var candidates := _load_candidates() var replaced := 0 for source_index in tileset.get_source_count(): var source_id := tileset.get_source_id(source_index) var atlas_source := tileset.get_source(source_id) as TileSetAtlasSource if atlas_source == null or atlas_source.texture == null: continue var source_hash := _texture_hash(atlas_source.texture) var replacement: Texture2D = candidates.get(source_hash) if replacement == null: _write_audit_image(source_id, atlas_source.texture) push_error("未找到匹配的外置纹理,source=%d hash=%s" % [source_id, source_hash]) quit(2) return atlas_source.texture = replacement replaced += 1 var error := ResourceSaver.save(tileset, TILESET_PATH) if error != OK: push_error("保存 TileSet 失败: %s" % error_string(error)) quit(3) return print("已外置 %d 个 TileSet 纹理源" % replaced) quit() func _load_candidates() -> Dictionary: var candidates: Dictionary = {} for file_name in DirAccess.get_files_at(TEXTURE_DIR): if not file_name.ends_with(".png"): continue var path := "%s/%s" % [TEXTURE_DIR, file_name] var texture := load(path) as Texture2D if texture != null: candidates[_bytes_hash(FileAccess.get_file_as_bytes(path))] = texture return candidates func _texture_hash(texture: Texture2D) -> String: var image := texture.get_image() if image == null: return "" return _bytes_hash(image.save_png_to_buffer()) func _bytes_hash(bytes: PackedByteArray) -> String: var context := HashingContext.new() var start_error := context.start(HashingContext.HASH_SHA256) if start_error != OK: return "" var update_error := context.update(bytes) if update_error != OK: return "" return context.finish().hex_encode() func _write_audit_image(source_id: int, texture: Texture2D) -> void: var directory := ProjectSettings.globalize_path("res://build/tileset-audit") DirAccess.make_dir_recursive_absolute(directory) var image := texture.get_image() if image == null: return var path := "%s/source_%d.png" % [directory, source_id] var error := image.save_png(path) if error == OK: print("已写出待核对纹理: %s (%dx%d)" % [path, image.get_width(), image.get_height()])