feat(engine): Android UX sweep — tap-to-move, safe area, HUD polish
Single-tap auto-move (input_plugin): - Remove 0.5 s double-tap window; any uncommitted TouchPhase::Ended on a face-up card now fires MoveRequestEvent immediately. Bottom safe-area inset (layout, table_plugin): - compute_layout gains safe_area_bottom param; height budget and bottom margin both respect the navigation bar reservation. Card back contrast (card_plugin): - CardBackFrame child sprite (gray, card_size + 3 px, local z=-0.01) spawned behind every face-down card so the dark back_0.png reads as a distinct rectangle against the dark felt. HUD action bar compactness (hud_plugin): - max_width 50% → 65% on the action button row; 6 buttons now wrap to 2 rows instead of 3 on a 360 dp phone. Dynamic tableau fan fraction (layout, card_plugin): - Layout gains available_tableau_height field. - update_tableau_fan_frac system (after GameMutation, before sync_cards_on_change) grows face-up fan from 0.25 to the window max as revealed column depth increases. Face-down fan is left at the window-adaptive value so stacks stay visible. ModesPopover + MenuPopover light-dismiss (hud_plugin): - Fullscreen transparent Button backdrop spawned at Z_HUD+4 behind each popover; tapping outside the panel despawns both panel and backdrop. Stock badge legibility (card_plugin): - Badge font TYPE_CAPTION (11 pt) → TYPE_BODY (14 pt); background sprite 28×16 → 34×20 world units. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -163,8 +163,10 @@ fn setup_table(
|
||||
// Safe-area insets arrive from JNI asynchronously; they are almost always
|
||||
// 0 here (populated ~frame 2-3). on_safe_area_changed fires when they
|
||||
// arrive and issues a synthetic WindowResized to re-snap all game objects.
|
||||
let safe_area_top = safe_area.as_deref().copied().unwrap_or_default().top / scale;
|
||||
let layout = compute_layout(window_size, safe_area_top);
|
||||
let insets = safe_area.as_deref().copied().unwrap_or_default();
|
||||
let safe_area_top = insets.top / scale;
|
||||
let safe_area_bottom = insets.bottom / scale;
|
||||
let layout = compute_layout(window_size, safe_area_top, safe_area_bottom);
|
||||
|
||||
let selected_bg = settings.as_ref().map_or(0, |s| s.0.selected_background);
|
||||
|
||||
@@ -300,8 +302,10 @@ fn on_window_resized(
|
||||
};
|
||||
let window_size = Vec2::new(ev.width, ev.height);
|
||||
let scale = windows.iter().next().map_or(1.0, |w| w.scale_factor());
|
||||
let safe_area_top = safe_area.as_deref().copied().unwrap_or_default().top / scale;
|
||||
let new_layout = compute_layout(window_size, safe_area_top);
|
||||
let insets = safe_area.as_deref().copied().unwrap_or_default();
|
||||
let safe_area_top = insets.top / scale;
|
||||
let safe_area_bottom = insets.bottom / scale;
|
||||
let new_layout = compute_layout(window_size, safe_area_top, safe_area_bottom);
|
||||
|
||||
if let Some(layout_res) = layout_res.as_deref_mut() {
|
||||
layout_res.0 = new_layout.clone();
|
||||
|
||||
Reference in New Issue
Block a user