Skip to content

Commit

Permalink
Fix the Bevy UI backend so it ignores clipped areas of UI nodes (#285)
Browse files Browse the repository at this point in the history
* The Bevy UI backend doesn't check for clipping, and allows interaction with clipped non-visible sections of UI nodes.

This PR intersects the node rect with its calculated clip rect (if it has one) and then checks if the clipped node contains the cursor.

* Removed unused import from `bevy_picking_ui`

* remove unused deps

* update changelog

---------

Co-authored-by: Aevyrie <[email protected]>
  • Loading branch information
ickshonpe and aevyrie authored Feb 23, 2024
1 parent 085bf9d commit 7aafa82
Show file tree
Hide file tree
Showing 4 changed files with 7 additions and 22 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# UNRELEASED

- Added: support for `bevy_ui` `UiScale`.
- Fixed: the bevy ui backend now ignores clipped areas of UI nodes.
- Added: `RaycastBackendSettings::raycast_visibility` to support picking hidden meshes.

# 0.17.0
Expand Down
2 changes: 0 additions & 2 deletions backends/bevy_picking_rapier/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,9 @@ resolver = "2"
[dependencies]
bevy_app = { version = "0.12", default-features = false }
bevy_ecs = { version = "0.12", default-features = false }
bevy_math = { version = "0.12", default-features = false }
bevy_reflect = { version = "0.12", default-features = false }
bevy_render = { version = "0.12", default-features = false }
bevy_transform = { version = "0.12", default-features = false }
bevy_utils = { version = "0.12", default-features = false }
bevy_window = { version = "0.12", default-features = false }

bevy_rapier3d = "0.23"
Expand Down
1 change: 0 additions & 1 deletion backends/bevy_picking_ui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ resolver = "2"
[dependencies]
bevy_app = { version = "0.12", default-features = false }
bevy_ecs = { version = "0.12", default-features = false }
bevy_math = { version = "0.12", default-features = false }
bevy_render = { version = "0.12", default-features = false }
bevy_transform = { version = "0.12", default-features = false }
bevy_window = { version = "0.12", default-features = false }
Expand Down
25 changes: 6 additions & 19 deletions backends/bevy_picking_ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@

use bevy_app::prelude::*;
use bevy_ecs::{prelude::*, query::WorldQuery};
use bevy_math::prelude::*;
use bevy_render::{camera::NormalizedRenderTarget, prelude::*};
use bevy_transform::prelude::*;
use bevy_ui::{prelude::*, RelativeCursorPosition, UiStack};
Expand Down Expand Up @@ -132,24 +131,12 @@ pub fn ui_picking(
}
}

let position = node.global_transform.translation();
let ui_position = position.truncate();
let extents = node.node.size() / 2.0;
let mut min = ui_position - extents;
if let Some(clip) = node.calculated_clip {
min = Vec2::max(min, clip.clip.min);
}

// The mouse position relative to the node
// (0., 0.) is the top-left corner, (1., 1.) is the bottom-right corner
let relative_cursor_position = Vec2::new(
(location.position.x - min.x) / node.node.size().x,
(location.position.y - min.y) / node.node.size().y,
);

if (0.0..1.).contains(&relative_cursor_position.x)
&& (0.0..1.).contains(&relative_cursor_position.y)
{
let node_rect = node.node.logical_rect(node.global_transform);
let visible_rect = node
.calculated_clip
.map(|clip| node_rect.intersect(clip.clip))
.unwrap_or(node_rect);
if visible_rect.contains(location.position) {
Some(*entity)
} else {
None
Expand Down

0 comments on commit 7aafa82

Please sign in to comment.