[app] Simplify interface to egui::app::App
This commit is contained in:
parent
daa7a2bdb2
commit
7638ca9962
9 changed files with 66 additions and 56 deletions
|
@ -13,7 +13,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||
c.bench_function("demo_windows_minimal", |b| {
|
||||
b.iter(|| {
|
||||
ctx.begin_frame(raw_input.clone());
|
||||
demo_windows.ui(&ctx, &Default::default(), None);
|
||||
demo_windows.ui(&ctx, &Default::default(), &mut None);
|
||||
ctx.end_frame()
|
||||
})
|
||||
});
|
||||
|
@ -27,7 +27,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||
c.bench_function("demo_windows_full", |b| {
|
||||
b.iter(|| {
|
||||
ctx.begin_frame(raw_input.clone());
|
||||
demo_windows.ui(&ctx, &Default::default(), None);
|
||||
demo_windows.ui(&ctx, &Default::default(), &mut None);
|
||||
ctx.end_frame()
|
||||
})
|
||||
});
|
||||
|
|
|
@ -17,23 +17,31 @@ pub trait App {
|
|||
fn ui(
|
||||
&mut self,
|
||||
ctx: &std::sync::Arc<Context>,
|
||||
info: &BackendInfo,
|
||||
tex_allocator: Option<&mut dyn TextureAllocator>,
|
||||
) -> AppOutput;
|
||||
integration_context: &mut IntegrationContext<'_>,
|
||||
);
|
||||
|
||||
/// Called once on shutdown. Allows you to save state.
|
||||
fn on_exit(&mut self, _storage: &mut dyn Storage) {}
|
||||
}
|
||||
|
||||
pub struct IntegrationContext<'a> {
|
||||
/// Information about the integration.
|
||||
pub info: IntegrationInfo,
|
||||
/// A way to allocate textures (on integrations that support it).
|
||||
pub tex_allocator: Option<&'a mut dyn TextureAllocator>,
|
||||
/// Where the app can issue commands back to the integration.
|
||||
pub output: AppOutput,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct WebInfo {
|
||||
/// e.g. "#fragment" part of "www.example.com/index.html#fragment"
|
||||
pub web_location_hash: String,
|
||||
}
|
||||
|
||||
/// Information about the backend passed to the use app each frame.
|
||||
/// Information about the integration passed to the use app each frame.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BackendInfo {
|
||||
pub struct IntegrationInfo {
|
||||
/// If the app is running in a Web context, this returns information about the environment.
|
||||
pub web_info: Option<WebInfo>,
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ impl Context {
|
|||
pub fn available_rect(&self) -> Rect {
|
||||
self.available_rect
|
||||
.lock()
|
||||
.expect("Called `avaiblable_rect()` before `begin_frame()`")
|
||||
.expect("Called `available_rect()` before `begin_frame()`")
|
||||
}
|
||||
|
||||
pub fn memory(&self) -> MutexGuard<'_, Memory> {
|
||||
|
|
|
@ -183,11 +183,11 @@ pub struct DemoApp {
|
|||
}
|
||||
|
||||
impl DemoApp {
|
||||
fn backend_ui(&mut self, ui: &mut Ui, info: &app::BackendInfo) -> app::AppOutput {
|
||||
fn backend_ui(&mut self, ui: &mut Ui, integration_context: &mut app::IntegrationContext<'_>) {
|
||||
self.frame_history
|
||||
.on_new_frame(ui.input().time, info.cpu_usage);
|
||||
.on_new_frame(ui.input().time, integration_context.info.cpu_usage);
|
||||
|
||||
let is_web = info.web_info.is_some();
|
||||
let is_web = integration_context.info.web_info.is_some();
|
||||
|
||||
if is_web {
|
||||
ui.label("Egui is an immediate mode GUI written in Rust, compiled to WebAssembly, rendered with WebGL.");
|
||||
|
@ -210,18 +210,16 @@ impl DemoApp {
|
|||
|
||||
ui.separator();
|
||||
|
||||
let mut output = app::AppOutput::default();
|
||||
output.pixels_per_point = self.pixels_per_point_ui(ui, info);
|
||||
integration_context.output.pixels_per_point =
|
||||
self.pixels_per_point_ui(ui, &integration_context.info);
|
||||
|
||||
if !is_web {
|
||||
ui.separator();
|
||||
output.quit |= ui.button("Quit").clicked;
|
||||
integration_context.output.quit |= ui.button("Quit").clicked;
|
||||
}
|
||||
|
||||
output
|
||||
}
|
||||
|
||||
fn pixels_per_point_ui(&mut self, ui: &mut Ui, info: &app::BackendInfo) -> Option<f32> {
|
||||
fn pixels_per_point_ui(&mut self, ui: &mut Ui, info: &app::IntegrationInfo) -> Option<f32> {
|
||||
self.pixels_per_point = self
|
||||
.pixels_per_point
|
||||
.or(info.native_pixels_per_point)
|
||||
|
@ -276,10 +274,10 @@ impl app::App for DemoApp {
|
|||
fn ui(
|
||||
&mut self,
|
||||
ctx: &Arc<Context>,
|
||||
info: &app::BackendInfo,
|
||||
tex_allocator: Option<&mut dyn app::TextureAllocator>,
|
||||
) -> app::AppOutput {
|
||||
let web_location_hash = info
|
||||
integration_context: &mut crate::app::IntegrationContext<'_>,
|
||||
) {
|
||||
let web_location_hash = integration_context
|
||||
.info
|
||||
.web_info
|
||||
.as_ref()
|
||||
.map(|info| info.web_location_hash.clone())
|
||||
|
@ -292,27 +290,27 @@ impl app::App for DemoApp {
|
|||
};
|
||||
|
||||
let demo_environment = demos::DemoEnvironment {
|
||||
seconds_since_midnight: info.seconds_since_midnight,
|
||||
seconds_since_midnight: integration_context.info.seconds_since_midnight,
|
||||
link,
|
||||
};
|
||||
|
||||
self.demo_windows.ui(ctx, &demo_environment, tex_allocator);
|
||||
|
||||
let mut output = app::AppOutput::default();
|
||||
self.demo_windows.ui(
|
||||
ctx,
|
||||
&demo_environment,
|
||||
&mut integration_context.tex_allocator,
|
||||
);
|
||||
|
||||
crate::Window::new("Backend")
|
||||
.min_width(360.0)
|
||||
.scroll(false)
|
||||
.show(ctx, |ui| {
|
||||
output = self.backend_ui(ui, info);
|
||||
self.backend_ui(ui, integration_context);
|
||||
});
|
||||
|
||||
if self.run_mode == RunMode::Continuous {
|
||||
// Tell the backend to repaint as soon as possible
|
||||
ctx.request_repaint();
|
||||
}
|
||||
|
||||
output
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde_json")]
|
||||
|
|
|
@ -46,7 +46,7 @@ impl DemoWindows {
|
|||
&mut self,
|
||||
ctx: &Arc<Context>,
|
||||
env: &DemoEnvironment,
|
||||
tex_allocator: Option<&mut dyn app::TextureAllocator>,
|
||||
tex_allocator: &mut Option<&mut dyn app::TextureAllocator>,
|
||||
) {
|
||||
if self.previous_link != env.link {
|
||||
match env.link {
|
||||
|
@ -93,7 +93,7 @@ impl DemoWindows {
|
|||
&mut self,
|
||||
ctx: &Arc<Context>,
|
||||
env: &DemoEnvironment,
|
||||
mut tex_allocator: Option<&mut dyn app::TextureAllocator>,
|
||||
tex_allocator: &mut Option<&mut dyn app::TextureAllocator>,
|
||||
) {
|
||||
let Self {
|
||||
open_windows,
|
||||
|
@ -135,7 +135,7 @@ impl DemoWindows {
|
|||
.scroll(true)
|
||||
.open(&mut open_windows.color_test)
|
||||
.show(ctx, |ui| {
|
||||
color_test.ui(ui, &mut tex_allocator);
|
||||
color_test.ui(ui, tex_allocator);
|
||||
});
|
||||
|
||||
fractal_clock.window(
|
||||
|
|
|
@ -99,7 +99,7 @@ pub fn text_egui_e2e() {
|
|||
const NUM_FRAMES: usize = 5;
|
||||
for _ in 0..NUM_FRAMES {
|
||||
ctx.begin_frame(raw_input.clone());
|
||||
demo_windows.ui(&ctx, &Default::default(), None);
|
||||
demo_windows.ui(&ctx, &Default::default(), &mut None);
|
||||
let (_output, paint_jobs) = ctx.end_frame();
|
||||
assert!(!paint_jobs.is_empty());
|
||||
}
|
||||
|
|
|
@ -75,15 +75,19 @@ pub fn run(
|
|||
raw_input.screen_size =
|
||||
screen_size_in_pixels(&display) / raw_input.pixels_per_point.unwrap();
|
||||
|
||||
let backend_info = egui::app::BackendInfo {
|
||||
web_info: None,
|
||||
cpu_usage: previous_frame_time,
|
||||
seconds_since_midnight: Some(seconds_since_midnight()),
|
||||
native_pixels_per_point: Some(native_pixels_per_point(&display)),
|
||||
};
|
||||
|
||||
ctx.begin_frame(raw_input.take());
|
||||
let app_output = app.ui(&ctx, &backend_info, Some(&mut painter));
|
||||
let mut integration_context = egui::app::IntegrationContext {
|
||||
info: egui::app::IntegrationInfo {
|
||||
web_info: None,
|
||||
cpu_usage: previous_frame_time,
|
||||
seconds_since_midnight: Some(seconds_since_midnight()),
|
||||
native_pixels_per_point: Some(native_pixels_per_point(&display)),
|
||||
},
|
||||
tex_allocator: Some(&mut painter),
|
||||
output: Default::default(),
|
||||
};
|
||||
app.ui(&ctx, &mut integration_context);
|
||||
let app_output = integration_context.output;
|
||||
let (egui_output, paint_jobs) = ctx.end_frame();
|
||||
|
||||
let frame_time = (Instant::now() - egui_start).as_secs_f64() as f32;
|
||||
|
|
|
@ -150,21 +150,24 @@ impl AppRunner {
|
|||
resize_canvas_to_screen_size(self.web_backend.canvas_id());
|
||||
|
||||
let raw_input = self.web_input.new_frame(self.pixels_per_point);
|
||||
self.web_backend.begin_frame(raw_input);
|
||||
|
||||
let backend_info = egui::app::BackendInfo {
|
||||
web_info: Some(WebInfo {
|
||||
web_location_hash: location_hash().unwrap_or_default(),
|
||||
}),
|
||||
cpu_usage: self.web_backend.previous_frame_time,
|
||||
seconds_since_midnight: Some(seconds_since_midnight()),
|
||||
native_pixels_per_point: Some(native_pixels_per_point()),
|
||||
let mut integration_context = egui::app::IntegrationContext {
|
||||
info: egui::app::IntegrationInfo {
|
||||
web_info: Some(WebInfo {
|
||||
web_location_hash: location_hash().unwrap_or_default(),
|
||||
}),
|
||||
cpu_usage: self.web_backend.previous_frame_time,
|
||||
seconds_since_midnight: Some(seconds_since_midnight()),
|
||||
native_pixels_per_point: Some(native_pixels_per_point()),
|
||||
},
|
||||
tex_allocator: Some(&mut self.web_backend.painter),
|
||||
output: Default::default(),
|
||||
};
|
||||
|
||||
self.web_backend.begin_frame(raw_input);
|
||||
let egui_ctx = &self.web_backend.ctx;
|
||||
let app_output = self
|
||||
.app
|
||||
.ui(egui_ctx, &backend_info, Some(&mut self.web_backend.painter));
|
||||
self.app.ui(egui_ctx, &mut integration_context);
|
||||
let app_output = integration_context.output;
|
||||
let (egui_output, paint_jobs) = self.web_backend.end_frame()?;
|
||||
handle_output(&egui_output);
|
||||
|
||||
|
|
|
@ -16,9 +16,8 @@ impl egui::app::App for MyApp {
|
|||
fn ui(
|
||||
&mut self,
|
||||
ctx: &std::sync::Arc<egui::Context>,
|
||||
_info: &egui::app::BackendInfo,
|
||||
_tex_allocator: Option<&mut dyn egui::app::TextureAllocator>,
|
||||
) -> egui::app::AppOutput {
|
||||
_integration_context: &mut egui::app::IntegrationContext,
|
||||
) {
|
||||
let MyApp { my_string, value } = self;
|
||||
|
||||
// Example used in `README.md`.
|
||||
|
@ -30,8 +29,6 @@ impl egui::app::App for MyApp {
|
|||
ui.text_edit(my_string);
|
||||
ui.add(egui::Slider::f32(value, 0.0..=1.0).text("float"));
|
||||
});
|
||||
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn on_exit(&mut self, storage: &mut dyn egui::app::Storage) {
|
||||
|
|
Loading…
Reference in a new issue