# editor/item_importer.gd @tool class_name PokeApiItemImporter extends RefCounted signal message(text : String) var _client : PokeApiClient var _fs : EditorFileSystem var _overwrite : bool var _languages : PackedStringArray var _pending : Array = [] # objets récupérés, en attente de sauvegarde des sprites func _init(client : PokeApiClient, fs : EditorFileSystem, overwrite : bool) -> void: _client = client _fs = fs _overwrite = overwrite _languages = PokeApiSettings.languages() ## Retourne un tableau de {"name": String, "count": int}, trié par nom. func list_categories() -> Array: var list = await _client.get_json(PokeApiClient.API + "item-category?limit=100") if list == null: return [] var names : Array = [] for r in PokeApiJson.get_array(list, "results"): names.append(PokeApiJson.get_str(r, "name")) var counts : Dictionary = {} # nom -> count, rempli par les tâches parallèles await _client.run_parallel(names, func(cat_name : String) -> void: var cat = await _client.get_json(PokeApiClient.API + "item-category/" + cat_name) counts[cat_name] = PokeApiJson.get_array(cat, "items").size() if cat != null else 0) names.sort() var out : Array = [] for cat_name in names: out.append({"name": cat_name, "count": counts.get(cat_name, 0)}) return out func run(category_names : Array) -> void: DirAccess.make_dir_recursive_absolute(PokeApiSettings.items_dir()) _pending.clear() var entries : Array = [] for cat_name in category_names: var cat = await _client.get_json(PokeApiClient.API + "item-category/" + cat_name) if cat == null: message.emit("[color=red]Catégorie introuvable : %s[/color]" % cat_name) continue for r in cat["items"]: entries.append(r) if entries.is_empty(): message.emit("Rien à importer.") return message.emit("%d objets à traiter..." % entries.size()) await _client.run_parallel(entries, _fetch_item) await _save_all() _pending.clear() message.emit("Objets terminés.") func _fetch_item(entry : Dictionary) -> void: var path : String = PokeApiSettings.items_dir() + entry["name"] + ".tres" if !_overwrite and FileAccess.file_exists(path): return var j = await _client.get_json(entry["url"]) if j == null: message.emit("[color=red]Échec : %s[/color]" % entry["name"]) return var it := ItemData.new() it.id = PokeApiJson.get_int(j, "id") it.api_name = PokeApiJson.get_str(j, "name", entry["name"]) it.category = PokeApiJson.get_dict_name(j, "category") it.names = PokeApiText.names(PokeApiJson.get_array(j, "names"), _languages) it.descriptions = PokeApiText.item_flavors(PokeApiJson.get_array(j, "flavor_text_entries"), _languages) it.cost = PokeApiJson.get_int(j, "cost") it.fling_power = PokeApiJson.get_int(j, "fling_power") var sprite_url := PokeApiJson.get_str(PokeApiJson.get_dict(j, "sprites"), "default") var png_path := await _client.download_file(sprite_url if sprite_url != "" else null, PokeApiSettings.items_dir() + it.api_name + ".png") _pending.append({"data": it, "path": path, "png": png_path}) func _save_all() -> void: if _pending.is_empty(): message.emit("[color=orange]Rien à sauvegarder : tous les objets ont été ignorés ou ont échoué.[/color]") return var pngs := PackedStringArray() for p in _pending: if p["png"] != "": pngs.append(p["png"]) if !pngs.is_empty(): _fs.scan() while _fs.is_scanning(): await _client.get_tree().process_frame _fs.reimport_files(pngs) for p in _pending: var it : ItemData = p["data"] if p["png"] != "": it.sprite = ResourceLoader.load(p["png"], "Texture2D", ResourceLoader.CACHE_MODE_REPLACE) var err := ResourceSaver.save(it, p["path"]) if err != OK: message.emit("[color=red]Échec de sauvegarde : %s (code %d)[/color]" % [it.api_name, err]) _fs.scan()