import 'dart:math' as math; import 'package:flutter/material.dart'; import '../utils/Colors.dart'; /// The Grounded mark: a lime sun resting on a ground line beneath two /// breathing arcs, on a night-green tile. Drawn, not bitmapped, so the splash /// can raise the sun and light the arcs. Geometry matches the launcher icon. class GroundedMark extends StatelessWidget { final double size; /// 0 → the sun is below the line; 1 → fully risen. final double rise; /// 0 → arcs hidden; 1 → both lit. The inner arc lights first. final double arcs; final bool tile; const GroundedMark({ super.key, this.size = 120, this.rise = 1, this.arcs = 1, this.tile = true, }); @override Widget build(BuildContext context) { return CustomPaint( size: Size.square(size), painter: _MarkPainter(rise, arcs, tile), ); } } class _MarkPainter extends CustomPainter { final double rise; final double arcs; final bool tile; _MarkPainter(this.rise, this.arcs, this.tile); @override void paint(Canvas canvas, Size size) { final double u = size.width / 1024; final Rect bounds = Offset.zero & size; if (tile) { canvas.drawRRect( RRect.fromRectAndRadius(bounds, Radius.circular(size.width * 0.235)), Paint() ..shader = const LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [colorNightLift, colorNight], ).createShader(bounds), ); } final double cx = 512 * u; final double horizon = 630 * u; // Arcs — inner then outer. final List radii = [250, 330]; final List alphas = [0.6, 0.28]; for (int i = 0; i < 2; i++) { final double lit = ((arcs * 2) - i).clamp(0.0, 1.0); if (lit <= 0) { continue; } final double r = radii[i] * u; canvas.drawArc( Rect.fromCircle(center: Offset(cx, horizon), radius: r - 15 * u), math.pi * 198 / 180, math.pi * 144 / 180, false, Paint() ..style = PaintingStyle.stroke ..strokeWidth = 30 * u ..strokeCap = StrokeCap.round ..color = colorAmbientMid.withValues(alpha: alphas[i] * lit), ); } // The sun, clipped at the horizon so it rises out of the ground. final double radius = 168 * u; canvas.save(); canvas.clipRect(Rect.fromLTRB(0, 0, size.width, horizon)); canvas.drawCircle( Offset(cx, horizon + radius * 2 * (1 - rise)), radius, Paint()..color = colorLime, ); canvas.restore(); // Ground line. final double ground = horizon + 52 * u; canvas.drawRRect( RRect.fromRectAndRadius( Rect.fromLTRB(250 * u, ground - 20 * u, 774 * u, ground + 20 * u), Radius.circular(20 * u), ), Paint()..color = colorAmbientMid, ); } @override bool shouldRepaint(covariant _MarkPainter oldDelegate) { return oldDelegate.rise != rise || oldDelegate.arcs != arcs || oldDelegate.tile != tile; } }