Skip to content

Commit

Permalink
Implement save-view-as-screenshot on web (#8472)
Browse files Browse the repository at this point in the history
### Related
* Part of #8264
* Using emilk/egui#5438

Still missing: copy screenshot to clipboard

Also fixes a crash when screenshotting graph views.

### Usage

![image](https://github.com/user-attachments/assets/88948342-8279-4bf6-9bc6-13722229dc44)

### Result
![Node-link
diagram](https://github.com/user-attachments/assets/b2ff8dd5-ae55-436a-9cd2-263eeb72a0df)
  • Loading branch information
emilk authored Dec 17, 2024
1 parent a7acf15 commit 11c06b1
Show file tree
Hide file tree
Showing 8 changed files with 33 additions and 27 deletions.
22 changes: 11 additions & 11 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1934,7 +1934,7 @@ checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
[[package]]
name = "ecolor"
version = "0.29.1"
source = "git+https://github.com/emilk/egui.git?rev=f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b#f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b"
source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091"
dependencies = [
"bytemuck",
"color-hex",
Expand All @@ -1951,7 +1951,7 @@ checksum = "18aade80d5e09429040243ce1143ddc08a92d7a22820ac512610410a4dd5214f"
[[package]]
name = "eframe"
version = "0.29.1"
source = "git+https://github.com/emilk/egui.git?rev=f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b#f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b"
source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091"
dependencies = [
"ahash",
"bytemuck",
Expand Down Expand Up @@ -1990,7 +1990,7 @@ dependencies = [
[[package]]
name = "egui"
version = "0.29.1"
source = "git+https://github.com/emilk/egui.git?rev=f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b#f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b"
source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091"
dependencies = [
"accesskit",
"ahash",
Expand All @@ -2007,7 +2007,7 @@ dependencies = [
[[package]]
name = "egui-wgpu"
version = "0.29.1"
source = "git+https://github.com/emilk/egui.git?rev=f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b#f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b"
source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091"
dependencies = [
"ahash",
"bytemuck",
Expand All @@ -2026,7 +2026,7 @@ dependencies = [
[[package]]
name = "egui-winit"
version = "0.29.1"
source = "git+https://github.com/emilk/egui.git?rev=f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b#f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b"
source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091"
dependencies = [
"accesskit_winit",
"ahash",
Expand Down Expand Up @@ -2068,7 +2068,7 @@ dependencies = [
[[package]]
name = "egui_extras"
version = "0.29.1"
source = "git+https://github.com/emilk/egui.git?rev=f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b#f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b"
source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091"
dependencies = [
"ahash",
"egui",
Expand All @@ -2085,7 +2085,7 @@ dependencies = [
[[package]]
name = "egui_glow"
version = "0.29.1"
source = "git+https://github.com/emilk/egui.git?rev=f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b#f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b"
source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091"
dependencies = [
"ahash",
"bytemuck",
Expand All @@ -2102,7 +2102,7 @@ dependencies = [
[[package]]
name = "egui_kittest"
version = "0.29.1"
source = "git+https://github.com/emilk/egui.git?rev=f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b#f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b"
source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091"
dependencies = [
"dify",
"egui",
Expand Down Expand Up @@ -2171,7 +2171,7 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "emath"
version = "0.29.1"
source = "git+https://github.com/emilk/egui.git?rev=f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b#f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b"
source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091"
dependencies = [
"bytemuck",
"serde",
Expand Down Expand Up @@ -2287,7 +2287,7 @@ dependencies = [
[[package]]
name = "epaint"
version = "0.29.1"
source = "git+https://github.com/emilk/egui.git?rev=f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b#f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b"
source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091"
dependencies = [
"ab_glyph",
"ahash",
Expand All @@ -2306,7 +2306,7 @@ dependencies = [
[[package]]
name = "epaint_default_fonts"
version = "0.29.1"
source = "git+https://github.com/emilk/egui.git?rev=f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b#f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b"
source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091"

[[package]]
name = "equivalent"
Expand Down
14 changes: 7 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -553,13 +553,13 @@ significant_drop_tightening = "allow" # An update of parking_lot made this trigg
# As a last resport, patch with a commit to our own repository.
# ALWAYS document what PR the commit hash is part of, or when it was merged into the upstream trunk.

ecolor = { git = "https://github.com/emilk/egui.git", rev = "f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b" } # egui master 2024-12-16
eframe = { git = "https://github.com/emilk/egui.git", rev = "f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b" } # egui master 2024-12-16
egui = { git = "https://github.com/emilk/egui.git", rev = "f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b" } # egui master 2024-12-16
egui_extras = { git = "https://github.com/emilk/egui.git", rev = "f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b" } # egui master 2024-12-16
egui_kittest = { git = "https://github.com/emilk/egui.git", rev = "f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b" } # egui master 2024-12-16
egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b" } # egui master 2024-12-16
emath = { git = "https://github.com/emilk/egui.git", rev = "f7efb2186d529ddc9e69f7173c6ae3ae5f403d0b" } # egui master 2024-12-16
ecolor = { git = "https://github.com/emilk/egui.git", rev = "0823a36952a6791a0e28e6e8eac4f35639ab3091" } # egui master 2024-12-16 15:08
eframe = { git = "https://github.com/emilk/egui.git", rev = "0823a36952a6791a0e28e6e8eac4f35639ab3091" } # egui master 2024-12-16 15:08
egui = { git = "https://github.com/emilk/egui.git", rev = "0823a36952a6791a0e28e6e8eac4f35639ab3091" } # egui master 2024-12-16 15:08
egui_extras = { git = "https://github.com/emilk/egui.git", rev = "0823a36952a6791a0e28e6e8eac4f35639ab3091" } # egui master 2024-12-16 15:08
egui_kittest = { git = "https://github.com/emilk/egui.git", rev = "0823a36952a6791a0e28e6e8eac4f35639ab3091" } # egui master 2024-12-16 15:08
egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "0823a36952a6791a0e28e6e8eac4f35639ab3091" } # egui master 2024-12-16 15:08
emath = { git = "https://github.com/emilk/egui.git", rev = "0823a36952a6791a0e28e6e8eac4f35639ab3091" } # egui master 2024-12-16 15:08

# Useful while developing:
# ecolor = { path = "../../egui/crates/ecolor" }
Expand Down
2 changes: 0 additions & 2 deletions crates/viewer/re_context_menu/src/actions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ pub(super) mod move_contents_to_new_container;
pub(super) mod remove;
pub(super) mod show_hide;

#[cfg(not(target_arch = "wasm32"))] // TODO(#8264): screenshotting on web
mod screenshot_action;

#[cfg(not(target_arch = "wasm32"))] // TODO(#8264): screenshotting on web
pub use screenshot_action::ScreenshotAction;
11 changes: 9 additions & 2 deletions crates/viewer/re_context_menu/src/actions/screenshot_action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ use re_viewer_context::{Item, PublishedViewInfo, ScreenshotTarget, ViewId, ViewR
use crate::{ContextMenuAction, ContextMenuContext};

/// View screenshot action.
#[cfg(not(target_arch = "wasm32"))]
pub enum ScreenshotAction {
/// Screenshot the view, and copy the results to clipboard.
#[cfg(not(target_arch = "wasm32"))] // TODO(#8264): copy-to-screenshot on web
CopyScreenshot,

/// Screenshot the view, and save the results to disk.
Expand Down Expand Up @@ -39,6 +39,7 @@ impl ContextMenuAction for ScreenshotAction {

fn label(&self, _ctx: &ContextMenuContext<'_>) -> String {
match self {
#[cfg(not(target_arch = "wasm32"))] // TODO(#8264): copy-to-screenshot on web
Self::CopyScreenshot => "Copy screenshot".to_owned(),
Self::SaveScreenshot => "Save screenshot…".to_owned(),
}
Expand All @@ -56,9 +57,15 @@ impl ContextMenuAction for ScreenshotAction {

let PublishedViewInfo { name, rect } = view_info;

let rect = rect.shrink(1.75); // Hacky: Shrink so we don't accidentally include the border of the view.
let rect = rect.shrink(2.5); // Hacky: Shrink so we don't accidentally include the border of the view.

if !rect.is_positive() {
re_log::info!("View too small for a screenshot");
return;
}

let target = match self {
#[cfg(not(target_arch = "wasm32"))] // TODO(#8264): copy-to-screenshot on web
Self::CopyScreenshot => ScreenshotTarget::CopyToClipboard,
Self::SaveScreenshot => ScreenshotTarget::SaveToDisk,
};
Expand Down
2 changes: 1 addition & 1 deletion crates/viewer/re_context_menu/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ fn action_list(
Box::new(HideAction),
Box::new(RemoveAction),
],
#[cfg(not(target_arch = "wasm32"))] // TODO(#8264): screenshotting on web
vec![
#[cfg(not(target_arch = "wasm32"))] // TODO(#8264): copy-to-screenshot on web
Box::new(actions::ScreenshotAction::CopyScreenshot),
Box::new(actions::ScreenshotAction::SaveScreenshot),
],
Expand Down
6 changes: 3 additions & 3 deletions crates/viewer/re_viewer/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1596,7 +1596,7 @@ impl App {
false
}

#[cfg(not(target_arch = "wasm32"))] // TODO(#8264): screenshotting on web
#[allow(clippy::needless_pass_by_ref_mut)] // False positive on wasm
fn process_screenshot_result(
&mut self,
image: &Arc<egui::ColorImage>,
Expand All @@ -1623,8 +1623,8 @@ impl App {
};

match target {
#[cfg(not(target_arch = "wasm32"))] // TODO(#8264): copy-to-screenshot on web
re_viewer_context::ScreenshotTarget::CopyToClipboard => {
#[cfg(not(target_arch = "wasm32"))] // TODO(#8264): screenshotting on web
re_viewer_context::Clipboard::with(|clipboard| {
clipboard.set_image(
[rgba.width(), rgba.height()],
Expand Down Expand Up @@ -1656,6 +1656,7 @@ impl App {
}
}
} else {
#[cfg(not(target_arch = "wasm32"))] // no full-app screenshotting on web
self.screenshotter.save(image);
}
}
Expand Down Expand Up @@ -1951,7 +1952,6 @@ impl eframe::App for App {
self.store_hub = Some(store_hub);

// Check for returned screenshot:
#[cfg(not(target_arch = "wasm32"))] // TODO(#8264): screenshotting on web
egui_ctx.input(|i| {
for event in &i.raw.events {
if let egui::Event::Screenshot {
Expand Down
1 change: 1 addition & 0 deletions crates/viewer/re_viewer_context/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ pub struct ScreenshotInfo {
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ScreenshotTarget {
/// The screenshot will be copied to the clipboard.
#[cfg(not(target_arch = "wasm32"))] // TODO(#8264): copy-to-screenshot on web
CopyToClipboard,

/// The screenshot will be saved to disk.
Expand Down
2 changes: 1 addition & 1 deletion crates/viewer/re_viewport/src/viewport_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ impl<'a> egui_tiles::Behavior<ViewId> for TilesDelegate<'a, '_> {
*view_id,
PublishedViewInfo {
name: view_blueprint.display_name_or_default().as_ref().to_owned(),
rect: ui.min_rect(),
rect: ui.max_rect(),
},
);
});
Expand Down

0 comments on commit 11c06b1

Please sign in to comment.