mirror of
https://github.com/emilk/egui.git
synced 2026-06-26 22:53:14 -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 = [
|
||||
"bytemuck",
|
||||
"document-features",
|
||||
"egui",
|
||||
"epaint",
|
||||
"log",
|
||||
"puffin",
|
||||
|
||||
@@ -269,6 +269,8 @@ pub fn run_simple_native(
|
||||
native_options: NativeOptions,
|
||||
update_fun: impl FnMut(&egui::Context, &mut Frame) + 'static,
|
||||
) -> Result<()> {
|
||||
use egui::{ViewportId, ViewportRender};
|
||||
|
||||
struct SimpleApp<U> {
|
||||
update_fun: U,
|
||||
}
|
||||
@@ -277,12 +279,12 @@ pub fn run_simple_native(
|
||||
&mut self,
|
||||
ctx: &egui::Context,
|
||||
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);
|
||||
} else if let Some(render_function) = render_function {
|
||||
render_function(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id())
|
||||
} else if let Some(render_function) = render {
|
||||
render_function(ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use raw_window_handle::{HasRawDisplayHandle as _, HasRawWindowHandle as _};
|
||||
|
||||
#[cfg(feature = "accesskit")]
|
||||
use egui::accesskit;
|
||||
use egui::{Context, NumExt as _, ViewportBuilder};
|
||||
use egui::{Context, NumExt as _, ViewportBuilder, ViewportId, ViewportRender};
|
||||
#[cfg(feature = "accesskit")]
|
||||
use egui_winit::accesskit_winit;
|
||||
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());
|
||||
self.egui_ctx
|
||||
.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.egui_ctx.memory_mut(|mem| *mem = saved_memory); // We don't want to remember that windows were huge.
|
||||
self.egui_ctx.clear_animations();
|
||||
@@ -449,14 +456,14 @@ impl EpiIntegration {
|
||||
event: &winit::event::WindowEvent<'_>,
|
||||
window_id: &winit::window::WindowId,
|
||||
egui_winit: &mut egui_winit::State,
|
||||
viewport_id: u64,
|
||||
viewport_id: ViewportId,
|
||||
) -> EventResponse {
|
||||
use winit::event::{ElementState, MouseButton, WindowEvent};
|
||||
|
||||
match event {
|
||||
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);
|
||||
}
|
||||
WindowEvent::Destroyed => {
|
||||
@@ -497,9 +504,9 @@ impl EpiIntegration {
|
||||
app: &mut dyn epi::App,
|
||||
window: &winit::window::Window,
|
||||
egui_winit: &mut egui_winit::State,
|
||||
render: Option<Arc<Box<dyn Fn(&Context, u64, u64) + Sync + Send>>>,
|
||||
viewport_id: u64,
|
||||
parent_id: u64,
|
||||
render: Option<Arc<Box<ViewportRender>>>,
|
||||
viewport_id: egui::ViewportId,
|
||||
parent_id: egui::ViewportId,
|
||||
) -> egui::FullOutput {
|
||||
let frame_start = std::time::Instant::now();
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
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 winit::{
|
||||
event_loop::{ControlFlow, EventLoop, EventLoopBuilder, EventLoopProxy, EventLoopWindowTarget},
|
||||
@@ -23,7 +23,7 @@ use super::epi_integration::{self, load_icon, EpiIntegration};
|
||||
#[derive(Debug)]
|
||||
pub enum UserEvent {
|
||||
RequestRepaint {
|
||||
window_id: u64,
|
||||
id: ViewportId,
|
||||
when: Instant,
|
||||
/// What the frame number was when the repaint was _requested_.
|
||||
frame_nr: u64,
|
||||
@@ -79,8 +79,8 @@ trait WinitApp {
|
||||
window_id: winit::window::WindowId,
|
||||
) -> Option<Arc<RwLock<winit::window::Window>>>;
|
||||
|
||||
fn get_window_winit_id(&self, id: u64) -> Option<winit::window::WindowId>;
|
||||
fn get_window_id(&self, id: &winit::window::WindowId) -> Option<u64>;
|
||||
fn get_window_winit_id(&self, id: ViewportId) -> Option<winit::window::WindowId>;
|
||||
fn get_window_id(&self, id: &winit::window::WindowId) -> Option<ViewportId>;
|
||||
|
||||
fn save_and_destroy(&mut self);
|
||||
|
||||
@@ -168,7 +168,7 @@ fn run_and_return(
|
||||
winit::event::Event::UserEvent(UserEvent::RequestRepaint {
|
||||
when,
|
||||
frame_nr,
|
||||
window_id,
|
||||
id: window_id,
|
||||
}) => {
|
||||
if winit_app.frame_nr() == *frame_nr {
|
||||
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 {
|
||||
when,
|
||||
frame_nr,
|
||||
window_id,
|
||||
id: window_id,
|
||||
}) => {
|
||||
if winit_app.frame_nr() == frame_nr {
|
||||
if let Some(window_id) = winit_app.get_window_winit_id(window_id) {
|
||||
@@ -462,8 +462,8 @@ mod glow_integration {
|
||||
builder: ViewportBuilder,
|
||||
gl_surface: Option<glutin::surface::Surface<glutin::surface::WindowSurface>>,
|
||||
window: Option<Arc<RwLock<winit::window::Window>>>,
|
||||
window_id: u64,
|
||||
parent_id: u64,
|
||||
window_id: ViewportId,
|
||||
parent_id: ViewportId,
|
||||
render: Option<Arc<Box<ViewportRender>>>,
|
||||
pub egui_winit: Option<egui_winit::State>,
|
||||
}
|
||||
@@ -487,11 +487,13 @@ mod glow_integration {
|
||||
current_gl_context: Option<glutin::context::PossiblyCurrentContext>,
|
||||
not_current_gl_context: Option<glutin::context::NotCurrentContext>,
|
||||
|
||||
windows: HashMap<u64, Arc<RwLock<Window>>>,
|
||||
window_maps: HashMap<winit::window::WindowId, u64>,
|
||||
windows: HashMap<ViewportId, Arc<RwLock<Window>>>,
|
||||
window_maps: HashMap<winit::window::WindowId, ViewportId>,
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe impl Sync for GlutinWindowContext {}
|
||||
#[allow(unsafe_code)]
|
||||
unsafe impl Send for GlutinWindowContext {}
|
||||
|
||||
impl GlutinWindowContext {
|
||||
@@ -599,20 +601,20 @@ mod glow_integration {
|
||||
|
||||
let mut window_maps = HashMap::default();
|
||||
if let Some(window) = &window {
|
||||
window_maps.insert(window.id(), 0);
|
||||
window_maps.insert(window.id(), ViewportId::MAIN);
|
||||
}
|
||||
|
||||
let mut windows = HashMap::default();
|
||||
windows.insert(
|
||||
0,
|
||||
ViewportId::MAIN,
|
||||
Arc::new(RwLock::new(Window {
|
||||
builder: window_builder,
|
||||
gl_surface: None,
|
||||
window: window.map(|w| Arc::new(RwLock::new(w))),
|
||||
window_id: 0,
|
||||
window_id: ViewportId::MAIN,
|
||||
egui_winit: None,
|
||||
render: None,
|
||||
parent_id: 0,
|
||||
parent_id: ViewportId::MAIN,
|
||||
})),
|
||||
);
|
||||
|
||||
@@ -739,18 +741,22 @@ mod glow_integration {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn window(&self, window_id: u64) -> Arc<RwLock<Window>> {
|
||||
fn window(&self, viewport_id: ViewportId) -> Arc<RwLock<Window>> {
|
||||
self.windows
|
||||
.get(&window_id)
|
||||
.get(&viewport_id)
|
||||
.map(|w| w.clone())
|
||||
.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 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();
|
||||
if let Some(gl_surface) = &window.gl_surface {
|
||||
self.current_gl_context = Some(
|
||||
@@ -788,7 +794,7 @@ mod glow_integration {
|
||||
// re-initializing the `GlowWinitRunning` state on Android if the application
|
||||
// suspends and resumes.
|
||||
app_creator: Option<epi::AppCreator>,
|
||||
is_focused: Arc<RwLock<Option<u64>>>,
|
||||
is_focused: Arc<RwLock<Option<ViewportId>>>,
|
||||
}
|
||||
|
||||
impl GlowWinitApp {
|
||||
@@ -804,7 +810,7 @@ mod glow_integration {
|
||||
native_options,
|
||||
running: Arc::new(RwLock::new(None)),
|
||||
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)?;
|
||||
|
||||
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();
|
||||
if let Some(window) = &window.window {
|
||||
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));
|
||||
|
||||
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,
|
||||
);
|
||||
let mut integration = epi_integration::EpiIntegration::new(
|
||||
event_loop,
|
||||
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,
|
||||
&self.app_name,
|
||||
&self.native_options,
|
||||
@@ -883,7 +901,7 @@ mod glow_integration {
|
||||
);
|
||||
#[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();
|
||||
integration.init_accesskit(
|
||||
window.egui_winit.as_mut().unwrap(),
|
||||
@@ -901,7 +919,7 @@ mod glow_integration {
|
||||
integration.egui_ctx.set_desktop(true);
|
||||
|
||||
gl_window
|
||||
.window(0)
|
||||
.window(ViewportId::MAIN)
|
||||
.read()
|
||||
.window
|
||||
.as_ref()
|
||||
@@ -910,7 +928,7 @@ mod glow_integration {
|
||||
.set_ime_allowed(true);
|
||||
if self.native_options.mouse_passthrough {
|
||||
gl_window
|
||||
.window(0)
|
||||
.window(ViewportId::MAIN)
|
||||
.read()
|
||||
.window
|
||||
.as_ref()
|
||||
@@ -931,7 +949,7 @@ mod glow_integration {
|
||||
event_loop_proxy
|
||||
.lock()
|
||||
.send_event(UserEvent::RequestRepaint {
|
||||
window_id: info.window_id,
|
||||
id: info.viewport_id,
|
||||
when,
|
||||
frame_nr,
|
||||
})
|
||||
@@ -943,7 +961,7 @@ mod glow_integration {
|
||||
.expect("Single-use AppCreator has unexpectedly already been taken");
|
||||
let mut app;
|
||||
{
|
||||
let window = gl_window.window(0);
|
||||
let window = gl_window.window(ViewportId::MAIN);
|
||||
let window = &mut *window.write();
|
||||
app = app_creator(&epi::CreationContext {
|
||||
egui_ctx: integration.egui_ctx.clone(),
|
||||
@@ -995,7 +1013,7 @@ mod glow_integration {
|
||||
viewport_id,
|
||||
parent_viewport_id,
|
||||
|ctx| {
|
||||
render(ctx, viewport_id, parent_viewport_id);
|
||||
render(ctx);
|
||||
},
|
||||
);
|
||||
let glutin = &mut *glutin.write();
|
||||
@@ -1065,7 +1083,7 @@ mod glow_integration {
|
||||
return;
|
||||
}
|
||||
}
|
||||
render(&egui_ctx, 0, 0);
|
||||
render(&egui_ctx);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1083,14 +1101,13 @@ mod glow_integration {
|
||||
fn process_viewport_builders(
|
||||
glutin_ctx: Arc<RwLock<GlutinWindowContext>>,
|
||||
mut viewports: Vec<(
|
||||
u64,
|
||||
u64,
|
||||
ViewportId,
|
||||
ViewportId,
|
||||
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![0];
|
||||
let mut active_viewports_ids = vec![ViewportId::MAIN];
|
||||
|
||||
viewports.retain_mut(|(id, _, builder, render)| {
|
||||
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| {
|
||||
if let Some(window) = r.glutin_ctx.read().windows.get(&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
|
||||
.read()
|
||||
.as_ref()
|
||||
@@ -1203,7 +1220,7 @@ mod glow_integration {
|
||||
&running
|
||||
.glutin_ctx
|
||||
.read()
|
||||
.window(0)
|
||||
.window(ViewportId::MAIN)
|
||||
.read()
|
||||
.window
|
||||
.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
|
||||
{
|
||||
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) {
|
||||
win.read()
|
||||
.window
|
||||
@@ -1485,7 +1502,7 @@ mod glow_integration {
|
||||
.unwrap()
|
||||
.glutin_ctx
|
||||
.read()
|
||||
.window(0)
|
||||
.window(ViewportId::MAIN)
|
||||
.read()
|
||||
.window
|
||||
.as_ref()
|
||||
@@ -1584,7 +1601,13 @@ mod glow_integration {
|
||||
None
|
||||
}
|
||||
})
|
||||
.flat_map(|id| if id == 0 { Some(()) } else { None })
|
||||
.flat_map(|id| {
|
||||
if id == ViewportId::MAIN {
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.count()
|
||||
== 1
|
||||
&& running.integration.read().should_close() =>
|
||||
@@ -1692,7 +1715,6 @@ mod wgpu_integration {
|
||||
use std::sync::Arc;
|
||||
|
||||
use egui::ViewportRender;
|
||||
use winit::window::ResizeDirection;
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -1701,12 +1723,12 @@ mod wgpu_integration {
|
||||
Arc<
|
||||
RwLock<
|
||||
HashMap<
|
||||
u64,
|
||||
ViewportId,
|
||||
(
|
||||
Option<Arc<RwLock<winit::window::Window>>>,
|
||||
Arc<RwLock<Option<egui_winit::State>>>,
|
||||
Option<Arc<Box<ViewportRender>>>,
|
||||
u64,
|
||||
ViewportId,
|
||||
ViewportBuilder,
|
||||
),
|
||||
>,
|
||||
@@ -1714,19 +1736,21 @@ mod wgpu_integration {
|
||||
>,
|
||||
);
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe impl Send for Windows {}
|
||||
#[allow(unsafe_code)]
|
||||
unsafe impl Sync for Windows {}
|
||||
|
||||
impl std::ops::Deref for Windows {
|
||||
type Target = Arc<
|
||||
RwLock<
|
||||
HashMap<
|
||||
u64,
|
||||
ViewportId,
|
||||
(
|
||||
Option<Arc<RwLock<winit::window::Window>>>,
|
||||
Arc<RwLock<Option<egui_winit::State>>>,
|
||||
Option<Arc<Box<ViewportRender>>>,
|
||||
u64,
|
||||
ViewportId,
|
||||
ViewportBuilder,
|
||||
),
|
||||
>,
|
||||
@@ -1746,7 +1770,7 @@ mod wgpu_integration {
|
||||
integration: Arc<RwLock<epi_integration::EpiIntegration>>,
|
||||
app: Box<dyn epi::App>,
|
||||
windows: Windows,
|
||||
windows_id: HashMap<winit::window::WindowId, u64>,
|
||||
windows_id: HashMap<winit::window::WindowId, ViewportId>,
|
||||
}
|
||||
|
||||
struct WgpuWinitApp {
|
||||
@@ -1758,7 +1782,7 @@ mod wgpu_integration {
|
||||
|
||||
/// 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.
|
||||
is_focused: Arc<RwLock<Option<u64>>>,
|
||||
is_focused: Arc<RwLock<Option<ViewportId>>>,
|
||||
}
|
||||
|
||||
impl WgpuWinitApp {
|
||||
@@ -1780,7 +1804,7 @@ mod wgpu_integration {
|
||||
native_options,
|
||||
running: None,
|
||||
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((window, _, _, _, _)) = running.windows.read().get(&id) {
|
||||
window.as_ref().map(|w| {
|
||||
@@ -1856,7 +1880,7 @@ mod wgpu_integration {
|
||||
),
|
||||
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();
|
||||
|
||||
@@ -1904,7 +1928,7 @@ mod wgpu_integration {
|
||||
.send_event(UserEvent::RequestRepaint {
|
||||
when,
|
||||
frame_nr,
|
||||
window_id: info.window_id,
|
||||
id: info.viewport_id,
|
||||
})
|
||||
.ok();
|
||||
});
|
||||
@@ -1928,16 +1952,16 @@ mod wgpu_integration {
|
||||
}
|
||||
|
||||
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())));
|
||||
windows.write().insert(
|
||||
0,
|
||||
ViewportId::MAIN,
|
||||
(
|
||||
Some(Arc::new(RwLock::new(window))),
|
||||
Arc::new(RwLock::new(Some(state))),
|
||||
None,
|
||||
0,
|
||||
ViewportId::MAIN,
|
||||
builder,
|
||||
),
|
||||
);
|
||||
@@ -1966,7 +1990,7 @@ mod wgpu_integration {
|
||||
viewport_id,
|
||||
parent_viewport_id,
|
||||
|ctx| {
|
||||
render(ctx, viewport_id, parent_viewport_id);
|
||||
render(ctx);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1998,7 +2022,7 @@ mod wgpu_integration {
|
||||
}
|
||||
|
||||
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)| {
|
||||
if let Some(w) = _windows.write().get_mut(id) {
|
||||
@@ -2027,7 +2051,7 @@ mod wgpu_integration {
|
||||
return;
|
||||
}
|
||||
}
|
||||
render(&egui_ctx, 0, 0);
|
||||
render(&egui_ctx);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -2078,7 +2102,7 @@ mod wgpu_integration {
|
||||
.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| {
|
||||
r.windows
|
||||
.read()
|
||||
@@ -2089,7 +2113,9 @@ mod wgpu_integration {
|
||||
|
||||
fn save_and_destroy(&mut self) {
|
||||
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
|
||||
.integration
|
||||
.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![]};
|
||||
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) {
|
||||
window.0.as_ref().map(|w| w.read().request_redraw());
|
||||
}
|
||||
@@ -2188,7 +2215,7 @@ mod wgpu_integration {
|
||||
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)| {
|
||||
if let Some(w) = windows.write().get_mut(id) {
|
||||
@@ -2219,7 +2246,7 @@ mod wgpu_integration {
|
||||
.write()
|
||||
.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];
|
||||
for repaint_after in repaint_after {
|
||||
@@ -2280,14 +2307,14 @@ mod wgpu_integration {
|
||||
Ok(match event {
|
||||
winit::event::Event::Resumed => {
|
||||
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(
|
||||
event_loop,
|
||||
running.integration.read().frame.storage(),
|
||||
&self.app_name,
|
||||
&self.native_options,
|
||||
)?;
|
||||
self.set_window(0)?;
|
||||
self.set_window(ViewportId::MAIN)?;
|
||||
}
|
||||
} else {
|
||||
let storage = epi_integration::create_storage(
|
||||
@@ -2310,7 +2337,7 @@ mod wgpu_integration {
|
||||
.unwrap()
|
||||
.windows
|
||||
.read()
|
||||
.get(&0)
|
||||
.get(&ViewportId::MAIN)
|
||||
.unwrap()
|
||||
.0
|
||||
.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
|
||||
.as_ref()
|
||||
.and_then(|r| r.windows_id.get(id).cloned())
|
||||
|
||||
@@ -36,6 +36,7 @@ winit = ["dep:winit"]
|
||||
|
||||
|
||||
[dependencies]
|
||||
egui = { version = "0.22.0", path = "../egui", default-features = false }
|
||||
epaint = { version = "0.22.0", path = "../epaint", default-features = false, features = [
|
||||
"bytemuck",
|
||||
] }
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use egui::ViewportId;
|
||||
use epaint::ahash::HashMap;
|
||||
|
||||
use crate::{renderer, RenderState, SurfaceErrorAction, WgpuConfiguration};
|
||||
@@ -85,7 +86,7 @@ pub struct Painter {
|
||||
|
||||
instance: wgpu::Instance,
|
||||
render_state: Option<RenderState>,
|
||||
surfaces: HashMap<u64, SurfaceState>,
|
||||
surfaces: HashMap<ViewportId, SurfaceState>,
|
||||
}
|
||||
|
||||
unsafe impl Send for Painter {}
|
||||
@@ -190,7 +191,7 @@ impl Painter {
|
||||
/// If the provided wgpu configuration does not match an available device.
|
||||
pub async fn set_window(
|
||||
&mut self,
|
||||
viewport_id: u64,
|
||||
viewport_id: ViewportId,
|
||||
window: Option<&winit::window::Window>,
|
||||
) -> Result<(), crate::WgpuError> {
|
||||
match window {
|
||||
@@ -274,7 +275,7 @@ impl Painter {
|
||||
|
||||
fn resize_and_generate_depth_texture_view_and_msaa_view(
|
||||
&mut self,
|
||||
viewport_id: u64,
|
||||
viewport_id: ViewportId,
|
||||
width_in_pixels: u32,
|
||||
height_in_pixels: u32,
|
||||
) {
|
||||
@@ -334,7 +335,7 @@ impl Painter {
|
||||
|
||||
pub fn on_window_resized(
|
||||
&mut self,
|
||||
viewport_id: u64,
|
||||
viewport_id: ViewportId,
|
||||
width_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.
|
||||
pub fn paint_and_update_textures(
|
||||
&mut self,
|
||||
viewport_id: u64,
|
||||
viewport_id: ViewportId,
|
||||
pixels_per_point: f32,
|
||||
clear_color: [f32; 4],
|
||||
clipped_primitives: &[epaint::ClippedPrimitive],
|
||||
@@ -618,9 +619,9 @@ impl Painter {
|
||||
screenshot
|
||||
}
|
||||
|
||||
pub fn clean_surfaces(&mut self, avalibile_viewports: Vec<u64>) {
|
||||
pub fn clean_surfaces(&mut self, avalibile_viewports: &[ViewportId]) {
|
||||
self.surfaces
|
||||
.retain(|id, _| avalibile_viewports.contains(id))
|
||||
.retain(|id, _| avalibile_viewports.contains(id));
|
||||
}
|
||||
|
||||
#[allow(clippy::unused_self)]
|
||||
|
||||
@@ -16,7 +16,7 @@ pub use accesskit_winit;
|
||||
pub use egui;
|
||||
#[cfg(feature = "accesskit")]
|
||||
use egui::accesskit;
|
||||
use egui::{mutex::RwLock, ViewportCommand};
|
||||
use egui::{mutex::RwLock, ViewportCommand, ViewportId};
|
||||
pub use winit;
|
||||
|
||||
pub mod clipboard;
|
||||
@@ -905,9 +905,9 @@ fn translate_cursor(cursor_icon: egui::CursorIcon) -> Option<winit::window::Curs
|
||||
}
|
||||
|
||||
pub fn process_viewport_commands(
|
||||
commands: Vec<(u64, ViewportCommand)>,
|
||||
focused: Option<u64>,
|
||||
get_window: impl Fn(u64) -> Option<Arc<RwLock<winit::window::Window>>>,
|
||||
commands: Vec<(ViewportId, ViewportCommand)>,
|
||||
focused: Option<ViewportId>,
|
||||
get_window: impl Fn(ViewportId) -> Option<Arc<RwLock<winit::window::Window>>>,
|
||||
) {
|
||||
use winit::dpi::PhysicalSize;
|
||||
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));
|
||||
}
|
||||
|
||||
return ctx.create_viewport_sync(
|
||||
window_builder,
|
||||
move |ctx, viewport_id, parent_viewport_id| {
|
||||
let mut op = is_open;
|
||||
let open = if show_close_button {
|
||||
Some(&mut op)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let scroll = scroll.clone();
|
||||
let title = title.clone();
|
||||
let frame = frame
|
||||
.unwrap_or_else(|| Frame::window(&ctx.style()))
|
||||
.outer_margin(0.0)
|
||||
.shadow(Shadow::NONE)
|
||||
.stroke(Stroke::new(
|
||||
1.0,
|
||||
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)
|
||||
return ctx.create_viewport_sync(window_builder, move |ctx| {
|
||||
let mut op = is_open;
|
||||
let open = if show_close_button {
|
||||
Some(&mut op)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let scroll = scroll.clone();
|
||||
let title = title.clone();
|
||||
let frame = frame
|
||||
.unwrap_or_else(|| Frame::window(&ctx.style()))
|
||||
.outer_margin(0.0)
|
||||
.shadow(Shadow::NONE)
|
||||
.stroke(Stroke::new(
|
||||
1.0,
|
||||
if ctx.input(|i| i.focused) {
|
||||
Color32::BLUE
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Color32::BROWN
|
||||
},
|
||||
));
|
||||
|
||||
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);
|
||||
}
|
||||
area.show_open_close_animation(ctx, &frame, is_open);
|
||||
|
||||
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 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(
|
||||
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;
|
||||
paint_resize_corner(
|
||||
&mut area_content_ui,
|
||||
&possible,
|
||||
outer_rect,
|
||||
frame_stroke,
|
||||
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,
|
||||
);
|
||||
|
||||
// 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(viewport_id, ViewportCommand::Drag);
|
||||
}
|
||||
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 {
|
||||
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(
|
||||
&mut area_content_ui,
|
||||
outer_rect,
|
||||
interaction,
|
||||
ctx.style().visuals.widgets.active,
|
||||
hover_interaction,
|
||||
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());
|
||||
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);
|
||||
}
|
||||
let full_response = area.end(ctx, area_content_ui);
|
||||
|
||||
return Some(InnerResponse {
|
||||
inner: content_inner,
|
||||
response: full_response,
|
||||
});
|
||||
},
|
||||
);
|
||||
if !collapsing.is_open() {
|
||||
let size = ctx.round_vec_to_pixels(full_response.rect.size());
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -849,234 +842,230 @@ impl<'open> Window<'open> {
|
||||
window_builder.max_inner_size = Some((max_size.x as u32, max_size.y as u32));
|
||||
}
|
||||
|
||||
ctx.create_viewport(
|
||||
window_builder,
|
||||
move |ctx, viewport_id, parent_viewport_id| {
|
||||
let mut op = is_open;
|
||||
let open = if show_close_button {
|
||||
Some(&mut op)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let scroll = scroll.clone();
|
||||
let title = title.clone();
|
||||
let frame = frame
|
||||
.unwrap_or_else(|| Frame::window(&ctx.style()))
|
||||
.outer_margin(0.0)
|
||||
.shadow(Shadow::NONE)
|
||||
.stroke(Stroke::new(
|
||||
1.0,
|
||||
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)
|
||||
ctx.create_viewport(window_builder, move |ctx| {
|
||||
let mut op = is_open;
|
||||
let open = if show_close_button {
|
||||
Some(&mut op)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let scroll = scroll.clone();
|
||||
let title = title.clone();
|
||||
let frame = frame
|
||||
.unwrap_or_else(|| Frame::window(&ctx.style()))
|
||||
.outer_margin(0.0)
|
||||
.shadow(Shadow::NONE)
|
||||
.stroke(Stroke::new(
|
||||
1.0,
|
||||
if ctx.input(|i| i.focused) {
|
||||
Color32::BLUE
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Color32::BROWN
|
||||
},
|
||||
));
|
||||
|
||||
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);
|
||||
}
|
||||
area.show_open_close_animation(ctx, &frame, is_open);
|
||||
|
||||
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 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(
|
||||
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;
|
||||
paint_resize_corner(
|
||||
&mut area_content_ui,
|
||||
&possible,
|
||||
outer_rect,
|
||||
frame_stroke,
|
||||
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,
|
||||
);
|
||||
|
||||
// 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 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);
|
||||
}
|
||||
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 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);
|
||||
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(
|
||||
&mut area_content_ui,
|
||||
outer_rect,
|
||||
interaction,
|
||||
ctx.style().visuals.widgets.active,
|
||||
hover_interaction,
|
||||
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() {
|
||||
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),
|
||||
);
|
||||
}
|
||||
if !collapsing.is_open() {
|
||||
let size = ctx.round_vec_to_pixels(full_response.rect.size());
|
||||
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(
|
||||
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);
|
||||
}
|
||||
},
|
||||
);
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ pub struct RequestRepaintInfo {
|
||||
/// triggered the painting of the next frame.
|
||||
pub current_frame_nr: u64,
|
||||
|
||||
/// This is used to specify what window to redraw
|
||||
pub window_id: u64,
|
||||
/// This is used to specify what viewport that should be redraw
|
||||
pub viewport_id: ViewportId,
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -60,10 +60,10 @@ struct Repaint {
|
||||
/// even if there's no new events.
|
||||
///
|
||||
/// 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.
|
||||
repaint_requests: HashMap<u64, u32>,
|
||||
repaint_requests: HashMap<ViewportId, u32>,
|
||||
request_repaint_callback: Option<Box<dyn Fn(RequestRepaintInfo) + Send + Sync>>,
|
||||
|
||||
requested_repaint_last_frame: bool,
|
||||
@@ -72,9 +72,9 @@ struct Repaint {
|
||||
impl Default for Repaint {
|
||||
fn default() -> Self {
|
||||
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();
|
||||
repaint_requests.insert(0, 1);
|
||||
repaint_requests.insert(ViewportId::MAIN, 1);
|
||||
Self {
|
||||
frame_nr: 0,
|
||||
repaint_after,
|
||||
@@ -88,11 +88,11 @@ impl Default for Repaint {
|
||||
}
|
||||
|
||||
impl Repaint {
|
||||
fn request_repaint(&mut self, window_id: u64) {
|
||||
self.request_repaint_after(std::time::Duration::ZERO, window_id);
|
||||
fn request_repaint(&mut self, viewport_id: ViewportId) {
|
||||
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 {
|
||||
// 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.
|
||||
@@ -114,14 +114,14 @@ impl Repaint {
|
||||
let info = RequestRepaintInfo {
|
||||
after,
|
||||
current_frame_nr: self.frame_nr,
|
||||
window_id: viewport_id,
|
||||
viewport_id,
|
||||
};
|
||||
(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.
|
||||
self.repaint_after.remove(&viewport_id);
|
||||
}
|
||||
@@ -129,9 +129,9 @@ impl Repaint {
|
||||
// returns how long to wait until repaint
|
||||
fn end_frame(
|
||||
&mut self,
|
||||
viewport_id: u64,
|
||||
viewports: Vec<u64>,
|
||||
) -> Vec<(u64, std::time::Duration)> {
|
||||
viewport_id: ViewportId,
|
||||
viewports: Vec<ViewportId>,
|
||||
) -> Vec<(ViewportId, std::time::Duration)> {
|
||||
// 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.
|
||||
let repaint_after = if self
|
||||
@@ -180,17 +180,17 @@ struct ContextImpl {
|
||||
|
||||
os: OperatingSystem,
|
||||
|
||||
input: HashMap<u64, InputState>,
|
||||
input: HashMap<ViewportId, InputState>,
|
||||
|
||||
/// 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
|
||||
frame_stack: Vec<(u64, u64)>,
|
||||
/// Viewport Id, Parent Viewport Id
|
||||
frame_stack: Vec<(ViewportId, ViewportId)>,
|
||||
|
||||
// The output of a frame:
|
||||
graphics: HashMap<u64, GraphicLayers>,
|
||||
output: HashMap<u64, PlatformOutput>,
|
||||
graphics: HashMap<ViewportId, GraphicLayers>,
|
||||
output: HashMap<ViewportId, PlatformOutput>,
|
||||
|
||||
paint_stats: PaintStats,
|
||||
|
||||
@@ -200,19 +200,23 @@ struct ContextImpl {
|
||||
String,
|
||||
(
|
||||
ViewportBuilder,
|
||||
u64,
|
||||
u64,
|
||||
ViewportId,
|
||||
ViewportId,
|
||||
bool,
|
||||
Option<Arc<Box<ViewportRender>>>,
|
||||
),
|
||||
>,
|
||||
viewport_commands: Vec<(u64, ViewportCommand)>,
|
||||
viewport_commands: Vec<(ViewportId, ViewportCommand)>,
|
||||
|
||||
render_sync: Option<
|
||||
Arc<
|
||||
Box<
|
||||
dyn for<'a> Fn(ViewportBuilder, u64, u64, Box<dyn FnOnce(&Context, u64, u64) + 'a>)
|
||||
+ Send
|
||||
dyn for<'a> Fn(
|
||||
ViewportBuilder,
|
||||
ViewportId,
|
||||
ViewportId,
|
||||
Box<dyn FnOnce(&Context) + 'a>,
|
||||
) + Send
|
||||
+ Sync,
|
||||
>,
|
||||
>,
|
||||
@@ -223,11 +227,11 @@ struct ContextImpl {
|
||||
|
||||
/// Written to during the frame.
|
||||
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
|
||||
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")]
|
||||
is_accesskit_enabled: bool,
|
||||
@@ -239,8 +243,8 @@ impl ContextImpl {
|
||||
fn begin_frame_mut(
|
||||
&mut self,
|
||||
mut new_raw_input: RawInput,
|
||||
viewport_id: u64,
|
||||
parent_viewport_id: u64,
|
||||
viewport_id: ViewportId,
|
||||
parent_viewport_id: ViewportId,
|
||||
) {
|
||||
// This is used to pause the last frame
|
||||
if !self.frame_stack.is_empty() {
|
||||
@@ -377,11 +381,17 @@ 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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -460,7 +470,7 @@ impl Default for Context {
|
||||
|
||||
s.write(|ctx| {
|
||||
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(
|
||||
&self,
|
||||
new_input: RawInput,
|
||||
viewport_id: u64,
|
||||
parent_viewport_id: u64,
|
||||
viewport_id: ViewportId,
|
||||
parent_viewport_id: ViewportId,
|
||||
run_ui: impl FnOnce(&Context),
|
||||
) -> FullOutput {
|
||||
self.begin_frame(new_input, viewport_id, parent_viewport_id);
|
||||
@@ -531,7 +541,12 @@ impl Context {
|
||||
/// let full_output = ctx.end_frame();
|
||||
/// // 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));
|
||||
}
|
||||
}
|
||||
@@ -568,7 +583,7 @@ impl Context {
|
||||
/// Read-write access to [`InputState`].
|
||||
#[inline]
|
||||
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`].
|
||||
@@ -1117,7 +1132,7 @@ impl Context {
|
||||
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))
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -1376,7 +1391,7 @@ impl Context {
|
||||
/// Call at the end of each frame.
|
||||
#[must_use]
|
||||
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.get_viewport_id(),
|
||||
std::mem::take(&mut ctx.layer_rects_this_frame),
|
||||
@@ -1386,7 +1401,7 @@ impl Context {
|
||||
.map(|(_, (_, id, _, _, _))| *id)
|
||||
.collect()
|
||||
});
|
||||
viewports.push(0);
|
||||
viewports.push(ViewportId::MAIN);
|
||||
|
||||
if self.input(|i| i.wants_repaint()) {
|
||||
self.request_repaint();
|
||||
@@ -1464,7 +1479,7 @@ impl Context {
|
||||
// This is used for,
|
||||
// If there are no viewport that contains the current viewpor that viewport needs to be destroyed!
|
||||
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() {
|
||||
avalibile_viewports.push(*id);
|
||||
}
|
||||
@@ -2139,17 +2154,23 @@ impl Context {
|
||||
|
||||
// Viewports
|
||||
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())
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
|
||||
pub fn set_render_sync_callback(
|
||||
&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
|
||||
+ Sync
|
||||
+ 'static,
|
||||
@@ -2166,14 +2187,14 @@ impl Context {
|
||||
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)))
|
||||
}
|
||||
|
||||
pub fn create_viewport(
|
||||
&self,
|
||||
viewport_builder: ViewportBuilder,
|
||||
func: impl Fn(&Context, u64, u64) + Send + Sync + 'static,
|
||||
func: impl Fn(&Context) + Send + Sync + 'static,
|
||||
) {
|
||||
if self.is_desktop() {
|
||||
self.write(|ctx| {
|
||||
@@ -2184,8 +2205,8 @@ impl Context {
|
||||
window.3 = true;
|
||||
window.4 = Some(Arc::new(Box::new(func)));
|
||||
} else {
|
||||
let id = ctx.viewport_counter + 1;
|
||||
ctx.viewport_counter = id;
|
||||
let id = ViewportId(ctx.viewport_counter + 1);
|
||||
ctx.viewport_counter += 1;
|
||||
ctx.viewports.insert(
|
||||
viewport_builder.title.clone(),
|
||||
(
|
||||
@@ -2199,18 +2220,18 @@ impl Context {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
func(self, 0, 0);
|
||||
func(self);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_viewport_sync<T>(
|
||||
&self,
|
||||
viewport_builder: ViewportBuilder,
|
||||
func: impl FnOnce(&Context, u64, u64) -> T,
|
||||
func: impl FnOnce(&Context) -> T,
|
||||
) -> T {
|
||||
if self.is_desktop() {
|
||||
let mut viewport_id = 0;
|
||||
let mut parent_viewport_id = 0;
|
||||
let mut viewport_id = ViewportId::MAIN;
|
||||
let mut parent_viewport_id = ViewportId::MAIN;
|
||||
let render_sync = self.write(|ctx| {
|
||||
viewport_id = ctx.get_viewport_id();
|
||||
if let Some(window) = ctx.viewports.get_mut(&viewport_builder.title) {
|
||||
@@ -2221,8 +2242,8 @@ impl Context {
|
||||
viewport_id = window.1;
|
||||
parent_viewport_id = window.2;
|
||||
} else {
|
||||
let id = ctx.viewport_counter + 1;
|
||||
ctx.viewport_counter = id;
|
||||
let id = ViewportId(ctx.viewport_counter + 1);
|
||||
ctx.viewport_counter += 1;
|
||||
ctx.viewports.insert(
|
||||
viewport_builder.title.clone(),
|
||||
(viewport_builder.clone(), id, viewport_id, true, None),
|
||||
@@ -2240,15 +2261,13 @@ impl Context {
|
||||
viewport_builder,
|
||||
viewport_id,
|
||||
parent_viewport_id,
|
||||
Box::new(move |context, viewport_id, parent_viewport_id| {
|
||||
*out = Some(func(context, viewport_id, parent_viewport_id))
|
||||
}),
|
||||
Box::new(move |context| *out = Some(func(context))),
|
||||
);
|
||||
}
|
||||
|
||||
out.unwrap()
|
||||
} else {
|
||||
func(self, 0, 0)
|
||||
func(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::Context;
|
||||
use crate::{ViewportBuilder, ViewportCommand, WidgetType};
|
||||
use crate::{ViewportId, ViewportRender};
|
||||
|
||||
/// 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,
|
||||
/// 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.
|
||||
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).
|
||||
///
|
||||
@@ -35,13 +35,13 @@ pub struct FullOutput {
|
||||
pub shapes: Vec<epaint::ClippedShape>,
|
||||
|
||||
pub viewports: Vec<(
|
||||
u64,
|
||||
u64,
|
||||
ViewportId,
|
||||
ViewportId,
|
||||
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 {
|
||||
|
||||
@@ -554,20 +554,30 @@ pub enum WidgetType {
|
||||
pub fn __run_test_ctx(mut run_ui: impl FnMut(&Context)) {
|
||||
let ctx = Context::default();
|
||||
ctx.set_fonts(FontDefinitions::empty()); // prevent fonts from being loaded (save CPU time)
|
||||
let _ = ctx.run(Default::default(), 0, 0, |ctx| {
|
||||
run_ui(ctx);
|
||||
});
|
||||
let _ = ctx.run(
|
||||
Default::default(),
|
||||
ViewportId::MAIN,
|
||||
ViewportId::MAIN,
|
||||
|ctx| {
|
||||
run_ui(ctx);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// For use in tests; especially doctests.
|
||||
pub fn __run_test_ui(mut add_contents: impl FnMut(&mut Ui)) {
|
||||
let ctx = Context::default();
|
||||
ctx.set_fonts(FontDefinitions::empty()); // prevent fonts from being loaded (save CPU time)
|
||||
let _ = ctx.run(Default::default(), 0, 0, |ctx| {
|
||||
crate::CentralPanel::default().show(ctx, |ui| {
|
||||
add_contents(ui);
|
||||
});
|
||||
});
|
||||
let _ = ctx.run(
|
||||
Default::default(),
|
||||
ViewportId::MAIN,
|
||||
ViewportId::MAIN,
|
||||
|ctx| {
|
||||
crate::CentralPanel::default().show(ctx, |ui| {
|
||||
add_contents(ui);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "accesskit")]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
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>,
|
||||
|
||||
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||
pub(crate) interactions: HashMap<u64, Interaction>,
|
||||
pub(crate) interactions: HashMap<ViewportId, Interaction>,
|
||||
|
||||
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||
pub(crate) interaction: Interaction,
|
||||
|
||||
// Current viewport
|
||||
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||
pub(crate) viewport_id: u64,
|
||||
pub(crate) viewport_id: ViewportId,
|
||||
|
||||
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||
pub(crate) window_interaction: Option<window::WindowInteraction>,
|
||||
|
||||
#[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))]
|
||||
pub(crate) drag_value: crate::widgets::drag_value::MonoState,
|
||||
@@ -94,7 +94,7 @@ pub struct Memory {
|
||||
pub(crate) areas: Areas,
|
||||
|
||||
#[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)?
|
||||
/// Could be a combo box, color picker, menu etc.
|
||||
@@ -370,7 +370,7 @@ impl Memory {
|
||||
&mut self,
|
||||
prev_input: &crate::input_state::InputState,
|
||||
new_input: &crate::data::input::RawInput,
|
||||
viewport_id: u64,
|
||||
viewport_id: ViewportId,
|
||||
) {
|
||||
self.viewport_id = viewport_id;
|
||||
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 {
|
||||
self.window_interactions
|
||||
.insert(viewport_id, window_interaction);
|
||||
@@ -403,7 +403,7 @@ impl Memory {
|
||||
pub(crate) fn end_frame(
|
||||
&mut self,
|
||||
input: &InputState,
|
||||
viewports: &[u64],
|
||||
viewports: &[ViewportId],
|
||||
used_ids: &IdMap<Rect>,
|
||||
) {
|
||||
self.caches.update();
|
||||
@@ -420,7 +420,7 @@ impl Memory {
|
||||
.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.areas = self.viewports_areas.remove(&viewport_id).unwrap();
|
||||
self.viewport_id = viewport_id;
|
||||
|
||||
@@ -1,11 +1,28 @@
|
||||
use std::sync::Arc;
|
||||
use std::fmt::Display;
|
||||
|
||||
use crate::Context;
|
||||
|
||||
/// This is used to render a viewport
|
||||
pub type ViewportRender = dyn Fn(&Context, u64, u64) + Sync + Send;
|
||||
/// This is used to send a command to a specific viewport
|
||||
///
|
||||
/// 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 title: String,
|
||||
pub name: Option<String>,
|
||||
|
||||
@@ -28,7 +28,7 @@ impl eframe::App for Custom3d {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
|
||||
@@ -21,7 +21,7 @@ impl eframe::App for EasyMarkApp {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
self.editor.panels(ctx);
|
||||
@@ -44,7 +44,7 @@ impl eframe::App for DemoApp {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
self.demo_windows.ui(ctx);
|
||||
@@ -67,7 +67,7 @@ impl eframe::App for FractalClockApp {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
egui::CentralPanel::default()
|
||||
@@ -95,7 +95,7 @@ impl eframe::App for ColorTestApp {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
@@ -270,7 +270,7 @@ impl eframe::App for WrapApp {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
|
||||
use egui::epaint::TextShape;
|
||||
use egui::{epaint::TextShape, ViewportId};
|
||||
use egui_demo_lib::LOREM_IPSUM_LONG;
|
||||
|
||||
pub fn criterion_benchmark(c: &mut Criterion) {
|
||||
@@ -13,24 +13,39 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
||||
// The most end-to-end benchmark.
|
||||
c.bench_function("demo_with_tessellate__realistic", |b| {
|
||||
b.iter(|| {
|
||||
let full_output = ctx.run(RawInput::default(), 0, 0, |ctx| {
|
||||
demo_windows.ui(ctx);
|
||||
});
|
||||
let full_output = ctx.run(
|
||||
RawInput::default(),
|
||||
ViewportId::MAIN,
|
||||
ViewportId::MAIN,
|
||||
|ctx| {
|
||||
demo_windows.ui(ctx);
|
||||
},
|
||||
);
|
||||
ctx.tessellate(full_output.shapes)
|
||||
});
|
||||
});
|
||||
|
||||
c.bench_function("demo_no_tessellate", |b| {
|
||||
b.iter(|| {
|
||||
ctx.run(RawInput::default(), 0, 0, |ctx| {
|
||||
demo_windows.ui(ctx);
|
||||
})
|
||||
ctx.run(
|
||||
RawInput::default(),
|
||||
ViewportId::MAIN,
|
||||
ViewportId::MAIN,
|
||||
|ctx| {
|
||||
demo_windows.ui(ctx);
|
||||
},
|
||||
)
|
||||
});
|
||||
});
|
||||
|
||||
let full_output = ctx.run(RawInput::default(), 0, 0, |ctx| {
|
||||
demo_windows.ui(ctx);
|
||||
});
|
||||
let full_output = ctx.run(
|
||||
RawInput::default(),
|
||||
ViewportId::MAIN,
|
||||
ViewportId::MAIN,
|
||||
|ctx| {
|
||||
demo_windows.ui(ctx);
|
||||
},
|
||||
);
|
||||
c.bench_function("demo_only_tessellate", |b| {
|
||||
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();
|
||||
c.bench_function("demo_full_no_tessellate", |b| {
|
||||
b.iter(|| {
|
||||
ctx.run(RawInput::default(), 0, 0, |ctx| {
|
||||
demo_windows.ui(ctx);
|
||||
})
|
||||
ctx.run(
|
||||
RawInput::default(),
|
||||
ViewportId::MAIN,
|
||||
ViewportId::MAIN,
|
||||
|ctx| {
|
||||
demo_windows.ui(ctx);
|
||||
},
|
||||
)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let ctx = egui::Context::default();
|
||||
let _ = ctx.run(RawInput::default(), 0, 0, |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");
|
||||
let _ = ctx.run(
|
||||
RawInput::default(),
|
||||
ViewportId::MAIN,
|
||||
ViewportId::MAIN,
|
||||
|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();
|
||||
ctx.begin_frame(RawInput::default(), 0, 0);
|
||||
ctx.begin_frame(RawInput::default(), ViewportId::MAIN, ViewportId::MAIN);
|
||||
|
||||
egui::CentralPanel::default().show(&ctx, |ui| {
|
||||
c.bench_function("Painter::rect", |b| {
|
||||
|
||||
@@ -19,6 +19,7 @@ pub mod syntax_highlighting;
|
||||
|
||||
pub use color_test::ColorTest;
|
||||
pub use demo::DemoWindows;
|
||||
use egui::ViewportId;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -68,9 +69,14 @@ fn test_egui_e2e() {
|
||||
|
||||
const NUM_FRAMES: usize = 5;
|
||||
for _ in 0..NUM_FRAMES {
|
||||
let full_output = ctx.run(raw_input.clone(), 0, 0, |ctx| {
|
||||
demo_windows.ui(ctx);
|
||||
});
|
||||
let full_output = ctx.run(
|
||||
raw_input.clone(),
|
||||
ViewportId::MAIN,
|
||||
ViewportId::MAIN,
|
||||
|ctx| {
|
||||
demo_windows.ui(ctx);
|
||||
},
|
||||
);
|
||||
let clipped_primitives = ctx.tessellate(full_output.shapes);
|
||||
assert!(!clipped_primitives.is_empty());
|
||||
}
|
||||
@@ -87,9 +93,14 @@ fn test_egui_zero_window_size() {
|
||||
|
||||
const NUM_FRAMES: usize = 5;
|
||||
for _ in 0..NUM_FRAMES {
|
||||
let full_output = ctx.run(raw_input.clone(), 0, 0, |ctx| {
|
||||
demo_windows.ui(ctx);
|
||||
});
|
||||
let full_output = ctx.run(
|
||||
raw_input.clone(),
|
||||
ViewportId::MAIN,
|
||||
ViewportId::MAIN,
|
||||
|ctx| {
|
||||
demo_windows.ui(ctx);
|
||||
},
|
||||
);
|
||||
let clipped_primitives = ctx.tessellate(full_output.shapes);
|
||||
assert!(
|
||||
clipped_primitives.is_empty(),
|
||||
|
||||
@@ -34,7 +34,7 @@ impl eframe::App for MyApp {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
|
||||
@@ -48,7 +48,7 @@ impl eframe::App for MyApp {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
|
||||
@@ -67,7 +67,7 @@ impl eframe::App for MyApp {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
|
||||
@@ -71,7 +71,7 @@ impl eframe::App for MyApp {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
egui::CentralPanel::default().show(ctx, content);
|
||||
|
||||
@@ -37,7 +37,7 @@ impl eframe::App for MyApp {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
custom_window_frame(ctx, frame, "egui with custom frame", |ui| {
|
||||
|
||||
@@ -28,7 +28,7 @@ impl eframe::App for MyApp {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
let promise = self.promise.get_or_insert_with(|| {
|
||||
|
||||
@@ -30,7 +30,7 @@ impl eframe::App for MyApp {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
|
||||
@@ -37,7 +37,7 @@ impl eframe::App for MyApp {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
|
||||
@@ -123,7 +123,7 @@ impl eframe::App for MyApp {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
egui::Window::new("Main thread").show(ctx, |ui| {
|
||||
|
||||
@@ -26,7 +26,7 @@ impl eframe::App for Content {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
|
||||
@@ -24,7 +24,7 @@ impl eframe::App for MyApp {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
|
||||
@@ -42,7 +42,7 @@ impl eframe::App for MyApp {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
|
||||
@@ -31,7 +31,7 @@ impl eframe::App for MyApp {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
|
||||
@@ -53,7 +53,7 @@ impl eframe::App for MyApp {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
|
||||
@@ -44,7 +44,7 @@ impl eframe::App for MyApp {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
|
||||
@@ -61,7 +61,7 @@ impl eframe::App for Application {
|
||||
render: Option<&ViewportRender>,
|
||||
) {
|
||||
if let Some(render) = render {
|
||||
render(ctx, ctx.get_viewport_id(), ctx.get_parent_viewport_id());
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
if let Some(request_at) = self.request_at {
|
||||
|
||||
@@ -39,7 +39,9 @@ fn main() {
|
||||
if show_sync {
|
||||
ctx.create_viewport_sync(
|
||||
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| {
|
||||
ui.label(format!("Frame: {}", ui.ctx().frame_nr()));
|
||||
ui.horizontal(|ui| {
|
||||
|
||||
Reference in New Issue
Block a user