mirror of
https://github.com/emilk/egui.git
synced 2026-09-01 14:20:04 -04:00
Now viewport_id always will be in a ViewportId you cannot create a ViewportId you can only get the main one everywere or get the current viewport id with Context::get_viewport_id
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1195,6 +1195,7 @@ version = "0.22.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"document-features",
|
"document-features",
|
||||||
|
"egui",
|
||||||
"epaint",
|
"epaint",
|
||||||
"log",
|
"log",
|
||||||
"puffin",
|
"puffin",
|
||||||
|
|||||||
@@ -269,6 +269,8 @@ pub fn run_simple_native(
|
|||||||
native_options: NativeOptions,
|
native_options: NativeOptions,
|
||||||
update_fun: impl FnMut(&egui::Context, &mut Frame) + 'static,
|
update_fun: impl FnMut(&egui::Context, &mut Frame) + 'static,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
use egui::{ViewportId, ViewportRender};
|
||||||
|
|
||||||
struct SimpleApp<U> {
|
struct SimpleApp<U> {
|
||||||
update_fun: U,
|
update_fun: U,
|
||||||
}
|
}
|
||||||
@@ -277,12 +279,12 @@ pub fn run_simple_native(
|
|||||||
&mut self,
|
&mut self,
|
||||||
ctx: &egui::Context,
|
ctx: &egui::Context,
|
||||||
frame: &mut Frame,
|
frame: &mut Frame,
|
||||||
render_function: Option<&(dyn Fn(&egui::Context, u64, u64) + Send + Sync)>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if ctx.get_viewport_id() == 0 {
|
if ctx.get_viewport_id() == ViewportId::MAIN {
|
||||||
(self.update_fun)(ctx, frame);
|
(self.update_fun)(ctx, frame);
|
||||||
} else if let Some(render_function) = render_function {
|
} else if let Some(render_function) = render {
|
||||||
render_function(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id())
|
render_function(ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use raw_window_handle::{HasRawDisplayHandle as _, HasRawWindowHandle as _};
|
|||||||
|
|
||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
use egui::accesskit;
|
use egui::accesskit;
|
||||||
use egui::{Context, NumExt as _, ViewportBuilder};
|
use egui::{Context, NumExt as _, ViewportBuilder, ViewportId, ViewportRender};
|
||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
use egui_winit::accesskit_winit;
|
use egui_winit::accesskit_winit;
|
||||||
use egui_winit::{native_pixels_per_point, EventResponse, WindowSettings};
|
use egui_winit::{native_pixels_per_point, EventResponse, WindowSettings};
|
||||||
@@ -432,7 +432,14 @@ impl EpiIntegration {
|
|||||||
let saved_memory: egui::Memory = self.egui_ctx.memory(|mem| mem.clone());
|
let saved_memory: egui::Memory = self.egui_ctx.memory(|mem| mem.clone());
|
||||||
self.egui_ctx
|
self.egui_ctx
|
||||||
.memory_mut(|mem| mem.set_everything_is_visible(true));
|
.memory_mut(|mem| mem.set_everything_is_visible(true));
|
||||||
let full_output = self.update(app, window, egui_winit, None, 0, 0);
|
let full_output = self.update(
|
||||||
|
app,
|
||||||
|
window,
|
||||||
|
egui_winit,
|
||||||
|
None,
|
||||||
|
ViewportId::MAIN,
|
||||||
|
ViewportId::MAIN,
|
||||||
|
);
|
||||||
self.pending_full_output.append(full_output); // Handle it next frame
|
self.pending_full_output.append(full_output); // Handle it next frame
|
||||||
self.egui_ctx.memory_mut(|mem| *mem = saved_memory); // We don't want to remember that windows were huge.
|
self.egui_ctx.memory_mut(|mem| *mem = saved_memory); // We don't want to remember that windows were huge.
|
||||||
self.egui_ctx.clear_animations();
|
self.egui_ctx.clear_animations();
|
||||||
@@ -449,14 +456,14 @@ impl EpiIntegration {
|
|||||||
event: &winit::event::WindowEvent<'_>,
|
event: &winit::event::WindowEvent<'_>,
|
||||||
window_id: &winit::window::WindowId,
|
window_id: &winit::window::WindowId,
|
||||||
egui_winit: &mut egui_winit::State,
|
egui_winit: &mut egui_winit::State,
|
||||||
viewport_id: u64,
|
viewport_id: ViewportId,
|
||||||
) -> EventResponse {
|
) -> EventResponse {
|
||||||
use winit::event::{ElementState, MouseButton, WindowEvent};
|
use winit::event::{ElementState, MouseButton, WindowEvent};
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
WindowEvent::CloseRequested => {
|
WindowEvent::CloseRequested => {
|
||||||
log::debug!("Received WindowEvent::CloseRequested");
|
log::debug!("Received WindowEvent::CloseRequested");
|
||||||
self.close = app.on_close_event() && viewport_id == 0;
|
self.close = app.on_close_event() && viewport_id == ViewportId::MAIN;
|
||||||
log::debug!("App::on_close_event returned {}", self.close);
|
log::debug!("App::on_close_event returned {}", self.close);
|
||||||
}
|
}
|
||||||
WindowEvent::Destroyed => {
|
WindowEvent::Destroyed => {
|
||||||
@@ -497,9 +504,9 @@ impl EpiIntegration {
|
|||||||
app: &mut dyn epi::App,
|
app: &mut dyn epi::App,
|
||||||
window: &winit::window::Window,
|
window: &winit::window::Window,
|
||||||
egui_winit: &mut egui_winit::State,
|
egui_winit: &mut egui_winit::State,
|
||||||
render: Option<Arc<Box<dyn Fn(&Context, u64, u64) + Sync + Send>>>,
|
render: Option<Arc<Box<ViewportRender>>>,
|
||||||
viewport_id: u64,
|
viewport_id: egui::ViewportId,
|
||||||
parent_id: u64,
|
parent_id: egui::ViewportId,
|
||||||
) -> egui::FullOutput {
|
) -> egui::FullOutput {
|
||||||
let frame_start = std::time::Instant::now();
|
let frame_start = std::time::Instant::now();
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
use std::{sync::Arc, time::Instant};
|
use std::{sync::Arc, time::Instant};
|
||||||
|
|
||||||
use egui::{epaint::ahash::HashMap, mutex::RwLock, ViewportBuilder};
|
use egui::{epaint::ahash::HashMap, mutex::RwLock, ViewportBuilder, ViewportId};
|
||||||
use raw_window_handle::{HasRawDisplayHandle as _, HasRawWindowHandle as _};
|
use raw_window_handle::{HasRawDisplayHandle as _, HasRawWindowHandle as _};
|
||||||
use winit::{
|
use winit::{
|
||||||
event_loop::{ControlFlow, EventLoop, EventLoopBuilder, EventLoopProxy, EventLoopWindowTarget},
|
event_loop::{ControlFlow, EventLoop, EventLoopBuilder, EventLoopProxy, EventLoopWindowTarget},
|
||||||
@@ -23,7 +23,7 @@ use super::epi_integration::{self, load_icon, EpiIntegration};
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum UserEvent {
|
pub enum UserEvent {
|
||||||
RequestRepaint {
|
RequestRepaint {
|
||||||
window_id: u64,
|
id: ViewportId,
|
||||||
when: Instant,
|
when: Instant,
|
||||||
/// What the frame number was when the repaint was _requested_.
|
/// What the frame number was when the repaint was _requested_.
|
||||||
frame_nr: u64,
|
frame_nr: u64,
|
||||||
@@ -79,8 +79,8 @@ trait WinitApp {
|
|||||||
window_id: winit::window::WindowId,
|
window_id: winit::window::WindowId,
|
||||||
) -> Option<Arc<RwLock<winit::window::Window>>>;
|
) -> Option<Arc<RwLock<winit::window::Window>>>;
|
||||||
|
|
||||||
fn get_window_winit_id(&self, id: u64) -> Option<winit::window::WindowId>;
|
fn get_window_winit_id(&self, id: ViewportId) -> Option<winit::window::WindowId>;
|
||||||
fn get_window_id(&self, id: &winit::window::WindowId) -> Option<u64>;
|
fn get_window_id(&self, id: &winit::window::WindowId) -> Option<ViewportId>;
|
||||||
|
|
||||||
fn save_and_destroy(&mut self);
|
fn save_and_destroy(&mut self);
|
||||||
|
|
||||||
@@ -168,7 +168,7 @@ fn run_and_return(
|
|||||||
winit::event::Event::UserEvent(UserEvent::RequestRepaint {
|
winit::event::Event::UserEvent(UserEvent::RequestRepaint {
|
||||||
when,
|
when,
|
||||||
frame_nr,
|
frame_nr,
|
||||||
window_id,
|
id: window_id,
|
||||||
}) => {
|
}) => {
|
||||||
if winit_app.frame_nr() == *frame_nr {
|
if winit_app.frame_nr() == *frame_nr {
|
||||||
log::trace!("UserEvent::RequestRepaint scheduling repaint at {when:?}");
|
log::trace!("UserEvent::RequestRepaint scheduling repaint at {when:?}");
|
||||||
@@ -325,7 +325,7 @@ fn run_and_exit(event_loop: EventLoop<UserEvent>, mut winit_app: impl WinitApp +
|
|||||||
winit::event::Event::UserEvent(UserEvent::RequestRepaint {
|
winit::event::Event::UserEvent(UserEvent::RequestRepaint {
|
||||||
when,
|
when,
|
||||||
frame_nr,
|
frame_nr,
|
||||||
window_id,
|
id: window_id,
|
||||||
}) => {
|
}) => {
|
||||||
if winit_app.frame_nr() == frame_nr {
|
if winit_app.frame_nr() == frame_nr {
|
||||||
if let Some(window_id) = winit_app.get_window_winit_id(window_id) {
|
if let Some(window_id) = winit_app.get_window_winit_id(window_id) {
|
||||||
@@ -462,8 +462,8 @@ mod glow_integration {
|
|||||||
builder: ViewportBuilder,
|
builder: ViewportBuilder,
|
||||||
gl_surface: Option<glutin::surface::Surface<glutin::surface::WindowSurface>>,
|
gl_surface: Option<glutin::surface::Surface<glutin::surface::WindowSurface>>,
|
||||||
window: Option<Arc<RwLock<winit::window::Window>>>,
|
window: Option<Arc<RwLock<winit::window::Window>>>,
|
||||||
window_id: u64,
|
window_id: ViewportId,
|
||||||
parent_id: u64,
|
parent_id: ViewportId,
|
||||||
render: Option<Arc<Box<ViewportRender>>>,
|
render: Option<Arc<Box<ViewportRender>>>,
|
||||||
pub egui_winit: Option<egui_winit::State>,
|
pub egui_winit: Option<egui_winit::State>,
|
||||||
}
|
}
|
||||||
@@ -487,11 +487,13 @@ mod glow_integration {
|
|||||||
current_gl_context: Option<glutin::context::PossiblyCurrentContext>,
|
current_gl_context: Option<glutin::context::PossiblyCurrentContext>,
|
||||||
not_current_gl_context: Option<glutin::context::NotCurrentContext>,
|
not_current_gl_context: Option<glutin::context::NotCurrentContext>,
|
||||||
|
|
||||||
windows: HashMap<u64, Arc<RwLock<Window>>>,
|
windows: HashMap<ViewportId, Arc<RwLock<Window>>>,
|
||||||
window_maps: HashMap<winit::window::WindowId, u64>,
|
window_maps: HashMap<winit::window::WindowId, ViewportId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
unsafe impl Sync for GlutinWindowContext {}
|
unsafe impl Sync for GlutinWindowContext {}
|
||||||
|
#[allow(unsafe_code)]
|
||||||
unsafe impl Send for GlutinWindowContext {}
|
unsafe impl Send for GlutinWindowContext {}
|
||||||
|
|
||||||
impl GlutinWindowContext {
|
impl GlutinWindowContext {
|
||||||
@@ -599,20 +601,20 @@ mod glow_integration {
|
|||||||
|
|
||||||
let mut window_maps = HashMap::default();
|
let mut window_maps = HashMap::default();
|
||||||
if let Some(window) = &window {
|
if let Some(window) = &window {
|
||||||
window_maps.insert(window.id(), 0);
|
window_maps.insert(window.id(), ViewportId::MAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut windows = HashMap::default();
|
let mut windows = HashMap::default();
|
||||||
windows.insert(
|
windows.insert(
|
||||||
0,
|
ViewportId::MAIN,
|
||||||
Arc::new(RwLock::new(Window {
|
Arc::new(RwLock::new(Window {
|
||||||
builder: window_builder,
|
builder: window_builder,
|
||||||
gl_surface: None,
|
gl_surface: None,
|
||||||
window: window.map(|w| Arc::new(RwLock::new(w))),
|
window: window.map(|w| Arc::new(RwLock::new(w))),
|
||||||
window_id: 0,
|
window_id: ViewportId::MAIN,
|
||||||
egui_winit: None,
|
egui_winit: None,
|
||||||
render: None,
|
render: None,
|
||||||
parent_id: 0,
|
parent_id: ViewportId::MAIN,
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -739,18 +741,22 @@ mod glow_integration {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn window(&self, window_id: u64) -> Arc<RwLock<Window>> {
|
fn window(&self, viewport_id: ViewportId) -> Arc<RwLock<Window>> {
|
||||||
self.windows
|
self.windows
|
||||||
.get(&window_id)
|
.get(&viewport_id)
|
||||||
.map(|w| w.clone())
|
.map(|w| w.clone())
|
||||||
.expect("winit window doesn't exist")
|
.expect("winit window doesn't exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resize(&mut self, window_id: u64, physical_size: winit::dpi::PhysicalSize<u32>) {
|
fn resize(
|
||||||
|
&mut self,
|
||||||
|
viewport_id: ViewportId,
|
||||||
|
physical_size: winit::dpi::PhysicalSize<u32>,
|
||||||
|
) {
|
||||||
let width = std::num::NonZeroU32::new(physical_size.width.at_least(1)).unwrap();
|
let width = std::num::NonZeroU32::new(physical_size.width.at_least(1)).unwrap();
|
||||||
let height = std::num::NonZeroU32::new(physical_size.height.at_least(1)).unwrap();
|
let height = std::num::NonZeroU32::new(physical_size.height.at_least(1)).unwrap();
|
||||||
|
|
||||||
if let Some(window) = self.windows.get(&window_id) {
|
if let Some(window) = self.windows.get(&viewport_id) {
|
||||||
let mut window = window.write();
|
let mut window = window.write();
|
||||||
if let Some(gl_surface) = &window.gl_surface {
|
if let Some(gl_surface) = &window.gl_surface {
|
||||||
self.current_gl_context = Some(
|
self.current_gl_context = Some(
|
||||||
@@ -788,7 +794,7 @@ mod glow_integration {
|
|||||||
// re-initializing the `GlowWinitRunning` state on Android if the application
|
// re-initializing the `GlowWinitRunning` state on Android if the application
|
||||||
// suspends and resumes.
|
// suspends and resumes.
|
||||||
app_creator: Option<epi::AppCreator>,
|
app_creator: Option<epi::AppCreator>,
|
||||||
is_focused: Arc<RwLock<Option<u64>>>,
|
is_focused: Arc<RwLock<Option<ViewportId>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GlowWinitApp {
|
impl GlowWinitApp {
|
||||||
@@ -804,7 +810,7 @@ mod glow_integration {
|
|||||||
native_options,
|
native_options,
|
||||||
running: Arc::new(RwLock::new(None)),
|
running: Arc::new(RwLock::new(None)),
|
||||||
app_creator: Some(app_creator),
|
app_creator: Some(app_creator),
|
||||||
is_focused: Arc::new(RwLock::new(Some(0))),
|
is_focused: Arc::new(RwLock::new(Some(ViewportId::MAIN))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -826,7 +832,7 @@ mod glow_integration {
|
|||||||
};
|
};
|
||||||
glutin_window_context.on_resume(event_loop)?;
|
glutin_window_context.on_resume(event_loop)?;
|
||||||
|
|
||||||
if let Some(window) = &glutin_window_context.windows.get(&0) {
|
if let Some(window) = &glutin_window_context.windows.get(&ViewportId::MAIN) {
|
||||||
let window = window.read();
|
let window = window.read();
|
||||||
if let Some(window) = &window.window {
|
if let Some(window) = &window.window {
|
||||||
epi_integration::apply_native_options_to_window(&window.read(), native_options);
|
epi_integration::apply_native_options_to_window(&window.read(), native_options);
|
||||||
@@ -866,13 +872,25 @@ mod glow_integration {
|
|||||||
.unwrap_or_else(|error| panic!("some OpenGL error occurred {}\n", error));
|
.unwrap_or_else(|error| panic!("some OpenGL error occurred {}\n", error));
|
||||||
|
|
||||||
let system_theme = system_theme(
|
let system_theme = system_theme(
|
||||||
&gl_window.window(0).read().window.as_ref().unwrap().read(),
|
&gl_window
|
||||||
|
.window(ViewportId::MAIN)
|
||||||
|
.read()
|
||||||
|
.window
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.read(),
|
||||||
&self.native_options,
|
&self.native_options,
|
||||||
);
|
);
|
||||||
let mut integration = epi_integration::EpiIntegration::new(
|
let mut integration = epi_integration::EpiIntegration::new(
|
||||||
event_loop,
|
event_loop,
|
||||||
painter.max_texture_side(),
|
painter.max_texture_side(),
|
||||||
&gl_window.window(0).read().window.as_ref().unwrap().read(),
|
&gl_window
|
||||||
|
.window(ViewportId::MAIN)
|
||||||
|
.read()
|
||||||
|
.window
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.read(),
|
||||||
system_theme,
|
system_theme,
|
||||||
&self.app_name,
|
&self.app_name,
|
||||||
&self.native_options,
|
&self.native_options,
|
||||||
@@ -883,7 +901,7 @@ mod glow_integration {
|
|||||||
);
|
);
|
||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
{
|
{
|
||||||
let window = gl_window.windows.get(&0).unwrap();
|
let window = gl_window.windows.get(&ViewportId::MAIN).unwrap();
|
||||||
let window = &mut *window.write();
|
let window = &mut *window.write();
|
||||||
integration.init_accesskit(
|
integration.init_accesskit(
|
||||||
window.egui_winit.as_mut().unwrap(),
|
window.egui_winit.as_mut().unwrap(),
|
||||||
@@ -901,7 +919,7 @@ mod glow_integration {
|
|||||||
integration.egui_ctx.set_desktop(true);
|
integration.egui_ctx.set_desktop(true);
|
||||||
|
|
||||||
gl_window
|
gl_window
|
||||||
.window(0)
|
.window(ViewportId::MAIN)
|
||||||
.read()
|
.read()
|
||||||
.window
|
.window
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -910,7 +928,7 @@ mod glow_integration {
|
|||||||
.set_ime_allowed(true);
|
.set_ime_allowed(true);
|
||||||
if self.native_options.mouse_passthrough {
|
if self.native_options.mouse_passthrough {
|
||||||
gl_window
|
gl_window
|
||||||
.window(0)
|
.window(ViewportId::MAIN)
|
||||||
.read()
|
.read()
|
||||||
.window
|
.window
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -931,7 +949,7 @@ mod glow_integration {
|
|||||||
event_loop_proxy
|
event_loop_proxy
|
||||||
.lock()
|
.lock()
|
||||||
.send_event(UserEvent::RequestRepaint {
|
.send_event(UserEvent::RequestRepaint {
|
||||||
window_id: info.window_id,
|
id: info.viewport_id,
|
||||||
when,
|
when,
|
||||||
frame_nr,
|
frame_nr,
|
||||||
})
|
})
|
||||||
@@ -943,7 +961,7 @@ mod glow_integration {
|
|||||||
.expect("Single-use AppCreator has unexpectedly already been taken");
|
.expect("Single-use AppCreator has unexpectedly already been taken");
|
||||||
let mut app;
|
let mut app;
|
||||||
{
|
{
|
||||||
let window = gl_window.window(0);
|
let window = gl_window.window(ViewportId::MAIN);
|
||||||
let window = &mut *window.write();
|
let window = &mut *window.write();
|
||||||
app = app_creator(&epi::CreationContext {
|
app = app_creator(&epi::CreationContext {
|
||||||
egui_ctx: integration.egui_ctx.clone(),
|
egui_ctx: integration.egui_ctx.clone(),
|
||||||
@@ -995,7 +1013,7 @@ mod glow_integration {
|
|||||||
viewport_id,
|
viewport_id,
|
||||||
parent_viewport_id,
|
parent_viewport_id,
|
||||||
|ctx| {
|
|ctx| {
|
||||||
render(ctx, viewport_id, parent_viewport_id);
|
render(ctx);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let glutin = &mut *glutin.write();
|
let glutin = &mut *glutin.write();
|
||||||
@@ -1065,7 +1083,7 @@ mod glow_integration {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
render(&egui_ctx, 0, 0);
|
render(&egui_ctx);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1083,14 +1101,13 @@ 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<(
|
||||||
u64,
|
ViewportId,
|
||||||
u64,
|
ViewportId,
|
||||||
ViewportBuilder,
|
ViewportBuilder,
|
||||||
Option<Arc<Box<dyn Fn(&egui::Context, u64, u64) + Sync + Send>>>,
|
Option<Arc<Box<ViewportRender>>>,
|
||||||
)>,
|
)>,
|
||||||
) {
|
) {
|
||||||
// 0 is the main viewport/window that will not be known by the egui_ctx
|
let mut active_viewports_ids = vec![ViewportId::MAIN];
|
||||||
let mut active_viewports_ids = vec![0];
|
|
||||||
|
|
||||||
viewports.retain_mut(|(id, _, builder, render)| {
|
viewports.retain_mut(|(id, _, builder, render)| {
|
||||||
if let Some(w) = glutin_ctx.read().windows.get(id) {
|
if let Some(w) = glutin_ctx.read().windows.get(id) {
|
||||||
@@ -1180,7 +1197,7 @@ mod glow_integration {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_window_winit_id(&self, id: u64) -> Option<winit::window::WindowId> {
|
fn get_window_winit_id(&self, id: ViewportId) -> Option<winit::window::WindowId> {
|
||||||
self.running.read().as_ref().and_then(|r| {
|
self.running.read().as_ref().and_then(|r| {
|
||||||
if let Some(window) = r.glutin_ctx.read().windows.get(&id) {
|
if let Some(window) = r.glutin_ctx.read().windows.get(&id) {
|
||||||
return window.read().window.as_ref().map(|w| w.read().id());
|
return window.read().window.as_ref().map(|w| w.read().id());
|
||||||
@@ -1189,7 +1206,7 @@ mod glow_integration {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_window_id(&self, id: &winit::window::WindowId) -> Option<u64> {
|
fn get_window_id(&self, id: &winit::window::WindowId) -> Option<ViewportId> {
|
||||||
self.running
|
self.running
|
||||||
.read()
|
.read()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -1203,7 +1220,7 @@ mod glow_integration {
|
|||||||
&running
|
&running
|
||||||
.glutin_ctx
|
.glutin_ctx
|
||||||
.read()
|
.read()
|
||||||
.window(0)
|
.window(ViewportId::MAIN)
|
||||||
.read()
|
.read()
|
||||||
.window
|
.window
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -1236,7 +1253,7 @@ mod glow_integration {
|
|||||||
// That means that the viewport cannot be rendered by itself and needs his parent to be rendered
|
// That means that the viewport cannot be rendered by itself and needs his parent to be rendered
|
||||||
{
|
{
|
||||||
let win = glutin_ctx.read().windows.get(&viewport_id).unwrap().clone();
|
let win = glutin_ctx.read().windows.get(&viewport_id).unwrap().clone();
|
||||||
if win.read().render.is_none() && viewport_id != 0 {
|
if win.read().render.is_none() && viewport_id != ViewportId::MAIN {
|
||||||
if let Some(win) = glutin_ctx.read().windows.get(&win.read().parent_id) {
|
if let Some(win) = glutin_ctx.read().windows.get(&win.read().parent_id) {
|
||||||
win.read()
|
win.read()
|
||||||
.window
|
.window
|
||||||
@@ -1485,7 +1502,7 @@ mod glow_integration {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.glutin_ctx
|
.glutin_ctx
|
||||||
.read()
|
.read()
|
||||||
.window(0)
|
.window(ViewportId::MAIN)
|
||||||
.read()
|
.read()
|
||||||
.window
|
.window
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -1584,7 +1601,13 @@ mod glow_integration {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.flat_map(|id| if id == 0 { Some(()) } else { None })
|
.flat_map(|id| {
|
||||||
|
if id == ViewportId::MAIN {
|
||||||
|
Some(())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
.count()
|
.count()
|
||||||
== 1
|
== 1
|
||||||
&& running.integration.read().should_close() =>
|
&& running.integration.read().should_close() =>
|
||||||
@@ -1692,7 +1715,6 @@ mod wgpu_integration {
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use egui::ViewportRender;
|
use egui::ViewportRender;
|
||||||
use winit::window::ResizeDirection;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@@ -1701,12 +1723,12 @@ mod wgpu_integration {
|
|||||||
Arc<
|
Arc<
|
||||||
RwLock<
|
RwLock<
|
||||||
HashMap<
|
HashMap<
|
||||||
u64,
|
ViewportId,
|
||||||
(
|
(
|
||||||
Option<Arc<RwLock<winit::window::Window>>>,
|
Option<Arc<RwLock<winit::window::Window>>>,
|
||||||
Arc<RwLock<Option<egui_winit::State>>>,
|
Arc<RwLock<Option<egui_winit::State>>>,
|
||||||
Option<Arc<Box<ViewportRender>>>,
|
Option<Arc<Box<ViewportRender>>>,
|
||||||
u64,
|
ViewportId,
|
||||||
ViewportBuilder,
|
ViewportBuilder,
|
||||||
),
|
),
|
||||||
>,
|
>,
|
||||||
@@ -1714,19 +1736,21 @@ mod wgpu_integration {
|
|||||||
>,
|
>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
unsafe impl Send for Windows {}
|
unsafe impl Send for Windows {}
|
||||||
|
#[allow(unsafe_code)]
|
||||||
unsafe impl Sync for Windows {}
|
unsafe impl Sync for Windows {}
|
||||||
|
|
||||||
impl std::ops::Deref for Windows {
|
impl std::ops::Deref for Windows {
|
||||||
type Target = Arc<
|
type Target = Arc<
|
||||||
RwLock<
|
RwLock<
|
||||||
HashMap<
|
HashMap<
|
||||||
u64,
|
ViewportId,
|
||||||
(
|
(
|
||||||
Option<Arc<RwLock<winit::window::Window>>>,
|
Option<Arc<RwLock<winit::window::Window>>>,
|
||||||
Arc<RwLock<Option<egui_winit::State>>>,
|
Arc<RwLock<Option<egui_winit::State>>>,
|
||||||
Option<Arc<Box<ViewportRender>>>,
|
Option<Arc<Box<ViewportRender>>>,
|
||||||
u64,
|
ViewportId,
|
||||||
ViewportBuilder,
|
ViewportBuilder,
|
||||||
),
|
),
|
||||||
>,
|
>,
|
||||||
@@ -1746,7 +1770,7 @@ mod wgpu_integration {
|
|||||||
integration: Arc<RwLock<epi_integration::EpiIntegration>>,
|
integration: Arc<RwLock<epi_integration::EpiIntegration>>,
|
||||||
app: Box<dyn epi::App>,
|
app: Box<dyn epi::App>,
|
||||||
windows: Windows,
|
windows: Windows,
|
||||||
windows_id: HashMap<winit::window::WindowId, u64>,
|
windows_id: HashMap<winit::window::WindowId, ViewportId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WgpuWinitApp {
|
struct WgpuWinitApp {
|
||||||
@@ -1758,7 +1782,7 @@ mod wgpu_integration {
|
|||||||
|
|
||||||
/// Window surface state that's initialized when the app starts running via a Resumed event
|
/// Window surface state that's initialized when the app starts running via a Resumed event
|
||||||
/// and on Android will also be destroyed if the application is paused.
|
/// and on Android will also be destroyed if the application is paused.
|
||||||
is_focused: Arc<RwLock<Option<u64>>>,
|
is_focused: Arc<RwLock<Option<ViewportId>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WgpuWinitApp {
|
impl WgpuWinitApp {
|
||||||
@@ -1780,7 +1804,7 @@ mod wgpu_integration {
|
|||||||
native_options,
|
native_options,
|
||||||
running: None,
|
running: None,
|
||||||
app_creator: Some(app_creator),
|
app_creator: Some(app_creator),
|
||||||
is_focused: Arc::new(RwLock::new(Some(0))),
|
is_focused: Arc::new(RwLock::new(Some(ViewportId::MAIN))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1818,7 +1842,7 @@ mod wgpu_integration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_window(&mut self, id: u64) -> std::result::Result<(), egui_wgpu::WgpuError> {
|
fn set_window(&mut self, id: ViewportId) -> std::result::Result<(), egui_wgpu::WgpuError> {
|
||||||
if let Some(running) = &mut self.running {
|
if let Some(running) = &mut self.running {
|
||||||
if let Some((window, _, _, _, _)) = running.windows.read().get(&id) {
|
if let Some((window, _, _, _, _)) = running.windows.read().get(&id) {
|
||||||
window.as_ref().map(|w| {
|
window.as_ref().map(|w| {
|
||||||
@@ -1856,7 +1880,7 @@ mod wgpu_integration {
|
|||||||
),
|
),
|
||||||
self.native_options.transparent,
|
self.native_options.transparent,
|
||||||
);
|
);
|
||||||
pollster::block_on(painter.set_window(0, Some(&window)))?;
|
pollster::block_on(painter.set_window(ViewportId::MAIN, Some(&window)))?;
|
||||||
|
|
||||||
let wgpu_render_state = painter.render_state();
|
let wgpu_render_state = painter.render_state();
|
||||||
|
|
||||||
@@ -1904,7 +1928,7 @@ mod wgpu_integration {
|
|||||||
.send_event(UserEvent::RequestRepaint {
|
.send_event(UserEvent::RequestRepaint {
|
||||||
when,
|
when,
|
||||||
frame_nr,
|
frame_nr,
|
||||||
window_id: info.window_id,
|
id: info.viewport_id,
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
});
|
});
|
||||||
@@ -1928,16 +1952,16 @@ mod wgpu_integration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut windows_id = HashMap::default();
|
let mut windows_id = HashMap::default();
|
||||||
windows_id.insert(window.id(), 0);
|
windows_id.insert(window.id(), ViewportId::MAIN);
|
||||||
|
|
||||||
let windows = Windows(Arc::new(RwLock::new(HashMap::default())));
|
let windows = Windows(Arc::new(RwLock::new(HashMap::default())));
|
||||||
windows.write().insert(
|
windows.write().insert(
|
||||||
0,
|
ViewportId::MAIN,
|
||||||
(
|
(
|
||||||
Some(Arc::new(RwLock::new(window))),
|
Some(Arc::new(RwLock::new(window))),
|
||||||
Arc::new(RwLock::new(Some(state))),
|
Arc::new(RwLock::new(Some(state))),
|
||||||
None,
|
None,
|
||||||
0,
|
ViewportId::MAIN,
|
||||||
builder,
|
builder,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -1966,7 +1990,7 @@ mod wgpu_integration {
|
|||||||
viewport_id,
|
viewport_id,
|
||||||
parent_viewport_id,
|
parent_viewport_id,
|
||||||
|ctx| {
|
|ctx| {
|
||||||
render(ctx, viewport_id, parent_viewport_id);
|
render(ctx);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1998,7 +2022,7 @@ mod wgpu_integration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut viewports = output.viewports;
|
let mut viewports = output.viewports;
|
||||||
let mut active_viewports_ids = vec![0];
|
let mut active_viewports_ids = vec![ViewportId::MAIN];
|
||||||
|
|
||||||
viewports.retain_mut(|(id, parent, builder, render)| {
|
viewports.retain_mut(|(id, parent, builder, render)| {
|
||||||
if let Some(w) = _windows.write().get_mut(id) {
|
if let Some(w) = _windows.write().get_mut(id) {
|
||||||
@@ -2027,7 +2051,7 @@ mod wgpu_integration {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
render(&egui_ctx, 0, 0);
|
render(&egui_ctx);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -2078,7 +2102,7 @@ mod wgpu_integration {
|
|||||||
.flatten()
|
.flatten()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_window_winit_id(&self, id: u64) -> Option<winit::window::WindowId> {
|
fn get_window_winit_id(&self, id: ViewportId) -> Option<winit::window::WindowId> {
|
||||||
self.running.as_ref().and_then(|r| {
|
self.running.as_ref().and_then(|r| {
|
||||||
r.windows
|
r.windows
|
||||||
.read()
|
.read()
|
||||||
@@ -2089,7 +2113,9 @@ mod wgpu_integration {
|
|||||||
|
|
||||||
fn save_and_destroy(&mut self) {
|
fn save_and_destroy(&mut self) {
|
||||||
if let Some(mut running) = self.running.take() {
|
if let Some(mut running) = self.running.take() {
|
||||||
if let Some((Some(window), _, _, _, _)) = running.windows.read().get(&0) {
|
if let Some((Some(window), _, _, _, _)) =
|
||||||
|
running.windows.read().get(&ViewportId::MAIN)
|
||||||
|
{
|
||||||
running
|
running
|
||||||
.integration
|
.integration
|
||||||
.write()
|
.write()
|
||||||
@@ -2130,7 +2156,8 @@ mod wgpu_integration {
|
|||||||
};
|
};
|
||||||
{
|
{
|
||||||
let Some((viewport_id, (Some(window), state, render, parent_viewport_id, _))) = windows_id.get(&window_id).and_then(|id|(windows.read().get(id).map(|w|(*id, w.clone())))) else{return vec![]};
|
let Some((viewport_id, (Some(window), state, render, parent_viewport_id, _))) = windows_id.get(&window_id).and_then(|id|(windows.read().get(id).map(|w|(*id, w.clone())))) else{return vec![]};
|
||||||
if viewport_id != 0 && render.is_none() {
|
// This is used to not render a viewport if is sync
|
||||||
|
if viewport_id != ViewportId::MAIN && render.is_none() {
|
||||||
if let Some(window) = running.windows.read().get(&parent_viewport_id) {
|
if let Some(window) = running.windows.read().get(&parent_viewport_id) {
|
||||||
window.0.as_ref().map(|w| w.read().request_redraw());
|
window.0.as_ref().map(|w| w.read().request_redraw());
|
||||||
}
|
}
|
||||||
@@ -2188,7 +2215,7 @@ mod wgpu_integration {
|
|||||||
integration.post_present(&window.read());
|
integration.post_present(&window.read());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut active_viewports_ids = vec![0];
|
let mut active_viewports_ids = vec![ViewportId::MAIN];
|
||||||
|
|
||||||
viewports.retain_mut(|(id, parent, builder, render)| {
|
viewports.retain_mut(|(id, parent, builder, render)| {
|
||||||
if let Some(w) = windows.write().get_mut(id) {
|
if let Some(w) = windows.write().get_mut(id) {
|
||||||
@@ -2219,7 +2246,7 @@ mod wgpu_integration {
|
|||||||
.write()
|
.write()
|
||||||
.retain(|id, _| active_viewports_ids.contains(id));
|
.retain(|id, _| active_viewports_ids.contains(id));
|
||||||
windows_id.retain(|_, id| active_viewports_ids.contains(id));
|
windows_id.retain(|_, id| active_viewports_ids.contains(id));
|
||||||
painter.write().clean_surfaces(active_viewports_ids);
|
painter.write().clean_surfaces(&active_viewports_ids);
|
||||||
|
|
||||||
let mut control_flow = vec![EventResult::Wait];
|
let mut control_flow = vec![EventResult::Wait];
|
||||||
for repaint_after in repaint_after {
|
for repaint_after in repaint_after {
|
||||||
@@ -2280,14 +2307,14 @@ mod wgpu_integration {
|
|||||||
Ok(match event {
|
Ok(match event {
|
||||||
winit::event::Event::Resumed => {
|
winit::event::Event::Resumed => {
|
||||||
if let Some(running) = &self.running {
|
if let Some(running) = &self.running {
|
||||||
if running.windows.read().get(&0).is_none() {
|
if running.windows.read().get(&ViewportId::MAIN).is_none() {
|
||||||
let window = Self::create_window(
|
let window = Self::create_window(
|
||||||
event_loop,
|
event_loop,
|
||||||
running.integration.read().frame.storage(),
|
running.integration.read().frame.storage(),
|
||||||
&self.app_name,
|
&self.app_name,
|
||||||
&self.native_options,
|
&self.native_options,
|
||||||
)?;
|
)?;
|
||||||
self.set_window(0)?;
|
self.set_window(ViewportId::MAIN)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let storage = epi_integration::create_storage(
|
let storage = epi_integration::create_storage(
|
||||||
@@ -2310,7 +2337,7 @@ mod wgpu_integration {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.windows
|
.windows
|
||||||
.read()
|
.read()
|
||||||
.get(&0)
|
.get(&ViewportId::MAIN)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0
|
.0
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -2458,7 +2485,7 @@ mod wgpu_integration {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_window_id(&self, id: &winit::window::WindowId) -> Option<u64> {
|
fn get_window_id(&self, id: &winit::window::WindowId) -> Option<ViewportId> {
|
||||||
self.running
|
self.running
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|r| r.windows_id.get(id).cloned())
|
.and_then(|r| r.windows_id.get(id).cloned())
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ winit = ["dep:winit"]
|
|||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
egui = { version = "0.22.0", path = "../egui", default-features = false }
|
||||||
epaint = { version = "0.22.0", path = "../epaint", default-features = false, features = [
|
epaint = { version = "0.22.0", path = "../epaint", default-features = false, features = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
] }
|
] }
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use egui::ViewportId;
|
||||||
use epaint::ahash::HashMap;
|
use epaint::ahash::HashMap;
|
||||||
|
|
||||||
use crate::{renderer, RenderState, SurfaceErrorAction, WgpuConfiguration};
|
use crate::{renderer, RenderState, SurfaceErrorAction, WgpuConfiguration};
|
||||||
@@ -85,7 +86,7 @@ pub struct Painter {
|
|||||||
|
|
||||||
instance: wgpu::Instance,
|
instance: wgpu::Instance,
|
||||||
render_state: Option<RenderState>,
|
render_state: Option<RenderState>,
|
||||||
surfaces: HashMap<u64, SurfaceState>,
|
surfaces: HashMap<ViewportId, SurfaceState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for Painter {}
|
unsafe impl Send for Painter {}
|
||||||
@@ -190,7 +191,7 @@ impl Painter {
|
|||||||
/// If the provided wgpu configuration does not match an available device.
|
/// If the provided wgpu configuration does not match an available device.
|
||||||
pub async fn set_window(
|
pub async fn set_window(
|
||||||
&mut self,
|
&mut self,
|
||||||
viewport_id: u64,
|
viewport_id: ViewportId,
|
||||||
window: Option<&winit::window::Window>,
|
window: Option<&winit::window::Window>,
|
||||||
) -> Result<(), crate::WgpuError> {
|
) -> Result<(), crate::WgpuError> {
|
||||||
match window {
|
match window {
|
||||||
@@ -274,7 +275,7 @@ impl Painter {
|
|||||||
|
|
||||||
fn resize_and_generate_depth_texture_view_and_msaa_view(
|
fn resize_and_generate_depth_texture_view_and_msaa_view(
|
||||||
&mut self,
|
&mut self,
|
||||||
viewport_id: u64,
|
viewport_id: ViewportId,
|
||||||
width_in_pixels: u32,
|
width_in_pixels: u32,
|
||||||
height_in_pixels: u32,
|
height_in_pixels: u32,
|
||||||
) {
|
) {
|
||||||
@@ -334,7 +335,7 @@ impl Painter {
|
|||||||
|
|
||||||
pub fn on_window_resized(
|
pub fn on_window_resized(
|
||||||
&mut self,
|
&mut self,
|
||||||
viewport_id: u64,
|
viewport_id: ViewportId,
|
||||||
width_in_pixels: u32,
|
width_in_pixels: u32,
|
||||||
height_in_pixels: u32,
|
height_in_pixels: u32,
|
||||||
) {
|
) {
|
||||||
@@ -451,7 +452,7 @@ impl Painter {
|
|||||||
// Returns a vector with the frame's pixel data if it was requested.
|
// Returns a vector with the frame's pixel data if it was requested.
|
||||||
pub fn paint_and_update_textures(
|
pub fn paint_and_update_textures(
|
||||||
&mut self,
|
&mut self,
|
||||||
viewport_id: u64,
|
viewport_id: ViewportId,
|
||||||
pixels_per_point: f32,
|
pixels_per_point: f32,
|
||||||
clear_color: [f32; 4],
|
clear_color: [f32; 4],
|
||||||
clipped_primitives: &[epaint::ClippedPrimitive],
|
clipped_primitives: &[epaint::ClippedPrimitive],
|
||||||
@@ -618,9 +619,9 @@ impl Painter {
|
|||||||
screenshot
|
screenshot
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clean_surfaces(&mut self, avalibile_viewports: Vec<u64>) {
|
pub fn clean_surfaces(&mut self, avalibile_viewports: &[ViewportId]) {
|
||||||
self.surfaces
|
self.surfaces
|
||||||
.retain(|id, _| avalibile_viewports.contains(id))
|
.retain(|id, _| avalibile_viewports.contains(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::unused_self)]
|
#[allow(clippy::unused_self)]
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ pub use accesskit_winit;
|
|||||||
pub use egui;
|
pub use egui;
|
||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
use egui::accesskit;
|
use egui::accesskit;
|
||||||
use egui::{mutex::RwLock, ViewportCommand};
|
use egui::{mutex::RwLock, ViewportCommand, ViewportId};
|
||||||
pub use winit;
|
pub use winit;
|
||||||
|
|
||||||
pub mod clipboard;
|
pub mod clipboard;
|
||||||
@@ -905,9 +905,9 @@ fn translate_cursor(cursor_icon: egui::CursorIcon) -> Option<winit::window::Curs
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_viewport_commands(
|
pub fn process_viewport_commands(
|
||||||
commands: Vec<(u64, ViewportCommand)>,
|
commands: Vec<(ViewportId, ViewportCommand)>,
|
||||||
focused: Option<u64>,
|
focused: Option<ViewportId>,
|
||||||
get_window: impl Fn(u64) -> Option<Arc<RwLock<winit::window::Window>>>,
|
get_window: impl Fn(ViewportId) -> Option<Arc<RwLock<winit::window::Window>>>,
|
||||||
) {
|
) {
|
||||||
use winit::dpi::PhysicalSize;
|
use winit::dpi::PhysicalSize;
|
||||||
use winit::window::ResizeDirection;
|
use winit::window::ResizeDirection;
|
||||||
|
|||||||
@@ -374,249 +374,242 @@ impl<'open> Window<'open> {
|
|||||||
window_builder.max_inner_size = Some((max_size.x as u32, max_size.y as u32));
|
window_builder.max_inner_size = Some((max_size.x as u32, max_size.y as u32));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctx.create_viewport_sync(
|
return ctx.create_viewport_sync(window_builder, move |ctx| {
|
||||||
window_builder,
|
let mut op = is_open;
|
||||||
move |ctx, viewport_id, parent_viewport_id| {
|
let open = if show_close_button {
|
||||||
let mut op = is_open;
|
Some(&mut op)
|
||||||
let open = if show_close_button {
|
} else {
|
||||||
Some(&mut op)
|
None
|
||||||
} else {
|
};
|
||||||
None
|
let scroll = scroll.clone();
|
||||||
};
|
let title = title.clone();
|
||||||
let scroll = scroll.clone();
|
let frame = frame
|
||||||
let title = title.clone();
|
.unwrap_or_else(|| Frame::window(&ctx.style()))
|
||||||
let frame = frame
|
.outer_margin(0.0)
|
||||||
.unwrap_or_else(|| Frame::window(&ctx.style()))
|
.shadow(Shadow::NONE)
|
||||||
.outer_margin(0.0)
|
.stroke(Stroke::new(
|
||||||
.shadow(Shadow::NONE)
|
1.0,
|
||||||
.stroke(Stroke::new(
|
if ctx.input(|i| i.focused) {
|
||||||
1.0,
|
Color32::BLUE
|
||||||
if ctx.input(|i| i.focused) {
|
|
||||||
Color32::BLUE
|
|
||||||
} else {
|
|
||||||
Color32::BROWN
|
|
||||||
},
|
|
||||||
));
|
|
||||||
|
|
||||||
area.show_open_close_animation(ctx, &frame, is_open);
|
|
||||||
|
|
||||||
let area_id = area.id;
|
|
||||||
let area_layer_id = area.layer();
|
|
||||||
let resize_id = area_id.with("resize");
|
|
||||||
let mut collapsing = CollapsingState::load_with_default_open(
|
|
||||||
ctx,
|
|
||||||
area_id.with("collapsing"),
|
|
||||||
default_open,
|
|
||||||
);
|
|
||||||
|
|
||||||
let is_collapsed = with_title_bar && !collapsing.is_open();
|
|
||||||
let possible = PossibleInteractions::new(&area, &resize, is_collapsed);
|
|
||||||
|
|
||||||
let area = area.movable(false); // We move it manually, or the area will move the window when we want to resize it
|
|
||||||
let resize = resize.resizable(false); // We move it manually
|
|
||||||
let mut resize = resize.id(resize_id);
|
|
||||||
|
|
||||||
let mut area = area.begin(ctx);
|
|
||||||
let win_size = ctx.input(|i| i.screen_rect.size());
|
|
||||||
area.state_mut().set_left_top_pos(Pos2::ZERO);
|
|
||||||
area.state_mut().size = win_size;
|
|
||||||
let title_content_spacing = 2.0 * ctx.style().spacing.item_spacing.y;
|
|
||||||
|
|
||||||
let title_bar_height = if with_title_bar {
|
|
||||||
let style = ctx.style();
|
|
||||||
ctx.fonts(|f| title.font_height(f, &style)) + title_content_spacing
|
|
||||||
} else {
|
|
||||||
0.0
|
|
||||||
};
|
|
||||||
let margins = frame.outer_margin.sum()
|
|
||||||
+ frame.inner_margin.sum()
|
|
||||||
+ vec2(0.0, title_bar_height)
|
|
||||||
- vec2(0.0, 3.0); //magic number
|
|
||||||
|
|
||||||
if let Some(mut state) = resize::State::load(ctx, resize_id) {
|
|
||||||
state.requested_size = Some(win_size - margins);
|
|
||||||
state.store(ctx, resize_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// First interact (move etc) to avoid frame delay:
|
|
||||||
let last_frame_outer_rect = area.state().rect();
|
|
||||||
|
|
||||||
let interaction = if possible.movable || possible.resizable() {
|
|
||||||
window_interaction(
|
|
||||||
ctx,
|
|
||||||
possible,
|
|
||||||
area_layer_id,
|
|
||||||
area_id.with("frame_resize"),
|
|
||||||
last_frame_outer_rect,
|
|
||||||
)
|
|
||||||
.and_then(|window_interaction| {
|
|
||||||
// Calculate roughly how much larger the window size is compared to the inner rect
|
|
||||||
|
|
||||||
let pointer_pos = ctx.input(|i| i.pointer.interact_pos())?;
|
|
||||||
let mut rect = window_interaction.start_rect; // prevent drift
|
|
||||||
|
|
||||||
window_interaction.set_cursor(ctx);
|
|
||||||
if window_interaction.is_resize() {
|
|
||||||
ctx.viewport_command(
|
|
||||||
viewport_id,
|
|
||||||
ViewportCommand::Resize(
|
|
||||||
window_interaction.top,
|
|
||||||
window_interaction.bottom,
|
|
||||||
window_interaction.right,
|
|
||||||
window_interaction.left,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
if ctx.input(|i| i.pointer.primary_pressed()) {}
|
|
||||||
}
|
|
||||||
ctx.memory_mut(|mem| mem.areas.move_to_top(area_layer_id));
|
|
||||||
|
|
||||||
Some(window_interaction)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let hover_interaction =
|
|
||||||
resize_hover(ctx, possible, area_layer_id, last_frame_outer_rect);
|
|
||||||
|
|
||||||
let mut area_content_ui = area.content_ui(ctx);
|
|
||||||
|
|
||||||
let mut size = Vec2::new(1.0, 1.0);
|
|
||||||
|
|
||||||
let content_inner = {
|
|
||||||
// BEGIN FRAME --------------------------------
|
|
||||||
let frame_stroke = frame.stroke;
|
|
||||||
let mut frame = frame.begin(&mut area_content_ui);
|
|
||||||
|
|
||||||
let title_bar = if with_title_bar {
|
|
||||||
let mut tmp_embedded = is_embedded;
|
|
||||||
|
|
||||||
let title_bar = show_title_bar(
|
|
||||||
&mut frame.content_ui,
|
|
||||||
title,
|
|
||||||
show_close_button,
|
|
||||||
&mut collapsing,
|
|
||||||
collapsible,
|
|
||||||
area_id,
|
|
||||||
);
|
|
||||||
|
|
||||||
if tmp_embedded != is_embedded {
|
|
||||||
area_content_ui.data_mut(|data| {
|
|
||||||
data.insert_persisted(
|
|
||||||
area_id.with("_embedded"),
|
|
||||||
tmp_embedded,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
resize.min_size.x =
|
|
||||||
resize.min_size.x.at_least(title_bar.rect.width()); // Prevent making window smaller than title bar width
|
|
||||||
Some(title_bar)
|
|
||||||
} else {
|
} else {
|
||||||
None
|
Color32::BROWN
|
||||||
};
|
},
|
||||||
|
));
|
||||||
|
|
||||||
let (content_inner, content_response) = collapsing
|
area.show_open_close_animation(ctx, &frame, is_open);
|
||||||
.show_body_unindented(&mut frame.content_ui, |ui| {
|
|
||||||
resize.show(ui, |ui| {
|
|
||||||
if title_bar.is_some() {
|
|
||||||
ui.add_space(title_content_spacing);
|
|
||||||
}
|
|
||||||
|
|
||||||
if scroll.has_any_bar() {
|
let area_id = area.id;
|
||||||
scroll.show(ui, |ui| add_contents(ui)).inner
|
let area_layer_id = area.layer();
|
||||||
} else {
|
let resize_id = area_id.with("resize");
|
||||||
add_contents(ui)
|
let mut collapsing = CollapsingState::load_with_default_open(
|
||||||
}
|
ctx,
|
||||||
})
|
area_id.with("collapsing"),
|
||||||
})
|
default_open,
|
||||||
.map_or((None, None), |ir| (Some(ir.inner), Some(ir.response)));
|
);
|
||||||
if let Some(content_response) = &content_response {
|
|
||||||
size = content_response.rect.size()
|
let is_collapsed = with_title_bar && !collapsing.is_open();
|
||||||
|
let possible = PossibleInteractions::new(&area, &resize, is_collapsed);
|
||||||
|
|
||||||
|
let area = area.movable(false); // We move it manually, or the area will move the window when we want to resize it
|
||||||
|
let resize = resize.resizable(false); // We move it manually
|
||||||
|
let mut resize = resize.id(resize_id);
|
||||||
|
|
||||||
|
let mut area = area.begin(ctx);
|
||||||
|
let win_size = ctx.input(|i| i.screen_rect.size());
|
||||||
|
area.state_mut().set_left_top_pos(Pos2::ZERO);
|
||||||
|
area.state_mut().size = win_size;
|
||||||
|
let title_content_spacing = 2.0 * ctx.style().spacing.item_spacing.y;
|
||||||
|
|
||||||
|
let title_bar_height = if with_title_bar {
|
||||||
|
let style = ctx.style();
|
||||||
|
ctx.fonts(|f| title.font_height(f, &style)) + title_content_spacing
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
};
|
||||||
|
let margins = frame.outer_margin.sum()
|
||||||
|
+ frame.inner_margin.sum()
|
||||||
|
+ vec2(0.0, title_bar_height)
|
||||||
|
- vec2(0.0, 3.0); //magic number
|
||||||
|
|
||||||
|
if let Some(mut state) = resize::State::load(ctx, resize_id) {
|
||||||
|
state.requested_size = Some(win_size - margins);
|
||||||
|
state.store(ctx, resize_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// First interact (move etc) to avoid frame delay:
|
||||||
|
let last_frame_outer_rect = area.state().rect();
|
||||||
|
|
||||||
|
let interaction = if possible.movable || possible.resizable() {
|
||||||
|
window_interaction(
|
||||||
|
ctx,
|
||||||
|
possible,
|
||||||
|
area_layer_id,
|
||||||
|
area_id.with("frame_resize"),
|
||||||
|
last_frame_outer_rect,
|
||||||
|
)
|
||||||
|
.and_then(|window_interaction| {
|
||||||
|
// Calculate roughly how much larger the window size is compared to the inner rect
|
||||||
|
|
||||||
|
let pointer_pos = ctx.input(|i| i.pointer.interact_pos())?;
|
||||||
|
let mut rect = window_interaction.start_rect; // prevent drift
|
||||||
|
|
||||||
|
window_interaction.set_cursor(ctx);
|
||||||
|
if window_interaction.is_resize() {
|
||||||
|
ctx.viewport_command(
|
||||||
|
ctx.get_viewport_id(),
|
||||||
|
ViewportCommand::Resize(
|
||||||
|
window_interaction.top,
|
||||||
|
window_interaction.bottom,
|
||||||
|
window_interaction.right,
|
||||||
|
window_interaction.left,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if ctx.input(|i| i.pointer.primary_pressed()) {}
|
||||||
}
|
}
|
||||||
|
ctx.memory_mut(|mem| mem.areas.move_to_top(area_layer_id));
|
||||||
|
|
||||||
let outer_rect = frame.end(&mut area_content_ui).rect;
|
Some(window_interaction)
|
||||||
paint_resize_corner(
|
})
|
||||||
&mut area_content_ui,
|
} else {
|
||||||
&possible,
|
None
|
||||||
outer_rect,
|
};
|
||||||
frame_stroke,
|
|
||||||
|
let hover_interaction =
|
||||||
|
resize_hover(ctx, possible, area_layer_id, last_frame_outer_rect);
|
||||||
|
|
||||||
|
let mut area_content_ui = area.content_ui(ctx);
|
||||||
|
|
||||||
|
let mut size = Vec2::new(1.0, 1.0);
|
||||||
|
|
||||||
|
let content_inner = {
|
||||||
|
// BEGIN FRAME --------------------------------
|
||||||
|
let frame_stroke = frame.stroke;
|
||||||
|
let mut frame = frame.begin(&mut area_content_ui);
|
||||||
|
|
||||||
|
let title_bar = if with_title_bar {
|
||||||
|
let mut tmp_embedded = is_embedded;
|
||||||
|
|
||||||
|
let title_bar = show_title_bar(
|
||||||
|
&mut frame.content_ui,
|
||||||
|
title,
|
||||||
|
show_close_button,
|
||||||
|
&mut collapsing,
|
||||||
|
collapsible,
|
||||||
|
area_id,
|
||||||
);
|
);
|
||||||
|
|
||||||
// END FRAME --------------------------------
|
if tmp_embedded != is_embedded {
|
||||||
|
area_content_ui.data_mut(|data| {
|
||||||
if let Some(title_bar) = title_bar {
|
data.insert_persisted(area_id.with("_embedded"), tmp_embedded)
|
||||||
let res = title_bar.ui(
|
});
|
||||||
&mut area_content_ui,
|
|
||||||
outer_rect,
|
|
||||||
&content_response,
|
|
||||||
open,
|
|
||||||
&mut collapsing,
|
|
||||||
collapsible,
|
|
||||||
);
|
|
||||||
if res.is_pointer_button_down_on() {
|
|
||||||
ctx.viewport_command(viewport_id, ViewportCommand::Drag);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
resize.min_size.x = resize.min_size.x.at_least(title_bar.rect.width()); // Prevent making window smaller than title bar width
|
||||||
|
Some(title_bar)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
collapsing.store(ctx);
|
let (content_inner, content_response) = collapsing
|
||||||
|
.show_body_unindented(&mut frame.content_ui, |ui| {
|
||||||
|
resize.show(ui, |ui| {
|
||||||
|
if title_bar.is_some() {
|
||||||
|
ui.add_space(title_content_spacing);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(interaction) = interaction {
|
if scroll.has_any_bar() {
|
||||||
|
scroll.show(ui, |ui| add_contents(ui)).inner
|
||||||
|
} else {
|
||||||
|
add_contents(ui)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.map_or((None, None), |ir| (Some(ir.inner), Some(ir.response)));
|
||||||
|
if let Some(content_response) = &content_response {
|
||||||
|
size = content_response.rect.size()
|
||||||
|
}
|
||||||
|
|
||||||
|
let outer_rect = frame.end(&mut area_content_ui).rect;
|
||||||
|
paint_resize_corner(
|
||||||
|
&mut area_content_ui,
|
||||||
|
&possible,
|
||||||
|
outer_rect,
|
||||||
|
frame_stroke,
|
||||||
|
);
|
||||||
|
|
||||||
|
// END FRAME --------------------------------
|
||||||
|
|
||||||
|
if let Some(title_bar) = title_bar {
|
||||||
|
let res = title_bar.ui(
|
||||||
|
&mut area_content_ui,
|
||||||
|
outer_rect,
|
||||||
|
&content_response,
|
||||||
|
open,
|
||||||
|
&mut collapsing,
|
||||||
|
collapsible,
|
||||||
|
);
|
||||||
|
if res.is_pointer_button_down_on() {
|
||||||
|
ctx.viewport_command(ctx.get_viewport_id(), ViewportCommand::Drag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
collapsing.store(ctx);
|
||||||
|
|
||||||
|
if let Some(interaction) = interaction {
|
||||||
|
paint_frame_interaction(
|
||||||
|
&mut area_content_ui,
|
||||||
|
outer_rect,
|
||||||
|
interaction,
|
||||||
|
ctx.style().visuals.widgets.active,
|
||||||
|
);
|
||||||
|
} else if let Some(hover_interaction) = hover_interaction {
|
||||||
|
if ctx.input(|i| i.pointer.has_pointer()) {
|
||||||
paint_frame_interaction(
|
paint_frame_interaction(
|
||||||
&mut area_content_ui,
|
&mut area_content_ui,
|
||||||
outer_rect,
|
outer_rect,
|
||||||
interaction,
|
hover_interaction,
|
||||||
ctx.style().visuals.widgets.active,
|
ctx.style().visuals.widgets.hovered,
|
||||||
);
|
);
|
||||||
} else if let Some(hover_interaction) = hover_interaction {
|
|
||||||
if ctx.input(|i| i.pointer.has_pointer()) {
|
|
||||||
paint_frame_interaction(
|
|
||||||
&mut area_content_ui,
|
|
||||||
outer_rect,
|
|
||||||
hover_interaction,
|
|
||||||
ctx.style().visuals.widgets.hovered,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
content_inner
|
|
||||||
};
|
|
||||||
|
|
||||||
let full_response = area.end(ctx, area_content_ui);
|
|
||||||
|
|
||||||
if !collapsing.is_open() {
|
|
||||||
let size = ctx.round_vec_to_pixels(full_response.rect.size());
|
|
||||||
ctx.viewport_command(
|
|
||||||
viewport_id,
|
|
||||||
ViewportCommand::InnerSize(size.x as u32, size.y as u32),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
content_inner
|
||||||
|
};
|
||||||
|
|
||||||
// let size = ctx.round_vec_to_pixels(full_response.rect.size());
|
let full_response = area.end(ctx, area_content_ui);
|
||||||
if win_size.x < size.x {
|
|
||||||
println!("Set size!");
|
|
||||||
ctx.viewport_command(
|
|
||||||
viewport_id,
|
|
||||||
ViewportCommand::InnerSize(size.x as u32, win_size.y as u32),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if win_size.y < size.y {
|
|
||||||
println!("Set size!");
|
|
||||||
ctx.viewport_command(
|
|
||||||
viewport_id,
|
|
||||||
ViewportCommand::InnerSize(win_size.x as u32, size.y as u32),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if show_close_button && op != is_open {
|
|
||||||
ctx.data_mut(|data| data.insert_persisted(area_id.with("_open"), op));
|
|
||||||
ctx.request_repaint_viewport(parent_viewport_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Some(InnerResponse {
|
if !collapsing.is_open() {
|
||||||
inner: content_inner,
|
let size = ctx.round_vec_to_pixels(full_response.rect.size());
|
||||||
response: full_response,
|
ctx.viewport_command(
|
||||||
});
|
ctx.get_viewport_id(),
|
||||||
},
|
ViewportCommand::InnerSize(size.x as u32, size.y as u32),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// let size = ctx.round_vec_to_pixels(full_response.rect.size());
|
||||||
|
if win_size.x < size.x {
|
||||||
|
println!("Set size!");
|
||||||
|
ctx.viewport_command(
|
||||||
|
ctx.get_viewport_id(),
|
||||||
|
ViewportCommand::InnerSize(size.x as u32, win_size.y as u32),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if win_size.y < size.y {
|
||||||
|
println!("Set size!");
|
||||||
|
ctx.viewport_command(
|
||||||
|
ctx.get_viewport_id(),
|
||||||
|
ViewportCommand::InnerSize(win_size.x as u32, size.y as u32),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if show_close_button && op != is_open {
|
||||||
|
ctx.data_mut(|data| data.insert_persisted(area_id.with("_open"), op));
|
||||||
|
ctx.request_repaint_viewport(ctx.get_parent_viewport_id());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(InnerResponse {
|
||||||
|
inner: content_inner,
|
||||||
|
response: full_response,
|
||||||
|
});
|
||||||
|
});
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -849,234 +842,230 @@ impl<'open> Window<'open> {
|
|||||||
window_builder.max_inner_size = Some((max_size.x as u32, max_size.y as u32));
|
window_builder.max_inner_size = Some((max_size.x as u32, max_size.y as u32));
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.create_viewport(
|
ctx.create_viewport(window_builder, move |ctx| {
|
||||||
window_builder,
|
let mut op = is_open;
|
||||||
move |ctx, viewport_id, parent_viewport_id| {
|
let open = if show_close_button {
|
||||||
let mut op = is_open;
|
Some(&mut op)
|
||||||
let open = if show_close_button {
|
} else {
|
||||||
Some(&mut op)
|
None
|
||||||
} else {
|
};
|
||||||
None
|
let scroll = scroll.clone();
|
||||||
};
|
let title = title.clone();
|
||||||
let scroll = scroll.clone();
|
let frame = frame
|
||||||
let title = title.clone();
|
.unwrap_or_else(|| Frame::window(&ctx.style()))
|
||||||
let frame = frame
|
.outer_margin(0.0)
|
||||||
.unwrap_or_else(|| Frame::window(&ctx.style()))
|
.shadow(Shadow::NONE)
|
||||||
.outer_margin(0.0)
|
.stroke(Stroke::new(
|
||||||
.shadow(Shadow::NONE)
|
1.0,
|
||||||
.stroke(Stroke::new(
|
if ctx.input(|i| i.focused) {
|
||||||
1.0,
|
Color32::BLUE
|
||||||
if ctx.input(|i| i.focused) {
|
|
||||||
Color32::BLUE
|
|
||||||
} else {
|
|
||||||
Color32::BROWN
|
|
||||||
},
|
|
||||||
));
|
|
||||||
|
|
||||||
area.show_open_close_animation(ctx, &frame, is_open);
|
|
||||||
|
|
||||||
let area_id = area.id;
|
|
||||||
let area_layer_id = area.layer();
|
|
||||||
let resize_id = area_id.with("resize");
|
|
||||||
let mut collapsing = CollapsingState::load_with_default_open(
|
|
||||||
ctx,
|
|
||||||
area_id.with("collapsing"),
|
|
||||||
default_open,
|
|
||||||
);
|
|
||||||
|
|
||||||
let is_collapsed = with_title_bar && !collapsing.is_open();
|
|
||||||
let possible = PossibleInteractions::new(&area, &resize, is_collapsed);
|
|
||||||
|
|
||||||
let area = area.movable(false); // We move it manually, or the area will move the window when we want to resize it
|
|
||||||
let resize = resize.resizable(false); // We move it manually
|
|
||||||
let mut resize = resize.id(resize_id);
|
|
||||||
|
|
||||||
let mut area = area.begin(ctx);
|
|
||||||
let win_size = ctx.input(|i| i.screen_rect.size());
|
|
||||||
area.state_mut().set_left_top_pos(Pos2::ZERO);
|
|
||||||
area.state_mut().size = win_size;
|
|
||||||
let title_content_spacing = 2.0 * ctx.style().spacing.item_spacing.y;
|
|
||||||
|
|
||||||
let title_bar_height = if with_title_bar {
|
|
||||||
let style = ctx.style();
|
|
||||||
ctx.fonts(|f| title.font_height(f, &style)) + title_content_spacing
|
|
||||||
} else {
|
|
||||||
0.0
|
|
||||||
};
|
|
||||||
let margins = frame.outer_margin.sum()
|
|
||||||
+ frame.inner_margin.sum()
|
|
||||||
+ vec2(0.0, title_bar_height)
|
|
||||||
- vec2(0.0, 3.0); //magic number
|
|
||||||
|
|
||||||
if let Some(mut state) = resize::State::load(ctx, resize_id) {
|
|
||||||
state.requested_size = Some(win_size - margins);
|
|
||||||
state.store(ctx, resize_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// First interact (move etc) to avoid frame delay:
|
|
||||||
let last_frame_outer_rect = area.state().rect();
|
|
||||||
|
|
||||||
let interaction = if possible.movable || possible.resizable() {
|
|
||||||
window_interaction(
|
|
||||||
ctx,
|
|
||||||
possible,
|
|
||||||
area_layer_id,
|
|
||||||
area_id.with("frame_resize"),
|
|
||||||
last_frame_outer_rect,
|
|
||||||
)
|
|
||||||
.and_then(|window_interaction| {
|
|
||||||
// Calculate roughly how much larger the window size is compared to the inner rect
|
|
||||||
|
|
||||||
let pointer_pos = ctx.input(|i| i.pointer.interact_pos())?;
|
|
||||||
let mut rect = window_interaction.start_rect; // prevent drift
|
|
||||||
|
|
||||||
window_interaction.set_cursor(ctx);
|
|
||||||
if window_interaction.is_resize() {
|
|
||||||
ctx.viewport_command(
|
|
||||||
viewport_id,
|
|
||||||
ViewportCommand::Resize(
|
|
||||||
window_interaction.top,
|
|
||||||
window_interaction.bottom,
|
|
||||||
window_interaction.right,
|
|
||||||
window_interaction.left,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
if ctx.input(|i| i.pointer.primary_pressed()) {}
|
|
||||||
}
|
|
||||||
ctx.memory_mut(|mem| mem.areas.move_to_top(area_layer_id));
|
|
||||||
|
|
||||||
Some(window_interaction)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let hover_interaction =
|
|
||||||
resize_hover(ctx, possible, area_layer_id, last_frame_outer_rect);
|
|
||||||
|
|
||||||
let mut area_content_ui = area.content_ui(ctx);
|
|
||||||
|
|
||||||
let mut size = Vec2::new(1.0, 1.0);
|
|
||||||
|
|
||||||
let content_inner = {
|
|
||||||
// BEGIN FRAME --------------------------------
|
|
||||||
let frame_stroke = frame.stroke;
|
|
||||||
let mut frame = frame.begin(&mut area_content_ui);
|
|
||||||
|
|
||||||
let title_bar = if with_title_bar {
|
|
||||||
let title_bar = show_title_bar(
|
|
||||||
&mut frame.content_ui,
|
|
||||||
title,
|
|
||||||
show_close_button,
|
|
||||||
&mut collapsing,
|
|
||||||
collapsible,
|
|
||||||
area_id,
|
|
||||||
);
|
|
||||||
|
|
||||||
resize.min_size.x =
|
|
||||||
resize.min_size.x.at_least(title_bar.rect.width()); // Prevent making window smaller than title bar width
|
|
||||||
Some(title_bar)
|
|
||||||
} else {
|
} else {
|
||||||
None
|
Color32::BROWN
|
||||||
};
|
},
|
||||||
|
));
|
||||||
|
|
||||||
let (content_inner, content_response) = collapsing
|
area.show_open_close_animation(ctx, &frame, is_open);
|
||||||
.show_body_unindented(&mut frame.content_ui, |ui| {
|
|
||||||
resize.show(ui, |ui| {
|
|
||||||
if title_bar.is_some() {
|
|
||||||
ui.add_space(title_content_spacing);
|
|
||||||
}
|
|
||||||
|
|
||||||
if scroll.has_any_bar() {
|
let area_id = area.id;
|
||||||
scroll.show(ui, |ui| add_contents(ui)).inner
|
let area_layer_id = area.layer();
|
||||||
} else {
|
let resize_id = area_id.with("resize");
|
||||||
add_contents(ui)
|
let mut collapsing = CollapsingState::load_with_default_open(
|
||||||
}
|
ctx,
|
||||||
})
|
area_id.with("collapsing"),
|
||||||
})
|
default_open,
|
||||||
.map_or((None, None), |ir| (Some(ir.inner), Some(ir.response)));
|
);
|
||||||
if let Some(content_response) = &content_response {
|
|
||||||
size = content_response.rect.size()
|
let is_collapsed = with_title_bar && !collapsing.is_open();
|
||||||
|
let possible = PossibleInteractions::new(&area, &resize, is_collapsed);
|
||||||
|
|
||||||
|
let area = area.movable(false); // We move it manually, or the area will move the window when we want to resize it
|
||||||
|
let resize = resize.resizable(false); // We move it manually
|
||||||
|
let mut resize = resize.id(resize_id);
|
||||||
|
|
||||||
|
let mut area = area.begin(ctx);
|
||||||
|
let win_size = ctx.input(|i| i.screen_rect.size());
|
||||||
|
area.state_mut().set_left_top_pos(Pos2::ZERO);
|
||||||
|
area.state_mut().size = win_size;
|
||||||
|
let title_content_spacing = 2.0 * ctx.style().spacing.item_spacing.y;
|
||||||
|
|
||||||
|
let title_bar_height = if with_title_bar {
|
||||||
|
let style = ctx.style();
|
||||||
|
ctx.fonts(|f| title.font_height(f, &style)) + title_content_spacing
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
};
|
||||||
|
let margins = frame.outer_margin.sum()
|
||||||
|
+ frame.inner_margin.sum()
|
||||||
|
+ vec2(0.0, title_bar_height)
|
||||||
|
- vec2(0.0, 3.0); //magic number
|
||||||
|
|
||||||
|
if let Some(mut state) = resize::State::load(ctx, resize_id) {
|
||||||
|
state.requested_size = Some(win_size - margins);
|
||||||
|
state.store(ctx, resize_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// First interact (move etc) to avoid frame delay:
|
||||||
|
let last_frame_outer_rect = area.state().rect();
|
||||||
|
|
||||||
|
let interaction = if possible.movable || possible.resizable() {
|
||||||
|
window_interaction(
|
||||||
|
ctx,
|
||||||
|
possible,
|
||||||
|
area_layer_id,
|
||||||
|
area_id.with("frame_resize"),
|
||||||
|
last_frame_outer_rect,
|
||||||
|
)
|
||||||
|
.and_then(|window_interaction| {
|
||||||
|
// Calculate roughly how much larger the window size is compared to the inner rect
|
||||||
|
|
||||||
|
let pointer_pos = ctx.input(|i| i.pointer.interact_pos())?;
|
||||||
|
let mut rect = window_interaction.start_rect; // prevent drift
|
||||||
|
|
||||||
|
window_interaction.set_cursor(ctx);
|
||||||
|
if window_interaction.is_resize() {
|
||||||
|
ctx.viewport_command(
|
||||||
|
ctx.get_viewport_id(),
|
||||||
|
ViewportCommand::Resize(
|
||||||
|
window_interaction.top,
|
||||||
|
window_interaction.bottom,
|
||||||
|
window_interaction.right,
|
||||||
|
window_interaction.left,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if ctx.input(|i| i.pointer.primary_pressed()) {}
|
||||||
}
|
}
|
||||||
|
ctx.memory_mut(|mem| mem.areas.move_to_top(area_layer_id));
|
||||||
|
|
||||||
let outer_rect = frame.end(&mut area_content_ui).rect;
|
Some(window_interaction)
|
||||||
paint_resize_corner(
|
})
|
||||||
&mut area_content_ui,
|
} else {
|
||||||
&possible,
|
None
|
||||||
outer_rect,
|
};
|
||||||
frame_stroke,
|
|
||||||
|
let hover_interaction =
|
||||||
|
resize_hover(ctx, possible, area_layer_id, last_frame_outer_rect);
|
||||||
|
|
||||||
|
let mut area_content_ui = area.content_ui(ctx);
|
||||||
|
|
||||||
|
let mut size = Vec2::new(1.0, 1.0);
|
||||||
|
|
||||||
|
let content_inner = {
|
||||||
|
// BEGIN FRAME --------------------------------
|
||||||
|
let frame_stroke = frame.stroke;
|
||||||
|
let mut frame = frame.begin(&mut area_content_ui);
|
||||||
|
|
||||||
|
let title_bar = if with_title_bar {
|
||||||
|
let title_bar = show_title_bar(
|
||||||
|
&mut frame.content_ui,
|
||||||
|
title,
|
||||||
|
show_close_button,
|
||||||
|
&mut collapsing,
|
||||||
|
collapsible,
|
||||||
|
area_id,
|
||||||
);
|
);
|
||||||
|
|
||||||
// END FRAME --------------------------------
|
resize.min_size.x = resize.min_size.x.at_least(title_bar.rect.width()); // Prevent making window smaller than title bar width
|
||||||
|
Some(title_bar)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(title_bar) = title_bar {
|
let (content_inner, content_response) = collapsing
|
||||||
let res = title_bar.ui(
|
.show_body_unindented(&mut frame.content_ui, |ui| {
|
||||||
&mut area_content_ui,
|
resize.show(ui, |ui| {
|
||||||
outer_rect,
|
if title_bar.is_some() {
|
||||||
&content_response,
|
ui.add_space(title_content_spacing);
|
||||||
open,
|
}
|
||||||
&mut collapsing,
|
|
||||||
collapsible,
|
if scroll.has_any_bar() {
|
||||||
);
|
scroll.show(ui, |ui| add_contents(ui)).inner
|
||||||
if res.is_pointer_button_down_on() {
|
} else {
|
||||||
ctx.viewport_command(viewport_id, ViewportCommand::Drag);
|
add_contents(ui)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.map_or((None, None), |ir| (Some(ir.inner), Some(ir.response)));
|
||||||
|
if let Some(content_response) = &content_response {
|
||||||
|
size = content_response.rect.size()
|
||||||
|
}
|
||||||
|
|
||||||
|
let outer_rect = frame.end(&mut area_content_ui).rect;
|
||||||
|
paint_resize_corner(
|
||||||
|
&mut area_content_ui,
|
||||||
|
&possible,
|
||||||
|
outer_rect,
|
||||||
|
frame_stroke,
|
||||||
|
);
|
||||||
|
|
||||||
|
// END FRAME --------------------------------
|
||||||
|
|
||||||
|
if let Some(title_bar) = title_bar {
|
||||||
|
let res = title_bar.ui(
|
||||||
|
&mut area_content_ui,
|
||||||
|
outer_rect,
|
||||||
|
&content_response,
|
||||||
|
open,
|
||||||
|
&mut collapsing,
|
||||||
|
collapsible,
|
||||||
|
);
|
||||||
|
if res.is_pointer_button_down_on() {
|
||||||
|
ctx.viewport_command(ctx.get_viewport_id(), ViewportCommand::Drag);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
collapsing.store(ctx);
|
collapsing.store(ctx);
|
||||||
|
|
||||||
if let Some(interaction) = interaction {
|
if let Some(interaction) = interaction {
|
||||||
|
paint_frame_interaction(
|
||||||
|
&mut area_content_ui,
|
||||||
|
outer_rect,
|
||||||
|
interaction,
|
||||||
|
ctx.style().visuals.widgets.active,
|
||||||
|
);
|
||||||
|
} else if let Some(hover_interaction) = hover_interaction {
|
||||||
|
if ctx.input(|i| i.pointer.has_pointer()) {
|
||||||
paint_frame_interaction(
|
paint_frame_interaction(
|
||||||
&mut area_content_ui,
|
&mut area_content_ui,
|
||||||
outer_rect,
|
outer_rect,
|
||||||
interaction,
|
hover_interaction,
|
||||||
ctx.style().visuals.widgets.active,
|
ctx.style().visuals.widgets.hovered,
|
||||||
);
|
);
|
||||||
} else if let Some(hover_interaction) = hover_interaction {
|
|
||||||
if ctx.input(|i| i.pointer.has_pointer()) {
|
|
||||||
paint_frame_interaction(
|
|
||||||
&mut area_content_ui,
|
|
||||||
outer_rect,
|
|
||||||
hover_interaction,
|
|
||||||
ctx.style().visuals.widgets.hovered,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
content_inner
|
}
|
||||||
};
|
content_inner
|
||||||
|
};
|
||||||
|
|
||||||
let full_response = area.end(ctx, area_content_ui);
|
let full_response = area.end(ctx, area_content_ui);
|
||||||
|
|
||||||
if !collapsing.is_open() {
|
if !collapsing.is_open() {
|
||||||
let size = ctx.round_vec_to_pixels(full_response.rect.size());
|
let size = ctx.round_vec_to_pixels(full_response.rect.size());
|
||||||
ctx.viewport_command(
|
ctx.viewport_command(
|
||||||
viewport_id,
|
ctx.get_viewport_id(),
|
||||||
ViewportCommand::InnerSize(size.x as u32, size.y as u32),
|
ViewportCommand::InnerSize(size.x as u32, size.y as u32),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// let size = ctx.round_vec_to_pixels(full_response.rect.size());
|
// let size = ctx.round_vec_to_pixels(full_response.rect.size());
|
||||||
if win_size.x < size.x {
|
if win_size.x < size.x {
|
||||||
println!("Set size!");
|
println!("Set size!");
|
||||||
ctx.viewport_command(
|
ctx.viewport_command(
|
||||||
viewport_id,
|
ctx.get_viewport_id(),
|
||||||
ViewportCommand::InnerSize(size.x as u32, win_size.y as u32),
|
ViewportCommand::InnerSize(size.x as u32, win_size.y as u32),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if win_size.y < size.y {
|
if win_size.y < size.y {
|
||||||
println!("Set size!");
|
println!("Set size!");
|
||||||
ctx.viewport_command(
|
ctx.viewport_command(
|
||||||
viewport_id,
|
ctx.get_viewport_id(),
|
||||||
ViewportCommand::InnerSize(win_size.x as u32, size.y as u32),
|
ViewportCommand::InnerSize(win_size.x as u32, size.y as u32),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if show_close_button && op != is_open {
|
if show_close_button && op != is_open {
|
||||||
ctx.data_mut(|data| data.insert_persisted(area_id.with("_open"), op));
|
ctx.data_mut(|data| data.insert_persisted(area_id.with("_open"), op));
|
||||||
ctx.request_repaint_viewport(parent_viewport_id);
|
ctx.request_repaint_viewport(ctx.get_parent_viewport_id());
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ pub struct RequestRepaintInfo {
|
|||||||
/// triggered the painting of the next frame.
|
/// triggered the painting of the next frame.
|
||||||
pub current_frame_nr: u64,
|
pub current_frame_nr: u64,
|
||||||
|
|
||||||
/// This is used to specify what window to redraw
|
/// This is used to specify what viewport that should be redraw
|
||||||
pub window_id: u64,
|
pub viewport_id: ViewportId,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -60,10 +60,10 @@ struct Repaint {
|
|||||||
/// even if there's no new events.
|
/// even if there's no new events.
|
||||||
///
|
///
|
||||||
/// Also used to suppress multiple calls to the repaint callback during the same frame.
|
/// Also used to suppress multiple calls to the repaint callback during the same frame.
|
||||||
pub repaint_after: HashMap<u64, std::time::Duration>,
|
pub repaint_after: HashMap<ViewportId, std::time::Duration>,
|
||||||
|
|
||||||
/// While positive, keep requesting repaints. Decrement at the end of each frame.
|
/// While positive, keep requesting repaints. Decrement at the end of each frame.
|
||||||
repaint_requests: HashMap<u64, u32>,
|
repaint_requests: HashMap<ViewportId, u32>,
|
||||||
request_repaint_callback: Option<Box<dyn Fn(RequestRepaintInfo) + Send + Sync>>,
|
request_repaint_callback: Option<Box<dyn Fn(RequestRepaintInfo) + Send + Sync>>,
|
||||||
|
|
||||||
requested_repaint_last_frame: bool,
|
requested_repaint_last_frame: bool,
|
||||||
@@ -72,9 +72,9 @@ struct Repaint {
|
|||||||
impl Default for Repaint {
|
impl Default for Repaint {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let mut repaint_after = HashMap::default();
|
let mut repaint_after = HashMap::default();
|
||||||
repaint_after.insert(0, std::time::Duration::from_millis(100));
|
repaint_after.insert(ViewportId::MAIN, std::time::Duration::from_millis(100));
|
||||||
let mut repaint_requests = HashMap::default();
|
let mut repaint_requests = HashMap::default();
|
||||||
repaint_requests.insert(0, 1);
|
repaint_requests.insert(ViewportId::MAIN, 1);
|
||||||
Self {
|
Self {
|
||||||
frame_nr: 0,
|
frame_nr: 0,
|
||||||
repaint_after,
|
repaint_after,
|
||||||
@@ -88,11 +88,11 @@ impl Default for Repaint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Repaint {
|
impl Repaint {
|
||||||
fn request_repaint(&mut self, window_id: u64) {
|
fn request_repaint(&mut self, viewport_id: ViewportId) {
|
||||||
self.request_repaint_after(std::time::Duration::ZERO, window_id);
|
self.request_repaint_after(std::time::Duration::ZERO, viewport_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn request_repaint_after(&mut self, after: std::time::Duration, viewport_id: u64) {
|
fn request_repaint_after(&mut self, after: std::time::Duration, viewport_id: ViewportId) {
|
||||||
if after == std::time::Duration::ZERO {
|
if after == std::time::Duration::ZERO {
|
||||||
// Do a few extra frames to let things settle.
|
// Do a few extra frames to let things settle.
|
||||||
// This is a bit of a hack, and we don't support it for `repaint_after` callbacks yet.
|
// This is a bit of a hack, and we don't support it for `repaint_after` callbacks yet.
|
||||||
@@ -114,14 +114,14 @@ impl Repaint {
|
|||||||
let info = RequestRepaintInfo {
|
let info = RequestRepaintInfo {
|
||||||
after,
|
after,
|
||||||
current_frame_nr: self.frame_nr,
|
current_frame_nr: self.frame_nr,
|
||||||
window_id: viewport_id,
|
viewport_id,
|
||||||
};
|
};
|
||||||
(callback)(info);
|
(callback)(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_frame(&mut self, viewport_id: u64) {
|
fn start_frame(&mut self, viewport_id: ViewportId) {
|
||||||
// We are repainting; no need to reschedule a repaint unless the user asks for it again.
|
// We are repainting; no need to reschedule a repaint unless the user asks for it again.
|
||||||
self.repaint_after.remove(&viewport_id);
|
self.repaint_after.remove(&viewport_id);
|
||||||
}
|
}
|
||||||
@@ -129,9 +129,9 @@ impl Repaint {
|
|||||||
// returns how long to wait until repaint
|
// returns how long to wait until repaint
|
||||||
fn end_frame(
|
fn end_frame(
|
||||||
&mut self,
|
&mut self,
|
||||||
viewport_id: u64,
|
viewport_id: ViewportId,
|
||||||
viewports: Vec<u64>,
|
viewports: Vec<ViewportId>,
|
||||||
) -> Vec<(u64, std::time::Duration)> {
|
) -> Vec<(ViewportId, std::time::Duration)> {
|
||||||
// if repaint_requests is greater than zero. just set the duration to zero for immediate
|
// if repaint_requests is greater than zero. just set the duration to zero for immediate
|
||||||
// repaint. if there's no repaint requests, then we can use the actual repaint_after instead.
|
// repaint. if there's no repaint requests, then we can use the actual repaint_after instead.
|
||||||
let repaint_after = if self
|
let repaint_after = if self
|
||||||
@@ -180,17 +180,17 @@ struct ContextImpl {
|
|||||||
|
|
||||||
os: OperatingSystem,
|
os: OperatingSystem,
|
||||||
|
|
||||||
input: HashMap<u64, InputState>,
|
input: HashMap<ViewportId, InputState>,
|
||||||
|
|
||||||
/// State that is collected during a frame and then cleared
|
/// State that is collected during a frame and then cleared
|
||||||
frame_state: HashMap<u64, FrameState>,
|
frame_state: HashMap<ViewportId, FrameState>,
|
||||||
|
|
||||||
// Viewport Id, Parent Viewport Id
|
/// Viewport Id, Parent Viewport Id
|
||||||
frame_stack: Vec<(u64, u64)>,
|
frame_stack: Vec<(ViewportId, ViewportId)>,
|
||||||
|
|
||||||
// The output of a frame:
|
// The output of a frame:
|
||||||
graphics: HashMap<u64, GraphicLayers>,
|
graphics: HashMap<ViewportId, GraphicLayers>,
|
||||||
output: HashMap<u64, PlatformOutput>,
|
output: HashMap<ViewportId, PlatformOutput>,
|
||||||
|
|
||||||
paint_stats: PaintStats,
|
paint_stats: PaintStats,
|
||||||
|
|
||||||
@@ -200,19 +200,23 @@ struct ContextImpl {
|
|||||||
String,
|
String,
|
||||||
(
|
(
|
||||||
ViewportBuilder,
|
ViewportBuilder,
|
||||||
u64,
|
ViewportId,
|
||||||
u64,
|
ViewportId,
|
||||||
bool,
|
bool,
|
||||||
Option<Arc<Box<ViewportRender>>>,
|
Option<Arc<Box<ViewportRender>>>,
|
||||||
),
|
),
|
||||||
>,
|
>,
|
||||||
viewport_commands: Vec<(u64, ViewportCommand)>,
|
viewport_commands: Vec<(ViewportId, ViewportCommand)>,
|
||||||
|
|
||||||
render_sync: Option<
|
render_sync: Option<
|
||||||
Arc<
|
Arc<
|
||||||
Box<
|
Box<
|
||||||
dyn for<'a> Fn(ViewportBuilder, u64, u64, Box<dyn FnOnce(&Context, u64, u64) + 'a>)
|
dyn for<'a> Fn(
|
||||||
+ Send
|
ViewportBuilder,
|
||||||
|
ViewportId,
|
||||||
|
ViewportId,
|
||||||
|
Box<dyn FnOnce(&Context) + 'a>,
|
||||||
|
) + Send
|
||||||
+ Sync,
|
+ Sync,
|
||||||
>,
|
>,
|
||||||
>,
|
>,
|
||||||
@@ -223,11 +227,11 @@ struct ContextImpl {
|
|||||||
|
|
||||||
/// Written to during the frame.
|
/// Written to during the frame.
|
||||||
layer_rects_this_frame: ahash::HashMap<LayerId, Vec<(Id, Rect)>>,
|
layer_rects_this_frame: ahash::HashMap<LayerId, Vec<(Id, Rect)>>,
|
||||||
layer_rects_this_viewports: HashMap<u64, HashMap<LayerId, Vec<(Id, Rect)>>>,
|
layer_rects_this_viewports: HashMap<ViewportId, HashMap<LayerId, Vec<(Id, Rect)>>>,
|
||||||
|
|
||||||
/// Read
|
/// Read
|
||||||
layer_rects_prev_frame: ahash::HashMap<LayerId, Vec<(Id, Rect)>>,
|
layer_rects_prev_frame: ahash::HashMap<LayerId, Vec<(Id, Rect)>>,
|
||||||
layer_rects_prev_viewports: HashMap<u64, HashMap<LayerId, Vec<(Id, Rect)>>>,
|
layer_rects_prev_viewports: HashMap<ViewportId, HashMap<LayerId, Vec<(Id, Rect)>>>,
|
||||||
|
|
||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
is_accesskit_enabled: bool,
|
is_accesskit_enabled: bool,
|
||||||
@@ -239,8 +243,8 @@ impl ContextImpl {
|
|||||||
fn begin_frame_mut(
|
fn begin_frame_mut(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut new_raw_input: RawInput,
|
mut new_raw_input: RawInput,
|
||||||
viewport_id: u64,
|
viewport_id: ViewportId,
|
||||||
parent_viewport_id: u64,
|
parent_viewport_id: ViewportId,
|
||||||
) {
|
) {
|
||||||
// This is used to pause the last frame
|
// This is used to pause the last frame
|
||||||
if !self.frame_stack.is_empty() {
|
if !self.frame_stack.is_empty() {
|
||||||
@@ -377,11 +381,17 @@ impl ContextImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ContextImpl {
|
impl ContextImpl {
|
||||||
pub(crate) fn get_viewport_id(&self) -> u64 {
|
// Return the `ViewportId` of the current viewport
|
||||||
|
//
|
||||||
|
// In the case of this viewport is the main viewport will be `ViewportId::MAIN`
|
||||||
|
pub(crate) fn get_viewport_id(&self) -> ViewportId {
|
||||||
self.frame_stack.last().cloned().unwrap_or_default().0
|
self.frame_stack.last().cloned().unwrap_or_default().0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_parent_viewport_id(&self) -> u64 {
|
// Return the `ViewportId` of his parent
|
||||||
|
//
|
||||||
|
// In the case of this viewport is the main viewport will be `ViewportId::MAIN`
|
||||||
|
pub(crate) fn get_parent_viewport_id(&self) -> ViewportId {
|
||||||
self.frame_stack.last().cloned().unwrap_or_default().1
|
self.frame_stack.last().cloned().unwrap_or_default().1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -460,7 +470,7 @@ impl Default for Context {
|
|||||||
|
|
||||||
s.write(|ctx| {
|
s.write(|ctx| {
|
||||||
ctx.render_sync = Some(Arc::new(Box::new(
|
ctx.render_sync = Some(Arc::new(Box::new(
|
||||||
move |_builder, _viewport_id, _parent_viewport_id, render| render(&clone, 0, 0),
|
move |_builder, _viewport_id, _parent_viewport_id, render| render(&clone),
|
||||||
)))
|
)))
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -505,8 +515,8 @@ impl Context {
|
|||||||
pub fn run(
|
pub fn run(
|
||||||
&self,
|
&self,
|
||||||
new_input: RawInput,
|
new_input: RawInput,
|
||||||
viewport_id: u64,
|
viewport_id: ViewportId,
|
||||||
parent_viewport_id: u64,
|
parent_viewport_id: ViewportId,
|
||||||
run_ui: impl FnOnce(&Context),
|
run_ui: impl FnOnce(&Context),
|
||||||
) -> FullOutput {
|
) -> FullOutput {
|
||||||
self.begin_frame(new_input, viewport_id, parent_viewport_id);
|
self.begin_frame(new_input, viewport_id, parent_viewport_id);
|
||||||
@@ -531,7 +541,12 @@ impl Context {
|
|||||||
/// let full_output = ctx.end_frame();
|
/// let full_output = ctx.end_frame();
|
||||||
/// // handle full_output
|
/// // handle full_output
|
||||||
/// ```
|
/// ```
|
||||||
pub fn begin_frame(&self, new_input: RawInput, viewport_id: u64, parent_viewport_id: u64) {
|
pub fn begin_frame(
|
||||||
|
&self,
|
||||||
|
new_input: RawInput,
|
||||||
|
viewport_id: ViewportId,
|
||||||
|
parent_viewport_id: ViewportId,
|
||||||
|
) {
|
||||||
self.write(|ctx| ctx.begin_frame_mut(new_input, viewport_id, parent_viewport_id));
|
self.write(|ctx| ctx.begin_frame_mut(new_input, viewport_id, parent_viewport_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -568,7 +583,7 @@ impl Context {
|
|||||||
/// Read-write access to [`InputState`].
|
/// Read-write access to [`InputState`].
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn input_mut<R>(&self, writer: impl FnOnce(&mut InputState) -> R) -> R {
|
pub fn input_mut<R>(&self, writer: impl FnOnce(&mut InputState) -> R) -> R {
|
||||||
self.write(move |ctx| writer(ctx.input.entry(ctx.viewport_counter).or_default()))
|
self.write(move |ctx| writer(ctx.input.entry(ctx.get_viewport_id()).or_default()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read-only access to [`Memory`].
|
/// Read-only access to [`Memory`].
|
||||||
@@ -1117,7 +1132,7 @@ impl Context {
|
|||||||
self.write(|ctx| ctx.repaint.request_repaint(ctx.get_viewport_id()));
|
self.write(|ctx| ctx.repaint.request_repaint(ctx.get_viewport_id()));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request_repaint_viewport(&self, id: u64) {
|
pub fn request_repaint_viewport(&self, id: ViewportId) {
|
||||||
self.write(|ctx| ctx.repaint.request_repaint(id))
|
self.write(|ctx| ctx.repaint.request_repaint(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1158,7 +1173,7 @@ impl Context {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request_repaint_viewport_after(&self, duration: std::time::Duration, id: u64) {
|
pub fn request_repaint_viewport_after(&self, duration: std::time::Duration, id: ViewportId) {
|
||||||
self.write(|ctx| ctx.repaint.request_repaint_after(duration, id))
|
self.write(|ctx| ctx.repaint.request_repaint_after(duration, id))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1376,7 +1391,7 @@ impl Context {
|
|||||||
/// Call at the end of each frame.
|
/// Call at the end of each frame.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn end_frame(&self) -> FullOutput {
|
pub fn end_frame(&self) -> FullOutput {
|
||||||
let mut viewports: Vec<u64> = self.write(|ctx| {
|
let mut viewports: Vec<ViewportId> = self.write(|ctx| {
|
||||||
ctx.layer_rects_prev_viewports.insert(
|
ctx.layer_rects_prev_viewports.insert(
|
||||||
ctx.get_viewport_id(),
|
ctx.get_viewport_id(),
|
||||||
std::mem::take(&mut ctx.layer_rects_this_frame),
|
std::mem::take(&mut ctx.layer_rects_this_frame),
|
||||||
@@ -1386,7 +1401,7 @@ impl Context {
|
|||||||
.map(|(_, (_, id, _, _, _))| *id)
|
.map(|(_, (_, id, _, _, _))| *id)
|
||||||
.collect()
|
.collect()
|
||||||
});
|
});
|
||||||
viewports.push(0);
|
viewports.push(ViewportId::MAIN);
|
||||||
|
|
||||||
if self.input(|i| i.wants_repaint()) {
|
if self.input(|i| i.wants_repaint()) {
|
||||||
self.request_repaint();
|
self.request_repaint();
|
||||||
@@ -1464,7 +1479,7 @@ impl Context {
|
|||||||
// This is used for,
|
// This is used for,
|
||||||
// If there are no viewport that contains the current viewpor that viewport needs to be destroyed!
|
// If there are no viewport that contains the current viewpor that viewport needs to be destroyed!
|
||||||
let avalibile_viewports = self.read(|ctx| {
|
let avalibile_viewports = self.read(|ctx| {
|
||||||
let mut avalibile_viewports = vec![0];
|
let mut avalibile_viewports = vec![ViewportId::MAIN];
|
||||||
for (_, (_, id, _, _, _)) in ctx.viewports.iter() {
|
for (_, (_, id, _, _, _)) in ctx.viewports.iter() {
|
||||||
avalibile_viewports.push(*id);
|
avalibile_viewports.push(*id);
|
||||||
}
|
}
|
||||||
@@ -2139,17 +2154,23 @@ impl Context {
|
|||||||
|
|
||||||
// Viewports
|
// Viewports
|
||||||
impl Context {
|
impl Context {
|
||||||
pub fn get_viewport_id(&self) -> u64 {
|
// Return the `ViewportId` of the current viewport
|
||||||
|
//
|
||||||
|
// In the case of this viewport is the main viewport will be `ViewportId::MAIN`
|
||||||
|
pub fn get_viewport_id(&self) -> ViewportId {
|
||||||
self.read(|ctx| ctx.get_viewport_id())
|
self.read(|ctx| ctx.get_viewport_id())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_parent_viewport_id(&self) -> u64 {
|
// Return the `ViewportId` of his parent
|
||||||
|
//
|
||||||
|
// In the case of this viewport is the main viewport will be `ViewportId::MAIN`
|
||||||
|
pub fn get_parent_viewport_id(&self) -> ViewportId {
|
||||||
self.read(|ctx| ctx.get_parent_viewport_id())
|
self.read(|ctx| ctx.get_parent_viewport_id())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_render_sync_callback(
|
pub fn set_render_sync_callback(
|
||||||
&self,
|
&self,
|
||||||
callback: impl for<'a> Fn(ViewportBuilder, u64, u64, Box<dyn FnOnce(&Context, u64, u64) + 'a>)
|
callback: impl for<'a> Fn(ViewportBuilder, ViewportId, ViewportId, Box<dyn FnOnce(&Context) + 'a>)
|
||||||
+ Send
|
+ Send
|
||||||
+ Sync
|
+ Sync
|
||||||
+ 'static,
|
+ 'static,
|
||||||
@@ -2166,14 +2187,14 @@ impl Context {
|
|||||||
self.write(|ctx| ctx.is_desktop = value)
|
self.write(|ctx| ctx.is_desktop = value)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn viewport_command(&self, id: u64, command: ViewportCommand) {
|
pub fn viewport_command(&self, id: ViewportId, command: ViewportCommand) {
|
||||||
self.write(|ctx| ctx.viewport_commands.push((id, command)))
|
self.write(|ctx| ctx.viewport_commands.push((id, command)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_viewport(
|
pub fn create_viewport(
|
||||||
&self,
|
&self,
|
||||||
viewport_builder: ViewportBuilder,
|
viewport_builder: ViewportBuilder,
|
||||||
func: impl Fn(&Context, u64, u64) + Send + Sync + 'static,
|
func: impl Fn(&Context) + Send + Sync + 'static,
|
||||||
) {
|
) {
|
||||||
if self.is_desktop() {
|
if self.is_desktop() {
|
||||||
self.write(|ctx| {
|
self.write(|ctx| {
|
||||||
@@ -2184,8 +2205,8 @@ impl Context {
|
|||||||
window.3 = true;
|
window.3 = true;
|
||||||
window.4 = Some(Arc::new(Box::new(func)));
|
window.4 = Some(Arc::new(Box::new(func)));
|
||||||
} else {
|
} else {
|
||||||
let id = ctx.viewport_counter + 1;
|
let id = ViewportId(ctx.viewport_counter + 1);
|
||||||
ctx.viewport_counter = id;
|
ctx.viewport_counter += 1;
|
||||||
ctx.viewports.insert(
|
ctx.viewports.insert(
|
||||||
viewport_builder.title.clone(),
|
viewport_builder.title.clone(),
|
||||||
(
|
(
|
||||||
@@ -2199,18 +2220,18 @@ impl Context {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
func(self, 0, 0);
|
func(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_viewport_sync<T>(
|
pub fn create_viewport_sync<T>(
|
||||||
&self,
|
&self,
|
||||||
viewport_builder: ViewportBuilder,
|
viewport_builder: ViewportBuilder,
|
||||||
func: impl FnOnce(&Context, u64, u64) -> T,
|
func: impl FnOnce(&Context) -> T,
|
||||||
) -> T {
|
) -> T {
|
||||||
if self.is_desktop() {
|
if self.is_desktop() {
|
||||||
let mut viewport_id = 0;
|
let mut viewport_id = ViewportId::MAIN;
|
||||||
let mut parent_viewport_id = 0;
|
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();
|
viewport_id = ctx.get_viewport_id();
|
||||||
if let Some(window) = ctx.viewports.get_mut(&viewport_builder.title) {
|
if let Some(window) = ctx.viewports.get_mut(&viewport_builder.title) {
|
||||||
@@ -2221,8 +2242,8 @@ impl Context {
|
|||||||
viewport_id = window.1;
|
viewport_id = window.1;
|
||||||
parent_viewport_id = window.2;
|
parent_viewport_id = window.2;
|
||||||
} else {
|
} else {
|
||||||
let id = ctx.viewport_counter + 1;
|
let id = ViewportId(ctx.viewport_counter + 1);
|
||||||
ctx.viewport_counter = id;
|
ctx.viewport_counter += 1;
|
||||||
ctx.viewports.insert(
|
ctx.viewports.insert(
|
||||||
viewport_builder.title.clone(),
|
viewport_builder.title.clone(),
|
||||||
(viewport_builder.clone(), id, viewport_id, true, None),
|
(viewport_builder.clone(), id, viewport_id, true, None),
|
||||||
@@ -2240,15 +2261,13 @@ impl Context {
|
|||||||
viewport_builder,
|
viewport_builder,
|
||||||
viewport_id,
|
viewport_id,
|
||||||
parent_viewport_id,
|
parent_viewport_id,
|
||||||
Box::new(move |context, viewport_id, parent_viewport_id| {
|
Box::new(move |context| *out = Some(func(context))),
|
||||||
*out = Some(func(context, viewport_id, parent_viewport_id))
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
out.unwrap()
|
out.unwrap()
|
||||||
} else {
|
} else {
|
||||||
func(self, 0, 0)
|
func(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::Context;
|
|
||||||
use crate::{ViewportBuilder, ViewportCommand, 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`].
|
||||||
///
|
///
|
||||||
@@ -21,7 +21,7 @@ pub struct FullOutput {
|
|||||||
/// duration elapses. when in reactive mode, egui spends forever waiting for input and only then,
|
/// duration elapses. when in reactive mode, egui spends forever waiting for input and only then,
|
||||||
/// will it repaint itself. this can be used to make sure that backend will only wait for a
|
/// will it repaint itself. this can be used to make sure that backend will only wait for a
|
||||||
/// specified amount of time, and repaint egui without any new input.
|
/// specified amount of time, and repaint egui without any new input.
|
||||||
pub repaint_after: Vec<(u64, std::time::Duration)>,
|
pub repaint_after: Vec<(ViewportId, std::time::Duration)>,
|
||||||
|
|
||||||
/// Texture changes since last frame (including the font texture).
|
/// Texture changes since last frame (including the font texture).
|
||||||
///
|
///
|
||||||
@@ -35,13 +35,13 @@ pub struct FullOutput {
|
|||||||
pub shapes: Vec<epaint::ClippedShape>,
|
pub shapes: Vec<epaint::ClippedShape>,
|
||||||
|
|
||||||
pub viewports: Vec<(
|
pub viewports: Vec<(
|
||||||
u64,
|
ViewportId,
|
||||||
u64,
|
ViewportId,
|
||||||
ViewportBuilder,
|
ViewportBuilder,
|
||||||
Option<Arc<Box<dyn Fn(&Context, u64, u64) + Sync + Send>>>,
|
Option<Arc<Box<ViewportRender>>>,
|
||||||
)>,
|
)>,
|
||||||
|
|
||||||
pub viewport_commands: Vec<(u64, ViewportCommand)>,
|
pub viewport_commands: Vec<(ViewportId, ViewportCommand)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FullOutput {
|
impl FullOutput {
|
||||||
|
|||||||
@@ -554,20 +554,30 @@ pub enum WidgetType {
|
|||||||
pub fn __run_test_ctx(mut run_ui: impl FnMut(&Context)) {
|
pub fn __run_test_ctx(mut run_ui: impl FnMut(&Context)) {
|
||||||
let ctx = Context::default();
|
let ctx = Context::default();
|
||||||
ctx.set_fonts(FontDefinitions::empty()); // prevent fonts from being loaded (save CPU time)
|
ctx.set_fonts(FontDefinitions::empty()); // prevent fonts from being loaded (save CPU time)
|
||||||
let _ = ctx.run(Default::default(), 0, 0, |ctx| {
|
let _ = ctx.run(
|
||||||
run_ui(ctx);
|
Default::default(),
|
||||||
});
|
ViewportId::MAIN,
|
||||||
|
ViewportId::MAIN,
|
||||||
|
|ctx| {
|
||||||
|
run_ui(ctx);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For use in tests; especially doctests.
|
/// For use in tests; especially doctests.
|
||||||
pub fn __run_test_ui(mut add_contents: impl FnMut(&mut Ui)) {
|
pub fn __run_test_ui(mut add_contents: impl FnMut(&mut Ui)) {
|
||||||
let ctx = Context::default();
|
let ctx = Context::default();
|
||||||
ctx.set_fonts(FontDefinitions::empty()); // prevent fonts from being loaded (save CPU time)
|
ctx.set_fonts(FontDefinitions::empty()); // prevent fonts from being loaded (save CPU time)
|
||||||
let _ = ctx.run(Default::default(), 0, 0, |ctx| {
|
let _ = ctx.run(
|
||||||
crate::CentralPanel::default().show(ctx, |ui| {
|
Default::default(),
|
||||||
add_contents(ui);
|
ViewportId::MAIN,
|
||||||
});
|
ViewportId::MAIN,
|
||||||
});
|
|ctx| {
|
||||||
|
crate::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
add_contents(ui);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "accesskit")]
|
#[cfg(feature = "accesskit")]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use ahash::HashMap;
|
use ahash::HashMap;
|
||||||
|
|
||||||
use crate::{area, window, Id, IdMap, InputState, LayerId, Pos2, Rect, Style};
|
use crate::{area, window, Id, IdMap, InputState, LayerId, Pos2, Rect, Style, ViewportId};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -72,20 +72,20 @@ pub struct Memory {
|
|||||||
pub(crate) new_font_definitions: Option<epaint::text::FontDefinitions>,
|
pub(crate) new_font_definitions: Option<epaint::text::FontDefinitions>,
|
||||||
|
|
||||||
#[cfg_attr(feature = "persistence", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
pub(crate) interactions: HashMap<u64, Interaction>,
|
pub(crate) interactions: HashMap<ViewportId, Interaction>,
|
||||||
|
|
||||||
#[cfg_attr(feature = "persistence", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
pub(crate) interaction: Interaction,
|
pub(crate) interaction: Interaction,
|
||||||
|
|
||||||
// Current viewport
|
// Current viewport
|
||||||
#[cfg_attr(feature = "persistence", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
pub(crate) viewport_id: u64,
|
pub(crate) viewport_id: ViewportId,
|
||||||
|
|
||||||
#[cfg_attr(feature = "persistence", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
pub(crate) window_interaction: Option<window::WindowInteraction>,
|
pub(crate) window_interaction: Option<window::WindowInteraction>,
|
||||||
|
|
||||||
#[cfg_attr(feature = "persistence", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
pub(crate) window_interactions: HashMap<u64, window::WindowInteraction>,
|
pub(crate) window_interactions: HashMap<ViewportId, window::WindowInteraction>,
|
||||||
|
|
||||||
#[cfg_attr(feature = "persistence", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
pub(crate) drag_value: crate::widgets::drag_value::MonoState,
|
pub(crate) drag_value: crate::widgets::drag_value::MonoState,
|
||||||
@@ -94,7 +94,7 @@ pub struct Memory {
|
|||||||
pub(crate) areas: Areas,
|
pub(crate) areas: Areas,
|
||||||
|
|
||||||
#[cfg_attr(feature = "persistence", serde(skip))]
|
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||||
pub(crate) viewports_areas: HashMap<u64, Areas>,
|
pub(crate) viewports_areas: HashMap<ViewportId, Areas>,
|
||||||
|
|
||||||
/// Which popup-window is open (if any)?
|
/// Which popup-window is open (if any)?
|
||||||
/// Could be a combo box, color picker, menu etc.
|
/// Could be a combo box, color picker, menu etc.
|
||||||
@@ -370,7 +370,7 @@ impl Memory {
|
|||||||
&mut self,
|
&mut self,
|
||||||
prev_input: &crate::input_state::InputState,
|
prev_input: &crate::input_state::InputState,
|
||||||
new_input: &crate::data::input::RawInput,
|
new_input: &crate::data::input::RawInput,
|
||||||
viewport_id: u64,
|
viewport_id: ViewportId,
|
||||||
) {
|
) {
|
||||||
self.viewport_id = viewport_id;
|
self.viewport_id = viewport_id;
|
||||||
self.interactions
|
self.interactions
|
||||||
@@ -389,7 +389,7 @@ impl Memory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn pause_frame(&mut self, viewport_id: u64) {
|
pub(crate) fn pause_frame(&mut self, viewport_id: ViewportId) {
|
||||||
if let Some(window_interaction) = self.window_interaction {
|
if let Some(window_interaction) = self.window_interaction {
|
||||||
self.window_interactions
|
self.window_interactions
|
||||||
.insert(viewport_id, window_interaction);
|
.insert(viewport_id, window_interaction);
|
||||||
@@ -403,7 +403,7 @@ impl Memory {
|
|||||||
pub(crate) fn end_frame(
|
pub(crate) fn end_frame(
|
||||||
&mut self,
|
&mut self,
|
||||||
input: &InputState,
|
input: &InputState,
|
||||||
viewports: &[u64],
|
viewports: &[ViewportId],
|
||||||
used_ids: &IdMap<Rect>,
|
used_ids: &IdMap<Rect>,
|
||||||
) {
|
) {
|
||||||
self.caches.update();
|
self.caches.update();
|
||||||
@@ -420,7 +420,7 @@ impl Memory {
|
|||||||
.retain(|id, _| viewports.contains(id));
|
.retain(|id, _| viewports.contains(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn resume_frame(&mut self, viewport_id: u64) {
|
pub(crate) fn resume_frame(&mut self, viewport_id: ViewportId) {
|
||||||
self.interaction = self.interactions.remove(&viewport_id).unwrap();
|
self.interaction = self.interactions.remove(&viewport_id).unwrap();
|
||||||
self.areas = self.viewports_areas.remove(&viewport_id).unwrap();
|
self.areas = self.viewports_areas.remove(&viewport_id).unwrap();
|
||||||
self.viewport_id = viewport_id;
|
self.viewport_id = viewport_id;
|
||||||
|
|||||||
@@ -1,11 +1,28 @@
|
|||||||
use std::sync::Arc;
|
use std::fmt::Display;
|
||||||
|
|
||||||
use crate::Context;
|
use crate::Context;
|
||||||
|
|
||||||
/// This is used to render a viewport
|
/// This is used to send a command to a specific viewport
|
||||||
pub type ViewportRender = dyn Fn(&Context, u64, u64) + Sync + Send;
|
///
|
||||||
|
/// This is returned by `Context::get_viewport_id` and `Context::get_parent_viewport_id`
|
||||||
|
#[derive(Default, Debug, Hash, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct ViewportId(pub(crate) u64);
|
||||||
|
|
||||||
#[derive(Hash, PartialEq, Clone)]
|
impl Display for ViewportId {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
self.0.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ViewportId {
|
||||||
|
/// This will return the `ViewportId` of the main viewport
|
||||||
|
pub const MAIN: Self = Self(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is used to render an async viewport
|
||||||
|
pub type ViewportRender = dyn Fn(&Context) + Sync + Send;
|
||||||
|
|
||||||
|
#[derive(Hash, PartialEq, Eq, Clone)]
|
||||||
pub struct ViewportBuilder {
|
pub struct ViewportBuilder {
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ impl eframe::App for Custom3d {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ impl eframe::App for EasyMarkApp {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.editor.panels(ctx);
|
self.editor.panels(ctx);
|
||||||
@@ -44,7 +44,7 @@ impl eframe::App for DemoApp {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.demo_windows.ui(ctx);
|
self.demo_windows.ui(ctx);
|
||||||
@@ -67,7 +67,7 @@ impl eframe::App for FractalClockApp {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
egui::CentralPanel::default()
|
egui::CentralPanel::default()
|
||||||
@@ -95,7 +95,7 @@ impl eframe::App for ColorTestApp {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
@@ -270,7 +270,7 @@ impl eframe::App for WrapApp {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use criterion::{criterion_group, criterion_main, Criterion};
|
use criterion::{criterion_group, criterion_main, Criterion};
|
||||||
|
|
||||||
use egui::epaint::TextShape;
|
use egui::{epaint::TextShape, ViewportId};
|
||||||
use egui_demo_lib::LOREM_IPSUM_LONG;
|
use egui_demo_lib::LOREM_IPSUM_LONG;
|
||||||
|
|
||||||
pub fn criterion_benchmark(c: &mut Criterion) {
|
pub fn criterion_benchmark(c: &mut Criterion) {
|
||||||
@@ -13,24 +13,39 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||||||
// The most end-to-end benchmark.
|
// The most end-to-end benchmark.
|
||||||
c.bench_function("demo_with_tessellate__realistic", |b| {
|
c.bench_function("demo_with_tessellate__realistic", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let full_output = ctx.run(RawInput::default(), 0, 0, |ctx| {
|
let full_output = ctx.run(
|
||||||
demo_windows.ui(ctx);
|
RawInput::default(),
|
||||||
});
|
ViewportId::MAIN,
|
||||||
|
ViewportId::MAIN,
|
||||||
|
|ctx| {
|
||||||
|
demo_windows.ui(ctx);
|
||||||
|
},
|
||||||
|
);
|
||||||
ctx.tessellate(full_output.shapes)
|
ctx.tessellate(full_output.shapes)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
c.bench_function("demo_no_tessellate", |b| {
|
c.bench_function("demo_no_tessellate", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
ctx.run(RawInput::default(), 0, 0, |ctx| {
|
ctx.run(
|
||||||
demo_windows.ui(ctx);
|
RawInput::default(),
|
||||||
})
|
ViewportId::MAIN,
|
||||||
|
ViewportId::MAIN,
|
||||||
|
|ctx| {
|
||||||
|
demo_windows.ui(ctx);
|
||||||
|
},
|
||||||
|
)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let full_output = ctx.run(RawInput::default(), 0, 0, |ctx| {
|
let full_output = ctx.run(
|
||||||
demo_windows.ui(ctx);
|
RawInput::default(),
|
||||||
});
|
ViewportId::MAIN,
|
||||||
|
ViewportId::MAIN,
|
||||||
|
|ctx| {
|
||||||
|
demo_windows.ui(ctx);
|
||||||
|
},
|
||||||
|
);
|
||||||
c.bench_function("demo_only_tessellate", |b| {
|
c.bench_function("demo_only_tessellate", |b| {
|
||||||
b.iter(|| ctx.tessellate(full_output.shapes.clone()));
|
b.iter(|| ctx.tessellate(full_output.shapes.clone()));
|
||||||
});
|
});
|
||||||
@@ -42,34 +57,44 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||||||
let mut demo_windows = egui_demo_lib::DemoWindows::default();
|
let mut demo_windows = egui_demo_lib::DemoWindows::default();
|
||||||
c.bench_function("demo_full_no_tessellate", |b| {
|
c.bench_function("demo_full_no_tessellate", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
ctx.run(RawInput::default(), 0, 0, |ctx| {
|
ctx.run(
|
||||||
demo_windows.ui(ctx);
|
RawInput::default(),
|
||||||
})
|
ViewportId::MAIN,
|
||||||
|
ViewportId::MAIN,
|
||||||
|
|ctx| {
|
||||||
|
demo_windows.ui(ctx);
|
||||||
|
},
|
||||||
|
)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let ctx = egui::Context::default();
|
let ctx = egui::Context::default();
|
||||||
let _ = ctx.run(RawInput::default(), 0, 0, |ctx| {
|
let _ = ctx.run(
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
RawInput::default(),
|
||||||
c.bench_function("label &str", |b| {
|
ViewportId::MAIN,
|
||||||
b.iter(|| {
|
ViewportId::MAIN,
|
||||||
ui.label("the quick brown fox jumps over the lazy dog");
|
|ctx| {
|
||||||
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
c.bench_function("label &str", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
ui.label("the quick brown fox jumps over the lazy dog");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
c.bench_function("label format!", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
ui.label("the quick brown fox jumps over the lazy dog".to_owned());
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
c.bench_function("label format!", |b| {
|
},
|
||||||
b.iter(|| {
|
);
|
||||||
ui.label("the quick brown fox jumps over the lazy dog".to_owned());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let ctx = egui::Context::default();
|
let ctx = egui::Context::default();
|
||||||
ctx.begin_frame(RawInput::default(), 0, 0);
|
ctx.begin_frame(RawInput::default(), ViewportId::MAIN, ViewportId::MAIN);
|
||||||
|
|
||||||
egui::CentralPanel::default().show(&ctx, |ui| {
|
egui::CentralPanel::default().show(&ctx, |ui| {
|
||||||
c.bench_function("Painter::rect", |b| {
|
c.bench_function("Painter::rect", |b| {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ pub mod syntax_highlighting;
|
|||||||
|
|
||||||
pub use color_test::ColorTest;
|
pub use color_test::ColorTest;
|
||||||
pub use demo::DemoWindows;
|
pub use demo::DemoWindows;
|
||||||
|
use egui::ViewportId;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -68,9 +69,14 @@ fn test_egui_e2e() {
|
|||||||
|
|
||||||
const NUM_FRAMES: usize = 5;
|
const NUM_FRAMES: usize = 5;
|
||||||
for _ in 0..NUM_FRAMES {
|
for _ in 0..NUM_FRAMES {
|
||||||
let full_output = ctx.run(raw_input.clone(), 0, 0, |ctx| {
|
let full_output = ctx.run(
|
||||||
demo_windows.ui(ctx);
|
raw_input.clone(),
|
||||||
});
|
ViewportId::MAIN,
|
||||||
|
ViewportId::MAIN,
|
||||||
|
|ctx| {
|
||||||
|
demo_windows.ui(ctx);
|
||||||
|
},
|
||||||
|
);
|
||||||
let clipped_primitives = ctx.tessellate(full_output.shapes);
|
let clipped_primitives = ctx.tessellate(full_output.shapes);
|
||||||
assert!(!clipped_primitives.is_empty());
|
assert!(!clipped_primitives.is_empty());
|
||||||
}
|
}
|
||||||
@@ -87,9 +93,14 @@ fn test_egui_zero_window_size() {
|
|||||||
|
|
||||||
const NUM_FRAMES: usize = 5;
|
const NUM_FRAMES: usize = 5;
|
||||||
for _ in 0..NUM_FRAMES {
|
for _ in 0..NUM_FRAMES {
|
||||||
let full_output = ctx.run(raw_input.clone(), 0, 0, |ctx| {
|
let full_output = ctx.run(
|
||||||
demo_windows.ui(ctx);
|
raw_input.clone(),
|
||||||
});
|
ViewportId::MAIN,
|
||||||
|
ViewportId::MAIN,
|
||||||
|
|ctx| {
|
||||||
|
demo_windows.ui(ctx);
|
||||||
|
},
|
||||||
|
);
|
||||||
let clipped_primitives = ctx.tessellate(full_output.shapes);
|
let clipped_primitives = ctx.tessellate(full_output.shapes);
|
||||||
assert!(
|
assert!(
|
||||||
clipped_primitives.is_empty(),
|
clipped_primitives.is_empty(),
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ impl eframe::App for MyApp {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ impl eframe::App for MyApp {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ impl eframe::App for MyApp {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ impl eframe::App for MyApp {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
egui::CentralPanel::default().show(ctx, content);
|
egui::CentralPanel::default().show(ctx, content);
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ impl eframe::App for MyApp {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
custom_window_frame(ctx, frame, "egui with custom frame", |ui| {
|
custom_window_frame(ctx, frame, "egui with custom frame", |ui| {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ impl eframe::App for MyApp {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let promise = self.promise.get_or_insert_with(|| {
|
let promise = self.promise.get_or_insert_with(|| {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ impl eframe::App for MyApp {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ impl eframe::App for MyApp {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ impl eframe::App for MyApp {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
egui::Window::new("Main thread").show(ctx, |ui| {
|
egui::Window::new("Main thread").show(ctx, |ui| {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ impl eframe::App for Content {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ impl eframe::App for MyApp {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ impl eframe::App for MyApp {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ impl eframe::App for MyApp {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ impl eframe::App for MyApp {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ impl eframe::App for MyApp {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ impl eframe::App for Application {
|
|||||||
render: Option<&ViewportRender>,
|
render: Option<&ViewportRender>,
|
||||||
) {
|
) {
|
||||||
if let Some(render) = render {
|
if let Some(render) = render {
|
||||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
render(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let Some(request_at) = self.request_at {
|
if let Some(request_at) = self.request_at {
|
||||||
|
|||||||
@@ -39,7 +39,9 @@ fn main() {
|
|||||||
if show_sync {
|
if show_sync {
|
||||||
ctx.create_viewport_sync(
|
ctx.create_viewport_sync(
|
||||||
ViewportBuilder::default().with_title("Sync rendering!"),
|
ViewportBuilder::default().with_title("Sync rendering!"),
|
||||||
|ctx, viewport_id, parent_viewport_id| {
|
|ctx| {
|
||||||
|
let viewport_id = ctx.get_viewport_id();
|
||||||
|
let parent_viewport_id = ctx.get_parent_viewport_id();
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
ui.label(format!("Frame: {}", ui.ctx().frame_nr()));
|
ui.label(format!("Frame: {}", ui.ctx().frame_nr()));
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
|
|||||||
Reference in New Issue
Block a user