pokeapi_importer/editor/pokemon_importer.gd
2026-09-29 15:56:43 +02:00

126 lines
4.5 KiB
GDScript

# editor/pokemon_importer.gd
@tool
class_name PokeApiPokemonImporter
extends RefCounted
signal message(text : String)
var _client : PokeApiClient
var _fs : EditorFileSystem
var _overwrite : bool
var _languages : PackedStringArray
var _pending : Array = [] # pokémon récupérés, en attente de sauvegarde
func _init(client : PokeApiClient, fs : EditorFileSystem, overwrite : bool) -> void:
_client = client
_fs = fs
_overwrite = overwrite
_languages = PokeApiSettings.languages()
func run(tokens : Array) -> void:
DirAccess.make_dir_recursive_absolute(PokeApiSettings.pokemon_dir())
DirAccess.make_dir_recursive_absolute(PokeApiSettings.sprites_dir())
if !DirAccess.dir_exists_absolute(PokeApiSettings.moves_dir()):
message.emit("[color=orange]Aucune capacité importée : les learnsets seront vides.[/color]")
_pending.clear()
await _client.run_parallel(tokens, _fetch_pokemon) # phase 1 : téléchargement
await _save_all() # phase 2 : sprites + .tres
_pending.clear()
message.emit("Pokémon terminés.")
func _fetch_pokemon(token : Variant) -> void:
var j = await _client.get_json(PokeApiClient.API + "pokemon/" + str(token))
if j == null:
message.emit("[color=red]Introuvable : %s[/color]" % str(token))
return
var poke_name : String = j["name"]
var stem := PokeApiSettings.pokemon_stem(int(j["id"]), poke_name)
var path : String = PokeApiSettings.pokemon_dir() + stem + ".tres"
if !_overwrite and FileAccess.file_exists(path):
message.emit("Déjà présent : %s" % poke_name)
return
var species = await _client.get_json(j["species"]["url"])
var d := PokemonData.new()
d.id = j["id"]
d.api_name = poke_name
d.height = j["height"] / 10.0
d.weight = j["weight"] / 10.0
for t in j["types"]:
d.types.append(t["type"]["name"])
for a in j["abilities"]:
d.abilities.append(a["ability"]["name"])
for s in j["stats"]:
d.base_stats[s["stat"]["name"]] = s["base_stat"]
d.names = {"en": poke_name.capitalize()} # repli si l'espèce est indisponible
if species != null:
d.names = PokeApiText.names(species["names"], _languages)
d.descriptions = PokeApiText.flavors(species["flavor_text_entries"], _languages)
var sprites : Dictionary = j["sprites"]
var art : Dictionary = sprites.get("other", {}).get("official-artwork", {})
var sprite_url = art.get("front_default", sprites.get("front_default"))
var shiny_url = art.get("front_shiny", sprites.get("front_shiny"))
var dir := PokeApiSettings.sprites_dir()
_pending.append({
"data": d, "path": path, "moves": j["moves"],
"png": await _client.download_file(sprite_url, dir + stem + ".png"),
"shiny_png": await _client.download_file(shiny_url, dir + stem + "_shiny.png"),
})
func _save_all() -> void:
var pngs := PackedStringArray()
for p in _pending:
for key in ["png", "shiny_png"]:
if p[key] != "": pngs.append(p[key])
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 d : PokemonData = p["data"]
d.menu_sprite = _load_texture(p["png"])
d.shiny_menu_sprite = _load_texture(p["shiny_png"])
_link_models(d)
d.learnset = _build_learnset(p["moves"])
ResourceSaver.save(d, p["path"])
message.emit("OK : %s (%d capacités)" % [d.get_display_name(), d.learnset.size()])
_fs.scan()
func _load_texture(path : String) -> Texture2D:
if path.is_empty(): return null
return ResourceLoader.load(path, "Texture2D", ResourceLoader.CACHE_MODE_REPLACE) as Texture2D
func _link_models(d : PokemonData) -> void:
var dir := PokeApiSettings.models_dir()
if dir.is_empty(): return
var model_path := "%s/%s.glb" % [dir, d.api_name]
if ResourceLoader.exists(model_path):
d.model_scene = load(model_path) as PackedScene
var tex_path := "%s/%s_shiny.png" % [dir, d.api_name]
if ResourceLoader.exists(tex_path):
d.shiny_albedo = load(tex_path) as Texture2D
func _build_learnset(raw_moves : Array) -> Array[LearnedMove]:
var result : Array[LearnedMove] = []
for m in raw_moves:
var move_path : String = PokeApiSettings.moves_dir() + String(m["move"]["name"]) + ".tres"
if !FileAccess.file_exists(move_path): continue
var details : Array = m["version_group_details"]
var last : Dictionary = details[details.size() - 1] # jeu le plus récent
var lm := LearnedMove.new()
lm.move = load(move_path) as MoveData
lm.level = last["level_learned_at"]
lm.method = last["move_learn_method"]["name"]
result.append(lm)
result.sort_custom(func(a : LearnedMove, b : LearnedMove) -> bool: return a.level < b.level)
return result