From 9ffefd463cbfcdc7e5b5aab8530984ecf2f5e573 Mon Sep 17 00:00:00 2001 From: KoalaTrapLord <265133236+KoalaTrapLord@users.noreply.github.com> Date: Sat, 28 Mar 2026 19:56:24 -0400 Subject: [PATCH] feat(#143): add CommanderZoneWidget with art crop, cast counter, and tax display --- .../UI/Battleground/CommanderZoneWidget.cs | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 unity-client/Assets/Scripts/UI/Battleground/CommanderZoneWidget.cs diff --git a/unity-client/Assets/Scripts/UI/Battleground/CommanderZoneWidget.cs b/unity-client/Assets/Scripts/UI/Battleground/CommanderZoneWidget.cs new file mode 100644 index 0000000..c5ada84 --- /dev/null +++ b/unity-client/Assets/Scripts/UI/Battleground/CommanderZoneWidget.cs @@ -0,0 +1,69 @@ +using UnityEngine; +using UnityEngine.UI; +using TMPro; +using CommanderAILab.Models; +using CommanderAILab.Services; + +namespace CommanderAILab.UI +{ + /// + /// Per-seat commander zone widget. + /// Shows: art crop banner, commander name, cast count, commander tax. + /// Requires ImageCache singleton in scene. + /// + public class CommanderZoneWidget : MonoBehaviour + { + [Header("References")] + [SerializeField] private RawImage artCropImage; + [SerializeField] private TMP_Text commanderNameLabel; + [SerializeField] private TMP_Text castCountLabel; + [SerializeField] private TMP_Text taxLabel; + [SerializeField] private UnityEngine.UI.Button castCommanderBtn; + + public CardModel CommanderCard { get; private set; } + private int _castCount = 0; + + // ── Binding ─────────────────────────────────────────── + public void Bind(CardModel commander) + { + CommanderCard = commander; + _castCount = commander != null ? commander.counters.GetValueOrDefault("cast_count", 0) : 0; + + if (commanderNameLabel) + commanderNameLabel.text = commander?.name ?? "No Commander"; + + UpdateTaxDisplay(); + + // Load art crop from Scryfall + if (commander != null && !string.IsNullOrEmpty(commander.name) + && artCropImage != null && ImageCache.Instance != null) + { + StartCoroutine(ImageCache.Instance.LoadArtCrop(commander.name, artCropImage)); + } + } + + // ── Cast tracking ────────────────────────────────────── + public void OnCommanderCast() + { + _castCount++; + UpdateTaxDisplay(); + } + + public void SetCastCount(int count) + { + _castCount = Mathf.Max(0, count); + UpdateTaxDisplay(); + } + + // ── Internal ────────────────────────────────────────── + private void UpdateTaxDisplay() + { + if (castCountLabel) + castCountLabel.text = _castCount == 0 ? "Not yet cast" : $"Cast #{_castCount}"; + + int tax = _castCount * 2; + if (taxLabel) + taxLabel.text = tax == 0 ? "No tax" : $"+{tax} ☀ tax"; + } + } +}