#bevy_mod_picking: the upstreamening

1 messages · Page 3 of 1

flat basin
#

That’s great news! Well done to you and all the other contributors!

flat basin
#

I’m trying to use the new bevy picking with bevy_prototype_lyon but not getting pointer over and pointer out events, when I spawn a plain mesh2d I do get these events (I have added the MeshPickingPlugin, and have the correct observers for each. If one of the picking sme’s here can tell me that there’s nothing else I should need to do then I’ll file a bug report on the bevy_prototype_lyon repo and try to fix this with Nilirad. I’ll post a link the MRE for this once I’m back at my computer. Thanks in advance for your help!

fluid sandal
#

I don't think there is support for mesh2d

flat basin
#

Maybe I'm misunderstanding something but the picking appears to work for the plain Mesh2d in the code

fluid sandal
#

odd, does it have an aabb?

flat basin
#

Oh is that how that picking backend works? So if say a mesh2d Rectangle automatically gets an aabb picking will work? But if the bevy_prototype_lyon mesh2d doesn’t get an aabb that’s why this difference in behaviour manifests?

thick umbra
#

of course no actual 2D ray casting in the XY plane, but you can cast rays against 2D meshes as if they were 3D, which is enough for picking

fluid sandal
jagged mango
#

I wanted to use avian2d Colliders with bevy_mod_picking but I think that's not possible for now, right? I will try to implement avian2d backend if that's the case. Should be quite straightforward. Just wanted to ask if there is already a backend for that, that I didn't find. 🙂

summer talon
thick umbra
jagged mango
summer talon
#

Report from user that some interactions are broken on mobile

#

Both browser emulators and phones

#

Could be that touch pointers are broken? Do the things they are pointing to use the picking events at all?

fluid sandal
#

Probably that. I haven't tested on a touch device yet.

summer talon
#

same

flat basin
# thick umbra of course no actual 2D ray casting in the XY plane, but you can cast rays agains...

I'm trying to figure out from that code why a manually spawned 2d mesh works with that picking code but one spawned via bevy_prototype_lyon does not. I have a MRE of this here (https://github.com/colepoirier/bevy_15_bevy_prototype_lyon_picking_bug_mre) can you provide some guidance on how I could start investigating this? My first thought is that the lyon mesh2d's are somehow 'behind' in layers or z-index or 3d space the point which the rays are being cast from?

thick umbra
#

You could try a manual ray cast at the mesh with the MeshRayCast system parameter to see if it's a picking-specific issue or if something goes wrong with the actual ray cast

#

Another thing to check is if the mesh has the correct Aabb, since lyon updates the mesh at runtime. IIRC it does this by swapping the mesh handle though, and I think that should trigger AABB recomputation

flat basin
#

Thanks! I tried manually adding a mesh-aabb re-computation system and that had no effect on the picking

#
fn force_update_aabb(
    mut commands: Commands,
    shapes: Query<(Entity, &Mesh2d), With<Path>>,
    meshes: Res<Assets<Mesh>>,
) {
    for (entity, mesh) in shapes.iter() {
        let mesh = meshes.get(mesh).unwrap();
        let aabb = mesh.compute_aabb().unwrap();
        println!("new aabb is {aabb:?}");
        commands.entity(entity).insert(aabb);
    }
}
#
new aabb is Aabb { center: Vec3A(0.0, 0.0, 0.0), half_extents: Vec3A(130.0, 130.0, 0.0) }
new aabb is Aabb { center: Vec3A(0.0, 0.0, 0.0), half_extents: Vec3A(130.0, 130.0, 0.0) }
#

Looks correct to me?

thick umbra
#

Yup

flat basin
#

Where in the picking code could I determine the point (?) that the ray is being cast from?

thick umbra
#

Looks like bevy_picking/src/backend.rs, ray::RayMap::repopulate

flat basin
thick umbra
#

Yes

flat basin
#

Thank you, new terminology for me

thick umbra
#

A ray towards -Z ("away from the screen")

flat basin
#

camera.viewport_to_world(camera_tfm, viewport_pos).ok() creates the ray?

#

Then in theory we could print the ray map to determine the rays?

thick umbra
#

Yes you could get Res<RayMap> and log them

flat basin
#

Thanks for the hand holding through the code, it's well written and logical, but hard to step into a new code base, haven't looked at bevy internals in 2 years

flat basin
#

Hmm nothing obvious is jumping out at me after printing out the transforms

#

Tried printing out the render layers but looks like neither of the two entities uses them (I probably misunderstood the purpose of render layers and they aren't at play here)

flat basin
#

I'd still like to know the reason why this isn't working, but I think I'm going to try implementing a point in polygon backend for 2d for now

fluid sandal
#

next step would be to check that the AABB is even being hit by debug printing or using gizmos

flat basin
#

Thanks for the guidance!

stoic flicker
#

Aevyrie said we shouldn't bother

#

Might make a nice example though

flat basin
#

I think that could be useful for implementing backends. Is there a better way to debug picking issues now that picking is upstreamed?

summer talon
#

not currently. We'll probably remake that bit.

#

could be added in a patch release no problem.

flat basin
#

Sorry are you saying it won't be useful or it wasn't upstreamed?

#

Ah sorry misread your message

summer talon
#

it might be useful, and it hasn't been upstreamed, but we might make something (new) that's similar

flat basin
#

Still trying to debug why bevy_prototype_lyon mesh2d's don't get picked, the gizmo aabb debug are correct

#

Going to have to println debug the picking process now I think 😅

summer talon
#

if you copy the debug stuff from mod_picking into your project it will probably (mostly) work

#

i was not closely involved with any of the back-end work unfortunately

#

no idea what could be causing that.

flat basin
#

I'm sure it will be obvious once I find the cause 😆

#

Hoping I find the cause...

summer talon
#

a minimal working reproduction of the issue would go a long way

flat basin
#

Does the repo not count as an MRE?

summer talon
#

there's a repo 👀

summer talon
#

oop, sorry

#

way ahead of me

flat basin
#

No worries, hard to track who see which messages in these threads!

summer talon
#

sort of ignored it because it wasn't in my direct area, but i'll take a look

flat basin
#

No problem, I appreciate your time

#

Pushed my changes to add the aabb gizmos

summer talon
#

i've got to sign off for the day, but i'll try to have a look tomorrow

#

nothing stands out as wrong to me

#

i'm surprised it doesn't work

flat basin
#

Me too, no rush on this I've been investigating small amounts with days in between

exotic maple
#

@flat basin any ideas so far, have had the same issue and haven't been able to find anything obvious, especially since picking a "normal bevy mesh" works

flat basin
#

Glad to have someone else to work on finding the root cause!

exotic maple
#

For some spammy log debugging:

fn debug_aabb(mut config_store: ResMut<GizmoConfigStore>) {
    let (_, config) = config_store.config_mut::<AabbGizmoConfigGroup>();

    config.default_color = Some(HOT_PINK.into());
    config.draw_all = true;
}

fn debug_rays(rays: Res<RayMap>, debug: Res<DebugPicking>, mut ray_cast: MeshRayCast) {
    if debug.0 {
        rays.iter().for_each(|(id, ray)| {
            debug!("ray: {id:?} => {ray:?}");
            let visibility = RayCastVisibility::Any;
            let settings = RayCastSettings::default()
                .with_visibility(visibility)
                .never_early_exit();
            let hits = ray_cast.cast_ray(*ray, &settings);
            debug!("{hits:#?}");
        });
    }
}

fn debug_picking(mut mouse_event: EventReader<PointerHits>, debug: Res<DebugPicking>) {
    if debug.0 {
        for ev in mouse_event.read() {
            trace!("{ev:?}");
        }
    }
}
flat basin
#

Sorry haven’t had the time to annotate with println debugging myself

#

I’ll run this when I have time (probably Thursday pst)

#

Thanks for the debugging code!

#

Next is probably to add printlns within the internal picking functions and systems

#

This is something that I wish we could write a unit test for

exotic maple
#

I'll definitely continue hacking on it tonight and have a 3hr train ride tomorrow I should be able to dedicate to that

flat basin
#

Here’s hoping by the time I get around to testing you’ve already solved it 😁

exotic maple
#

fn debug_rays2(
    mouse: Query<&PointerLocation>,
    debug: Res<DebugPicking>,
    mut ray_cast: MeshRayCast,
    camera_query: Query<(&Camera, &GlobalTransform)>,
) {
    if debug.0 {
        let (camera, camera_transform) = camera_query.single();
        mouse
            .iter()
            .filter_map(|p| p.location.as_ref())
            .for_each(|loc| {
                let pos = camera
                    .viewport_to_world_2d(camera_transform, loc.position)
                    .unwrap()
                    .extend(-1000.0);
                let ray = Ray3d::new(pos, Dir3::Z);
                debug!("ray: {ray:?}");
                let visibility = RayCastVisibility::Any;
                let settings = RayCastSettings::default()
                    .with_visibility(visibility)
                    .never_early_exit();
                let hits = ray_cast.cast_ray(ray, &settings);
                debug!("{hits:#?}");
            });
    }
}

Hah, it's pickable from below

#

If I am interpreting that correctly

summer talon
#

probably a normals issue then

exotic maple
#
                    .extend(1000.0);
                let ray = Ray3d::new(pos, Dir3::NEG_Z);

instead of the above doesn't hit

exotic maple
summer talon
#

a bit of both. maybe lyon's normals are backwards for some reason, but we should probably still hit faces with backwards normals ideally.

exotic maple
#

Is there an easy way to override "all of bevy" to be from a local path? I seem to have to override each of bevy_* to not have two different versions pulled in using [patch.crates-io]

summer talon
#

@thick umbra opinions on raycast backface culling?

#

the renderer dosn't seem to distinguish faces for 2d meshes

#

so there's a visual discrepancy currently

thick umbra
#

For 3D it makes sense to cull by default I think

summer talon
#

i'd be cool with that

#

we don't render 3d backfaces, so it would be confusing not to cull there

exotic maple
exotic maple
# stoic flicker Can you PR this?

@summer talon does that look like a proper fix?
I previously had no idea how the code works and not really sure this is completely correct

summer talon
#

maybe? it looks like a fix. But something's up with RayCastBackfaces, maybe we should just have Mesh2d require RayCastBackfaces?

stoic flicker
summer talon
#

tru

#

well, then yeah i support this

flat basin
fluid sandal
#

backfaces should probably not be a marker component, but matched by value.

flat basin
#

Not sure if this question makes sense but could we… flip(?) the bevy prototype lyon mesh2d’s?

fluid sandal
#

The problem is winding order

flat basin
#

So the backfaces become front faces?

exotic maple
#

Nonetheless if the backfaces are rendered by Camera2d it seems illogical to not be able to pick them

fluid sandal
#

Ideally it should match whatever the mesh/camera is set to.

flat basin
#

Am I misunderstanding the problem? My interpretation of the description of the issue is that the lyon shapes are being rebdered flipped upside down. Why can’t we fix the issue by flipping the lyon meshes?

stoic flicker
#

But bevy_picking should be robust to this

#

Since you never want to do this deliberately

flat basin
#

Ah ok, thank you, my understanding of rendering is almost non-existent

stoic flicker
#

Yeah so in 3D it makes sense to be "inside" something

#

But in 2D, if something is visible you should always be able to select it

#

Even if it's somehow upside down

flat basin
#

Thanks for the eli5 🙂

#

Really appreciate yours and everyone else’s help with this, I’d have just kept trying to figure it out periodically and getting frustrated that I couldn’t figure out what was wrong

fluid sandal
#

As far as I know, there isn't really even a concept of backface or frontface in 2d, because it's an optimizaiton that only really makes sense for 3d shapes that have volume, where there will always be front-facing triangles covering up backfacing triangles.

flat basin
#

Thanks for the eli5 from you as well Aevyrie 🙂

summer talon
#

Doing a little review of some of the open groups. It seems like there is still a reasonable amount of picking work to do on the ui integration side. I think we should keep this group open thought the 0.16 cycle until the integration seems stable and complete.

exotic maple
dusk spruce
#

https://github.com/bevyengine/bevy/pull/16103 got merged before I could bring this up, but how do you deal with non-window render targets? e.g. image render targets.
For example, I have my entire game scene rendered to a texture, with custom pointer events set to the texture as the location target. Where should the events be propagated here?

halcyon pilot
fluid sandal
fluid sandal
#

The viewport widget handles both mapping picks on the surface into the camera's world, as well as bubbling up any inputs that fail to hit anything else.

halcyon pilot
dusk spruce
fluid sandal
dusk spruce
#

Oh wait I guess you can put it inside PointerTraversal somehow? Not really sure how it works.

#

Oh it's just a query. But I still don't think there's a way to obtain the viewport entity information without a new mechanism.

fluid sandal
#

Your picking backend is just sending an event that says the viewport entity is being hit at the lowest depth. If that ends up being the only thing hit, that sends pointer events to that viewport entity.

#

So, pretty much identical to the linked window picking PR.

dusk spruce
#

Oh yeah, if I could somehow override it with my own custom impl that'd make it a lot easier. But I don't think there's a way to override PointerTraversal, so I'd not only need to create a custom pointer event, I'd need to override all backends.

#

I guess I could also make a system that catches all pointer events and sends it to the viewport entity if it has no parent. But it seems inefficient because we're checking twice now.

fluid sandal
#

You don't need to override anything. Just send a PointerHit to the viewport entity when the pointer is interacting with it.

#

For passing inut, you also need an input plugin for your viewports to inform them what pointers are interacting with the surface, and pipe that into the picking system.

dusk spruce
#

Never mind, I don't think trying to manually implement propagation this way would end well. Stuff like trigger.propagate(false) would just stop working.

thick umbra
#

Would people be opposed to renaming RayCastSettings to MeshRayCastSettings? It conflicts annoyingly with physics, I need to name my type RayCastConfig because of it

#

The system param is also MeshRayCast already, and there's MeshPickingSettings

thick umbra
summer talon
#

btw, idk if i mentioned this but we were looking at Enter/Leave events and we had two options: do up-traversal every from every hovered object between every two frames and diff, or try to exploit events already doing traversal and do it only when the hover state changes. The latter would be much more efficient, but it can't account for hierarchy changes, so I decided it wasn't going to work.

#

with the immutable hooks approach to the hierarchy being worked on rn, the second approach becomes feasible again, because we can do automatic cleanup when the hierarchy changes.

#

so i'm holding off on working on it until the hierarchy stuff is a bit further along, to see which seems more viable.

knotty dune
#

@summer talon I'm attempting to use the window picking stuff, and something is not working. Specifically, in bevy_input_focus, if an element has focus, keyboard events are dispatched to the focus element which (if not handled) will eventually reach the window; otherwise if there's no focus element, then events are dispatched to the window directly.

However, when I place an observer on the window, I see events which are dispatched to the window directly, but not events which bubbled up from the focus. The focus element is getting the event (and not calling propagate(false)), but the event never reaches the window for some reason.

#

Do I need to do something special with the event?

summer talon
#

hmm, sounds like the window back-end is working but the bubble-to-window traversal is not

#

i'll look into it, give me a bit

#

seems like a bug

knotty dune
#

Actually, I'm probably doing something wrong

summer talon
#

are you using custom events or picking events?

knotty dune
#

Custom events

summer talon
#

they need to use PointerTraversal as the traversal strategy

#

again, this api is kind of raw and unfinished. I'd like to hide some of this behind the event macro.

summer talon
#

setting type Traversal = &'static Parent; will only traverse to parents.

#

the picking pointer events use type Traversal = PointerTraversal;

#

but they only work with Pointer events

#
#[derive(QueryData)]
pub struct PointerTraversal {
    parent: Option<&'static Parent>,
    window: Option<&'static Window>,
}

impl<E> Traversal<Pointer<E>> for PointerTraversal
where
    E: Debug + Clone + Reflect,
{
    fn traverse(item: Self::Item<'_>, pointer: &Pointer<E>) -> Option<Entity> {
        let PointerTraversalItem { parent, window } = item;

        // Send event to parent, if it has one.
        if let Some(parent) = parent {
            return Some(parent.get());
        };

        // Otherwise, send it to the window entity (unless this is a window entity).
        if window.is_none() {
            if let NormalizedRenderTarget::Window(window_ref) = pointer.pointer_location.target {
                return Some(window_ref.entity());
            }
        }

        None
    }
}
#

the event needs to know which window to dispatch itself to, which means the traversal needs to access that information from the event.

knotty dune
# summer talon the picking pointer events use `type Traversal = PointerTraversal;`
the trait bound `bevy_picking::events::PointerTraversal: bevy_ecs::traversal::Traversal<FocusKeyboardInput>` is not satisfied
the trait `bevy_ecs::traversal::Traversal<bevy_picking::events::Pointer<_>>` is implemented for `bevy_picking::events::PointerTraversal`
for that trait implementation, expected `bevy_picking::events::Pointer<_>`, found `FocusKeyboardInput`
#

Oh, I need to implement it for my custom event

#

OK, so keyboard events don't have a window field

summer talon
#

if you have a custom event type, I would do something like the following

#[derive(QueryData)]
/// These are for accessing components defined on the targeted entity
pub struct WindowTraversal {
    parent: Option<&'static Parent>,
    window: Option<&'static Window>,
}

trait HasWindow {
    fn get_window(&self) -> Option<Entity>;
}

impl<E> Traversal<E> for WindowTraversal
where
    E: HasWindow + Debug + Clone + Reflect,
{
    fn traverse(item: Self::Item<'_>, event: &E) -> Option<Entity> {
        let WindowTraversalItem { parent, window } = item;

        // Send event to parent, if it has one.
        if let Some(parent) = parent {
            return Some(parent.get());
        };

        // Otherwise, send it to the window entity (unless this is a window entity).
        if window.is_none() {
            event.get_winddow()
        }

        None
    }
}
#

then you can implement HasWindow on your custom events, and use WindowTraversal

#

this api is... very convoluted and low level

#

i would like to wrap it up into something nice, but you are the first person to use it other than me in bevy_picking

#

but it is very flexible.

#

because you can now have events propagate in arbitrary ways depending on both the components of the current entity, and the data contained within the event itself.

#

but if this doesn't work for your needs we can change it.

#

@knotty dune (forgot to ping in response)

knotty dune
#

There's a larger issue, though, which is for keyboard events, which window should we propagate to? I'm assuming the PrimaryWindow

#

I guess we will have to modify FocusKeyboardEvent to have a window field

summer talon
#

we could allow them to split and go to multiple entities (that would allow downward propagation) but I remember it being complex to implement.

knotty dune
#

The good news is that we do know the primary window when the event is triggered

#

Here's the logic:

    // If an element has keyboard focus, then dispatch the key event to that element.
    if let Some(focus_elt) = focus.0 {
        for ev in key_events.read() {
            commands.trigger_targets(FocusKeyboardInput(ev.clone()), focus_elt);
        }
    } else {
        // If no element has input focus, then dispatch the key event to the primary window.
        // There should be only one primary window.
        if let Ok(window) = windows.get_single() {
            for ev in key_events.read() {
                commands.trigger_targets(FocusKeyboardInput(ev.clone()), window);
            }
        }
    }
summer talon
#

I might be able to make it so that you can pull in the primary window from the ecs somehow

#

having to put it into the event is not super nice.

summer talon
summer talon
#

ignore me

#

i was reading it wrong

knotty dune
#

I mean, this is really a question of "how should keyboard shortcuts in multi-window apps behave?", which is not a question we can really answer. However, you can always install a keyboard listener on the UI root for each window, so in a sense it doesn't matter what we decide, because you can override it.

#

In any case, I guess what we need to do is change:

pub struct FocusKeyboardInput(pub KeyboardInput);

into

pub struct FocusKeyboardInput {
    input: pub KeyboardInput,
    window: Entity,
}
summer talon
#

yeah, basically, and then do the song and dance to implement the traversal for that type.

#

i feel like keyboard events should go to whatever window the mouse is hovering. If you have multiple mice then you'd need a custom seats abstraction.

#

but then, what if you don't have a mouse... what if you're on a touch screen.

#

not something we need to solve now, but will be a headache if it ever comes up

knotty dune
#

Well, the dispatcher is just a system so you can do whatever you want

summer talon
#

yeah

#

main window is a sane default

knotty dune
#

But I don't think I can implement this as things stand

summer talon
#

why not?

knotty dune
#

That is, I don't think I can implement PointerTraversal, because of the private fields

summer talon
#

yeah, you'll need to define a new traversial type that implements QueryData. Like #1236111180624297984 message

#
// The event we want to propagate
pub struct FocusKeyboardInput {
    /// The keyboard input payload
    input: pub KeyboardInput,
    /// The window we want to propagate to after we visit all the ancestors
    window: Entity,
}

impl Event for FocusKeyboardInput {
    type Traversal = FocusTraversal;
    const AUTO_PROPAGATE: bool = true;
}

#[derive(QueryData)]
/// The type that knows how to propagate a `FocusKeyboardInput` event
pub struct FocusTraversal {
    /// Gets the `Parent` component on the current target, if it has one
    parent: Option<&'static Parent>,
    /// Gets the `Window` component on the current target, if it has one
    window: Option<&'static Window>,
}

/// The propagation logic
impl Traversal<FocusKeyboardInput> for FocusTraversal {
    /// Traverses to the parent, if one exists, then to the window indicated in the event.
    /// Stops propagation when the current target is a window.
    fn traverse(item: Self::Item<'_>, event: &FocusKeyboardInput) -> Option<Entity> {
        // Access the query data on the current target.
        let FocusTraversalItem { parent, window } = item;

        // If the current target is a window, stop propagating.
        if window.is_some() {
            return None;
        }

        // If the current target has a parent, propagate to the parent.
        if let Some(parent) = parent {
            return Some(parent.get());
        };

        // If the current taget has no parent (we have reached the root) send it to the window entity specified in the event.
        Some(event.window)
    }
}
#

that ought to do it

#

FocusTraversalItem is created automatically by the QueryData derive

knotty dune
#

Why is window a Window and not an Entity?

summer talon
#

FocusTraversal is pulling data off the entity that is being visited by the observer executor.

#

we query for window because we want to know if we are already on a window.

#

if we didn't check that, it would get to the window, see that it has no parents, and propagate to the window again

#

and get suck in a loop

#

I added some more context to the example above, hope it helps.

fluid sandal
summer talon
#

Does winit expose that?

#

Oh hey it has a whole api for which window has keyboard focus.

knotty dune
summer talon
#

Nice! I’m going to play around with the traversal api to make custom implementations a bit more ergonomic.

knotty dune
#

Notice in particular how the tab groups are out of order - this gives you flexibility in determining the tab order within your UI, so it doesn't have to be strictly based on ECS order, although ECS order is the default.

#

Note: we still need to do the work of hooking this up to bevy_a11y::Focus

fluid sandal
#

Looking good!

knotty dune
#

Something that I'm not planning on doing, but which would be a nice project for someone else, is to come up with a "gamepad navigation" add-on which uses the on-screen coordinates of the current focus element, and then searches for the next element in the left/right/up/down direction.

knotty dune
#

@summer talon So with regard to Enter/Leave events, there's a solution that can work today that is not too difficult:

  • User adds a Hovering(pub bool) component to any entity which is interested in getting enter/leave events.
  • An ECS system iterates through all Hovering components, and sets the inner value based on whether it is an ancestor of the current entity in the hover map.
  • Regular Bevy change detection can now be used to detect enter and leave on a per-entity basis.
#
/// Component which indicates that the entity is interested in knowing when the mouse is hovering
/// over it or any of its children.
#[derive(Debug, Clone, Copy, Component, Default)]
pub struct Hovering(pub bool);

// Note: previously this was implemented as a Reaction, however it was reacting every frame
// because HoverMap is mutated every frame regardless of whether or not it changed.
pub(crate) fn update_hover_states(
    hover_map: Option<Res<HoverMap>>,
    mut hovers: Query<(Entity, &mut Hovering)>,
    parent_query: Query<&Parent>,
) {
    let Some(hover_map) = hover_map else { return };
    let hover_set = hover_map.get(&PointerId::Mouse);
    for (entity, mut hoverable) in hovers.iter_mut() {
        let is_hovering = match hover_set {
            Some(map) => map.iter().any(|(ha, _)| {
                *ha == entity || parent_query.iter_ancestors(*ha).any(|e| e == entity)
            }),
            None => false,
        };
        if hoverable.0 != is_hovering {
            hoverable.0 = is_hovering;
        }
    }
}
summer talon
queen raven
#

Is there a new or more up to date tracking issue for this working group? Interested in seeing if there's work I could contribute here but the issue linked in the OP is marked as completed

stoic flicker
#

That said, folks have been missing the debug picking plugin from bevy_mod_picking

#

And I'll want reviews on my Interaction work soon

queen raven
#

Sounds good - I'll glance through the debug stuff to see if there's a reasonable slice to take from there, may just continue looking around the issue tracker for other areas that spark interest too

queen raven
stoic flicker
#

Mesh picking should already work though

queen raven
#

Ah, good to know, I didn't see a direct 1:1 in bevy_picking so I assumed that it was more recent / might not be compatible for some unforeseen reason

fluid sandal
#

It's mostly a direct port.

#

mod_raycast was also upstreamed as a meshraycast systemparam.

queen raven
#

First stumbling block I think... we'd need a dependency on bevy_ui for actually doing the debug draw, but bevy_ui itself has a dependency on bevy_picking

Not really sure what the correct path forward here would be, feels like we need to extract a subset of one of the dependencies into a common crate to break the dependency cycle but no real idea on what to move

#

I suppose the best option is moving it out of bevy_picking and into bevy_dev_tools?

knotty dune
queen raven
#

Thanks you two - and yeah, the debug ui being in bevy_dev_tools is effectively doing what you suggested, Talin

#

Was the selection feature (bevy_picking_selection) excluded intentionally, or is it work that's still pending potential implementation?

stoic flicker
fluid sandal
#

It's also an absolutely tiny standalone crate that you can fork and maintain yourself.

#

I think it's a single file.

queen raven
#

Was just curious since there was some specific debug code that handled aggregating and printing related info with the feature enabled

fluid sandal
#

Yup, not particularly important imo

queen raven
#

While you're around, @fluid sandal , had another related question - there was a DragMap struct that was removed in the process of upstreaming, but it seemed to only be implemented (& relevant?) for usage with bevy_egui. Any thoughts on if it would be useful / feasible to port something similar for drag events after the initial upstreaming is done?

fluid sandal
#

Huh, that is surprising, I would expect that to still be around, you need it to track drags between pointers.

queen raven
#

Ahh, though still, AFAICS, it was only used in the debug.rs file for populating PointerDebug.drag_start, which seems to only have actually been used in the debug_draw_egui code path

summer talon
#

Yeah I can elaborate on this change if needed, drag map was combined with some other state to make the event ordering better specified.

queen raven
#

Didn't know if the omission in the "normal" debug_draw method was intentional

old venture
fluid sandal
#

I'll try to get caldera loaded again and check tonight.

old venture
fluid sandal
fluid sandal
#

not too shabby

fluid sandal
spice carbon
#

I migrating to bevy_picking and noticed that if I have UI on the scene, I can't pick avian colliders, for example.
Is this expected?

#

In my game I have a UI node that takes the entire screen, but it's transparent and have some buttons on it.

#

Ah, I need to use PickingBehavior::IGNORE

fluid sandal
#

Yeah, this has been a common issue, but we haven't decided if changing behavior is the right call here.

stoic flicker
summer talon
#

i liked the original design where all back-ends were optional

#

so yeah

fluid sandal
#

But I agree. The backend plugins should probably not be added in the DefaultPlugins

summer talon
#

oh, yeah haven't looked at the code yet tbh

craggy jasper
#

okay

#

Minimal reproduction, only in places where the two meshes overlap does picking occur