feat(engine): add Terminal cursor block to splash overlay
Splash now renders the design system's signature `▌` cyan terminal- cursor glyph (96px) above the wordmark, matching docs/ui-mockups/ splash-mobile.html. The cursor uses ACCENT_PRIMARY and fades on the same per-frame alpha schedule as the title and subtitle so the brand beat still dissolves as a single layer. Did NOT pull in the mockup's full boot-loader treatment (scanline overlay, ✓ check log lines, progress bar, ROOT@SOLITAIRE prompt) — those are aesthetic features that warrant their own commit, not this token-port pass. The splash already consumed every relevant ui_theme token; the cursor glyph is the single highest-signal visual element the spec called for. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -101,6 +101,15 @@ struct SplashTitle;
|
|||||||
#[derive(Component, Debug)]
|
#[derive(Component, Debug)]
|
||||||
struct SplashSubtitle;
|
struct SplashSubtitle;
|
||||||
|
|
||||||
|
/// Marker on the cyan "terminal cursor" block (`▌`) painted above the
|
||||||
|
/// title. Visual signature of the Terminal design system per
|
||||||
|
/// `docs/ui-mockups/design-system.md` — the same `#6fc2ef` block
|
||||||
|
/// appears on the card-back theme, on the splash, and (per spec) is
|
||||||
|
/// the project's cursor motif. Faded together with the rest of the
|
||||||
|
/// splash so the dissolve still reads as one layer.
|
||||||
|
#[derive(Component, Debug)]
|
||||||
|
struct SplashCursor;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Systems
|
// Systems
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -129,6 +138,14 @@ fn spawn_splash(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let font_handle = font_res.map(|f| f.0.clone()).unwrap_or_default();
|
let font_handle = font_res.map(|f| f.0.clone()).unwrap_or_default();
|
||||||
|
let cursor_font = TextFont {
|
||||||
|
font: font_handle.clone(),
|
||||||
|
// Larger than TYPE_DISPLAY so the cursor block reads as the
|
||||||
|
// signature element above the wordmark. Hand-tuned literal —
|
||||||
|
// a one-off display character outside the regular text scale.
|
||||||
|
font_size: 96.0,
|
||||||
|
..default()
|
||||||
|
};
|
||||||
let title_font = TextFont {
|
let title_font = TextFont {
|
||||||
font: font_handle.clone(),
|
font: font_handle.clone(),
|
||||||
font_size: TYPE_DISPLAY,
|
font_size: TYPE_DISPLAY,
|
||||||
@@ -171,6 +188,12 @@ fn spawn_splash(
|
|||||||
GlobalZIndex(Z_SPLASH),
|
GlobalZIndex(Z_SPLASH),
|
||||||
))
|
))
|
||||||
.with_children(|root| {
|
.with_children(|root| {
|
||||||
|
root.spawn((
|
||||||
|
SplashCursor,
|
||||||
|
Text::new("\u{258C}"), // ▌ — the Terminal cursor block.
|
||||||
|
cursor_font,
|
||||||
|
TextColor(initial_title),
|
||||||
|
));
|
||||||
root.spawn((
|
root.spawn((
|
||||||
SplashTitle,
|
SplashTitle,
|
||||||
Text::new("Solitaire Quest"),
|
Text::new("Solitaire Quest"),
|
||||||
@@ -219,12 +242,23 @@ fn splash_alpha(age: Duration) -> Option<f32> {
|
|||||||
/// scrim + text alpha, despawning the splash once the timeline
|
/// scrim + text alpha, despawning the splash once the timeline
|
||||||
/// finishes. Despawns with descendants so the title and subtitle leave
|
/// finishes. Despawns with descendants so the title and subtitle leave
|
||||||
/// the world together.
|
/// the world together.
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
fn advance_splash(
|
fn advance_splash(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
mut roots: Query<(Entity, &mut SplashAge, &mut BackgroundColor, &Children), With<SplashRoot>>,
|
mut roots: Query<(Entity, &mut SplashAge, &mut BackgroundColor, &Children), With<SplashRoot>>,
|
||||||
mut titles: Query<&mut TextColor, (With<SplashTitle>, Without<SplashSubtitle>)>,
|
mut titles: Query<
|
||||||
mut subtitles: Query<&mut TextColor, (With<SplashSubtitle>, Without<SplashTitle>)>,
|
&mut TextColor,
|
||||||
|
(With<SplashTitle>, Without<SplashSubtitle>, Without<SplashCursor>),
|
||||||
|
>,
|
||||||
|
mut subtitles: Query<
|
||||||
|
&mut TextColor,
|
||||||
|
(With<SplashSubtitle>, Without<SplashTitle>, Without<SplashCursor>),
|
||||||
|
>,
|
||||||
|
mut cursors: Query<
|
||||||
|
&mut TextColor,
|
||||||
|
(With<SplashCursor>, Without<SplashTitle>, Without<SplashSubtitle>),
|
||||||
|
>,
|
||||||
) {
|
) {
|
||||||
for (entity, mut age, mut bg, children) in &mut roots {
|
for (entity, mut age, mut bg, children) in &mut roots {
|
||||||
age.0 = age.0.saturating_add(time.delta());
|
age.0 = age.0.saturating_add(time.delta());
|
||||||
@@ -239,9 +273,16 @@ fn advance_splash(
|
|||||||
bg.0 = scrim;
|
bg.0 = scrim;
|
||||||
|
|
||||||
// Walk the splash root's direct children for the title /
|
// Walk the splash root's direct children for the title /
|
||||||
// subtitle markers and update their alpha. The hierarchy is
|
// subtitle / cursor markers and update their alpha. The
|
||||||
// shallow (root → 2 text children) so a small loop is fine.
|
// hierarchy is shallow (root → 3 text children) so a small
|
||||||
|
// loop is fine.
|
||||||
for child in children.iter() {
|
for child in children.iter() {
|
||||||
|
if let Ok(mut color) = cursors.get_mut(child) {
|
||||||
|
let mut c = ACCENT_PRIMARY;
|
||||||
|
c.set_alpha(alpha);
|
||||||
|
color.0 = c;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if let Ok(mut color) = titles.get_mut(child) {
|
if let Ok(mut color) = titles.get_mut(child) {
|
||||||
let mut c = ACCENT_PRIMARY;
|
let mut c = ACCENT_PRIMARY;
|
||||||
c.set_alpha(alpha);
|
c.set_alpha(alpha);
|
||||||
|
|||||||
Reference in New Issue
Block a user