using Cthangover.Mods.Interface.Base.Lists; using Cthangover.Core.UI.Theming; using Godot; using Cthangover.Mods.Interface.Theming; namespace Cthangover.Mods.Skills { /// /// Grid card of one collected skill. Pure presentation: the panel binds a /// through and toggles /// selection through , while every colour comes /// from so the same rarity reads identically on /// the card, the study plate and the rarity filter tabs. /// /// Clicking is intentionally not handled here: the panel subscribes to /// GuiInput, so the card keeps a single responsibility and can be /// hosted by any list without knowing its owner. Hover is handled inside /// because it only repaints the card itself. /// public partial class SkillCardBehaviour : ListItem { [Export] private Panel bg; [Export] private Panel accent; [Export] private PanelContainer art; [Export] private TextureRect imgCard; [Export] private Label txtName; [Export] private Label txtGems; [Export] private PanelContainer badgeBox; [Export] private Label badgeLabel; [Export] private HBoxContainer effectRow; [Export] private Label effectValue; [Export] private Label effectLabel; private bool _selected; private bool _hover; /// Configures the card to accept mouse input for hover/selection feedback. public override void _Ready() { MouseFilter = MouseFilterEnum.Stop; MouseEntered += OnMouseEntered; MouseExited += OnMouseExited; } /// /// Binds the skill definition to the card: artwork, translated name, /// rarity gems (one diamond per tier), the type badge and the first /// numeric effect as the card's short line. Skills without effects hide /// the effect row instead of leaving an empty band; a skill without /// artwork keeps the empty well, which is a valid authored state. /// public override void Construct(SkillInfo skillInfo) { base.Construct(skillInfo); ResolveNodes(); if (art != null) art.AddThemeStyleboxOverride("panel", UiKit.Frame(UiTokens.RadiusSm, UiTokens.Well, UiTokens.Line)); if (skillInfo == null) return; if (imgCard != null) imgCard.Texture = skillInfo.Sprite; if (txtName != null) { txtName.Text = TranslationServer.Translate(skillInfo.Name); txtName.AddThemeFontSizeOverride("font_size", UiTokens.FontBodySmall); txtName.AddThemeColorOverride("font_color", UiTokens.InkBright); } if (txtGems != null) { txtGems.Text = new string('◆', Mathf.Clamp((int)skillInfo.RareType + 1, 1, 5)); txtGems.AddThemeFontSizeOverride("font_size", UiTokens.FontMicro); txtGems.AddThemeColorOverride("font_color", SkillPalette.RarityColor(skillInfo.RareType)); } ApplyTypeBadge(skillInfo); ApplyEffect(skillInfo); RefreshStyle(); } /// /// Applies the panel-owned selection state: the selected card gets the /// golden surface, rarity border and a soft rarity glow, while hover /// only lifts the border. Both are repainted from scratch so the card /// can never end up half-styled after a filter rebuild. /// public void SetSelected(bool selected) { _selected = selected; RefreshStyle(); } /// Frees the node; the panel owns the card's lifetime and rebuilds the grid. public override void Destruct() { QueueFree(); } private void ResolveNodes() { bg ??= GetNodeOrNull("Bg"); accent ??= GetNodeOrNull("Accent"); art ??= GetNodeOrNull("Art"); imgCard ??= GetNodeOrNull("Art/ImgCard"); txtName ??= GetNodeOrNull