From cf21c299950431461721452d67d7850fc8a01005 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 11 Jun 2024 13:18:54 +0200 Subject: [PATCH 1/5] add interactive component --- .../re_types/definitions/rerun/blueprint.fbs | 1 + .../blueprint/components/interactive.fbs | 22 +++ .../rerun/blueprint/components/visible.fbs | 2 +- .../src/blueprint/components/.gitattributes | 1 + .../src/blueprint/components/interactive.rs | 150 ++++++++++++++++++ .../re_types/src/blueprint/components/mod.rs | 2 + .../src/blueprint/components/visible.rs | 2 +- .../src/blueprint/validation_gen/mod.rs | 2 + .../re_viewer/src/component_defaults/mod.rs | 4 + rerun_cpp/src/rerun/blueprint/components.hpp | 1 + .../rerun/blueprint/components/.gitattributes | 1 + .../blueprint/components/interactive.hpp | 66 ++++++++ .../rerun/blueprint/components/visible.hpp | 2 +- .../rerun/blueprint/components/.gitattributes | 1 + .../rerun/blueprint/components/__init__.py | 4 + .../rerun/blueprint/components/interactive.py | 32 ++++ .../rerun/blueprint/components/visible.py | 2 +- 17 files changed, 291 insertions(+), 4 deletions(-) create mode 100644 crates/re_types/definitions/rerun/blueprint/components/interactive.fbs create mode 100644 crates/re_types/src/blueprint/components/interactive.rs create mode 100644 rerun_cpp/src/rerun/blueprint/components/interactive.hpp create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/components/interactive.py diff --git a/crates/re_types/definitions/rerun/blueprint.fbs b/crates/re_types/definitions/rerun/blueprint.fbs index 15e62816cb97..3264c73f890c 100644 --- a/crates/re_types/definitions/rerun/blueprint.fbs +++ b/crates/re_types/definitions/rerun/blueprint.fbs @@ -9,6 +9,7 @@ include "./blueprint/components/entity_properties_component.fbs"; include "./blueprint/components/grid_columns.fbs"; include "./blueprint/components/included_content.fbs"; include "./blueprint/components/included_space_view.fbs"; +include "./blueprint/components/interactive.fbs"; include "./blueprint/components/lock_range_during_zoom.fbs"; include "./blueprint/components/panel_state.fbs"; include "./blueprint/components/query_expression.fbs"; diff --git a/crates/re_types/definitions/rerun/blueprint/components/interactive.fbs b/crates/re_types/definitions/rerun/blueprint/components/interactive.fbs new file mode 100644 index 000000000000..fb2a8e339e59 --- /dev/null +++ b/crates/re_types/definitions/rerun/blueprint/components/interactive.fbs @@ -0,0 +1,22 @@ +include "arrow/attributes.fbs"; +include "python/attributes.fbs"; +include "rust/attributes.fbs"; + +include "rerun/datatypes.fbs"; +include "rerun/attributes.fbs"; + +namespace rerun.blueprint.components; + +// --- + +/// Whether the entity can be interacted with. +/// +/// Non interactive components are still visible, but mouse iteractions in the view are disabled. +struct Interactive ( + "attr.rerun.scope": "blueprint", + "attr.rust.derive": "Copy, Default, PartialEq, Eq, PartialOrd, Ord", + "attr.rust.repr": "transparent", + "attr.rust.tuple_struct" +) { + interactive: rerun.datatypes.Bool (order: 100); +} diff --git a/crates/re_types/definitions/rerun/blueprint/components/visible.fbs b/crates/re_types/definitions/rerun/blueprint/components/visible.fbs index ee11f7651d5d..66c674e31f8f 100644 --- a/crates/re_types/definitions/rerun/blueprint/components/visible.fbs +++ b/crates/re_types/definitions/rerun/blueprint/components/visible.fbs @@ -9,7 +9,7 @@ namespace rerun.blueprint.components; // --- -/// Whether the container, space view, entity or instance is currently visible. +/// Whether the container, view, entity or instance is currently visible. struct Visible ( "attr.arrow.transparent", "attr.rerun.scope": "blueprint", diff --git a/crates/re_types/src/blueprint/components/.gitattributes b/crates/re_types/src/blueprint/components/.gitattributes index e1a76cba51a7..e3b52f6662ed 100644 --- a/crates/re_types/src/blueprint/components/.gitattributes +++ b/crates/re_types/src/blueprint/components/.gitattributes @@ -6,6 +6,7 @@ background_kind.rs linguist-generated=true column_share.rs linguist-generated=true corner2d.rs linguist-generated=true included_content.rs linguist-generated=true +interactive.rs linguist-generated=true lock_range_during_zoom.rs linguist-generated=true mod.rs linguist-generated=true panel_state.rs linguist-generated=true diff --git a/crates/re_types/src/blueprint/components/interactive.rs b/crates/re_types/src/blueprint/components/interactive.rs new file mode 100644 index 000000000000..f364620a878a --- /dev/null +++ b/crates/re_types/src/blueprint/components/interactive.rs @@ -0,0 +1,150 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/blueprint/components/interactive.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Component**: Whether the entity can be interacted with. +/// +/// Non interactive components are still visible, but mouse iteractions in the view are disabled. +#[derive(Clone, Debug, Copy, Default, PartialEq, Eq, PartialOrd, Ord)] +#[repr(transparent)] +pub struct Interactive(pub crate::datatypes::Bool); + +impl ::re_types_core::SizeBytes for Interactive { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.0.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + } +} + +impl> From for Interactive { + fn from(v: T) -> Self { + Self(v.into()) + } +} + +impl std::borrow::Borrow for Interactive { + #[inline] + fn borrow(&self) -> &crate::datatypes::Bool { + &self.0 + } +} + +impl std::ops::Deref for Interactive { + type Target = crate::datatypes::Bool; + + #[inline] + fn deref(&self) -> &crate::datatypes::Bool { + &self.0 + } +} + +impl std::ops::DerefMut for Interactive { + #[inline] + fn deref_mut(&mut self) -> &mut crate::datatypes::Bool { + &mut self.0 + } +} + +::re_types_core::macros::impl_into_cow!(Interactive); + +impl ::re_types_core::Loggable for Interactive { + type Name = ::re_types_core::ComponentName; + + #[inline] + fn name() -> Self::Name { + "rerun.blueprint.components.Interactive".into() + } + + #[allow(clippy::wildcard_imports)] + #[inline] + fn arrow_datatype() -> arrow2::datatypes::DataType { + use arrow2::datatypes::*; + DataType::Boolean + } + + #[allow(clippy::wildcard_imports)] + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult> + where + Self: Clone + 'a, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, datatypes::*}; + Ok({ + let (somes, data0): (Vec<_>, Vec<_>) = data + .into_iter() + .map(|datum| { + let datum: Option<::std::borrow::Cow<'a, Self>> = datum.map(Into::into); + let datum = datum.map(|datum| datum.into_owned().0); + (datum.is_some(), datum) + }) + .unzip(); + let data0_bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + BooleanArray::new( + Self::arrow_datatype(), + data0 + .into_iter() + .map(|datum| datum.map(|datum| datum.0).unwrap_or_default()) + .collect(), + data0_bitmap, + ) + .boxed() + }) + } + + #[allow(clippy::wildcard_imports)] + fn from_arrow_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, buffer::*, datatypes::*}; + Ok(arrow_data + .as_any() + .downcast_ref::() + .ok_or_else(|| { + let expected = Self::arrow_datatype(); + let actual = arrow_data.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) + }) + .with_context("rerun.blueprint.components.Interactive#interactive")? + .into_iter() + .map(|res_or_opt| res_or_opt.map(|v| crate::datatypes::Bool(v))) + .map(|v| v.ok_or_else(DeserializationError::missing_data)) + .map(|res| res.map(|v| Some(Self(v)))) + .collect::>>>() + .with_context("rerun.blueprint.components.Interactive#interactive") + .with_context("rerun.blueprint.components.Interactive")?) + } +} diff --git a/crates/re_types/src/blueprint/components/mod.rs b/crates/re_types/src/blueprint/components/mod.rs index cc1b48d2f5ac..8cd4fc1df758 100644 --- a/crates/re_types/src/blueprint/components/mod.rs +++ b/crates/re_types/src/blueprint/components/mod.rs @@ -6,6 +6,7 @@ mod column_share; mod corner2d; mod corner2d_ext; mod included_content; +mod interactive; mod lock_range_during_zoom; mod panel_state; mod panel_state_ext; @@ -28,6 +29,7 @@ pub use self::background_kind::BackgroundKind; pub use self::column_share::ColumnShare; pub use self::corner2d::Corner2D; pub use self::included_content::IncludedContent; +pub use self::interactive::Interactive; pub use self::lock_range_during_zoom::LockRangeDuringZoom; pub use self::panel_state::PanelState; pub use self::query_expression::QueryExpression; diff --git a/crates/re_types/src/blueprint/components/visible.rs b/crates/re_types/src/blueprint/components/visible.rs index 6634016dc492..92f4bbcb2253 100644 --- a/crates/re_types/src/blueprint/components/visible.rs +++ b/crates/re_types/src/blueprint/components/visible.rs @@ -22,7 +22,7 @@ use ::re_types_core::SerializationResult; use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; -/// **Component**: Whether the container, space view, entity or instance is currently visible. +/// **Component**: Whether the container, view, entity or instance is currently visible. #[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord)] #[repr(transparent)] pub struct Visible(pub bool); diff --git a/crates/re_viewer/src/blueprint/validation_gen/mod.rs b/crates/re_viewer/src/blueprint/validation_gen/mod.rs index 4e9fec40c0c4..c4d1f904c4e4 100644 --- a/crates/re_viewer/src/blueprint/validation_gen/mod.rs +++ b/crates/re_viewer/src/blueprint/validation_gen/mod.rs @@ -7,6 +7,7 @@ pub use re_types::blueprint::components::BackgroundKind; pub use re_types::blueprint::components::ColumnShare; pub use re_types::blueprint::components::Corner2D; pub use re_types::blueprint::components::IncludedContent; +pub use re_types::blueprint::components::Interactive; pub use re_types::blueprint::components::LockRangeDuringZoom; pub use re_types::blueprint::components::PanelState; pub use re_types::blueprint::components::QueryExpression; @@ -40,6 +41,7 @@ pub fn is_valid_blueprint(blueprint: &EntityDb) -> bool { && validate_component::(blueprint) && validate_component::(blueprint) && validate_component::(blueprint) + && validate_component::(blueprint) && validate_component::(blueprint) && validate_component::(blueprint) && validate_component::(blueprint) diff --git a/crates/re_viewer/src/component_defaults/mod.rs b/crates/re_viewer/src/component_defaults/mod.rs index e73c7045b887..40ad6c3b8b77 100644 --- a/crates/re_viewer/src/component_defaults/mod.rs +++ b/crates/re_viewer/src/component_defaults/mod.rs @@ -59,6 +59,10 @@ pub fn list_default_components( ::name(), IncludedSpaceView::default().to_arrow()?, ), + ( + ::name(), + Interactive::default().to_arrow()?, + ), ( ::name(), LockRangeDuringZoom::default().to_arrow()?, diff --git a/rerun_cpp/src/rerun/blueprint/components.hpp b/rerun_cpp/src/rerun/blueprint/components.hpp index 577118b8d830..a04e70df58de 100644 --- a/rerun_cpp/src/rerun/blueprint/components.hpp +++ b/rerun_cpp/src/rerun/blueprint/components.hpp @@ -13,6 +13,7 @@ #include "blueprint/components/grid_columns.hpp" #include "blueprint/components/included_content.hpp" #include "blueprint/components/included_space_view.hpp" +#include "blueprint/components/interactive.hpp" #include "blueprint/components/lock_range_during_zoom.hpp" #include "blueprint/components/panel_state.hpp" #include "blueprint/components/query_expression.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/components/.gitattributes b/rerun_cpp/src/rerun/blueprint/components/.gitattributes index f0d60f96bab5..70cbc1aeb15e 100644 --- a/rerun_cpp/src/rerun/blueprint/components/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/components/.gitattributes @@ -20,6 +20,7 @@ grid_columns.cpp linguist-generated=true grid_columns.hpp linguist-generated=true included_content.hpp linguist-generated=true included_space_view.hpp linguist-generated=true +interactive.hpp linguist-generated=true lock_range_during_zoom.hpp linguist-generated=true panel_state.cpp linguist-generated=true panel_state.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/components/interactive.hpp b/rerun_cpp/src/rerun/blueprint/components/interactive.hpp new file mode 100644 index 000000000000..49964535aa1b --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/components/interactive.hpp @@ -0,0 +1,66 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/components/interactive.fbs". + +#pragma once + +#include "../../datatypes/bool.hpp" +#include "../../result.hpp" + +#include +#include + +namespace rerun::blueprint::components { + /// **Component**: Whether the entity can be interacted with. + /// + /// Non interactive components are still visible, but mouse iteractions in the view are disabled. + struct Interactive { + rerun::datatypes::Bool interactive; + + public: + Interactive() = default; + + Interactive(rerun::datatypes::Bool interactive_) : interactive(interactive_) {} + + Interactive& operator=(rerun::datatypes::Bool interactive_) { + interactive = interactive_; + return *this; + } + + Interactive(bool value_) : interactive(value_) {} + + Interactive& operator=(bool value_) { + interactive = value_; + return *this; + } + + /// Cast to the underlying Bool datatype + operator rerun::datatypes::Bool() const { + return interactive; + } + }; +} // namespace rerun::blueprint::components + +namespace rerun { + static_assert(sizeof(rerun::datatypes::Bool) == sizeof(blueprint::components::Interactive)); + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.blueprint.components.Interactive"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } + + /// Serializes an array of `rerun::blueprint:: components::Interactive` into an arrow array. + static Result> to_arrow( + const blueprint::components::Interactive* instances, size_t num_instances + ) { + return Loggable::to_arrow( + &instances->interactive, + num_instances + ); + } + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/visible.hpp b/rerun_cpp/src/rerun/blueprint/components/visible.hpp index 510a46cacf34..0a46dc35008a 100644 --- a/rerun_cpp/src/rerun/blueprint/components/visible.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/visible.hpp @@ -15,7 +15,7 @@ namespace arrow { } // namespace arrow namespace rerun::blueprint::components { - /// **Component**: Whether the container, space view, entity or instance is currently visible. + /// **Component**: Whether the container, view, entity or instance is currently visible. struct Visible { bool visible; diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes index e0d6a940b940..311929e15e4f 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes @@ -13,6 +13,7 @@ entity_properties_component.py linguist-generated=true grid_columns.py linguist-generated=true included_content.py linguist-generated=true included_space_view.py linguist-generated=true +interactive.py linguist-generated=true lock_range_during_zoom.py linguist-generated=true panel_state.py linguist-generated=true query_expression.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py index cca68bfa447e..39c13ad26795 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py @@ -37,6 +37,7 @@ from .grid_columns import GridColumns, GridColumnsArrayLike, GridColumnsBatch, GridColumnsLike, GridColumnsType from .included_content import IncludedContent, IncludedContentBatch, IncludedContentType from .included_space_view import IncludedSpaceView, IncludedSpaceViewBatch, IncludedSpaceViewType +from .interactive import Interactive, InteractiveBatch, InteractiveType from .lock_range_during_zoom import LockRangeDuringZoom, LockRangeDuringZoomBatch, LockRangeDuringZoomType from .panel_state import PanelState, PanelStateArrayLike, PanelStateBatch, PanelStateLike, PanelStateType from .query_expression import QueryExpression, QueryExpressionBatch, QueryExpressionType @@ -104,6 +105,9 @@ "IncludedSpaceView", "IncludedSpaceViewBatch", "IncludedSpaceViewType", + "Interactive", + "InteractiveBatch", + "InteractiveType", "LockRangeDuringZoom", "LockRangeDuringZoomBatch", "LockRangeDuringZoomType", diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/interactive.py b/rerun_py/rerun_sdk/rerun/blueprint/components/interactive.py new file mode 100644 index 000000000000..824ed8be59cf --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/interactive.py @@ -0,0 +1,32 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/components/interactive.fbs". + +# You can extend this class by creating a "InteractiveExt" class in "interactive_ext.py". + +from __future__ import annotations + +from ... import datatypes +from ..._baseclasses import ComponentBatchMixin + +__all__ = ["Interactive", "InteractiveBatch", "InteractiveType"] + + +class Interactive(datatypes.Bool): + """ + **Component**: Whether the entity can be interacted with. + + Non interactive components are still visible, but mouse iteractions in the view are disabled. + """ + + # You can define your own __init__ function as a member of InteractiveExt in interactive_ext.py + + # Note: there are no fields here because Interactive delegates to datatypes.Bool + pass + + +class InteractiveType(datatypes.BoolType): + _TYPE_NAME: str = "rerun.blueprint.components.Interactive" + + +class InteractiveBatch(datatypes.BoolBatch, ComponentBatchMixin): + _ARROW_TYPE = InteractiveType() diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/visible.py b/rerun_py/rerun_sdk/rerun/blueprint/components/visible.py index 59d3fbc9a6e5..6d3cc01f7514 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/visible.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/visible.py @@ -18,7 +18,7 @@ @define(init=False) class Visible: - """**Component**: Whether the container, space view, entity or instance is currently visible.""" + """**Component**: Whether the container, view, entity or instance is currently visible.""" def __init__(self: Any, visible: VisibleLike): """Create a new instance of the Visible component.""" From b537e258e9de067a1e2ba6348f3bb1d8166aad4b Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 11 Jun 2024 16:02:56 +0200 Subject: [PATCH 2/5] Use new `Interactive` component --- crates/re_entity_db/src/entity_properties.rs | 13 ++-- .../re_selection_panel/src/selection_panel.rs | 76 +++++++++++++------ crates/re_space_view_spatial/src/ui.rs | 2 +- .../blueprint/components/interactive_ext.rs | 8 ++ crates/re_types/src/datatypes/bool_ext.rs | 12 +++ crates/re_types/src/lib.rs | 1 + .../src/space_view/view_query.rs | 30 +++++++- .../re_viewport_blueprint/src/space_view.rs | 10 +-- 8 files changed, 114 insertions(+), 38 deletions(-) create mode 100644 crates/re_types/src/blueprint/components/interactive_ext.rs create mode 100644 crates/re_types/src/datatypes/bool_ext.rs diff --git a/crates/re_entity_db/src/entity_properties.rs b/crates/re_entity_db/src/entity_properties.rs index 4493d2e0bba3..0199af77f020 100644 --- a/crates/re_entity_db/src/entity_properties.rs +++ b/crates/re_entity_db/src/entity_properties.rs @@ -94,7 +94,8 @@ 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 interactive: bool, // TODO(andreas): similar to `visible`, needs to become a regular (slightly special - doesn't show up in archetypes) component. + // TODO(#5067): Test property used so we don't have to continously adjust existing tests while we're dismantling `EntityProperties`. + pub test_property: bool, /// What kind of color mapping should be applied (none, map, texture, transfer..)? pub color_mapper: EditableAutoValue, // TODO(andreas): should become a component and be part of the DepthImage and regular Images (with limitation to mono channel image). @@ -122,7 +123,7 @@ pub struct EntityProperties { impl Default for EntityProperties { fn default() -> Self { Self { - interactive: true, + test_property: true, color_mapper: EditableAutoValue::default(), backproject_depth: EditableAutoValue::Auto(true), depth_from_world_scale: EditableAutoValue::Auto(1.0), @@ -137,7 +138,7 @@ impl EntityProperties { /// Multiply/and these together. pub fn with_child(&self, child: &Self) -> Self { Self { - interactive: self.interactive && child.interactive, + test_property: self.test_property && child.test_property, color_mapper: self.color_mapper.or(&child.color_mapper).clone(), @@ -167,7 +168,7 @@ 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 { - interactive: other.interactive, + test_property: other.test_property, color_mapper: other.color_mapper.or(&self.color_mapper).clone(), @@ -191,7 +192,7 @@ impl EntityProperties { /// Determine whether this `EntityProperty` has user-edits relative to another `EntityProperty` pub fn has_edits(&self, other: &Self) -> bool { let Self { - interactive, + test_property, color_mapper, backproject_depth, depth_from_world_scale, @@ -199,7 +200,7 @@ impl EntityProperties { time_series_aggregator, } = self; - interactive != &other.interactive + test_property != &other.test_property || color_mapper.has_edits(&other.color_mapper) || backproject_depth.has_edits(&other.backproject_depth) || depth_from_world_scale.has_edits(&other.depth_from_world_scale) diff --git a/crates/re_selection_panel/src/selection_panel.rs b/crates/re_selection_panel/src/selection_panel.rs index e39169908605..2e7cf64c5f4e 100644 --- a/crates/re_selection_panel/src/selection_panel.rs +++ b/crates/re_selection_panel/src/selection_panel.rs @@ -15,6 +15,7 @@ use re_space_view::DataResultQuery as _; use re_space_view_time_series::TimeSeriesSpaceView; use re_types::{ archetypes::{Axes3D, Pinhole}, + blueprint::components::Interactive, components::{ AxisLength, ImagePlaneDistance, PinholeProjection, Transform3D, VisualizerOverrides, }, @@ -1184,33 +1185,64 @@ fn entity_props_ui( let entity_path = &data_result.entity_path; - { - let visible_before = data_result.is_visible(ctx.viewer_ctx); - let mut visible = visible_before; + list_item::list_item_scope(ui, "entity_props", |ui| { + { + let visible_before = data_result.is_visible(ctx.viewer_ctx); + let mut visible = visible_before; - let override_source = - data_result.component_override_source(&query_result.tree, &Visible::name()); - let is_inherited = - override_source.is_some() && override_source.as_ref() != Some(entity_path); + let inherited_hint = if data_result.is_inherited(&query_result.tree, Visible::name()) { + "\n\nVisible status was inherited from a parent entity." + } else { + "" + }; - ui.horizontal(|ui| { - ui.re_checkbox(&mut visible, "Visible"); - if is_inherited { - ui.label("(inherited)"); - } - }); + ui.list_item() + .interactive(false) + .show_flat( + ui, + list_item::PropertyContent::new("Visible").value_bool_mut(&mut visible), + ) + .on_hover_text(format!( + "If disabled, the entity won't be shown in the view.{inherited_hint}" + )); - if visible_before != visible { - data_result.save_recursive_override_or_clear_if_redundant( - ctx.viewer_ctx, - &query_result.tree, - &Visible(visible), - ); + if visible_before != visible { + data_result.save_recursive_override_or_clear_if_redundant( + ctx.viewer_ctx, + &query_result.tree, + &Visible(visible), + ); + } } - } - ui.re_checkbox(&mut entity_props.interactive, "Interactive") - .on_hover_text("If disabled, the entity will not react to any mouse interaction"); + { + let interactive_before = data_result.is_interactive(ctx.viewer_ctx); + let mut interactive = interactive_before; + + let inherited_hint = + if data_result.is_inherited(&query_result.tree, Interactive::name()) { + "\n\nInteractive status was inherited from a parent entity." + } else { + "" + }; + + ui.list_item() + .interactive(false) + .show_flat( + ui, + list_item::PropertyContent::new("Interactive").value_bool_mut(&mut interactive), + ) + .on_hover_text(format!("If disabled, the entity will not react to any mouse interaction.{inherited_hint}")); + + if interactive_before != interactive { + data_result.save_recursive_override_or_clear_if_redundant( + ctx.viewer_ctx, + &query_result.tree, + &Interactive(interactive.into()), + ); + } + } + }); query_range_ui_data_result(ctx.viewer_ctx, ui, data_result); diff --git a/crates/re_space_view_spatial/src/ui.rs b/crates/re_space_view_spatial/src/ui.rs index fd3cd3e299bf..7e855d652d3d 100644 --- a/crates/re_space_view_spatial/src/ui.rs +++ b/crates/re_space_view_spatial/src/ui.rs @@ -488,7 +488,7 @@ pub fn picking( .lookup_query_result(query.space_view_id) .tree .lookup_result_by_path(&instance_path.entity_path) - .map_or(false, |result| result.accumulated_properties().interactive); + .map_or(false, |result| result.is_interactive(ctx)); if !interactive { continue; } diff --git a/crates/re_types/src/blueprint/components/interactive_ext.rs b/crates/re_types/src/blueprint/components/interactive_ext.rs new file mode 100644 index 000000000000..51edb22c512c --- /dev/null +++ b/crates/re_types/src/blueprint/components/interactive_ext.rs @@ -0,0 +1,8 @@ +use super::Interactive; + +impl Default for Interactive { + #[inline] + fn default() -> Self { + Self(true) + } +} diff --git a/crates/re_types/src/datatypes/bool_ext.rs b/crates/re_types/src/datatypes/bool_ext.rs new file mode 100644 index 000000000000..e69408b1d06a --- /dev/null +++ b/crates/re_types/src/datatypes/bool_ext.rs @@ -0,0 +1,12 @@ +use std::ops::Deref; + +use super::Bool; + +impl Deref for Bool { + type Target = bool; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/crates/re_types/src/lib.rs b/crates/re_types/src/lib.rs index 655d42b0a3ff..6c27bc038874 100644 --- a/crates/re_types/src/lib.rs +++ b/crates/re_types/src/lib.rs @@ -238,6 +238,7 @@ pub mod datatypes { #[path = "../datatypes/mod.rs"] mod _datatypes; + mod bool_ext; pub use self::_datatypes::*; pub use re_types_core::datatypes::*; diff --git a/crates/re_viewer_context/src/space_view/view_query.rs b/crates/re_viewer_context/src/space_view/view_query.rs index ea1914c32111..6ec22f9ce511 100644 --- a/crates/re_viewer_context/src/space_view/view_query.rs +++ b/crates/re_viewer_context/src/space_view/view_query.rs @@ -377,11 +377,10 @@ impl DataResult { /// /// Returns None if there was no override at all. /// Note that if this returns the current path, the override might be either an individual or recursive override. - #[inline] pub fn component_override_source( &self, result_tree: &DataResultTree, - component_name: &ComponentName, + component_name: ComponentName, ) -> Option { re_tracing::profile_function!(); @@ -389,7 +388,7 @@ impl DataResult { let active_override = self .property_overrides .as_ref() - .and_then(|p| p.resolved_component_overrides.get(component_name))?; + .and_then(|p| p.resolved_component_overrides.get(&component_name))?; // Walk up the tree to find the highest ancestor which has a matching override. // This must be the ancestor we inherited the override from. Note that `active_override` @@ -404,7 +403,7 @@ impl DataResult { // This should access `recursive_component_overrides` instead. property_overrides .resolved_component_overrides - .get(component_name) + .get(&component_name) != Some(active_override) }) { @@ -417,6 +416,16 @@ impl DataResult { Some(override_source) } + /// Returns true if the current component's value was inherited from a parent entity. + pub fn is_inherited( + &self, + result_tree: &DataResultTree, + component_name: ComponentName, + ) -> bool { + let override_source = self.component_override_source(result_tree, component_name); + override_source.is_some() && override_source.as_ref() != Some(&self.entity_path) + } + /// Shorthand for checking for visibility on data overrides. /// /// Note that this won't check if the data store has visibility logged. @@ -429,6 +438,19 @@ impl DataResult { .0 } + /// Shorthand for checking for interactivity on data overrides. + /// + /// Note that this won't check if the data store has interactivity logged. + // TODO(andreas): Should this be possible? + // TODO(andreas): Should the result be cached, this might be a very common operation? + #[inline] + pub fn is_interactive(&self, ctx: &ViewerContext<'_>) -> bool { + *self + .lookup_override::(ctx) + .unwrap_or_default() + .0 + } + /// Returns the query range for this data result. pub fn query_range(&self) -> &QueryRange { const DEFAULT_RANGE: QueryRange = QueryRange::LatestAt; diff --git a/crates/re_viewport_blueprint/src/space_view.rs b/crates/re_viewport_blueprint/src/space_view.rs index d59c3c1c2dd9..2091ac4175ea 100644 --- a/crates/re_viewport_blueprint/src/space_view.rs +++ b/crates/re_viewport_blueprint/src/space_view.rs @@ -636,7 +636,7 @@ mod tests { // Now, override interactive on parent individually. let mut overrides = parent.individual_properties().cloned().unwrap_or_default(); - overrides.interactive = false; + overrides.test_property = false; save_override( overrides, @@ -672,10 +672,10 @@ mod tests { .lookup_result_by_path(&EntityPath::from("parent/skip/child2")) .unwrap(); - assert!(!parent.accumulated_properties().interactive); + assert!(!parent.accumulated_properties().test_property); for result in [child1, child2] { - assert!(result.accumulated_properties().interactive); + assert!(result.accumulated_properties().test_property); } // Override interactivity on parent recursively. @@ -683,7 +683,7 @@ mod tests { .individual_properties() .cloned() .unwrap_or_default(); - overrides.interactive = false; + overrides.test_property = false; save_override( overrides, @@ -715,7 +715,7 @@ mod tests { .unwrap(); for result in [parent, child1, child2] { - assert!(!result.accumulated_properties().interactive); + assert!(!result.accumulated_properties().test_property); } } } From 22212ab928e603392f1f721c1f425b803dacb569 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 11 Jun 2024 16:07:33 +0200 Subject: [PATCH 3/5] fixed messed up `mod` & default impl --- .../definitions/rerun/blueprint/components/interactive.fbs | 2 +- crates/re_types/src/blueprint/components/interactive.rs | 2 +- crates/re_types/src/blueprint/components/interactive_ext.rs | 2 +- crates/re_types/src/blueprint/components/mod.rs | 1 + crates/re_types/src/datatypes/mod.rs | 1 + crates/re_types/src/lib.rs | 1 - 6 files changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/re_types/definitions/rerun/blueprint/components/interactive.fbs b/crates/re_types/definitions/rerun/blueprint/components/interactive.fbs index fb2a8e339e59..c5060f07e914 100644 --- a/crates/re_types/definitions/rerun/blueprint/components/interactive.fbs +++ b/crates/re_types/definitions/rerun/blueprint/components/interactive.fbs @@ -14,7 +14,7 @@ namespace rerun.blueprint.components; /// Non interactive components are still visible, but mouse iteractions in the view are disabled. struct Interactive ( "attr.rerun.scope": "blueprint", - "attr.rust.derive": "Copy, Default, PartialEq, Eq, PartialOrd, Ord", + "attr.rust.derive": "Copy, PartialEq, Eq, PartialOrd, Ord", "attr.rust.repr": "transparent", "attr.rust.tuple_struct" ) { diff --git a/crates/re_types/src/blueprint/components/interactive.rs b/crates/re_types/src/blueprint/components/interactive.rs index f364620a878a..3a5489223f3b 100644 --- a/crates/re_types/src/blueprint/components/interactive.rs +++ b/crates/re_types/src/blueprint/components/interactive.rs @@ -25,7 +25,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Component**: Whether the entity can be interacted with. /// /// Non interactive components are still visible, but mouse iteractions in the view are disabled. -#[derive(Clone, Debug, Copy, Default, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord)] #[repr(transparent)] pub struct Interactive(pub crate::datatypes::Bool); diff --git a/crates/re_types/src/blueprint/components/interactive_ext.rs b/crates/re_types/src/blueprint/components/interactive_ext.rs index 51edb22c512c..b52f93aef7ee 100644 --- a/crates/re_types/src/blueprint/components/interactive_ext.rs +++ b/crates/re_types/src/blueprint/components/interactive_ext.rs @@ -3,6 +3,6 @@ use super::Interactive; impl Default for Interactive { #[inline] fn default() -> Self { - Self(true) + Self(true.into()) } } diff --git a/crates/re_types/src/blueprint/components/mod.rs b/crates/re_types/src/blueprint/components/mod.rs index 8cd4fc1df758..b9de2e1b482e 100644 --- a/crates/re_types/src/blueprint/components/mod.rs +++ b/crates/re_types/src/blueprint/components/mod.rs @@ -7,6 +7,7 @@ mod corner2d; mod corner2d_ext; mod included_content; mod interactive; +mod interactive_ext; mod lock_range_during_zoom; mod panel_state; mod panel_state_ext; diff --git a/crates/re_types/src/datatypes/mod.rs b/crates/re_types/src/datatypes/mod.rs index d2f880d5d8f1..5b113ce47dee 100644 --- a/crates/re_types/src/datatypes/mod.rs +++ b/crates/re_types/src/datatypes/mod.rs @@ -5,6 +5,7 @@ mod angle_ext; mod annotation_info; mod annotation_info_ext; mod bool; +mod bool_ext; mod class_description; mod class_description_ext; mod class_description_map_elem; diff --git a/crates/re_types/src/lib.rs b/crates/re_types/src/lib.rs index 6c27bc038874..655d42b0a3ff 100644 --- a/crates/re_types/src/lib.rs +++ b/crates/re_types/src/lib.rs @@ -238,7 +238,6 @@ pub mod datatypes { #[path = "../datatypes/mod.rs"] mod _datatypes; - mod bool_ext; pub use self::_datatypes::*; pub use re_types_core::datatypes::*; From 8091087b1b930db8d60b9cc48ede19e0c2563bd5 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 11 Jun 2024 16:13:22 +0200 Subject: [PATCH 4/5] leave notes to #6541 --- crates/re_viewer_context/src/space_view/view_query.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/re_viewer_context/src/space_view/view_query.rs b/crates/re_viewer_context/src/space_view/view_query.rs index 6ec22f9ce511..15230fbb7581 100644 --- a/crates/re_viewer_context/src/space_view/view_query.rs +++ b/crates/re_viewer_context/src/space_view/view_query.rs @@ -429,8 +429,7 @@ impl DataResult { /// Shorthand for checking for visibility on data overrides. /// /// Note that this won't check if the data store has visibility logged. - // TODO(andreas): Should this be possible? - // TODO(andreas): Should the result be cached, this might be a very common operation? + // TODO(#6541): Check the datastore. #[inline] pub fn is_visible(&self, ctx: &ViewerContext<'_>) -> bool { self.lookup_override::(ctx) @@ -441,8 +440,7 @@ impl DataResult { /// Shorthand for checking for interactivity on data overrides. /// /// Note that this won't check if the data store has interactivity logged. - // TODO(andreas): Should this be possible? - // TODO(andreas): Should the result be cached, this might be a very common operation? + // TODO(#6541): Check the datastore. #[inline] pub fn is_interactive(&self, ctx: &ViewerContext<'_>) -> bool { *self From 90004d9f26da423026f7917dca9cf837d96e2742 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 11 Jun 2024 16:15:38 +0200 Subject: [PATCH 5/5] typo fix --- crates/re_entity_db/src/entity_properties.rs | 2 +- .../definitions/rerun/blueprint/components/interactive.fbs | 2 +- crates/re_types/src/blueprint/components/interactive.rs | 2 +- rerun_cpp/src/rerun/blueprint/components/interactive.hpp | 2 +- rerun_py/rerun_sdk/rerun/blueprint/components/interactive.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/re_entity_db/src/entity_properties.rs b/crates/re_entity_db/src/entity_properties.rs index 0199af77f020..5cac538ae3de 100644 --- a/crates/re_entity_db/src/entity_properties.rs +++ b/crates/re_entity_db/src/entity_properties.rs @@ -94,7 +94,7 @@ impl FromIterator<(EntityPath, EntityProperties)> for EntityPropertyMap { #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", serde(default))] pub struct EntityProperties { - // TODO(#5067): Test property used so we don't have to continously adjust existing tests while we're dismantling `EntityProperties`. + // TODO(#5067): Test property used so we don't have to continuously adjust existing tests while we're dismantling `EntityProperties`. pub test_property: bool, /// What kind of color mapping should be applied (none, map, texture, transfer..)? diff --git a/crates/re_types/definitions/rerun/blueprint/components/interactive.fbs b/crates/re_types/definitions/rerun/blueprint/components/interactive.fbs index c5060f07e914..d94cd45c99c9 100644 --- a/crates/re_types/definitions/rerun/blueprint/components/interactive.fbs +++ b/crates/re_types/definitions/rerun/blueprint/components/interactive.fbs @@ -11,7 +11,7 @@ namespace rerun.blueprint.components; /// Whether the entity can be interacted with. /// -/// Non interactive components are still visible, but mouse iteractions in the view are disabled. +/// Non interactive components are still visible, but mouse interactions in the view are disabled. struct Interactive ( "attr.rerun.scope": "blueprint", "attr.rust.derive": "Copy, PartialEq, Eq, PartialOrd, Ord", diff --git a/crates/re_types/src/blueprint/components/interactive.rs b/crates/re_types/src/blueprint/components/interactive.rs index 3a5489223f3b..672f1f142223 100644 --- a/crates/re_types/src/blueprint/components/interactive.rs +++ b/crates/re_types/src/blueprint/components/interactive.rs @@ -24,7 +24,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Component**: Whether the entity can be interacted with. /// -/// Non interactive components are still visible, but mouse iteractions in the view are disabled. +/// Non interactive components are still visible, but mouse interactions in the view are disabled. #[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord)] #[repr(transparent)] pub struct Interactive(pub crate::datatypes::Bool); diff --git a/rerun_cpp/src/rerun/blueprint/components/interactive.hpp b/rerun_cpp/src/rerun/blueprint/components/interactive.hpp index 49964535aa1b..778353aace85 100644 --- a/rerun_cpp/src/rerun/blueprint/components/interactive.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/interactive.hpp @@ -12,7 +12,7 @@ namespace rerun::blueprint::components { /// **Component**: Whether the entity can be interacted with. /// - /// Non interactive components are still visible, but mouse iteractions in the view are disabled. + /// Non interactive components are still visible, but mouse interactions in the view are disabled. struct Interactive { rerun::datatypes::Bool interactive; diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/interactive.py b/rerun_py/rerun_sdk/rerun/blueprint/components/interactive.py index 824ed8be59cf..df4b4c3d8a7b 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/interactive.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/interactive.py @@ -15,7 +15,7 @@ class Interactive(datatypes.Bool): """ **Component**: Whether the entity can be interacted with. - Non interactive components are still visible, but mouse iteractions in the view are disabled. + Non interactive components are still visible, but mouse interactions in the view are disabled. """ # You can define your own __init__ function as a member of InteractiveExt in interactive_ext.py