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:
@@ -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,39 +1184,49 @@ 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(
|
||||||
let mut glutin = glutin_ctx.write();
|
|ViewportOutput {
|
||||||
let last_builder = glutin.builders.entry(*id).or_insert(builder.clone());
|
builder,
|
||||||
let (commands, recreate) = changes_between_builders(builder, last_builder);
|
pair: ViewportIdPair { this: id, .. },
|
||||||
drop(glutin);
|
render,
|
||||||
if let Some(w) = glutin_ctx.read().windows.get(id) {
|
}| {
|
||||||
let mut w = w.write();
|
let mut glutin = glutin_ctx.write();
|
||||||
if recreate {
|
let last_builder = glutin.builders.entry(*id).or_insert(builder.clone());
|
||||||
w.window = None;
|
let (commands, recreate) = changes_between_builders(builder, last_builder);
|
||||||
w.gl_surface = None;
|
drop(glutin);
|
||||||
w.render = render.clone();
|
if let Some(w) = glutin_ctx.read().windows.get(id) {
|
||||||
w.parent_id = *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
|
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,18 +2351,33 @@ 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(
|
||||||
if let Some(w) = windows.write().get_mut(id) {
|
|ViewportOutput {
|
||||||
w.render = render.clone();
|
pair: ViewportIdPair { this: id, parent },
|
||||||
w.parent_id = *parent;
|
render,
|
||||||
active_viewports_ids.push(*id);
|
..
|
||||||
false
|
}| {
|
||||||
} else {
|
if let Some(w) = windows.write().get_mut(id) {
|
||||||
true
|
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() {
|
if builder.icon.is_none() {
|
||||||
builder.icon = windows
|
builder.icon = windows
|
||||||
.read()
|
.read()
|
||||||
|
|||||||
@@ -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))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>>>,
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user