Skip to content
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

Add Examples page to the Welcome Screen #3191

Merged
merged 25 commits into from
Sep 6, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9f9eefc
Add Examples page to the Welcome Screen
abey79 Sep 1, 2023
e93f3e5
Update the large files allow list
abey79 Sep 3, 2023
fb6cdf5
Reduced the verbosity of the SfM example description
abey79 Sep 4, 2023
4eacbae
Change to reactive grid layout
abey79 Sep 4, 2023
670fa82
Fixed the detect_and_track_objects thumbnail
abey79 Sep 4, 2023
1a7e895
Clamp to at least one column.
abey79 Sep 4, 2023
e271ce6
Lint fix and (temp) updated copy
abey79 Sep 4, 2023
38853d1
Updated manifest from #3201
abey79 Sep 4, 2023
b98b8eb
Merge branch 'main' into antoine/example-list
abey79 Sep 4, 2023
ec97ebf
Tags, layout update, centering behaviour
abey79 Sep 4, 2023
95f6269
No button, full example card hoverable/clickable
abey79 Sep 5, 2023
a8bd2b2
Merge branch 'main' into antoine/example-list
abey79 Sep 5, 2023
5be001c
Fixe title wrap + update some comments
abey79 Sep 5, 2023
1715e24
Update RRD links to more recent build
abey79 Sep 5, 2023
e39ad02
Proper line height for example description + fixed scroll area
abey79 Sep 5, 2023
8332ebe
Updated egui commit
abey79 Sep 5, 2023
1a2a5b0
Fix welcome page issue on wasm
abey79 Sep 5, 2023
5ff9cd6
Add loading animation to example cards on click
emilk Sep 5, 2023
671af4e
Cleanup spinner code into functions
abey79 Sep 5, 2023
8e0d729
Spacing adjustments and better looking spinner
abey79 Sep 6, 2023
f91363a
Proper line-height for the page title
abey79 Sep 6, 2023
ac1cc7e
Review comments
abey79 Sep 6, 2023
61c77a8
Load thumbnails from the web
abey79 Sep 6, 2023
ea1d80c
Revert allow list
abey79 Sep 6, 2023
3be107e
TOML formatting fix + review comments
abey79 Sep 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 10 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ eframe = { version = "0.22.0", default-features = false, features = [
"x11",
] }
egui = { version = "0.22.0", features = ["extra_debug_asserts", "log"] }
egui_extras = { version = "0.22.0", features = ["log"] }
egui_plot = { git = "https://github.com/emilk/egui", rev = "707ca04c081c1fa7d00c9d8d88f33ad5bb218714" }
egui_extras = { version = "0.22.0", features = ["log", "image", "http", "puffin"] }
egui_plot = { git = "https://github.com/emilk/egui", rev = "2338a854f932658ad0548aa4f00874b3427970c1" }
egui_tiles = { version = "0.2" }
egui-wgpu = "0.22.0"
ehttp = { version = "0.3" }
Expand Down Expand Up @@ -160,14 +160,14 @@ debug = true
# ALWAYS document what PR the commit hash is part of, or when it was merged into the upstream trunk.

# Temporary patch until next egui release
ecolor = { git = "https://github.com/emilk/egui", rev = "707ca04c081c1fa7d00c9d8d88f33ad5bb218714" }
eframe = { git = "https://github.com/emilk/egui", rev = "707ca04c081c1fa7d00c9d8d88f33ad5bb218714" }
egui-wgpu = { git = "https://github.com/emilk/egui", rev = "707ca04c081c1fa7d00c9d8d88f33ad5bb218714" }
egui-winit = { git = "https://github.com/emilk/egui", rev = "707ca04c081c1fa7d00c9d8d88f33ad5bb218714" }
egui = { git = "https://github.com/emilk/egui", rev = "707ca04c081c1fa7d00c9d8d88f33ad5bb218714" }
egui_extras = { git = "https://github.com/emilk/egui", rev = "707ca04c081c1fa7d00c9d8d88f33ad5bb218714" }
emath = { git = "https://github.com/emilk/egui", rev = "707ca04c081c1fa7d00c9d8d88f33ad5bb218714" }
epaint = { git = "https://github.com/emilk/egui", rev = "707ca04c081c1fa7d00c9d8d88f33ad5bb218714" }
ecolor = { git = "https://github.com/emilk/egui", rev = "2338a854f932658ad0548aa4f00874b3427970c1" }
eframe = { git = "https://github.com/emilk/egui", rev = "2338a854f932658ad0548aa4f00874b3427970c1" }
egui-wgpu = { git = "https://github.com/emilk/egui", rev = "2338a854f932658ad0548aa4f00874b3427970c1" }
egui-winit = { git = "https://github.com/emilk/egui", rev = "2338a854f932658ad0548aa4f00874b3427970c1" }
egui = { git = "https://github.com/emilk/egui", rev = "2338a854f932658ad0548aa4f00874b3427970c1" }
egui_extras = { git = "https://github.com/emilk/egui", rev = "2338a854f932658ad0548aa4f00874b3427970c1" }
emath = { git = "https://github.com/emilk/egui", rev = "2338a854f932658ad0548aa4f00874b3427970c1" }
epaint = { git = "https://github.com/emilk/egui", rev = "2338a854f932658ad0548aa4f00874b3427970c1" }

