Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mouse event stuck on MouseJustReleased #66

Closed
trashuj opened this issue Nov 24, 2020 · 7 comments
Closed

Mouse event stuck on MouseJustReleased #66

trashuj opened this issue Nov 24, 2020 · 7 comments

Comments

@trashuj
Copy link

trashuj commented Nov 24, 2020

Hello,
I noticed an issue that happens quite frequently in my app when an Interactable entity keeps receiving the MouseJustReleased event even when the mouse is at rest.
Sorry i dont have an easy repro... Though I managed to repro it in the events example, by adding more "planes" next to another, and clicking frantically on a plane then another then back etc..
Eventually you'll see the MouseJustReleased start pouring non stop, even if you take your hand off the mouse.

This seems to happen when you click on a plane then move the mouse out of the plane quickly, because it stops pourring events when you bring the cursor back on top of the stuck plane (if that makes sense)

I hope that's enought information, i'll try to find time to investigate this, might be an issue in the event system or in bevy's mouse input.

Here is the code i use to repro, in example/event.rs just replace the plane spawning by:

//plane
.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Plane { size: 4.9 })),
transform: Transform::from_translation(Vec3::new(-5.0, 0.0, -5.0)),
material: materials.add(Color::rgb(1.0, 1.0, 1.0).into()),
..Default::default()
})
.with(PickableMesh::default())
.with(InteractableMesh::default())
//plane
.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Plane { size: 4.9 })),
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 0.0)),
material: materials.add(Color::rgb(1.0, 1.0, 1.0).into()),
..Default::default()
})
.with(PickableMesh::default())
.with(InteractableMesh::default())
//plane
.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Plane { size: 4.9 })),
transform: Transform::from_translation(Vec3::new(0.0, 0.0, -5.0)),
material: materials.add(Color::rgb(1.0, 1.0, 1.0).into()),
..Default::default()
})
.with(PickableMesh::default())
.with(InteractableMesh::default())
//plane
.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Plane { size: 4.9 })),
transform: Transform::from_translation(Vec3::new(-5.0, 0.0, 0.0)),
material: materials.add(Color::rgb(1.0, 1.0, 1.0).into()),
..Default::default()
})
.with(PickableMesh::default())
.with(InteractableMesh::default())

Then quickly click on 1 plane, then another, then another... etc

Hope that helps!

@trashuj
Copy link
Author

trashuj commented Nov 24, 2020

looks like the issue is in interactable.rs.
if the interactable is not hovered anymore, the event is never reset.
Maybe we just need to reset it to None if it's not hovered.

@trashuj
Copy link
Author

trashuj commented Nov 24, 2020

dirty fix (seems to work fine)

pub fn generate_click_events(
// Resources
mouse_inputs: Res<Input>,
// Queries
mut interactable_query: Query<(&mut InteractableMesh, &PickableMesh)>,
) {
for (mut interactable, pickable) in interactable_query.iter_mut() {
for group in &pickable.groups {
let hover = match interactable.hover(&group) {
Ok(false) => false,
Err(_) => false,
_ => true,
};
let new_event = interactable
.watched_mouse_inputs
.iter()
.map(|button| {
(
*button,
if !hover {
MouseDownEvents::None
} else if mouse_inputs.just_released(*button) {
MouseDownEvents::MouseJustReleased
} else if mouse_inputs.just_pressed(*button) {
MouseDownEvents::MouseJustPressed
} else {
MouseDownEvents::None
},
)
})
.collect();
interactable.mouse_down_events.insert(*group, new_event);
}
}
}

@trashuj
Copy link
Author

trashuj commented Nov 24, 2020

on a side note would it be possible to send events only when the state changes?

@aevyrie
Copy link
Owner

aevyrie commented Nov 27, 2020

Thanks for the example and fix, I'll take a closer look soon.

on a side note would it be possible to send events only when the state changes?

That is how it should behave in practice, are you seeing extra events somewhere?

@aevyrie
Copy link
Owner

aevyrie commented Dec 17, 2020

As a follow up to the "only send events when the state changes", you can use this to only run on a state change.

// Only print updates if at least one event has occured.
if hover_event.is_none() && mouse_down_event.is_none() {
continue;
}

PR #79 should address this issue in interactable.rs I used a slightly condensed version of the solution you provided. Thanks!

@aevyrie aevyrie closed this as completed Dec 17, 2020
@trashuj
Copy link
Author

trashuj commented Dec 17, 2020 via email

@aevyrie
Copy link
Owner

aevyrie commented Dec 17, 2020

but I guess it's not very ECS style.

I'm right there with you, I'm not sure what the "best" way to do this is. I was just thinking the other day that it might make more sense to use the Bevy event system. ¯\_(ツ)_/¯

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants