From 44bca2cb58a08bd8270c0005ebcbbb7f13d24cf9 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 19 Jun 2024 10:08:26 +0200 Subject: [PATCH 1/2] `Rect`: the distance to a negative rectangle is always infinite --- crates/emath/src/rect.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/crates/emath/src/rect.rs b/crates/emath/src/rect.rs index 23d0428ac0a..ec220395bd7 100644 --- a/crates/emath/src/rect.rs +++ b/crates/emath/src/rect.rs @@ -361,6 +361,8 @@ impl Rect { /// The distance from the rect to the position. /// /// The distance is zero when the position is in the interior of the rectangle. + /// + /// [Negative rectangles](Self::is_negative) always return [`f32::INFINITY`]. #[inline] pub fn distance_to_pos(&self, pos: Pos2) -> f32 { self.distance_sq_to_pos(pos).sqrt() @@ -369,8 +371,14 @@ impl Rect { /// The distance from the rect to the position, squared. /// /// The distance is zero when the position is in the interior of the rectangle. + /// + /// [Negative rectangles](Self::is_negative) always return [`f32::INFINITY`]. #[inline] pub fn distance_sq_to_pos(&self, pos: Pos2) -> f32 { + if self.is_negative() { + return f32::INFINITY; + } + let dx = if self.min.x > pos.x { self.min.x - pos.x } else if pos.x > self.max.x { @@ -394,6 +402,8 @@ impl Rect { /// /// Negative inside the box. /// + /// [Negative rectangles](Self::is_negative) always return [`f32::INFINITY`]. + /// /// ``` /// # use emath::{pos2, Rect}; /// let rect = Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 1.0)); @@ -402,6 +412,10 @@ impl Rect { /// assert_eq!(rect.signed_distance_to_pos(pos2(1.50, 0.50)), 0.50); /// ``` pub fn signed_distance_to_pos(&self, pos: Pos2) -> f32 { + if self.is_negative() { + return f32::INFINITY; + } + let edge_distances = (pos - self.center()).abs() - self.size() * 0.5; let inside_dist = edge_distances.max_elem().min(0.0); let outside_dist = edge_distances.max(Vec2::ZERO).length(); From ea3ffc63c6df2a08db3d81e93043d2975202f848 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 19 Jun 2024 10:08:44 +0200 Subject: [PATCH 2/2] Explicitly handle negatve rectangle in hit interaction code --- crates/egui/src/hit_test.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/egui/src/hit_test.rs b/crates/egui/src/hit_test.rs index 62a762aa52d..42099d248cc 100644 --- a/crates/egui/src/hit_test.rs +++ b/crates/egui/src/hit_test.rs @@ -58,6 +58,10 @@ pub fn hit_test( .filter(|layer| layer.order.allow_interaction()) .flat_map(|&layer_id| widgets.get_layer(layer_id)) .filter(|&w| { + if w.interact_rect.is_negative() { + return false; + } + let pos_in_layer = pos_in_layers.get(&w.layer_id).copied().unwrap_or(pos); let dist_sq = w.interact_rect.distance_sq_to_pos(pos_in_layer); @@ -311,6 +315,10 @@ fn find_closest(widgets: impl Iterator, pos: Pos2) -> Option< let mut closest = None; let mut closest_dist_sq = f32::INFINITY; for widget in widgets { + if widget.interact_rect.is_negative() { + continue; + } + let dist_sq = widget.interact_rect.distance_sq_to_pos(pos); // In case of a tie, take the last one = the one on top.