210 lines
6.5 KiB
GDScript
210 lines
6.5 KiB
GDScript
# SkillPanel.gd
|
|
# Zeigt alle verfügbaren Fähigkeiten an, von hier aus auf Aktionsleiste ziehen
|
|
extends CanvasLayer
|
|
|
|
var panel_visible = false
|
|
var player = null
|
|
|
|
# Pagination
|
|
const SKILLS_PER_PAGE: int = 9
|
|
var current_page: int = 0
|
|
var _page_label: Label = null
|
|
var _prev_btn: Button = null
|
|
var _next_btn: Button = null
|
|
|
|
# Drag State
|
|
var dragging = false
|
|
var drag_skill_id: String = ""
|
|
var drag_icon: TextureRect = null
|
|
|
|
@onready var panel = $Panel
|
|
@onready var skill_list = $Panel/VBoxContainer/ScrollContainer/SkillList
|
|
|
|
func _ready():
|
|
panel.visible = false
|
|
_create_pagination_bar()
|
|
|
|
func _create_pagination_bar():
|
|
var vbox = $Panel/VBoxContainer
|
|
var nav = HBoxContainer.new()
|
|
nav.alignment = BoxContainer.ALIGNMENT_CENTER
|
|
nav.add_theme_constant_override("separation", 12)
|
|
|
|
_prev_btn = Button.new()
|
|
_prev_btn.text = "< Zurück"
|
|
_prev_btn.add_theme_font_size_override("font_size", 13)
|
|
_prev_btn.pressed.connect(_on_prev_page)
|
|
nav.add_child(_prev_btn)
|
|
|
|
_page_label = Label.new()
|
|
_page_label.add_theme_font_size_override("font_size", 13)
|
|
_page_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
_page_label.custom_minimum_size = Vector2(80, 0)
|
|
nav.add_child(_page_label)
|
|
|
|
_next_btn = Button.new()
|
|
_next_btn.text = "Weiter >"
|
|
_next_btn.add_theme_font_size_override("font_size", 13)
|
|
_next_btn.pressed.connect(_on_next_page)
|
|
nav.add_child(_next_btn)
|
|
|
|
vbox.add_child(nav)
|
|
|
|
func _on_prev_page():
|
|
current_page = max(0, current_page - 1)
|
|
_refresh_skills()
|
|
|
|
func _on_next_page():
|
|
var total_pages = _get_total_pages()
|
|
current_page = min(total_pages - 1, current_page + 1)
|
|
_refresh_skills()
|
|
|
|
func _get_total_pages() -> int:
|
|
if player == null:
|
|
return 1
|
|
return max(1, ceili(float(player.available_skills.size()) / SKILLS_PER_PAGE))
|
|
|
|
func setup(p):
|
|
player = p
|
|
|
|
func toggle():
|
|
panel_visible = !panel_visible
|
|
panel.visible = panel_visible
|
|
if panel_visible:
|
|
current_page = 0
|
|
_refresh_skills()
|
|
|
|
func _refresh_skills():
|
|
if player == null:
|
|
return
|
|
|
|
for child in skill_list.get_children():
|
|
child.queue_free()
|
|
|
|
# Pagination-Grenzen berechnen
|
|
var total_pages = _get_total_pages()
|
|
var start = current_page * SKILLS_PER_PAGE
|
|
var end = min(start + SKILLS_PER_PAGE, player.available_skills.size())
|
|
var page_skills = player.available_skills.slice(start, end)
|
|
|
|
# Navigations-Buttons und Label aktualisieren
|
|
_page_label.text = "Seite %d / %d" % [current_page + 1, total_pages]
|
|
_prev_btn.disabled = current_page == 0
|
|
_next_btn.disabled = current_page >= total_pages - 1
|
|
|
|
for skill in page_skills:
|
|
var is_locked: bool = skill.get("locked", false)
|
|
|
|
# Hintergrund-Panel für Lesbarkeit
|
|
var panel = PanelContainer.new()
|
|
var style = StyleBoxFlat.new()
|
|
style.bg_color = Color(0.9, 0.85, 0.75, 0.18) if not is_locked else Color(0.3, 0.3, 0.3, 0.15)
|
|
style.set_corner_radius_all(4)
|
|
panel.add_theme_stylebox_override("panel", style)
|
|
panel.mouse_filter = Control.MOUSE_FILTER_STOP
|
|
|
|
var hbox = HBoxContainer.new()
|
|
hbox.add_theme_constant_override("separation", 8)
|
|
hbox.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
panel.add_child(hbox)
|
|
|
|
# Icon
|
|
var icon_rect = TextureRect.new()
|
|
var tex = load(skill["icon"])
|
|
if tex:
|
|
icon_rect.texture = tex
|
|
icon_rect.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
|
icon_rect.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
|
|
icon_rect.custom_minimum_size = Vector2(36, 36)
|
|
icon_rect.size = Vector2(36, 36)
|
|
icon_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
if is_locked:
|
|
icon_rect.modulate = Color(1, 1, 1, 0.35)
|
|
hbox.add_child(icon_rect)
|
|
|
|
# Name + Level-Anforderung
|
|
var vbox = VBoxContainer.new()
|
|
vbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
vbox.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
hbox.add_child(vbox)
|
|
|
|
var label = Label.new()
|
|
label.text = skill["name"]
|
|
label.add_theme_font_size_override("font_size", 14)
|
|
label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
if is_locked:
|
|
label.modulate = Color(0.55, 0.55, 0.55, 1.0)
|
|
vbox.add_child(label)
|
|
|
|
if is_locked:
|
|
var req_label = Label.new()
|
|
req_label.text = "Benötigt Level %d" % skill.get("level_required", 0)
|
|
req_label.add_theme_font_size_override("font_size", 10)
|
|
req_label.modulate = Color(0.6, 0.45, 0.3, 1.0)
|
|
req_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
vbox.add_child(req_label)
|
|
|
|
# Tooltip
|
|
panel.tooltip_text = skill["name"] + "\n" + skill["description"]
|
|
if is_locked:
|
|
panel.tooltip_text += "\n\n[Gesperrt bis Level %d]" % skill.get("level_required", 0)
|
|
|
|
# Drag nur bei freigeschalteten Skills
|
|
if not is_locked:
|
|
var skill_id = skill["id"]
|
|
var skill_icon_path = skill["icon"]
|
|
panel.gui_input.connect(_on_skill_input.bind(skill_id, skill_icon_path))
|
|
|
|
skill_list.add_child(panel)
|
|
|
|
func _on_skill_input(event: InputEvent, skill_id: String, icon_path: String):
|
|
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
|
|
_start_drag(skill_id, icon_path)
|
|
|
|
func _start_drag(skill_id: String, icon_path: String):
|
|
dragging = true
|
|
drag_skill_id = skill_id
|
|
var tex = load(icon_path)
|
|
drag_icon = TextureRect.new()
|
|
drag_icon.texture = tex
|
|
drag_icon.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
|
drag_icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
|
|
drag_icon.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
var drag_layer = CanvasLayer.new()
|
|
drag_layer.name = "DragLayer"
|
|
drag_layer.layer = 200
|
|
drag_layer.add_child(drag_icon)
|
|
get_tree().root.add_child(drag_layer)
|
|
# Größe erst nach add_child setzen, sonst überschreibt Godot sie
|
|
drag_icon.custom_minimum_size = Vector2(48, 48)
|
|
drag_icon.size = Vector2(48, 48)
|
|
drag_icon.position = get_viewport().get_mouse_position() - Vector2(24, 24)
|
|
if player and player.hud:
|
|
player.hud.set_drag_active(true)
|
|
|
|
func _process(_delta):
|
|
if dragging and drag_icon:
|
|
drag_icon.position = get_viewport().get_mouse_position() - Vector2(20, 20)
|
|
if player and player.hud:
|
|
player.hud.update_drag_hover(get_viewport().get_mouse_position())
|
|
|
|
func _input(event):
|
|
if not dragging:
|
|
return
|
|
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and not event.pressed:
|
|
_end_drag()
|
|
|
|
func _end_drag():
|
|
if not dragging:
|
|
return
|
|
if player and player.hud:
|
|
var slot_index = player.hud.get_slot_at_position(get_viewport().get_mouse_position())
|
|
if slot_index >= 0 and slot_index <= 8 and drag_skill_id != "":
|
|
player.assign_skill_to_action_bar(slot_index, drag_skill_id)
|
|
player.hud.set_drag_active(false)
|
|
if drag_icon:
|
|
var drag_layer = drag_icon.get_parent()
|
|
drag_layer.queue_free()
|
|
drag_icon = null
|
|
dragging = false
|
|
drag_skill_id = ""
|