Skip to content

MeshPickingSettings.require_markers = true doesn't ignore UI nodes without RayCastPickable #17023

@MatrixDev

Description

@MatrixDev

Bevy version

0.15.0

Relevant system information

- cargo 1.83.0 (5ffbef321 2024-10-29)
- MacOS Sonoma 14.1.1 (23B81)
- SystemInfo { os: "MacOS 14.1.1 ", kernel: "23.1.0", cpu: "Apple M1 Max", core_count: "10", memory: "64.0 GiB" }
- AdapterInfo { name: "Apple M1 Max", vendor: 0, device: 0, device_type: IntegratedGpu, driver: "", driver_info: "", backend: Metal }

What you did

I'm using bevy::picking to pick meshes from the main camera. I also have a different camera with some UI overlay that provides context information (it is shown over the objects). In my case I have only few types of entities that can be picked, so instead of marking everything with PickingBehavior::IGNORE I'm just marking which entities I want to be pickable with RayCastPickable (also MeshPickingSettings.require_markers = true).

What went wrong

UI entity always steals all pointer events:
Image

All this happens despite both entity and its camera having no RayCastPickable marker:
Image
Image

Additional information

The only workaround so far is to manually mark every UI node with PickingBehavior::IGNORE but this becomes very tedious and error prone with ever increasing number of different entities.

Example code:

use bevy::prelude::*;
use bevy::render::view::RenderLayers;
use bevy_inspector_egui::quick::WorldInspectorPlugin;

fn main() {
    let app = &mut App::new();
    app
        .add_plugins((
            DefaultPlugins,
            MeshPickingPlugin, WorldInspectorPlugin::default(),
        ))
        .add_systems(Startup, startup);

    app.world_mut().resource_mut::<MeshPickingSettings>().require_markers = true;
    app.run();
}

fn startup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    commands.spawn((
        Camera3d::default(),
        Transform::from_xyz(2.0, 1.0, 2.0).looking_at(Vec3::ZERO, Vec3::Y),
        RayCastPickable,
    ));

    commands.spawn((
        PointLight {
            shadows_enabled: true,
            ..default()
        },
        Transform::from_xyz(4.0, 8.0, 4.0),
    ));

    commands.spawn((
        Mesh3d(meshes.add(Cuboid::from_length(1.0))),
        MeshMaterial3d(materials.add(Color::srgb(1.0, 0.0, 0.0))),
        RayCastPickable,
    ))
        .observe(on_pointer_enter)
        .observe(on_pointer_leave);

    let ui_camera = commands.spawn((
        Name::new("UI Camera"),
        Camera2d,
        Camera {
            clear_color: ClearColorConfig::None,
            order: 1,
            ..default()
        },
        RenderLayers::layer(1),
    )).id();

    commands.spawn((
        Name::new("UI Node"),
        Node {
            position_type: PositionType::Absolute,
            top: Val::Percent(33.0),
            width: Val::Percent(100.0),
            height: Val::Percent(33.0),
            ..default()
        },
        TargetCamera(ui_camera),
        BackgroundColor(Color::WHITE.with_alpha(0.1)),
    ));
}

fn on_pointer_enter(
    event: Trigger<Pointer<Over>>,
    query: Query<&MeshMaterial3d<StandardMaterial>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    if let Ok(material) = query.get(event.target) {
        if let Some(material) = materials.get_mut(material) {
            material.base_color = Color::srgb(0.0, 0.0, 1.0);
        }
    }
}

fn on_pointer_leave(
    event: Trigger<Pointer<Out>>,
    query: Query<&MeshMaterial3d<StandardMaterial>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    if let Ok(material) = query.get(event.target) {
        if let Some(material) = materials.get_mut(material) {
            material.base_color = Color::srgb(1.0, 0.0, 0.0);
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-BugAn unexpected or incorrect behaviorS-Needs-TriageThis issue needs to be labelled

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions