1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-01 06:10:06 -04:00

Create struct ImmediateViewport to simplify argument lists

This commit is contained in:
Emil Ernerfeldt
2023-11-14 06:26:53 +01:00
parent 66662e4414
commit 002110ee3d
4 changed files with 59 additions and 49 deletions

View File

@@ -455,8 +455,8 @@ mod glow_integration {
}; };
use egui::{ use egui::{
epaint::ahash::HashMap, NumExt as _, ViewportIdMap, ViewportIdPair, ViewportIdSet, epaint::ahash::HashMap, ImmediateViewport, NumExt as _, ViewportIdMap, ViewportIdPair,
ViewportOutput, ViewportUiCallback, ViewportIdSet, ViewportOutput, ViewportUiCallback,
}; };
use egui_winit::{create_winit_window_builder, process_viewport_commands, EventResponse}; use egui_winit::{create_winit_window_builder, process_viewport_commands, EventResponse};
@@ -1362,7 +1362,7 @@ mod glow_integration {
let event_loop: *const EventLoopWindowTarget<UserEvent> = event_loop; let event_loop: *const EventLoopWindowTarget<UserEvent> = event_loop;
egui::Context::set_immediate_viewport_renderer( egui::Context::set_immediate_viewport_renderer(
move |egui_ctx, viewport_builder, ids, viewport_ui_cb| { move |egui_ctx, immediate_viewport| {
if let (Some(glutin), Some(painter)) = (glutin.upgrade(), painter.upgrade()) if let (Some(glutin), Some(painter)) = (glutin.upgrade(), painter.upgrade())
{ {
// SAFETY: the event loop lives longer than // SAFETY: the event loop lives longer than
@@ -1373,12 +1373,10 @@ mod glow_integration {
render_immediate_viewport( render_immediate_viewport(
event_loop, event_loop,
egui_ctx, egui_ctx,
viewport_builder,
ids,
viewport_ui_cb,
&glutin, &glutin,
&painter, &painter,
beginning, beginning,
immediate_viewport,
); );
} else { } else {
log::warn!("render_sync_callback called after window closed"); log::warn!("render_sync_callback called after window closed");
@@ -1400,28 +1398,30 @@ mod glow_integration {
/// This is called (via a callback) by user code to render immediate viewports, /// This is called (via a callback) by user code to render immediate viewports,
/// i.e. viewport that are directly nested inside a parent viewport. /// i.e. viewport that are directly nested inside a parent viewport.
#[inline(always)]
#[allow(clippy::too_many_arguments)]
fn render_immediate_viewport( fn render_immediate_viewport(
event_loop: &EventLoopWindowTarget<UserEvent>, event_loop: &EventLoopWindowTarget<UserEvent>,
egui_ctx: &egui::Context, egui_ctx: &egui::Context,
mut viewport_builder: ViewportBuilder,
ids: ViewportIdPair,
viewport_ui_cb: Box<dyn FnOnce(&egui::Context) + '_>,
glutin: &RefCell<GlutinWindowContext>, glutin: &RefCell<GlutinWindowContext>,
painter: &RefCell<egui_glow::Painter>, painter: &RefCell<egui_glow::Painter>,
beginning: Instant, beginning: Instant,
immediate_viewport: ImmediateViewport<'_>,
) { ) {
crate::profile_function!(); crate::profile_function!();
let ImmediateViewport {
ids,
mut builder,
viewport_ui_cb,
} = immediate_viewport;
if !glutin.borrow().viewports.contains_key(&ids.this) { if !glutin.borrow().viewports.contains_key(&ids.this) {
// A new viewport - create a window for it! // A new viewport - create a window for it!
let mut glutin = glutin.borrow_mut(); let mut glutin = glutin.borrow_mut();
// Inherit parent icon if none // Inherit parent icon if none
if viewport_builder.icon.is_none() && glutin.builders.get(&ids.this).is_none() { if builder.icon.is_none() && glutin.builders.get(&ids.this).is_none() {
viewport_builder.icon = glutin builder.icon = glutin
.builders .builders
.get(&ids.parent) .get(&ids.parent)
.and_then(|b| b.icon.clone()); .and_then(|b| b.icon.clone());
@@ -1432,7 +1432,7 @@ mod glow_integration {
.entry(ids.this) .entry(ids.this)
.or_insert(Viewport::new(ids)); .or_insert(Viewport::new(ids));
glutin.builders.entry(ids.this).or_insert(viewport_builder); glutin.builders.entry(ids.this).or_insert(builder);
glutin glutin
.init_viewport(ids.this, event_loop) .init_viewport(ids.this, event_loop)
@@ -1820,8 +1820,8 @@ mod wgpu_integration {
use parking_lot::Mutex; use parking_lot::Mutex;
use egui::{ use egui::{
FullOutput, ViewportIdMap, ViewportIdPair, ViewportIdSet, ViewportOutput, FullOutput, ImmediateViewport, ViewportIdMap, ViewportIdPair, ViewportIdSet,
ViewportUiCallback, ViewportOutput, ViewportUiCallback,
}; };
use egui_winit::{create_winit_window_builder, process_viewport_commands}; use egui_winit::{create_winit_window_builder, process_viewport_commands};
@@ -2075,7 +2075,7 @@ mod wgpu_integration {
let event_loop: *const EventLoopWindowTarget<UserEvent> = event_loop; let event_loop: *const EventLoopWindowTarget<UserEvent> = event_loop;
egui::Context::set_immediate_viewport_renderer( egui::Context::set_immediate_viewport_renderer(
move |egui_ctx, viewport_builder, ids, viewport_ui_cb| { move |egui_ctx, immediate_viewport| {
if let Some(shared) = shared.upgrade() { if let Some(shared) = shared.upgrade() {
// SAFETY: the event loop lives longer than // SAFETY: the event loop lives longer than
// the Rc:s we just upgraded above. // the Rc:s we just upgraded above.
@@ -2085,11 +2085,9 @@ mod wgpu_integration {
render_immediate_viewport( render_immediate_viewport(
event_loop, event_loop,
egui_ctx, egui_ctx,
viewport_builder,
ids,
viewport_ui_cb,
beginning, beginning,
&shared, &shared,
immediate_viewport,
); );
} else { } else {
log::warn!("render_sync_callback called after window closed"); log::warn!("render_sync_callback called after window closed");
@@ -2125,19 +2123,21 @@ mod wgpu_integration {
Ok((window, window_builder)) Ok((window, window_builder))
} }
#[inline(always)]
#[allow(clippy::too_many_arguments)]
fn render_immediate_viewport( fn render_immediate_viewport(
event_loop: &EventLoopWindowTarget<UserEvent>, event_loop: &EventLoopWindowTarget<UserEvent>,
egui_ctx: &egui::Context, egui_ctx: &egui::Context,
mut viewport_builder: ViewportBuilder,
ids: ViewportIdPair,
viewport_ui_cb: Box<dyn FnOnce(&egui::Context) + '_>,
beginning: Instant, beginning: Instant,
shared: &RefCell<SharedState>, shared: &RefCell<SharedState>,
immediate_viewport: ImmediateViewport<'_>,
) { ) {
crate::profile_function!(); crate::profile_function!();
let ImmediateViewport {
ids,
mut builder,
viewport_ui_cb,
} = immediate_viewport;
let input = { let input = {
let mut shared = shared.borrow_mut(); let mut shared = shared.borrow_mut();
let SharedState { let SharedState {
@@ -2148,15 +2148,15 @@ mod wgpu_integration {
// Creating a new native window if is needed // Creating a new native window if is needed
if !viewports.contains_key(&ids.this) { if !viewports.contains_key(&ids.this) {
if viewport_builder.icon.is_none() { if builder.icon.is_none() {
viewport_builder.icon = viewports builder.icon = viewports
.get(&ids.parent) .get(&ids.parent)
.and_then(|vp| vp.builder.icon.clone()); .and_then(|vp| vp.builder.icon.clone());
} }
let viewport = viewports.entry(ids.this).or_insert(Viewport { let viewport = viewports.entry(ids.this).or_insert(Viewport {
ids, ids,
builder: viewport_builder, builder,
viewport_ui_cb: None, viewport_ui_cb: None,
window: None, window: None,
egui_winit: None, egui_winit: None,
@@ -2586,16 +2586,16 @@ mod wgpu_integration {
// Add new viewports, and update existing ones: // Add new viewports, and update existing ones:
for ViewportOutput { for ViewportOutput {
builder: mut new_builder,
ids, ids,
mut builder,
viewport_ui_cb, viewport_ui_cb,
} in out_viewports } in out_viewports
{ {
active_viewports_ids.insert(ids.this); active_viewports_ids.insert(ids.this);
if new_builder.icon.is_none() { if builder.icon.is_none() {
// Inherit icon from parent // Inherit icon from parent
new_builder.icon = viewports builder.icon = viewports
.get_mut(&ids.parent) .get_mut(&ids.parent)
.and_then(|vp| vp.builder.icon.clone()); .and_then(|vp| vp.builder.icon.clone());
} }
@@ -2605,7 +2605,7 @@ mod wgpu_integration {
// New viewport: // New viewport:
entry.insert(Viewport { entry.insert(Viewport {
ids, ids,
builder: new_builder, builder,
viewport_ui_cb, viewport_ui_cb,
window: None, window: None,
egui_winit: None, egui_winit: None,
@@ -2619,7 +2619,7 @@ mod wgpu_integration {
viewport.ids.parent = ids.parent; viewport.ids.parent = ids.parent;
viewport.viewport_ui_cb = viewport_ui_cb; viewport.viewport_ui_cb = viewport_ui_cb;
let (commands, recreate) = viewport.builder.patch(&new_builder); let (commands, recreate) = viewport.builder.patch(&builder);
if recreate { if recreate {
if let Some(viewport) = viewports.get_mut(&ids.this) { if let Some(viewport) = viewports.get_mut(&ids.this) {

View File

@@ -2517,8 +2517,7 @@ impl Context {
/// Look in `crates/eframe/native/run.rs` and search for `set_immediate_viewport_renderer` to see for what is used. /// Look in `crates/eframe/native/run.rs` and search for `set_immediate_viewport_renderer` to see for what is used.
#[allow(clippy::unused_self)] #[allow(clippy::unused_self)]
pub fn set_immediate_viewport_renderer( pub fn set_immediate_viewport_renderer(
callback: impl for<'a> Fn(&Context, ViewportBuilder, ViewportIdPair, Box<dyn FnOnce(&Context) + 'a>) callback: impl for<'a> Fn(&Context, ImmediateViewport<'a>) + 'static,
+ 'static,
) { ) {
let callback = Box::new(callback); let callback = Box::new(callback);
IMMEDIATE_VIEWPORT_RENDERER.with(|render_sync| { IMMEDIATE_VIEWPORT_RENDERER.with(|render_sync| {
@@ -2628,7 +2627,7 @@ impl Context {
/// `ctx.viewport_id() != ctx.parent_viewport_id` if false you should create a [`crate::Window`]. /// `ctx.viewport_id() != ctx.parent_viewport_id` if false you should create a [`crate::Window`].
pub fn show_viewport_immediate<T>( pub fn show_viewport_immediate<T>(
&self, &self,
viewport_builder: &ViewportBuilder, builder: ViewportBuilder,
viewport_ui_cb: impl FnOnce(&Context) -> T, viewport_ui_cb: impl FnOnce(&Context) -> T,
) -> T { ) -> T {
crate::profile_function!(); crate::profile_function!();
@@ -2647,9 +2646,9 @@ impl Context {
let ids = self.write(|ctx| { let ids = self.write(|ctx| {
let parent = ctx.viewport_id(); let parent = ctx.viewport_id();
if let Some(window) = ctx.viewports.get_mut(&viewport_builder.id) { if let Some(window) = ctx.viewports.get_mut(&builder.id) {
// Existing // Existing
window.builder = viewport_builder.clone(); window.builder = builder.clone();
window.ids.parent = parent; window.ids.parent = parent;
window.used = true; window.used = true;
window.viewport_ui_cb = None; window.viewport_ui_cb = None;
@@ -2657,13 +2656,13 @@ impl Context {
} else { } else {
// New // New
let ids = ViewportIdPair { let ids = ViewportIdPair {
this: viewport_builder.id, this: builder.id,
parent, parent,
}; };
ctx.viewports.insert( ctx.viewports.insert(
viewport_builder.id, builder.id,
ViewportState { ViewportState {
builder: viewport_builder.clone(), builder: builder.clone(),
ids, ids,
used: true, used: true,
viewport_ui_cb: None, viewport_ui_cb: None,
@@ -2677,12 +2676,13 @@ impl Context {
{ {
let out = &mut out; let out = &mut out;
immediate_viewport_renderer( let viewport = ImmediateViewport {
self,
viewport_builder.clone(),
ids, ids,
Box::new(move |context| *out = Some(viewport_ui_cb(context))), builder,
); viewport_ui_cb: Box::new(move |context| *out = Some(viewport_ui_cb(context))),
};
immediate_viewport_renderer(self, viewport);
} }
out.expect( out.expect(

View File

@@ -89,8 +89,7 @@ impl ViewportIdPair {
pub type ViewportUiCallback = dyn Fn(&Context) + Sync + Send; pub type ViewportUiCallback = dyn Fn(&Context) + Sync + Send;
/// Render the given viewport, calling the given ui callback. /// Render the given viewport, calling the given ui callback.
pub type ImmediateViewportRendererCallback = pub type ImmediateViewportRendererCallback = dyn for<'a> Fn(&Context, ImmediateViewport<'a>);
dyn for<'a> Fn(&Context, ViewportBuilder, ViewportIdPair, Box<dyn FnOnce(&Context) + 'a>);
/// Control the building of a new egui viewport (i.e. native window). /// Control the building of a new egui viewport (i.e. native window).
/// ///
@@ -734,3 +733,14 @@ impl ViewportOutput {
self.ids.this self.ids.this
} }
} }
/// Viewport for immediate rendering.
pub struct ImmediateViewport<'a> {
/// Id of us and our parent.
pub ids: ViewportIdPair,
pub builder: ViewportBuilder,
/// The user-code that shows the GUI.
pub viewport_ui_cb: Box<dyn FnOnce(&Context) + 'a>,
}

View File

@@ -72,7 +72,7 @@ impl ViewportState {
if immediate { if immediate {
let mut vp_state = vp_state.write(); let mut vp_state = vp_state.write();
ctx.show_viewport_immediate(&vp_builder, move |ctx| { ctx.show_viewport_immediate(vp_builder, move |ctx| {
show_as_popup(ctx, &title, vp_id.into(), |ui: &mut egui::Ui| { show_as_popup(ctx, &title, vp_id.into(), |ui: &mut egui::Ui| {
generic_child_ui(ui, &mut vp_state); generic_child_ui(ui, &mut vp_state);
}); });