mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-09 02:29:50 -10:00
A TextAndIcon button's label stays clear of its icon; tab labels stay inside their tab
SpriteIconButton.TextAndIcon.extractContents gives the label left = x + 2, right = x + width - spriteWidth - 4 and centerX = x + width / 2, and ActiveTextCollector.defaultScrollingHelper centres a label that fits on Mth.clamp(centerX, left + lineWidth / 2, right - lineWidth / 2). Title's Button::draw_label used x + 2 .. x + width - 2 for every button, so on the first-launch Accessibility screen a label that fits (fil_ph "Settings sa Aksesibilidad...", about 30 languages) ended under the icon and a wider one (fr_ca, about 35 languages) slid under it. ui::scrolling_text_around_at takes the centre; scrolling_text_at is the default centre (left + right) / 2 and draws as before. Button::draw_label_at passes the icon's room and the button's middle. MenuTabBar.MenuTabButton.renderLabel hands the tab's label to acceptScrollingWithDefaultCenter with a 1 px margin, its box 3 px lower on an unselected tab, gray only on an inactive tab (WithInactiveMessage). The Create World tabs drew it unclipped, so a label wider than its tab ran into the next one; the Statistics tabs did too, drew every label at the selected tab's height and grayed the active unselected ones. Both draw through ui::menu_tab_label now. The port ledger rows of acceptScrolling, RenderingTextCollector.acceptScrolling, acceptScrollingWithDefaultCenter, defaultScrollingHelper, extractScrollingStringOverContents, the slider's extractWidgetRenderState, TextAndIcon.extractContents (it has a caller: the Accessibility screen) and MenuTabButton.renderLabel say what is drawn now. Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01RodDbPWCByh96WKcbiEQpB
This commit is contained in:
1 parent
8d93d68f1d
commit
dd428288d1
8 files changed
+297
-40
No files matched your search
@@ -384,19 +384,42 @@ pub fn scrolling_text_at(
|
||||
y: f32,
|
||||
now_ms: i64,
|
||||
color: u32,
|
||||
) {
|
||||
// `acceptScrollingWithDefaultCenter`: `centerX = (left + right) / 2`.
|
||||
let center_x = left + ((right - left) / 2.0).floor();
|
||||
scrolling_text_around_at(
|
||||
batch, atlas, text, center_x, left, right, top, bottom, y, now_ms, color,
|
||||
);
|
||||
}
|
||||
|
||||
/// [`scrolling_text_at`] around an explicit `center_x`
|
||||
/// (`ActiveTextCollector.acceptScrolling`, which `SpriteIconButton.TextAndIcon`
|
||||
/// calls with the button's middle): a label that fits is centred on `center_x`
|
||||
/// moved as far as it must to stay between `left` and `right`
|
||||
/// (`Mth.clamp(centerX, left + lineWidth / 2, right - lineWidth / 2)`), so
|
||||
/// beside an icon it ends where the icon's room begins. A wider one is drawn
|
||||
/// from the left and slid inside the box.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn scrolling_text_around_at(
|
||||
batch: &mut HudBatch,
|
||||
atlas: &HudAtlas,
|
||||
text: &Text,
|
||||
center_x: f32,
|
||||
left: f32,
|
||||
right: f32,
|
||||
top: f32,
|
||||
bottom: f32,
|
||||
y: f32,
|
||||
now_ms: i64,
|
||||
color: u32,
|
||||
) {
|
||||
let text = text.resolved();
|
||||
let width = atlas.font.width_text(&text);
|
||||
let room = right - left;
|
||||
if width <= room {
|
||||
batch.text_styled(
|
||||
atlas,
|
||||
&text,
|
||||
centered_left(left, room, width),
|
||||
y,
|
||||
color,
|
||||
true,
|
||||
);
|
||||
let half = (width / 2.0).floor();
|
||||
let text_x = center_x.max(left + half).min(right - half);
|
||||
batch.text_styled(atlas, &text, text_x - half, y, color, true);
|
||||
return;
|
||||
}
|
||||
// Scissored to the widget: what does not fit is read as the label
|
||||
@@ -440,6 +463,37 @@ pub fn scrolling_text(
|
||||
);
|
||||
}
|
||||
|
||||
/// `MenuTabBar.MenuTabButton.renderLabel` for the tab at `x, y`: its label
|
||||
/// inside the tab less 1 px on each side, from the tab's top when selected
|
||||
/// and 3 px lower when not (`acceptScrollingWithDefaultCenter`, so one wider
|
||||
/// than the tab slides instead of running into the next tab). White, gray
|
||||
/// for an inactive tab (`WithInactiveMessage`).
|
||||
pub fn menu_tab_label(
|
||||
batch: &mut HudBatch,
|
||||
atlas: &HudAtlas,
|
||||
label: &Text,
|
||||
(x, y, width, height): (f32, f32, f32, f32),
|
||||
selected: bool,
|
||||
active: bool,
|
||||
now_ms: i64,
|
||||
) {
|
||||
let top = y + if selected { 0.0 } else { 3.0 };
|
||||
let bottom = y + height;
|
||||
scrolling_text_at(
|
||||
batch,
|
||||
atlas,
|
||||
label,
|
||||
x + 1.0,
|
||||
x + width - 1.0,
|
||||
top,
|
||||
bottom,
|
||||
// defaultScrollingHelper: `(top + bottom - lineHeight) / 2 + 1`.
|
||||
((top + bottom - 9.0) / 2.0).floor() + 1.0,
|
||||
now_ms,
|
||||
if active { u32::MAX } else { 0xFFA0_A0A0 },
|
||||
);
|
||||
}
|
||||
|
||||
/// Button (AbstractButton): nine-slice sprite plus the centred label.
|
||||
pub fn button(
|
||||
batch: &mut HudBatch,
|
||||
@@ -1642,6 +1696,51 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
/// `MenuTabButton.renderLabel` on a 24 px tab: centred on the tab, its
|
||||
/// text top at `(0 + 24 - 9) / 2 + 1 = 8` when selected and at
|
||||
/// `(3 + 24 - 9) / 2 + 1 = 10` when not; white on an active tab, selected
|
||||
/// or not, `0xA0A0A0` on an inactive one (`WithInactiveMessage`). The
|
||||
/// Statistics tabs drew every label at 8 and an active unselected one gray.
|
||||
#[test]
|
||||
fn a_tab_label_sits_lower_on_an_unselected_tab_and_is_gray_only_when_inactive() {
|
||||
let atlas = atlas();
|
||||
let label = Text::literal("Items");
|
||||
let half = (atlas.font.width_text(&label.resolved()) / 2.0).floor();
|
||||
// A 124 px tab at x = 100: `(left + right) / 2 = (101 + 223) / 2 = 162`.
|
||||
let left = 162.0 - half;
|
||||
for (selected, active, y, color) in [
|
||||
(true, true, 8.0, u32::MAX),
|
||||
(false, true, 10.0, u32::MAX),
|
||||
(false, false, 10.0, 0xFFA0_A0A0),
|
||||
] {
|
||||
let mut tab = HudBatch::new([640, 480]);
|
||||
menu_tab_label(
|
||||
&mut tab,
|
||||
&atlas,
|
||||
&label,
|
||||
(100.0, 0.0, 124.0, 24.0),
|
||||
selected,
|
||||
active,
|
||||
0,
|
||||
);
|
||||
let mut want = HudBatch::new([640, 480]);
|
||||
want.text_styled(&atlas, &label.resolved(), left, y, color, true);
|
||||
let glyphs = |b: &HudBatch| -> Vec<([u32; 2], u32)> {
|
||||
b.vertices
|
||||
.iter()
|
||||
.filter(|v| v.text == 1)
|
||||
.map(|v| ([v.pos[0].to_bits(), v.pos[1].to_bits()], v.color))
|
||||
.collect()
|
||||
};
|
||||
assert!(!glyphs(&want).is_empty());
|
||||
assert_eq!(
|
||||
glyphs(&tab),
|
||||
glyphs(&want),
|
||||
"selected {selected}, active {active}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slider_track_is_outlined_only_while_dragged() {
|
||||
let (track, handle) = slider_sprites(true, true, false);
|
||||
|
||||
@@ -326,20 +326,14 @@ impl Game<'_> {
|
||||
(false, false) => "gui/sprites/widget/tab",
|
||||
};
|
||||
ui::nine_slice(batch, atlas, sprite, x, 0.0, tw, TAB_H, u32::MAX);
|
||||
let label = Text::translate(key, &[]);
|
||||
let lw = atlas.font.width_text(&label);
|
||||
let color = if selected && active {
|
||||
u32::MAX
|
||||
} else {
|
||||
0xFFA0_A0A0
|
||||
};
|
||||
batch.text_styled(
|
||||
ui::menu_tab_label(
|
||||
batch,
|
||||
atlas,
|
||||
&label,
|
||||
(x + (tw - lw) / 2.0).floor(),
|
||||
8.0,
|
||||
color,
|
||||
true,
|
||||
&Text::translate(key, &[]),
|
||||
(x, 0.0, tw, TAB_H),
|
||||
selected,
|
||||
active,
|
||||
horizon_client::hud_overlays::now_ms(),
|
||||
);
|
||||
if selected {
|
||||
batch.fill(atlas, x + 2.0, TAB_H - 3.0, tw - 4.0, 1.0, u32::MAX);
|
||||
|
||||
@@ -470,7 +470,8 @@ pub(crate) struct Button {
|
||||
enabled: bool,
|
||||
id: u8,
|
||||
icon: Option<(&'static str, f32)>,
|
||||
/// `SpriteIconButton.TextAndIcon`: the icon at the right end, the text centred.
|
||||
/// `SpriteIconButton.TextAndIcon`: the icon at the right end, the text
|
||||
/// centred in the room left of it.
|
||||
trailing: Option<(&'static str, f32)>,
|
||||
}
|
||||
impl Button {
|
||||
@@ -479,17 +480,36 @@ impl Button {
|
||||
/// (`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).
|
||||
/// A button with a `trailing` icon is `SpriteIconButton.TextAndIcon`, whose
|
||||
/// label keeps clear of the icon: see [`Button::draw_label_at`].
|
||||
fn draw_label(&self, batch: &mut HudBatch, atlas: &HudAtlas, color: u32) {
|
||||
let label = Text::literal(&self.label);
|
||||
crate::ui::scrolling_text(
|
||||
self.draw_label_at(batch, atlas, color, crate::hud_overlays::now_ms());
|
||||
}
|
||||
|
||||
/// [`Button::draw_label`] at `now_ms`. `SpriteIconButton.TextAndIcon`
|
||||
/// (`extractContents`) hands the label to `acceptScrolling` with `left`
|
||||
/// at the button's x plus 2, `right` at its x plus width minus the
|
||||
/// sprite's width minus 4, and `centerX` at its x plus half its width: the
|
||||
/// label slides inside that box when wider, and one that fits is moved
|
||||
/// left until it ends where the icon's room begins. A button without an
|
||||
/// icon has `right` 2 short of its edge, where `centerX` is the middle of
|
||||
/// the box and nothing moves.
|
||||
fn draw_label_at(&self, batch: &mut HudBatch, atlas: &HudAtlas, color: u32, now_ms: i64) {
|
||||
let right = match self.trailing {
|
||||
Some((_, size)) => self.x + self.w - size - 4.0,
|
||||
None => self.x + self.w - 2.0,
|
||||
};
|
||||
crate::ui::scrolling_text_around_at(
|
||||
batch,
|
||||
atlas,
|
||||
&label,
|
||||
&Text::literal(&self.label),
|
||||
self.x + (self.w / 2.0).floor(),
|
||||
self.x + 2.0,
|
||||
self.x + self.w - 2.0,
|
||||
right,
|
||||
self.y,
|
||||
self.y + 20.0,
|
||||
self.y + 6.0,
|
||||
now_ms,
|
||||
color,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -535,15 +535,14 @@ impl Title {
|
||||
u32::MAX,
|
||||
);
|
||||
}
|
||||
// The label sits 3 pixels lower on unselected tabs.
|
||||
let top = if selected { 0.0 } else { 3.0 };
|
||||
batch.text_styled(
|
||||
ui::menu_tab_label(
|
||||
batch,
|
||||
atlas,
|
||||
&label,
|
||||
x + (tw / 2.0).floor() - (lw / 2.0).floor(),
|
||||
((top + TAB_BAR - 9.0) / 2.0).floor() + 1.0,
|
||||
u32::MAX,
|
||||
(x, 0.0, tw, TAB_BAR),
|
||||
selected,
|
||||
true,
|
||||
crate::hud_overlays::now_ms(),
|
||||
);
|
||||
}
|
||||
let (gx, gy) = grid(w, h, o.tab);
|
||||
|
||||
@@ -2027,3 +2027,148 @@ fn labels_at(f: &Fixture) -> (f32, f32, (f32, f32)) {
|
||||
(customize.x + 10.0, customize.y + 10.0),
|
||||
)
|
||||
}
|
||||
|
||||
/// A button with an icon at its right end (`SpriteIconButton.TextAndIcon`, the
|
||||
/// Music & Sounds button of the Accessibility screen): `extractContents` gives
|
||||
/// the label `left = x + 2` and `right = x + width - spriteWidth - 4`.
|
||||
mod text_and_icon {
|
||||
use super::*;
|
||||
|
||||
fn atlas() -> HudAtlas {
|
||||
HudAtlas::build(std::path::Path::new("/nonexistent/horizon-test-assets")).unwrap()
|
||||
}
|
||||
fn button(label: &str, icon: Option<(&'static str, f32)>) -> Button {
|
||||
Button {
|
||||
x: 30.0,
|
||||
y: 40.0,
|
||||
w: 150.0,
|
||||
label: label.into(),
|
||||
enabled: true,
|
||||
id: 0,
|
||||
icon: None,
|
||||
trailing: icon,
|
||||
}
|
||||
}
|
||||
/// The x of every vertex of the label's text.
|
||||
fn xs(batch: &HudBatch) -> Vec<f32> {
|
||||
batch
|
||||
.vertices
|
||||
.iter()
|
||||
.filter(|v| v.text == 1)
|
||||
.map(|v| v.pos[0])
|
||||
.collect()
|
||||
}
|
||||
/// The first `n` letters of a text with no repeating pattern.
|
||||
fn label(n: usize) -> String {
|
||||
"Bezpostrzydnie połōnczynie Direct Connection Join Server"
|
||||
.chars()
|
||||
.take(n)
|
||||
.collect()
|
||||
}
|
||||
fn width(atlas: &HudAtlas, label: &str) -> i32 {
|
||||
HudBatch::text_width(atlas, label).ceil() as i32
|
||||
}
|
||||
|
||||
/// A label that fits beside the icon but, centred on the button, would end
|
||||
/// under it (`Settings sa Aksesibilidad...` in `fil_ph`, and about 40 other
|
||||
/// languages) is moved left until it ends where the icon's room begins:
|
||||
/// `Mth.clamp(centerX, left + lineWidth / 2, right - lineWidth / 2)` in
|
||||
/// `defaultScrollingHelper`. It does not scroll. The same label in a plain
|
||||
/// button stays centred.
|
||||
#[test]
|
||||
fn a_label_that_fits_beside_the_icon_is_moved_clear_of_it() {
|
||||
let atlas = atlas();
|
||||
// A 16 px icon: `left = x + 2`, `right = x + 130`, `centerX = x + 75`.
|
||||
let (left, right, center) = (32, 30 + 130, 30 + 75);
|
||||
// The widest label that fits; `right - width / 2 < centerX` by most.
|
||||
let text = (1..60)
|
||||
.map(label)
|
||||
.rfind(|t| width(&atlas, t) <= right - left)
|
||||
.expect("a label that fits");
|
||||
let half = width(&atlas, &text) / 2;
|
||||
assert!(right - half < center, "{text}: {}", width(&atlas, &text));
|
||||
let drawn_from = |from: i32| {
|
||||
let mut batch = HudBatch::new([640, 480]);
|
||||
batch.text(&atlas, &text, from as f32, 46.0, u32::MAX, true);
|
||||
xs(&batch)
|
||||
};
|
||||
let draw = |b: &Button, now_ms: i64| {
|
||||
let mut batch = HudBatch::new([640, 480]);
|
||||
b.draw_label_at(&mut batch, &atlas, u32::MAX, now_ms);
|
||||
xs(&batch)
|
||||
};
|
||||
let b = button(&text, Some(("icon/music_notes", 16.0)));
|
||||
// Vanilla: `textX = right - width / 2`, drawn from `textX - width / 2`.
|
||||
assert!(draw(&b, 0) == drawn_from(right - half - half), "{text}");
|
||||
for now_ms in [700, 1500, 31_337] {
|
||||
assert!(draw(&b, now_ms) == draw(&b, 0), "it scrolls at {now_ms}");
|
||||
}
|
||||
let plain = button(&text, None);
|
||||
assert!(draw(&plain, 0) == drawn_from(center - half), "plain {text}");
|
||||
}
|
||||
|
||||
/// A label wider than the room beside the icon scrolls inside
|
||||
/// `x + 2 ..= x + width - spriteWidth - 4`, never under the icon.
|
||||
#[test]
|
||||
fn a_label_wider_than_the_room_beside_the_icon_scrolls_clear_of_it() {
|
||||
let atlas = atlas();
|
||||
let text = label(40);
|
||||
let b = button(&text, Some(("icon/music_notes", 16.0)));
|
||||
assert!(width(&atlas, &text) > 130 - 2);
|
||||
let mut seen = std::collections::BTreeSet::new();
|
||||
for now_ms in (0..40_000).step_by(250) {
|
||||
let mut batch = HudBatch::new([640, 480]);
|
||||
b.draw_label_at(&mut batch, &atlas, u32::MAX, now_ms);
|
||||
let xs = xs(&batch);
|
||||
assert!(!xs.is_empty());
|
||||
for x in &xs {
|
||||
assert!(
|
||||
(32.0..=30.0 + 150.0 - 16.0 - 4.0).contains(x),
|
||||
"{x} at {now_ms} ms"
|
||||
);
|
||||
}
|
||||
seen.insert(xs.iter().map(|x| x.to_bits()).collect::<Vec<_>>());
|
||||
}
|
||||
assert!(seen.len() > 3, "the label hardly moves");
|
||||
}
|
||||
}
|
||||
|
||||
/// `MenuTabBar.MenuTabButton.renderLabel`: a tab's label slides inside the
|
||||
/// tab's box with a 1 px margin when it is wider than the tab (here a window
|
||||
/// too narrow for the English labels), instead of running into the next tab.
|
||||
#[test]
|
||||
fn a_create_world_tab_label_wider_than_its_tab_stays_inside_it() {
|
||||
let mut f = Fixture::new();
|
||||
f.click("Singleplayer");
|
||||
let atlas = HudAtlas::build(std::path::Path::new("/nonexistent/horizon-test-assets")).unwrap();
|
||||
// 90 px wide: three 20 px tabs from x = 14, too narrow for "Game".
|
||||
let mut batch = HudBatch::new([90, 262]);
|
||||
f.title.draw(&atlas, &mut batch, (0.0, 100.0), true);
|
||||
let labels: Vec<f32> = batch
|
||||
.vertices
|
||||
.iter()
|
||||
.filter(|v| v.text == 1 && v.pos[1] < 24.0)
|
||||
.map(|v| v.pos[0])
|
||||
.collect();
|
||||
assert!(!labels.is_empty());
|
||||
let boxes: Vec<(f32, f32)> = (0..3)
|
||||
.map(|tab| {
|
||||
(
|
||||
14.0 + 20.0 * tab as f32 + 1.0,
|
||||
14.0 + 20.0 * (tab + 1) as f32 - 1.0,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
for x in &labels {
|
||||
assert!(
|
||||
boxes.iter().any(|(lo, hi)| (*lo..=*hi).contains(x)),
|
||||
"label vertex at {x} is outside every tab's box"
|
||||
);
|
||||
}
|
||||
for (tab, (lo, hi)) in boxes.iter().enumerate() {
|
||||
assert!(
|
||||
labels.iter().any(|x| (*lo..=*hi).contains(x)),
|
||||
"tab {tab} draws no label"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
ActiveTextCollector.accept inline crates/horizon-client-render/src/screen_draw.rs::text default overload: left-aligned text at x,y with default parameters
|
||||
ActiveTextCollector.acceptScrolling port crates/horizon-client-render/src/screen_draw.rs::scrolling_text gap: minor: only the screen_draw widgets (Button) scroll; ui.rs centered_text clips
|
||||
ActiveTextCollector.acceptScrollingWithDefaultCenter port crates/horizon-client-render/src/ui.rs::centered_text gap: minor: centres the message; wider text is clipped instead of scrolled
|
||||
ActiveTextCollector.defaultScrollingHelper port crates/horizon-client-render/src/screen_draw.rs::scrolling_text gap: minor: only the screen_draw widgets (Button) call it; ui.rs centered_text still clips wider text. The offset is screen_draw.rs::scroll_offset
|
||||
ActiveTextCollector.acceptScrolling port crates/horizon-client-render/src/ui.rs::scrolling_text_around_at the HudBatch widgets; a label that fits is clamped between left and right around centerX (title.rs::Button::draw_label_at passes the middle of a TextAndIcon button); screen_draw.rs::scrolling_text is the same for the screen_draw widgets
|
||||
ActiveTextCollector.acceptScrollingWithDefaultCenter port crates/horizon-client-render/src/ui.rs::scrolling_text_at centre (left + right) / 2; ui::button, ui::slider and the tab labels (ui::menu_tab_label) draw through it
|
||||
ActiveTextCollector.defaultScrollingHelper port crates/horizon-client-render/src/screen_draw.rs::scrolling_text the offset is ui.rs::scroll_offset (screen_draw.rs::scroll_offset for the screen_draw widgets); ui.rs::centered_text, for titles and text lines, still clips because vanilla does not scroll them
|
||||
ActiveTextCollector.findElementUnderCursor port crates/horizon-client-render/src/chat.rs::Chat::style_at gap: minor: hit test covers chat lines only; book links use game/books.rs book_link_at
|
||||
ActiveTextCollector.isPointInRectangle port crates/horizon-client-render/src/ui.rs::hovered half-open rectangle test with the same bounds
|
||||
ActiveTextCollector.ClickableStyleFinder.accept port crates/horizon-client-render/src/chat.rs::Chat::style_at gap: minor: only chat lines are searched for click and hover styles
|
||||
@@ -62,7 +62,7 @@ GuiGraphicsExtractor.textRendererForWidget skip:ui builds a text collector for
|
||||
GuiGraphicsExtractor.textRenderer skip:ui builds a text collector; Horizon draws text directly
|
||||
GuiGraphicsExtractor.createDefaultTextParameters skip:ui default pose, opacity and scissor for text; Horizon passes colour and rectangle directly
|
||||
GuiGraphicsExtractor.RenderingTextCollector.accept port crates/horizon-client-render/src/screen_draw.rs::text gap: minor: no hover or click registration here (see Chat::style_at)
|
||||
GuiGraphicsExtractor.RenderingTextCollector.acceptScrolling port crates/horizon-client-render/src/screen_draw.rs::scrolling_text gap: minor: only the screen_draw widgets (Button) scroll; ui.rs centered_text clips
|
||||
GuiGraphicsExtractor.RenderingTextCollector.acceptScrolling port crates/horizon-client-render/src/screen_draw.rs::scrolling_text the font's width and a 9 px line into defaultScrollingHelper, for the screen_draw widgets; ui.rs::scrolling_text_around_at is the same for the HudBatch widgets
|
||||
GuiGraphicsExtractor.ScissorStack.push inline crates/horizon-client-render/src/screen_draw.rs::paint gap: minor: the pushed rectangle replaces the current one; it is not intersected
|
||||
GuiGraphicsExtractor.ScissorStack.pop inline crates/horizon-client-render/src/screen_draw.rs::paint gap: minor: Draw::NoScissor clears the scissor instead of restoring the enclosing one
|
||||
GuiGraphicsExtractor.ScissorStack.containsPoint missing minor: hover ignores the scissor, so a widget clipped out of view can still highlight
|
||||
@@ -121,7 +121,7 @@ AbstractSelectionList.TrackedList.set skip:java delegate list wrapper
|
||||
AbstractSliderButton.getSprite inline crates/horizon-client-render/src/ui.rs::slider gap: minor: the track outline is drawn while dragged only; keyboard focus does not highlight it; hover highlights only the handle
|
||||
AbstractSliderButton.getHandleSprite inline crates/horizon-client-render/src/ui.rs::slider gap: minor: handle highlight follows hover only
|
||||
AbstractSliderButton.updateWidgetNarration skip:other narration only
|
||||
AbstractSliderButton.extractWidgetRenderState port crates/horizon-client-render/src/ui.rs::slider gap: minor: the label is clipped rather than scrolled
|
||||
AbstractSliderButton.extractWidgetRenderState port crates/horizon-client-render/src/ui.rs::slider_ext the whole message, value included, scrolls inside the slider (margin 2)
|
||||
AbstractSliderButton.handleCursor port crates/horizon-client-render/src/widgets.rs::widget_cursor gap: minor: no resize cursor while dragging
|
||||
AbstractSliderButton.setFocused missing minor: keyboard focus does not enable value changes; there is no change-value state
|
||||
AbstractSliderButton.keyPressed missing minor: Left and Right do not move a focused slider; Enter does not toggle it
|
||||
@@ -139,7 +139,7 @@ AbstractTextAreaWidget.extractBorder skip:ui frame sprite; no behaviour
|
||||
AbstractTextAreaWidget.withinContentAreaTopBottom skip:ui visibility cull while drawing lines
|
||||
AbstractWidget.extractRenderState port crates/horizon-client-render/src/ui.rs::hovered gap: minor: the scissor test is not part of the hover check
|
||||
AbstractWidget.extractTooltipForNextRenderPass port crates/horizon-client-render/src/ui.rs::tooltip gap: minor: unsure: widget hover delay not checked
|
||||
AbstractWidget.extractScrollingStringOverContents port crates/horizon-client-render/src/ui.rs::centered_text gap: minor: text is clipped, not scrolled
|
||||
AbstractWidget.extractScrollingStringOverContents port crates/horizon-client-render/src/ui.rs::scrolling_text ui::button and ui::slider (margin 2) draw it for the HudBatch widgets; screen_draw.rs::scrolling_string_over_contents for the screen_draw ones
|
||||
AbstractWidget.mouseClicked port crates/horizon-client/src/title.rs::Title::click gap: minor: click dispatch is per screen; the press sound is audio.rs Audio::play_button_click
|
||||
AbstractWidget.mouseReleased port crates/horizon-client-render/src/ui.rs::Scroll::release gap: minor: only the scroll release; widget onRelease is per screen
|
||||
AbstractWidget.mouseDragged port crates/horizon-client-render/src/ui.rs::Scroll::drag gap: minor: only scroll drag; widget onDrag is per screen
|
||||
|
||||
|
@@ -72,7 +72,7 @@ SpriteIconButton.extractLoadingStateIfLoading skip:service loading spinner only
|
||||
SpriteIconButton.Builder.sprite skip:java builder setter; Horizon draws its icon buttons with fixed sprites
|
||||
SpriteIconButton.Builder.build skip:java builder; no object is needed
|
||||
SpriteIconButton.CenteredIcon.extractContents skip:service FriendsButton (social)
|
||||
SpriteIconButton.TextAndIcon.extractContents skip:other no caller in 26.3
|
||||
SpriteIconButton.TextAndIcon.extractContents port crates/horizon-client/src/title.rs::Button::draw_label_at the Accessibility screen's Music & Sounds, Accessibility Settings and Language buttons (AccessibilityOnboardingScreen): the label in x + 2 .. x + width - icon - 4 centred on the button's middle, the icon drawn in Title::draw
|
||||
StringWidget.setMaxWidth port crates/horizon-client-render/src/screen_draw.rs::string_widget clips at max_width (CLAMPED)
|
||||
StringWidget.getWidth port crates/horizon-client-render/src/screen_draw.rs::label_width the smaller of max width and text width
|
||||
StringWidget.visitLines port crates/horizon-client-render/src/screen_draw.rs::string_widget gap: minor: SCROLLING overflow (scrolling text) is not ported; CLAMPED draws "..."
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 35 and column 134.
|
@@ -20,7 +20,7 @@ MenuTabBar.Builder.addTabs skip:java builder
|
||||
MenuTabBar.Builder.build skip:java builder
|
||||
MenuTabBar.MenuTabButton.extractWidgetRenderState inline crates/horizon-client/src/title/create_world.rs::Title::draw_create tab loop: sprite by selected and hover state, underline, label
|
||||
MenuTabBar.MenuTabButton.renderMenuBackground inline crates/horizon-client/src/title/create_world.rs::Title::draw_create menu background inside the selected tab
|
||||
MenuTabBar.MenuTabButton.renderLabel inline crates/horizon-client/src/title/create_world.rs::Title::draw_create label centred, 3 px lower on unselected tabs
|
||||
MenuTabBar.MenuTabButton.renderLabel port crates/horizon-client-render/src/ui.rs::menu_tab_label the Create World and Statistics tabs: centred, 3 px lower on unselected tabs, gray on inactive ones; a label wider than the tab (margin 1) scrolls
|
||||
MenuTabBar.MenuTabButton.renderFocusUnderline inline crates/horizon-client/src/title/create_world.rs::Title::draw_create 1 px underline under the selected tab label
|
||||
TabManager.setTabArea skip:ui tab area layout; create world computes the tab row on every draw (tabs())
|
||||
TabManager.setCurrentTab port crates/horizon-client/src/title.rs::Title::click a click on a tab sets options.tab
|
||||
|
||||
|
Reference in new issue
Block a user