@@ -373,8 +373,9 @@ impl Touches {
373
373
}
374
374
TouchPhase :: Moved => {
375
375
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
378
379
new_touch. position = event. position ;
379
380
new_touch. force = event. force ;
380
381
self . pressed . insert ( event. id , new_touch) ;
@@ -427,8 +428,15 @@ pub fn touch_screen_input_system(
427
428
touch_state. just_canceled . clear ( ) ;
428
429
}
429
430
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
+ }
432
440
}
433
441
}
434
442
@@ -551,6 +559,69 @@ mod test {
551
559
assert_ne ! ( touch. previous_position, touch. position) ;
552
560
}
553
561
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
+
554
625
#[ test]
555
626
fn touch_pressed ( ) {
556
627
use crate :: { touch:: TouchPhase , TouchInput , Touches } ;
0 commit comments