Skip to content

Commit aa47702

Browse files
authored
fix previous_position / previous_force being discarded too early (#12556)
# Objective Fixes #12442 ## Solution Change `process_touch_event` to not update previous_position / previous_force, and change it once per frame in `touch_screen_input_system`.
1 parent 891c2f1 commit aa47702

File tree

1 file changed

+75
-4
lines changed

1 file changed

+75
-4
lines changed

crates/bevy_input/src/touch.rs

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -373,8 +373,9 @@ impl Touches {
373373
}
374374
TouchPhase::Moved => {
375375
if let Some(mut new_touch) = self.pressed.get(&event.id).cloned() {
376-
new_touch.previous_position = new_touch.position;
377-
new_touch.previous_force = new_touch.force;
376+
// NOTE: This does not update the previous_force / previous_position field;
377+
// they should be updated once per frame, not once per event
378+
// See https://github.com/bevyengine/bevy/issues/12442
378379
new_touch.position = event.position;
379380
new_touch.force = event.force;
380381
self.pressed.insert(event.id, new_touch);
@@ -427,8 +428,15 @@ pub fn touch_screen_input_system(
427428
touch_state.just_canceled.clear();
428429
}
429430

430-
for event in touch_input_events.read() {
431-
touch_state.process_touch_event(event);
431+
if !touch_input_events.is_empty() {
432+
for touch in touch_state.pressed.values_mut() {
433+
touch.previous_position = touch.position;
434+
touch.previous_force = touch.force;
435+
}
436+
437+
for event in touch_input_events.read() {
438+
touch_state.process_touch_event(event);
439+
}
432440
}
433441
}
434442

@@ -551,6 +559,69 @@ mod test {
551559
assert_ne!(touch.previous_position, touch.position);
552560
}
553561

562+
// See https://github.com/bevyengine/bevy/issues/12442
563+
#[test]
564+
fn touch_process_multi_event() {
565+
use crate::{touch::TouchPhase, TouchInput, Touches};
566+
use bevy_ecs::entity::Entity;
567+
use bevy_math::Vec2;
568+
569+
let mut touches = Touches::default();
570+
571+
let started_touch_event = TouchInput {
572+
phase: TouchPhase::Started,
573+
position: Vec2::splat(4.0),
574+
window: Entity::PLACEHOLDER,
575+
force: None,
576+
id: 4,
577+
};
578+
579+
let moved_touch_event1 = TouchInput {
580+
phase: TouchPhase::Moved,
581+
position: Vec2::splat(5.0),
582+
window: Entity::PLACEHOLDER,
583+
force: None,
584+
id: started_touch_event.id,
585+
};
586+
587+
let moved_touch_event2 = TouchInput {
588+
phase: TouchPhase::Moved,
589+
position: Vec2::splat(6.0),
590+
window: Entity::PLACEHOLDER,
591+
force: None,
592+
id: started_touch_event.id,
593+
};
594+
595+
// tick 1: touch is started during frame
596+
for touch in touches.pressed.values_mut() {
597+
// update ONCE, at start of frame
598+
touch.previous_position = touch.position;
599+
}
600+
touches.process_touch_event(&started_touch_event);
601+
touches.process_touch_event(&moved_touch_event1);
602+
touches.process_touch_event(&moved_touch_event2);
603+
604+
{
605+
let touch = touches.get_pressed(started_touch_event.id).unwrap();
606+
assert_eq!(touch.previous_position, started_touch_event.position);
607+
assert_eq!(touch.position, moved_touch_event2.position);
608+
}
609+
610+
// tick 2: touch was started before frame
611+
for touch in touches.pressed.values_mut() {
612+
touch.previous_position = touch.position;
613+
}
614+
touches.process_touch_event(&moved_touch_event1);
615+
touches.process_touch_event(&moved_touch_event2);
616+
touches.process_touch_event(&moved_touch_event1);
617+
618+
{
619+
let touch = touches.get_pressed(started_touch_event.id).unwrap();
620+
assert_eq!(touch.previous_position, moved_touch_event2.position);
621+
assert_eq!(touch.position, moved_touch_event1.position);
622+
}
623+
}
624+
554625
#[test]
555626
fn touch_pressed() {
556627
use crate::{touch::TouchPhase, TouchInput, Touches};

0 commit comments

Comments
 (0)