From 915d1b699749c9cdd824f0c1b6bad496bc3a4b5c Mon Sep 17 00:00:00 2001 From: Konkitoman Date: Tue, 19 Sep 2023 17:55:54 +0300 Subject: [PATCH] Add ViewportIdPair, Viewport, ViewportOutput --- crates/eframe/src/native/run.rs | 114 ++++++++++++++++----------- crates/egui/src/context.rs | 132 +++++++++++++++++--------------- crates/egui/src/data/output.rs | 13 +--- crates/egui/src/viewport.rs | 31 +++++++- 4 files changed, 174 insertions(+), 116 deletions(-) diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index d86d94410..befae8f90 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -461,7 +461,10 @@ fn run_and_exit(event_loop: EventLoop, mut winit_app: impl WinitApp + mod glow_integration { use std::sync::Arc; - use egui::{epaint::ahash::HashMap, mutex::RwLock, NumExt as _, ViewportRender}; + use egui::{ + epaint::ahash::HashMap, mutex::RwLock, NumExt as _, ViewportIdPair, ViewportOutput, + ViewportRender, + }; use egui_winit::{ changes_between_builders, create_winit_window_builder, process_viewport_commands, EventResponse, @@ -1060,7 +1063,7 @@ mod glow_integration { // ## Sync Rendering integration.egui_ctx.set_render_sync_callback( - move |egui_ctx, mut viewport_builder, viewport_id, parent_id, render| { + move |egui_ctx, mut viewport_builder, ViewportIdPair{ this: viewport_id, parent: parent_id }, render| { if viewport_builder.icon.is_none(){ viewport_builder.icon = glutin.read().builders.get(&parent_id).and_then(|b|b.icon.clone()); } @@ -1181,39 +1184,49 @@ mod glow_integration { fn process_viewport_builders( glutin_ctx: &Arc>, - mut viewports: Vec<( - ViewportId, - ViewportId, - ViewportBuilder, - Option>>, - )>, + mut viewports: Vec, ) { let mut active_viewports_ids = vec![ViewportId::MAIN]; - viewports.retain_mut(|(id, _, builder, render)| { - let mut glutin = glutin_ctx.write(); - let last_builder = glutin.builders.entry(*id).or_insert(builder.clone()); - let (commands, recreate) = changes_between_builders(builder, last_builder); - drop(glutin); - if let Some(w) = glutin_ctx.read().windows.get(id) { - let mut w = w.write(); - if recreate { - w.window = None; - w.gl_surface = None; - w.render = render.clone(); - w.parent_id = *id; + viewports.retain_mut( + |ViewportOutput { + builder, + pair: ViewportIdPair { this: id, .. }, + render, + }| { + let mut glutin = glutin_ctx.write(); + let last_builder = glutin.builders.entry(*id).or_insert(builder.clone()); + let (commands, recreate) = changes_between_builders(builder, last_builder); + drop(glutin); + if let Some(w) = glutin_ctx.read().windows.get(id) { + let mut w = w.write(); + if recreate { + w.window = None; + w.gl_surface = None; + w.render = render.clone(); + w.parent_id = *id; + } + if let Some(w) = w.window.clone() { + process_viewport_commands(commands, *id, None, &w); + } + active_viewports_ids.push(*id); + false + } else { + true } - if let Some(w) = w.window.clone() { - process_viewport_commands(commands, *id, None, &w); - } - active_viewports_ids.push(*id); - false - } else { - true - } - }); + }, + ); - for (id, parent_id, mut builder, render) in viewports { + for ViewportOutput { + mut builder, + pair: + ViewportIdPair { + this: id, + parent: parent_id, + }, + render, + } in viewports + { let default_icon = glutin_ctx .read() .builders @@ -1819,7 +1832,7 @@ pub use glow_integration::run_glow; mod wgpu_integration { use std::sync::Arc; - use egui::ViewportRender; + use egui::{ViewportIdPair, ViewportOutput, ViewportRender}; use egui_winit::create_winit_window_builder; use parking_lot::Mutex; @@ -2109,7 +2122,7 @@ mod wgpu_integration { // ## Sync Rendering integration.egui_ctx.set_render_sync_callback( - move |egui_ctx, viewport_builder, viewport_id, parent_viewport_id, render| { + move |egui_ctx, viewport_builder, ViewportIdPair{this: viewport_id, parent: parent_viewport_id} , render| { // TODO: If the `viewport_builder` do not have a icon set the icon to be the icon of the parent viewport if _windows.read().get(&viewport_id).is_none(){ @@ -2338,18 +2351,33 @@ mod wgpu_integration { let mut active_viewports_ids = vec![ViewportId::MAIN]; - viewports.retain_mut(|(id, parent, _builder, render)| { - if let Some(w) = windows.write().get_mut(id) { - w.render = render.clone(); - w.parent_id = *parent; - active_viewports_ids.push(*id); - false - } else { - true - } - }); + viewports.retain_mut( + |ViewportOutput { + pair: ViewportIdPair { this: id, parent }, + render, + .. + }| { + if let Some(w) = windows.write().get_mut(id) { + w.render = render.clone(); + w.parent_id = *parent; + active_viewports_ids.push(*id); + false + } else { + true + } + }, + ); - for (id, parent_id, mut builder, render) in viewports { + for ViewportOutput { + mut builder, + pair: + ViewportIdPair { + this: id, + parent: parent_id, + }, + render, + } in viewports + { if builder.icon.is_none() { builder.icon = windows .read() diff --git a/crates/egui/src/context.rs b/crates/egui/src/context.rs index 8e4573a5e..dc0de9d67 100644 --- a/crates/egui/src/context.rs +++ b/crates/egui/src/context.rs @@ -200,16 +200,7 @@ struct ContextImpl { repaint: Repaint, - viewports: HashMap< - Id, - ( - ViewportBuilder, - ViewportId, - ViewportId, - bool, - Option>>, - ), - >, + viewports: HashMap, viewport_commands: Vec<(ViewportId, ViewportCommand)>, render_sync: Option>>, @@ -483,9 +474,9 @@ impl Default for Context { s.write(|ctx| { ctx.force_embedding = true; - ctx.render_sync = Some(Arc::new(Box::new( - move |ctx, _builder, _viewport_id, _parent_viewport_id, render| render(ctx), - ))); + ctx.render_sync = Some(Arc::new(Box::new(move |ctx, _builder, _pair, render| { + render(ctx); + }))); }); s @@ -1494,7 +1485,15 @@ impl Context { ); ctx.viewports .iter() - .map(|(_, (_, id, _, _, _))| *id) + .map( + |( + _, + Viewport { + pair: ViewportIdPair { this, .. }, + .. + }, + )| *this, + ) .collect() }); viewports.push(ViewportId::MAIN); @@ -1562,8 +1561,12 @@ impl Context { // If there are no viewport that contains the current viewport that viewport needs to be destroyed! let avalibile_viewports = self.read(|ctx| { let mut avalibile_viewports = vec![ViewportId::MAIN]; - for (_, id, _, _, _) in ctx.viewports.values() { - avalibile_viewports.push(*id); + for Viewport { + pair: ViewportIdPair { this, .. }, + .. + } in ctx.viewports.values() + { + avalibile_viewports.push(*this); } avalibile_viewports }); @@ -1572,17 +1575,29 @@ impl Context { let mut viewports = Vec::new(); self.write(|ctx| { - ctx.viewports - .retain(|_, (builder, id, parent, used, render)| { + ctx.viewports.retain( + |_, + Viewport { + builder, + pair, + used, + render, + }| { let out = *used; - if viewport_id == *parent { + if viewport_id == pair.parent { *used = false; } - viewports.push((*id, *parent, builder.clone(), render.clone())); - (out || viewport_id != *parent) && avalibile_viewports.contains(parent) - }); + viewports.push(ViewportOutput { + builder: builder.clone(), + pair: *pair, + render: render.clone(), + }); + (out || viewport_id != pair.parent) + && avalibile_viewports.contains(&pair.parent) + }, + ); }); // This is used to resume the last frame! @@ -2533,14 +2548,9 @@ impl Context { self.read(|ctx| ctx.get_parent_viewport_id()) } - /// This will return the `ViewportId` of the specified id - pub fn get_viewport_id_by_id(&self, id: impl Into) -> Option { - self.read(|ctx| ctx.viewports.get(&id.into()).map(|v| v.1)) - } - - /// This will return the parent `ViewportId` of the specified id - pub fn get_viewport_parent_id_by_id(&self, id: impl Into) -> Option { - self.read(|ctx| ctx.viewports.get(&id.into()).map(|v| v.1)) + /// This will return the `ViewportIdPair` of the specified id + pub fn get_viewport_id_pair(&self, id: impl Into) -> Option { + self.read(|ctx| ctx.viewports.get(&id.into()).map(|v| v.pair)) } /// This should only be used by the backend! @@ -2550,13 +2560,8 @@ impl Context { /// Look in `crates/eframe/native/run.rs` and search for ``set_render_sync_callback`` to see for what is used! pub fn set_render_sync_callback( &self, - callback: impl for<'a> Fn( - &Context, - ViewportBuilder, - ViewportId, - ViewportId, - Box, - ) + Send + callback: impl for<'a> Fn(&Context, ViewportBuilder, ViewportIdPair, Box) + + Send + Sync + 'static, ) { @@ -2603,22 +2608,24 @@ impl Context { self.write(|ctx| { let viewport_id = ctx.get_viewport_id(); if let Some(window) = ctx.viewports.get_mut(&viewport_builder.id) { - window.0 = viewport_builder; - window.2 = viewport_id; - window.3 = true; - window.4 = Some(Arc::new(Box::new(render))); + window.builder = viewport_builder; + window.pair.parent = viewport_id; + window.used = true; + window.render = Some(Arc::new(Box::new(render))); } else { let id = ViewportId(ctx.viewport_counter + 1); ctx.viewport_counter += 1; ctx.viewports.insert( viewport_builder.id, - ( - viewport_builder, - id, - viewport_id, - true, - Some(Arc::new(Box::new(render))), - ), + Viewport { + builder: viewport_builder, + pair: ViewportIdPair { + this: id, + parent: viewport_id, + }, + used: true, + render: Some(Arc::new(Box::new(render))), + }, ); } }); @@ -2640,26 +2647,28 @@ impl Context { func: impl FnOnce(&Context) -> T, ) -> T { if !self.force_embedding() { - let mut viewport_id = ViewportId::MAIN; - let mut parent_viewport_id = ViewportId::MAIN; + let mut id_pair = ViewportIdPair::MAIN; let render_sync = self.write(|ctx| { - viewport_id = ctx.get_viewport_id(); + id_pair.parent = ctx.get_viewport_id(); if let Some(window) = ctx.viewports.get_mut(&viewport_builder.id) { - window.0 = viewport_builder.clone(); - window.2 = viewport_id; - window.3 = true; - window.4 = None; - viewport_id = window.1; - parent_viewport_id = window.2; + window.builder = viewport_builder.clone(); + window.pair.parent = id_pair.parent; + window.used = true; + window.render = None; + id_pair = window.pair; } else { let id = ViewportId(ctx.viewport_counter + 1); ctx.viewport_counter += 1; + id_pair.this = id; ctx.viewports.insert( viewport_builder.id, - (viewport_builder.clone(), id, viewport_id, true, None), + Viewport { + builder: viewport_builder.clone(), + pair: id_pair, + used: true, + render: None, + }, ); - viewport_id = id; - parent_viewport_id = ctx.get_viewport_id(); } ctx.render_sync.clone() @@ -2670,8 +2679,7 @@ impl Context { render_sync.unwrap()( self, viewport_builder, - viewport_id, - parent_viewport_id, + id_pair, Box::new(move |context| *out = Some(func(context))), ); } diff --git a/crates/egui/src/data/output.rs b/crates/egui/src/data/output.rs index 3bf22d991..e4b36314e 100644 --- a/crates/egui/src/data/output.rs +++ b/crates/egui/src/data/output.rs @@ -1,9 +1,7 @@ //! All the data egui returns to the backend at the end of each frame. -use std::sync::Arc; - -use crate::{ViewportBuilder, ViewportCommand, WidgetType}; -use crate::{ViewportId, ViewportRender}; +use crate::ViewportId; +use crate::{ViewportCommand, ViewportOutput, WidgetType}; /// What egui emits each frame from [`crate::Context::run`]. /// @@ -34,12 +32,7 @@ pub struct FullOutput { /// You can use [`crate::Context::tessellate`] to turn this into triangles. pub shapes: Vec, - pub viewports: Vec<( - ViewportId, - ViewportId, - ViewportBuilder, - Option>>, - )>, + pub viewports: Vec, pub viewport_commands: Vec<(ViewportId, ViewportCommand)>, } diff --git a/crates/egui/src/viewport.rs b/crates/egui/src/viewport.rs index abe9c8ba4..3c6456fb4 100644 --- a/crates/egui/src/viewport.rs +++ b/crates/egui/src/viewport.rs @@ -21,10 +21,24 @@ impl ViewportId { pub const MAIN: Self = Self(0); } +#[derive(Default, Debug, Hash, Clone, Copy, PartialEq, Eq)] +pub struct ViewportIdPair { + pub this: ViewportId, + pub parent: ViewportId, +} + +impl ViewportIdPair { + /// This will return the `ViewportIdPair` of the main viewport + pub const MAIN: Self = Self { + this: ViewportId::MAIN, + parent: ViewportId::MAIN, + }; +} + /// This is used to render an async viewport pub type ViewportRender = dyn Fn(&Context) + Sync + Send; -pub type ViewportRenderSyncCallback = dyn for<'a> Fn(&Context, ViewportBuilder, ViewportId, ViewportId, Box) +pub type ViewportRenderSyncCallback = dyn for<'a> Fn(&Context, ViewportBuilder, ViewportIdPair, Box) + Send + Sync; @@ -304,3 +318,18 @@ pub enum ViewportCommand { CursorHitTest(bool), } + +#[derive(Clone)] +pub(crate) struct Viewport { + pub(crate) builder: ViewportBuilder, + pub(crate) pair: ViewportIdPair, + pub(crate) used: bool, + pub(crate) render: Option>>, +} + +#[derive(Clone)] +pub struct ViewportOutput { + pub builder: ViewportBuilder, + pub pair: ViewportIdPair, + pub render: Option>>, +}