Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee7cf85255 | ||
|
|
1686b791bc | ||
|
|
12752c41e2 | ||
|
|
293464e297 |
@@ -140,6 +140,10 @@ tyre pressures, GPS (lat, lon, elevation, heading) and the is_* flags. It does *
|
|||||||
confirmed car facts, app structure, UI conventions, build/test/ship, documents. It replaces
|
confirmed car facts, app structure, UI conventions, build/test/ship, documents. It replaces
|
||||||
upstream's EVABRPUploader text. The test emulator is now in the flake: `nix run .#car-emulator`
|
upstream's EVABRPUploader text. The test emulator is now in the flake: `nix run .#car-emulator`
|
||||||
(Android 9 AOSP at 1920×720, 160 dpi; the car build installs as the system user — checked).
|
(Android 9 AOSP at 1920×720, 160 dpi; the car build installs as the system user — checked).
|
||||||
|
- 2026-10-31 — App 2.43.2: Halloween's teeth are triangles hanging from the grin's upper lip, each in the colour of the rib behind it (the right one was the darker orange on the lighter rib; owner: "the color on the right side is off"). Two screenshots redone. Tested: unit tests, lint, emulator with sample values (drawing in panel and full screen, regenerating in full screen) and with no data. Not tried on the car.
|
||||||
|
- 2026-10-31 — App 2.43.1 published (`car-2.43.1`).
|
||||||
|
- 2026-10-31 — App 2.43.1: Halloween's bats can be seen. They were near-black and small on the darkest part of the sky, and the owner did not spot them; now a moonlit purple-grey with a light edge, a third larger. Two screenshots redone. Tested: unit tests, lint, emulator with sample values (panel and full screen) and with no data (no bats). Not tried on the car.
|
||||||
|
- 2026-10-31 — App 2.43.0 published (`car-2.43.0`).
|
||||||
- 2026-10-31 — App 2.43.0: Overview styles **Día de Muertos** (`MuertosView`) and **Halloween**
|
- 2026-10-31 — App 2.43.0: Overview styles **Día de Muertos** (`MuertosView`) and **Halloween**
|
||||||
(`HalloweenView`; owner: "let's design a 'dia de muertos' and a 'halloween' style"), each with
|
(`HalloweenView`; owner: "let's design a 'dia de muertos' and a 'halloween' style"), each with
|
||||||
its own palette (the papel picado's pink, the pumpkin's orange). Día de Muertos, an ofrenda and
|
its own palette (the papel picado's pink, the pumpkin's orange). Día de Muertos, an ofrenda and
|
||||||
|
|||||||
+2
-2
@@ -34,8 +34,8 @@ android {
|
|||||||
applicationId "com.stinnesbeck.nilsmg4"
|
applicationId "com.stinnesbeck.nilsmg4"
|
||||||
minSdk 27
|
minSdk 27
|
||||||
targetSdk 36
|
targetSdk 36
|
||||||
versionCode 153
|
versionCode 155
|
||||||
versionName "2.43.0"
|
versionName "2.43.2"
|
||||||
|
|
||||||
// Nothing about the server ships in the APK: its URL and ingest token are entered in
|
// Nothing about the server ships in the APK: its URL and ingest token are entered in
|
||||||
// the app's Server tab (ServerConfig), and the database is only reachable by the server.
|
// the app's Server tab (ServerConfig), and the database is only reachable by the server.
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ final class HalloweenView extends ClusterCanvasView {
|
|||||||
private static final int STONE_DARK = 0xFF3E3C4A, MOON = 0xFFF4E9B8, MOON_SHADE = 0xFFD8C98C;
|
private static final int STONE_DARK = 0xFF3E3C4A, MOON = 0xFFF4E9B8, MOON_SHADE = 0xFFD8C98C;
|
||||||
private static final int POTION = 0xFF7BF03A, GLASS = 0xFFB9D8D0, BONE = 0xFFF2EAD8, ORANGE = 0xFFFF8C1A;
|
private static final int POTION = 0xFF7BF03A, GLASS = 0xFFB9D8D0, BONE = 0xFFF2EAD8, ORANGE = 0xFFFF8C1A;
|
||||||
private static final int STEM = 0xFF4E7A2B, WOOD = 0xFF2E1B10, INK = 0xFF140A08;
|
private static final int STEM = 0xFF4E7A2B, WOOD = 0xFF2E1B10, INK = 0xFF140A08;
|
||||||
|
private static final int BAT = 0xFF6F6390, BAT_EDGE = 0xFFD6CCEA;
|
||||||
|
|
||||||
private final Paint fill = new Paint(Paint.ANTI_ALIAS_FLAG);
|
private final Paint fill = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
private final Paint line = new Paint(Paint.ANTI_ALIAS_FLAG);
|
private final Paint line = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
@@ -180,11 +181,11 @@ final class HalloweenView extends ClusterCanvasView {
|
|||||||
float x = ((i * 0.13f * span + time * speed) % span) + w * 0.04f;
|
float x = ((i * 0.13f * span + time * speed) % span) + w * 0.04f;
|
||||||
float y = lane + (float) Math.sin(time * 2f + i) * 8f * u;
|
float y = lane + (float) Math.sin(time * 2f + i) * 8f * u;
|
||||||
if (Math.abs(x - cx) < 60f * u) y -= 10f * u;
|
if (Math.abs(x - cx) < 60f * u) y -= 10f * u;
|
||||||
bat(c, x, y, (i % 2 == 0 ? 15f : 12f) * u, (float) Math.sin(time * 14f + i * 2f));
|
bat(c, x, y, (i % 2 == 0 ? 20f : 16f) * u, (float) Math.sin(time * 14f + i * 2f), u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bat(Canvas c, float x, float y, float s, float flap) {
|
private void bat(Canvas c, float x, float y, float s, float flap, float u) {
|
||||||
float tip = -s * 0.5f * flap;
|
float tip = -s * 0.5f * flap;
|
||||||
path.reset();
|
path.reset();
|
||||||
path.moveTo(x, y - s * 0.3f);
|
path.moveTo(x, y - s * 0.3f);
|
||||||
@@ -197,8 +198,12 @@ final class HalloweenView extends ClusterCanvasView {
|
|||||||
path.quadTo(x - s * 1.1f, y + s * 0.05f, x - s * 1.5f, y - s * 0.3f + tip);
|
path.quadTo(x - s * 1.1f, y + s * 0.05f, x - s * 1.5f, y - s * 0.3f + tip);
|
||||||
path.quadTo(x - s * 0.6f, y - s * 0.7f + tip, x, y - s * 0.3f);
|
path.quadTo(x - s * 0.6f, y - s * 0.7f + tip, x, y - s * 0.3f);
|
||||||
path.close();
|
path.close();
|
||||||
fill.setColor(0xFF06030C);
|
// Lit by the moon: black would vanish in the night sky.
|
||||||
|
fill.setColor(BAT);
|
||||||
c.drawPath(path, fill);
|
c.drawPath(path, fill);
|
||||||
|
line.setColor(BAT_EDGE);
|
||||||
|
line.setStrokeWidth(1.5f * u);
|
||||||
|
c.drawPath(path, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------- Ghost: only where there is room ----------
|
// ---------- Ghost: only where there is room ----------
|
||||||
@@ -334,10 +339,9 @@ final class HalloweenView extends ClusterCanvasView {
|
|||||||
fill.setColor(burn);
|
fill.setColor(burn);
|
||||||
c.drawPath(path, fill);
|
c.drawPath(path, fill);
|
||||||
c.restore();
|
c.restore();
|
||||||
// Two teeth at the grin's corners, clear of the digits.
|
// Two teeth at the grin's corners, clear of the digits, each the colour of the rib it hangs from.
|
||||||
fill.setColor(PUMPKIN);
|
tooth(c, cx, -120f * u, gw, gt, 26f * u, 17f * u, gt + 40f * u, PUMPKIN, u);
|
||||||
tooth(c, cx - 120f * u, gt + 12f * u, 15f * u, 28f * u);
|
tooth(c, cx, 120f * u, gw, gt, 26f * u, 17f * u, gt + 40f * u, PUMPKIN_LIT, u);
|
||||||
tooth(c, cx + 120f * u, gt + 12f * u, 15f * u, 28f * u);
|
|
||||||
label(c, fmt(v.speedKmh, "%.0f", "—"), cx, gb - 18f * u, 92f * u, INK, serif, Paint.Align.CENTER);
|
label(c, fmt(v.speedKmh, "%.0f", "—"), cx, gb - 18f * u, 92f * u, INK, serif, Paint.Align.CENTER);
|
||||||
label(c, "KM/H", cx + 80f * u, cy + 64f * u, 16f * u, INK, face, Paint.Align.LEFT);
|
label(c, "KM/H", cx + 80f * u, cy + 64f * u, 16f * u, INK, face, Paint.Align.LEFT);
|
||||||
// The power under the pumpkin, above the ridge.
|
// The power under the pumpkin, above the ridge.
|
||||||
@@ -359,14 +363,27 @@ final class HalloweenView extends ClusterCanvasView {
|
|||||||
c.drawPath(path, line);
|
c.drawPath(path, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tooth(Canvas c, float x, float y, float halfW, float tall) {
|
/** A triangle hanging from the grin's upper lip (a curve sagging by {@code sag}) to {@code tipY}. */
|
||||||
|
private void tooth(Canvas c, float cx, float dx, float gw, float gt, float sag, float halfW, float tipY, int colour, float u) {
|
||||||
|
float left = lip(dx - halfW, gw, gt, sag), right = lip(dx + halfW, gw, gt, sag);
|
||||||
path.reset();
|
path.reset();
|
||||||
path.moveTo(x - halfW, y - tall * 0.3f);
|
// A little above the lip, so none of its dark edge shows across the tooth's root.
|
||||||
path.lineTo(x + halfW, y - tall * 0.3f);
|
path.moveTo(cx + dx - halfW, left - 1.5f * u);
|
||||||
path.lineTo(x + halfW, y + tall * 0.7f);
|
path.lineTo(cx + dx + halfW, right - 1.5f * u);
|
||||||
path.lineTo(x - halfW, y + tall * 0.7f);
|
path.lineTo(cx + dx, tipY);
|
||||||
path.close();
|
path.close();
|
||||||
|
fill.setColor(colour);
|
||||||
c.drawPath(path, fill);
|
c.drawPath(path, fill);
|
||||||
|
line.setColor(0xFF4A1F04);
|
||||||
|
line.setStrokeWidth(3f * u);
|
||||||
|
c.drawLine(cx + dx - halfW, left + 2f * u, cx + dx, tipY, line);
|
||||||
|
c.drawLine(cx + dx + halfW, right + 2f * u, cx + dx, tipY, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The height of the grin's upper lip {@code dx} from the middle. */
|
||||||
|
private static float lip(float dx, float gw, float gt, float sag) {
|
||||||
|
float t = (gw - Math.abs(dx)) / (2f * gw);
|
||||||
|
return gt + 2f * t * (1f - t) * sag;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------- Left: the sign under the cobweb ----------
|
// ---------- Left: the sign under the cobweb ----------
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 325 KiB After Width: | Height: | Size: 334 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 295 KiB After Width: | Height: | Size: 304 KiB |
Reference in New Issue
Block a user