Update debug_pokemon_panel.gd

This commit is contained in:
TheThomaas 2026-10-18 15:02:27 +02:00
parent e666c8a34d
commit ce4aa6b30e

View file

@ -1,21 +1,43 @@
extends CanvasLayer
# Autoload : DebugPokemonPanel
#panneau de test (build de debug uniquement) : liste des pokemon du Pokedex, un clic ajoute a l'equipe
#panneau de test (build de debug uniquement) :
# - onglet "Ajouter" : liste des pokemon du Pokedex, un clic ajoute a l'equipe
# - onglet "Capacites" : on choisit un pokemon de l'equipe, puis on remplace ses capacites
# par n'importe quelle capacite importee (recherche par nom, type, categorie ou statut)
enum Mode { ADD, MOVES }
const TOGGLE_ACTION : StringName = &"debug_pokemon_panel"
const DEFAULT_LEVEL : int = 10
var _root : Control
var _mode : Mode = Mode.ADD
var _message : Label
var _was_paused : bool = false
var _prev_mouse_mode : Input.MouseMode = Input.MOUSE_MODE_VISIBLE
#onglet "Ajouter"
var _add_view : Control
var _filter : LineEdit
var _level_spin : SpinBox
var _team_label : Label
var _scroll : ScrollContainer
var _list : VBoxContainer
var _message : Label
var _buttons : Array[Button] = []
var _populated : bool = false
var _was_paused : bool = false
var _prev_mouse_mode : Input.MouseMode = Input.MOUSE_MODE_VISIBLE
#onglet "Capacites"
var _moves_view : Control
var _moves_team_box : HFlowContainer
var _slots_box : VBoxContainer
var _picker_box : VBoxContainer
var _picker_title : Label
var _move_filter : LineEdit
var _move_list : VBoxContainer
var _move_buttons : Array[Button] = []
var _moves_populated : bool = false
var _edit_pokemon : PokemonInstance = null
var _edit_slot : int = -1
func _ready() -> void:
if !OS.is_debug_build():
@ -44,13 +66,15 @@ func _unhandled_input(event : InputEvent) -> void:
else: _open()
get_viewport().set_input_as_handled()
elif _root.visible and event.is_action_pressed(&"ui_cancel"):
_close()
#Echap / B : ferme d'abord la liste des capacites, puis le panneau
if _mode == Mode.MOVES and _picker_box.visible: _close_picker()
else: _close()
get_viewport().set_input_as_handled()
#---------- ouverture / fermeture ----------
func _open() -> void:
if !_populated: _populate()
if _mode == Mode.ADD and !_populated: _populate()
_was_paused = get_tree().paused
_prev_mouse_mode = Input.mouse_mode
get_tree().paused = true
@ -58,6 +82,7 @@ func _open() -> void:
_root.visible = true
_message.text = ""
_refresh_team()
if _mode == Mode.MOVES: _refresh_moves_team()
_focus_first.call_deferred()
func _close() -> void:
@ -66,10 +91,29 @@ func _close() -> void:
Input.mouse_mode = _prev_mouse_mode
func _focus_first() -> void:
for b in _buttons:
if b.is_visible_in_tree():
b.grab_focus()
return
if _mode == Mode.ADD:
for b in _buttons:
if b.is_visible_in_tree():
b.grab_focus()
return
else:
for child in _moves_team_box.get_children():
if child is Button:
child.grab_focus()
return
func _set_mode(mode : Mode) -> void:
_mode = mode
_add_view.visible = mode == Mode.ADD
_moves_view.visible = mode == Mode.MOVES
_message.text = ""
if mode == Mode.ADD:
if !_populated: _populate()
_refresh_team()
else:
_close_picker()
_refresh_moves_team()
_focus_first.call_deferred()
#---------- interface ----------
@ -88,7 +132,7 @@ func _build_ui() -> void:
_root.add_child(center)
var panel := PanelContainer.new()
panel.custom_minimum_size = Vector2(580, 640)
panel.custom_minimum_size = Vector2(620, 680)
center.add_child(panel)
var margin := MarginContainer.new()
@ -101,12 +145,64 @@ func _build_ui() -> void:
margin.add_child(box)
var title := Label.new()
title.text = "Debug : ajouter un Pokémon à l'équipe"
title.text = "Debug : Pokémon"
title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
box.add_child(title)
#onglets
var tabs := HBoxContainer.new()
tabs.add_theme_constant_override("separation", 8)
box.add_child(tabs)
var group := ButtonGroup.new()
tabs.add_child(_make_tab_button("Ajouter un Pokémon", Mode.ADD, group, true))
tabs.add_child(_make_tab_button("Modifier les capacités", Mode.MOVES, group, false))
_build_add_view(box)
_build_moves_view(box)
_message = Label.new()
_message.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
box.add_child(_message)
var actions := HBoxContainer.new()
actions.add_theme_constant_override("separation", 8)
box.add_child(actions)
actions.add_child(_make_action_button("Soigner l'équipe", _on_heal_pressed))
actions.add_child(_make_action_button("Vider l'équipe", _on_clear_pressed))
actions.add_child(_make_action_button("Fermer", _close))
var hint := Label.new()
hint.text = "F3 / Select : ouvrir-fermer | Échap / B : retour, puis fermer"
hint.modulate = Color(1.0, 1.0, 1.0, 0.5)
hint.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
box.add_child(hint)
func _make_tab_button(label : String, mode : Mode, group : ButtonGroup, pressed : bool) -> Button:
var button := Button.new()
button.text = label
button.toggle_mode = true
button.button_group = group
button.button_pressed = pressed
button.size_flags_horizontal = Control.SIZE_EXPAND_FILL
button.pressed.connect(_set_mode.bind(mode))
return button
func _make_action_button(label : String, callback : Callable) -> Button:
var button := Button.new()
button.text = label
button.size_flags_horizontal = Control.SIZE_EXPAND_FILL
button.pressed.connect(callback)
return button
func _build_add_view(parent : Control) -> void:
var view := VBoxContainer.new()
view.size_flags_vertical = Control.SIZE_EXPAND_FILL
view.add_theme_constant_override("separation", 8)
parent.add_child(view)
_add_view = view
var level_row := HBoxContainer.new()
box.add_child(level_row)
view.add_child(level_row)
var level_label := Label.new()
level_label.text = "Niveau"
level_row.add_child(level_label)
@ -125,40 +221,68 @@ func _build_ui() -> void:
_team_label = Label.new()
_team_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
box.add_child(_team_label)
view.add_child(_team_label)
_scroll = ScrollContainer.new()
_scroll.size_flags_vertical = Control.SIZE_EXPAND_FILL
_scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED
_scroll.follow_focus = true
box.add_child(_scroll)
view.add_child(_scroll)
_list = VBoxContainer.new()
_list.size_flags_horizontal = Control.SIZE_EXPAND_FILL
_scroll.add_child(_list)
_message = Label.new()
box.add_child(_message)
var actions := HBoxContainer.new()
actions.add_theme_constant_override("separation", 8)
box.add_child(actions)
actions.add_child(_make_action_button("Soigner l'équipe", _on_heal_pressed))
actions.add_child(_make_action_button("Vider l'équipe", _on_clear_pressed))
actions.add_child(_make_action_button("Fermer", _close))
var hint := Label.new()
hint.text = "F3 / Select : ouvrir-fermer | Échap / B : fermer"
hint.modulate = Color(1.0, 1.0, 1.0, 0.5)
hint.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
box.add_child(hint)
func _make_action_button(label : String, callback : Callable) -> Button:
var button := Button.new()
button.text = label
button.size_flags_horizontal = Control.SIZE_EXPAND_FILL
button.pressed.connect(callback)
return button
func _build_moves_view(parent : Control) -> void:
var view := VBoxContainer.new()
view.size_flags_vertical = Control.SIZE_EXPAND_FILL
view.add_theme_constant_override("separation", 8)
view.visible = false
parent.add_child(view)
_moves_view = view
var team_title := Label.new()
team_title.text = "Pokémon à modifier"
view.add_child(team_title)
_moves_team_box = HFlowContainer.new()
view.add_child(_moves_team_box)
var slots_title := Label.new()
slots_title.text = "Capacités : clique sur un emplacement pour le remplacer"
view.add_child(slots_title)
_slots_box = VBoxContainer.new()
view.add_child(_slots_box)
#liste de toutes les capacites (affichee quand un emplacement est choisi)
_picker_box = VBoxContainer.new()
_picker_box.size_flags_vertical = Control.SIZE_EXPAND_FILL
_picker_box.add_theme_constant_override("separation", 6)
_picker_box.visible = false
view.add_child(_picker_box)
_picker_title = Label.new()
_picker_box.add_child(_picker_title)
var search_row := HBoxContainer.new()
_picker_box.add_child(search_row)
_move_filter = LineEdit.new()
_move_filter.placeholder_text = "Rechercher (nom, type, physical/special/status, statut)..."
_move_filter.clear_button_enabled = true
_move_filter.size_flags_horizontal = Control.SIZE_EXPAND_FILL
_move_filter.text_changed.connect(_on_move_filter_changed)
search_row.add_child(_move_filter)
search_row.add_child(_make_action_button("Retirer cette capacité", _on_remove_move_pressed))
var move_scroll := ScrollContainer.new()
move_scroll.size_flags_vertical = Control.SIZE_EXPAND_FILL
move_scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED
move_scroll.follow_focus = true
_picker_box.add_child(move_scroll)
_move_list = VBoxContainer.new()
_move_list.size_flags_horizontal = Control.SIZE_EXPAND_FILL
move_scroll.add_child(_move_list)
#---------- onglet "Ajouter" ----------
func _populate() -> void:
_populated = true
@ -181,8 +305,6 @@ func _populate() -> void:
if _buttons.is_empty():
_message.text = "Aucun Pokémon dans le Pokedex."
#---------- actions ----------
func _on_pokemon_pressed(data : PokemonData) -> void:
var team : PokemonTeam = GameData.player_team
if team.is_full():
@ -194,18 +316,6 @@ func _on_pokemon_pressed(data : PokemonData) -> void:
_message.text = "%s Lv.%d ajouté (%d/%d)" % [pokemon.get_display_name(), pokemon.level, team.size(), PokemonTeam.MAX_SIZE]
_refresh_team()
func _on_clear_pressed() -> void:
var team : PokemonTeam = GameData.player_team
while !team.is_empty():
team.remove_at(team.size() - 1)
GameData.validate_selection()
_message.text = "Équipe vidée"
_refresh_team()
func _on_heal_pressed() -> void:
GameData.player_team.heal_all()
_message.text = "Équipe soignée"
func _on_filter_changed(text : String) -> void:
var needle : String = text.strip_edges().to_lower()
for b in _buttons:
@ -220,3 +330,148 @@ func _refresh_team() -> void:
for p in team.members:
names.append("%s Lv.%d" % [p.get_display_name(), p.level])
_team_label.text = "Équipe (%d/%d) : %s" % [team.size(), PokemonTeam.MAX_SIZE, ", ".join(names)]
#---------- onglet "Capacites" ----------
func _refresh_moves_team() -> void:
for child in _moves_team_box.get_children():
_moves_team_box.remove_child(child)
child.queue_free()
var team : PokemonTeam = GameData.player_team
if !team.members.has(_edit_pokemon):
_edit_pokemon = team.members[0] if !team.is_empty() else null
var group := ButtonGroup.new()
for p in team.members:
var button := Button.new()
button.text = "%s Lv.%d" % [p.get_display_name(), p.level]
button.toggle_mode = true
button.button_group = group
button.button_pressed = p == _edit_pokemon
button.pressed.connect(_select_pokemon.bind(p))
_moves_team_box.add_child(button)
if team.is_empty():
var empty := Label.new()
empty.text = "L'équipe est vide : ajoute d'abord un Pokémon (onglet « Ajouter »)."
_moves_team_box.add_child(empty)
_refresh_slots()
func _select_pokemon(pokemon : PokemonInstance) -> void:
_edit_pokemon = pokemon
_close_picker()
_refresh_slots()
func _refresh_slots() -> void:
for child in _slots_box.get_children():
_slots_box.remove_child(child)
child.queue_free()
if _edit_pokemon == null: return
for i in PokemonInstance.MAX_ACTIVE_MOVES:
var button := Button.new()
button.alignment = HORIZONTAL_ALIGNMENT_LEFT
var prefix : String = "▶ " if i == _edit_slot else ""
if i < _edit_pokemon.active_moves.size():
var ms : MoveSlot = _edit_pokemon.active_moves[i]
button.text = "%s%d. %s PP %d/%d" % [prefix, i + 1, ms.move.get_display_name(), ms.current_pp, ms.max_pp]
else:
button.text = "%s%d. (vide)" % [prefix, i + 1]
button.pressed.connect(_on_slot_pressed.bind(i))
_slots_box.add_child(button)
func _on_slot_pressed(index : int) -> void:
if _edit_pokemon == null: return
_edit_slot = index
_picker_title.text = "Capacité n°%d de %s : choisis un remplacement" % [index + 1, _edit_pokemon.get_display_name()]
_picker_box.visible = true
_refresh_slots()
if !_moves_populated: await _populate_moves()
_move_filter.text = ""
_on_move_filter_changed("")
_focus_first_move.call_deferred()
func _close_picker() -> void:
_edit_slot = -1
if _picker_box != null: _picker_box.visible = false
if _slots_box != null: _refresh_slots()
func _populate_moves() -> void:
#charge toutes les capacites importees (une seule fois) ; "Pokedex" les garde ensuite en cache
_moves_populated = true
var names : PackedStringArray = PackedStringArray()
for file in ResourceLoader.list_directory(PokeApiSettings.moves_dir()):
if file.ends_with(".tres"): names.append(file.get_basename())
names.sort()
var loaded : int = 0
for move_name in names:
var move : MoveData = Pokedex.get_move(move_name)
if move == null: continue
var power_text : String = str(move.power) if move.power > 0 else "-"
var button := Button.new()
button.alignment = HORIZONTAL_ALIGNMENT_LEFT
button.text = "%s [%s · %s · puiss. %s]" % [move.get_display_name(), move.type, move.category, power_text]
button.set_meta("search", ("%s %s %s %s %s" % [move_name, move.get_display_name(), move.type, move.category, move.ailment]).to_lower())
button.pressed.connect(_on_move_pressed.bind(move))
_move_list.add_child(button)
_move_buttons.append(button)
loaded += 1
if loaded % 40 == 0:
_message.text = "Chargement des capacités... %d/%d" % [loaded, names.size()]
await get_tree().process_frame
_message.text = "%d capacités disponibles." % loaded
if loaded == 0:
_message.text = "Aucune capacité trouvée : importe d'abord les capacités avec le plugin."
func _on_move_filter_changed(text : String) -> void:
var needle : String = text.strip_edges().to_lower()
for b in _move_buttons:
b.visible = needle == "" or needle in String(b.get_meta("search"))
func _focus_first_move() -> void:
for b in _move_buttons:
if b.is_visible_in_tree():
b.grab_focus()
return
func _on_move_pressed(move : MoveData) -> void:
if _edit_pokemon == null or _edit_slot < 0: return
var pokemon : PokemonInstance = _edit_pokemon
#la capacite devient aussi "apprise" (coherence avec le reste du jeu)
if !pokemon.learned_moves.has(move): pokemon.learned_moves.append(move)
var move_slot := MoveSlot.new(move)
if _edit_slot < pokemon.active_moves.size():
pokemon.active_moves[_edit_slot] = move_slot
else:
pokemon.active_moves.append(move_slot)
_message.text = "%s : %s en position %d" % [pokemon.get_display_name(), move.get_display_name(), _edit_slot + 1]
_close_picker()
func _on_remove_move_pressed() -> void:
if _edit_pokemon == null or _edit_slot < 0: return
if _edit_slot < _edit_pokemon.active_moves.size():
_edit_pokemon.active_moves.remove_at(_edit_slot)
_message.text = "Capacité n°%d retirée" % (_edit_slot + 1)
_close_picker()
#---------- actions communes ----------
func _on_clear_pressed() -> void:
var team : PokemonTeam = GameData.player_team
while !team.is_empty():
team.remove_at(team.size() - 1)
GameData.validate_selection()
_message.text = "Équipe vidée"
_refresh_team()
if _mode == Mode.MOVES: _refresh_moves_team()
func _on_heal_pressed() -> void:
GameData.player_team.heal_all() #rend aussi tous les PP
_message.text = "Équipe soignée (PV et PP)"
if _mode == Mode.MOVES: _refresh_slots()