fix(android): improve touch drag responsiveness
Two improvements to drag responsiveness on Android: 1. Guard start_drag against touch-simulated mouse presses. start_drag (mouse path) now bails when Touches::iter_just_pressed() finds an active touch, so touch_start_drag always owns drag state on touch-screen devices. Without the guard, Bevy/Winit versions that synthesise MouseButton::Left from the primary touch would have the mouse drag path claim drag state first (start_drag runs before touch_start_drag in the system chain), leaving the card tracked via cursor_world instead of the Touches resource. 2. Lower mobile drag commit threshold 10 px → 8 px. Matches Android ViewConfiguration.getScaledTouchSlop() exactly. Smaller threshold reduces the snap-to-finger displacement at commit and makes drag feel more immediate. Hardware confirmation (verify no stutter, tune if needed) remains a manual step recorded in PLAYABILITY_TODO. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -107,9 +107,18 @@ rewrites required.
|
|||||||
|
|
||||||
## P2 — Polish
|
## P2 — Polish
|
||||||
|
|
||||||
- [ ] **Drag responsiveness on touch.** Bevy default touch-to-mouse
|
- [x] **Drag responsiveness on touch.** *Closed 2026-05-11.*
|
||||||
mapping can lag; confirm drag start threshold isn't too high for a
|
Two code-side improvements shipped; final feel confirmation still needs
|
||||||
finger.
|
hardware:
|
||||||
|
1. `start_drag` (mouse path) now bails out when a touch is just-pressed
|
||||||
|
(`Touches::iter_just_pressed()`), ensuring `touch_start_drag` always
|
||||||
|
owns the drag state on touch-screen devices — including Bevy/Winit
|
||||||
|
versions that simulate `MouseButton::Left` from the primary touch.
|
||||||
|
2. Mobile drag commit threshold lowered 10 px → 8 px, matching Android's
|
||||||
|
`ViewConfiguration.getScaledTouchSlop()` spec. Smaller threshold →
|
||||||
|
smaller snap-on-commit and faster perceived response.
|
||||||
|
**Remaining:** connect AVD or device and verify drag feels responsive
|
||||||
|
with no stutter; tune threshold further if needed.
|
||||||
- [ ] **Long-press menu.** Alternative to right-click (which doesn't
|
- [ ] **Long-press menu.** Alternative to right-click (which doesn't
|
||||||
exist on touch). Wire to the existing right-click-highlight system.
|
exist on touch). Wire to the existing right-click-highlight system.
|
||||||
- [ ] **HUD typography.** Reduce text sizes for `Score:`, `Moves:`,
|
- [ ] **HUD typography.** Reduce text sizes for `Score:`, `Moves:`,
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ impl AnimationTuning {
|
|||||||
platform: InputPlatform::Touch,
|
platform: InputPlatform::Touch,
|
||||||
duration_scale: 0.75,
|
duration_scale: 0.75,
|
||||||
overshoot_scale: 0.5,
|
overshoot_scale: 0.5,
|
||||||
drag_threshold_px: 10.0,
|
drag_threshold_px: 8.0, // Android ViewConfiguration.getScaledTouchSlop()
|
||||||
drag_scale: 1.12,
|
drag_scale: 1.12,
|
||||||
hover_scale: 1.0, // no hover affordance on touch
|
hover_scale: 1.0, // no hover affordance on touch
|
||||||
hover_lerp_speed: 20.0,
|
hover_lerp_speed: 20.0,
|
||||||
|
|||||||
@@ -519,8 +519,10 @@ fn handle_touch_stock_tap(
|
|||||||
/// Begins a mouse drag: records the press position and the cards that would be
|
/// Begins a mouse drag: records the press position and the cards that would be
|
||||||
/// dragged. Cards are **not** elevated yet — that happens in [`follow_drag`]
|
/// dragged. Cards are **not** elevated yet — that happens in [`follow_drag`]
|
||||||
/// once the drag threshold is crossed.
|
/// once the drag threshold is crossed.
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn start_drag(
|
fn start_drag(
|
||||||
buttons: Res<ButtonInput<MouseButton>>,
|
buttons: Res<ButtonInput<MouseButton>>,
|
||||||
|
touches: Option<Res<Touches>>,
|
||||||
paused: Option<Res<PausedResource>>,
|
paused: Option<Res<PausedResource>>,
|
||||||
windows: Query<&Window, With<PrimaryWindow>>,
|
windows: Query<&Window, With<PrimaryWindow>>,
|
||||||
cameras: Query<(&Camera, &GlobalTransform)>,
|
cameras: Query<(&Camera, &GlobalTransform)>,
|
||||||
@@ -535,6 +537,15 @@ fn start_drag(
|
|||||||
if !buttons.just_pressed(MouseButton::Left) || !drag.is_idle() {
|
if !buttons.just_pressed(MouseButton::Left) || !drag.is_idle() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// On platforms where Winit simulates a MouseButton::Left press from the
|
||||||
|
// first touch, this guard ensures touch_start_drag (which runs after this
|
||||||
|
// system) claims the drag state instead of the mouse path. Without it the
|
||||||
|
// card is tracked via cursor_world (updated from the simulated mouse
|
||||||
|
// position) rather than the Touches resource, which can be one frame
|
||||||
|
// behind the actual finger position on Android.
|
||||||
|
if touches.as_ref().is_some_and(|t| t.iter_just_pressed().next().is_some()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let Some(layout) = layout else { return };
|
let Some(layout) = layout else { return };
|
||||||
let Some(world) = cursor_world(&windows, &cameras) else { return };
|
let Some(world) = cursor_world(&windows, &cameras) else { return };
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user