-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
eframe: capture a screenshot using Frame::request_screenshot
#2676
Changes from 23 commits
c533c46
318b1d5
dd6f898
447b68f
1f1e58f
6b7bf39
7e2232e
fb55318
387d81a
78650a2
2dc00e7
e1aa669
ae5d24e
a3b253b
94f3a84
9cf3b52
094f284
bf6e33a
52f886a
ff32cd8
06e6dc0
570e941
204a450
214146e
391629a
b333b56
73ea872
886fb7f
3245832
ecd4d96
554834c
632e0e5
3f34373
64a8452
c0b526a
23016b3
5fa9ced
f239e7a
4a1c38d
c154774
f437c12
00c63d4
78de848
516f8c6
4d638b1
c62aa2b
e3d937e
bf08887
08ea093
10e072c
19f7577
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -651,6 +651,9 @@ pub struct Frame { | |
/// Can be used to manage GPU resources for custom rendering with WGPU using [`egui::PaintCallback`]s. | ||
#[cfg(feature = "wgpu")] | ||
pub(crate) wgpu_render_state: Option<egui_wgpu::RenderState>, | ||
|
||
#[cfg(not(target_arch = "wasm32"))] | ||
pub(crate) screenshot: std::cell::Cell<Option<egui::ColorImage>>, | ||
Wumpf marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
impl Frame { | ||
|
@@ -668,10 +671,69 @@ impl Frame { | |
} | ||
|
||
/// A place where you can store custom data in a way that persists when you restart the app. | ||
#[cfg(not(target_arch = "wasm32"))] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have storage on web (local storage)
emilk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
pub fn storage(&self) -> Option<&dyn Storage> { | ||
self.storage.as_deref() | ||
} | ||
|
||
/// Request the current frame's pixel data. Needs to be retrieved by calling [`Frame::screenshot`] | ||
/// during [`App::post_rendering`]. | ||
#[cfg(not(target_arch = "wasm32"))] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the limitation for implementing this on web? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mostly my inexperience with wasm and any kind of web-dev. I took a stab at trying to port the screenshot example to wasm with the eframe-template though, and it seems like App::post_rendering is never called on the web?
I chose to use the Frame struct for delivering the flag and image data between the app and the backend, which was easy on native since everything could be handled inside the WinitApp::paint function. I didn't look too closely at the architecture of the webpainter yet, but as App::post_rendering is never called, there would be no way to deliver the image data back to the app. If this is solved, I believe it would be possible to more or less copy-paste the actual screen capturing logic for wgpu and glow. |
||
pub fn request_screenshot(&mut self) { | ||
self.output.screenshot_requested = true; | ||
} | ||
|
||
/// Cancel a request made with [`Frame::request_screenshot`]. | ||
#[cfg(not(target_arch = "wasm32"))] | ||
pub fn cancel_screenshot_request(&mut self) { | ||
self.output.screenshot_requested = false; | ||
} | ||
|
||
/// During [`App::post_rendering`], use this to retrieve the pixel data that was requested during | ||
/// [`App::update`] via [`Frame::request_screenshot`]. | ||
/// | ||
/// Returns None if: | ||
/// * Called in [`App::update`] | ||
/// * [`Frame::request_screenshot`] wasn't called on this frame during [`App::update`] | ||
/// * The rendering backend doesn't support this feature (yet). Currently implemented for wgpu and glow, but not with wasm as target. | ||
/// * Retrieving the data was unsuccessful in some way. | ||
/// | ||
/// See also [`egui::ColorImage::region`] | ||
/// | ||
/// ## Example generating a capture of everything within a square of 100 pixels located at the top left of the app and saving it with the [`image`](crates.io/crates/image) crate: | ||
/// ``` | ||
/// impl eframe::App for MyApp{ | ||
/// fn update(ctx: &egui::Context, frame: &mut eframe::Frame){ | ||
/// ... // In real code the app would render something here | ||
/// frame.request_screenshot() | ||
/// ... // Things that are added to the frame after the call to | ||
/// // request_screenshot() will still be included. | ||
/// } | ||
/// | ||
/// fn post_rendering(&mut self, _window_size: [u32; 2], frame: &eframe::Frame){ | ||
/// if let Some(screenshot) = frame.screenshot(){ | ||
/// let pixels_per_point = frame.info().native_pixels_per_point; | ||
/// let region = egui::Rect::from_two_pos( | ||
/// egui::Pos2::ZERO, | ||
/// egui::Pos2{ x: 100., y: 100. }, | ||
/// ); | ||
/// let top_left_corner = screenshot.region(®ion, pixels_per_point); | ||
/// image::save_buffer( | ||
/// "top_left.png", | ||
/// top_left_corner.as_raw(), | ||
/// top_left_corner.width() as u32, | ||
/// top_left_corner.height() as u32, | ||
/// image::ColorType::Rgba8, | ||
/// ).unwrap(); | ||
/// } | ||
/// } | ||
/// } | ||
amfaber marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// ``` | ||
#[cfg(not(target_arch = "wasm32"))] | ||
pub fn screenshot(&self) -> Option<egui::ColorImage> { | ||
self.screenshot.take() | ||
} | ||
|
||
/// A place where you can store custom data in a way that persists when you restart the app. | ||
pub fn storage_mut(&mut self) -> Option<&mut (dyn Storage + 'static)> { | ||
self.storage.as_deref_mut() | ||
|
@@ -1037,5 +1099,8 @@ pub(crate) mod backend { | |
/// Set to some bool to maximize or unmaximize window. | ||
#[cfg(not(target_arch = "wasm32"))] | ||
pub maximized: Option<bool>, | ||
|
||
#[cfg(not(target_arch = "wasm32"))] | ||
pub screenshot_requested: bool, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these should go into the
eframe
andegui-wgpu
changelogs, and include al ink to this PR