diff --git a/crates/egui/src/containers/area.rs b/crates/egui/src/containers/area.rs index 557b3843..b355c75b 100644 --- a/crates/egui/src/containers/area.rs +++ b/crates/egui/src/containers/area.rs @@ -2,7 +2,7 @@ //! It has no frame or own size. It is potentially movable. //! It is the foundation for windows and popups. -use crate::*; +use crate::{layers::ZLayer, *}; /// State that is persisted between frames. // TODO(emilk): this is not currently stored in `memory().data`, but maybe it should be? @@ -268,7 +268,7 @@ impl Area { let move_response = ctx.interact( Rect::EVERYTHING, ctx.style().spacing.item_spacing, - layer_id, + ZLayer::from_area_layer(layer_id), interact_id, state.rect(), sense, diff --git a/crates/egui/src/context.rs b/crates/egui/src/context.rs index 785da03c..b1151dda 100644 --- a/crates/egui/src/context.rs +++ b/crates/egui/src/context.rs @@ -2,9 +2,15 @@ use std::sync::Arc; use crate::{ - animation_manager::AnimationManager, data::output::PlatformOutput, frame_state::FrameState, - input_state::*, layers::GraphicLayers, memory::Options, os::OperatingSystem, - output::FullOutput, TextureHandle, *, + animation_manager::AnimationManager, + data::output::PlatformOutput, + frame_state::FrameState, + input_state::*, + layers::{GraphicLayers, ZLayer, ZOrder}, + memory::Options, + os::OperatingSystem, + output::FullOutput, + TextureHandle, *, }; use epaint::{mutex::*, stats::*, text::Fonts, TessellationOptions, *}; @@ -64,9 +70,9 @@ struct ContextImpl { requested_repaint_last_frame: bool, /// Written to during the frame. - layer_rects_this_frame: ahash::HashMap>, + layer_rects_this_frame: ahash::HashMap>, /// Read - layer_rects_prev_frame: ahash::HashMap>, + layer_rects_prev_frame: ahash::HashMap>, #[cfg(feature = "accesskit")] is_accesskit_enabled: bool, @@ -377,7 +383,7 @@ impl Context { &self, clip_rect: Rect, item_spacing: Vec2, - layer_id: AreaLayerId, + layer: ZLayer, id: Id, rect: Rect, sense: Sense, @@ -394,7 +400,7 @@ impl Context { // Respect clip rectangle when interacting let interact_rect = clip_rect.intersect(interact_rect); - let mut hovered = self.rect_contains_pointer(layer_id, interact_rect); + let mut hovered = self.rect_contains_pointer(layer.area_layer, interact_rect); // This solves the problem of overlapping widgets. // Whichever widget is added LAST (=on top) gets the input: @@ -411,16 +417,18 @@ impl Context { let mut slf = self.write(); slf.layer_rects_this_frame - .entry(layer_id) + .entry(layer.area_layer) .or_default() - .push((id, interact_rect)); + .push((id, layer.z, interact_rect)); if hovered { let pointer_pos = slf.input.pointer.interact_pos(); if let Some(pointer_pos) = pointer_pos { - if let Some(rects) = slf.layer_rects_prev_frame.get(&layer_id) { - for &(prev_id, prev_rect) in rects.iter().rev() { - if prev_id == id { + if let Some(rects) = slf.layer_rects_prev_frame.get_mut(&layer.area_layer) { + rects.sort_by_key(|(_id, z, ..)| *z); + + for &(prev_id, prev_z, prev_rect) in rects.iter().rev() { + if prev_id == id && prev_z <= layer.z { break; // there is no other interactive widget covering us at the pointer position. } if prev_rect.contains(pointer_pos) { @@ -450,7 +458,7 @@ impl Context { } } - self.interact_with_hovered(layer_id, id, rect, sense, enabled, hovered) + self.interact_with_hovered(layer.area_layer, id, rect, sense, enabled, hovered) } /// You specify if a thing is hovered, and the function gives a [`Response`]. diff --git a/crates/egui/src/layers.rs b/crates/egui/src/layers.rs index 4dae378e..a086875b 100644 --- a/crates/egui/src/layers.rs +++ b/crates/egui/src/layers.rs @@ -224,6 +224,16 @@ impl ZLayer { pub fn below_by(self, levels: i32) -> Self { self.with_z(self.z.below_by(levels)) } + + #[inline(always)] + pub fn id(&self) -> Id { + self.area_layer.id + } + + #[inline(always)] + pub fn order(&self) -> Order { + self.area_layer.order + } } /// A unique identifier of a specific [`Shape`] in a [`PaintList`]. diff --git a/crates/egui/src/painter.rs b/crates/egui/src/painter.rs index 91f9de0e..eaae7156 100644 --- a/crates/egui/src/painter.rs +++ b/crates/egui/src/painter.rs @@ -140,6 +140,12 @@ impl Painter { self.layer.area_layer } + /// Where we paint, and on what Z-level + #[inline(always)] + pub fn zlayer(&self) -> ZLayer { + self.layer + } + #[inline(always)] pub fn z(&self) -> ZOrder { self.layer.z diff --git a/crates/egui/src/ui.rs b/crates/egui/src/ui.rs index 899b6d56..4c11fe85 100644 --- a/crates/egui/src/ui.rs +++ b/crates/egui/src/ui.rs @@ -327,6 +327,11 @@ impl Ui { self.painter().layer() } + #[inline] + pub fn layer(&self) -> ZLayer { + self.painter().zlayer() + } + /// The [`InputState`] of the [`Context`] associated with this [`Ui`]. /// Equivalent to `.ctx().input()`. /// @@ -623,7 +628,7 @@ impl Ui { self.ctx().interact( self.clip_rect(), self.spacing().item_spacing, - self.layer_id(), + self.layer(), id, rect, sense,