fix(engine): resize cards along with the rest of the layout
CI / Test & Lint (push) Failing after 24s
CI / Release Build (push) Has been skipped

The first resize-jitter fix (366fd6d) only snapped card transforms,
not the Sprite::custom_size. Cards stayed at the old size after a
window resize until the next StateChangedEvent (move, draw, undo,
new-game) refreshed them via sync_cards_on_change. Reported during
smoke testing: "the placeholder grey boxes change size but the cards
do not until I make an update to the window".

Replace the manual transform-only loop in snap_cards_on_window_resize
with a call to sync_cards(slide_secs = 0.0). update_card_entity
unconditionally inserts a fresh Sprite via card_sprite() with the
current layout.card_size, so cards now visibly resize. With
slide_secs=0 it also takes the snap branch (no CardAnim slide), so
the underlying jitter fix from 366fd6d is preserved.

apply_stock_empty_indicator is still called separately because
sync_cards doesn't touch the stock-empty "↺" label.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
funman300
2026-04-29 22:52:16 +00:00
parent 366fd6d127
commit b10e1a5a87
+26 -17
View File
@@ -1116,7 +1116,8 @@ fn update_stock_empty_indicator(
); );
} }
/// Snaps every card sprite to its target position when the window is resized. /// Snaps every card sprite to its target position and size when the window
/// is resized.
/// ///
/// This replaces the old "fire `StateChangedEvent` from `on_window_resized`" /// This replaces the old "fire `StateChangedEvent` from `on_window_resized`"
/// path. That path went through `sync_cards_on_change` → `update_card_entity`, /// path. That path went through `sync_cards_on_change` → `update_card_entity`,
@@ -1125,10 +1126,11 @@ fn update_stock_empty_indicator(
/// retargeted the tween from the card's mid-slide position, so cards never /// retargeted the tween from the card's mid-slide position, so cards never
/// reached steady state — the visible "snap back and forth" jitter. /// reached steady state — the visible "snap back and forth" jitter.
/// ///
/// Cards now snap directly (no slide), matching the instant repositioning /// Calls `sync_cards` with `slide_secs = 0.0` so `update_card_entity` snaps
/// already used for backgrounds and pile markers in /// instantly (line `(cur - target).length() > 1.0 && slide_secs > 0.0` falls
/// `table_plugin::on_window_resized`. Any in-flight `CardAnim` is removed so /// to the snap branch), refreshes the `Sprite` with the new
/// it cannot keep writing the old target translation after the snap. /// `layout.card_size` (so cards visibly resize, not just reposition), and
/// removes any in-flight `CardAnim`.
/// ///
/// The "↺" stock-empty label's `font_size` is derived from /// The "↺" stock-empty label's `font_size` is derived from
/// `layout.card_size.x`, so this system also reapplies the stock indicator — /// `layout.card_size.x`, so this system also reapplies the stock indicator —
@@ -1137,13 +1139,15 @@ fn update_stock_empty_indicator(
/// ///
/// Scheduled `.after(LayoutSystem::UpdateOnResize)` so `LayoutResource` has /// Scheduled `.after(LayoutSystem::UpdateOnResize)` so `LayoutResource` has
/// been refreshed by `table_plugin::on_window_resized` before this runs. /// been refreshed by `table_plugin::on_window_resized` before this runs.
#[allow(clippy::type_complexity)] #[allow(clippy::too_many_arguments)]
fn snap_cards_on_window_resize( fn snap_cards_on_window_resize(
mut events: MessageReader<WindowResized>, mut events: MessageReader<WindowResized>,
mut commands: Commands, mut commands: Commands,
game: Option<Res<GameStateResource>>, game: Option<Res<GameStateResource>>,
layout: Option<Res<LayoutResource>>, layout: Option<Res<LayoutResource>>,
mut entities: Query<(Entity, &CardEntity, &mut Transform)>, settings: Option<Res<SettingsResource>>,
card_images: Option<Res<CardImageSet>>,
entities: Query<(Entity, &CardEntity, &Transform)>,
mut pile_markers: Query<(Entity, &PileMarker, &mut Sprite)>, mut pile_markers: Query<(Entity, &PileMarker, &mut Sprite)>,
label_children: Query<(Entity, &ChildOf), With<StockEmptyLabel>>, label_children: Query<(Entity, &ChildOf), With<StockEmptyLabel>>,
) { ) {
@@ -1153,16 +1157,21 @@ fn snap_cards_on_window_resize(
let Some(game) = game else { return }; let Some(game) = game else { return };
let Some(layout) = layout else { return }; let Some(layout) = layout else { return };
let mut targets: HashMap<u32, (Vec2, f32)> = HashMap::new(); let selected_back = settings.as_ref().map_or(0, |s| s.0.selected_card_back);
for (card, pos, z) in card_positions(&game.0, &layout.0) { let back_colour = card_back_colour(selected_back);
targets.insert(card.id, (pos, z)); let color_blind = settings.as_ref().is_some_and(|s| s.0.color_blind_mode);
}
for (entity, marker, mut transform) in &mut entities { sync_cards(
if let Some(&(pos, z)) = targets.get(&marker.card_id) { commands.reborrow(),
transform.translation = Vec3::new(pos.x, pos.y, z); &game.0,
commands.entity(entity).remove::<CardAnim>(); &layout.0,
} 0.0,
} back_colour,
color_blind,
&entities,
card_images.as_deref(),
selected_back,
);
apply_stock_empty_indicator( apply_stock_empty_indicator(
&mut commands, &mut commands,