From 978299704539a380a4d4ee30a57142200efe0087 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 30 Sep 2024 14:43:57 +0200 Subject: [PATCH 1/7] Add `UiBuilder::layer_id` --- crates/egui/src/ui.rs | 9 +++++---- crates/egui/src/ui_builder.rs | 10 +++++++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/crates/egui/src/ui.rs b/crates/egui/src/ui.rs index ee77888f811..542bc7abce3 100644 --- a/crates/egui/src/ui.rs +++ b/crates/egui/src/ui.rs @@ -247,6 +247,7 @@ impl Ui { let UiBuilder { id_salt, ui_stack_info, + layer_id, max_rect, layout, disabled, @@ -262,6 +263,9 @@ impl Ui { let max_rect = max_rect.unwrap_or_else(|| self.available_rect_before_wrap()); let mut layout = layout.unwrap_or(*self.layout()); let enabled = self.enabled && !disabled && !invisible; + if let Some(layer_id) = layer_id { + painter.set_layer_id(layer_id); + } if invisible { painter.set_invisible(); } @@ -2311,10 +2315,7 @@ impl Ui { layer_id: LayerId, add_contents: impl FnOnce(&mut Self) -> R, ) -> InnerResponse { - self.scope(|ui| { - ui.painter.set_layer_id(layer_id); - add_contents(ui) - }) + self.scope_builder(UiBuilder::new().layer_id(layer_id), add_contents) } /// A [`CollapsingHeader`] that starts out collapsed. diff --git a/crates/egui/src/ui_builder.rs b/crates/egui/src/ui_builder.rs index 33a48dbd553..e1075a9e674 100644 --- a/crates/egui/src/ui_builder.rs +++ b/crates/egui/src/ui_builder.rs @@ -1,6 +1,6 @@ use std::{hash::Hash, sync::Arc}; -use crate::{Id, Layout, Rect, Sense, Style, UiStackInfo}; +use crate::{Id, LayerId, Layout, Rect, Sense, Style, UiStackInfo}; #[allow(unused_imports)] // Used for doclinks use crate::Ui; @@ -15,6 +15,7 @@ use crate::Ui; pub struct UiBuilder { pub id_salt: Option, pub ui_stack_info: UiStackInfo, + pub layer_id: Option, pub max_rect: Option, pub layout: Option, pub disabled: bool, @@ -48,6 +49,13 @@ impl UiBuilder { self } + /// Show the [`Ui`] in a different [`LayerId`] from its parent. + #[inline] + pub fn layer_id(mut self, layer_id: LayerId) -> Self { + self.layer_id = Some(layer_id); + self + } + /// Set the max rectangle, within which widgets will go. /// /// New widgets will *try* to fit within this rectangle. From cda4c638db69c8819533fabe54dd8ddd0a0b594a Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 30 Sep 2024 14:44:36 +0200 Subject: [PATCH 2/7] Remove `layer_id` argument from `Ui::new` --- crates/egui/src/containers/area.rs | 3 ++- crates/egui/src/containers/panel.rs | 18 +++++++++--------- crates/egui/src/ui.rs | 5 ++++- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/crates/egui/src/containers/area.rs b/crates/egui/src/containers/area.rs index fa8e5fc203b..b0cb0330159 100644 --- a/crates/egui/src/containers/area.rs +++ b/crates/egui/src/containers/area.rs @@ -540,6 +540,7 @@ impl Prepared { let mut ui_builder = UiBuilder::new() .ui_stack_info(UiStackInfo::new(self.kind)) + .layer_id(self.layer_id) .max_rect(max_rect); if !self.enabled { @@ -549,7 +550,7 @@ impl Prepared { ui_builder = ui_builder.sizing_pass().invisible(); } - let mut ui = Ui::new(ctx.clone(), self.layer_id, self.layer_id.id, ui_builder); + let mut ui = Ui::new(ctx.clone(), self.layer_id.id, ui_builder); ui.set_clip_rect(self.constrain_rect); // Don't paint outside our bounds if self.fade_in { diff --git a/crates/egui/src/containers/panel.rs b/crates/egui/src/containers/panel.rs index f3b6c913cfc..f9c6c4fa757 100644 --- a/crates/egui/src/containers/panel.rs +++ b/crates/egui/src/containers/panel.rs @@ -375,14 +375,14 @@ impl SidePanel { ctx: &Context, add_contents: Box R + 'c>, ) -> InnerResponse { - let layer_id = LayerId::background(); let side = self.side; let available_rect = ctx.available_rect(); let mut panel_ui = Ui::new( ctx.clone(), - layer_id, self.id, - UiBuilder::new().max_rect(available_rect), + UiBuilder::new() + .layer_id(LayerId::background()) + .max_rect(available_rect), ); panel_ui.set_clip_rect(ctx.screen_rect()); @@ -868,15 +868,15 @@ impl TopBottomPanel { ctx: &Context, add_contents: Box R + 'c>, ) -> InnerResponse { - let layer_id = LayerId::background(); let available_rect = ctx.available_rect(); let side = self.side; let mut panel_ui = Ui::new( ctx.clone(), - layer_id, self.id, - UiBuilder::new().max_rect(available_rect), + UiBuilder::new() + .layer_id(LayerId::background()) + .max_rect(available_rect), ); panel_ui.set_clip_rect(ctx.screen_rect()); @@ -1135,14 +1135,14 @@ impl CentralPanel { add_contents: Box R + 'c>, ) -> InnerResponse { let available_rect = ctx.available_rect(); - let layer_id = LayerId::background(); let id = Id::new((ctx.viewport_id(), "central_panel")); let mut panel_ui = Ui::new( ctx.clone(), - layer_id, id, - UiBuilder::new().max_rect(available_rect), + UiBuilder::new() + .layer_id(LayerId::background()) + .max_rect(available_rect), ); panel_ui.set_clip_rect(ctx.screen_rect()); diff --git a/crates/egui/src/ui.rs b/crates/egui/src/ui.rs index 542bc7abce3..e484c862853 100644 --- a/crates/egui/src/ui.rs +++ b/crates/egui/src/ui.rs @@ -120,10 +120,11 @@ impl Ui { /// /// Normally you would not use this directly, but instead use /// [`crate::SidePanel`], [`crate::TopBottomPanel`], [`crate::CentralPanel`], [`crate::Window`] or [`crate::Area`]. - pub fn new(ctx: Context, layer_id: LayerId, id: Id, ui_builder: UiBuilder) -> Self { + pub fn new(ctx: Context, id: Id, ui_builder: UiBuilder) -> Self { let UiBuilder { id_salt, ui_stack_info, + layer_id, max_rect, layout, disabled, @@ -133,6 +134,8 @@ impl Ui { sense, } = ui_builder; + let layer_id = layer_id.unwrap_or(LayerId::background()); + debug_assert!( id_salt.is_none(), "Top-level Ui:s should not have an id_salt" From 9c64356741be87c84a2a3340fa2eb4574c88e9af Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 30 Sep 2024 14:44:59 +0200 Subject: [PATCH 3/7] Deprecate `ui.with_layer_id` --- crates/egui/src/ui.rs | 4 +++- tests/test_viewports/src/main.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/egui/src/ui.rs b/crates/egui/src/ui.rs index e484c862853..19bbfc50c2b 100644 --- a/crates/egui/src/ui.rs +++ b/crates/egui/src/ui.rs @@ -2313,6 +2313,7 @@ impl Ui { /// }); /// # }); /// ``` + #[deprecated = "Use ui.scope_builder(UiBuilder::new().layer_id(…), …) instead"] pub fn with_layer_id( &mut self, layer_id: LayerId, @@ -2764,7 +2765,8 @@ impl Ui { // Paint the body to a new layer: let layer_id = LayerId::new(Order::Tooltip, id); - let InnerResponse { inner, response } = self.with_layer_id(layer_id, add_contents); + let InnerResponse { inner, response } = + self.scope_builder(UiBuilder::new().layer_id(layer_id), add_contents); // Now we move the visuals of the body to where the mouse is. // Normally you need to decide a location for a widget first, diff --git a/tests/test_viewports/src/main.rs b/tests/test_viewports/src/main.rs index 24046e041ac..9d06db431e4 100644 --- a/tests/test_viewports/src/main.rs +++ b/tests/test_viewports/src/main.rs @@ -433,7 +433,7 @@ fn drag_source( // Paint the body to a new layer: let layer_id = egui::LayerId::new(egui::Order::Tooltip, id); - let res = ui.with_layer_id(layer_id, body); + let res = ui.scope_builder(UiBuilder::new().layer_id(layer_id), body); if let Some(pointer_pos) = ui.ctx().pointer_interact_pos() { let delta = pointer_pos - res.response.rect.center(); From 210b34e4eaec592d913a6a7666e3421df4d16ccc Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 30 Sep 2024 14:45:21 +0200 Subject: [PATCH 4/7] Document the perils of chaning `layer_id` of `ui.painter()` --- crates/egui/src/painter.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/egui/src/painter.rs b/crates/egui/src/painter.rs index feefe47db43..b9dc5789269 100644 --- a/crates/egui/src/painter.rs +++ b/crates/egui/src/painter.rs @@ -74,6 +74,9 @@ impl Painter { } /// Redirect where you are painting. + /// + /// It is undefined behavior to change the [`LayerId`] + /// of [`Ui::painter`]. pub fn set_layer_id(&mut self, layer_id: LayerId) { self.layer_id = layer_id; } From 9dc74984e1e9e91173306e584d0a99db6c367d4b Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 30 Sep 2024 14:45:28 +0200 Subject: [PATCH 5/7] Improve comment --- crates/egui/src/ui.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/egui/src/ui.rs b/crates/egui/src/ui.rs index 19bbfc50c2b..9db1404d939 100644 --- a/crates/egui/src/ui.rs +++ b/crates/egui/src/ui.rs @@ -173,7 +173,7 @@ impl Ui { }; // Register in the widget stack early, to ensure we are behind all widgets we contain: - let start_rect = Rect::NOTHING; // This will be overwritten when/if `remember_min_rect` is called + let start_rect = Rect::NOTHING; // This will be overwritten when `remember_min_rect` is called ui.ctx().create_widget( WidgetRect { id: ui.unique_id, @@ -317,7 +317,7 @@ impl Ui { }; // Register in the widget stack early, to ensure we are behind all widgets we contain: - let start_rect = Rect::NOTHING; // This will be overwritten when/if `remember_min_rect` is called + let start_rect = Rect::NOTHING; // This will be overwritten when `remember_min_rect` is called child_ui.ctx().create_widget( WidgetRect { id: child_ui.unique_id, From 6bd6b2a58c6b5ade21c8d12643bb6812911a7009 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 30 Sep 2024 14:46:02 +0200 Subject: [PATCH 6/7] Reintroduce debug_assert for widgets that change layer_id --- crates/egui/src/widget_rect.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/egui/src/widget_rect.rs b/crates/egui/src/widget_rect.rs index 91924352ee7..dd900af1f11 100644 --- a/crates/egui/src/widget_rect.rs +++ b/crates/egui/src/widget_rect.rs @@ -139,6 +139,14 @@ impl WidgetRects { // e.g. calling `response.interact(…)` to add more interaction. let (idx_in_layer, existing) = entry.get_mut(); + debug_assert!( + existing.layer_id == widget_rect.layer_id, + "Widget {:?} changed layer_id during the frame from {:?} to {:?}", + widget_rect.id, + existing.layer_id, + widget_rect.layer_id + ); + // Update it: existing.rect = widget_rect.rect; // last wins existing.interact_rect = widget_rect.interact_rect; // last wins From 0d089bf5357c1d570823aee53260299e9da205ea Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 1 Oct 2024 10:15:57 +0200 Subject: [PATCH 7/7] Fix doclink --- crates/egui/src/painter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/egui/src/painter.rs b/crates/egui/src/painter.rs index b9dc5789269..5b8ae77df37 100644 --- a/crates/egui/src/painter.rs +++ b/crates/egui/src/painter.rs @@ -76,7 +76,7 @@ impl Painter { /// Redirect where you are painting. /// /// It is undefined behavior to change the [`LayerId`] - /// of [`Ui::painter`]. + /// of [`crate::Ui::painter`]. pub fn set_layer_id(&mut self, layer_id: LayerId) { self.layer_id = layer_id; }