Title screens scroll a label wider than its button, as vanilla does

Title::draw's button loop drew every title-screen label centred over its own
full width, so a label wider than the button ran over the buttons beside it
(Create World's 590 px World Type label in so_so, Multiplayer's Join Server in
hi_in). AbstractButton.extractDefaultLabel hands the label to
extractScrollingStringOverContents with a 2 px margin, and vanilla slides it
inside the button; the loop now draws through ui::scrolling_text, which is
that helper.
This commit is contained in:
sv authored and MSedgeMC committed 2026-11-01 20:04:41 +00:00
1 parent 5057e98cd3
commit 26e6743fba
2 files changed
+67 -9

No files matched your search

+23 -9
View File
@@ -461,6 +461,28 @@ pub(crate) struct Button {
/// `SpriteIconButton.TextAndIcon`: the icon at the right end, the text centred.
trailing: Option<(&'static str, f32)>,
}
impl Button {
/// `AbstractButton.extractDefaultLabel`: the label centred with a 2 px
/// margin, and slid inside the button when it does not fit
/// (`AbstractWidget.extractScrollingStringOverContents`), instead of being
/// drawn past it over the buttons beside it (so_so's 590 px World Type
/// label on Create World, hi_in's Join Server in the Multiplayer footer).
fn draw_label(&self, batch: &mut HudBatch, atlas: &HudAtlas, color: u32) {
let label = Text::literal(&self.label);
crate::ui::scrolling_text(
batch,
atlas,
&label,
self.x + 2.0,
self.x + self.w - 2.0,
self.y,
self.y + 20.0,
self.y + 6.0,
color,
);
}
}
/// Java String.hashCode for text seeds (WorldOptions.parseSeed).
pub fn parse_seed(text: &str) -> Option<i64> {
let t = text.trim();
@@ -2991,15 +3013,7 @@ Would you like to enable the Narrator or visit the Accessibility Settings?",
);
continue;
}
let tw = HudBatch::text_width(atlas, &b.label);
batch.text(
atlas,
&b.label,
b.x + (b.w / 2.0).floor() - (tw.ceil() / 2.0).floor(),
b.y + 6.0,
color,
true,
);
b.draw_label(batch, atlas, color);
if let Some((icon, size)) = b.trailing {
// TextAndIcon: `x + width - spriteWidth - 2`, centred in the height.
batch.sprite_scaled(
+44
View File
@@ -1821,3 +1821,47 @@ fn a_finished_optimization_stamps_the_level_data() {
let version = root.get("Data").and_then(|d| d.get("DataVersion"));
assert!(matches!(version, Some(Tag::Int(v)) if *v == horizon_world::DATA_VERSION));
}
/// `AbstractButton.extractDefaultLabel`: a label too wide for its button is
/// slid inside it, not drawn centred over the buttons beside it (`so_so`'s
/// 590 px World Type label on Create World, `hi_in`'s Join Server).
#[test]
fn a_button_label_wider_than_its_button_stays_inside_it() {
let atlas = HudAtlas::build(std::path::Path::new("/nonexistent/horizon-test-assets")).unwrap();
let mut b = Button {
x: 100.0,
y: 40.0,
w: 100.0,
label: "Create Backup and Load the World Anyway".into(),
enabled: true,
id: 40,
icon: None,
trailing: None,
};
assert!(HudBatch::text_width(&atlas, &b.label) > b.w - 4.0);
let mut batch = HudBatch::new([640, 480]);
b.draw_label(&mut batch, &atlas, u32::MAX);
assert!(!batch.vertices.is_empty());
for v in &batch.vertices {
assert!(
(b.x + 2.0..=b.x + b.w - 2.0).contains(&v.pos[0])
&& (b.y..=b.y + 20.0).contains(&v.pos[1]),
"label vertex {:?} outside the button",
v.pos
);
}
// A label that fits is centred in the button, as `centered_left` does.
b.label = "Done".into();
let width = HudBatch::text_width(&atlas, &b.label);
let mut batch = HudBatch::new([640, 480]);
b.draw_label(&mut batch, &atlas, u32::MAX);
let lo = batch
.vertices
.iter()
.map(|v| v.pos[0])
.fold(f32::INFINITY, f32::min);
assert!(
(lo - (b.x + 2.0 + (b.w - 4.0) / 2.0 - (width / 2.0).floor())).abs() < 0.001,
"a fitting label starts at {lo}"
);
}