Files
BlockSeasons/lib/ui/widgets/piece_painter.dart
T
airkjw 3138fc4b08 Add playable core UI: board painter, drag-and-drop, HUD, result overlay
CustomPainter board with gems/ghost/clear-flash, finger-lifted drag
with snap preview, combo text effect, HUD chips, phase overlays with
rescue stubs, demo stage. E2E widget test drives a real drag gesture.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 13:19:34 +09:00

83 lines
2.1 KiB
Dart

import 'package:flutter/material.dart';
import '../../game/models/piece.dart';
import '../theme/palette.dart';
/// Draws a piece as rounded tiles at a given cell size; reused by the tray,
/// the drag overlay, and ghost previews.
void paintPiece(
Canvas canvas,
Piece piece, {
required double cellSize,
Offset origin = Offset.zero,
Color? overrideColor,
}) {
final paint = Paint()
..color = overrideColor ?? GamePalette.tile(piece.colorId);
final inset = cellSize * 0.05;
final radius = Radius.circular(cellSize * 0.18);
for (final (dx, dy) in piece.offsets) {
final rect = Rect.fromLTWH(
origin.dx + dx * cellSize + inset,
origin.dy + dy * cellSize + inset,
cellSize - inset * 2,
cellSize - inset * 2,
);
canvas.drawRRect(RRect.fromRectAndRadius(rect, radius), paint);
if (overrideColor == null) {
// Subtle top highlight for depth.
final highlight = Paint()..color = Colors.white.withValues(alpha: 0.18);
canvas.drawRRect(
RRect.fromRectAndRadius(
Rect.fromLTWH(rect.left, rect.top, rect.width, rect.height * 0.32),
radius,
),
highlight,
);
}
}
}
/// Bounding size of a piece in cells.
(int, int) pieceCellBounds(Piece piece) {
var w = 0;
var h = 0;
for (final (dx, dy) in piece.offsets) {
if (dx + 1 > w) w = dx + 1;
if (dy + 1 > h) h = dy + 1;
}
return (w, h);
}
class PieceWidget extends StatelessWidget {
const PieceWidget({super.key, required this.piece, required this.cellSize});
final Piece piece;
final double cellSize;
@override
Widget build(BuildContext context) {
final (w, h) = pieceCellBounds(piece);
return CustomPaint(
size: Size(w * cellSize, h * cellSize),
painter: _PiecePainter(piece, cellSize),
);
}
}
class _PiecePainter extends CustomPainter {
const _PiecePainter(this.piece, this.cellSize);
final Piece piece;
final double cellSize;
@override
void paint(Canvas canvas, Size size) {
paintPiece(canvas, piece, cellSize: cellSize);
}
@override
bool shouldRepaint(_PiecePainter old) =>
old.piece != piece || old.cellSize != cellSize;
}