Skip to content

Commit

Permalink
Allow hiding/showing entity subtrees under shown/hidden parent tree (#…
Browse files Browse the repository at this point in the history
…5508)

### What

* Fixes #5464
* using the design we agreed upon that doesn't use tristate buttons in
the blueprint panel
* Next step on #5463
* Fixes #5396
* Fixes #3194 

The title describes the main effect this has on what Rerun can do
compared to the previous release. But the real star of the show is that
visible is now a component, not part of `EntityProperties`.

@ reviewer: Please take your time and explore the behavior both on
blueprint panel and selection panel, there's a surprising amount of
nuance in here.
For instance there's extra logic for allowing you to go back to a clean
slate with ui interactions - for instance hiding & unhiding an item that
doesn't receive any parent overrides will remove the visibility override
completely as the default value for visibility is 'true'.


You can now hide/show under a shown/hidden parent tree:


https://github.com/rerun-io/rerun/assets/1220815/f412cac5-2db6-43d0-9b02-d2269cb60824

We're able to keep track of where an override comes from, this is
exposed in the selection panels' tooltip:

![image](https://github.com/rerun-io/rerun/assets/1220815/ef7794ac-07c8-4930-ba92-11a45f91f6fe)



### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using newly built examples:
[app.rerun.io](https://app.rerun.io/pr/5508/index.html)
* Using examples from latest `main` build:
[app.rerun.io](https://app.rerun.io/pr/5508/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[app.rerun.io](https://app.rerun.io/pr/5508/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/5508)
- [Docs
preview](https://rerun.io/preview/a09f77a2233fd101a4c5a94703f7726a920a18c6/docs)
<!--DOCS-PREVIEW-->
- [Examples
preview](https://rerun.io/preview/a09f77a2233fd101a4c5a94703f7726a920a18c6/examples)
<!--EXAMPLES-PREVIEW-->
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)
  • Loading branch information
Wumpf authored Mar 15, 2024
1 parent a79520e commit c8d6edf
Show file tree
Hide file tree
Showing 31 changed files with 388 additions and 219 deletions.
8 changes: 1 addition & 7 deletions crates/re_entity_db/src/entity_properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ impl FromIterator<(EntityPath, EntityProperties)> for EntityPropertyMap {
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct EntityProperties {
pub visible: bool,
pub visible_history: re_query::ExtraQueryHistory,
pub interactive: bool,

Expand Down Expand Up @@ -144,7 +143,6 @@ pub struct EntityProperties {
impl Default for EntityProperties {
fn default() -> Self {
Self {
visible: true,
visible_history: re_query::ExtraQueryHistory::default(),
interactive: true,
color_mapper: EditableAutoValue::default(),
Expand All @@ -166,7 +164,6 @@ impl EntityProperties {
/// Multiply/and these together.
pub fn with_child(&self, child: &Self) -> Self {
Self {
visible: self.visible && child.visible,
visible_history: self.visible_history.with_child(&child.visible_history),
interactive: self.interactive && child.interactive,

Expand Down Expand Up @@ -211,7 +208,6 @@ impl EntityProperties {
/// loaded from the Blueprint store where the Auto values are not up-to-date.
pub fn merge_with(&self, other: &Self) -> Self {
Self {
visible: other.visible,
visible_history: self.visible_history.with_child(&other.visible_history),
interactive: other.interactive,

Expand Down Expand Up @@ -250,7 +246,6 @@ impl EntityProperties {
/// Determine whether this `EntityProperty` has user-edits relative to another `EntityProperty`
pub fn has_edits(&self, other: &Self) -> bool {
let Self {
visible,
visible_history,
interactive,
color_mapper,
Expand All @@ -265,8 +260,7 @@ impl EntityProperties {
time_series_aggregator,
} = self;

visible != &other.visible
|| visible_history != &other.visible_history
visible_history != &other.visible_history
|| interactive != &other.interactive
|| color_mapper.has_edits(&other.color_mapper)
|| pinhole_image_plane_distance.has_edits(&other.pinhole_image_plane_distance)
Expand Down
9 changes: 5 additions & 4 deletions crates/re_space_view/src/data_query.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
use ahash::HashMap;
use nohash_hasher::IntMap;

use re_entity_db::{external::re_data_store::LatestAtQuery, EntityProperties, EntityPropertyMap};
use re_log_types::{EntityPath, StoreKind};
use re_types::ComponentName;
use re_viewer_context::{DataQueryResult, PerVisualizer, StoreContext, VisualizableEntities};
use re_viewer_context::{
DataQueryResult, OverridePath, PerVisualizer, StoreContext, VisualizableEntities,
};

pub struct EntityOverrideContext {
pub root: EntityProperties,
pub individual: EntityPropertyMap,
pub recursive: EntityPropertyMap,

/// Base component overrides that are inherited by all entities.
pub root_component_overrides: HashMap<ComponentName, (StoreKind, EntityPath)>,
pub root_component_overrides: IntMap<ComponentName, OverridePath>,
}

/// Trait for resolving properties needed by most implementations of [`DataQuery`]
Expand Down
36 changes: 18 additions & 18 deletions crates/re_space_view/src/space_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ impl SpaceViewBlueprint {
accumulated_properties,
individual_properties,
recursive_properties: Default::default(),
component_overrides: Default::default(),
resolved_component_overrides: Default::default(),
recursive_override_path: entity_path.clone(),
individual_override_path: entity_path,
}),
Expand All @@ -464,8 +464,8 @@ mod tests {
};
use re_types::{archetypes::Points3D, ComponentBatch, ComponentName, Loggable as _};
use re_viewer_context::{
blueprint_timeline, IndicatedEntities, PerVisualizer, SpaceViewClassRegistry, StoreContext,
VisualizableEntities,
blueprint_timeline, IndicatedEntities, OverridePath, PerVisualizer, SpaceViewClassRegistry,
StoreContext, VisualizableEntities,
};
use std::collections::HashMap;

Expand Down Expand Up @@ -582,9 +582,9 @@ mod tests {
);
}

// Now, override visibility on parent individually.
// Now, override interactive on parent individually.
let mut overrides = parent.individual_properties().cloned().unwrap_or_default();
overrides.visible = false;
overrides.interactive = false;

save_override(
overrides,
Expand All @@ -593,7 +593,7 @@ mod tests {
);
}

// Parent is not visible, but children are
// Parent is not interactive, but children are
{
let ctx = StoreContext {
app_id: re_log_types::ApplicationId::unknown(),
Expand Down Expand Up @@ -622,18 +622,18 @@ mod tests {
.lookup_result_by_path(&EntityPath::from("parent/skip/child2"))
.unwrap();

assert!(!parent.accumulated_properties().visible);
assert!(!parent.accumulated_properties().interactive);

for result in [child1, child2] {
assert!(result.accumulated_properties().visible);
assert!(result.accumulated_properties().interactive);
}

// Override visibility on parent recursively.
// Override interactivity on parent recursively.
let mut overrides = parent_group
.individual_properties()
.cloned()
.unwrap_or_default();
overrides.visible = false;
overrides.interactive = false;

save_override(
overrides,
Expand All @@ -642,7 +642,7 @@ mod tests {
);
}

// Nobody is visible
// Nobody is interactive
{
let ctx = StoreContext {
app_id: re_log_types::ApplicationId::unknown(),
Expand All @@ -668,11 +668,11 @@ mod tests {
.unwrap();

for result in [parent, child1, child2] {
assert!(!result.accumulated_properties().visible);
assert!(!result.accumulated_properties().interactive);
}
}

// Override visible range on root
// Override interactive range on root
{
let root = space_view.root_data_result(
&StoreContext {
Expand All @@ -694,7 +694,7 @@ mod tests {
);
}

// Everyone has visible history
// Everyone has interactive history
{
let ctx = StoreContext {
app_id: re_log_types::ApplicationId::unknown(),
Expand Down Expand Up @@ -736,7 +736,7 @@ mod tests {
);
}

// Child2 has its own visible history
// Child2 has its own interactive history
{
let ctx = StoreContext {
app_id: re_log_types::ApplicationId::unknown(),
Expand Down Expand Up @@ -1042,13 +1042,13 @@ mod tests {
query_result.tree.visit(&mut |node| {
let result = &node.data_result;
if let Some(property_overrides) = &result.property_overrides {
if !property_overrides.component_overrides.is_empty() {
if !property_overrides.resolved_component_overrides.is_empty() {
visited.insert(
result.entity_path.clone(),
property_overrides
.component_overrides
.resolved_component_overrides
.iter()
.map(|(component_name, (store_kind, path))| {
.map(|(component_name, OverridePath { store_kind, path })| {
assert_eq!(store_kind, &StoreKind::Blueprint);
(*component_name, path.clone())
})
Expand Down
22 changes: 11 additions & 11 deletions crates/re_space_view/src/space_view_contents.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
use ahash::HashMap;
use nohash_hasher::IntMap;
use slotmap::SlotMap;
use smallvec::SmallVec;

use re_entity_db::{
external::re_data_store::LatestAtQuery, EntityDb, EntityProperties, EntityPropertiesComponent,
EntityPropertyMap, EntityTree,
};
use re_log_types::{path::RuleEffect, EntityPath, EntityPathFilter, EntityPathRule, StoreKind};
use re_log_types::{path::RuleEffect, EntityPath, EntityPathFilter, EntityPathRule};
use re_types::{
blueprint::{archetypes as blueprint_archetypes, components::QueryExpression},
Archetype as _,
};
use re_types_core::{components::VisualizerOverrides, ComponentName};
use re_viewer_context::{
DataQueryResult, DataResult, DataResultHandle, DataResultNode, DataResultTree,
IndicatedEntities, PerVisualizer, PropertyOverrides, SpaceViewClassIdentifier, SpaceViewId,
StoreContext, ViewerContext, VisualizableEntities,
IndicatedEntities, OverridePath, PerVisualizer, PropertyOverrides, SpaceViewClassIdentifier,
SpaceViewId, StoreContext, ViewerContext, VisualizableEntities,
};

use crate::{
Expand Down Expand Up @@ -340,7 +340,7 @@ impl DataQueryPropertyResolver<'_> {
.space_view
.root_data_result(ctx, query)
.property_overrides
.map(|p| (p.accumulated_properties, p.component_overrides))
.map(|p| (p.accumulated_properties, p.resolved_component_overrides))
.unwrap_or_default();

for prefix in &self.default_stack {
Expand Down Expand Up @@ -416,7 +416,7 @@ impl DataQueryPropertyResolver<'_> {
query_result: &mut DataQueryResult,
override_context: &EntityOverrideContext,
accumulated: &EntityProperties,
recursive_property_overrides: &HashMap<ComponentName, (StoreKind, EntityPath)>,
recursive_property_overrides: &IntMap<ComponentName, OverridePath>,
handle: DataResultHandle,
) {
if let Some((child_handles, accumulated, recursive_property_overrides)) =
Expand Down Expand Up @@ -493,7 +493,7 @@ impl DataQueryPropertyResolver<'_> {
if !component_data.is_empty() {
recursive_property_overrides.to_mut().insert(
*component,
(StoreKind::Blueprint, recursive_override_path.clone()),
OverridePath::blueprint_path(recursive_override_path.clone()),
);
}
}
Expand All @@ -502,7 +502,7 @@ impl DataQueryPropertyResolver<'_> {

// Then, gather individual overrides - these may override the recursive ones again,
// but recursive overrides are still inherited to children.
let mut component_overrides = (*recursive_property_overrides).clone();
let mut resolved_component_overrides = (*recursive_property_overrides).clone();
if let Some(individual_override_subtree) =
ctx.blueprint.tree().subtree(&individual_override_path)
{
Expand All @@ -514,9 +514,9 @@ impl DataQueryPropertyResolver<'_> {
.and_then(|(_, _, cells)| cells[0].clone())
{
if !component_data.is_empty() {
component_overrides.insert(
resolved_component_overrides.insert(
*component,
(StoreKind::Blueprint, individual_override_path.clone()),
OverridePath::blueprint_path(individual_override_path.clone()),
);
}
}
Expand All @@ -527,7 +527,7 @@ impl DataQueryPropertyResolver<'_> {
accumulated_properties,
individual_properties: individual_properties.cloned(),
recursive_properties: recursive_properties.cloned(),
component_overrides,
resolved_component_overrides,
recursive_override_path,
individual_override_path,
});
Expand Down
2 changes: 1 addition & 1 deletion crates/re_space_view_bar_chart/src/visualizer_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ impl VisualizerSystem for BarChartVisualizerSystem {

let store = ctx.entity_db.store();

for data_result in query.iter_visible_data_results(Self::identifier()) {
for data_result in query.iter_visible_data_results(ctx, Self::identifier()) {
let query = LatestAtQuery::new(query.timeline, query.latest_at);
let tensor = store.query_latest_component::<re_types::components::TensorData>(
&data_result.entity_path,
Expand Down
2 changes: 1 addition & 1 deletion crates/re_space_view_dataframe/src/space_view_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ impl SpaceViewClass for DataframeSpaceView {
// These are the entity paths whose content we must display.
let sorted_entity_paths: BTreeSet<_> = query
.iter_all_data_results()
.filter(|data_result| data_result.accumulated_properties().visible)
.filter(|data_result| data_result.is_visible(ctx))
.map(|data_result| &data_result.entity_path)
.cloned()
.collect();
Expand Down
2 changes: 1 addition & 1 deletion crates/re_space_view_spatial/src/contexts/depth_offsets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl ViewContextSystem for EntityDepthOffsets {

// Use a BTreeSet for entity hashes to get a stable order.
let mut entities_per_draw_order = BTreeMap::<DrawOrder, BTreeSet<DrawOrderTarget>>::new();
for data_result in query.iter_visible_data_results(Self::identifier()) {
for data_result in query.iter_visible_data_results(ctx, Self::identifier()) {
if let Some(draw_order) = store
.query_latest_component::<DrawOrder>(&data_result.entity_path, &ctx.current_query())
{
Expand Down
2 changes: 1 addition & 1 deletion crates/re_space_view_spatial/src/visualizers/cameras.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ impl VisualizerSystem for CamerasVisualizer {
let mut line_builder = re_renderer::LineDrawableBuilder::new(ctx.render_ctx);
line_builder.radius_boost_in_ui_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES);

for data_result in query.iter_visible_data_results(Self::identifier()) {
for data_result in query.iter_visible_data_results(ctx, Self::identifier()) {
let time_query = re_data_store::LatestAtQuery::new(query.timeline, query.latest_at);

if let Some(pinhole) = query_pinhole(store, &time_query, &data_result.entity_path) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ where
let annotations = view_ctx.get::<AnnotationSceneContext>()?;
let counter = view_ctx.get::<PrimitiveCounter>()?;

for data_result in query.iter_visible_data_results(System::identifier()) {
for data_result in query.iter_visible_data_results(ctx, System::identifier()) {
// The transform that considers pinholes only makes sense if this is a 3D space-view
let world_from_entity =
if view_ctx.space_view_class_identifier() == SpatialSpaceView3D::identifier() {
Expand Down Expand Up @@ -151,7 +151,7 @@ macro_rules! impl_process_archetype {
let annotations = view_ctx.get::<AnnotationSceneContext>()?;
let counter = view_ctx.get::<PrimitiveCounter>()?;

for data_result in query.iter_visible_data_results(S::identifier()) {
for data_result in query.iter_visible_data_results(ctx, S::identifier()) {
// The transform that considers pinholes only makes sense if this is a 3D space-view
let world_from_entity = if view_ctx.space_view_class_identifier() == SpatialSpaceView3D::identifier() {
transforms.reference_from_entity(&data_result.entity_path)
Expand Down Expand Up @@ -256,7 +256,7 @@ pub fn count_instances_in_archetype_views<

let mut num_instances = 0;

for data_result in query.iter_visible_data_results(System::identifier()) {
for data_result in query.iter_visible_data_results(ctx, System::identifier()) {
match query_archetype_with_history::<A, N>(
ctx.entity_db.store(),
&query.timeline,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl VisualizerSystem for Transform3DArrowsVisualizer {
let mut line_builder = re_renderer::LineDrawableBuilder::new(ctx.render_ctx);
line_builder.radius_boost_in_ui_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES);

for data_result in query.iter_visible_data_results(Self::identifier()) {
for data_result in query.iter_visible_data_results(ctx, Self::identifier()) {
if !*data_result.accumulated_properties().transform_3d_visible {
continue;
}
Expand Down
2 changes: 1 addition & 1 deletion crates/re_space_view_tensor/src/visualizer_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl VisualizerSystem for TensorSystem {
re_tracing::profile_function!();

let store = ctx.entity_db.store();
for data_result in query.iter_visible_data_results(Self::identifier()) {
for data_result in query.iter_visible_data_results(ctx, Self::identifier()) {
let timeline_query = LatestAtQuery::new(query.timeline, query.latest_at);

if let Some(tensor) = store
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl VisualizerSystem for TextDocumentSystem {

let timeline_query = LatestAtQuery::new(query.timeline, query.latest_at);

for data_result in query.iter_visible_data_results(Self::identifier()) {
for data_result in query.iter_visible_data_results(ctx, Self::identifier()) {
// TODO(#3320): this match can go away once the issue is resolved
match query_archetype::<archetypes::TextDocument>(
store,
Expand Down
2 changes: 1 addition & 1 deletion crates/re_space_view_text_log/src/visualizer_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl VisualizerSystem for TextLogSystem {
let query_caches = ctx.entity_db.query_caches();
let store = ctx.entity_db.store();

for data_result in query.iter_visible_data_results(Self::identifier()) {
for data_result in query.iter_visible_data_results(ctx, Self::identifier()) {
re_tracing::profile_scope!("primary", &data_result.entity_path.to_string());

// We want everything, for all times:
Expand Down
Loading

0 comments on commit c8d6edf

Please sign in to comment.