Ui.allocate_new_ui() adds extra padding not present when is_sizing_pass()
Describe the bug
When is_sizing_pass(), allocate_new_ui() correctly does not add space before and after itself. When rendering "for real", it does. ui.horizontal() does not have this issue. (I'm using sizing_pass to get the size of the popup so I can center it when it's rendered "for real"--this seems like a natural use case for sizing_pass, but maybe there's a better way?)
In this image, I left the .invisible() off the sizing pass, the (correctly) laid out buttons in the upper left are how they are laid out while sizing. The popup is what's rendered, with !is_sizing_pass(), wherein you can see that the allocate_new_ui() allocates extra, unwanted padding, in addition to item_spacing.y.
To Reproduce
Run code like:
let modal = ModalPopup::new(c, &def);
let layer_id = LayerId::new(Order::Foreground, Id::new("PopupLayer"));
let window_id = Id::new("ModalDialog");
let ui_builder = UiBuilder::new().ui_stack_info(UiStackInfo::new(UiKind::Popup));
let content_size = {
let sizing_builder = ui_builder.clone().sizing_pass()/*.invisible()*/;
modal.render_content(&mut Ui::new(ctx.clone(), layer_id, window_id, sizing_builder))
};
let popup_size = content_size + Vec2::splat(c.vh_to_px(DIALOG_BUTTON_HEIGHT_VH));
let popup_rect = Rect::from_pos(c.ctx.screen_rect().center())
.expand2(popup_size / 2.0);
Ui::new(ctx.clone(), layer_id, window_id, ui_builder.max_rect(popup_rect))
.add(modal);
where render_content() looks like:
impl<'c, 'vuc> ModalPopup<'c, 'vuc> {
fn render_content(&self, ui: &mut Ui) -> Vec2 {
ui.style_mut().spacing.item_spacing.y = self.get_margin_px();
ui.label(LayoutJob::simple(
self.modal.get_message().to_string(),
egui::FontId::new(self.c.vh_to_px(DIALOG_TEXT_HEIGHT_VH), egui::FontFamily::Proportional),
Color32::BLACK,
self.c.ctx.screen_rect().width() - 100.0
));
ui.separator();
self.modal.update_controls(ui, self.c);
ui.min_size()
}
}
and ui() looks like:
impl<'c, 'vuc> Widget for ModalPopup<'c, 'vuc> {
fn ui(self, ui: &mut Ui) -> Response {
let stroke_px = 1.0;
let shadow = Shadow {
offset: vec2(10.0, 20.0),
blur: 20.0,
spread: 0.0,
color: Color32::from_black_alpha(96),
};
let outer_margin = Margin {
left: stroke_px,
top: stroke_px,
right: stroke_px + shadow.offset.x + shadow.blur,
bottom: stroke_px + shadow.offset.y + shadow.blur,
};
let margin_px = self.get_margin_px();
let frame = Frame {
inner_margin: Margin::same(margin_px),
outer_margin: outer_margin,
fill: Color32::WHITE,
stroke: Stroke::new(1.0, Color32::GRAY),
rounding: Rounding::same(margin_px),
shadow: shadow,
..Default::default()
};
frame.show(ui, |ui| self.render_content(ui)).response
}
}
and update_controls() looks like:
impl<'refs> Modal for SettingsModal<'refs> {
fn get_message<'refs2>(&'refs2 self) -> &'refs2 str {
self.message
}
fn update_controls<'args, 'vuc>(&self, ui: &mut Ui, c: &'args ViewUpdateContext<'args, 'vuc>) {
ui.allocate_new_ui(
UiBuilder::new()
.layout(egui::Layout::top_down(Align::Min)),
|ui| {
dialog_button(ui, c, "load_button", "Load", Some(SM::Event::LoadIconClicked));
dialog_button(ui, c, "load_button", "Load", Some(SM::Event::LoadIconClicked));
ui.allocate_new_ui( // <==== This is the allocate_new_ui() in question
UiBuilder::new()
.layout(egui::Layout::left_to_right(Align::Center)),
|ui| {
dialog_button(ui, c, "simulate_none_button", "No Sim.", Some(SM::Event::SimulateNone ));
dialog_button(ui, c, "simulate_drive_plus_button", "Sim Drive Plus", Some(SM::Event::SimulateDrivePlus));
dialog_button(ui, c, "simulate_632_button", "Sim 632", Some(SM::Event::Simulate632 ));
}
);
dialog_button(ui, c, "cancel_button", "CANCEL", None);
}
);
}
}
Expected behavior
allocate_new_ui() does not add extra vertical spacing when !is_sizing_pass().
Desktop (please complete the following information):
- OS: Windows 11 Pro
- Browser: n/a
- Version: egui 1.29