fix(ui): restore original high-score windows

Replace modern overlays with the reconstructed HighScore child and DIALOG 32514 topology, exact DAT993 background, row coordinates, original strings, unpadded scores, and 21-character edit behavior. Restore OK/Cancel semantics, including Escape preserving the prefilled name and allowing an accepted empty name, with deterministic screenshot scenarios.

Test Plan:
- cargo test --all-targets
- cargo clippy --all-targets --all-features -- -D warnings
- rumdl check CHANGELOG.md RECONSTRUCTION.md README.md
- cargo run --quiet -- --simulate highscores --step 0 --screenshot /tmp/tdkpin-highscores.png
- cargo run --quiet -- --simulate name-entry --step 0 --screenshot /tmp/tdkpin-name-entry.png
- git diff --check
This commit is contained in:
2026-08-23 19:09:28 +02:00
parent c80f5e2136
commit fae322bb91
8 changed files with 148 additions and 54 deletions
+102 -45
View File
@@ -193,6 +193,20 @@ impl App {
self.loading_until = get_time() + 60.0;
}
pub fn set_simulation_highscores(&mut self) {
self.game = None;
self.return_screen = Screen::Attract;
self.screen = Screen::HighScores;
}
pub fn set_simulation_name_entry(&mut self) {
self.game = Some(Game::new(1));
self.return_screen = Screen::Playing;
self.pending_score = 6_537_393;
"TDK Pinball Player".clone_into(&mut self.name);
self.screen = Screen::NameEntry;
}
pub fn render_simulation(&self) {
self.draw_logical();
}
@@ -409,32 +423,46 @@ impl App {
fn update_name_entry(&mut self) {
while let Some(character) = get_char_pressed() {
if !character.is_control() && self.name.chars().count() < 21 {
if !character.is_control()
&& u32::from(character) <= 0xff
&& self.name.chars().count() < 21
{
self.name.push(character);
}
}
if is_key_pressed(KeyCode::Backspace) {
self.name.pop();
}
if is_key_pressed(KeyCode::Enter) && !self.name.trim().is_empty() {
insert_high_score(
&mut self.saved.high_scores,
HighScore {
name: self.name.trim().to_owned(),
score: self.pending_score,
},
);
self.save();
if self.game.as_ref().is_some_and(|game| game.finished) {
self.game = None;
self.return_screen = Screen::Attract;
} else {
self.return_screen = Screen::Playing;
}
self.screen = Screen::HighScores;
let click = is_mouse_button_pressed(MouseButton::Left).then(Self::logical_mouse);
let clicked_ok = click.is_some_and(|point| Rect::new(255.0, 256.0, 60.0, 23.0).contains(point));
let clicked_cancel =
click.is_some_and(|point| Rect::new(324.0, 256.0, 60.0, 23.0).contains(point));
if is_key_pressed(KeyCode::Escape) || clicked_cancel {
"TDK Pinball Player".clone_into(&mut self.name);
self.accept_high_score_name();
} else if is_key_pressed(KeyCode::Enter) || clicked_ok {
self.accept_high_score_name();
}
}
fn accept_high_score_name(&mut self) {
insert_high_score(
&mut self.saved.high_scores,
HighScore {
name: self.name.clone(),
score: self.pending_score,
},
);
self.save();
if self.game.as_ref().is_some_and(|game| game.finished) {
self.game = None;
self.return_screen = Screen::Attract;
} else {
self.return_screen = Screen::Playing;
}
self.screen = Screen::HighScores;
}
fn draw_logical(&self) {
let mut camera = Camera2D::from_display_rect(Rect::new(0.0, 0.0, WIDTH, HEIGHT));
camera.render_target = Some(self.render_target.clone());
@@ -1079,36 +1107,47 @@ impl App {
#[allow(clippy::cast_precision_loss)]
fn draw_high_scores(&self) {
draw_texture(&self.assets.inactive_table, 0.0, 0.0, WHITE);
draw_panel(124.0, 32.0, 392.0, 398.0);
draw_centered("TDK HIGHSCORES", 72.0, 28, BLACK);
self.draw_modal_background();
draw_rectangle(140.0, 58.0, 360.0, 22.0, Color::from_rgba(0, 0, 128, 255));
draw_rectangle_lines(140.0, 58.0, 360.0, 22.0, 2.0, WHITE);
draw_text("HighScore", 147.0, 74.0, 14.0, WHITE);
draw_texture(&self.assets.highscore_background, 140.0, 80.0, WHITE);
draw_centered_at("HIGH SCORES", 320.0, 122.0, 18, BLACK);
for (index, entry) in self.saved.high_scores.iter().take(10).enumerate() {
let y = 110.0 + index as f32 * 29.0;
draw_text(format!("{:>2}.", index + 1), 153.0, y, 17.0, BLACK);
draw_text(&entry.name, 190.0, y, 17.0, BLACK);
let score = format!("{:09}", entry.score);
draw_text(&score, 389.0, y, 17.0, Color::from_rgba(0, 72, 102, 255));
let rank = index + 1;
let y = 155.0 + index as f32 * 20.0;
let prefix = if rank < 10 { " " } else { "" };
draw_text(
format!("{prefix}{rank}. {}", entry.name),
170.0,
y,
16.0,
BLACK,
);
let score = entry.score.to_string();
let width = measure_text(&score, None, 16, 1.0).width;
draw_text(&score, 460.0 - width, y, 16.0, BLACK);
}
draw_centered("ENTER / ESC TO RETURN", 409.0, 14, BLACK);
}
fn draw_name_entry(&self) {
draw_texture(&self.assets.active_table, 0.0, 0.0, WHITE);
draw_panel(112.0, 145.0, 416.0, 170.0);
draw_centered("NEW TDK HIGHSCORE", 183.0, 28, BLACK);
draw_centered(
&format!("SCORE {:09}", self.pending_score),
218.0,
21,
BLACK,
);
draw_rectangle(
153.0,
235.0,
334.0,
38.0,
Color::from_rgba(0, 191, 209, 255),
self.draw_modal_background();
let x = 185.0;
let y = 168.0;
draw_rectangle(x, y, 270.0, 124.0, Color::from_rgba(192, 192, 192, 255));
draw_rectangle_lines(x, y, 270.0, 124.0, 2.0, WHITE);
draw_rectangle_lines(x + 2.0, y + 2.0, 266.0, 120.0, 2.0, DARKGRAY);
draw_rectangle(x + 4.0, y + 4.0, 262.0, 20.0, Color::from_rgba(0, 0, 128, 255));
draw_text(
"Congratulations! This is a Top Ten Score!",
x + 9.0,
y + 19.0,
12.0,
WHITE,
);
draw_text("Please input your name:", x + 15.0, y + 44.0, 14.0, BLACK);
draw_rectangle(x + 15.0, y + 52.0, 240.0, 21.0, WHITE);
draw_rectangle_lines(x + 14.0, y + 51.0, 242.0, 23.0, 2.0, DARKGRAY);
draw_text(
format!(
"{}{}",
@@ -1119,12 +1158,30 @@ impl App {
""
}
),
164.0,
262.0,
23.0,
x + 18.0,
y + 68.0,
14.0,
BLACK,
);
draw_centered("TYPE YOUR NAME, THEN PRESS ENTER", 296.0, 14, BLACK);
Self::draw_dialog_button(x + 70.0, y + 88.0, "OK", true);
Self::draw_dialog_button(x + 139.0, y + 88.0, "Cancel", false);
}
fn draw_modal_background(&self) {
if self.game.is_some() {
self.draw_game();
} else {
self.draw_attract();
}
}
fn draw_dialog_button(x: f32, y: f32, label: &str, default: bool) {
if default {
draw_rectangle_lines(x - 2.0, y - 2.0, 64.0, 27.0, 1.0, BLACK);
}
draw_rectangle(x, y, 60.0, 23.0, Color::from_rgba(192, 192, 192, 255));
draw_rectangle_lines(x, y, 60.0, 23.0, 2.0, WHITE);
draw_centered_at(label, x + 30.0, y + 17.0, 13, BLACK);
}
fn present(&self) {