CyberKeyGeometry.build constructor

CyberKeyGeometry.build(
  1. Size size, {
  2. required double chamfer,
  3. required double edgeWidth,
  4. required double plunge,
})

Builds the geometry of a key box of size.

Implementation

CyberKeyGeometry.build(
  Size size, {
  required double chamfer,
  required double edgeWidth,
  required double plunge,
}) {
  final s = size.shortestSide;
  inset = (0.045 * s).clamp(2.0, 3.5);
  depth = math.max(0, math.min(plunge, s / 16)).toDouble();
  face = Rect.fromLTRB(
    inset,
    inset,
    size.width - inset,
    size.height - inset - depth,
  );
  final short = math.max(0, face.shortestSide).toDouble();
  cut = (chamfer * short).clamp(0.0, 0.30 * short);
  edge = math.max(0, math.min(edgeWidth, s / 24)).toDouble();
  if (face.width <= 0 || face.height <= 0) {
    inner = face;
    return;
  }
  addCutOctagon(facePath, face, cut);
  addInsetCutOctagon(edgePath, face, cut, edge / 2);
  addInsetCutOctagon(insetEdgePath, face, cut, edge / 2 + 1.5);
  inner = face.deflate(edge);
  addInsetCutOctagon(innerPath, face, cut, edge);
  // HUD ticks: L-brackets at the square corners (top-right, bottom-left).
  // Each arm ends above the label zone (26 % of the plate height).
  if (s >= 36) {
    void ticks(Path path, double i) {
      final a = math.min((0.14 * s).clamp(4.0, 9.0), 0.26 * face.height - i);
      if (a < 2) return;
      path
        ..moveTo(face.right - i - a, face.top + i)
        ..lineTo(face.right - i, face.top + i)
        ..lineTo(face.right - i, face.top + i + a)
        ..moveTo(face.left + i, face.bottom - i - a)
        ..lineTo(face.left + i, face.bottom - i)
        ..lineTo(face.left + i + a, face.bottom - i);
    }

    ticks(tickPath, edge + 2);
    ticks(insetTickPath, edge + 3.5);
  }
  // Bloom bands: the top and bottom 16 % of the plate (outside the label
  // zone), each clipped to the octagon analytically; the light hugs the
  // neon line (most of it in the outer 5 %).
  final band = face.height * bloomBand;
  final l = face.left;
  final t = face.top;
  final r = face.right;
  final b = face.bottom;
  final c = cut;
  if (band >= c) {
    bloomPath
      ..moveTo(l + c, t)
      ..lineTo(r, t)
      ..lineTo(r, t + band)
      ..lineTo(l, t + band)
      ..lineTo(l, t + c)
      ..close()
      ..moveTo(l, b - band)
      ..lineTo(r, b - band)
      ..lineTo(r, b - c)
      ..lineTo(r - c, b)
      ..lineTo(l, b)
      ..close();
  } else {
    bloomPath
      ..moveTo(l + c, t)
      ..lineTo(r, t)
      ..lineTo(r, t + band)
      ..lineTo(l + c - band, t + band)
      ..close()
      ..moveTo(l, b - band)
      ..lineTo(r - c + band, b - band)
      ..lineTo(r - c, b)
      ..lineTo(l, b)
      ..close();
  }
  bloomShader = ui.Gradient.linear(
    Offset(0, t),
    Offset(0, b),
    const [
      Color(0x66FFFFFF),
      Color(0x1FFFFFFF),
      Color(0x00FFFFFF),
      Color(0x00FFFFFF),
      Color(0x1FFFFFFF),
      Color(0x66FFFFFF),
    ],
    const [0, 0.05, bloomBand, 1 - bloomBand, 0.95, 1],
  );
  // Lite tier: one un-blurred glow ring, 2 dp wide, centred 1.5 dp
  // outside the plate.
  addInsetCutOctagon(liteRing, face, cut, -1.5);
}