Add a dummy warm-up frame to the demo app to pre-cache emojis
This commit is contained in:
parent
4202c4b6a9
commit
14a96ca5d0
14 changed files with 144 additions and 55 deletions
|
@ -870,36 +870,36 @@ async function init(input) {
|
|||
var ret = wasm.memory;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper2178 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 536, __wbg_adapter_26);
|
||||
imports.wbg.__wbindgen_closure_wrapper2332 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 607, __wbg_adapter_26);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper2179 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 536, __wbg_adapter_29);
|
||||
imports.wbg.__wbindgen_closure_wrapper2333 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 607, __wbg_adapter_29);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper2182 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 536, __wbg_adapter_32);
|
||||
imports.wbg.__wbindgen_closure_wrapper2336 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 607, __wbg_adapter_32);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper2184 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 536, __wbg_adapter_35);
|
||||
imports.wbg.__wbindgen_closure_wrapper2338 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 607, __wbg_adapter_35);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper2186 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 536, __wbg_adapter_38);
|
||||
imports.wbg.__wbindgen_closure_wrapper2340 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 607, __wbg_adapter_38);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper2188 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 536, __wbg_adapter_41);
|
||||
imports.wbg.__wbindgen_closure_wrapper2342 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 607, __wbg_adapter_41);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper2190 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 536, __wbg_adapter_44);
|
||||
imports.wbg.__wbindgen_closure_wrapper2344 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 607, __wbg_adapter_44);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper3036 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 608, __wbg_adapter_47);
|
||||
imports.wbg.__wbindgen_closure_wrapper3087 = function(arg0, arg1, arg2) {
|
||||
var ret = makeMutClosure(arg0, arg1, 649, __wbg_adapter_47);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
|
||||
|
|
Binary file not shown.
|
@ -35,7 +35,7 @@ impl State {
|
|||
|
||||
// Helper
|
||||
pub fn is_open(ctx: &Context, id: Id) -> Option<bool> {
|
||||
if ctx.memory().all_collpasing_are_open {
|
||||
if ctx.memory().everything_is_visible() {
|
||||
Some(true)
|
||||
} else {
|
||||
ctx.memory()
|
||||
|
@ -52,7 +52,11 @@ impl State {
|
|||
|
||||
/// 0 for closed, 1 for open, with tweening
|
||||
pub fn openness(&self, ctx: &Context, id: Id) -> f32 {
|
||||
ctx.animate_bool(id, self.open || ctx.memory().all_collpasing_are_open)
|
||||
if ctx.memory().everything_is_visible() {
|
||||
1.0
|
||||
} else {
|
||||
ctx.animate_bool(id, self.open)
|
||||
}
|
||||
}
|
||||
|
||||
/// Show contents if we are open, with a nice animation between closed and open
|
||||
|
|
|
@ -25,6 +25,8 @@ pub fn show_tooltip(ctx: &CtxRef, add_contents: impl FnOnce(&mut Ui)) {
|
|||
let position = position.min(ctx.input().screen_rect().right_bottom() - expected_size);
|
||||
let position = position.max(ctx.input().screen_rect().left_top());
|
||||
position
|
||||
} else if ctx.memory().everything_is_visible() {
|
||||
Pos2::default()
|
||||
} else {
|
||||
return; // No good place for a tooltip :(
|
||||
};
|
||||
|
|
|
@ -209,7 +209,7 @@ impl<'open> Window<'open> {
|
|||
with_title_bar,
|
||||
} = self;
|
||||
|
||||
if matches!(open, Some(false)) && !ctx.memory().all_windows_are_open {
|
||||
if matches!(open, Some(false)) && !ctx.memory().everything_is_visible() {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ pub(crate) struct FrameState {
|
|||
|
||||
/// How much space is used by panels.
|
||||
used_by_panels: Rect,
|
||||
|
||||
pub(crate) scroll_delta: Vec2,
|
||||
pub(crate) scroll_target: Option<(f32, Align)>,
|
||||
// TODO: move some things from `Memory` to here
|
||||
|
@ -56,7 +57,7 @@ impl Default for FrameState {
|
|||
}
|
||||
|
||||
impl FrameState {
|
||||
pub fn begin_frame(&mut self, input: &InputState) {
|
||||
fn begin_frame(&mut self, input: &InputState) {
|
||||
self.available_rect = input.screen_rect();
|
||||
self.unused_rect = input.screen_rect();
|
||||
self.used_by_panels = Rect::nothing();
|
||||
|
@ -717,6 +718,11 @@ impl Context {
|
|||
}
|
||||
animated_value
|
||||
}
|
||||
|
||||
/// Clear memory of any animations.
|
||||
pub fn clear_animations(&self) {
|
||||
*self.animation_manager.lock() = Default::default();
|
||||
}
|
||||
}
|
||||
|
||||
impl Context {
|
||||
|
|
|
@ -60,12 +60,8 @@ pub struct Memory {
|
|||
#[cfg_attr(feature = "serde", serde(skip))]
|
||||
pub(crate) tooltip_rect: Option<Rect>,
|
||||
|
||||
/// Useful for debugging, benchmarking etc.
|
||||
pub all_collpasing_are_open: bool,
|
||||
/// Useful for debugging, benchmarking etc.
|
||||
pub all_menus_are_open: bool,
|
||||
/// Useful for debugging, benchmarking etc.
|
||||
pub all_windows_are_open: bool,
|
||||
#[cfg_attr(feature = "serde", serde(skip))]
|
||||
everything_is_visible: bool,
|
||||
}
|
||||
|
||||
/// Say there is a button in a scroll area.
|
||||
|
@ -258,7 +254,7 @@ impl Memory {
|
|||
/// Only one can be be open at a time.
|
||||
impl Memory {
|
||||
pub fn is_popup_open(&mut self, popup_id: Id) -> bool {
|
||||
self.popup == Some(popup_id)
|
||||
self.popup == Some(popup_id) || self.everything_is_visible()
|
||||
}
|
||||
|
||||
pub fn open_popup(&mut self, popup_id: Id) {
|
||||
|
@ -276,6 +272,24 @@ impl Memory {
|
|||
self.open_popup(popup_id);
|
||||
}
|
||||
}
|
||||
|
||||
/// If true, all windows, menus, tooltips etc are to be visible at once.
|
||||
///
|
||||
/// This is useful for testing, benchmarking, pre-caching, etc.
|
||||
///
|
||||
/// Experimental feature!
|
||||
pub fn everything_is_visible(&self) -> bool {
|
||||
self.everything_is_visible
|
||||
}
|
||||
|
||||
/// If true, all windows, menus, tooltips etc are to be visible at once.
|
||||
///
|
||||
/// This is useful for testing, benchmarking, pre-caching, etc.
|
||||
///
|
||||
/// Experimental feature!
|
||||
pub fn set_everything_is_visible(&mut self, value: bool) {
|
||||
self.everything_is_visible = value;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
@ -94,7 +94,7 @@ fn menu_impl<'c>(
|
|||
bar_state.open_menu = Some(menu_id);
|
||||
}
|
||||
|
||||
if bar_state.open_menu == Some(menu_id) || ui.memory().all_menus_are_open {
|
||||
if bar_state.open_menu == Some(menu_id) || ui.ctx().memory().everything_is_visible() {
|
||||
let area = Area::new(menu_id)
|
||||
.order(Order::Foreground)
|
||||
.fixed_pos(button_response.rect.left_bottom());
|
||||
|
|
|
@ -139,7 +139,7 @@ impl Response {
|
|||
/// Show this UI if the item was hovered (i.e. a tooltip).
|
||||
/// If you call this multiple times the tooltips will stack underneath the previous ones.
|
||||
pub fn on_hover_ui(self, add_contents: impl FnOnce(&mut Ui)) -> Self {
|
||||
if self.hovered {
|
||||
if self.hovered || self.ctx.memory().everything_is_visible() {
|
||||
crate::containers::show_tooltip(&self.ctx, add_contents);
|
||||
}
|
||||
self
|
||||
|
|
|
@ -18,7 +18,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||
|
||||
{
|
||||
let mut ctx = egui::CtxRef::default();
|
||||
ctx.memory().all_collpasing_are_open = true; // expand the demo window with everything
|
||||
ctx.memory().set_everything_is_visible(true); // give us everything
|
||||
let mut demo_windows = egui_demo_lib::DemoWindows::default();
|
||||
|
||||
c.bench_function("demo_windows_full", |b| {
|
||||
|
@ -32,7 +32,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||
|
||||
{
|
||||
let mut ctx = egui::CtxRef::default();
|
||||
ctx.memory().all_collpasing_are_open = true; // expand the demo window with everything
|
||||
ctx.memory().set_everything_is_visible(true); // give us everything
|
||||
let mut demo_windows = egui_demo_lib::DemoWindows::default();
|
||||
ctx.begin_frame(raw_input.clone());
|
||||
demo_windows.ui(&ctx);
|
||||
|
|
|
@ -42,6 +42,10 @@ impl epi::App for WrapApp {
|
|||
epi::set_value(storage, epi::APP_KEY, self);
|
||||
}
|
||||
|
||||
fn warm_up_enabled(&self) -> bool {
|
||||
true // The example windows use a lot of emojis. Pre-cache them by running one frame where everything is open.
|
||||
}
|
||||
|
||||
fn update(&mut self, ctx: &egui::CtxRef, frame: &mut epi::Frame<'_>) {
|
||||
if let Some(web_info) = frame.info().web_info.as_ref() {
|
||||
if let Some(anchor) = web_info.web_location_hash.strip_prefix("#") {
|
||||
|
@ -91,14 +95,14 @@ impl epi::App for WrapApp {
|
|||
});
|
||||
|
||||
self.backend_panel.update(ctx, frame);
|
||||
if self.backend_panel.open {
|
||||
if self.backend_panel.open || ctx.memory().everything_is_visible() {
|
||||
egui::SidePanel::left("backend_panel", 150.0).show(ctx, |ui| {
|
||||
self.backend_panel.ui(ui, frame);
|
||||
});
|
||||
}
|
||||
|
||||
for (anchor, app) in self.apps.iter_mut() {
|
||||
if anchor == self.selected_anchor {
|
||||
if anchor == self.selected_anchor || ctx.memory().everything_is_visible() {
|
||||
app.update(ctx, frame);
|
||||
}
|
||||
}
|
||||
|
@ -192,19 +196,6 @@ impl BackendPanel {
|
|||
fn ui(&mut self, ui: &mut egui::Ui, frame: &mut epi::Frame<'_>) {
|
||||
ui.heading("💻 Backend");
|
||||
|
||||
if frame.is_web() {
|
||||
ui.label("Egui is an immediate mode GUI written in Rust, compiled to WebAssembly, rendered with WebGL.");
|
||||
ui.label(
|
||||
"Everything you see is rendered as textured triangles. There is no DOM. There are no HTML elements. \
|
||||
This is not JavaScript. This is Rust, running at 60 FPS. This is the web page, reinvented with game tech.");
|
||||
ui.label("This is also work in progress, and not ready for production... yet :)");
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Project home page:");
|
||||
ui.hyperlink("https://github.com/emilk/egui");
|
||||
});
|
||||
ui.separator();
|
||||
}
|
||||
|
||||
self.run_mode_ui(ui);
|
||||
|
||||
ui.separator();
|
||||
|
@ -219,8 +210,19 @@ impl BackendPanel {
|
|||
}
|
||||
}
|
||||
|
||||
if !frame.is_web() {
|
||||
ui.separator();
|
||||
|
||||
if frame.is_web() {
|
||||
ui.label("Egui is an immediate mode GUI written in Rust, compiled to WebAssembly, rendered with WebGL.");
|
||||
ui.label(
|
||||
"Everything you see is rendered as textured triangles. There is no DOM. There are no HTML elements. \
|
||||
This is not JavaScript. This is Rust, running at 60 FPS. This is the web page, reinvented with game tech.");
|
||||
ui.label("This is also work in progress, and not ready for production... yet :)");
|
||||
ui.horizontal_wrapped_for_text(egui::TextStyle::Body, |ui| {
|
||||
ui.label("Project home page:");
|
||||
ui.hyperlink("https://github.com/emilk/egui");
|
||||
});
|
||||
} else {
|
||||
if ui
|
||||
.button("📱 Phone Size")
|
||||
.on_hover_text("Resize the window to be small like a phone.")
|
||||
|
|
|
@ -90,6 +90,18 @@ fn create_storage(app_name: &str) -> Option<Box<dyn epi::Storage>> {
|
|||
}
|
||||
}
|
||||
|
||||
fn integration_info(
|
||||
display: &glium::Display,
|
||||
previous_frame_time: Option<f32>,
|
||||
) -> epi::IntegrationInfo {
|
||||
epi::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)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Run an egui app
|
||||
pub fn run(mut app: Box<dyn epi::App>) -> ! {
|
||||
let mut storage = create_storage(app.name());
|
||||
|
@ -113,6 +125,7 @@ pub fn run(mut app: Box<dyn epi::App>) -> ! {
|
|||
.as_mut()
|
||||
.and_then(|storage| epi::get_value(storage.as_ref(), EGUI_MEMORY_KEY))
|
||||
.unwrap_or_default();
|
||||
|
||||
app.setup(&ctx);
|
||||
|
||||
let mut input_state = GliumInputState::from_pixels_per_point(native_pixels_per_point(&display));
|
||||
|
@ -126,6 +139,36 @@ pub fn run(mut app: Box<dyn epi::App>) -> ! {
|
|||
|
||||
let http = std::sync::Arc::new(crate::http::GliumHttp {});
|
||||
|
||||
if app.warm_up_enabled() {
|
||||
// let warm_up_start = Instant::now();
|
||||
input_state.raw.time = Some(0.0);
|
||||
input_state.raw.screen_rect = Some(Rect::from_min_size(
|
||||
Default::default(),
|
||||
screen_size_in_pixels(&display) / input_state.raw.pixels_per_point.unwrap(),
|
||||
));
|
||||
ctx.begin_frame(input_state.raw.take());
|
||||
let mut app_output = epi::backend::AppOutput::default();
|
||||
let mut frame = epi::backend::FrameBuilder {
|
||||
info: integration_info(&display, None),
|
||||
tex_allocator: Some(&mut painter),
|
||||
http: http.clone(),
|
||||
output: &mut app_output,
|
||||
repaint_signal: repaint_signal.clone(),
|
||||
}
|
||||
.build();
|
||||
|
||||
let saved_memory = ctx.memory().clone();
|
||||
ctx.memory().set_everything_is_visible(true);
|
||||
app.update(&ctx, &mut frame);
|
||||
*ctx.memory() = saved_memory; // We don't want to remember that windows were huge.
|
||||
ctx.clear_animations();
|
||||
|
||||
let (egui_output, _paint_commands) = ctx.end_frame();
|
||||
handle_output(egui_output, &display, clipboard.as_mut());
|
||||
// TODO: handle app_output
|
||||
// eprintln!("Warmed up in {} ms", warm_up_start.elapsed().as_millis())
|
||||
}
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
let mut redraw = || {
|
||||
let frame_start = Instant::now();
|
||||
|
@ -138,12 +181,7 @@ pub fn run(mut app: Box<dyn epi::App>) -> ! {
|
|||
ctx.begin_frame(input_state.raw.take());
|
||||
let mut app_output = epi::backend::AppOutput::default();
|
||||
let mut frame = epi::backend::FrameBuilder {
|
||||
info: epi::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)),
|
||||
},
|
||||
info: integration_info(&display, previous_frame_time),
|
||||
tex_allocator: Some(&mut painter),
|
||||
http: http.clone(),
|
||||
output: &mut app_output,
|
||||
|
|
|
@ -179,6 +179,20 @@ impl AppRunner {
|
|||
self.web_backend.canvas_id()
|
||||
}
|
||||
|
||||
pub fn warm_up(&mut self) -> Result<(), JsValue> {
|
||||
if self.app.warm_up_enabled() {
|
||||
let saved_memory = self.web_backend.ctx.memory().clone();
|
||||
self.web_backend
|
||||
.ctx
|
||||
.memory()
|
||||
.set_everything_is_visible(true);
|
||||
self.logic()?;
|
||||
*self.web_backend.ctx.memory() = saved_memory; // We don't want to remember that windows were huge.
|
||||
self.web_backend.ctx.clear_animations();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn logic(&mut self) -> Result<(egui::Output, egui::PaintJobs), JsValue> {
|
||||
resize_canvas_to_screen_size(self.web_backend.canvas_id());
|
||||
let canvas_size = canvas_size_in_points(self.web_backend.canvas_id());
|
||||
|
@ -227,7 +241,8 @@ impl AppRunner {
|
|||
/// and start running the given app.
|
||||
pub fn start(canvas_id: &str, app: Box<dyn epi::App>) -> Result<AppRunnerRef, JsValue> {
|
||||
let backend = WebBackend::new(canvas_id)?;
|
||||
let runner = AppRunner::new(backend, app)?;
|
||||
let mut runner = AppRunner::new(backend, app)?;
|
||||
runner.warm_up()?;
|
||||
start_runner(runner)
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,14 @@ pub trait App {
|
|||
/// Optional.
|
||||
fn setup(&mut self, _ctx: &egui::CtxRef) {}
|
||||
|
||||
/// If `true` a warm-up call to [`Self::update`] will be issued where
|
||||
/// `ctx.memory().everything_is_visible()` will be set to `true`.
|
||||
///
|
||||
/// In this warm-up call, all paint commands will be ignored.
|
||||
fn warm_up_enabled(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// Called once on start. Allows you to restore state.
|
||||
fn load(&mut self, _storage: &dyn Storage) {}
|
||||
|
||||
|
|
Loading…
Reference in a new issue