You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
3.7 KiB
140 lines
3.7 KiB
|
3 weeks ago
|
extends PanelContainer
|
||
|
|
class_name AbilityButton
|
||
|
|
## Individual ability/action button for the action bar
|
||
|
|
## Shows icon, keybind, cooldown overlay, and tooltip
|
||
|
|
|
||
|
|
signal pressed()
|
||
|
|
signal hovered()
|
||
|
|
|
||
|
|
# References
|
||
|
|
@onready var icon: TextureRect = $MarginContainer/VBoxContainer/Icon
|
||
|
|
@onready var keybind_label: Label = $MarginContainer/VBoxContainer/KeybindLabel
|
||
|
|
@onready var cooldown_overlay: ColorRect = $MarginContainer/VBoxContainer/Icon/CooldownOverlay
|
||
|
|
@onready var cooldown_label: Label = $MarginContainer/VBoxContainer/Icon/CooldownLabel
|
||
|
|
|
||
|
|
# Data
|
||
|
|
var ability_icon: Texture2D = null
|
||
|
|
var keybind_text: String = ""
|
||
|
|
var ability_name: String = ""
|
||
|
|
var ability_description: String = ""
|
||
|
|
|
||
|
|
# Cooldown tracking
|
||
|
|
var is_on_cooldown: bool = false
|
||
|
|
var cooldown_remaining: float = 0.0
|
||
|
|
var cooldown_total: float = 0.0
|
||
|
|
|
||
|
|
# Colors
|
||
|
|
const COOLDOWN_COLOR = Color(0.0, 0.0, 0.0, 0.7) # Dark overlay during cooldown
|
||
|
|
const EMPTY_SLOT_COLOR = Color(0.3, 0.3, 0.3, 0.5) # Gray for empty slots
|
||
|
|
|
||
|
|
func _ready():
|
||
|
|
# Setup default appearance
|
||
|
|
cooldown_overlay.visible = false
|
||
|
|
cooldown_label.visible = false
|
||
|
|
|
||
|
|
# Connect mouse events for tooltip
|
||
|
|
mouse_entered.connect(_on_mouse_entered)
|
||
|
|
mouse_exited.connect(_on_mouse_exited)
|
||
|
|
|
||
|
|
_update_appearance()
|
||
|
|
|
||
|
|
func _process(delta):
|
||
|
|
if is_on_cooldown:
|
||
|
|
cooldown_remaining -= delta
|
||
|
|
if cooldown_remaining <= 0:
|
||
|
|
cooldown_remaining = 0
|
||
|
|
is_on_cooldown = false
|
||
|
|
_update_cooldown_display()
|
||
|
|
else:
|
||
|
|
_update_cooldown_display()
|
||
|
|
|
||
|
|
## Set the ability data
|
||
|
|
func set_ability(ability_texture: Texture2D, keybind: String, name: String = "", description: String = ""):
|
||
|
|
ability_icon = ability_texture
|
||
|
|
keybind_text = keybind
|
||
|
|
ability_name = name
|
||
|
|
ability_description = description
|
||
|
|
_update_appearance()
|
||
|
|
|
||
|
|
## Clear the ability (make slot empty)
|
||
|
|
func clear_ability():
|
||
|
|
ability_icon = null
|
||
|
|
ability_name = ""
|
||
|
|
ability_description = ""
|
||
|
|
_update_appearance()
|
||
|
|
|
||
|
|
## Set only the keybind (for empty slots)
|
||
|
|
func set_keybind(keybind: String):
|
||
|
|
keybind_text = keybind
|
||
|
|
_update_appearance()
|
||
|
|
|
||
|
|
## Start a cooldown animation
|
||
|
|
func start_cooldown(remaining: float, total: float = -1):
|
||
|
|
# If total is provided, use it; otherwise use remaining as both
|
||
|
|
if total > 0:
|
||
|
|
cooldown_total = total
|
||
|
|
else:
|
||
|
|
# Only set cooldown_total if we're starting a new cooldown
|
||
|
|
if not is_on_cooldown:
|
||
|
|
cooldown_total = remaining
|
||
|
|
|
||
|
|
is_on_cooldown = true
|
||
|
|
cooldown_remaining = remaining
|
||
|
|
_update_cooldown_display()
|
||
|
|
|
||
|
|
## Update visual appearance based on current state
|
||
|
|
func _update_appearance():
|
||
|
|
if not is_node_ready():
|
||
|
|
return
|
||
|
|
|
||
|
|
# Update icon
|
||
|
|
if ability_icon:
|
||
|
|
icon.texture = ability_icon
|
||
|
|
icon.modulate = Color.WHITE
|
||
|
|
else:
|
||
|
|
icon.texture = null
|
||
|
|
icon.modulate = EMPTY_SLOT_COLOR
|
||
|
|
|
||
|
|
# Update keybind label
|
||
|
|
if keybind_label:
|
||
|
|
keybind_label.text = keybind_text
|
||
|
|
|
||
|
|
## Update cooldown overlay and label
|
||
|
|
func _update_cooldown_display():
|
||
|
|
if not is_node_ready():
|
||
|
|
return
|
||
|
|
|
||
|
|
if is_on_cooldown:
|
||
|
|
cooldown_overlay.visible = true
|
||
|
|
cooldown_overlay.color = COOLDOWN_COLOR
|
||
|
|
|
||
|
|
# Show timer for cooldowns > 1 second
|
||
|
|
if cooldown_total > 1.0:
|
||
|
|
cooldown_label.visible = true
|
||
|
|
cooldown_label.text = str(ceil(cooldown_remaining))
|
||
|
|
else:
|
||
|
|
cooldown_label.visible = false
|
||
|
|
|
||
|
|
# Animate overlay height based on remaining cooldown
|
||
|
|
var percent_remaining = cooldown_remaining / cooldown_total
|
||
|
|
cooldown_overlay.size.y = icon.size.y * percent_remaining
|
||
|
|
else:
|
||
|
|
cooldown_overlay.visible = false
|
||
|
|
cooldown_label.visible = false
|
||
|
|
|
||
|
|
## Mouse hover handlers for tooltip
|
||
|
|
func _on_mouse_entered():
|
||
|
|
hovered.emit()
|
||
|
|
# Tooltip will be implemented later
|
||
|
|
|
||
|
|
func _on_mouse_exited():
|
||
|
|
# Hide tooltip
|
||
|
|
pass
|
||
|
|
|
||
|
|
## Handle button press
|
||
|
|
func _gui_input(event):
|
||
|
|
if event is InputEventMouseButton:
|
||
|
|
if event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
|
||
|
|
if not is_on_cooldown and ability_icon != null:
|
||
|
|
pressed.emit()
|