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

Unified visualizer & override ui, enabled on all entities #6599

Merged
merged 11 commits into from
Jun 20, 2024
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5260,6 +5260,7 @@ dependencies = [
"half 2.3.1",
"indexmap 2.1.0",
"itertools 0.13.0",
"linked-hash-map",
"macaw",
"ndarray",
"nohash-hasher",
Expand Down
27 changes: 14 additions & 13 deletions crates/re_data_ui/src/component.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
use std::sync::Arc;

use egui::NumExt;

use re_entity_db::{external::re_query::LatestAtComponentResults, EntityPath, InstancePath};
use re_log_types::Instance;
use re_types::ComponentName;
use re_ui::{ContextExt as _, SyntaxHighlighting as _};
use re_viewer_context::{UiLayout, ViewerContext};

use super::DataUi;
use crate::item_ui;

/// All the values of a specific [`re_log_types::ComponentPath`].
pub struct EntityLatestAtResults {
pub struct EntityLatestAtResults<'a> {
pub entity_path: EntityPath,
pub component_name: ComponentName,
pub results: Arc<LatestAtComponentResults>,
pub results: &'a LatestAtComponentResults,
}

impl DataUi for EntityLatestAtResults {
impl<'a> DataUi for EntityLatestAtResults<'a> {
fn data_ui(
&self,
ctx: &ViewerContext<'_>,
Expand All @@ -27,12 +23,17 @@ impl DataUi for EntityLatestAtResults {
query: &re_data_store::LatestAtQuery,
db: &re_entity_db::EntityDb,
) {
re_tracing::profile_function!(self.component_name);
let Some(component_name) = self.results.component_name(db.resolver()) else {
// TODO(#5607): what should happen if the promise is still pending?
return;
};

re_tracing::profile_function!(component_name);

// TODO(#5607): what should happen if the promise is still pending?
let Some(num_instances) = self
.results
.raw(db.resolver(), self.component_name)
.raw(db.resolver(), component_name)
.map(|data| data.len())
else {
ui.weak("<pending>");
Expand Down Expand Up @@ -74,7 +75,7 @@ impl DataUi for EntityLatestAtResults {
if let Some(histogram) = db
.tree()
.subtree(&self.entity_path)
.and_then(|tree| tree.entity.components.get(&self.component_name))
.and_then(|tree| tree.entity.components.get(&component_name))
{
if histogram.num_static_messages() > 1 {
ui.label(ui.ctx().warning_text(format!(
Expand Down Expand Up @@ -139,7 +140,7 @@ impl DataUi for EntityLatestAtResults {
query,
db,
&self.entity_path,
&self.results,
self.results,
&Instance::from(0),
);
} else if one_line {
Expand All @@ -157,7 +158,7 @@ impl DataUi for EntityLatestAtResults {
ui.label("Index");
});
header.col(|ui| {
ui.label(self.component_name.short_name());
ui.label(component_name.short_name());
});
})
.body(|mut body| {
Expand Down Expand Up @@ -186,7 +187,7 @@ impl DataUi for EntityLatestAtResults {
query,
db,
&self.entity_path,
&self.results,
self.results,
&instance,
);
});
Expand Down
5 changes: 1 addition & 4 deletions crates/re_data_ui/src/component_path.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::sync::Arc;

use re_log_types::ComponentPath;
use re_ui::ContextExt as _;
use re_viewer_context::{UiLayout, ViewerContext};
Expand Down Expand Up @@ -31,8 +29,7 @@ impl DataUi for ComponentPath {
if let Some(results) = results.components.get(component_name) {
crate::EntityLatestAtResults {
entity_path: entity_path.clone(),
component_name: *component_name,
results: Arc::clone(results),
results: results.as_ref(),
}
.data_ui(ctx, ui, ui_layout, query, db);
} else if let Some(entity_tree) = ctx.recording().tree().subtree(entity_path) {
Expand Down
49 changes: 23 additions & 26 deletions crates/re_data_ui/src/component_ui_registry.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use re_data_store::LatestAtQuery;
use re_entity_db::{external::re_query::LatestAtComponentResults, EntityDb};
use re_log_types::{external::arrow2, EntityPath, Instance};
use re_entity_db::EntityDb;
use re_log_types::{external::arrow2, EntityPath};
use re_types::external::arrow2::array::Utf8Array;
use re_ui::UiExt;
use re_viewer_context::{ComponentUiRegistry, UiLayout, ViewerContext};

use super::EntityDataUi;
Expand Down Expand Up @@ -39,43 +40,39 @@ pub fn add_to_registry<C: EntityDataUi + re_types::Component>(registry: &mut Com
registry.add_display_ui(
C::name(),
Box::new(
|ctx, ui, ui_layout, query, db, entity_path, component, instance| {
// TODO(#5607): what should happen if the promise is still pending?
if let Some(component) = component.instance::<C>(db.resolver(), instance.get() as _)
{
component.entity_data_ui(ctx, ui, ui_layout, entity_path, query, db);
} else {
ui.weak("(not found)");
|ctx, ui, ui_layout, query, db, entity_path, component_raw| match C::from_arrow(
component_raw,
) {
Ok(components) => match components.len() {
0 => {
ui.weak("(empty)");
}
1 => {
components[0].entity_data_ui(ctx, ui, ui_layout, entity_path, query, db);
}
i => {
ui.label(format!("{} values", re_format::format_uint(i)));
}
},
Err(err) => {
ui.error_label("(failed to deserialize)")
.on_hover_text(err.to_string());
}
},
),
);
}

#[allow(clippy::too_many_arguments)]
fn fallback_component_ui(
_ctx: &ViewerContext<'_>,
ui: &mut egui::Ui,
ui_layout: UiLayout,
_query: &LatestAtQuery,
db: &EntityDb,
_db: &EntityDb,
_entity_path: &EntityPath,
component: &LatestAtComponentResults,
instance: &Instance,
component: &dyn arrow2::array::Array,
) {
// TODO(#5607): what should happen if the promise is still pending?
let value = component
.component_name(db.resolver())
.and_then(|component_name| {
component.instance_raw(db.resolver(), component_name, instance.get() as _)
});

// No special ui implementation - use a generic one:
if let Some(value) = value {
arrow_ui(ui, ui_layout, &*value);
} else {
ui.weak("(null)");
}
arrow_ui(ui, ui_layout, component);
}

fn arrow_ui(ui: &mut egui::Ui, ui_layout: UiLayout, array: &dyn arrow2::array::Array) {
Expand Down
3 changes: 1 addition & 2 deletions crates/re_data_ui/src/instance_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,7 @@ impl DataUi for InstancePath {
if instance.is_all() {
crate::EntityLatestAtResults {
entity_path: entity_path.clone(),
component_name,
results: std::sync::Arc::clone(results),
results: results.as_ref(),
}
.data_ui(
ctx,
Expand Down
3 changes: 2 additions & 1 deletion crates/re_edit_ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use datatype_editors::{
use re_types::{
blueprint::components::{BackgroundKind, Corner2D, LockRangeDuringZoom, ViewFit, Visible},
components::{
AggregationPolicy, AxisLength, Color, Colormap, FillRatio, GammaCorrection,
AggregationPolicy, AxisLength, Color, Colormap, DepthMeter, FillRatio, GammaCorrection,
ImagePlaneDistance, MagnificationFilter, MarkerSize, Name, Radius, StrokeWidth, Text,
},
};
Expand Down Expand Up @@ -59,6 +59,7 @@ pub fn register_editors(registry: &mut re_viewer_context::ComponentUiRegistry) {
registry.add_singleline_editor_ui::<Text>(edit_singleline_string);
registry.add_singleline_editor_ui::<Name>(edit_singleline_string);

registry.add_singleline_editor_ui::<DepthMeter>(edit_f32_zero_to_max_float_raw);
registry.add_singleline_editor_ui::<MarkerSize>(edit_f32_zero_to_max_float_raw);
registry.add_singleline_editor_ui::<Radius>(edit_f32_zero_to_max_float_raw);
registry.add_singleline_editor_ui::<StrokeWidth>(edit_f32_zero_to_max_float_raw);
Expand Down
11 changes: 11 additions & 0 deletions crates/re_query/src/latest_at/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ impl LatestAtComponentResults {
}
}

/// Tries to return the component data as an arrow array.
///
/// Logs a warning and returns `None` if the component is missing or cannot be deserialized.
#[inline]
pub fn try_raw(&self, resolver: &PromiseResolver) -> Option<Box<dyn Array>> {
match self.resolved(resolver) {
PromiseResult::Pending | PromiseResult::Error(_) => None,
PromiseResult::Ready(cell) => Some(cell.to_arrow()),
}
}

/// Returns true if the component is missing, an empty array or still pending.
pub fn is_empty(&self, resolver: &PromiseResolver) -> bool {
match self.resolved(resolver) {
Expand Down
2 changes: 1 addition & 1 deletion crates/re_selection_panel/src/defaults_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub fn defaults_ui(ctx: &ViewContext<'_>, space_view: &SpaceViewBlueprint, ui: &
// TODO(jleibs): We can do something fancier in the future such as presenting both
// options once we have a motivating use-case.
for (id, vis) in ctx.visualizer_collection.iter_with_identifiers() {
for component in vis.visualizer_query_info().queried {
for &component in vis.visualizer_query_info().queried.iter() {
component_to_vis.entry(component).or_insert_with(|| id);
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/re_selection_panel/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
//! The UI for the selection panel.

mod defaults_ui;
mod override_ui;
mod query_range_ui;
mod selection_history_ui;
mod selection_panel;
mod space_view_entity_picker;
mod space_view_space_origin_ui;
mod visualizer_ui;

pub use selection_panel::SelectionPanel;

Expand Down
Loading
Loading