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:
parent
3995491212
commit
b1d2551e7e
|
|
@ -1,5 +1,4 @@
|
||||||
use egui::{TexturesDelta, UserData, ViewportCommand};
|
use egui::{TexturesDelta, UserData, ViewportCommand};
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
use crate::{epi, App};
|
use crate::{epi, App};
|
||||||
|
|
||||||
|
|
@ -17,8 +16,9 @@ pub struct AppRunner {
|
||||||
last_save_time: f64,
|
last_save_time: f64,
|
||||||
pub(crate) text_agent: TextAgent,
|
pub(crate) text_agent: TextAgent,
|
||||||
|
|
||||||
// If not empty, the painter should capture the next frame
|
// If not empty, the painter should capture n frames from now.
|
||||||
screenshot_commands: Vec<UserData>,
|
// zero means capture the exact next frame.
|
||||||
|
screenshot_commands_with_frame_delay: Vec<(UserData, usize)>,
|
||||||
|
|
||||||
// Output for the last run:
|
// Output for the last run:
|
||||||
textures_delta: TexturesDelta,
|
textures_delta: TexturesDelta,
|
||||||
|
|
@ -114,7 +114,7 @@ impl AppRunner {
|
||||||
needs_repaint,
|
needs_repaint,
|
||||||
last_save_time: now_sec(),
|
last_save_time: now_sec(),
|
||||||
text_agent,
|
text_agent,
|
||||||
screenshot_commands: vec![],
|
screenshot_commands_with_frame_delay: vec![],
|
||||||
textures_delta: Default::default(),
|
textures_delta: Default::default(),
|
||||||
clipped_primitives: None,
|
clipped_primitives: None,
|
||||||
};
|
};
|
||||||
|
|
@ -236,7 +236,8 @@ impl AppRunner {
|
||||||
for command in viewport_output.commands {
|
for command in viewport_output.commands {
|
||||||
match command {
|
match command {
|
||||||
ViewportCommand::Screenshot(user_data) => {
|
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
|
// TODO(emilk): handle some of the commands
|
||||||
|
|
@ -259,12 +260,27 @@ impl AppRunner {
|
||||||
let clipped_primitives = std::mem::take(&mut self.clipped_primitives);
|
let clipped_primitives = std::mem::take(&mut self.clipped_primitives);
|
||||||
|
|
||||||
if let Some(clipped_primitives) = 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(
|
if let Err(err) = self.painter.paint_and_update_textures(
|
||||||
self.app.clear_color(&self.egui_ctx.style().visuals),
|
self.app.clear_color(&self.egui_ctx.style().visuals),
|
||||||
&clipped_primitives,
|
&clipped_primitives,
|
||||||
self.egui_ctx.pixels_per_point(),
|
self.egui_ctx.pixels_per_point(),
|
||||||
&textures_delta,
|
&textures_delta,
|
||||||
mem::take(&mut self.screenshot_commands),
|
screenshot_commands,
|
||||||
) {
|
) {
|
||||||
log::error!("Failed to paint: {}", super::string_from_js_value(&err));
|
log::error!("Failed to paint: {}", super::string_from_js_value(&err));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1056,7 +1056,7 @@ pub enum ViewportCommand {
|
||||||
/// Enable mouse pass-through: mouse clicks pass through the window, used for non-interactable overlays.
|
/// Enable mouse pass-through: mouse clicks pass through the window, used for non-interactable overlays.
|
||||||
MousePassthrough(bool),
|
MousePassthrough(bool),
|
||||||
|
|
||||||
/// Take a screenshot.
|
/// Take a screenshot of the next frame after this.
|
||||||
///
|
///
|
||||||
/// The results are returned in [`crate::Event::Screenshot`].
|
/// The results are returned in [`crate::Event::Screenshot`].
|
||||||
Screenshot(crate::UserData),
|
Screenshot(crate::UserData),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue