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

Example of how to embed the Rerun Viewer inside your own GUI (+ ergonomic improvements) #2250

Merged
merged 25 commits into from
May 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
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
30 changes: 25 additions & 5 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ re_arrow_store = { path = "crates/re_arrow_store", version = "0.7.0-alpha.0", de
re_build_build_info = { path = "crates/re_build_build_info", version = "0.7.0-alpha.0", default-features = false }
re_build_info = { path = "crates/re_build_info", version = "0.7.0-alpha.0", default-features = false }
re_build_web_viewer = { path = "crates/re_build_web_viewer", version = "0.7.0-alpha.0", default-features = false }
re_crash_handler = { path = "crates/re_crash_handler", version = "0.7.0-alpha.0", default-features = false }
re_data_store = { path = "crates/re_data_store", version = "0.7.0-alpha.0", default-features = false }
re_data_ui = { path = "crates/re_data_ui", version = "0.7.0-alpha.0", default-features = false }
re_error = { path = "crates/re_error", version = "0.7.0-alpha.0", default-features = false }
Expand Down
4 changes: 4 additions & 0 deletions crates/re_arrow_store/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ pub use arrow2::io::ipc::read::{StreamReader, StreamState};
#[doc(no_inline)]
pub use re_log_types::{TimeInt, TimeRange, TimeType, Timeline}; // for politeness sake

pub mod external {
pub use arrow2;
}

// ---

/// Native-only profiling macro for puffin.
Expand Down
4 changes: 2 additions & 2 deletions crates/re_arrow_store/src/store_helpers.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use re_log_types::{
ComponentName, DataCell, DataRow, DeserializableComponent, EntityPath, RowId,
SerializableComponent, TimeInt, TimePoint, Timeline,
SerializableComponent, TimePoint, Timeline,
};

use crate::{DataStore, LatestAtQuery};
Expand Down Expand Up @@ -86,7 +86,7 @@ impl DataStore {
{
crate::profile_function!();

let query = LatestAtQuery::new(Timeline::default(), TimeInt::MAX);
let query = LatestAtQuery::latest(Timeline::default());
self.query_latest_component(entity_path, &query)
}
}
Expand Down
7 changes: 7 additions & 0 deletions crates/re_arrow_store/src/store_read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ impl LatestAtQuery {
pub const fn new(timeline: Timeline, at: TimeInt) -> Self {
Self { timeline, at }
}

pub const fn latest(timeline: Timeline) -> Self {
Self {
timeline,
at: TimeInt::MAX,
}
}
}

/// A query over a time range, for a given timeline.
Expand Down
40 changes: 40 additions & 0 deletions crates/re_crash_handler/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[package]
name = "re_crash_handler"
authors.workspace = true
description = "Detect panics and signals, logging them and optionally sending them to analytics."
edition.workspace = true
homepage.workspace = true
include.workspace = true
license.workspace = true
publish = true
readme = "README.md"
repository.workspace = true
rust-version.workspace = true
version.workspace = true

[package.metadata.docs.rs]
all-features = true


[features]
default = ["analytics"]

## Send analytics to Rerun on crashes
analytics = ["dep:re_analytics"]

[dependencies]
re_build_info.workspace = true

itertools.workspace = true
parking_lot.workspace = true

# Optional dependencies:
re_analytics = { workspace = true, optional = true }

# Native dependencies:
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
backtrace = "0.3"

# Native unix dependencies:
[target.'cfg(not(any(target_arch = "wasm32", target_os = "windows")))'.dependencies]
libc = "0.2"
10 changes: 10 additions & 0 deletions crates/re_crash_handler/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# re_crash_handler

Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates.

[![Latest version](https://img.shields.io/crates/v/re_crash_handler.svg)](https://crates.io/crates/re_crash_handler)
[![Documentation](https://docs.rs/re_crash_handler/badge.svg)](https://docs.rs/re_crash_handler)
![MIT](https://img.shields.io/badge/license-MIT-blue.svg)
![Apache](https://img.shields.io/badge/license-Apache-blue.svg)

Detect and handle signals, panics, and other crashes, making sure to log them and optionally send them off to analytics.
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Detect and handle signals, panics, and other crashes, making sure to log them and optionally send them off to analytics.

use re_build_info::BuildInfo;

use parking_lot::Mutex;
Expand Down Expand Up @@ -180,10 +182,7 @@ fn install_signal_handler(build_info: BuildInfo) {

// Send analytics - this also sleeps a while to give the analytics time to send the event.
#[cfg(feature = "analytics")]
{
let build_info = BUILD_INFO
.lock()
.unwrap_or_else(|| re_build_info::build_info!());
if let Some(build_info) = *BUILD_INFO.lock() {
send_signal_analytics(build_info, signal_name, callstack);
}

Expand Down
6 changes: 6 additions & 0 deletions crates/re_data_store/src/log_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ impl Default for EntityDb {
}

impl EntityDb {
/// A sorted list of all the entity paths in this database.
pub fn entity_paths(&self) -> Vec<&EntityPath> {
use itertools::Itertools as _;
self.entity_path_from_hash.values().sorted().collect()
}

#[inline]
pub fn entity_path_from_hash(&self, entity_path_hash: &EntityPathHash) -> Option<&EntityPath> {
self.entity_path_from_hash.get(entity_path_hash)
Expand Down
5 changes: 2 additions & 3 deletions crates/re_data_store/src/util.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use re_arrow_store::LatestAtQuery;
use re_log_types::{
DataRow, DeserializableComponent, EntityPath, RowId, SerializableComponent, TimeInt, TimePoint,
Timeline,
DataRow, DeserializableComponent, EntityPath, RowId, SerializableComponent, TimePoint, Timeline,
};

use crate::LogDb;
Expand Down Expand Up @@ -53,7 +52,7 @@ pub fn query_timeless_single<C: DeserializableComponent>(
where
for<'b> &'b C::ArrayType: IntoIterator,
{
let query = re_arrow_store::LatestAtQuery::new(Timeline::default(), TimeInt::MAX);
let query = re_arrow_store::LatestAtQuery::latest(Timeline::default());
query_latest_single(data_store, entity_path, &query)
}

Expand Down
23 changes: 6 additions & 17 deletions crates/re_data_ui/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,7 @@ impl DataUi for EntityComponentWithInstances {
) {
crate::profile_function!(self.component_name().full_name());

let mut instance_keys = match self.component_data.iter_instance_keys() {
Ok(instance_keys) => instance_keys,
Err(err) => {
ui.label(ctx.re_ui.error_text(format!("Error: {err}")));
return;
}
};
let instance_keys: Vec<_> = self.component_data.iter_instance_keys().collect();

let num_instances = self.num_instances();

Expand All @@ -52,15 +46,15 @@ impl DataUi for EntityComponentWithInstances {
if num_instances == 0 {
ui.weak("(empty)");
} else if num_instances == 1 {
if let Some(instance_key) = instance_keys.next() {
if let Some(instance_key) = instance_keys.first() {
ctx.component_ui_registry.ui(
ctx,
ui,
verbosity,
query,
&self.entity_path,
&self.component_data,
&instance_key,
instance_key,
);
} else {
ui.label(ctx.re_ui.error_text("Error: missing instance key"));
Expand Down Expand Up @@ -88,15 +82,10 @@ impl DataUi for EntityComponentWithInstances {
re_ui::ReUi::setup_table_body(&mut body);
let row_height = re_ui::ReUi::table_line_height();
body.rows(row_height, num_instances, |index, mut row| {
if let Some(instance_key) = self
.component_data
.iter_instance_keys()
.ok()
.and_then(|mut keys| keys.nth(index))
{
if let Some(instance_key) = instance_keys.get(index) {
row.col(|ui| {
let instance_path =
InstancePath::instance(self.entity_path.clone(), instance_key);
InstancePath::instance(self.entity_path.clone(), *instance_key);
item_ui::instance_path_button_to(
ctx,
ui,
Expand All @@ -113,7 +102,7 @@ impl DataUi for EntityComponentWithInstances {
query,
&self.entity_path,
&self.component_data,
&instance_key,
instance_key,
);
});
}
Expand Down
21 changes: 7 additions & 14 deletions crates/re_data_ui/src/component_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,19 @@ impl DataUi for ComponentPath {
) {
let store = &ctx.log_db.entity_db.data_store;

match re_query::get_component_with_instances(
if let Some((_, component_data)) = re_query::get_component_with_instances(
store,
query,
self.entity_path(),
self.component_name,
) {
Err(re_query::QueryError::PrimaryNotFound) => {
ui.label("<unset>");
}
Err(err) => {
// Any other failure to get a component is unexpected
ui.label(ctx.re_ui.error_text(format!("Error: {err}")));
}
Ok((_, component_data)) => {
super::component::EntityComponentWithInstances {
entity_path: self.entity_path.clone(),
component_data,
}
.data_ui(ctx, ui, verbosity, query);
super::component::EntityComponentWithInstances {
entity_path: self.entity_path.clone(),
component_data,
}
.data_ui(ctx, ui, verbosity, query);
} else {
ui.label("<unset>");
}
}
}
30 changes: 19 additions & 11 deletions crates/re_data_ui/src/component_ui_registry.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use re_arrow_store::LatestAtQuery;
use re_log_types::{
component_types::InstanceKey, external::arrow2, DeserializableComponent, EntityPath, SizeBytes,
component_types::InstanceKey, external::arrow2, DeserializableComponent, EntityPath,
};
use re_query::ComponentWithInstances;
use re_viewer_context::{ComponentUiRegistry, UiVerbosity, ViewerContext};
Expand Down Expand Up @@ -79,21 +79,29 @@ fn fallback_component_ui(
) {
// No special ui implementation - use a generic one:
if let Some(value) = component.lookup_arrow(instance_key) {
let bytes = value.total_size_bytes();
if bytes < 256 {
// For small items, print them
let mut repr = String::new();
let display = arrow2::array::get_display(value.as_ref(), "null");
display(&mut repr, 0).unwrap();
ui.label(repr);
} else {
ui.label(format!("{bytes} bytes"));
}
ui.label(format_arrow(&*value));
} else {
ui.weak("(null)");
}
}

fn format_arrow(value: &dyn arrow2::array::Array) -> String {
use re_log_types::SizeBytes as _;

let bytes = value.total_size_bytes();
if bytes < 256 {
// Print small items:
let mut string = String::new();
let display = arrow2::array::get_display(value, "null");
if display(&mut string, 0).is_ok() {
return string;
}
}

// Fallback:
format!("{bytes} bytes")
}

// ----------------------------------------------------------------------------

impl DataUi for re_log_types::component_types::TextEntry {
Expand Down
Loading