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

Res<ButtonInput<MouseButton>> is cleared when hovering a bevy_ui interactable. #672

Open
rparrett opened this issue Jan 5, 2025 · 1 comment
Labels
bug Something isn't working

Comments

@rparrett
Copy link
Contributor

rparrett commented Jan 5, 2025

Version

0.16

Operating system & version

Macos

What you did

Have an app with InputManagerPlugin and a normal bevy_ui button.

Hover over the button, left click, and release.

Expand Code
use bevy::prelude::*;
use leafwing_input_manager::prelude::*;

#[derive(Actionlike, PartialEq, Eq, Clone, Copy, Hash, Debug, Reflect)]
enum Action {
    Run,
    Jump,
}

const NORMAL_BUTTON: Color = Color::srgb(0.15, 0.15, 0.15);

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, (button_system, button_input_system))
        .add_plugins(InputManagerPlugin::<Action>::default())
        .run();
}

fn button_system(
    mut interaction_query: Query<(&Interaction, &Children), (Changed<Interaction>, With<Button>)>,
    mut text_query: Query<&mut Text>,
) {
    for (interaction, children) in &mut interaction_query {
        let mut text = text_query.get_mut(children[0]).unwrap();
        match *interaction {
            Interaction::Pressed => {
                **text = "Press".to_string();
            }
            Interaction::Hovered => {
                **text = "Hover".to_string();
            }
            Interaction::None => {
                **text = "Button".to_string();
            }
        }
    }
}

fn button_input_system(input: Res<ButtonInput<MouseButton>>) {
    if input.is_changed() {
        info!("{:?}", input);
    }
}

fn setup(mut commands: Commands) {
    commands.spawn(Camera2d);

    commands
        .spawn(Node {
            width: Val::Percent(100.0),
            height: Val::Percent(100.0),
            align_items: AlignItems::Center,
            justify_content: JustifyContent::Center,
            ..default()
        })
        .with_children(|parent| {
            parent
                .spawn((
                    Button,
                    Node {
                        width: Val::Px(150.0),
                        height: Val::Px(65.0),
                        border: UiRect::all(Val::Px(5.0)),
                        justify_content: JustifyContent::Center,
                        align_items: AlignItems::Center,
                        ..default()
                    },
                    BackgroundColor(NORMAL_BUTTON),
                ))
                .with_child(Text::new("Button"));
        });
}

What you expected to happen

Res(ButtonInput { pressed: {}, just_pressed: {}, just_released: {} })
Res(ButtonInput { pressed: {Left}, just_pressed: {Left}, just_released: {} })
Res(ButtonInput { pressed: {}, just_pressed: {}, just_released: {Left} })

(This is the output when the button is not hovered)

What actually happened

  1. There is a debug print every frame, because LWIM is triggering Res<ButtonInput<MouseButton>>'s change detection.
  2. just_released and just_released are never Left at any point.
  3. LWIM is seemingly clearing ButtonInput on purpose, yet pressed occasionally does have a value.
Res(ButtonInput { pressed: {}, just_pressed: {}, just_released: {} }) // lots of these
Res(ButtonInput { pressed: {}, just_pressed: {}, just_released: {} })
Res(ButtonInput { pressed: {}, just_pressed: {}, just_released: {} })
Res(ButtonInput { pressed: {Left}, just_pressed: {}, just_released: {} })
Res(ButtonInput { pressed: {Left}, just_pressed: {}, just_released: {} })
Res(ButtonInput { pressed: {Left}, just_pressed: {}, just_released: {} })
Res(ButtonInput { pressed: {}, just_pressed: {}, just_released: {} }) // IMPORTANT: just_released is empty
Res(ButtonInput { pressed: {}, just_pressed: {}, just_released: {} })
Res(ButtonInput { pressed: {}, just_pressed: {}, just_released: {} })

Additional information

I got here while debugging an app that uses both leafwing-input-manager and bevy-alt-ui-navigation-lite. bevy-alt-ui-navigation-lite uses some convoluted logic and Res<ButtonInput<MouseButton>> to determine whether a nav or focus event should be sent when either hovering or clicking. After upgrading to LWIM / Bevy 0.15, this no longer works.

I think that in my case, I can just disable leafwing-input-manager's ui feature. But I'm opening this because at the very least, the change detection thing seems like a potential LWIM bug.

@rparrett rparrett added the bug Something isn't working label Jan 5, 2025
@alice-i-cecile
Copy link
Contributor

Hmm; I think we should be able to just kill the ui feature entirely at this point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants