Skip to content

Conversation

@bytemunch
Copy link
Contributor

Objective

Fixes #18005

Utilize RayMap in sprite picking in order to get picking working with differing viewport scaling. Adds RenderLayers to the sprite query for layer-exclusive picking control.

Solution

Small rewrite of the loops in bevy_sprite/picking_backend.rs. Implementing either RayMap or RenderLayers on their own didn't have the correct results, so both solutions are rolled into one PR.

Testing

CI & an updated version of the reproduction repo in the original issue, along with the sprite_picking example.


@michalvankodev
Copy link

Will this be also ported to 0.15 ?

@bytemunch
Copy link
Contributor Author

I wouldn't expect so but that's not my call. You can take the code changes and build a custom sprite picking backend that implements the same fixes if you need this to work asap :)

@alice-i-cecile
Copy link
Member

I wouldn't expect any further backports to 0.15 at this stage, except maybe for the most serious of problems.

Copy link
Member

@alice-i-cecile alice-i-cecile left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense to me as a fix. I'd prefer more automated tests for this area of the code, but given that we don't have any set up for picking broadly I won't block on this.

This won't work on non-primary windows, which is annoying, but that's a pre-existing bug that should be fixed seperately.

@alice-i-cecile alice-i-cecile added C-Bug An unexpected or incorrect behavior D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Needs-Review Needs reviewer attention (from anyone!) to move forward A-Picking Pointing at and selecting objects of all sorts labels Feb 27, 2025
Comment on lines +171 to +177
if let Some(cam_render_layers) = cam_render_layers {
if let Some(layers) = layers {
if !cam_render_layers.intersects(layers) {
return None;
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if let Some(cam_render_layers) = cam_render_layers {
if let Some(layers) = layers {
if !cam_render_layers.intersects(layers) {
return None;
}
}
}
if !cam_render_layers
.unwrap_or_default()
.intersects(layers.unwrap_or_default())
{
return None;
}

Entities without RenderLayers are assumed to be RenderLayers::layer(0) (which is the default() value). This is needed to skip cases like camera = None, sprite = Some(RenderLayers::layer(1)) .

Mesh picking backend does this:

let cam_layers = cam_layers.to_owned().unwrap_or_default();

let entity_layers = layers.get(entity).cloned().unwrap_or_default();
let render_layers_match = cam_layers.intersects(&entity_layers);

@bloopyboop
Copy link

Hi, I would like to adopt this PR (as was recommended to me on bevy's discord). I'm not sure if I've done everything right, but here is my new PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Picking Pointing at and selecting objects of all sorts C-Bug An unexpected or incorrect behavior D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Needs-Review Needs reviewer attention (from anyone!) to move forward

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Trigger<Pointer<_>> events are triggered for different position when using 2 cameras with RenderLayers

5 participants