Chessistics/Scripts/UI/PieceStockPanel.cs

160 lines
5.4 KiB
C#
Raw Normal View History

using Godot;
using System;
using System.Collections.Generic;
using Chessistics.Engine.Model;
using Chessistics.Scripts.Pieces;
namespace Chessistics.Scripts.UI;
public partial class PieceStockPanel : VBoxContainer
{
[Signal]
public delegate void PieceSelectedEventHandler(int kindIndex);
private readonly Dictionary<PieceKind, (Button button, Label countLabel, int remaining)> _entries = new();
private PieceKind? _selectedKind;
public PieceKind? SelectedKind => _selectedKind;
private static readonly Color NormalBg = new("#2A2A2E");
private static readonly Color SelectedBg = new("#3D6B8E");
private static readonly Color HoverBg = new("#353538");
private static readonly Color DisabledBg = new("#1E1E20");
private static readonly Color BorderNormal = new("#444448");
private static readonly Color BorderSelected = new("#5A9ECC");
public void Setup(IReadOnlyList<PieceStock> stock)
{
foreach (var child in GetChildren())
child.QueueFree();
_entries.Clear();
_selectedKind = null;
var title = new Label { Text = "PIECES" };
title.AddThemeFontSizeOverride("font_size", 16);
title.AddThemeColorOverride("font_color", new Color("#B8942A"));
AddChild(title);
AddChild(new HSeparator());
foreach (var entry in stock)
{
var hbox = new HBoxContainer();
hbox.AddThemeConstantOverride("separation", 8);
// Color dot matching piece color
var dot = new ColorRect
{
CustomMinimumSize = new Vector2(10, 10),
Size = new Vector2(10, 10),
Color = PieceView.GetPieceColor(entry.Kind),
MouseFilter = Control.MouseFilterEnum.Ignore
};
var dotCenter = new CenterContainer { CustomMinimumSize = new Vector2(14, 32) };
dotCenter.AddChild(dot);
hbox.AddChild(dotCenter);
var button = new Button
{
Text = GetPieceName(entry.Kind),
CustomMinimumSize = new Vector2(120, 32),
ToggleMode = false // We manage selection state ourselves
};
ApplyButtonStyle(button, false);
var countLabel = new Label { Text = $"x{entry.Count}" };
countLabel.AddThemeFontSizeOverride("font_size", 13);
countLabel.AddThemeColorOverride("font_color", new Color("#999999"));
var kind = entry.Kind;
button.Pressed += () => OnPieceButtonPressed(kind);
hbox.AddChild(button);
hbox.AddChild(countLabel);
AddChild(hbox);
_entries[entry.Kind] = (button, countLabel, entry.Count);
}
}
private void OnPieceButtonPressed(PieceKind kind)
{
if (_selectedKind == kind)
{
_selectedKind = null;
UpdateButtonStates();
return;
}
_selectedKind = kind;
UpdateButtonStates();
EmitSignal(SignalName.PieceSelected, (int)kind);
}
private void UpdateButtonStates()
{
foreach (var (k, (button, _, remaining)) in _entries)
{
bool selected = k == _selectedKind;
button.Disabled = remaining <= 0;
ApplyButtonStyle(button, selected);
}
}
private static void ApplyButtonStyle(Button button, bool selected)
{
var bg = selected ? SelectedBg : NormalBg;
var border = selected ? BorderSelected : BorderNormal;
var normal = MakeStyle(bg, border);
var hover = MakeStyle(selected ? SelectedBg.Lightened(0.1f) : HoverBg, border);
var disabled = MakeStyle(DisabledBg, new Color("#2A2A2E"));
button.AddThemeStyleboxOverride("normal", normal);
button.AddThemeStyleboxOverride("hover", hover);
button.AddThemeStyleboxOverride("pressed", MakeStyle(bg.Darkened(0.15f), border));
button.AddThemeStyleboxOverride("disabled", disabled);
button.AddThemeFontSizeOverride("font_size", 12);
button.AddThemeColorOverride("font_color", selected ? Colors.White : new Color("#CCCCCC"));
button.AddThemeColorOverride("font_disabled_color", new Color("#555555"));
}
private static StyleBoxFlat MakeStyle(Color bg, Color border)
{
return new StyleBoxFlat
{
BgColor = bg,
BorderColor = border,
BorderWidthBottom = 1, BorderWidthTop = 1,
BorderWidthLeft = 1, BorderWidthRight = 1,
CornerRadiusTopLeft = 4, CornerRadiusTopRight = 4,
CornerRadiusBottomLeft = 4, CornerRadiusBottomRight = 4,
ContentMarginLeft = 8, ContentMarginRight = 8,
ContentMarginTop = 4, ContentMarginBottom = 4
};
}
public void UpdateCount(PieceKind kind, int remaining)
{
if (!_entries.TryGetValue(kind, out var entry)) return;
_entries[kind] = (entry.button, entry.countLabel, remaining);
entry.countLabel.Text = $"x{remaining}";
entry.button.Disabled = remaining <= 0;
}
public void ClearSelection()
{
_selectedKind = null;
UpdateButtonStates();
}
private static string GetPieceName(PieceKind kind) => kind switch
{
PieceKind.Pawn => "Pion",
PieceKind.Rook => "Tour II",
PieceKind.Bishop => "Fou II",
PieceKind.Knight => "Cavalier",
_ => kind.ToString()
};
}