Fix stop reset, piece selection visuals, add trajectory preview and menu button
Bugfixes:
- Stop now fully rebuilds piece visuals (fixes destroyed pieces not
reappearing and lingering cargo indicators)
- Piece stock buttons use explicit selected/unselected styling instead
of ambiguous toggle behavior (teal bg + bright border when selected)
- Color dots next to stock buttons match piece colors
Features:
- Clicking a placed piece highlights its start/end cells with piece color
- Back-to-menu button ("← Menu") in top-left returns to level selector
with fade transition
- DetailPanel shows "Pion" name and has styled remove button
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
43a3e97f28
commit
210be72100
3 changed files with 162 additions and 14 deletions
|
|
@ -133,14 +133,35 @@ public partial class Main : Node2D
|
||||||
uiRoot.MouseFilter = Control.MouseFilterEnum.Ignore;
|
uiRoot.MouseFilter = Control.MouseFilterEnum.Ignore;
|
||||||
_uiLayer.AddChild(uiRoot);
|
_uiLayer.AddChild(uiRoot);
|
||||||
|
|
||||||
// Level title (top-left)
|
// Level title bar (top-left)
|
||||||
|
var titleBar = new HBoxContainer();
|
||||||
|
titleBar.SetAnchorsPreset(Control.LayoutPreset.TopLeft);
|
||||||
|
titleBar.OffsetLeft = 12;
|
||||||
|
titleBar.OffsetTop = 8;
|
||||||
|
titleBar.AddThemeConstantOverride("separation", 12);
|
||||||
|
|
||||||
|
var backButton = new Button { Text = "← Menu", CustomMinimumSize = new Vector2(70, 28) };
|
||||||
|
backButton.AddThemeFontSizeOverride("font_size", 11);
|
||||||
|
var backStyle = new StyleBoxFlat
|
||||||
|
{
|
||||||
|
BgColor = new Color("#2A2A2E"),
|
||||||
|
BorderColor = new Color("#444448"),
|
||||||
|
BorderWidthBottom = 1, BorderWidthTop = 1, BorderWidthLeft = 1, BorderWidthRight = 1,
|
||||||
|
CornerRadiusTopLeft = 4, CornerRadiusTopRight = 4,
|
||||||
|
CornerRadiusBottomLeft = 4, CornerRadiusBottomRight = 4,
|
||||||
|
ContentMarginLeft = 8, ContentMarginRight = 8,
|
||||||
|
ContentMarginTop = 2, ContentMarginBottom = 2
|
||||||
|
};
|
||||||
|
backButton.AddThemeStyleboxOverride("normal", backStyle);
|
||||||
|
backButton.Pressed += OnBackToMenu;
|
||||||
|
titleBar.AddChild(backButton);
|
||||||
|
|
||||||
_levelTitle = new Label { Text = "CHESSISTICS" };
|
_levelTitle = new Label { Text = "CHESSISTICS" };
|
||||||
_levelTitle.SetAnchorsPreset(Control.LayoutPreset.TopLeft);
|
|
||||||
_levelTitle.OffsetLeft = 16;
|
|
||||||
_levelTitle.OffsetTop = 12;
|
|
||||||
_levelTitle.AddThemeFontSizeOverride("font_size", 20);
|
_levelTitle.AddThemeFontSizeOverride("font_size", 20);
|
||||||
_levelTitle.MouseFilter = Control.MouseFilterEnum.Ignore;
|
_levelTitle.MouseFilter = Control.MouseFilterEnum.Ignore;
|
||||||
uiRoot.AddChild(_levelTitle);
|
titleBar.AddChild(_levelTitle);
|
||||||
|
|
||||||
|
uiRoot.AddChild(titleBar);
|
||||||
|
|
||||||
// --- Side Panel (anchored to right edge) ---
|
// --- Side Panel (anchored to right edge) ---
|
||||||
_sidePanel = new PanelContainer();
|
_sidePanel = new PanelContainer();
|
||||||
|
|
@ -268,13 +289,24 @@ public partial class Main : Node2D
|
||||||
var snap = _sim.GetSnapshot();
|
var snap = _sim.GetSnapshot();
|
||||||
if (snap.Phase != SimPhase.Edit) return;
|
if (snap.Phase != SimPhase.Edit) return;
|
||||||
|
|
||||||
|
_boardView.ClearHighlights();
|
||||||
|
|
||||||
var coords = new Coords(col, row);
|
var coords = new Coords(col, row);
|
||||||
var piece = snap.Pieces.FirstOrDefault(p => p.StartCell == coords || p.EndCell == coords);
|
var piece = snap.Pieces.FirstOrDefault(p => p.StartCell == coords || p.EndCell == coords);
|
||||||
if (piece != null)
|
if (piece != null)
|
||||||
|
{
|
||||||
_detailPanel.ShowPiece(piece);
|
_detailPanel.ShowPiece(piece);
|
||||||
|
|
||||||
|
// Highlight start and end cells to show trajectory
|
||||||
|
var pieceColor = PieceView.GetPieceColor(piece.Kind);
|
||||||
|
var highlightColor = new Color(pieceColor, 0.3f);
|
||||||
|
_boardView.HighlightCells([piece.StartCell, piece.EndCell], highlightColor);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
_detailPanel.Hide();
|
_detailPanel.Hide();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- Level Management ---
|
// --- Level Management ---
|
||||||
|
|
||||||
|
|
@ -491,13 +523,32 @@ public partial class Main : Node2D
|
||||||
_running = false;
|
_running = false;
|
||||||
_simTimer.Stop();
|
_simTimer.Stop();
|
||||||
_sim.ProcessCommand(new StopSimulationCommand());
|
_sim.ProcessCommand(new StopSimulationCommand());
|
||||||
_eventAnimator.ResetPiecePositions(_sim.GetSnapshot());
|
|
||||||
|
// Full visual rebuild: clear everything and recreate from snapshot
|
||||||
|
_eventAnimator.ClearAll();
|
||||||
|
var snap = _sim.GetSnapshot();
|
||||||
|
foreach (var ps in snap.Pieces)
|
||||||
|
{
|
||||||
|
var pieceView = new PieceView();
|
||||||
|
pieceView.Setup(ps.Id, ps.Kind, ps.StartCell, ps.EndCell, _boardView);
|
||||||
|
_boardView.AddChild(pieceView);
|
||||||
|
|
||||||
|
var color = PieceView.GetPieceColor(ps.Kind);
|
||||||
|
var trajectView = new TrajectView();
|
||||||
|
trajectView.Setup(ps.Id,
|
||||||
|
_boardView.CoordsToPixel(ps.StartCell),
|
||||||
|
_boardView.CoordsToPixel(ps.EndCell),
|
||||||
|
color);
|
||||||
|
_boardView.AddChild(trajectView);
|
||||||
|
|
||||||
|
_eventAnimator.RegisterPiece(ps.Id, pieceView, trajectView);
|
||||||
|
}
|
||||||
|
|
||||||
_controlBar.UpdateForPhase(SimPhase.Edit);
|
_controlBar.UpdateForPhase(SimPhase.Edit);
|
||||||
_controlBar.ResetTurn();
|
_controlBar.ResetTurn();
|
||||||
_metricsOverlay.Hide();
|
_metricsOverlay.Hide();
|
||||||
_inputMapper.SetSnapshot(_sim.GetSnapshot());
|
_inputMapper.SetSnapshot(snap);
|
||||||
|
|
||||||
// Reset objective panel
|
|
||||||
if (_currentLevel != null)
|
if (_currentLevel != null)
|
||||||
_objectivePanel.Setup(_currentLevel.Demands);
|
_objectivePanel.Setup(_currentLevel.Demands);
|
||||||
}
|
}
|
||||||
|
|
@ -550,4 +601,18 @@ public partial class Main : Node2D
|
||||||
else
|
else
|
||||||
ShowLevelSelect();
|
ShowLevelSelect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnBackToMenu()
|
||||||
|
{
|
||||||
|
SfxManager.Instance?.PlayClick();
|
||||||
|
_running = false;
|
||||||
|
_simTimer.Stop();
|
||||||
|
_eventAnimator.ClearAll();
|
||||||
|
|
||||||
|
FadeOut(0.2f, () =>
|
||||||
|
{
|
||||||
|
ShowLevelSelect();
|
||||||
|
FadeIn(0.3f);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using Godot;
|
using Godot;
|
||||||
using Chessistics.Engine.Model;
|
using Chessistics.Engine.Model;
|
||||||
|
using Chessistics.Scripts.Pieces;
|
||||||
|
|
||||||
namespace Chessistics.Scripts.UI;
|
namespace Chessistics.Scripts.UI;
|
||||||
|
|
||||||
|
|
@ -14,17 +15,41 @@ public partial class DetailPanel : PanelContainer
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
|
var style = new StyleBoxFlat
|
||||||
|
{
|
||||||
|
BgColor = new Color(0.14f, 0.14f, 0.16f, 0.95f),
|
||||||
|
BorderColor = new Color("#444448"),
|
||||||
|
BorderWidthTop = 1,
|
||||||
|
CornerRadiusTopLeft = 4, CornerRadiusTopRight = 4,
|
||||||
|
ContentMarginLeft = 12, ContentMarginRight = 12,
|
||||||
|
ContentMarginTop = 8, ContentMarginBottom = 8
|
||||||
|
};
|
||||||
|
AddThemeStyleboxOverride("panel", style);
|
||||||
|
|
||||||
var vbox = new VBoxContainer();
|
var vbox = new VBoxContainer();
|
||||||
|
vbox.AddThemeConstantOverride("separation", 4);
|
||||||
|
|
||||||
var title = new Label { Text = "DETAIL" };
|
var title = new Label { Text = "DETAIL" };
|
||||||
title.AddThemeFontSizeOverride("font_size", 14);
|
title.AddThemeFontSizeOverride("font_size", 13);
|
||||||
|
title.AddThemeColorOverride("font_color", new Color("#B8942A"));
|
||||||
vbox.AddChild(title);
|
vbox.AddChild(title);
|
||||||
|
|
||||||
_infoLabel = new Label { Text = "" };
|
_infoLabel = new Label { Text = "" };
|
||||||
_infoLabel.AddThemeFontSizeOverride("font_size", 11);
|
_infoLabel.AddThemeFontSizeOverride("font_size", 11);
|
||||||
|
_infoLabel.AddThemeColorOverride("font_color", new Color("#CCCCCC"));
|
||||||
vbox.AddChild(_infoLabel);
|
vbox.AddChild(_infoLabel);
|
||||||
|
|
||||||
_removeButton = new Button { Text = "Retirer" };
|
_removeButton = new Button { Text = "Retirer", CustomMinimumSize = new Vector2(80, 26) };
|
||||||
|
_removeButton.AddThemeFontSizeOverride("font_size", 11);
|
||||||
|
var btnStyle = new StyleBoxFlat
|
||||||
|
{
|
||||||
|
BgColor = new Color("#5A2A2A"),
|
||||||
|
CornerRadiusTopLeft = 4, CornerRadiusTopRight = 4,
|
||||||
|
CornerRadiusBottomLeft = 4, CornerRadiusBottomRight = 4,
|
||||||
|
ContentMarginLeft = 8, ContentMarginRight = 8,
|
||||||
|
ContentMarginTop = 2, ContentMarginBottom = 2
|
||||||
|
};
|
||||||
|
_removeButton.AddThemeStyleboxOverride("normal", btnStyle);
|
||||||
_removeButton.Pressed += () => EmitSignal(SignalName.RemoveRequested, _currentPieceId);
|
_removeButton.Pressed += () => EmitSignal(SignalName.RemoveRequested, _currentPieceId);
|
||||||
vbox.AddChild(_removeButton);
|
vbox.AddChild(_removeButton);
|
||||||
|
|
||||||
|
|
@ -37,6 +62,7 @@ public partial class DetailPanel : PanelContainer
|
||||||
_currentPieceId = piece.Id;
|
_currentPieceId = piece.Id;
|
||||||
var kindName = piece.Kind switch
|
var kindName = piece.Kind switch
|
||||||
{
|
{
|
||||||
|
PieceKind.Pawn => "Pion",
|
||||||
PieceKind.Rook => "Tour II",
|
PieceKind.Rook => "Tour II",
|
||||||
PieceKind.Bishop => "Fou II",
|
PieceKind.Bishop => "Fou II",
|
||||||
PieceKind.Knight => "Cavalier",
|
PieceKind.Knight => "Cavalier",
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using Godot;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Chessistics.Engine.Model;
|
using Chessistics.Engine.Model;
|
||||||
|
using Chessistics.Scripts.Pieces;
|
||||||
|
|
||||||
namespace Chessistics.Scripts.UI;
|
namespace Chessistics.Scripts.UI;
|
||||||
|
|
||||||
|
|
@ -15,6 +16,13 @@ public partial class PieceStockPanel : VBoxContainer
|
||||||
|
|
||||||
public PieceKind? SelectedKind => _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)
|
public void Setup(IReadOnlyList<PieceStock> stock)
|
||||||
{
|
{
|
||||||
foreach (var child in GetChildren())
|
foreach (var child in GetChildren())
|
||||||
|
|
@ -24,7 +32,7 @@ public partial class PieceStockPanel : VBoxContainer
|
||||||
|
|
||||||
var title = new Label { Text = "PIECES" };
|
var title = new Label { Text = "PIECES" };
|
||||||
title.AddThemeFontSizeOverride("font_size", 16);
|
title.AddThemeFontSizeOverride("font_size", 16);
|
||||||
title.AddThemeColorOverride("font_color", new Color("#FFD700"));
|
title.AddThemeColorOverride("font_color", new Color("#B8942A"));
|
||||||
AddChild(title);
|
AddChild(title);
|
||||||
|
|
||||||
AddChild(new HSeparator());
|
AddChild(new HSeparator());
|
||||||
|
|
@ -32,16 +40,31 @@ public partial class PieceStockPanel : VBoxContainer
|
||||||
foreach (var entry in stock)
|
foreach (var entry in stock)
|
||||||
{
|
{
|
||||||
var hbox = new HBoxContainer();
|
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
|
var button = new Button
|
||||||
{
|
{
|
||||||
Text = GetPieceName(entry.Kind),
|
Text = GetPieceName(entry.Kind),
|
||||||
CustomMinimumSize = new Vector2(120, 32),
|
CustomMinimumSize = new Vector2(120, 32),
|
||||||
ToggleMode = true
|
ToggleMode = false // We manage selection state ourselves
|
||||||
};
|
};
|
||||||
|
ApplyButtonStyle(button, false);
|
||||||
|
|
||||||
var countLabel = new Label { Text = $"x{entry.Count}" };
|
var countLabel = new Label { Text = $"x{entry.Count}" };
|
||||||
countLabel.AddThemeFontSizeOverride("font_size", 14);
|
countLabel.AddThemeFontSizeOverride("font_size", 13);
|
||||||
|
countLabel.AddThemeColorOverride("font_color", new Color("#999999"));
|
||||||
|
|
||||||
var kind = entry.Kind;
|
var kind = entry.Kind;
|
||||||
button.Pressed += () => OnPieceButtonPressed(kind);
|
button.Pressed += () => OnPieceButtonPressed(kind);
|
||||||
|
|
@ -72,11 +95,45 @@ public partial class PieceStockPanel : VBoxContainer
|
||||||
{
|
{
|
||||||
foreach (var (k, (button, _, remaining)) in _entries)
|
foreach (var (k, (button, _, remaining)) in _entries)
|
||||||
{
|
{
|
||||||
button.ButtonPressed = k == _selectedKind;
|
bool selected = k == _selectedKind;
|
||||||
button.Disabled = remaining <= 0;
|
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)
|
public void UpdateCount(PieceKind kind, int remaining)
|
||||||
{
|
{
|
||||||
if (!_entries.TryGetValue(kind, out var entry)) return;
|
if (!_entries.TryGetValue(kind, out var entry)) return;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue