Make frame delay on screenshots consistently one frame on web as well (#5482)

Native is already delayed by a frame because it calls
`handle_viewport_output` -> `egui_winit::process_viewport_commands`
after drawing. On web however, we process input including viewport
commands separately from drawing.
This adds an arbitrary frame delay mechanism for web and then uses this
with 1 frame delay always
This commit is contained in:
Andreas Reich 2024-12-16 15:03:01 +01:00 committed by GitHub
parent 3995491212
commit b1d2551e7e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 23 additions and 7 deletions

View File

@ -1,5 +1,4 @@
use egui::{TexturesDelta, UserData, ViewportCommand};
use std::mem;
use crate::{epi, App};
@ -17,8 +16,9 @@ pub struct AppRunner {
last_save_time: f64,
pub(crate) text_agent: TextAgent,
// If not empty, the painter should capture the next frame
screenshot_commands: Vec<UserData>,
// If not empty, the painter should capture n frames from now.
// zero means capture the exact next frame.
screenshot_commands_with_frame_delay: Vec<(UserData, usize)>,
// Output for the last run:
textures_delta: TexturesDelta,
@ -114,7 +114,7 @@ impl AppRunner {
needs_repaint,
last_save_time: now_sec(),
text_agent,
screenshot_commands: vec![],
screenshot_commands_with_frame_delay: vec![],
textures_delta: Default::default(),
clipped_primitives: None,
};
@ -236,7 +236,8 @@ impl AppRunner {
for command in viewport_output.commands {
match command {
ViewportCommand::Screenshot(user_data) => {
self.screenshot_commands.push(user_data);
self.screenshot_commands_with_frame_delay
.push((user_data, 1));
}
_ => {
// TODO(emilk): handle some of the commands
@ -259,12 +260,27 @@ impl AppRunner {
let clipped_primitives = std::mem::take(&mut self.clipped_primitives);
if let Some(clipped_primitives) = clipped_primitives {
let mut screenshot_commands = vec![];
self.screenshot_commands_with_frame_delay
.retain_mut(|(user_data, frame_delay)| {
if *frame_delay == 0 {
screenshot_commands.push(user_data.clone());
false
} else {
*frame_delay -= 1;
true
}
});
if !self.screenshot_commands_with_frame_delay.is_empty() {
self.egui_ctx().request_repaint();
}
if let Err(err) = self.painter.paint_and_update_textures(
self.app.clear_color(&self.egui_ctx.style().visuals),
&clipped_primitives,
self.egui_ctx.pixels_per_point(),
&textures_delta,
mem::take(&mut self.screenshot_commands),
screenshot_commands,
) {
log::error!("Failed to paint: {}", super::string_from_js_value(&err));
}

View File

@ -1056,7 +1056,7 @@ pub enum ViewportCommand {
/// Enable mouse pass-through: mouse clicks pass through the window, used for non-interactable overlays.
MousePassthrough(bool),
/// Take a screenshot.
/// Take a screenshot of the next frame after this.
///
/// The results are returned in [`crate::Event::Screenshot`].
Screenshot(crate::UserData),