Open Vrixyz opened 8 months ago
This is caused by bevy's lack of inter-frame event ordering. There is no way to know if a mouse up came before or after a mouse move, or a mouse down before or after a mouse move within the same frame. Additionally, all the events are split into independent events. Once the bevy issue is fixed, the plugin will also need to switch to a unified pointer event stream.
Context
I want to implement a drag and drop, when dropping, I want to "snap" the position.
bug description
Sometimes, the snapping occurs incorrectly. this bug doesn't happen on all sessions, but is easily reproducible after a few relaunches.
DragEnd
event sometimes occurs beforeDrag
events: so logic inDragEnd
gets overridden by logic inDrag
.Video description
https://github.com/aevyrie/bevy_mod_picking/assets/2290685/5302bd08-95a4-407b-83e6-e90f8ee3ae38
More details
part of relevant code
```rs fn round_to_nearest(value: f32) -> f32 { (value / multiple).round() * 50f32 } ... // handle drag On::>::listener_component_mut::(|drag, transform| {
transform.translation.x += drag.delta.x;
transform.translation.y -= drag.delta.y;
}),
On::>::run(|event: ListenerMut>,
mut transforms: Query<&mut Transform>,| {
let Ok(mut transform) = transforms.get_mut(event.listener()) else {
return;
};
// snap to position
transform.translation.x = round_to_nearest(transform.translation.x, 60f32); // Make the square follow the mouse
transform.translation.y = round_to_nearest(transform.translation.y, 60f32);
// re-enable picking
commands.entity(event.target()).insert(Pickable::default());
})
```
Trace image
Not sure why there are 2 drag events on the same frame too 🤔 ![image](https://github.com/aevyrie/bevy_mod_picking/assets/2290685/c4e84edf-b25c-4a19-9141-bf02386d421c)
full tracy trace file: drag_trace.zip
Code source:https://github.com/Vrixyz/rsword/blob/8fbe5713856d971dc2e71eaad4ac200085314dfb/src/game.rs#L121
Thoughts on fix
I looked a tiny bit into how we could fix that, and I guess we could avoid sending a
Drag
when we detect aDragEnd
? Around https://github.com/Vrixyz/bevy_mod_picking/blob/1471a9f83435f3fdd43829b90391e6ab965e0e73/crates/bevy_picking_core/src/events.rs#L417-L418Workaround
As a workaround, in user code I fire an event when a
DragEnd
is detected, so its logic is computed after lastDrag
inputs.Code Screenshot