1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-02 23:00:04 -04:00

Add ViewportIdPair, Viewport, ViewportOutput

This commit is contained in:
Konkitoman
2023-09-19 17:55:54 +03:00
parent c96197db79
commit 915d1b6997
4 changed files with 174 additions and 116 deletions

View File

@@ -461,7 +461,10 @@ fn run_and_exit(event_loop: EventLoop<UserEvent>, mut winit_app: impl WinitApp +
mod glow_integration { mod glow_integration {
use std::sync::Arc; 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::{ use egui_winit::{
changes_between_builders, create_winit_window_builder, process_viewport_commands, changes_between_builders, create_winit_window_builder, process_viewport_commands,
EventResponse, EventResponse,
@@ -1060,7 +1063,7 @@ mod glow_integration {
// ## Sync Rendering // ## Sync Rendering
integration.egui_ctx.set_render_sync_callback( 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(){ if viewport_builder.icon.is_none(){
viewport_builder.icon = glutin.read().builders.get(&parent_id).and_then(|b|b.icon.clone()); viewport_builder.icon = glutin.read().builders.get(&parent_id).and_then(|b|b.icon.clone());
} }
@@ -1181,16 +1184,16 @@ mod glow_integration {
fn process_viewport_builders( fn process_viewport_builders(
glutin_ctx: &Arc<RwLock<GlutinWindowContext>>, glutin_ctx: &Arc<RwLock<GlutinWindowContext>>,
mut viewports: Vec<( mut viewports: Vec<ViewportOutput>,
ViewportId,
ViewportId,
ViewportBuilder,
Option<Arc<Box<ViewportRender>>>,
)>,
) { ) {
let mut active_viewports_ids = vec![ViewportId::MAIN]; let mut active_viewports_ids = vec![ViewportId::MAIN];
viewports.retain_mut(|(id, _, builder, render)| { viewports.retain_mut(
|ViewportOutput {
builder,
pair: ViewportIdPair { this: id, .. },
render,
}| {
let mut glutin = glutin_ctx.write(); let mut glutin = glutin_ctx.write();
let last_builder = glutin.builders.entry(*id).or_insert(builder.clone()); let last_builder = glutin.builders.entry(*id).or_insert(builder.clone());
let (commands, recreate) = changes_between_builders(builder, last_builder); let (commands, recreate) = changes_between_builders(builder, last_builder);
@@ -1211,9 +1214,19 @@ mod glow_integration {
} else { } else {
true 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 let default_icon = glutin_ctx
.read() .read()
.builders .builders
@@ -1819,7 +1832,7 @@ pub use glow_integration::run_glow;
mod wgpu_integration { mod wgpu_integration {
use std::sync::Arc; use std::sync::Arc;
use egui::ViewportRender; use egui::{ViewportIdPair, ViewportOutput, ViewportRender};
use egui_winit::create_winit_window_builder; use egui_winit::create_winit_window_builder;
use parking_lot::Mutex; use parking_lot::Mutex;
@@ -2109,7 +2122,7 @@ mod wgpu_integration {
// ## Sync Rendering // ## Sync Rendering
integration.egui_ctx.set_render_sync_callback( 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 // 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(){ if _windows.read().get(&viewport_id).is_none(){
@@ -2338,7 +2351,12 @@ mod wgpu_integration {
let mut active_viewports_ids = vec![ViewportId::MAIN]; let mut active_viewports_ids = vec![ViewportId::MAIN];
viewports.retain_mut(|(id, parent, _builder, render)| { viewports.retain_mut(
|ViewportOutput {
pair: ViewportIdPair { this: id, parent },
render,
..
}| {
if let Some(w) = windows.write().get_mut(id) { if let Some(w) = windows.write().get_mut(id) {
w.render = render.clone(); w.render = render.clone();
w.parent_id = *parent; w.parent_id = *parent;
@@ -2347,9 +2365,19 @@ mod wgpu_integration {
} else { } else {
true 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() { if builder.icon.is_none() {
builder.icon = windows builder.icon = windows
.read() .read()

View File

@@ -200,16 +200,7 @@ struct ContextImpl {
repaint: Repaint, repaint: Repaint,
viewports: HashMap< viewports: HashMap<Id, Viewport>,
Id,
(
ViewportBuilder,
ViewportId,
ViewportId,
bool,
Option<Arc<Box<ViewportRender>>>,
),
>,
viewport_commands: Vec<(ViewportId, ViewportCommand)>, viewport_commands: Vec<(ViewportId, ViewportCommand)>,
render_sync: Option<Arc<Box<ViewportRenderSyncCallback>>>, render_sync: Option<Arc<Box<ViewportRenderSyncCallback>>>,
@@ -483,9 +474,9 @@ impl Default for Context {
s.write(|ctx| { s.write(|ctx| {
ctx.force_embedding = true; ctx.force_embedding = true;
ctx.render_sync = Some(Arc::new(Box::new( ctx.render_sync = Some(Arc::new(Box::new(move |ctx, _builder, _pair, render| {
move |ctx, _builder, _viewport_id, _parent_viewport_id, render| render(ctx), render(ctx);
))); })));
}); });
s s
@@ -1494,7 +1485,15 @@ impl Context {
); );
ctx.viewports ctx.viewports
.iter() .iter()
.map(|(_, (_, id, _, _, _))| *id) .map(
|(
_,
Viewport {
pair: ViewportIdPair { this, .. },
..
},
)| *this,
)
.collect() .collect()
}); });
viewports.push(ViewportId::MAIN); 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! // If there are no viewport that contains the current viewport that viewport needs to be destroyed!
let avalibile_viewports = self.read(|ctx| { let avalibile_viewports = self.read(|ctx| {
let mut avalibile_viewports = vec![ViewportId::MAIN]; let mut avalibile_viewports = vec![ViewportId::MAIN];
for (_, id, _, _, _) in ctx.viewports.values() { for Viewport {
avalibile_viewports.push(*id); pair: ViewportIdPair { this, .. },
..
} in ctx.viewports.values()
{
avalibile_viewports.push(*this);
} }
avalibile_viewports avalibile_viewports
}); });
@@ -1572,17 +1575,29 @@ impl Context {
let mut viewports = Vec::new(); let mut viewports = Vec::new();
self.write(|ctx| { self.write(|ctx| {
ctx.viewports ctx.viewports.retain(
.retain(|_, (builder, id, parent, used, render)| { |_,
Viewport {
builder,
pair,
used,
render,
}| {
let out = *used; let out = *used;
if viewport_id == *parent { if viewport_id == pair.parent {
*used = false; *used = false;
} }
viewports.push((*id, *parent, builder.clone(), render.clone())); viewports.push(ViewportOutput {
(out || viewport_id != *parent) && avalibile_viewports.contains(parent) 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! // This is used to resume the last frame!
@@ -2533,14 +2548,9 @@ impl Context {
self.read(|ctx| ctx.get_parent_viewport_id()) self.read(|ctx| ctx.get_parent_viewport_id())
} }
/// This will return the `ViewportId` of the specified id /// This will return the `ViewportIdPair` of the specified id
pub fn get_viewport_id_by_id(&self, id: impl Into<Id>) -> Option<ViewportId> { pub fn get_viewport_id_pair(&self, id: impl Into<Id>) -> Option<ViewportIdPair> {
self.read(|ctx| ctx.viewports.get(&id.into()).map(|v| v.1)) self.read(|ctx| ctx.viewports.get(&id.into()).map(|v| v.pair))
}
/// This will return the parent `ViewportId` of the specified id
pub fn get_viewport_parent_id_by_id(&self, id: impl Into<Id>) -> Option<ViewportId> {
self.read(|ctx| ctx.viewports.get(&id.into()).map(|v| v.1))
} }
/// This should only be used by the backend! /// 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! /// 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( pub fn set_render_sync_callback(
&self, &self,
callback: impl for<'a> Fn( callback: impl for<'a> Fn(&Context, ViewportBuilder, ViewportIdPair, Box<dyn FnOnce(&Context) + 'a>)
&Context, + Send
ViewportBuilder,
ViewportId,
ViewportId,
Box<dyn FnOnce(&Context) + 'a>,
) + Send
+ Sync + Sync
+ 'static, + 'static,
) { ) {
@@ -2603,22 +2608,24 @@ impl Context {
self.write(|ctx| { self.write(|ctx| {
let viewport_id = ctx.get_viewport_id(); let viewport_id = ctx.get_viewport_id();
if let Some(window) = ctx.viewports.get_mut(&viewport_builder.id) { if let Some(window) = ctx.viewports.get_mut(&viewport_builder.id) {
window.0 = viewport_builder; window.builder = viewport_builder;
window.2 = viewport_id; window.pair.parent = viewport_id;
window.3 = true; window.used = true;
window.4 = Some(Arc::new(Box::new(render))); window.render = Some(Arc::new(Box::new(render)));
} else { } else {
let id = ViewportId(ctx.viewport_counter + 1); let id = ViewportId(ctx.viewport_counter + 1);
ctx.viewport_counter += 1; ctx.viewport_counter += 1;
ctx.viewports.insert( ctx.viewports.insert(
viewport_builder.id, viewport_builder.id,
( Viewport {
viewport_builder, builder: viewport_builder,
id, pair: ViewportIdPair {
viewport_id, this: id,
true, parent: viewport_id,
Some(Arc::new(Box::new(render))), },
), used: true,
render: Some(Arc::new(Box::new(render))),
},
); );
} }
}); });
@@ -2640,26 +2647,28 @@ impl Context {
func: impl FnOnce(&Context) -> T, func: impl FnOnce(&Context) -> T,
) -> T { ) -> T {
if !self.force_embedding() { if !self.force_embedding() {
let mut viewport_id = ViewportId::MAIN; let mut id_pair = ViewportIdPair::MAIN;
let mut parent_viewport_id = ViewportId::MAIN;
let render_sync = self.write(|ctx| { 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) { if let Some(window) = ctx.viewports.get_mut(&viewport_builder.id) {
window.0 = viewport_builder.clone(); window.builder = viewport_builder.clone();
window.2 = viewport_id; window.pair.parent = id_pair.parent;
window.3 = true; window.used = true;
window.4 = None; window.render = None;
viewport_id = window.1; id_pair = window.pair;
parent_viewport_id = window.2;
} else { } else {
let id = ViewportId(ctx.viewport_counter + 1); let id = ViewportId(ctx.viewport_counter + 1);
ctx.viewport_counter += 1; ctx.viewport_counter += 1;
id_pair.this = id;
ctx.viewports.insert( ctx.viewports.insert(
viewport_builder.id, 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() ctx.render_sync.clone()
@@ -2670,8 +2679,7 @@ impl Context {
render_sync.unwrap()( render_sync.unwrap()(
self, self,
viewport_builder, viewport_builder,
viewport_id, id_pair,
parent_viewport_id,
Box::new(move |context| *out = Some(func(context))), Box::new(move |context| *out = Some(func(context))),
); );
} }

View File

@@ -1,9 +1,7 @@
//! All the data egui returns to the backend at the end of each frame. //! All the data egui returns to the backend at the end of each frame.
use std::sync::Arc; use crate::ViewportId;
use crate::{ViewportCommand, ViewportOutput, WidgetType};
use crate::{ViewportBuilder, ViewportCommand, WidgetType};
use crate::{ViewportId, ViewportRender};
/// What egui emits each frame from [`crate::Context::run`]. /// 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. /// You can use [`crate::Context::tessellate`] to turn this into triangles.
pub shapes: Vec<epaint::ClippedShape>, pub shapes: Vec<epaint::ClippedShape>,
pub viewports: Vec<( pub viewports: Vec<ViewportOutput>,
ViewportId,
ViewportId,
ViewportBuilder,
Option<Arc<Box<ViewportRender>>>,
)>,
pub viewport_commands: Vec<(ViewportId, ViewportCommand)>, pub viewport_commands: Vec<(ViewportId, ViewportCommand)>,
} }

View File

@@ -21,10 +21,24 @@ impl ViewportId {
pub const MAIN: Self = Self(0); 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 /// This is used to render an async viewport
pub type ViewportRender = dyn Fn(&Context) + Sync + Send; pub type ViewportRender = dyn Fn(&Context) + Sync + Send;
pub type ViewportRenderSyncCallback = dyn for<'a> Fn(&Context, ViewportBuilder, ViewportId, ViewportId, Box<dyn FnOnce(&Context) + 'a>) pub type ViewportRenderSyncCallback = dyn for<'a> Fn(&Context, ViewportBuilder, ViewportIdPair, Box<dyn FnOnce(&Context) + 'a>)
+ Send + Send
+ Sync; + Sync;
@@ -304,3 +318,18 @@ pub enum ViewportCommand {
CursorHitTest(bool), CursorHitTest(bool),
} }
#[derive(Clone)]
pub(crate) struct Viewport {
pub(crate) builder: ViewportBuilder,
pub(crate) pair: ViewportIdPair,
pub(crate) used: bool,
pub(crate) render: Option<Arc<Box<ViewportRender>>>,
}
#[derive(Clone)]
pub struct ViewportOutput {
pub builder: ViewportBuilder,
pub pair: ViewportIdPair,
pub render: Option<Arc<Box<ViewportRender>>>,
}