# Temporary patch until next egui_tiles release
egui_tiles = { git = "https://github.com/rerun-io/egui_tiles", rev = "f835c4df1cc260a58122a8d37c7c3738902b9643" }
2 changes: 2 additions & 0 deletions crates/re_ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ pub struct ReUi {
impl ReUi {
/// Create [`ReUi`] and apply style to the given egui context.
pub fn load_and_apply(egui_ctx: &egui::Context) -> Self {
egui_extras::loaders::install(egui_ctx);

Self {
egui_ctx: egui_ctx.clone(),
design_tokens: DesignTokens::load_and_apply(egui_ctx),
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
172 changes: 65 additions & 107 deletions crates/re_viewer/src/ui/welcome_screen/example_page.rs
Original file line number Diff line number Diff line change
@@ -1,68 +1,8 @@
use egui::{NumExt, Ui};
use egui::load::TexturePoll;
use egui::{NumExt, TextureOptions, Ui};
use re_log_types::LogMsg;
use re_smart_channel::ReceiveSet;
use re_ui::ReUi;
use re_viewer_context::SystemCommandSender;
use std::collections::HashMap;

// TODO(emilk/egui#3291): replace this by loading image from the web
static THUMBNAIL_CACHE: once_cell::sync::Lazy<HashMap<&'static str, re_ui::icons::Icon>> =
once_cell::sync::Lazy::new(|| {
[
re_ui::icons::Icon::new(
"efb301d64eef6f25e8f6ae29294bd003c0cda3a7_detect_and_track_objects_480w.png",
include_bytes!(
"../../../data/example_thumbnails/efb301d64eef6f25e8f6ae29294bd003c0cda3a7\
_detect_and_track_objects_480w.png"
),
),
re_ui::icons::Icon::new(
"8b90a80c72b27fad289806b7e5dff0c9ac97e87c_arkit_scenes_480w.png",
include_bytes!(
"../../../data/example_thumbnails/8b90a80c72b27fad289806b7e5dff0c9ac97e87c\
_arkit_scenes_480w.png"
),
),
re_ui::icons::Icon::new(
"033edff752f86bcdc9a81f7877e0b4411ff4e6c5_structure_from_motion_480w.png",
include_bytes!(
"../../../data/example_thumbnails/033edff752f86bcdc9a81f7877e0b4411ff4e6c5\
_structure_from_motion_480w.png"
),
),
re_ui::icons::Icon::new(
"277b9c72da1d0d0ae9d221f7552dede9c4d5b2fa_human_pose_tracking_480w.png",
include_bytes!(
"../../../data/example_thumbnails/277b9c72da1d0d0ae9d221f7552dede9c4d5b2fa\
_human_pose_tracking_480w.png"
),
),
re_ui::icons::Icon::new(
"b8b25dd01e892e6daf5177e6fc05ff5feb19ee8d_dicom_mri_480w.png",
include_bytes!(
"../../../data/example_thumbnails/b8b25dd01e892e6daf5177e6fc05ff5feb19ee8d\
_dicom_mri_480w.png"
),
),
re_ui::icons::Icon::new(
"ca0c72df93d70c79b0e640fb4b7c33cdc0bfe5f4_plots_480w.png",
include_bytes!(
"../../../data/example_thumbnails/ca0c72df93d70c79b0e640fb4b7c33cdc0bfe5f4\
_plots_480w.png"
),
),
re_ui::icons::Icon::new(
"ea7a9ab2f716bd37d1bbc1eabf3f55e4f526660e_helix_480w.png",
include_bytes!(
"../../../data/example_thumbnails/ea7a9ab2f716bd37d1bbc1eabf3f55e4f526660e\
_helix_480w.png"
),
),
]
.into_iter()
.map(|icon| (icon.id, icon))
.collect()
});

#[derive(Debug, serde::Deserialize)]
struct ExampleThumbnail {
Expand All @@ -72,13 +12,19 @@ struct ExampleThumbnail {
}

#[derive(Debug, serde::Deserialize)]
#[allow(unused)]
struct ExampleDesc {
// snake_case version of the example name
name: String,

// human readable version of the example name
abey79 marked this conversation as resolved.
Show resolved Hide resolved
title: String,

description: String,
tags: Vec<String>,

#[allow(unused)]
demo_url: String,

rrd_url: String,
thumbnail: ExampleThumbnail,
}
Expand Down Expand Up @@ -114,12 +60,12 @@ struct ExampleDescLayout {

impl ExampleDescLayout {
/// Saves the top left corner of the hover/click area for this example.
fn update_top_left(&mut self, pos: egui::Pos2) {
fn set_top_left(&mut self, pos: egui::Pos2) {
self.rect.min = pos;
}

/// Saves the bottom right corner of the hover/click area for this example.
fn update_bottom_right(&mut self, pos: egui::Pos2) {
fn set_bottom_right(&mut self, pos: egui::Pos2) {
self.rect.max = pos;
}

Expand Down Expand Up @@ -156,7 +102,6 @@ impl ExamplePage {

pub(super) fn ui(
&mut self,
re_ui: &re_ui::ReUi,
ui: &mut egui::Ui,
rx: &re_smart_channel::ReceiveSet<re_log_types::LogMsg>,
command_sender: &re_viewer_context::CommandSender,
Expand Down Expand Up @@ -217,7 +162,7 @@ impl ExamplePage {
.for_each(|example_layouts| {
for example in &mut *example_layouts {
// this is the beginning of the first cell for this example
example.update_top_left(ui.cursor().min);
example.set_top_left(ui.cursor().min);

let thumbnail = &example.desc.thumbnail;
let width = thumbnail.width as f32;
Expand All @@ -229,7 +174,6 @@ impl ExamplePage {
);

example_thumbnail(
re_ui,
ui,
rx,
&example.desc,
Expand Down Expand Up @@ -262,7 +206,7 @@ impl ExamplePage {
example_tags(ui, &example.desc);

// this is the end of the last cell for this example
example.update_bottom_right(egui::pos2(
example.set_bottom_right(egui::pos2(
ui.cursor().min.x + column_width,
ui.cursor().min.y,
));
Expand Down Expand Up @@ -302,52 +246,66 @@ fn is_loading(rx: &ReceiveSet<LogMsg>, example: &ExampleDesc) -> bool {
}

fn example_thumbnail(
re_ui: &ReUi,
ui: &mut Ui,
rx: &ReceiveSet<LogMsg>,
example: &ExampleDesc,
size: egui::Vec2,
hovered: bool,
) {
// TODO(emilk/egui#3291): pull from web rather than cache
let file_name = example.thumbnail.url.split('/').last();

if let Some(file_name) = file_name {
if let Some(icon) = THUMBNAIL_CACHE.get(file_name) {
let image = re_ui.icon_image(icon);
let texture_id = image.texture_id(ui.ctx());

let rounding = egui::Rounding::same(THUMBNAIL_RADIUS);
let resp = ui.add(egui::Image::new(texture_id, size).rounding(rounding));

// TODO(ab): use design tokens
let border_color = if hovered {
ui.visuals_mut().widgets.hovered.fg_stroke.color
} else {
egui::Color32::from_gray(44)
};

ui.painter()
.rect_stroke(resp.rect, rounding, (1.0, border_color));

// spinner overlay
if is_loading(rx, example) {
ui.painter().rect_filled(
resp.rect,
rounding,
egui::Color32::BLACK.gamma_multiply(0.75),
);

let spinner_size = resp.rect.size().min_elem().at_most(72.0);
let spinner_rect = egui::Rect::from_center_size(
resp.rect.center(),
egui::Vec2::splat(spinner_size),
);
ui.allocate_ui_at_rect(spinner_rect, |ui| {
ui.add(egui::Spinner::new().size(spinner_size));
let rounding = egui::Rounding::same(THUMBNAIL_RADIUS);

let resp = match ui.ctx().try_load_texture(
example.thumbnail.url.as_str(),
TextureOptions::LINEAR,
egui::SizeHint::from(size),
) {
Ok(TexturePoll::Ready { texture }) => {
ui.add(egui::Image::new(texture.id, size).rounding(rounding))
}
Ok(TexturePoll::Pending { .. }) => {
ui.allocate_ui_at_rect(egui::Rect::from_min_size(ui.cursor().min, size), |ui| {
// add some space before the spinner
ui.add_space(4.0);
ui.horizontal(|ui| {
ui.add_space(4.0);
ui.spinner()
.on_hover_text(format!("Loading thumbnail for {} example…", example.title));
});
}

// Eat all available space so the spinner container has the same size as the
// thumbnail itself.
ui.allocate_exact_size(ui.max_rect().max - ui.cursor().min, egui::Sense::hover());
})
.response
}

Err(err) => ui.colored_label(ui.visuals().error_fg_color, err.to_string()),
};

// TODO(ab): use design tokens
let border_color = if hovered {
ui.visuals_mut().widgets.hovered.fg_stroke.color
} else {
egui::Color32::from_gray(44)
};

ui.painter()
.rect_stroke(resp.rect, rounding, (1.0, border_color));

// spinner overlay
if is_loading(rx, example) {
ui.painter().rect_filled(
resp.rect,
rounding,
egui::Color32::BLACK.gamma_multiply(0.75),
);

let spinner_size = resp.rect.size().min_elem().at_most(72.0);
let spinner_rect =
egui::Rect::from_center_size(resp.rect.center(), egui::Vec2::splat(spinner_size));
ui.allocate_ui_at_rect(spinner_rect, |ui| {
ui.add(egui::Spinner::new().size(spinner_size));
});
}
}

Expand Down
Loading