Merge pull request 'fix(engine): resize pile-marker outline and watermark children on relayout' (#131) from fix/pile-marker-child-resize into master
This commit is contained in:
@@ -362,7 +362,15 @@ fn on_window_resized(
|
|||||||
(&mut Sprite, &mut Transform),
|
(&mut Sprite, &mut Transform),
|
||||||
(With<TableBackground>, Without<PileMarker>),
|
(With<TableBackground>, Without<PileMarker>),
|
||||||
>,
|
>,
|
||||||
mut markers: Query<(&PileMarker, &mut Sprite, &mut Transform), Without<TableBackground>>,
|
mut markers: Query<
|
||||||
|
(&PileMarker, &mut Sprite, &mut Transform, Option<&Children>),
|
||||||
|
Without<TableBackground>,
|
||||||
|
>,
|
||||||
|
mut marker_outlines: Query<
|
||||||
|
&mut Sprite,
|
||||||
|
(Without<PileMarker>, Without<TableBackground>, Without<Text2d>),
|
||||||
|
>,
|
||||||
|
mut marker_labels: Query<&mut TextFont, With<Text2d>>,
|
||||||
) {
|
) {
|
||||||
let Some(ev) = events.read().last() else {
|
let Some(ev) = events.read().last() else {
|
||||||
return;
|
return;
|
||||||
@@ -373,6 +381,14 @@ fn on_window_resized(
|
|||||||
let safe_area_top = insets.top / scale;
|
let safe_area_top = insets.top / scale;
|
||||||
let safe_area_bottom = insets.bottom / scale;
|
let safe_area_bottom = insets.bottom / scale;
|
||||||
let hud_visible = hud_vis.as_deref().copied().unwrap_or_default() == HudVisibility::Visible;
|
let hud_visible = hud_vis.as_deref().copied().unwrap_or_default() == HudVisibility::Visible;
|
||||||
|
// Android surface sizes after fold/unfold are unreliable (winit does not
|
||||||
|
// forward every content-rect change), so make each relayout observable
|
||||||
|
// in logcat — this is the primary evidence channel for foldable bugs.
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
info!(
|
||||||
|
"layout: resize to {:.0}x{:.0} (insets top={:.0} bottom={:.0}, hud={hud_visible})",
|
||||||
|
window_size.x, window_size.y, insets.top, insets.bottom
|
||||||
|
);
|
||||||
let mut new_layout = compute_layout(window_size, safe_area_top, safe_area_bottom, hud_visible);
|
let mut new_layout = compute_layout(window_size, safe_area_top, safe_area_bottom, hud_visible);
|
||||||
|
|
||||||
// compute_layout sizes the fan for a worst-case column; refine it to the
|
// compute_layout sizes the fan for a worst-case column; refine it to the
|
||||||
@@ -394,11 +410,27 @@ fn on_window_resized(
|
|||||||
transform.translation.y = 0.0;
|
transform.translation.y = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (marker, mut sprite, mut transform) in &mut markers {
|
for (marker, mut sprite, mut transform, children) in &mut markers {
|
||||||
if let Some(pos) = new_layout.pile_positions.get(&marker.0) {
|
if let Some(pos) = new_layout.pile_positions.get(&marker.0) {
|
||||||
sprite.custom_size = Some(new_layout.card_size);
|
sprite.custom_size = Some(new_layout.card_size);
|
||||||
transform.translation.x = pos.x;
|
transform.translation.x = pos.x;
|
||||||
transform.translation.y = pos.y;
|
transform.translation.y = pos.y;
|
||||||
|
// Children carry the outline frame and the "A"/"K" watermark.
|
||||||
|
// They are sized at spawn from that layout's card size, so they
|
||||||
|
// must be re-derived here too or a resize (fold/unfold, rotation)
|
||||||
|
// leaves them at the stale size — visible as oversized grey
|
||||||
|
// frames on empty piles.
|
||||||
|
let outline_size =
|
||||||
|
new_layout.card_size + Vec2::splat(PILE_MARKER_OUTLINE_WIDTH * 2.0);
|
||||||
|
let font_size = new_layout.card_size.x * 0.28;
|
||||||
|
for child in children.into_iter().flatten() {
|
||||||
|
if let Ok(mut outline) = marker_outlines.get_mut(*child) {
|
||||||
|
outline.custom_size = Some(outline_size);
|
||||||
|
}
|
||||||
|
if let Ok(mut label) = marker_labels.get_mut(*child) {
|
||||||
|
label.font_size = font_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -623,6 +655,58 @@ mod tests {
|
|||||||
assert_eq!(types.len(), 12);
|
assert_eq!(types.len(), 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn resize_updates_marker_outline_and_watermark_children() {
|
||||||
|
// Regression (found on Galaxy Fold 7, v0.41.0): `on_window_resized`
|
||||||
|
// resized the marker fill sprite but never its children, so after a
|
||||||
|
// fold/unfold the outline frame and "A"/"K" watermark stayed at
|
||||||
|
// spawn-time size — rendering as oversized grey slabs on empty piles.
|
||||||
|
let mut app = headless_app();
|
||||||
|
// Shrink the window well below the 1280×800 spawn default.
|
||||||
|
app.world_mut().write_message(WindowResized {
|
||||||
|
window: Entity::PLACEHOLDER,
|
||||||
|
width: 640.0,
|
||||||
|
height: 480.0,
|
||||||
|
});
|
||||||
|
app.update();
|
||||||
|
|
||||||
|
let card_size = app.world().resource::<LayoutResource>().0.card_size;
|
||||||
|
let expected_outline = card_size + Vec2::splat(PILE_MARKER_OUTLINE_WIDTH * 2.0);
|
||||||
|
let expected_font = card_size.x * 0.28;
|
||||||
|
|
||||||
|
let marker_children: Vec<Entity> = {
|
||||||
|
let mut q = app.world_mut().query::<(&PileMarker, &Children)>();
|
||||||
|
q.iter(app.world())
|
||||||
|
.flat_map(|(_, c)| c.iter().collect::<Vec<_>>())
|
||||||
|
.collect()
|
||||||
|
};
|
||||||
|
assert!(
|
||||||
|
!marker_children.is_empty(),
|
||||||
|
"pile markers must have outline/watermark children"
|
||||||
|
);
|
||||||
|
let mut outlines = 0;
|
||||||
|
let mut labels = 0;
|
||||||
|
for child in marker_children {
|
||||||
|
if let Some(sprite) = app.world().entity(child).get::<Sprite>() {
|
||||||
|
assert_eq!(
|
||||||
|
sprite.custom_size,
|
||||||
|
Some(expected_outline),
|
||||||
|
"outline child must track the resized card size",
|
||||||
|
);
|
||||||
|
outlines += 1;
|
||||||
|
}
|
||||||
|
if let Some(font) = app.world().entity(child).get::<TextFont>() {
|
||||||
|
assert!(
|
||||||
|
(font.font_size - expected_font).abs() < 0.01,
|
||||||
|
"watermark font must track the resized card size",
|
||||||
|
);
|
||||||
|
labels += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert_eq!(outlines, 12, "all 12 markers carry an outline child");
|
||||||
|
assert!(labels >= 11, "tableau + foundation markers carry watermarks");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pile_markers_hide_when_pile_is_occupied() {
|
fn pile_markers_hide_when_pile_is_occupied() {
|
||||||
// After a fresh deal: the 7 tableau piles + the stock pile are
|
// After a fresh deal: the 7 tableau piles + the stock pile are
|
||||||
|
|||||||
Reference in New Issue
Block a user