diff --git a/Cargo.lock b/Cargo.lock index cba234963c38..f41c6edc923b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2455,9 +2455,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "fjadra" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccc0416b27f53bba6c9bd564260f27d4784c5f430926eb16a519356be7d66bbc" +checksum = "d8d17b174735bd1464bc491c49570fc824466e9140617c371de9a6d86ebd33ec" [[package]] name = "flatbuffers" @@ -5999,7 +5999,6 @@ dependencies = [ "bytemuck", "clean-path", "criterion", - "crossbeam", "document-features", "fixed", "half", @@ -6393,6 +6392,7 @@ dependencies = [ "re_data_ui", "re_entity_db", "re_format", + "re_log", "re_log_types", "re_query", "re_renderer", diff --git a/Cargo.toml b/Cargo.toml index ab7e374f6c69..75aebebf1c04 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -190,7 +190,7 @@ enumset = "1.0.12" env_logger = { version = "0.10", default-features = false } ffmpeg-sidecar = { version = "2.0.2", default-features = false } fixed = { version = "1.28", default-features = false } -fjadra = "0.1" +fjadra = "0.2" flatbuffers = "23.0" futures-channel = "0.3" futures-util = { version = "0.3", default-features = false } diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes.fbs index 448b93b16a60..ec814ca64051 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes.fbs @@ -3,6 +3,11 @@ include "./archetypes/background.fbs"; include "./archetypes/container_blueprint.fbs"; include "./archetypes/dataframe_query.fbs"; +include "./archetypes/force_center.fbs"; +include "./archetypes/force_collision_radius.fbs"; +include "./archetypes/force_link.fbs"; +include "./archetypes/force_many_body.fbs"; +include "./archetypes/force_position.fbs"; include "./archetypes/line_grid3d.fbs"; include "./archetypes/map_background.fbs"; include "./archetypes/map_zoom.fbs"; diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_center.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_center.fbs new file mode 100644 index 000000000000..c3b477bf49d0 --- /dev/null +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_center.fbs @@ -0,0 +1,12 @@ +namespace rerun.blueprint.archetypes; + +/// Tries to move the center of mass of the graph to the origin. +struct ForceCenter ( + "attr.rerun.scope": "blueprint" +) { + /// Whether the force is enabled. + enabled: rerun.blueprint.components.Enabled ("attr.rerun.component_optional", nullable, order: 100); + + /// The strength of the force. + strength: rerun.blueprint.components.ForceStrength ("attr.rerun.component_optional", nullable, order: 200); +} diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_collision_radius.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_collision_radius.fbs new file mode 100644 index 000000000000..9ffcf43376ff --- /dev/null +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_collision_radius.fbs @@ -0,0 +1,17 @@ +namespace rerun.blueprint.archetypes; + +/// Resolves collisions between the bounding spheres, according to the radius of the nodes. +struct ForceCollisionRadius ( + "attr.rerun.scope": "blueprint" +) { + /// Whether the force is enabled. + enabled: rerun.blueprint.components.Enabled ("attr.rerun.component_optional", nullable, order: 100); + + /// The strength of the force. + strength: rerun.blueprint.components.ForceStrength ("attr.rerun.component_optional", nullable, order: 200); + + /// Specifies how often this force should be applied per iteration. + /// + /// Increasing this parameter can lead to better results at the cost of longer computation time. + iterations: rerun.blueprint.components.ForceIterations ("attr.rerun.component_optional", nullable, order: 300); +} diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_link.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_link.fbs new file mode 100644 index 000000000000..fc963b757cf3 --- /dev/null +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_link.fbs @@ -0,0 +1,17 @@ +namespace rerun.blueprint.archetypes; + +/// Aims to achieve a target distance between two nodes that are connected by an edge. +struct ForceLink ( + "attr.rerun.scope": "blueprint" +) { + /// Whether the force is enabled. + enabled: rerun.blueprint.components.Enabled ("attr.rerun.component_optional", nullable, order: 100); + + /// The target distance between two nodes. + distance: rerun.blueprint.components.ForceDistance ("attr.rerun.component_optional", nullable, order: 200); + + /// Specifies how often this force should be applied per iteration. + /// + /// Increasing this parameter can lead to better results at the cost of longer computation time. + iterations: rerun.blueprint.components.ForceIterations ("attr.rerun.component_optional", nullable, order: 300); +} diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_many_body.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_many_body.fbs new file mode 100644 index 000000000000..edafce01c777 --- /dev/null +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_many_body.fbs @@ -0,0 +1,16 @@ +namespace rerun.blueprint.archetypes; + +/// A force between each pair of nodes that ressembles an electrical charge. +/// +/// If `strength` is smaller than 0, it pushes nodes apart, if it is larger than 0 it pulls them together. +struct ForceManyBody ( + "attr.rerun.scope": "blueprint" +) { + /// Whether the force is enabled. + enabled: rerun.blueprint.components.Enabled ("attr.rerun.component_optional", nullable, order: 100); + + /// The strength of the force. + /// + /// If `strength` is smaller than 0, it pushes nodes apart, if it is larger than 0 it pulls them together. + strength: rerun.blueprint.components.ForceStrength ("attr.rerun.component_optional", nullable, order: 200); +} diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_position.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_position.fbs new file mode 100644 index 000000000000..7ff9fd24d340 --- /dev/null +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_position.fbs @@ -0,0 +1,15 @@ +namespace rerun.blueprint.archetypes; + +/// Similar to gravity, this force pulls nodes towards a specific position. +struct ForcePosition ( + "attr.rerun.scope": "blueprint" +) { + /// Whether the force is enabled. + enabled: rerun.blueprint.components.Enabled ("attr.rerun.component_optional", nullable, order: 100); + + /// The strength of the force. + strength: rerun.blueprint.components.ForceStrength ("attr.rerun.component_optional", nullable, order: 200); + + /// The position where the nodes should be pulled towards. + position: rerun.components.Position2D ("attr.rerun.component_optional", nullable, order: 300); +} diff --git a/crates/store/re_types/definitions/rerun/blueprint/components.fbs b/crates/store/re_types/definitions/rerun/blueprint/components.fbs index 4f216593296d..55db3d7a4e50 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/components.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/components.fbs @@ -9,8 +9,12 @@ include "./components/column_share.fbs"; include "./components/component_column_selector.fbs"; include "./components/container_kind.fbs"; include "./components/corner_2d.fbs"; +include "./components/enabled.fbs"; include "./components/filter_by_range.fbs"; include "./components/filter_is_not_null.fbs"; +include "./components/force_distance.fbs"; +include "./components/force_iterations.fbs"; +include "./components/force_strength.fbs"; include "./components/grid_columns.fbs"; include "./components/grid_spacing.fbs"; include "./components/included_content.fbs"; diff --git a/crates/store/re_types/definitions/rerun/blueprint/components/enabled.fbs b/crates/store/re_types/definitions/rerun/blueprint/components/enabled.fbs new file mode 100644 index 000000000000..d4b9219adb9f --- /dev/null +++ b/crates/store/re_types/definitions/rerun/blueprint/components/enabled.fbs @@ -0,0 +1,15 @@ +namespace rerun.blueprint.components; + +// --- + +/// Whether a procedure is enabled. +struct Enabled ( + "attr.arrow.transparent", + "attr.rerun.scope": "blueprint", + "attr.python.aliases": "bool", + "attr.rust.derive": "Copy, Default, PartialEq, Eq, PartialOrd, Ord", + "attr.rust.repr": "transparent", + "attr.rust.tuple_struct" +) { + visible: rerun.datatypes.Bool (order: 100); +} diff --git a/crates/store/re_types/definitions/rerun/blueprint/components/force_distance.fbs b/crates/store/re_types/definitions/rerun/blueprint/components/force_distance.fbs new file mode 100644 index 000000000000..49d728662e03 --- /dev/null +++ b/crates/store/re_types/definitions/rerun/blueprint/components/force_distance.fbs @@ -0,0 +1,14 @@ + +namespace rerun.blueprint.components; + +/// The target distance between two nodes. +/// +/// This is helpful to scale the layout, for example if long labels are involved. +struct ForceDistance ( + "attr.arrow.transparent", + "attr.rust.derive": "Default, Copy, PartialEq", + "attr.rust.repr": "transparent", + "attr.rerun.scope": "blueprint" +) { + distance: rerun.datatypes.Float64 (order: 100); +} diff --git a/crates/store/re_types/definitions/rerun/blueprint/components/force_iterations.fbs b/crates/store/re_types/definitions/rerun/blueprint/components/force_iterations.fbs new file mode 100644 index 000000000000..6cdcca9af94c --- /dev/null +++ b/crates/store/re_types/definitions/rerun/blueprint/components/force_iterations.fbs @@ -0,0 +1,14 @@ + +namespace rerun.blueprint.components; + +/// Specifies how often this force should be applied per iteration. +/// +/// Increasing this parameter can lead to better results at the cost of longer computation time. +struct ForceIterations ( + "attr.arrow.transparent", + "attr.rust.derive": "Default, Copy, PartialEq, Eq", + "attr.rust.repr": "transparent", + "attr.rerun.scope": "blueprint" +) { + distance: rerun.datatypes.UInt64 (order: 100); +} diff --git a/crates/store/re_types/definitions/rerun/blueprint/components/force_strength.fbs b/crates/store/re_types/definitions/rerun/blueprint/components/force_strength.fbs new file mode 100644 index 000000000000..505deda12ac7 --- /dev/null +++ b/crates/store/re_types/definitions/rerun/blueprint/components/force_strength.fbs @@ -0,0 +1,14 @@ + +namespace rerun.blueprint.components; + +/// The strength of a given force. +/// +/// Allows to assign different weights to the individual forces, prioritizing one over the other. +struct ForceStrength ( + "attr.arrow.transparent", + "attr.rust.derive": "Default, Copy, PartialEq", + "attr.rust.repr": "transparent", + "attr.rerun.scope": "blueprint" +) { + distance: rerun.datatypes.Float64 (order: 100); +} diff --git a/crates/store/re_types/definitions/rerun/blueprint/views/graph.fbs b/crates/store/re_types/definitions/rerun/blueprint/views/graph.fbs index 2f808bb8df2a..848ad4f3255a 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/views/graph.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/views/graph.fbs @@ -11,4 +11,19 @@ table GraphView ( /// /// Somethings outside of these bounds may also be visible due to letterboxing. visual_bounds: rerun.blueprint.archetypes.VisualBounds2D (order: 1000); + + /// Allows to control the interaction between two nodes connected by an edge. + force_link: rerun.blueprint.archetypes.ForceLink (order: 2000); + + /// A force between each pair of nodes that ressembles an electrical charge. + force_many_body: rerun.blueprint.archetypes.ForceManyBody (order: 3000); + + /// Similar to gravity, this force pulls nodes towards a specific position. + force_position: rerun.blueprint.archetypes.ForcePosition (order: 4000); + + /// Resolves collisions between the bounding spheres, according to the radius of the nodes. + force_collision_radius: rerun.blueprint.archetypes.ForceCollisionRadius (order: 5000); + + /// Tries to move the center of mass of the graph to the origin. + force_center: rerun.blueprint.archetypes.ForceCenter (order: 6000); } diff --git a/crates/store/re_types/src/blueprint/archetypes/.gitattributes b/crates/store/re_types/src/blueprint/archetypes/.gitattributes index 0053d35aa081..4ef9cf481468 100644 --- a/crates/store/re_types/src/blueprint/archetypes/.gitattributes +++ b/crates/store/re_types/src/blueprint/archetypes/.gitattributes @@ -3,6 +3,11 @@ .gitattributes linguist-generated=true background.rs linguist-generated=true dataframe_query.rs linguist-generated=true +force_center.rs linguist-generated=true +force_collision_radius.rs linguist-generated=true +force_link.rs linguist-generated=true +force_many_body.rs linguist-generated=true +force_position.rs linguist-generated=true line_grid3d.rs linguist-generated=true map_background.rs linguist-generated=true map_zoom.rs linguist-generated=true diff --git a/crates/store/re_types/src/blueprint/archetypes/force_center.rs b/crates/store/re_types/src/blueprint/archetypes/force_center.rs new file mode 100644 index 000000000000..9cb1870a5af5 --- /dev/null +++ b/crates/store/re_types/src/blueprint/archetypes/force_center.rs @@ -0,0 +1,242 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/force_center.fbs". + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::map_flatten)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor}; +use ::re_types_core::{ComponentDescriptor, ComponentName}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Archetype**: Tries to move the center of mass of the graph to the origin. +#[derive(Clone, Debug)] +pub struct ForceCenter { + /// Whether the force is enabled. + pub enabled: Option, + + /// The strength of the force. + pub strength: Option, +} + +static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 0usize]> = + once_cell::sync::Lazy::new(|| []); + +static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 1usize]> = + once_cell::sync::Lazy::new(|| { + [ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceCenter".into()), + component_name: "rerun.blueprint.components.ForceCenterIndicator".into(), + archetype_field_name: None, + }] + }); + +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 2usize]> = + once_cell::sync::Lazy::new(|| { + [ + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceCenter".into()), + component_name: "rerun.blueprint.components.Enabled".into(), + archetype_field_name: Some("enabled".into()), + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceCenter".into()), + component_name: "rerun.blueprint.components.ForceStrength".into(), + archetype_field_name: Some("strength".into()), + }, + ] + }); + +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 3usize]> = + once_cell::sync::Lazy::new(|| { + [ + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceCenter".into()), + component_name: "rerun.blueprint.components.ForceCenterIndicator".into(), + archetype_field_name: None, + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceCenter".into()), + component_name: "rerun.blueprint.components.Enabled".into(), + archetype_field_name: Some("enabled".into()), + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceCenter".into()), + component_name: "rerun.blueprint.components.ForceStrength".into(), + archetype_field_name: Some("strength".into()), + }, + ] + }); + +impl ForceCenter { + /// The total number of components in the archetype: 0 required, 1 recommended, 2 optional + pub const NUM_COMPONENTS: usize = 3usize; +} + +/// Indicator component for the [`ForceCenter`] [`::re_types_core::Archetype`] +pub type ForceCenterIndicator = ::re_types_core::GenericIndicatorComponent; + +impl ::re_types_core::Archetype for ForceCenter { + type Indicator = ForceCenterIndicator; + + #[inline] + fn name() -> ::re_types_core::ArchetypeName { + "rerun.blueprint.archetypes.ForceCenter".into() + } + + #[inline] + fn display_name() -> &'static str { + "Force center" + } + + #[inline] + fn indicator() -> ComponentBatchCowWithDescriptor<'static> { + static INDICATOR: ForceCenterIndicator = ForceCenterIndicator::DEFAULT; + ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + } + + #[inline] + fn required_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + REQUIRED_COMPONENTS.as_slice().into() + } + + #[inline] + fn recommended_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + RECOMMENDED_COMPONENTS.as_slice().into() + } + + #[inline] + fn optional_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + OPTIONAL_COMPONENTS.as_slice().into() + } + + #[inline] + fn all_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + ALL_COMPONENTS.as_slice().into() + } + + #[inline] + fn from_arrow2_components( + arrow_data: impl IntoIterator)>, + ) -> DeserializationResult { + re_tracing::profile_function!(); + use ::re_types_core::{Loggable as _, ResultExt as _}; + let arrays_by_name: ::std::collections::HashMap<_, _> = arrow_data + .into_iter() + .map(|(name, array)| (name.full_name(), array)) + .collect(); + let enabled = if let Some(array) = arrays_by_name.get("rerun.blueprint.components.Enabled") + { + ::from_arrow2_opt(&**array) + .with_context("rerun.blueprint.archetypes.ForceCenter#enabled")? + .into_iter() + .next() + .flatten() + } else { + None + }; + let strength = + if let Some(array) = arrays_by_name.get("rerun.blueprint.components.ForceStrength") { + ::from_arrow2_opt(&**array) + .with_context("rerun.blueprint.archetypes.ForceCenter#strength")? + .into_iter() + .next() + .flatten() + } else { + None + }; + Ok(Self { enabled, strength }) + } +} + +impl ::re_types_core::AsComponents for ForceCenter { + fn as_component_batches(&self) -> Vec> { + re_tracing::profile_function!(); + use ::re_types_core::Archetype as _; + [ + Some(Self::indicator()), + (self + .enabled + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch))) + .map(|batch| ::re_types_core::ComponentBatchCowWithDescriptor { + batch: batch.into(), + descriptor_override: Some(ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceCenter".into()), + archetype_field_name: Some(("enabled").into()), + component_name: ("rerun.blueprint.components.Enabled").into(), + }), + }), + (self + .strength + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch))) + .map(|batch| ::re_types_core::ComponentBatchCowWithDescriptor { + batch: batch.into(), + descriptor_override: Some(ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceCenter".into()), + archetype_field_name: Some(("strength").into()), + component_name: ("rerun.blueprint.components.ForceStrength").into(), + }), + }), + ] + .into_iter() + .flatten() + .collect() + } +} + +impl ::re_types_core::ArchetypeReflectionMarker for ForceCenter {} + +impl ForceCenter { + /// Create a new `ForceCenter`. + #[inline] + pub fn new() -> Self { + Self { + enabled: None, + strength: None, + } + } + + /// Whether the force is enabled. + #[inline] + pub fn with_enabled( + mut self, + enabled: impl Into, + ) -> Self { + self.enabled = Some(enabled.into()); + self + } + + /// The strength of the force. + #[inline] + pub fn with_strength( + mut self, + strength: impl Into, + ) -> Self { + self.strength = Some(strength.into()); + self + } +} + +impl ::re_types_core::SizeBytes for ForceCenter { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.enabled.heap_size_bytes() + self.strength.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + >::is_pod() + && >::is_pod() + } +} diff --git a/crates/store/re_types/src/blueprint/archetypes/force_collision_radius.rs b/crates/store/re_types/src/blueprint/archetypes/force_collision_radius.rs new file mode 100644 index 000000000000..71055ab49f0f --- /dev/null +++ b/crates/store/re_types/src/blueprint/archetypes/force_collision_radius.rs @@ -0,0 +1,300 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/force_collision_radius.fbs". + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::map_flatten)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor}; +use ::re_types_core::{ComponentDescriptor, ComponentName}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Archetype**: Resolves collisions between the bounding spheres, according to the radius of the nodes. +#[derive(Clone, Debug)] +pub struct ForceCollisionRadius { + /// Whether the force is enabled. + pub enabled: Option, + + /// The strength of the force. + pub strength: Option, + + /// Specifies how often this force should be applied per iteration. + /// + /// Increasing this parameter can lead to better results at the cost of longer computation time. + pub iterations: Option, +} + +static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 0usize]> = + once_cell::sync::Lazy::new(|| []); + +static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 1usize]> = + once_cell::sync::Lazy::new(|| { + [ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceCollisionRadius".into()), + component_name: "rerun.blueprint.components.ForceCollisionRadiusIndicator".into(), + archetype_field_name: None, + }] + }); + +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 3usize]> = + once_cell::sync::Lazy::new(|| { + [ + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceCollisionRadius".into()), + component_name: "rerun.blueprint.components.Enabled".into(), + archetype_field_name: Some("enabled".into()), + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceCollisionRadius".into()), + component_name: "rerun.blueprint.components.ForceStrength".into(), + archetype_field_name: Some("strength".into()), + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceCollisionRadius".into()), + component_name: "rerun.blueprint.components.ForceIterations".into(), + archetype_field_name: Some("iterations".into()), + }, + ] + }); + +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 4usize]> = + once_cell::sync::Lazy::new(|| { + [ + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceCollisionRadius".into()), + component_name: "rerun.blueprint.components.ForceCollisionRadiusIndicator".into(), + archetype_field_name: None, + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceCollisionRadius".into()), + component_name: "rerun.blueprint.components.Enabled".into(), + archetype_field_name: Some("enabled".into()), + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceCollisionRadius".into()), + component_name: "rerun.blueprint.components.ForceStrength".into(), + archetype_field_name: Some("strength".into()), + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceCollisionRadius".into()), + component_name: "rerun.blueprint.components.ForceIterations".into(), + archetype_field_name: Some("iterations".into()), + }, + ] + }); + +impl ForceCollisionRadius { + /// The total number of components in the archetype: 0 required, 1 recommended, 3 optional + pub const NUM_COMPONENTS: usize = 4usize; +} + +/// Indicator component for the [`ForceCollisionRadius`] [`::re_types_core::Archetype`] +pub type ForceCollisionRadiusIndicator = + ::re_types_core::GenericIndicatorComponent; + +impl ::re_types_core::Archetype for ForceCollisionRadius { + type Indicator = ForceCollisionRadiusIndicator; + + #[inline] + fn name() -> ::re_types_core::ArchetypeName { + "rerun.blueprint.archetypes.ForceCollisionRadius".into() + } + + #[inline] + fn display_name() -> &'static str { + "Force collision radius" + } + + #[inline] + fn indicator() -> ComponentBatchCowWithDescriptor<'static> { + static INDICATOR: ForceCollisionRadiusIndicator = ForceCollisionRadiusIndicator::DEFAULT; + ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + } + + #[inline] + fn required_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + REQUIRED_COMPONENTS.as_slice().into() + } + + #[inline] + fn recommended_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + RECOMMENDED_COMPONENTS.as_slice().into() + } + + #[inline] + fn optional_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + OPTIONAL_COMPONENTS.as_slice().into() + } + + #[inline] + fn all_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + ALL_COMPONENTS.as_slice().into() + } + + #[inline] + fn from_arrow2_components( + arrow_data: impl IntoIterator)>, + ) -> DeserializationResult { + re_tracing::profile_function!(); + use ::re_types_core::{Loggable as _, ResultExt as _}; + let arrays_by_name: ::std::collections::HashMap<_, _> = arrow_data + .into_iter() + .map(|(name, array)| (name.full_name(), array)) + .collect(); + let enabled = if let Some(array) = arrays_by_name.get("rerun.blueprint.components.Enabled") + { + ::from_arrow2_opt(&**array) + .with_context("rerun.blueprint.archetypes.ForceCollisionRadius#enabled")? + .into_iter() + .next() + .flatten() + } else { + None + }; + let strength = + if let Some(array) = arrays_by_name.get("rerun.blueprint.components.ForceStrength") { + ::from_arrow2_opt(&**array) + .with_context("rerun.blueprint.archetypes.ForceCollisionRadius#strength")? + .into_iter() + .next() + .flatten() + } else { + None + }; + let iterations = + if let Some(array) = arrays_by_name.get("rerun.blueprint.components.ForceIterations") { + ::from_arrow2_opt(&**array) + .with_context("rerun.blueprint.archetypes.ForceCollisionRadius#iterations")? + .into_iter() + .next() + .flatten() + } else { + None + }; + Ok(Self { + enabled, + strength, + iterations, + }) + } +} + +impl ::re_types_core::AsComponents for ForceCollisionRadius { + fn as_component_batches(&self) -> Vec> { + re_tracing::profile_function!(); + use ::re_types_core::Archetype as _; + [ + Some(Self::indicator()), + (self + .enabled + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch))) + .map(|batch| ::re_types_core::ComponentBatchCowWithDescriptor { + batch: batch.into(), + descriptor_override: Some(ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceCollisionRadius".into()), + archetype_field_name: Some(("enabled").into()), + component_name: ("rerun.blueprint.components.Enabled").into(), + }), + }), + (self + .strength + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch))) + .map(|batch| ::re_types_core::ComponentBatchCowWithDescriptor { + batch: batch.into(), + descriptor_override: Some(ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceCollisionRadius".into()), + archetype_field_name: Some(("strength").into()), + component_name: ("rerun.blueprint.components.ForceStrength").into(), + }), + }), + (self + .iterations + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch))) + .map(|batch| ::re_types_core::ComponentBatchCowWithDescriptor { + batch: batch.into(), + descriptor_override: Some(ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceCollisionRadius".into()), + archetype_field_name: Some(("iterations").into()), + component_name: ("rerun.blueprint.components.ForceIterations").into(), + }), + }), + ] + .into_iter() + .flatten() + .collect() + } +} + +impl ::re_types_core::ArchetypeReflectionMarker for ForceCollisionRadius {} + +impl ForceCollisionRadius { + /// Create a new `ForceCollisionRadius`. + #[inline] + pub fn new() -> Self { + Self { + enabled: None, + strength: None, + iterations: None, + } + } + + /// Whether the force is enabled. + #[inline] + pub fn with_enabled( + mut self, + enabled: impl Into, + ) -> Self { + self.enabled = Some(enabled.into()); + self + } + + /// The strength of the force. + #[inline] + pub fn with_strength( + mut self, + strength: impl Into, + ) -> Self { + self.strength = Some(strength.into()); + self + } + + /// Specifies how often this force should be applied per iteration. + /// + /// Increasing this parameter can lead to better results at the cost of longer computation time. + #[inline] + pub fn with_iterations( + mut self, + iterations: impl Into, + ) -> Self { + self.iterations = Some(iterations.into()); + self + } +} + +impl ::re_types_core::SizeBytes for ForceCollisionRadius { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.enabled.heap_size_bytes() + + self.strength.heap_size_bytes() + + self.iterations.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + >::is_pod() + && >::is_pod() + && >::is_pod() + } +} diff --git a/crates/store/re_types/src/blueprint/archetypes/force_link.rs b/crates/store/re_types/src/blueprint/archetypes/force_link.rs new file mode 100644 index 000000000000..9c6fe8aa11d2 --- /dev/null +++ b/crates/store/re_types/src/blueprint/archetypes/force_link.rs @@ -0,0 +1,299 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/force_link.fbs". + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::map_flatten)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor}; +use ::re_types_core::{ComponentDescriptor, ComponentName}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Archetype**: Aims to achieve a target distance between two nodes that are connected by an edge. +#[derive(Clone, Debug)] +pub struct ForceLink { + /// Whether the force is enabled. + pub enabled: Option, + + /// The target distance between two nodes. + pub distance: Option, + + /// Specifies how often this force should be applied per iteration. + /// + /// Increasing this parameter can lead to better results at the cost of longer computation time. + pub iterations: Option, +} + +static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 0usize]> = + once_cell::sync::Lazy::new(|| []); + +static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 1usize]> = + once_cell::sync::Lazy::new(|| { + [ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceLink".into()), + component_name: "rerun.blueprint.components.ForceLinkIndicator".into(), + archetype_field_name: None, + }] + }); + +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 3usize]> = + once_cell::sync::Lazy::new(|| { + [ + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceLink".into()), + component_name: "rerun.blueprint.components.Enabled".into(), + archetype_field_name: Some("enabled".into()), + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceLink".into()), + component_name: "rerun.blueprint.components.ForceDistance".into(), + archetype_field_name: Some("distance".into()), + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceLink".into()), + component_name: "rerun.blueprint.components.ForceIterations".into(), + archetype_field_name: Some("iterations".into()), + }, + ] + }); + +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 4usize]> = + once_cell::sync::Lazy::new(|| { + [ + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceLink".into()), + component_name: "rerun.blueprint.components.ForceLinkIndicator".into(), + archetype_field_name: None, + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceLink".into()), + component_name: "rerun.blueprint.components.Enabled".into(), + archetype_field_name: Some("enabled".into()), + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceLink".into()), + component_name: "rerun.blueprint.components.ForceDistance".into(), + archetype_field_name: Some("distance".into()), + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceLink".into()), + component_name: "rerun.blueprint.components.ForceIterations".into(), + archetype_field_name: Some("iterations".into()), + }, + ] + }); + +impl ForceLink { + /// The total number of components in the archetype: 0 required, 1 recommended, 3 optional + pub const NUM_COMPONENTS: usize = 4usize; +} + +/// Indicator component for the [`ForceLink`] [`::re_types_core::Archetype`] +pub type ForceLinkIndicator = ::re_types_core::GenericIndicatorComponent; + +impl ::re_types_core::Archetype for ForceLink { + type Indicator = ForceLinkIndicator; + + #[inline] + fn name() -> ::re_types_core::ArchetypeName { + "rerun.blueprint.archetypes.ForceLink".into() + } + + #[inline] + fn display_name() -> &'static str { + "Force link" + } + + #[inline] + fn indicator() -> ComponentBatchCowWithDescriptor<'static> { + static INDICATOR: ForceLinkIndicator = ForceLinkIndicator::DEFAULT; + ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + } + + #[inline] + fn required_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + REQUIRED_COMPONENTS.as_slice().into() + } + + #[inline] + fn recommended_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + RECOMMENDED_COMPONENTS.as_slice().into() + } + + #[inline] + fn optional_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + OPTIONAL_COMPONENTS.as_slice().into() + } + + #[inline] + fn all_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + ALL_COMPONENTS.as_slice().into() + } + + #[inline] + fn from_arrow2_components( + arrow_data: impl IntoIterator)>, + ) -> DeserializationResult { + re_tracing::profile_function!(); + use ::re_types_core::{Loggable as _, ResultExt as _}; + let arrays_by_name: ::std::collections::HashMap<_, _> = arrow_data + .into_iter() + .map(|(name, array)| (name.full_name(), array)) + .collect(); + let enabled = if let Some(array) = arrays_by_name.get("rerun.blueprint.components.Enabled") + { + ::from_arrow2_opt(&**array) + .with_context("rerun.blueprint.archetypes.ForceLink#enabled")? + .into_iter() + .next() + .flatten() + } else { + None + }; + let distance = + if let Some(array) = arrays_by_name.get("rerun.blueprint.components.ForceDistance") { + ::from_arrow2_opt(&**array) + .with_context("rerun.blueprint.archetypes.ForceLink#distance")? + .into_iter() + .next() + .flatten() + } else { + None + }; + let iterations = + if let Some(array) = arrays_by_name.get("rerun.blueprint.components.ForceIterations") { + ::from_arrow2_opt(&**array) + .with_context("rerun.blueprint.archetypes.ForceLink#iterations")? + .into_iter() + .next() + .flatten() + } else { + None + }; + Ok(Self { + enabled, + distance, + iterations, + }) + } +} + +impl ::re_types_core::AsComponents for ForceLink { + fn as_component_batches(&self) -> Vec> { + re_tracing::profile_function!(); + use ::re_types_core::Archetype as _; + [ + Some(Self::indicator()), + (self + .enabled + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch))) + .map(|batch| ::re_types_core::ComponentBatchCowWithDescriptor { + batch: batch.into(), + descriptor_override: Some(ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceLink".into()), + archetype_field_name: Some(("enabled").into()), + component_name: ("rerun.blueprint.components.Enabled").into(), + }), + }), + (self + .distance + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch))) + .map(|batch| ::re_types_core::ComponentBatchCowWithDescriptor { + batch: batch.into(), + descriptor_override: Some(ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceLink".into()), + archetype_field_name: Some(("distance").into()), + component_name: ("rerun.blueprint.components.ForceDistance").into(), + }), + }), + (self + .iterations + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch))) + .map(|batch| ::re_types_core::ComponentBatchCowWithDescriptor { + batch: batch.into(), + descriptor_override: Some(ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceLink".into()), + archetype_field_name: Some(("iterations").into()), + component_name: ("rerun.blueprint.components.ForceIterations").into(), + }), + }), + ] + .into_iter() + .flatten() + .collect() + } +} + +impl ::re_types_core::ArchetypeReflectionMarker for ForceLink {} + +impl ForceLink { + /// Create a new `ForceLink`. + #[inline] + pub fn new() -> Self { + Self { + enabled: None, + distance: None, + iterations: None, + } + } + + /// Whether the force is enabled. + #[inline] + pub fn with_enabled( + mut self, + enabled: impl Into, + ) -> Self { + self.enabled = Some(enabled.into()); + self + } + + /// The target distance between two nodes. + #[inline] + pub fn with_distance( + mut self, + distance: impl Into, + ) -> Self { + self.distance = Some(distance.into()); + self + } + + /// Specifies how often this force should be applied per iteration. + /// + /// Increasing this parameter can lead to better results at the cost of longer computation time. + #[inline] + pub fn with_iterations( + mut self, + iterations: impl Into, + ) -> Self { + self.iterations = Some(iterations.into()); + self + } +} + +impl ::re_types_core::SizeBytes for ForceLink { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.enabled.heap_size_bytes() + + self.distance.heap_size_bytes() + + self.iterations.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + >::is_pod() + && >::is_pod() + && >::is_pod() + } +} diff --git a/crates/store/re_types/src/blueprint/archetypes/force_many_body.rs b/crates/store/re_types/src/blueprint/archetypes/force_many_body.rs new file mode 100644 index 000000000000..9720ff5a4f17 --- /dev/null +++ b/crates/store/re_types/src/blueprint/archetypes/force_many_body.rs @@ -0,0 +1,248 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/force_many_body.fbs". + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::map_flatten)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor}; +use ::re_types_core::{ComponentDescriptor, ComponentName}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Archetype**: A force between each pair of nodes that ressembles an electrical charge. +/// +/// If `strength` is smaller than 0, it pushes nodes apart, if it is larger than 0 it pulls them together. +#[derive(Clone, Debug)] +pub struct ForceManyBody { + /// Whether the force is enabled. + pub enabled: Option, + + /// The strength of the force. + /// + /// If `strength` is smaller than 0, it pushes nodes apart, if it is larger than 0 it pulls them together. + pub strength: Option, +} + +static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 0usize]> = + once_cell::sync::Lazy::new(|| []); + +static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 1usize]> = + once_cell::sync::Lazy::new(|| { + [ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceManyBody".into()), + component_name: "rerun.blueprint.components.ForceManyBodyIndicator".into(), + archetype_field_name: None, + }] + }); + +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 2usize]> = + once_cell::sync::Lazy::new(|| { + [ + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceManyBody".into()), + component_name: "rerun.blueprint.components.Enabled".into(), + archetype_field_name: Some("enabled".into()), + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceManyBody".into()), + component_name: "rerun.blueprint.components.ForceStrength".into(), + archetype_field_name: Some("strength".into()), + }, + ] + }); + +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 3usize]> = + once_cell::sync::Lazy::new(|| { + [ + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceManyBody".into()), + component_name: "rerun.blueprint.components.ForceManyBodyIndicator".into(), + archetype_field_name: None, + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceManyBody".into()), + component_name: "rerun.blueprint.components.Enabled".into(), + archetype_field_name: Some("enabled".into()), + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceManyBody".into()), + component_name: "rerun.blueprint.components.ForceStrength".into(), + archetype_field_name: Some("strength".into()), + }, + ] + }); + +impl ForceManyBody { + /// The total number of components in the archetype: 0 required, 1 recommended, 2 optional + pub const NUM_COMPONENTS: usize = 3usize; +} + +/// Indicator component for the [`ForceManyBody`] [`::re_types_core::Archetype`] +pub type ForceManyBodyIndicator = ::re_types_core::GenericIndicatorComponent; + +impl ::re_types_core::Archetype for ForceManyBody { + type Indicator = ForceManyBodyIndicator; + + #[inline] + fn name() -> ::re_types_core::ArchetypeName { + "rerun.blueprint.archetypes.ForceManyBody".into() + } + + #[inline] + fn display_name() -> &'static str { + "Force many body" + } + + #[inline] + fn indicator() -> ComponentBatchCowWithDescriptor<'static> { + static INDICATOR: ForceManyBodyIndicator = ForceManyBodyIndicator::DEFAULT; + ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + } + + #[inline] + fn required_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + REQUIRED_COMPONENTS.as_slice().into() + } + + #[inline] + fn recommended_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + RECOMMENDED_COMPONENTS.as_slice().into() + } + + #[inline] + fn optional_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + OPTIONAL_COMPONENTS.as_slice().into() + } + + #[inline] + fn all_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + ALL_COMPONENTS.as_slice().into() + } + + #[inline] + fn from_arrow2_components( + arrow_data: impl IntoIterator)>, + ) -> DeserializationResult { + re_tracing::profile_function!(); + use ::re_types_core::{Loggable as _, ResultExt as _}; + let arrays_by_name: ::std::collections::HashMap<_, _> = arrow_data + .into_iter() + .map(|(name, array)| (name.full_name(), array)) + .collect(); + let enabled = if let Some(array) = arrays_by_name.get("rerun.blueprint.components.Enabled") + { + ::from_arrow2_opt(&**array) + .with_context("rerun.blueprint.archetypes.ForceManyBody#enabled")? + .into_iter() + .next() + .flatten() + } else { + None + }; + let strength = + if let Some(array) = arrays_by_name.get("rerun.blueprint.components.ForceStrength") { + ::from_arrow2_opt(&**array) + .with_context("rerun.blueprint.archetypes.ForceManyBody#strength")? + .into_iter() + .next() + .flatten() + } else { + None + }; + Ok(Self { enabled, strength }) + } +} + +impl ::re_types_core::AsComponents for ForceManyBody { + fn as_component_batches(&self) -> Vec> { + re_tracing::profile_function!(); + use ::re_types_core::Archetype as _; + [ + Some(Self::indicator()), + (self + .enabled + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch))) + .map(|batch| ::re_types_core::ComponentBatchCowWithDescriptor { + batch: batch.into(), + descriptor_override: Some(ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceManyBody".into()), + archetype_field_name: Some(("enabled").into()), + component_name: ("rerun.blueprint.components.Enabled").into(), + }), + }), + (self + .strength + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch))) + .map(|batch| ::re_types_core::ComponentBatchCowWithDescriptor { + batch: batch.into(), + descriptor_override: Some(ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForceManyBody".into()), + archetype_field_name: Some(("strength").into()), + component_name: ("rerun.blueprint.components.ForceStrength").into(), + }), + }), + ] + .into_iter() + .flatten() + .collect() + } +} + +impl ::re_types_core::ArchetypeReflectionMarker for ForceManyBody {} + +impl ForceManyBody { + /// Create a new `ForceManyBody`. + #[inline] + pub fn new() -> Self { + Self { + enabled: None, + strength: None, + } + } + + /// Whether the force is enabled. + #[inline] + pub fn with_enabled( + mut self, + enabled: impl Into, + ) -> Self { + self.enabled = Some(enabled.into()); + self + } + + /// The strength of the force. + /// + /// If `strength` is smaller than 0, it pushes nodes apart, if it is larger than 0 it pulls them together. + #[inline] + pub fn with_strength( + mut self, + strength: impl Into, + ) -> Self { + self.strength = Some(strength.into()); + self + } +} + +impl ::re_types_core::SizeBytes for ForceManyBody { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.enabled.heap_size_bytes() + self.strength.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + >::is_pod() + && >::is_pod() + } +} diff --git a/crates/store/re_types/src/blueprint/archetypes/force_position.rs b/crates/store/re_types/src/blueprint/archetypes/force_position.rs new file mode 100644 index 000000000000..e106a452c2a2 --- /dev/null +++ b/crates/store/re_types/src/blueprint/archetypes/force_position.rs @@ -0,0 +1,291 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/force_position.fbs". + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::map_flatten)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor}; +use ::re_types_core::{ComponentDescriptor, ComponentName}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Archetype**: Similar to gravity, this force pulls nodes towards a specific position. +#[derive(Clone, Debug)] +pub struct ForcePosition { + /// Whether the force is enabled. + pub enabled: Option, + + /// The strength of the force. + pub strength: Option, + + /// The position where the nodes should be pulled towards. + pub position: Option, +} + +static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 0usize]> = + once_cell::sync::Lazy::new(|| []); + +static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 1usize]> = + once_cell::sync::Lazy::new(|| { + [ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForcePosition".into()), + component_name: "rerun.blueprint.components.ForcePositionIndicator".into(), + archetype_field_name: None, + }] + }); + +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 3usize]> = + once_cell::sync::Lazy::new(|| { + [ + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForcePosition".into()), + component_name: "rerun.blueprint.components.Enabled".into(), + archetype_field_name: Some("enabled".into()), + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForcePosition".into()), + component_name: "rerun.blueprint.components.ForceStrength".into(), + archetype_field_name: Some("strength".into()), + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForcePosition".into()), + component_name: "rerun.components.Position2D".into(), + archetype_field_name: Some("position".into()), + }, + ] + }); + +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentDescriptor; 4usize]> = + once_cell::sync::Lazy::new(|| { + [ + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForcePosition".into()), + component_name: "rerun.blueprint.components.ForcePositionIndicator".into(), + archetype_field_name: None, + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForcePosition".into()), + component_name: "rerun.blueprint.components.Enabled".into(), + archetype_field_name: Some("enabled".into()), + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForcePosition".into()), + component_name: "rerun.blueprint.components.ForceStrength".into(), + archetype_field_name: Some("strength".into()), + }, + ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForcePosition".into()), + component_name: "rerun.components.Position2D".into(), + archetype_field_name: Some("position".into()), + }, + ] + }); + +impl ForcePosition { + /// The total number of components in the archetype: 0 required, 1 recommended, 3 optional + pub const NUM_COMPONENTS: usize = 4usize; +} + +/// Indicator component for the [`ForcePosition`] [`::re_types_core::Archetype`] +pub type ForcePositionIndicator = ::re_types_core::GenericIndicatorComponent; + +impl ::re_types_core::Archetype for ForcePosition { + type Indicator = ForcePositionIndicator; + + #[inline] + fn name() -> ::re_types_core::ArchetypeName { + "rerun.blueprint.archetypes.ForcePosition".into() + } + + #[inline] + fn display_name() -> &'static str { + "Force position" + } + + #[inline] + fn indicator() -> ComponentBatchCowWithDescriptor<'static> { + static INDICATOR: ForcePositionIndicator = ForcePositionIndicator::DEFAULT; + ComponentBatchCowWithDescriptor::new(&INDICATOR as &dyn ::re_types_core::ComponentBatch) + } + + #[inline] + fn required_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + REQUIRED_COMPONENTS.as_slice().into() + } + + #[inline] + fn recommended_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + RECOMMENDED_COMPONENTS.as_slice().into() + } + + #[inline] + fn optional_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + OPTIONAL_COMPONENTS.as_slice().into() + } + + #[inline] + fn all_components() -> ::std::borrow::Cow<'static, [ComponentDescriptor]> { + ALL_COMPONENTS.as_slice().into() + } + + #[inline] + fn from_arrow2_components( + arrow_data: impl IntoIterator)>, + ) -> DeserializationResult { + re_tracing::profile_function!(); + use ::re_types_core::{Loggable as _, ResultExt as _}; + let arrays_by_name: ::std::collections::HashMap<_, _> = arrow_data + .into_iter() + .map(|(name, array)| (name.full_name(), array)) + .collect(); + let enabled = if let Some(array) = arrays_by_name.get("rerun.blueprint.components.Enabled") + { + ::from_arrow2_opt(&**array) + .with_context("rerun.blueprint.archetypes.ForcePosition#enabled")? + .into_iter() + .next() + .flatten() + } else { + None + }; + let strength = + if let Some(array) = arrays_by_name.get("rerun.blueprint.components.ForceStrength") { + ::from_arrow2_opt(&**array) + .with_context("rerun.blueprint.archetypes.ForcePosition#strength")? + .into_iter() + .next() + .flatten() + } else { + None + }; + let position = if let Some(array) = arrays_by_name.get("rerun.components.Position2D") { + ::from_arrow2_opt(&**array) + .with_context("rerun.blueprint.archetypes.ForcePosition#position")? + .into_iter() + .next() + .flatten() + } else { + None + }; + Ok(Self { + enabled, + strength, + position, + }) + } +} + +impl ::re_types_core::AsComponents for ForcePosition { + fn as_component_batches(&self) -> Vec> { + re_tracing::profile_function!(); + use ::re_types_core::Archetype as _; + [ + Some(Self::indicator()), + (self + .enabled + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch))) + .map(|batch| ::re_types_core::ComponentBatchCowWithDescriptor { + batch: batch.into(), + descriptor_override: Some(ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForcePosition".into()), + archetype_field_name: Some(("enabled").into()), + component_name: ("rerun.blueprint.components.Enabled").into(), + }), + }), + (self + .strength + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch))) + .map(|batch| ::re_types_core::ComponentBatchCowWithDescriptor { + batch: batch.into(), + descriptor_override: Some(ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForcePosition".into()), + archetype_field_name: Some(("strength").into()), + component_name: ("rerun.blueprint.components.ForceStrength").into(), + }), + }), + (self + .position + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch))) + .map(|batch| ::re_types_core::ComponentBatchCowWithDescriptor { + batch: batch.into(), + descriptor_override: Some(ComponentDescriptor { + archetype_name: Some("rerun.blueprint.archetypes.ForcePosition".into()), + archetype_field_name: Some(("position").into()), + component_name: ("rerun.components.Position2D").into(), + }), + }), + ] + .into_iter() + .flatten() + .collect() + } +} + +impl ::re_types_core::ArchetypeReflectionMarker for ForcePosition {} + +impl ForcePosition { + /// Create a new `ForcePosition`. + #[inline] + pub fn new() -> Self { + Self { + enabled: None, + strength: None, + position: None, + } + } + + /// Whether the force is enabled. + #[inline] + pub fn with_enabled( + mut self, + enabled: impl Into, + ) -> Self { + self.enabled = Some(enabled.into()); + self + } + + /// The strength of the force. + #[inline] + pub fn with_strength( + mut self, + strength: impl Into, + ) -> Self { + self.strength = Some(strength.into()); + self + } + + /// The position where the nodes should be pulled towards. + #[inline] + pub fn with_position(mut self, position: impl Into) -> Self { + self.position = Some(position.into()); + self + } +} + +impl ::re_types_core::SizeBytes for ForcePosition { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.enabled.heap_size_bytes() + + self.strength.heap_size_bytes() + + self.position.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + >::is_pod() + && >::is_pod() + && >::is_pod() + } +} diff --git a/crates/store/re_types/src/blueprint/archetypes/mod.rs b/crates/store/re_types/src/blueprint/archetypes/mod.rs index 4b5aa896e251..24cd2e1518c5 100644 --- a/crates/store/re_types/src/blueprint/archetypes/mod.rs +++ b/crates/store/re_types/src/blueprint/archetypes/mod.rs @@ -2,6 +2,11 @@ mod background; mod dataframe_query; +mod force_center; +mod force_collision_radius; +mod force_link; +mod force_many_body; +mod force_position; mod line_grid3d; mod map_background; mod map_zoom; @@ -18,6 +23,11 @@ mod visual_bounds2d; pub use self::background::Background; pub use self::dataframe_query::DataframeQuery; +pub use self::force_center::ForceCenter; +pub use self::force_collision_radius::ForceCollisionRadius; +pub use self::force_link::ForceLink; +pub use self::force_many_body::ForceManyBody; +pub use self::force_position::ForcePosition; pub use self::line_grid3d::LineGrid3D; pub use self::map_background::MapBackground; pub use self::map_zoom::MapZoom; diff --git a/crates/store/re_types/src/blueprint/components/.gitattributes b/crates/store/re_types/src/blueprint/components/.gitattributes index 65eeb1377804..38cab9cb557b 100644 --- a/crates/store/re_types/src/blueprint/components/.gitattributes +++ b/crates/store/re_types/src/blueprint/components/.gitattributes @@ -7,8 +7,12 @@ background_kind.rs linguist-generated=true column_share.rs linguist-generated=true component_column_selector.rs linguist-generated=true corner2d.rs linguist-generated=true +enabled.rs linguist-generated=true filter_by_range.rs linguist-generated=true filter_is_not_null.rs linguist-generated=true +force_distance.rs linguist-generated=true +force_iterations.rs linguist-generated=true +force_strength.rs linguist-generated=true grid_spacing.rs linguist-generated=true included_content.rs linguist-generated=true interactive.rs linguist-generated=true diff --git a/crates/store/re_types/src/blueprint/components/enabled.rs b/crates/store/re_types/src/blueprint/components/enabled.rs new file mode 100644 index 000000000000..dc258abb03d2 --- /dev/null +++ b/crates/store/re_types/src/blueprint/components/enabled.rs @@ -0,0 +1,105 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/components/enabled.fbs". + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::map_flatten)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor}; +use ::re_types_core::{ComponentDescriptor, ComponentName}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Component**: Whether a procedure is enabled. +#[derive(Clone, Debug, Copy, Default, PartialEq, Eq, PartialOrd, Ord)] +#[repr(transparent)] +pub struct Enabled(pub crate::datatypes::Bool); + +impl ::re_types_core::Component for Enabled { + #[inline] + fn descriptor() -> ComponentDescriptor { + ComponentDescriptor::new("rerun.blueprint.components.Enabled") + } +} + +::re_types_core::macros::impl_into_cow!(Enabled); + +impl ::re_types_core::Loggable for Enabled { + #[inline] + fn arrow_datatype() -> arrow::datatypes::DataType { + crate::datatypes::Bool::arrow_datatype() + } + + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult + where + Self: Clone + 'a, + { + crate::datatypes::Bool::to_arrow_opt(data.into_iter().map(|datum| { + datum.map(|datum| match datum.into() { + ::std::borrow::Cow::Borrowed(datum) => ::std::borrow::Cow::Borrowed(&datum.0), + ::std::borrow::Cow::Owned(datum) => ::std::borrow::Cow::Owned(datum.0), + }) + })) + } + + fn from_arrow2_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + crate::datatypes::Bool::from_arrow2_opt(arrow_data) + .map(|v| v.into_iter().map(|v| v.map(Self)).collect()) + } +} + +impl> From for Enabled { + fn from(v: T) -> Self { + Self(v.into()) + } +} + +impl std::borrow::Borrow for Enabled { + #[inline] + fn borrow(&self) -> &crate::datatypes::Bool { + &self.0 + } +} + +impl std::ops::Deref for Enabled { + type Target = crate::datatypes::Bool; + + #[inline] + fn deref(&self) -> &crate::datatypes::Bool { + &self.0 + } +} + +impl std::ops::DerefMut for Enabled { + #[inline] + fn deref_mut(&mut self) -> &mut crate::datatypes::Bool { + &mut self.0 + } +} + +impl ::re_types_core::SizeBytes for Enabled { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.0.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + } +} diff --git a/crates/store/re_types/src/blueprint/components/enabled_ext.rs b/crates/store/re_types/src/blueprint/components/enabled_ext.rs new file mode 100644 index 000000000000..2865f1ca4b5b --- /dev/null +++ b/crates/store/re_types/src/blueprint/components/enabled_ext.rs @@ -0,0 +1,8 @@ +use super::Enabled; + +impl From for bool { + #[inline] + fn from(v: Enabled) -> Self { + v.0.into() + } +} diff --git a/crates/store/re_types/src/blueprint/components/force_distance.rs b/crates/store/re_types/src/blueprint/components/force_distance.rs new file mode 100644 index 000000000000..8a70ffc068f7 --- /dev/null +++ b/crates/store/re_types/src/blueprint/components/force_distance.rs @@ -0,0 +1,116 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/components/force_distance.fbs". + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::map_flatten)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor}; +use ::re_types_core::{ComponentDescriptor, ComponentName}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Component**: The target distance between two nodes. +/// +/// This is helpful to scale the layout, for example if long labels are involved. +#[derive(Clone, Debug, Default, Copy, PartialEq)] +#[repr(transparent)] +pub struct ForceDistance(pub crate::datatypes::Float64); + +impl ::re_types_core::Component for ForceDistance { + #[inline] + fn descriptor() -> ComponentDescriptor { + ComponentDescriptor::new("rerun.blueprint.components.ForceDistance") + } +} + +::re_types_core::macros::impl_into_cow!(ForceDistance); + +impl ::re_types_core::Loggable for ForceDistance { + #[inline] + fn arrow_datatype() -> arrow::datatypes::DataType { + crate::datatypes::Float64::arrow_datatype() + } + + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult + where + Self: Clone + 'a, + { + crate::datatypes::Float64::to_arrow_opt(data.into_iter().map(|datum| { + datum.map(|datum| match datum.into() { + ::std::borrow::Cow::Borrowed(datum) => ::std::borrow::Cow::Borrowed(&datum.0), + ::std::borrow::Cow::Owned(datum) => ::std::borrow::Cow::Owned(datum.0), + }) + })) + } + + fn from_arrow2_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + crate::datatypes::Float64::from_arrow2_opt(arrow_data) + .map(|v| v.into_iter().map(|v| v.map(Self)).collect()) + } + + #[inline] + fn from_arrow2(arrow_data: &dyn arrow2::array::Array) -> DeserializationResult> + where + Self: Sized, + { + crate::datatypes::Float64::from_arrow2(arrow_data) + .map(|v| v.into_iter().map(Self).collect()) + } +} + +impl> From for ForceDistance { + fn from(v: T) -> Self { + Self(v.into()) + } +} + +impl std::borrow::Borrow for ForceDistance { + #[inline] + fn borrow(&self) -> &crate::datatypes::Float64 { + &self.0 + } +} + +impl std::ops::Deref for ForceDistance { + type Target = crate::datatypes::Float64; + + #[inline] + fn deref(&self) -> &crate::datatypes::Float64 { + &self.0 + } +} + +impl std::ops::DerefMut for ForceDistance { + #[inline] + fn deref_mut(&mut self) -> &mut crate::datatypes::Float64 { + &mut self.0 + } +} + +impl ::re_types_core::SizeBytes for ForceDistance { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.0.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + } +} diff --git a/crates/store/re_types/src/blueprint/components/force_iterations.rs b/crates/store/re_types/src/blueprint/components/force_iterations.rs new file mode 100644 index 000000000000..d91a043a615f --- /dev/null +++ b/crates/store/re_types/src/blueprint/components/force_iterations.rs @@ -0,0 +1,115 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/components/force_iterations.fbs". + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::map_flatten)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor}; +use ::re_types_core::{ComponentDescriptor, ComponentName}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Component**: Specifies how often this force should be applied per iteration. +/// +/// Increasing this parameter can lead to better results at the cost of longer computation time. +#[derive(Clone, Debug, Default, Copy, PartialEq, Eq)] +#[repr(transparent)] +pub struct ForceIterations(pub crate::datatypes::UInt64); + +impl ::re_types_core::Component for ForceIterations { + #[inline] + fn descriptor() -> ComponentDescriptor { + ComponentDescriptor::new("rerun.blueprint.components.ForceIterations") + } +} + +::re_types_core::macros::impl_into_cow!(ForceIterations); + +impl ::re_types_core::Loggable for ForceIterations { + #[inline] + fn arrow_datatype() -> arrow::datatypes::DataType { + crate::datatypes::UInt64::arrow_datatype() + } + + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult + where + Self: Clone + 'a, + { + crate::datatypes::UInt64::to_arrow_opt(data.into_iter().map(|datum| { + datum.map(|datum| match datum.into() { + ::std::borrow::Cow::Borrowed(datum) => ::std::borrow::Cow::Borrowed(&datum.0), + ::std::borrow::Cow::Owned(datum) => ::std::borrow::Cow::Owned(datum.0), + }) + })) + } + + fn from_arrow2_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + crate::datatypes::UInt64::from_arrow2_opt(arrow_data) + .map(|v| v.into_iter().map(|v| v.map(Self)).collect()) + } + + #[inline] + fn from_arrow2(arrow_data: &dyn arrow2::array::Array) -> DeserializationResult> + where + Self: Sized, + { + crate::datatypes::UInt64::from_arrow2(arrow_data).map(|v| v.into_iter().map(Self).collect()) + } +} + +impl> From for ForceIterations { + fn from(v: T) -> Self { + Self(v.into()) + } +} + +impl std::borrow::Borrow for ForceIterations { + #[inline] + fn borrow(&self) -> &crate::datatypes::UInt64 { + &self.0 + } +} + +impl std::ops::Deref for ForceIterations { + type Target = crate::datatypes::UInt64; + + #[inline] + fn deref(&self) -> &crate::datatypes::UInt64 { + &self.0 + } +} + +impl std::ops::DerefMut for ForceIterations { + #[inline] + fn deref_mut(&mut self) -> &mut crate::datatypes::UInt64 { + &mut self.0 + } +} + +impl ::re_types_core::SizeBytes for ForceIterations { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.0.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + } +} diff --git a/crates/store/re_types/src/blueprint/components/force_strength.rs b/crates/store/re_types/src/blueprint/components/force_strength.rs new file mode 100644 index 000000000000..d1efe60bbb4f --- /dev/null +++ b/crates/store/re_types/src/blueprint/components/force_strength.rs @@ -0,0 +1,116 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/components/force_strength.fbs". + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::map_flatten)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor}; +use ::re_types_core::{ComponentDescriptor, ComponentName}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Component**: The strength of a given force. +/// +/// Allows to assign different weights to the individual forces, prioritizing one over the other. +#[derive(Clone, Debug, Default, Copy, PartialEq)] +#[repr(transparent)] +pub struct ForceStrength(pub crate::datatypes::Float64); + +impl ::re_types_core::Component for ForceStrength { + #[inline] + fn descriptor() -> ComponentDescriptor { + ComponentDescriptor::new("rerun.blueprint.components.ForceStrength") + } +} + +::re_types_core::macros::impl_into_cow!(ForceStrength); + +impl ::re_types_core::Loggable for ForceStrength { + #[inline] + fn arrow_datatype() -> arrow::datatypes::DataType { + crate::datatypes::Float64::arrow_datatype() + } + + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult + where + Self: Clone + 'a, + { + crate::datatypes::Float64::to_arrow_opt(data.into_iter().map(|datum| { + datum.map(|datum| match datum.into() { + ::std::borrow::Cow::Borrowed(datum) => ::std::borrow::Cow::Borrowed(&datum.0), + ::std::borrow::Cow::Owned(datum) => ::std::borrow::Cow::Owned(datum.0), + }) + })) + } + + fn from_arrow2_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + crate::datatypes::Float64::from_arrow2_opt(arrow_data) + .map(|v| v.into_iter().map(|v| v.map(Self)).collect()) + } + + #[inline] + fn from_arrow2(arrow_data: &dyn arrow2::array::Array) -> DeserializationResult> + where + Self: Sized, + { + crate::datatypes::Float64::from_arrow2(arrow_data) + .map(|v| v.into_iter().map(Self).collect()) + } +} + +impl> From for ForceStrength { + fn from(v: T) -> Self { + Self(v.into()) + } +} + +impl std::borrow::Borrow for ForceStrength { + #[inline] + fn borrow(&self) -> &crate::datatypes::Float64 { + &self.0 + } +} + +impl std::ops::Deref for ForceStrength { + type Target = crate::datatypes::Float64; + + #[inline] + fn deref(&self) -> &crate::datatypes::Float64 { + &self.0 + } +} + +impl std::ops::DerefMut for ForceStrength { + #[inline] + fn deref_mut(&mut self) -> &mut crate::datatypes::Float64 { + &mut self.0 + } +} + +impl ::re_types_core::SizeBytes for ForceStrength { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.0.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + } +} diff --git a/crates/store/re_types/src/blueprint/components/mod.rs b/crates/store/re_types/src/blueprint/components/mod.rs index 15647fbf1138..0fb6d14946dc 100644 --- a/crates/store/re_types/src/blueprint/components/mod.rs +++ b/crates/store/re_types/src/blueprint/components/mod.rs @@ -8,10 +8,15 @@ mod component_column_selector; mod component_column_selector_ext; mod corner2d; mod corner2d_ext; +mod enabled; +mod enabled_ext; mod filter_by_range; mod filter_by_range_ext; mod filter_is_not_null; mod filter_is_not_null_ext; +mod force_distance; +mod force_iterations; +mod force_strength; mod grid_spacing; mod grid_spacing_ext; mod included_content; @@ -50,8 +55,12 @@ pub use self::background_kind::BackgroundKind; pub use self::column_share::ColumnShare; pub use self::component_column_selector::ComponentColumnSelector; pub use self::corner2d::Corner2D; +pub use self::enabled::Enabled; pub use self::filter_by_range::FilterByRange; pub use self::filter_is_not_null::FilterIsNotNull; +pub use self::force_distance::ForceDistance; +pub use self::force_iterations::ForceIterations; +pub use self::force_strength::ForceStrength; pub use self::grid_spacing::GridSpacing; pub use self::included_content::IncludedContent; pub use self::interactive::Interactive; diff --git a/crates/store/re_types/src/blueprint/views/graph_view.rs b/crates/store/re_types/src/blueprint/views/graph_view.rs index 7eff672bef81..74e6771dc9b2 100644 --- a/crates/store/re_types/src/blueprint/views/graph_view.rs +++ b/crates/store/re_types/src/blueprint/views/graph_view.rs @@ -25,43 +25,27 @@ pub struct GraphView { /// /// Somethings outside of these bounds may also be visible due to letterboxing. pub visual_bounds: crate::blueprint::archetypes::VisualBounds2D, -} -impl ::re_types_core::View for GraphView { - #[inline] - fn identifier() -> ::re_types_core::SpaceViewClassIdentifier { - "Graph".into() - } -} + /// Allows to control the interaction between two nodes connected by an edge. + pub force_link: crate::blueprint::archetypes::ForceLink, -impl> From for GraphView { - fn from(v: T) -> Self { - Self { - visual_bounds: v.into(), - } - } -} + /// A force between each pair of nodes that ressembles an electrical charge. + pub force_many_body: crate::blueprint::archetypes::ForceManyBody, -impl std::borrow::Borrow for GraphView { - #[inline] - fn borrow(&self) -> &crate::blueprint::archetypes::VisualBounds2D { - &self.visual_bounds - } -} + /// Similar to gravity, this force pulls nodes towards a specific position. + pub force_position: crate::blueprint::archetypes::ForcePosition, -impl std::ops::Deref for GraphView { - type Target = crate::blueprint::archetypes::VisualBounds2D; + /// Resolves collisions between the bounding spheres, according to the radius of the nodes. + pub force_collision_radius: crate::blueprint::archetypes::ForceCollisionRadius, - #[inline] - fn deref(&self) -> &crate::blueprint::archetypes::VisualBounds2D { - &self.visual_bounds - } + /// Tries to move the center of mass of the graph to the origin. + pub force_center: crate::blueprint::archetypes::ForceCenter, } -impl std::ops::DerefMut for GraphView { +impl ::re_types_core::View for GraphView { #[inline] - fn deref_mut(&mut self) -> &mut crate::blueprint::archetypes::VisualBounds2D { - &mut self.visual_bounds + fn identifier() -> ::re_types_core::SpaceViewClassIdentifier { + "Graph".into() } } @@ -69,10 +53,20 @@ impl ::re_types_core::SizeBytes for GraphView { #[inline] fn heap_size_bytes(&self) -> u64 { self.visual_bounds.heap_size_bytes() + + self.force_link.heap_size_bytes() + + self.force_many_body.heap_size_bytes() + + self.force_position.heap_size_bytes() + + self.force_collision_radius.heap_size_bytes() + + self.force_center.heap_size_bytes() } #[inline] fn is_pod() -> bool { ::is_pod() + && ::is_pod() + && ::is_pod() + && ::is_pod() + && ::is_pod() + && ::is_pod() } } diff --git a/crates/viewer/re_component_ui/src/datatype_uis/float_drag.rs b/crates/viewer/re_component_ui/src/datatype_uis/float_drag.rs index b9aa5fa87b9b..8964dd6cce4c 100644 --- a/crates/viewer/re_component_ui/src/datatype_uis/float_drag.rs +++ b/crates/viewer/re_component_ui/src/datatype_uis/float_drag.rs @@ -111,6 +111,42 @@ fn edit_f32_zero_to_one_raw(ui: &mut egui::Ui, value: &mut MaybeMutRef<'_, f32>) // --- +/// Generic editor for a [`re_types::datatypes::Float64`] value from zero to max float. +pub fn edit_f64_zero_to_max( + _ctx: &re_viewer_context::ViewerContext<'_>, + ui: &mut egui::Ui, + value: &mut MaybeMutRef<'_, impl std::ops::DerefMut>, +) -> egui::Response { + let mut value: MaybeMutRef<'_, f64> = match value { + MaybeMutRef::Ref(value) => MaybeMutRef::Ref(value), + MaybeMutRef::MutRef(value) => MaybeMutRef::MutRef(&mut value.deref_mut().0), + }; + edit_f64_float_raw_impl(ui, &mut value, 0.0..=f64::MAX) +} + +/// Generic editor for a [`re_types::datatypes::Float64`] value from min to max float. +pub fn edit_f64_min_to_max_float( + _ctx: &re_viewer_context::ViewerContext<'_>, + ui: &mut egui::Ui, + value: &mut MaybeMutRef<'_, impl std::ops::DerefMut>, +) -> egui::Response { + let mut value: MaybeMutRef<'_, f64> = match value { + MaybeMutRef::Ref(value) => MaybeMutRef::Ref(value), + MaybeMutRef::MutRef(value) => MaybeMutRef::MutRef(&mut value.deref_mut().0), + }; + edit_f64_float_raw_impl(ui, &mut value, f64::MIN..=f64::MAX) +} + +/// Non monomorphized implementation for f64 float editing. +pub fn edit_f64_float_raw_impl( + ui: &mut egui::Ui, + value: &mut MaybeMutRef<'_, f64>, + range: RangeInclusive, +) -> egui::Response { + let speed = (value.abs() * 0.01).at_least(0.001); + edit_f64_float_raw_with_speed_impl(ui, value, range, speed) +} + /// Non monomorphized implementation for f64 float editing with a given speed. pub fn edit_f64_float_raw_with_speed_impl( ui: &mut egui::Ui, diff --git a/crates/viewer/re_component_ui/src/datatype_uis/int_drag.rs b/crates/viewer/re_component_ui/src/datatype_uis/int_drag.rs new file mode 100644 index 000000000000..e92b3c91a39b --- /dev/null +++ b/crates/viewer/re_component_ui/src/datatype_uis/int_drag.rs @@ -0,0 +1,51 @@ +use std::ops::RangeInclusive; + +use egui::NumExt as _; +use re_types_core::datatypes; +use re_viewer_context::MaybeMutRef; + +/// Generic editor for a [`re_types::datatypes::UInt64`] values within a given range. +pub fn edit_u64_range( + _ctx: &re_viewer_context::ViewerContext<'_>, + ui: &mut egui::Ui, + value: &mut MaybeMutRef<'_, impl std::ops::DerefMut>, + range: RangeInclusive, +) -> egui::Response { + let mut value: MaybeMutRef<'_, u64> = match value { + MaybeMutRef::Ref(value) => MaybeMutRef::Ref(value), + MaybeMutRef::MutRef(value) => MaybeMutRef::MutRef(&mut value.deref_mut().0), + }; + edit_u64_raw(ui, &mut value, range, "") +} + +/// Non monomorphized implementation for u64 editing. +pub fn edit_u64_raw( + ui: &mut egui::Ui, + value: &mut MaybeMutRef<'_, u64>, + range: RangeInclusive, + suffix: &str, +) -> egui::Response { + let speed = (**value as f64 * 0.01).at_least(0.001); + edit_u64_raw_with_speed_impl(ui, value, range, speed, suffix) +} + +/// Non monomorphized implementation for u64 editing with a given speed. +pub fn edit_u64_raw_with_speed_impl( + ui: &mut egui::Ui, + value: &mut MaybeMutRef<'_, u64>, + range: RangeInclusive, + speed: f64, + suffix: &str, +) -> egui::Response { + if let Some(value) = value.as_mut() { + ui.add( + egui::DragValue::new(value) + .clamp_existing_to_range(false) + .range(range) + .speed(speed) + .suffix(suffix), + ) + } else { + ui.label(format!("{}{}", re_format::format_uint(**value), suffix)) + } +} diff --git a/crates/viewer/re_component_ui/src/datatype_uis/mod.rs b/crates/viewer/re_component_ui/src/datatype_uis/mod.rs index 5147a63dac32..b355a9e0aeae 100644 --- a/crates/viewer/re_component_ui/src/datatype_uis/mod.rs +++ b/crates/viewer/re_component_ui/src/datatype_uis/mod.rs @@ -1,6 +1,7 @@ mod bool_toggle; mod enum_combobox; mod float_drag; +mod int_drag; mod range1d; mod singleline_string; mod vec; @@ -14,8 +15,10 @@ pub use enum_combobox::{ }; pub use float_drag::{ edit_f32_float_raw, edit_f32_min_to_max_float, edit_f32_zero_to_max, edit_f32_zero_to_one, - edit_f64_float_raw_with_speed_impl, edit_ui_points, + edit_f64_float_raw_with_speed_impl, edit_f64_min_to_max_float, edit_f64_zero_to_max, + edit_ui_points, }; +pub use int_drag::edit_u64_range; pub use range1d::edit_view_range1d; pub use singleline_string::{ display_name_ui, display_text_ui, edit_multiline_string, edit_singleline_string, diff --git a/crates/viewer/re_component_ui/src/lib.rs b/crates/viewer/re_component_ui/src/lib.rs index abe649c8b3a7..3877b6648cff 100644 --- a/crates/viewer/re_component_ui/src/lib.rs +++ b/crates/viewer/re_component_ui/src/lib.rs @@ -28,15 +28,16 @@ mod zoom_level; use datatype_uis::{ display_name_ui, display_text_ui, edit_bool, edit_f32_min_to_max_float, edit_f32_zero_to_max, - edit_f32_zero_to_one, edit_multiline_string, edit_or_view_vec2d, edit_or_view_vec3d, - edit_singleline_string, edit_ui_points, edit_view_enum, edit_view_enum_with_variant_available, - edit_view_range1d, view_uuid, view_view_id, + edit_f32_zero_to_one, edit_f64_min_to_max_float, edit_f64_zero_to_max, edit_multiline_string, + edit_or_view_vec2d, edit_or_view_vec3d, edit_singleline_string, edit_u64_range, edit_ui_points, + edit_view_enum, edit_view_enum_with_variant_available, edit_view_range1d, view_uuid, + view_view_id, }; use re_types::{ blueprint::components::{ - BackgroundKind, Corner2D, GridSpacing, LockRangeDuringZoom, MapProvider, NearClipPlane, - ViewFit, Visible, + BackgroundKind, Corner2D, Enabled, ForceDistance, ForceIterations, ForceStrength, + GridSpacing, LockRangeDuringZoom, MapProvider, NearClipPlane, ViewFit, Visible, }, components::{ AggregationPolicy, AlbedoFactor, AxisLength, Color, DepthMeter, DrawOrder, FillMode, @@ -72,6 +73,7 @@ pub fn create_component_ui_registry() -> re_viewer_context::ComponentUiRegistry registry.add_singleline_edit_or_view::(edit_f32_zero_to_max); registry.add_singleline_edit_or_view::(edit_f32_zero_to_max); registry.add_singleline_edit_or_view::(edit_f32_zero_to_max); + registry.add_singleline_edit_or_view::(edit_f64_zero_to_max); registry.add_singleline_edit_or_view::(edit_f32_zero_to_max); registry.add_singleline_edit_or_view::(edit_f32_zero_to_max); registry.add_singleline_edit_or_view::(edit_f32_zero_to_max); @@ -81,12 +83,18 @@ pub fn create_component_ui_registry() -> re_viewer_context::ComponentUiRegistry // float min-max components: registry.add_singleline_edit_or_view::(edit_f32_min_to_max_float); + registry.add_singleline_edit_or_view::(edit_f64_min_to_max_float); // float 0-1 components: registry.add_singleline_edit_or_view::(edit_f32_zero_to_one); + // integer range components: + registry.add_singleline_edit_or_view::(|ctx, ui, value| { + edit_u64_range(ctx, ui, value, 1..=5) + }); + // Bool components: - registry.add_singleline_edit_or_view::(edit_bool); + registry.add_singleline_edit_or_view::(edit_bool); registry.add_singleline_edit_or_view::(edit_bool); registry.add_singleline_edit_or_view::(edit_bool); registry.add_singleline_edit_or_view::(edit_bool); @@ -154,11 +162,6 @@ pub fn create_component_ui_registry() -> re_viewer_context::ComponentUiRegistry registry.add_singleline_edit_or_view(radius::edit_radius_ui); registry.add_singleline_edit_or_view(marker_shape::edit_marker_shape_ui); - registry.add_multiline_edit_or_view(visual_bounds2d::multiline_edit_visual_bounds2d); - registry.add_singleline_edit_or_view(visual_bounds2d::singleline_edit_visual_bounds2d); - registry.add_multiline_edit_or_view(visual_bounds2d::multiline_edit_visual_bounds2d); - registry.add_singleline_edit_or_view(visual_bounds2d::singleline_edit_visual_bounds2d); - registry.add_singleline_edit_or_view(pinhole::singleline_view_pinhole); registry.add_multiline_edit_or_view(pinhole::multiline_view_pinhole); diff --git a/crates/viewer/re_space_view_graph/Cargo.toml b/crates/viewer/re_space_view_graph/Cargo.toml index 136dbbbb2ad3..6ba3f933edb0 100644 --- a/crates/viewer/re_space_view_graph/Cargo.toml +++ b/crates/viewer/re_space_view_graph/Cargo.toml @@ -23,6 +23,7 @@ re_data_ui.workspace = true re_chunk.workspace = true re_entity_db.workspace = true re_format.workspace = true +re_log.workspace = true re_log_types.workspace = true re_query.workspace = true re_renderer.workspace = true diff --git a/crates/viewer/re_space_view_graph/src/layout/mod.rs b/crates/viewer/re_space_view_graph/src/layout/mod.rs index a06d3748be2f..52cbf8fa094b 100644 --- a/crates/viewer/re_space_view_graph/src/layout/mod.rs +++ b/crates/viewer/re_space_view_graph/src/layout/mod.rs @@ -1,10 +1,12 @@ mod geometry; +mod params; mod provider; mod request; mod result; mod slots; pub use geometry::{EdgeGeometry, PathGeometry}; +pub use params::ForceLayoutParams; pub use provider::ForceLayoutProvider; pub use request::{EdgeTemplate, LayoutRequest}; pub use result::Layout; diff --git a/crates/viewer/re_space_view_graph/src/layout/params.rs b/crates/viewer/re_space_view_graph/src/layout/params.rs new file mode 100644 index 000000000000..14192d905c26 --- /dev/null +++ b/crates/viewer/re_space_view_graph/src/layout/params.rs @@ -0,0 +1,109 @@ +use re_types::{ + blueprint::{ + archetypes::{ForceCenter, ForceCollisionRadius, ForceLink, ForceManyBody, ForcePosition}, + components::{Enabled, ForceDistance, ForceIterations, ForceStrength}, + }, + components::Position2D, + Archetype, Component, +}; +use re_viewer_context::{ComponentFallbackProvider, SpaceViewState, ViewQuery, ViewerContext}; +use re_viewport_blueprint::{ViewProperty, ViewPropertyQueryError}; + +#[derive(Debug, PartialEq)] +pub struct ForceLayoutParams { + // Link + pub(super) force_link_enabled: Enabled, + pub(super) force_link_distance: ForceDistance, + pub(super) force_link_iterations: ForceIterations, + // Many body + pub(super) force_many_body_enabled: Enabled, + pub(super) force_many_body_strength: ForceStrength, + // Position + pub(super) force_position_enabled: Enabled, + pub(super) force_position_strength: ForceStrength, + pub(super) force_position_pos: Position2D, + // Center + pub(super) force_center_enabled: Enabled, + pub(super) force_center_strength: ForceStrength, + // Collision + pub(super) force_collision_enabled: Enabled, + pub(super) force_collision_strength: ForceStrength, + pub(super) force_collision_iterations: ForceIterations, +} + +/// Convenience struct for querying the components of a blueprint archetype or its fallbacks. +struct QueryArchetype<'a, T> { + ctx: &'a ViewerContext<'a>, + provider: &'a dyn ComponentFallbackProvider, + view_state: &'a dyn SpaceViewState, + property: ViewProperty, + _marker: std::marker::PhantomData, +} + +impl<'a, T: Archetype> QueryArchetype<'a, T> { + fn new( + ctx: &'a ViewerContext<'a>, + query: &'a ViewQuery<'a>, + provider: &'a dyn ComponentFallbackProvider, + view_state: &'a dyn SpaceViewState, + ) -> Self { + let property = ViewProperty::from_archetype::( + ctx.blueprint_db(), + ctx.blueprint_query, + query.space_view_id, + ); + Self { + ctx, + provider, + view_state, + property, + _marker: Default::default(), + } + } + + fn get(&self) -> Result + where + R: Component + Default, + { + self.property + .component_or_fallback(self.ctx, self.provider, self.view_state) + } +} + +impl ForceLayoutParams { + pub fn get( + ctx: &ViewerContext<'_>, + query: &ViewQuery<'_>, + provider: &dyn ComponentFallbackProvider, + view_state: &dyn SpaceViewState, + ) -> Result { + // Query the components for the archetype + let force_link = QueryArchetype::::new(ctx, query, provider, view_state); + let force_many = QueryArchetype::::new(ctx, query, provider, view_state); + let force_position = QueryArchetype::::new(ctx, query, provider, view_state); + let force_center = QueryArchetype::::new(ctx, query, provider, view_state); + let force_collision = + QueryArchetype::::new(ctx, query, provider, view_state); + + Ok(Self { + // Link + force_link_enabled: force_link.get()?, + force_link_distance: force_link.get()?, + force_link_iterations: force_link.get()?, + // Many body + force_many_body_enabled: force_many.get()?, + force_many_body_strength: force_many.get()?, + // Position + force_position_enabled: force_position.get()?, + force_position_strength: force_position.get()?, + force_position_pos: force_position.get()?, + // Center + force_center_enabled: force_center.get()?, + force_center_strength: force_center.get()?, + // Collision + force_collision_enabled: force_collision.get()?, + force_collision_strength: force_collision.get()?, + force_collision_iterations: force_collision.get()?, + }) + } +} diff --git a/crates/viewer/re_space_view_graph/src/layout/provider.rs b/crates/viewer/re_space_view_graph/src/layout/provider.rs index f4af4f5409d5..72c6b7a31f17 100644 --- a/crates/viewer/re_space_view_graph/src/layout/provider.rs +++ b/crates/viewer/re_space_view_graph/src/layout/provider.rs @@ -6,11 +6,12 @@ // layouts, such as `dot` from `graphviz`. use egui::{Pos2, Rect, Vec2}; -use fjadra::{self as fj}; +use fjadra::{self as fj, Simulation}; use crate::graph::{EdgeId, NodeId}; use super::{ + params::ForceLayoutParams, request::NodeTemplate, slots::{slotted_edges, Slot, SlotKind}, EdgeGeometry, EdgeTemplate, Layout, LayoutRequest, PathGeometry, @@ -25,6 +26,77 @@ impl<'a> From<&'a NodeTemplate> for fj::Node { } } +// TODO(grtlr): Do this more efficiently, as this currently rebuilds all helper functions. +pub fn update_simulation( + mut simulation: fj::Simulation, + params: &ForceLayoutParams, + edges: Vec<(usize, usize)>, + radii: Vec, +) -> Simulation { + // We destructure here to get compiler warnings if we add new parameters. + let &ForceLayoutParams { + force_link_enabled, + force_link_distance, + force_link_iterations, + force_many_body_enabled, + force_many_body_strength, + force_position_enabled, + force_position_strength, + force_position_pos, + force_center_enabled, + force_center_strength, + force_collision_enabled, + force_collision_strength, + force_collision_iterations, + } = params; + + if **force_link_enabled { + simulation = simulation.add_force( + "link", + fj::Link::new(edges) + .distance(**force_link_distance) + .iterations(**force_link_iterations as usize), + ); + } + if **force_many_body_enabled { + simulation = simulation.add_force( + "charge", + fj::ManyBody::new().strength(**force_many_body_strength), + ); + } + if **force_position_enabled { + simulation = simulation + .add_force( + "x", + fj::PositionX::new() + .strength(**force_position_strength) + .x(force_position_pos[0].into()), + ) + .add_force( + "y", + fj::PositionY::new() + .strength(**force_position_strength) + .y(force_position_pos[1].into()), + ); + } + if **force_collision_enabled { + simulation = simulation.add_force( + "collision", + fj::Collide::new() + .radius(move |i| radii[i]) + .iterations(**force_collision_iterations as usize) + .strength(**force_collision_strength), + ); + } + if **force_center_enabled { + simulation = simulation.add_force( + "center", + fj::Center::new().strength(**force_center_strength), + ); + } + simulation +} + pub struct ForceLayoutProvider { simulation: fj::Simulation, pub request: LayoutRequest, @@ -44,19 +116,17 @@ fn considered_edges(request: &LayoutRequest) -> Vec<(usize, usize)> { } impl ForceLayoutProvider { - pub fn new(request: LayoutRequest) -> Self { + pub fn new(request: LayoutRequest, params: &ForceLayoutParams) -> Self { let nodes = request.all_nodes().map(|(_, v)| fj::Node::from(v)); + let radii = request + .all_nodes() + .map(|(_, v)| v.size.max_elem() as f64 / 2.0) + .collect::>(); let edges = considered_edges(&request); - // TODO(grtlr): Currently we guesstimate good forces. Eventually these should be exposed as blueprints. - let simulation = fj::SimulationBuilder::default() - .with_alpha_decay(0.01) // TODO(grtlr): slows down the simulation for demo - .build(nodes) - .add_force("link", fj::Link::new(edges).distance(50.0).iterations(2)) - .add_force("charge", fj::ManyBody::new()) - // TODO(grtlr): This is a small stop-gap until we have blueprints to prevent nodes from flying away. - .add_force("x", fj::PositionX::new().strength(0.01)) - .add_force("y", fj::PositionY::new().strength(0.01)); + let simulation = fj::SimulationBuilder::default().build(nodes); + + let simulation = update_simulation(simulation, params, edges, radii); Self { simulation, @@ -64,7 +134,11 @@ impl ForceLayoutProvider { } } - pub fn new_with_previous(request: LayoutRequest, layout: &Layout) -> Self { + pub fn new_with_previous( + request: LayoutRequest, + layout: &Layout, + params: &ForceLayoutParams, + ) -> Self { let nodes = request.all_nodes().map(|(id, v)| { if let Some(rect) = layout.get_node(&id) { let pos = rect.center(); @@ -73,17 +147,14 @@ impl ForceLayoutProvider { fj::Node::from(v) } }); + let radii = request + .all_nodes() + .map(|(_, v)| v.size.max_elem() as f64 / 2.0) + .collect::>(); let edges = considered_edges(&request); - // TODO(grtlr): Currently we guesstimate good forces. Eventually these should be exposed as blueprints. - let simulation = fj::SimulationBuilder::default() - .with_alpha_decay(0.01) // TODO(grtlr): slows down the simulation for demo - .build(nodes) - .add_force("link", fj::Link::new(edges).distance(50.0).iterations(2)) - .add_force("charge", fj::ManyBody::new()) - // TODO(grtlr): This is a small stop-gap until we have blueprints to prevent nodes from flying away. - .add_force("x", fj::PositionX::new().strength(0.01)) - .add_force("y", fj::PositionY::new().strength(0.01)); + let simulation = fj::SimulationBuilder::default().build(nodes); + let simulation = update_simulation(simulation, params, edges, radii); Self { simulation, @@ -229,7 +300,7 @@ impl ForceLayoutProvider { } pub fn is_finished(&self) -> bool { - self.simulation.finished() + self.simulation.is_finished() } } diff --git a/crates/viewer/re_space_view_graph/src/properties.rs b/crates/viewer/re_space_view_graph/src/properties.rs index de6b0255f0ca..402831a223a8 100644 --- a/crates/viewer/re_space_view_graph/src/properties.rs +++ b/crates/viewer/re_space_view_graph/src/properties.rs @@ -1,4 +1,11 @@ -use re_types::blueprint::components::VisualBounds2D; +use re_types::{ + blueprint::{ + archetypes, + components::{Enabled, ForceDistance, ForceIterations, ForceStrength, VisualBounds2D}, + }, + components::Position2D, + Archetype as _, +}; use re_viewer_context::{SpaceViewStateExt as _, TypedComponentFallbackProvider}; use crate::{ui::GraphSpaceViewState, GraphSpaceView}; @@ -20,4 +27,47 @@ impl TypedComponentFallbackProvider for GraphSpaceView { } } -re_viewer_context::impl_component_fallback_provider!(GraphSpaceView => [VisualBounds2D]); +impl TypedComponentFallbackProvider for GraphSpaceView { + fn fallback_for(&self, ctx: &re_viewer_context::QueryContext<'_>) -> Enabled { + match ctx.archetype_name { + Some(name) if name == archetypes::ForceLink::name() => true.into(), + Some(name) if name == archetypes::ForceManyBody::name() => true.into(), + Some(name) if name == archetypes::ForcePosition::name() => true.into(), + _ => false.into(), + } + } +} + +impl TypedComponentFallbackProvider for GraphSpaceView { + fn fallback_for(&self, _ctx: &re_viewer_context::QueryContext<'_>) -> ForceDistance { + (60.).into() + } +} + +impl TypedComponentFallbackProvider for GraphSpaceView { + fn fallback_for(&self, ctx: &re_viewer_context::QueryContext<'_>) -> ForceStrength { + match ctx.archetype_name { + Some(name) if name == archetypes::ForceManyBody::name() => (-60.).into(), + Some(name) if name == archetypes::ForcePosition::name() => (0.01).into(), + _ => (1.0).into(), + } + } +} + +impl TypedComponentFallbackProvider for GraphSpaceView { + fn fallback_for(&self, ctx: &re_viewer_context::QueryContext<'_>) -> ForceIterations { + match ctx.archetype_name { + Some(name) if name == archetypes::ForceLink::name() => 3.into(), + Some(name) if name == archetypes::ForceCollisionRadius::name() => 1.into(), + _ => Default::default(), + } + } +} + +impl TypedComponentFallbackProvider for GraphSpaceView { + fn fallback_for(&self, _ctx: &re_viewer_context::QueryContext<'_>) -> Position2D { + Default::default() + } +} + +re_viewer_context::impl_component_fallback_provider!(GraphSpaceView => [VisualBounds2D, Enabled, ForceDistance, ForceStrength, ForceIterations, Position2D]); diff --git a/crates/viewer/re_space_view_graph/src/ui/draw.rs b/crates/viewer/re_space_view_graph/src/ui/draw.rs index 21ab773bafa0..0379e9de5518 100644 --- a/crates/viewer/re_space_view_graph/src/ui/draw.rs +++ b/crates/viewer/re_space_view_graph/src/ui/draw.rs @@ -89,9 +89,11 @@ impl DrawableLabel { fn draw_circle_label( ui: &mut Ui, label: &CircleLabel, - _highlight: InteractionHighlight, + highlight: InteractionHighlight, ) -> Response { let &CircleLabel { radius, color } = label; + let visuals = &ui.style().visuals.clone(); + let (resp, painter) = ui.allocate_painter(Vec2::splat(radius * 2.0), Sense::click()); painter.circle( resp.rect.center(), @@ -99,6 +101,16 @@ fn draw_circle_label( color.unwrap_or_else(|| ui.style().visuals.text_color()), Stroke::NONE, ); + + if highlight.selection == SelectionHighlight::Selection { + painter.circle( + resp.rect.center(), + radius - 2.0, + Color32::TRANSPARENT, + Stroke::new(2.0, visuals.selection.stroke.color), + ); + } + resp } diff --git a/crates/viewer/re_space_view_graph/src/ui/mod.rs b/crates/viewer/re_space_view_graph/src/ui/mod.rs index 57c7974e5b72..876b32ffb8ac 100644 --- a/crates/viewer/re_space_view_graph/src/ui/mod.rs +++ b/crates/viewer/re_space_view_graph/src/ui/mod.rs @@ -1,5 +1,7 @@ mod draw; +mod selection; mod state; pub use draw::{draw_debug, draw_graph, DrawableLabel}; +pub use selection::view_property_force_ui; pub use state::GraphSpaceViewState; diff --git a/crates/viewer/re_space_view_graph/src/ui/selection.rs b/crates/viewer/re_space_view_graph/src/ui/selection.rs new file mode 100644 index 000000000000..3b67eeef116f --- /dev/null +++ b/crates/viewer/re_space_view_graph/src/ui/selection.rs @@ -0,0 +1,90 @@ +use re_space_view::{view_property_component_ui, view_property_component_ui_custom}; +use re_types::{ + blueprint::components::Enabled, Archetype, ArchetypeReflectionMarker, Component as _, +}; +use re_viewer_context::{ComponentFallbackProvider, SpaceViewId, SpaceViewState, ViewerContext}; +use re_viewport_blueprint::ViewProperty; + +/// This function is similar to [`view_property_component_ui`], but it always +/// picks the [`Enabled`] component for the single-line edit UI. +/// Also, it will always show the single-line edit UI (and not only if there is +/// a single property per archetype). +pub fn view_property_force_ui( + ctx: &ViewerContext<'_>, + ui: &mut egui::Ui, + view_id: SpaceViewId, + fallback_provider: &dyn ComponentFallbackProvider, + view_state: &dyn SpaceViewState, +) { + let property = + ViewProperty::from_archetype::(ctx.blueprint_db(), ctx.blueprint_query, view_id); + + let Some(reflection) = ctx.reflection.archetypes.get(&property.archetype_name) else { + // The `ArchetypeReflectionMarker` bound should make this impossible. + re_log::warn_once!( + "Missing reflection data for archetype {:?}.", + property.archetype_name + ); + return; + }; + + let query_ctx = property.query_context(ctx, view_state); + + if reflection.fields.len() == 1 { + let field = &reflection.fields[0]; + + view_property_component_ui( + &query_ctx, + ui, + &property, + reflection.display_name, + field, + fallback_provider, + ); + } else { + let sub_prop_ui = |ui: &mut egui::Ui| { + for field in &reflection.fields { + view_property_component_ui( + &query_ctx, + ui, + &property, + field.display_name, + field, + fallback_provider, + ); + } + }; + + let field = reflection + .fields + .iter() + .find(|field| field.component_name == Enabled::name()) + .expect("forces are required to have an `Enabled` component"); + + let component_array = property.component_raw(field.component_name); + let row_id = property.component_row_id(field.component_name); + + let singleline_ui: &dyn Fn(&mut egui::Ui) = &|ui| { + ctx.component_ui_registry.singleline_edit_ui( + &query_ctx, + ui, + ctx.blueprint_db(), + query_ctx.target_entity_path, + field.component_name, + row_id, + component_array.as_deref(), + fallback_provider, + ); + }; + + view_property_component_ui_custom( + &query_ctx, + ui, + &property, + reflection.display_name, + field, + singleline_ui, + Some(&sub_prop_ui), + ); + } +} diff --git a/crates/viewer/re_space_view_graph/src/ui/state.rs b/crates/viewer/re_space_view_graph/src/ui/state.rs index 4f22ca995c53..60f901a3c160 100644 --- a/crates/viewer/re_space_view_graph/src/ui/state.rs +++ b/crates/viewer/re_space_view_graph/src/ui/state.rs @@ -4,7 +4,7 @@ use re_types::blueprint::components::VisualBounds2D; use re_ui::UiExt; use re_viewer_context::SpaceViewState; -use crate::layout::{ForceLayoutProvider, Layout, LayoutRequest}; +use crate::layout::{ForceLayoutParams, ForceLayoutProvider, Layout, LayoutRequest}; /// Space view state for the custom space view. /// @@ -67,10 +67,12 @@ pub enum LayoutState { InProgress { layout: Layout, provider: ForceLayoutProvider, + params: ForceLayoutParams, }, Finished { layout: Layout, provider: ForceLayoutProvider, + params: ForceLayoutParams, }, } @@ -97,48 +99,83 @@ impl LayoutState { } /// A simple state machine that keeps track of the different stages and if the layout needs to be recomputed. - fn update(self, new_request: LayoutRequest) -> Self { + fn update(self, new_request: LayoutRequest, new_params: ForceLayoutParams) -> Self { match self { // Layout is up to date, nothing to do here. - Self::Finished { ref provider, .. } if provider.request == new_request => { + Self::Finished { + ref provider, + ref params, + .. + } if (provider.request == new_request) && (params == &new_params) => { self // no op } // We need to recompute the layout. Self::None => { - let mut provider = ForceLayoutProvider::new(new_request); + let mut provider = ForceLayoutProvider::new(new_request, &new_params); let layout = provider.tick(); - Self::InProgress { layout, provider } + Self::InProgress { + layout, + provider, + params: new_params, + } } Self::Finished { layout, .. } => { - let mut provider = ForceLayoutProvider::new_with_previous(new_request, &layout); + let mut provider = + ForceLayoutProvider::new_with_previous(new_request, &layout, &new_params); let layout = provider.tick(); - Self::InProgress { layout, provider } + Self::InProgress { + layout, + provider, + params: new_params, + } } Self::InProgress { layout, provider, .. } if provider.request != new_request => { - let mut provider = ForceLayoutProvider::new_with_previous(new_request, &layout); + let mut provider = + ForceLayoutProvider::new_with_previous(new_request, &layout, &new_params); let layout = provider.tick(); - Self::InProgress { layout, provider } + Self::InProgress { + layout, + provider, + params: new_params, + } } // We keep iterating on the layout until it is stable. Self::InProgress { mut provider, layout, - } => match provider.is_finished() { - true => Self::Finished { layout, provider }, - false => Self::InProgress { + params: old_params, + } => match (provider.is_finished(), new_params == old_params) { + (true, true) => Self::Finished { + layout, + provider, + params: new_params, + }, + (false, true) => Self::InProgress { layout: provider.tick(), provider, + params: new_params, }, + _ => { + let mut provider = + ForceLayoutProvider::new_with_previous(new_request, &layout, &new_params); + let layout = provider.tick(); + + Self::InProgress { + layout, + provider, + params: new_params, + } + } }, } } /// This method is lazy. A new layout is only computed if the current timestamp requires it. - pub fn get(&mut self, request: LayoutRequest) -> &mut Layout { - *self = std::mem::take(self).update(request); + pub fn get(&mut self, request: LayoutRequest, params: ForceLayoutParams) -> &mut Layout { + *self = std::mem::take(self).update(request, params); match self { Self::Finished { layout, .. } | Self::InProgress { layout, .. } => layout, diff --git a/crates/viewer/re_space_view_graph/src/view.rs b/crates/viewer/re_space_view_graph/src/view.rs index 6539892a1447..dc84ead92cc3 100644 --- a/crates/viewer/re_space_view_graph/src/view.rs +++ b/crates/viewer/re_space_view_graph/src/view.rs @@ -4,7 +4,13 @@ use re_space_view::{ view_property_ui, }; use re_types::{ - blueprint::{self, archetypes::VisualBounds2D}, + blueprint::{ + self, + archetypes::{ + ForceCenter, ForceCollisionRadius, ForceLink, ForceManyBody, ForcePosition, + VisualBounds2D, + }, + }, SpaceViewClassIdentifier, }; use re_ui::{ @@ -22,8 +28,8 @@ use re_viewport_blueprint::ViewProperty; use crate::{ graph::Graph, - layout::LayoutRequest, - ui::{draw_debug, draw_graph, GraphSpaceViewState}, + layout::{ForceLayoutParams, LayoutRequest}, + ui::{draw_debug, draw_graph, view_property_force_ui, GraphSpaceViewState}, visualizers::{merge, EdgesVisualizer, NodeVisualizer}, }; @@ -129,7 +135,14 @@ Display a graph of nodes and edges. state.debug_ui(ui); }); - view_property_ui::(ctx, ui, space_view_id, self, state); + re_ui::list_item::list_item_scope(ui, "graph_selection_ui", |ui| { + view_property_ui::(ctx, ui, space_view_id, self, state); + view_property_force_ui::(ctx, ui, space_view_id, self, state); + view_property_force_ui::(ctx, ui, space_view_id, self, state); + view_property_force_ui::(ctx, ui, space_view_id, self, state); + view_property_force_ui::(ctx, ui, space_view_id, self, state); + view_property_force_ui::(ctx, ui, space_view_id, self, state); + }); Ok(()) } @@ -164,11 +177,13 @@ Display a graph of nodes and edges. let rect_in_scene: blueprint::components::VisualBounds2D = bounds_property.component_or_fallback(ctx, self, state)?; + let params = ForceLayoutParams::get(ctx, query, self, state)?; + let rect_in_ui = ui.max_rect(); let request = LayoutRequest::from_graphs(graphs.iter()); let layout_was_empty = state.layout_state.is_none(); - let layout = state.layout_state.get(request); + let layout = state.layout_state.get(request, params); let mut ui_from_world = fit_to_rect_in_scene(rect_in_ui, rect_in_scene.into()); diff --git a/crates/viewer/re_space_view_spatial/src/view_3d_properties.rs b/crates/viewer/re_space_view_spatial/src/view_3d_properties.rs index 60721a944df4..3c9ddac728b9 100644 --- a/crates/viewer/re_space_view_spatial/src/view_3d_properties.rs +++ b/crates/viewer/re_space_view_spatial/src/view_3d_properties.rs @@ -4,7 +4,7 @@ use re_types::{ components::BackgroundKind, }, components::{Color, Plane3D, StrokeWidth}, - Archetype, + Archetype as _, }; use re_viewer_context::{SpaceViewStateExt as _, TypedComponentFallbackProvider}; diff --git a/crates/viewer/re_viewer/src/blueprint/validation_gen/mod.rs b/crates/viewer/re_viewer/src/blueprint/validation_gen/mod.rs index e2ffaf50eb40..0e307fbc746b 100644 --- a/crates/viewer/re_viewer/src/blueprint/validation_gen/mod.rs +++ b/crates/viewer/re_viewer/src/blueprint/validation_gen/mod.rs @@ -7,8 +7,12 @@ pub use re_types::blueprint::components::BackgroundKind; pub use re_types::blueprint::components::ColumnShare; pub use re_types::blueprint::components::ComponentColumnSelector; pub use re_types::blueprint::components::Corner2D; +pub use re_types::blueprint::components::Enabled; pub use re_types::blueprint::components::FilterByRange; pub use re_types::blueprint::components::FilterIsNotNull; +pub use re_types::blueprint::components::ForceDistance; +pub use re_types::blueprint::components::ForceIterations; +pub use re_types::blueprint::components::ForceStrength; pub use re_types::blueprint::components::GridSpacing; pub use re_types::blueprint::components::IncludedContent; pub use re_types::blueprint::components::Interactive; @@ -50,8 +54,12 @@ 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) + && validate_component::(blueprint) + && validate_component::(blueprint) && validate_component::(blueprint) && validate_component::(blueprint) && validate_component::(blueprint) diff --git a/crates/viewer/re_viewer/src/reflection/mod.rs b/crates/viewer/re_viewer/src/reflection/mod.rs index 2a4902df555e..72dd45c8db17 100644 --- a/crates/viewer/re_viewer/src/reflection/mod.rs +++ b/crates/viewer/re_viewer/src/reflection/mod.rs @@ -108,6 +108,14 @@ fn generate_component_reflection() -> Result::name(), + ComponentReflection { + docstring_md: "Whether a procedure is enabled.", + custom_placeholder: Some(Enabled::default().to_arrow2()?), + datatype: Enabled::arrow2_datatype(), + }, + ), ( ::name(), ComponentReflection { @@ -124,6 +132,30 @@ fn generate_component_reflection() -> Result::name(), + ComponentReflection { + docstring_md: "The target distance between two nodes.\n\nThis is helpful to scale the layout, for example if long labels are involved.", + custom_placeholder: Some(ForceDistance::default().to_arrow2()?), + datatype: ForceDistance::arrow2_datatype(), + }, + ), + ( + ::name(), + ComponentReflection { + docstring_md: "Specifies how often this force should be applied per iteration.\n\nIncreasing this parameter can lead to better results at the cost of longer computation time.", + custom_placeholder: Some(ForceIterations::default().to_arrow2()?), + datatype: ForceIterations::arrow2_datatype(), + }, + ), + ( + ::name(), + ComponentReflection { + docstring_md: "The strength of a given force.\n\nAllows to assign different weights to the individual forces, prioritizing one over the other.", + custom_placeholder: Some(ForceStrength::default().to_arrow2()?), + datatype: ForceStrength::arrow2_datatype(), + }, + ), ( ::name(), ComponentReflection { @@ -1954,6 +1986,99 @@ fn generate_archetype_reflection() -> ArchetypeReflectionMap { ], }, ), + ( + ArchetypeName::new("rerun.blueprint.archetypes.ForceCenter"), + ArchetypeReflection { + display_name: "Force center", + view_types: &[], + fields: vec![ + ArchetypeFieldReflection { component_name : + "rerun.blueprint.components.Enabled".into(), display_name : + "Enabled", docstring_md : "Whether the force is enabled.", + is_required : false, }, ArchetypeFieldReflection { component_name : + "rerun.blueprint.components.ForceStrength".into(), display_name : + "Strength", docstring_md : "The strength of the force.", is_required + : false, }, + ], + }, + ), + ( + ArchetypeName::new("rerun.blueprint.archetypes.ForceCollisionRadius"), + ArchetypeReflection { + display_name: "Force collision radius", + view_types: &[], + fields: vec![ + ArchetypeFieldReflection { component_name : + "rerun.blueprint.components.Enabled".into(), display_name : + "Enabled", docstring_md : "Whether the force is enabled.", + is_required : false, }, ArchetypeFieldReflection { component_name : + "rerun.blueprint.components.ForceStrength".into(), display_name : + "Strength", docstring_md : "The strength of the force.", is_required + : false, }, ArchetypeFieldReflection { component_name : + "rerun.blueprint.components.ForceIterations".into(), display_name : + "Iterations", docstring_md : + "Specifies how often this force should be applied per iteration.\n\nIncreasing this parameter can lead to better results at the cost of longer computation time.", + is_required : false, }, + ], + }, + ), + ( + ArchetypeName::new("rerun.blueprint.archetypes.ForceLink"), + ArchetypeReflection { + display_name: "Force link", + view_types: &[], + fields: vec![ + ArchetypeFieldReflection { component_name : + "rerun.blueprint.components.Enabled".into(), display_name : + "Enabled", docstring_md : "Whether the force is enabled.", + is_required : false, }, ArchetypeFieldReflection { component_name : + "rerun.blueprint.components.ForceDistance".into(), display_name : + "Distance", docstring_md : "The target distance between two nodes.", + is_required : false, }, ArchetypeFieldReflection { component_name : + "rerun.blueprint.components.ForceIterations".into(), display_name : + "Iterations", docstring_md : + "Specifies how often this force should be applied per iteration.\n\nIncreasing this parameter can lead to better results at the cost of longer computation time.", + is_required : false, }, + ], + }, + ), + ( + ArchetypeName::new("rerun.blueprint.archetypes.ForceManyBody"), + ArchetypeReflection { + display_name: "Force many body", + view_types: &[], + fields: vec![ + ArchetypeFieldReflection { component_name : + "rerun.blueprint.components.Enabled".into(), display_name : + "Enabled", docstring_md : "Whether the force is enabled.", + is_required : false, }, ArchetypeFieldReflection { component_name : + "rerun.blueprint.components.ForceStrength".into(), display_name : + "Strength", docstring_md : + "The strength of the force.\n\nIf `strength` is smaller than 0, it pushes nodes apart, if it is larger than 0 it pulls them together.", + is_required : false, }, + ], + }, + ), + ( + ArchetypeName::new("rerun.blueprint.archetypes.ForcePosition"), + ArchetypeReflection { + display_name: "Force position", + view_types: &[], + fields: vec![ + ArchetypeFieldReflection { component_name : + "rerun.blueprint.components.Enabled".into(), display_name : + "Enabled", docstring_md : "Whether the force is enabled.", + is_required : false, }, ArchetypeFieldReflection { component_name : + "rerun.blueprint.components.ForceStrength".into(), display_name : + "Strength", docstring_md : "The strength of the force.", is_required + : false, }, ArchetypeFieldReflection { component_name : + "rerun.components.Position2D".into(), display_name : "Position", + docstring_md : + "The position where the nodes should be pulled towards.", is_required + : false, }, + ], + }, + ), ( ArchetypeName::new("rerun.blueprint.archetypes.LineGrid3D"), ArchetypeReflection { diff --git a/docs/content/reference/types/views/graph_view.md b/docs/content/reference/types/views/graph_view.md index 58432cb123b8..4b483c3fda87 100644 --- a/docs/content/reference/types/views/graph_view.md +++ b/docs/content/reference/types/views/graph_view.md @@ -14,6 +14,34 @@ Somethings outside of these bounds may also be visible due to letterboxing. * `range`: Controls the visible range of a 2D view. * `near_clip_plane`: Controls the distance to the near clip plane in 3D scene units. +### `force_link` +Allows to control the interaction between two nodes connected by an edge. + +* `enabled`: Whether the force is enabled. +* `distance`: The target distance between two nodes. +* `iterations`: Specifies how often this force should be applied per iteration. +### `force_many_body` +A force between each pair of nodes that ressembles an electrical charge. + +* `enabled`: Whether the force is enabled. +* `strength`: The strength of the force. +### `force_position` +Similar to gravity, this force pulls nodes towards a specific position. + +* `enabled`: Whether the force is enabled. +* `strength`: The strength of the force. +* `position`: The position where the nodes should be pulled towards. +### `force_collision_radius` +Resolves collisions between the bounding spheres, according to the radius of the nodes. + +* `enabled`: Whether the force is enabled. +* `strength`: The strength of the force. +* `iterations`: Specifies how often this force should be applied per iteration. +### `force_center` +Tries to move the center of mass of the graph to the origin. + +* `enabled`: Whether the force is enabled. +* `strength`: The strength of the force. ## API reference links * 🐍 [Python API docs for `GraphView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views?speculative-link#rerun.blueprint.views.GraphView) diff --git a/rerun_cpp/src/rerun/blueprint/archetypes.hpp b/rerun_cpp/src/rerun/blueprint/archetypes.hpp index 09042a682126..75ec3053e31b 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes.hpp @@ -5,6 +5,11 @@ #include "blueprint/archetypes/background.hpp" #include "blueprint/archetypes/container_blueprint.hpp" #include "blueprint/archetypes/dataframe_query.hpp" +#include "blueprint/archetypes/force_center.hpp" +#include "blueprint/archetypes/force_collision_radius.hpp" +#include "blueprint/archetypes/force_link.hpp" +#include "blueprint/archetypes/force_many_body.hpp" +#include "blueprint/archetypes/force_position.hpp" #include "blueprint/archetypes/line_grid3d.hpp" #include "blueprint/archetypes/map_background.hpp" #include "blueprint/archetypes/map_zoom.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes b/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes index ec736e25d263..e2e5fc6eb05e 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes @@ -7,6 +7,16 @@ container_blueprint.cpp linguist-generated=true container_blueprint.hpp linguist-generated=true dataframe_query.cpp linguist-generated=true dataframe_query.hpp linguist-generated=true +force_center.cpp linguist-generated=true +force_center.hpp linguist-generated=true +force_collision_radius.cpp linguist-generated=true +force_collision_radius.hpp linguist-generated=true +force_link.cpp linguist-generated=true +force_link.hpp linguist-generated=true +force_many_body.cpp linguist-generated=true +force_many_body.hpp linguist-generated=true +force_position.cpp linguist-generated=true +force_position.hpp linguist-generated=true line_grid3d.cpp linguist-generated=true line_grid3d.hpp linguist-generated=true map_background.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_center.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_center.cpp new file mode 100644 index 000000000000..a05527d07e18 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_center.cpp @@ -0,0 +1,52 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/force_center.fbs". + +#include "force_center.hpp" + +#include "../../collection_adapter_builtins.hpp" + +namespace rerun::blueprint::archetypes {} + +namespace rerun { + + Result> AsComponents::serialize( + const blueprint::archetypes::ForceCenter& archetype + ) { + using namespace blueprint::archetypes; + std::vector cells; + cells.reserve(3); + + if (archetype.enabled.has_value()) { + auto result = ComponentBatch::from_loggable( + archetype.enabled.value(), + ComponentDescriptor( + "rerun.blueprint.archetypes.ForceCenter", + "enabled", + "rerun.blueprint.components.Enabled" + ) + ); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + if (archetype.strength.has_value()) { + auto result = ComponentBatch::from_loggable( + archetype.strength.value(), + ComponentDescriptor( + "rerun.blueprint.archetypes.ForceCenter", + "strength", + "rerun.blueprint.components.ForceStrength" + ) + ); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + { + auto indicator = ForceCenter::IndicatorComponent(); + auto result = ComponentBatch::from_loggable(indicator); + RR_RETURN_NOT_OK(result.error); + cells.emplace_back(std::move(result.value)); + } + + return cells; + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_center.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_center.hpp new file mode 100644 index 000000000000..8c3854765b91 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_center.hpp @@ -0,0 +1,69 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/force_center.fbs". + +#pragma once + +#include "../../blueprint/components/enabled.hpp" +#include "../../blueprint/components/force_strength.hpp" +#include "../../collection.hpp" +#include "../../compiler_utils.hpp" +#include "../../component_batch.hpp" +#include "../../indicator_component.hpp" +#include "../../result.hpp" + +#include +#include +#include +#include + +namespace rerun::blueprint::archetypes { + /// **Archetype**: Tries to move the center of mass of the graph to the origin. + struct ForceCenter { + /// Whether the force is enabled. + std::optional enabled; + + /// The strength of the force. + std::optional strength; + + public: + static constexpr const char IndicatorComponentName[] = + "rerun.blueprint.components.ForceCenterIndicator"; + + /// Indicator component, used to identify the archetype when converting to a list of components. + using IndicatorComponent = rerun::components::IndicatorComponent; + + public: + ForceCenter() = default; + ForceCenter(ForceCenter&& other) = default; + + /// Whether the force is enabled. + ForceCenter with_enabled(rerun::blueprint::components::Enabled _enabled) && { + enabled = std::move(_enabled); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + + /// The strength of the force. + ForceCenter with_strength(rerun::blueprint::components::ForceStrength _strength) && { + strength = std::move(_strength); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + }; + +} // namespace rerun::blueprint::archetypes + +namespace rerun { + /// \private + template + struct AsComponents; + + /// \private + template <> + struct AsComponents { + /// Serialize all set component batches. + static Result> serialize( + const blueprint::archetypes::ForceCenter& archetype + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.cpp new file mode 100644 index 000000000000..1fd8539d8a54 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.cpp @@ -0,0 +1,65 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/force_collision_radius.fbs". + +#include "force_collision_radius.hpp" + +#include "../../collection_adapter_builtins.hpp" + +namespace rerun::blueprint::archetypes {} + +namespace rerun { + + Result> + AsComponents::serialize( + const blueprint::archetypes::ForceCollisionRadius& archetype + ) { + using namespace blueprint::archetypes; + std::vector cells; + cells.reserve(4); + + if (archetype.enabled.has_value()) { + auto result = ComponentBatch::from_loggable( + archetype.enabled.value(), + ComponentDescriptor( + "rerun.blueprint.archetypes.ForceCollisionRadius", + "enabled", + "rerun.blueprint.components.Enabled" + ) + ); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + if (archetype.strength.has_value()) { + auto result = ComponentBatch::from_loggable( + archetype.strength.value(), + ComponentDescriptor( + "rerun.blueprint.archetypes.ForceCollisionRadius", + "strength", + "rerun.blueprint.components.ForceStrength" + ) + ); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + if (archetype.iterations.has_value()) { + auto result = ComponentBatch::from_loggable( + archetype.iterations.value(), + ComponentDescriptor( + "rerun.blueprint.archetypes.ForceCollisionRadius", + "iterations", + "rerun.blueprint.components.ForceIterations" + ) + ); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + { + auto indicator = ForceCollisionRadius::IndicatorComponent(); + auto result = ComponentBatch::from_loggable(indicator); + RR_RETURN_NOT_OK(result.error); + cells.emplace_back(std::move(result.value)); + } + + return cells; + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.hpp new file mode 100644 index 000000000000..5b8ff3d1d511 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.hpp @@ -0,0 +1,87 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/force_collision_radius.fbs". + +#pragma once + +#include "../../blueprint/components/enabled.hpp" +#include "../../blueprint/components/force_iterations.hpp" +#include "../../blueprint/components/force_strength.hpp" +#include "../../collection.hpp" +#include "../../compiler_utils.hpp" +#include "../../component_batch.hpp" +#include "../../indicator_component.hpp" +#include "../../result.hpp" + +#include +#include +#include +#include + +namespace rerun::blueprint::archetypes { + /// **Archetype**: Resolves collisions between the bounding spheres, according to the radius of the nodes. + struct ForceCollisionRadius { + /// Whether the force is enabled. + std::optional enabled; + + /// The strength of the force. + std::optional strength; + + /// Specifies how often this force should be applied per iteration. + /// + /// Increasing this parameter can lead to better results at the cost of longer computation time. + std::optional iterations; + + public: + static constexpr const char IndicatorComponentName[] = + "rerun.blueprint.components.ForceCollisionRadiusIndicator"; + + /// Indicator component, used to identify the archetype when converting to a list of components. + using IndicatorComponent = rerun::components::IndicatorComponent; + + public: + ForceCollisionRadius() = default; + ForceCollisionRadius(ForceCollisionRadius&& other) = default; + + /// Whether the force is enabled. + ForceCollisionRadius with_enabled(rerun::blueprint::components::Enabled _enabled) && { + enabled = std::move(_enabled); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + + /// The strength of the force. + ForceCollisionRadius with_strength(rerun::blueprint::components::ForceStrength _strength + ) && { + strength = std::move(_strength); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + + /// Specifies how often this force should be applied per iteration. + /// + /// Increasing this parameter can lead to better results at the cost of longer computation time. + ForceCollisionRadius with_iterations( + rerun::blueprint::components::ForceIterations _iterations + ) && { + iterations = std::move(_iterations); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + }; + +} // namespace rerun::blueprint::archetypes + +namespace rerun { + /// \private + template + struct AsComponents; + + /// \private + template <> + struct AsComponents { + /// Serialize all set component batches. + static Result> serialize( + const blueprint::archetypes::ForceCollisionRadius& archetype + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_link.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_link.cpp new file mode 100644 index 000000000000..7cda317fa91b --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_link.cpp @@ -0,0 +1,64 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/force_link.fbs". + +#include "force_link.hpp" + +#include "../../collection_adapter_builtins.hpp" + +namespace rerun::blueprint::archetypes {} + +namespace rerun { + + Result> AsComponents::serialize( + const blueprint::archetypes::ForceLink& archetype + ) { + using namespace blueprint::archetypes; + std::vector cells; + cells.reserve(4); + + if (archetype.enabled.has_value()) { + auto result = ComponentBatch::from_loggable( + archetype.enabled.value(), + ComponentDescriptor( + "rerun.blueprint.archetypes.ForceLink", + "enabled", + "rerun.blueprint.components.Enabled" + ) + ); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + if (archetype.distance.has_value()) { + auto result = ComponentBatch::from_loggable( + archetype.distance.value(), + ComponentDescriptor( + "rerun.blueprint.archetypes.ForceLink", + "distance", + "rerun.blueprint.components.ForceDistance" + ) + ); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + if (archetype.iterations.has_value()) { + auto result = ComponentBatch::from_loggable( + archetype.iterations.value(), + ComponentDescriptor( + "rerun.blueprint.archetypes.ForceLink", + "iterations", + "rerun.blueprint.components.ForceIterations" + ) + ); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + { + auto indicator = ForceLink::IndicatorComponent(); + auto result = ComponentBatch::from_loggable(indicator); + RR_RETURN_NOT_OK(result.error); + cells.emplace_back(std::move(result.value)); + } + + return cells; + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_link.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_link.hpp new file mode 100644 index 000000000000..0d88538bc59b --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_link.hpp @@ -0,0 +1,84 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/force_link.fbs". + +#pragma once + +#include "../../blueprint/components/enabled.hpp" +#include "../../blueprint/components/force_distance.hpp" +#include "../../blueprint/components/force_iterations.hpp" +#include "../../collection.hpp" +#include "../../compiler_utils.hpp" +#include "../../component_batch.hpp" +#include "../../indicator_component.hpp" +#include "../../result.hpp" + +#include +#include +#include +#include + +namespace rerun::blueprint::archetypes { + /// **Archetype**: Aims to achieve a target distance between two nodes that are connected by an edge. + struct ForceLink { + /// Whether the force is enabled. + std::optional enabled; + + /// The target distance between two nodes. + std::optional distance; + + /// Specifies how often this force should be applied per iteration. + /// + /// Increasing this parameter can lead to better results at the cost of longer computation time. + std::optional iterations; + + public: + static constexpr const char IndicatorComponentName[] = + "rerun.blueprint.components.ForceLinkIndicator"; + + /// Indicator component, used to identify the archetype when converting to a list of components. + using IndicatorComponent = rerun::components::IndicatorComponent; + + public: + ForceLink() = default; + ForceLink(ForceLink&& other) = default; + + /// Whether the force is enabled. + ForceLink with_enabled(rerun::blueprint::components::Enabled _enabled) && { + enabled = std::move(_enabled); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + + /// The target distance between two nodes. + ForceLink with_distance(rerun::blueprint::components::ForceDistance _distance) && { + distance = std::move(_distance); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + + /// Specifies how often this force should be applied per iteration. + /// + /// Increasing this parameter can lead to better results at the cost of longer computation time. + ForceLink with_iterations(rerun::blueprint::components::ForceIterations _iterations) && { + iterations = std::move(_iterations); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + }; + +} // namespace rerun::blueprint::archetypes + +namespace rerun { + /// \private + template + struct AsComponents; + + /// \private + template <> + struct AsComponents { + /// Serialize all set component batches. + static Result> serialize( + const blueprint::archetypes::ForceLink& archetype + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.cpp new file mode 100644 index 000000000000..58a115516b29 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.cpp @@ -0,0 +1,53 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/force_many_body.fbs". + +#include "force_many_body.hpp" + +#include "../../collection_adapter_builtins.hpp" + +namespace rerun::blueprint::archetypes {} + +namespace rerun { + + Result> + AsComponents::serialize( + const blueprint::archetypes::ForceManyBody& archetype + ) { + using namespace blueprint::archetypes; + std::vector cells; + cells.reserve(3); + + if (archetype.enabled.has_value()) { + auto result = ComponentBatch::from_loggable( + archetype.enabled.value(), + ComponentDescriptor( + "rerun.blueprint.archetypes.ForceManyBody", + "enabled", + "rerun.blueprint.components.Enabled" + ) + ); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + if (archetype.strength.has_value()) { + auto result = ComponentBatch::from_loggable( + archetype.strength.value(), + ComponentDescriptor( + "rerun.blueprint.archetypes.ForceManyBody", + "strength", + "rerun.blueprint.components.ForceStrength" + ) + ); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + { + auto indicator = ForceManyBody::IndicatorComponent(); + auto result = ComponentBatch::from_loggable(indicator); + RR_RETURN_NOT_OK(result.error); + cells.emplace_back(std::move(result.value)); + } + + return cells; + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.hpp new file mode 100644 index 000000000000..c5267b3cf692 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.hpp @@ -0,0 +1,75 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/force_many_body.fbs". + +#pragma once + +#include "../../blueprint/components/enabled.hpp" +#include "../../blueprint/components/force_strength.hpp" +#include "../../collection.hpp" +#include "../../compiler_utils.hpp" +#include "../../component_batch.hpp" +#include "../../indicator_component.hpp" +#include "../../result.hpp" + +#include +#include +#include +#include + +namespace rerun::blueprint::archetypes { + /// **Archetype**: A force between each pair of nodes that ressembles an electrical charge. + /// + /// If `strength` is smaller than 0, it pushes nodes apart, if it is larger than 0 it pulls them together. + struct ForceManyBody { + /// Whether the force is enabled. + std::optional enabled; + + /// The strength of the force. + /// + /// If `strength` is smaller than 0, it pushes nodes apart, if it is larger than 0 it pulls them together. + std::optional strength; + + public: + static constexpr const char IndicatorComponentName[] = + "rerun.blueprint.components.ForceManyBodyIndicator"; + + /// Indicator component, used to identify the archetype when converting to a list of components. + using IndicatorComponent = rerun::components::IndicatorComponent; + + public: + ForceManyBody() = default; + ForceManyBody(ForceManyBody&& other) = default; + + /// Whether the force is enabled. + ForceManyBody with_enabled(rerun::blueprint::components::Enabled _enabled) && { + enabled = std::move(_enabled); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + + /// The strength of the force. + /// + /// If `strength` is smaller than 0, it pushes nodes apart, if it is larger than 0 it pulls them together. + ForceManyBody with_strength(rerun::blueprint::components::ForceStrength _strength) && { + strength = std::move(_strength); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + }; + +} // namespace rerun::blueprint::archetypes + +namespace rerun { + /// \private + template + struct AsComponents; + + /// \private + template <> + struct AsComponents { + /// Serialize all set component batches. + static Result> serialize( + const blueprint::archetypes::ForceManyBody& archetype + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_position.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_position.cpp new file mode 100644 index 000000000000..d30542673513 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_position.cpp @@ -0,0 +1,65 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/force_position.fbs". + +#include "force_position.hpp" + +#include "../../collection_adapter_builtins.hpp" + +namespace rerun::blueprint::archetypes {} + +namespace rerun { + + Result> + AsComponents::serialize( + const blueprint::archetypes::ForcePosition& archetype + ) { + using namespace blueprint::archetypes; + std::vector cells; + cells.reserve(4); + + if (archetype.enabled.has_value()) { + auto result = ComponentBatch::from_loggable( + archetype.enabled.value(), + ComponentDescriptor( + "rerun.blueprint.archetypes.ForcePosition", + "enabled", + "rerun.blueprint.components.Enabled" + ) + ); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + if (archetype.strength.has_value()) { + auto result = ComponentBatch::from_loggable( + archetype.strength.value(), + ComponentDescriptor( + "rerun.blueprint.archetypes.ForcePosition", + "strength", + "rerun.blueprint.components.ForceStrength" + ) + ); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + if (archetype.position.has_value()) { + auto result = ComponentBatch::from_loggable( + archetype.position.value(), + ComponentDescriptor( + "rerun.blueprint.archetypes.ForcePosition", + "position", + "rerun.components.Position2D" + ) + ); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + { + auto indicator = ForcePosition::IndicatorComponent(); + auto result = ComponentBatch::from_loggable(indicator); + RR_RETURN_NOT_OK(result.error); + cells.emplace_back(std::move(result.value)); + } + + return cells; + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_position.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_position.hpp new file mode 100644 index 000000000000..36d740ce7393 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_position.hpp @@ -0,0 +1,80 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/force_position.fbs". + +#pragma once + +#include "../../blueprint/components/enabled.hpp" +#include "../../blueprint/components/force_strength.hpp" +#include "../../collection.hpp" +#include "../../compiler_utils.hpp" +#include "../../component_batch.hpp" +#include "../../components/position2d.hpp" +#include "../../indicator_component.hpp" +#include "../../result.hpp" + +#include +#include +#include +#include + +namespace rerun::blueprint::archetypes { + /// **Archetype**: Similar to gravity, this force pulls nodes towards a specific position. + struct ForcePosition { + /// Whether the force is enabled. + std::optional enabled; + + /// The strength of the force. + std::optional strength; + + /// The position where the nodes should be pulled towards. + std::optional position; + + public: + static constexpr const char IndicatorComponentName[] = + "rerun.blueprint.components.ForcePositionIndicator"; + + /// Indicator component, used to identify the archetype when converting to a list of components. + using IndicatorComponent = rerun::components::IndicatorComponent; + + public: + ForcePosition() = default; + ForcePosition(ForcePosition&& other) = default; + + /// Whether the force is enabled. + ForcePosition with_enabled(rerun::blueprint::components::Enabled _enabled) && { + enabled = std::move(_enabled); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + + /// The strength of the force. + ForcePosition with_strength(rerun::blueprint::components::ForceStrength _strength) && { + strength = std::move(_strength); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + + /// The position where the nodes should be pulled towards. + ForcePosition with_position(rerun::components::Position2D _position) && { + position = std::move(_position); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + }; + +} // namespace rerun::blueprint::archetypes + +namespace rerun { + /// \private + template + struct AsComponents; + + /// \private + template <> + struct AsComponents { + /// Serialize all set component batches. + static Result> serialize( + const blueprint::archetypes::ForcePosition& archetype + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components.hpp b/rerun_cpp/src/rerun/blueprint/components.hpp index e5ed33415971..9407110804f8 100644 --- a/rerun_cpp/src/rerun/blueprint/components.hpp +++ b/rerun_cpp/src/rerun/blueprint/components.hpp @@ -11,8 +11,12 @@ #include "blueprint/components/component_column_selector.hpp" #include "blueprint/components/container_kind.hpp" #include "blueprint/components/corner2d.hpp" +#include "blueprint/components/enabled.hpp" #include "blueprint/components/filter_by_range.hpp" #include "blueprint/components/filter_is_not_null.hpp" +#include "blueprint/components/force_distance.hpp" +#include "blueprint/components/force_iterations.hpp" +#include "blueprint/components/force_strength.hpp" #include "blueprint/components/grid_columns.hpp" #include "blueprint/components/grid_spacing.hpp" #include "blueprint/components/included_content.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/components/.gitattributes b/rerun_cpp/src/rerun/blueprint/components/.gitattributes index 01c332e58b9c..222d19806052 100644 --- a/rerun_cpp/src/rerun/blueprint/components/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/components/.gitattributes @@ -13,8 +13,12 @@ container_kind.cpp linguist-generated=true container_kind.hpp linguist-generated=true corner2d.cpp linguist-generated=true corner2d.hpp linguist-generated=true +enabled.hpp linguist-generated=true filter_by_range.hpp linguist-generated=true filter_is_not_null.hpp linguist-generated=true +force_distance.hpp linguist-generated=true +force_iterations.hpp linguist-generated=true +force_strength.hpp linguist-generated=true grid_columns.hpp linguist-generated=true grid_spacing.hpp linguist-generated=true included_content.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/components/enabled.hpp b/rerun_cpp/src/rerun/blueprint/components/enabled.hpp new file mode 100644 index 000000000000..c80c4f640189 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/components/enabled.hpp @@ -0,0 +1,74 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/components/enabled.fbs". + +#pragma once + +#include "../../component_descriptor.hpp" +#include "../../datatypes/bool.hpp" +#include "../../result.hpp" + +#include +#include + +namespace rerun::blueprint::components { + /// **Component**: Whether a procedure is enabled. + struct Enabled { + rerun::datatypes::Bool visible; + + public: + Enabled() = default; + + Enabled(rerun::datatypes::Bool visible_) : visible(visible_) {} + + Enabled& operator=(rerun::datatypes::Bool visible_) { + visible = visible_; + return *this; + } + + Enabled(bool value_) : visible(value_) {} + + Enabled& operator=(bool value_) { + visible = value_; + return *this; + } + + /// Cast to the underlying Bool datatype + operator rerun::datatypes::Bool() const { + return visible; + } + }; +} // namespace rerun::blueprint::components + +namespace rerun { + static_assert(sizeof(rerun::datatypes::Bool) == sizeof(blueprint::components::Enabled)); + + /// \private + template <> + struct Loggable { + static constexpr ComponentDescriptor Descriptor = "rerun.blueprint.components.Enabled"; + + /// 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::Enabled` into an arrow array. + static Result> to_arrow( + const blueprint::components::Enabled* instances, size_t num_instances + ) { + if (num_instances == 0) { + return Loggable::to_arrow(nullptr, 0); + } else if (instances == nullptr) { + return rerun::Error( + ErrorCode::UnexpectedNullArgument, + "Passed array instances is null when num_elements> 0." + ); + } else { + return Loggable::to_arrow( + &instances->visible, + num_instances + ); + } + } + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/force_distance.hpp b/rerun_cpp/src/rerun/blueprint/components/force_distance.hpp new file mode 100644 index 000000000000..05b0b79dbeb1 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/components/force_distance.hpp @@ -0,0 +1,79 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/components/force_distance.fbs". + +#pragma once + +#include "../../component_descriptor.hpp" +#include "../../datatypes/float64.hpp" +#include "../../result.hpp" + +#include +#include + +namespace rerun::blueprint::components { + /// **Component**: The target distance between two nodes. + /// + /// This is helpful to scale the layout, for example if long labels are involved. + struct ForceDistance { + rerun::datatypes::Float64 distance; + + public: + ForceDistance() = default; + + ForceDistance(rerun::datatypes::Float64 distance_) : distance(distance_) {} + + ForceDistance& operator=(rerun::datatypes::Float64 distance_) { + distance = distance_; + return *this; + } + + ForceDistance(double value_) : distance(value_) {} + + ForceDistance& operator=(double value_) { + distance = value_; + return *this; + } + + /// Cast to the underlying Float64 datatype + operator rerun::datatypes::Float64() const { + return distance; + } + }; +} // namespace rerun::blueprint::components + +namespace rerun { + static_assert( + sizeof(rerun::datatypes::Float64) == sizeof(blueprint::components::ForceDistance) + ); + + /// \private + template <> + struct Loggable { + static constexpr ComponentDescriptor Descriptor = + "rerun.blueprint.components.ForceDistance"; + + /// 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::ForceDistance` into an arrow array. + static Result> to_arrow( + const blueprint::components::ForceDistance* instances, size_t num_instances + ) { + if (num_instances == 0) { + return Loggable::to_arrow(nullptr, 0); + } else if (instances == nullptr) { + return rerun::Error( + ErrorCode::UnexpectedNullArgument, + "Passed array instances is null when num_elements> 0." + ); + } else { + return Loggable::to_arrow( + &instances->distance, + num_instances + ); + } + } + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/force_iterations.hpp b/rerun_cpp/src/rerun/blueprint/components/force_iterations.hpp new file mode 100644 index 000000000000..49f1ceef04ea --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/components/force_iterations.hpp @@ -0,0 +1,79 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/components/force_iterations.fbs". + +#pragma once + +#include "../../component_descriptor.hpp" +#include "../../datatypes/uint64.hpp" +#include "../../result.hpp" + +#include +#include + +namespace rerun::blueprint::components { + /// **Component**: Specifies how often this force should be applied per iteration. + /// + /// Increasing this parameter can lead to better results at the cost of longer computation time. + struct ForceIterations { + rerun::datatypes::UInt64 distance; + + public: + ForceIterations() = default; + + ForceIterations(rerun::datatypes::UInt64 distance_) : distance(distance_) {} + + ForceIterations& operator=(rerun::datatypes::UInt64 distance_) { + distance = distance_; + return *this; + } + + ForceIterations(uint64_t value_) : distance(value_) {} + + ForceIterations& operator=(uint64_t value_) { + distance = value_; + return *this; + } + + /// Cast to the underlying UInt64 datatype + operator rerun::datatypes::UInt64() const { + return distance; + } + }; +} // namespace rerun::blueprint::components + +namespace rerun { + static_assert( + sizeof(rerun::datatypes::UInt64) == sizeof(blueprint::components::ForceIterations) + ); + + /// \private + template <> + struct Loggable { + static constexpr ComponentDescriptor Descriptor = + "rerun.blueprint.components.ForceIterations"; + + /// 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::ForceIterations` into an arrow array. + static Result> to_arrow( + const blueprint::components::ForceIterations* instances, size_t num_instances + ) { + if (num_instances == 0) { + return Loggable::to_arrow(nullptr, 0); + } else if (instances == nullptr) { + return rerun::Error( + ErrorCode::UnexpectedNullArgument, + "Passed array instances is null when num_elements> 0." + ); + } else { + return Loggable::to_arrow( + &instances->distance, + num_instances + ); + } + } + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/force_strength.hpp b/rerun_cpp/src/rerun/blueprint/components/force_strength.hpp new file mode 100644 index 000000000000..ebb49b44191b --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/components/force_strength.hpp @@ -0,0 +1,79 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/blueprint/components/force_strength.fbs". + +#pragma once + +#include "../../component_descriptor.hpp" +#include "../../datatypes/float64.hpp" +#include "../../result.hpp" + +#include +#include + +namespace rerun::blueprint::components { + /// **Component**: The strength of a given force. + /// + /// Allows to assign different weights to the individual forces, prioritizing one over the other. + struct ForceStrength { + rerun::datatypes::Float64 distance; + + public: + ForceStrength() = default; + + ForceStrength(rerun::datatypes::Float64 distance_) : distance(distance_) {} + + ForceStrength& operator=(rerun::datatypes::Float64 distance_) { + distance = distance_; + return *this; + } + + ForceStrength(double value_) : distance(value_) {} + + ForceStrength& operator=(double value_) { + distance = value_; + return *this; + } + + /// Cast to the underlying Float64 datatype + operator rerun::datatypes::Float64() const { + return distance; + } + }; +} // namespace rerun::blueprint::components + +namespace rerun { + static_assert( + sizeof(rerun::datatypes::Float64) == sizeof(blueprint::components::ForceStrength) + ); + + /// \private + template <> + struct Loggable { + static constexpr ComponentDescriptor Descriptor = + "rerun.blueprint.components.ForceStrength"; + + /// 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::ForceStrength` into an arrow array. + static Result> to_arrow( + const blueprint::components::ForceStrength* instances, size_t num_instances + ) { + if (num_instances == 0) { + return Loggable::to_arrow(nullptr, 0); + } else if (instances == nullptr) { + return rerun::Error( + ErrorCode::UnexpectedNullArgument, + "Passed array instances is null when num_elements> 0." + ); + } else { + return Loggable::to_arrow( + &instances->distance, + num_instances + ); + } + } + }; +} // namespace rerun diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes index 45d2c2e0e797..03a4f9d20824 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes @@ -5,6 +5,11 @@ __init__.py linguist-generated=true background.py linguist-generated=true container_blueprint.py linguist-generated=true dataframe_query.py linguist-generated=true +force_center.py linguist-generated=true +force_collision_radius.py linguist-generated=true +force_link.py linguist-generated=true +force_many_body.py linguist-generated=true +force_position.py linguist-generated=true line_grid3d.py linguist-generated=true map_background.py linguist-generated=true map_zoom.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py index de30db55093f..58d545a3f97a 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py @@ -5,6 +5,11 @@ from .background import Background from .container_blueprint import ContainerBlueprint from .dataframe_query import DataframeQuery +from .force_center import ForceCenter +from .force_collision_radius import ForceCollisionRadius +from .force_link import ForceLink +from .force_many_body import ForceManyBody +from .force_position import ForcePosition from .line_grid3d import LineGrid3D from .map_background import MapBackground from .map_zoom import MapZoom @@ -24,6 +29,11 @@ "Background", "ContainerBlueprint", "DataframeQuery", + "ForceCenter", + "ForceCollisionRadius", + "ForceLink", + "ForceManyBody", + "ForcePosition", "LineGrid3D", "MapBackground", "MapZoom", diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_center.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_center.py new file mode 100644 index 000000000000..7d026c887d70 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_center.py @@ -0,0 +1,80 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/force_center.fbs". + +# You can extend this class by creating a "ForceCenterExt" class in "force_center_ext.py". + +from __future__ import annotations + +from typing import Any + +from attrs import define, field + +from ... import datatypes +from ..._baseclasses import ( + Archetype, +) +from ...blueprint import components as blueprint_components +from ...error_utils import catch_and_log_exceptions + +__all__ = ["ForceCenter"] + + +@define(str=False, repr=False, init=False) +class ForceCenter(Archetype): + """**Archetype**: Tries to move the center of mass of the graph to the origin.""" + + def __init__( + self: Any, *, enabled: datatypes.BoolLike | None = None, strength: datatypes.Float64Like | None = None + ): + """ + Create a new instance of the ForceCenter archetype. + + Parameters + ---------- + enabled: + Whether the force is enabled. + strength: + The strength of the force. + + """ + + # You can define your own __init__ function as a member of ForceCenterExt in force_center_ext.py + with catch_and_log_exceptions(context=self.__class__.__name__): + self.__attrs_init__(enabled=enabled, strength=strength) + return + self.__attrs_clear__() + + def __attrs_clear__(self) -> None: + """Convenience method for calling `__attrs_init__` with all `None`s.""" + self.__attrs_init__( + enabled=None, # type: ignore[arg-type] + strength=None, # type: ignore[arg-type] + ) + + @classmethod + def _clear(cls) -> ForceCenter: + """Produce an empty ForceCenter, bypassing `__init__`.""" + inst = cls.__new__(cls) + inst.__attrs_clear__() + return inst + + enabled: blueprint_components.EnabledBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=blueprint_components.EnabledBatch._optional, # type: ignore[misc] + ) + # Whether the force is enabled. + # + # (Docstring intentionally commented out to hide this field from the docs) + + strength: blueprint_components.ForceStrengthBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=blueprint_components.ForceStrengthBatch._optional, # type: ignore[misc] + ) + # The strength of the force. + # + # (Docstring intentionally commented out to hide this field from the docs) + + __str__ = Archetype.__str__ + __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_collision_radius.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_collision_radius.py new file mode 100644 index 000000000000..80464759b93f --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_collision_radius.py @@ -0,0 +1,100 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/force_collision_radius.fbs". + +# You can extend this class by creating a "ForceCollisionRadiusExt" class in "force_collision_radius_ext.py". + +from __future__ import annotations + +from typing import Any + +from attrs import define, field + +from ... import datatypes +from ..._baseclasses import ( + Archetype, +) +from ...blueprint import components as blueprint_components +from ...error_utils import catch_and_log_exceptions + +__all__ = ["ForceCollisionRadius"] + + +@define(str=False, repr=False, init=False) +class ForceCollisionRadius(Archetype): + """**Archetype**: Resolves collisions between the bounding spheres, according to the radius of the nodes.""" + + def __init__( + self: Any, + *, + enabled: datatypes.BoolLike | None = None, + strength: datatypes.Float64Like | None = None, + iterations: datatypes.UInt64Like | None = None, + ): + """ + Create a new instance of the ForceCollisionRadius archetype. + + Parameters + ---------- + enabled: + Whether the force is enabled. + strength: + The strength of the force. + iterations: + Specifies how often this force should be applied per iteration. + + Increasing this parameter can lead to better results at the cost of longer computation time. + + """ + + # You can define your own __init__ function as a member of ForceCollisionRadiusExt in force_collision_radius_ext.py + with catch_and_log_exceptions(context=self.__class__.__name__): + self.__attrs_init__(enabled=enabled, strength=strength, iterations=iterations) + return + self.__attrs_clear__() + + def __attrs_clear__(self) -> None: + """Convenience method for calling `__attrs_init__` with all `None`s.""" + self.__attrs_init__( + enabled=None, # type: ignore[arg-type] + strength=None, # type: ignore[arg-type] + iterations=None, # type: ignore[arg-type] + ) + + @classmethod + def _clear(cls) -> ForceCollisionRadius: + """Produce an empty ForceCollisionRadius, bypassing `__init__`.""" + inst = cls.__new__(cls) + inst.__attrs_clear__() + return inst + + enabled: blueprint_components.EnabledBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=blueprint_components.EnabledBatch._optional, # type: ignore[misc] + ) + # Whether the force is enabled. + # + # (Docstring intentionally commented out to hide this field from the docs) + + strength: blueprint_components.ForceStrengthBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=blueprint_components.ForceStrengthBatch._optional, # type: ignore[misc] + ) + # The strength of the force. + # + # (Docstring intentionally commented out to hide this field from the docs) + + iterations: blueprint_components.ForceIterationsBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=blueprint_components.ForceIterationsBatch._optional, # type: ignore[misc] + ) + # Specifies how often this force should be applied per iteration. + # + # Increasing this parameter can lead to better results at the cost of longer computation time. + # + # (Docstring intentionally commented out to hide this field from the docs) + + __str__ = Archetype.__str__ + __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_link.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_link.py new file mode 100644 index 000000000000..bf24c7265d63 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_link.py @@ -0,0 +1,100 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/force_link.fbs". + +# You can extend this class by creating a "ForceLinkExt" class in "force_link_ext.py". + +from __future__ import annotations + +from typing import Any + +from attrs import define, field + +from ... import datatypes +from ..._baseclasses import ( + Archetype, +) +from ...blueprint import components as blueprint_components +from ...error_utils import catch_and_log_exceptions + +__all__ = ["ForceLink"] + + +@define(str=False, repr=False, init=False) +class ForceLink(Archetype): + """**Archetype**: Aims to achieve a target distance between two nodes that are connected by an edge.""" + + def __init__( + self: Any, + *, + enabled: datatypes.BoolLike | None = None, + distance: datatypes.Float64Like | None = None, + iterations: datatypes.UInt64Like | None = None, + ): + """ + Create a new instance of the ForceLink archetype. + + Parameters + ---------- + enabled: + Whether the force is enabled. + distance: + The target distance between two nodes. + iterations: + Specifies how often this force should be applied per iteration. + + Increasing this parameter can lead to better results at the cost of longer computation time. + + """ + + # You can define your own __init__ function as a member of ForceLinkExt in force_link_ext.py + with catch_and_log_exceptions(context=self.__class__.__name__): + self.__attrs_init__(enabled=enabled, distance=distance, iterations=iterations) + return + self.__attrs_clear__() + + def __attrs_clear__(self) -> None: + """Convenience method for calling `__attrs_init__` with all `None`s.""" + self.__attrs_init__( + enabled=None, # type: ignore[arg-type] + distance=None, # type: ignore[arg-type] + iterations=None, # type: ignore[arg-type] + ) + + @classmethod + def _clear(cls) -> ForceLink: + """Produce an empty ForceLink, bypassing `__init__`.""" + inst = cls.__new__(cls) + inst.__attrs_clear__() + return inst + + enabled: blueprint_components.EnabledBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=blueprint_components.EnabledBatch._optional, # type: ignore[misc] + ) + # Whether the force is enabled. + # + # (Docstring intentionally commented out to hide this field from the docs) + + distance: blueprint_components.ForceDistanceBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=blueprint_components.ForceDistanceBatch._optional, # type: ignore[misc] + ) + # The target distance between two nodes. + # + # (Docstring intentionally commented out to hide this field from the docs) + + iterations: blueprint_components.ForceIterationsBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=blueprint_components.ForceIterationsBatch._optional, # type: ignore[misc] + ) + # Specifies how often this force should be applied per iteration. + # + # Increasing this parameter can lead to better results at the cost of longer computation time. + # + # (Docstring intentionally commented out to hide this field from the docs) + + __str__ = Archetype.__str__ + __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_many_body.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_many_body.py new file mode 100644 index 000000000000..4750ac834505 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_many_body.py @@ -0,0 +1,88 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/force_many_body.fbs". + +# You can extend this class by creating a "ForceManyBodyExt" class in "force_many_body_ext.py". + +from __future__ import annotations + +from typing import Any + +from attrs import define, field + +from ... import datatypes +from ..._baseclasses import ( + Archetype, +) +from ...blueprint import components as blueprint_components +from ...error_utils import catch_and_log_exceptions + +__all__ = ["ForceManyBody"] + + +@define(str=False, repr=False, init=False) +class ForceManyBody(Archetype): + """ + **Archetype**: A force between each pair of nodes that ressembles an electrical charge. + + If `strength` is smaller than 0, it pushes nodes apart, if it is larger than 0 it pulls them together. + """ + + def __init__( + self: Any, *, enabled: datatypes.BoolLike | None = None, strength: datatypes.Float64Like | None = None + ): + """ + Create a new instance of the ForceManyBody archetype. + + Parameters + ---------- + enabled: + Whether the force is enabled. + strength: + The strength of the force. + + If `strength` is smaller than 0, it pushes nodes apart, if it is larger than 0 it pulls them together. + + """ + + # You can define your own __init__ function as a member of ForceManyBodyExt in force_many_body_ext.py + with catch_and_log_exceptions(context=self.__class__.__name__): + self.__attrs_init__(enabled=enabled, strength=strength) + return + self.__attrs_clear__() + + def __attrs_clear__(self) -> None: + """Convenience method for calling `__attrs_init__` with all `None`s.""" + self.__attrs_init__( + enabled=None, # type: ignore[arg-type] + strength=None, # type: ignore[arg-type] + ) + + @classmethod + def _clear(cls) -> ForceManyBody: + """Produce an empty ForceManyBody, bypassing `__init__`.""" + inst = cls.__new__(cls) + inst.__attrs_clear__() + return inst + + enabled: blueprint_components.EnabledBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=blueprint_components.EnabledBatch._optional, # type: ignore[misc] + ) + # Whether the force is enabled. + # + # (Docstring intentionally commented out to hide this field from the docs) + + strength: blueprint_components.ForceStrengthBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=blueprint_components.ForceStrengthBatch._optional, # type: ignore[misc] + ) + # The strength of the force. + # + # If `strength` is smaller than 0, it pushes nodes apart, if it is larger than 0 it pulls them together. + # + # (Docstring intentionally commented out to hide this field from the docs) + + __str__ = Archetype.__str__ + __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_position.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_position.py new file mode 100644 index 000000000000..61e63623c9c2 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_position.py @@ -0,0 +1,96 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/blueprint/archetypes/force_position.fbs". + +# You can extend this class by creating a "ForcePositionExt" class in "force_position_ext.py". + +from __future__ import annotations + +from typing import Any + +from attrs import define, field + +from ... import components, datatypes +from ..._baseclasses import ( + Archetype, +) +from ...blueprint import components as blueprint_components +from ...error_utils import catch_and_log_exceptions + +__all__ = ["ForcePosition"] + + +@define(str=False, repr=False, init=False) +class ForcePosition(Archetype): + """**Archetype**: Similar to gravity, this force pulls nodes towards a specific position.""" + + def __init__( + self: Any, + *, + enabled: datatypes.BoolLike | None = None, + strength: datatypes.Float64Like | None = None, + position: datatypes.Vec2DLike | None = None, + ): + """ + Create a new instance of the ForcePosition archetype. + + Parameters + ---------- + enabled: + Whether the force is enabled. + strength: + The strength of the force. + position: + The position where the nodes should be pulled towards. + + """ + + # You can define your own __init__ function as a member of ForcePositionExt in force_position_ext.py + with catch_and_log_exceptions(context=self.__class__.__name__): + self.__attrs_init__(enabled=enabled, strength=strength, position=position) + return + self.__attrs_clear__() + + def __attrs_clear__(self) -> None: + """Convenience method for calling `__attrs_init__` with all `None`s.""" + self.__attrs_init__( + enabled=None, # type: ignore[arg-type] + strength=None, # type: ignore[arg-type] + position=None, # type: ignore[arg-type] + ) + + @classmethod + def _clear(cls) -> ForcePosition: + """Produce an empty ForcePosition, bypassing `__init__`.""" + inst = cls.__new__(cls) + inst.__attrs_clear__() + return inst + + enabled: blueprint_components.EnabledBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=blueprint_components.EnabledBatch._optional, # type: ignore[misc] + ) + # Whether the force is enabled. + # + # (Docstring intentionally commented out to hide this field from the docs) + + strength: blueprint_components.ForceStrengthBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=blueprint_components.ForceStrengthBatch._optional, # type: ignore[misc] + ) + # The strength of the force. + # + # (Docstring intentionally commented out to hide this field from the docs) + + position: components.Position2DBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=components.Position2DBatch._optional, # type: ignore[misc] + ) + # The position where the nodes should be pulled towards. + # + # (Docstring intentionally commented out to hide this field from the docs) + + __str__ = Archetype.__str__ + __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes index 4fdcc51e8c50..6c5eeaa92aa6 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes @@ -11,8 +11,12 @@ column_share.py linguist-generated=true component_column_selector.py linguist-generated=true container_kind.py linguist-generated=true corner2d.py linguist-generated=true +enabled.py linguist-generated=true filter_by_range.py linguist-generated=true filter_is_not_null.py linguist-generated=true +force_distance.py linguist-generated=true +force_iterations.py linguist-generated=true +force_strength.py linguist-generated=true grid_columns.py linguist-generated=true grid_spacing.py linguist-generated=true included_content.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 18d213e617d7..d09f761a625d 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py @@ -11,8 +11,12 @@ from .component_column_selector import ComponentColumnSelector, ComponentColumnSelectorBatch from .container_kind import ContainerKind, ContainerKindArrayLike, ContainerKindBatch, ContainerKindLike from .corner2d import Corner2D, Corner2DArrayLike, Corner2DBatch, Corner2DLike +from .enabled import Enabled, EnabledBatch from .filter_by_range import FilterByRange, FilterByRangeBatch from .filter_is_not_null import FilterIsNotNull, FilterIsNotNullBatch +from .force_distance import ForceDistance, ForceDistanceBatch +from .force_iterations import ForceIterations, ForceIterationsBatch +from .force_strength import ForceStrength, ForceStrengthBatch from .grid_columns import GridColumns, GridColumnsBatch from .grid_spacing import GridSpacing, GridSpacingBatch from .included_content import IncludedContent, IncludedContentBatch @@ -63,10 +67,18 @@ "Corner2DArrayLike", "Corner2DBatch", "Corner2DLike", + "Enabled", + "EnabledBatch", "FilterByRange", "FilterByRangeBatch", "FilterIsNotNull", "FilterIsNotNullBatch", + "ForceDistance", + "ForceDistanceBatch", + "ForceIterations", + "ForceIterationsBatch", + "ForceStrength", + "ForceStrengthBatch", "GridColumns", "GridColumnsBatch", "GridSpacing", diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/enabled.py b/rerun_py/rerun_sdk/rerun/blueprint/components/enabled.py new file mode 100644 index 000000000000..6487469df9bb --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/enabled.py @@ -0,0 +1,33 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/blueprint/components/enabled.fbs". + +# You can extend this class by creating a "EnabledExt" class in "enabled_ext.py". + +from __future__ import annotations + +from ... import datatypes +from ..._baseclasses import ( + ComponentBatchMixin, + ComponentDescriptor, + ComponentMixin, +) + +__all__ = ["Enabled", "EnabledBatch"] + + +class Enabled(datatypes.Bool, ComponentMixin): + """**Component**: Whether a procedure is enabled.""" + + _BATCH_TYPE = None + # You can define your own __init__ function as a member of EnabledExt in enabled_ext.py + + # Note: there are no fields here because Enabled delegates to datatypes.Bool + pass + + +class EnabledBatch(datatypes.BoolBatch, ComponentBatchMixin): + _COMPONENT_DESCRIPTOR: ComponentDescriptor = ComponentDescriptor("rerun.blueprint.components.Enabled") + + +# This is patched in late to avoid circular dependencies. +Enabled._BATCH_TYPE = EnabledBatch # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/force_distance.py b/rerun_py/rerun_sdk/rerun/blueprint/components/force_distance.py new file mode 100644 index 000000000000..b0bb1069b160 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/force_distance.py @@ -0,0 +1,37 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/blueprint/components/force_distance.fbs". + +# You can extend this class by creating a "ForceDistanceExt" class in "force_distance_ext.py". + +from __future__ import annotations + +from ... import datatypes +from ..._baseclasses import ( + ComponentBatchMixin, + ComponentDescriptor, + ComponentMixin, +) + +__all__ = ["ForceDistance", "ForceDistanceBatch"] + + +class ForceDistance(datatypes.Float64, ComponentMixin): + """ + **Component**: The target distance between two nodes. + + This is helpful to scale the layout, for example if long labels are involved. + """ + + _BATCH_TYPE = None + # You can define your own __init__ function as a member of ForceDistanceExt in force_distance_ext.py + + # Note: there are no fields here because ForceDistance delegates to datatypes.Float64 + pass + + +class ForceDistanceBatch(datatypes.Float64Batch, ComponentBatchMixin): + _COMPONENT_DESCRIPTOR: ComponentDescriptor = ComponentDescriptor("rerun.blueprint.components.ForceDistance") + + +# This is patched in late to avoid circular dependencies. +ForceDistance._BATCH_TYPE = ForceDistanceBatch # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/force_iterations.py b/rerun_py/rerun_sdk/rerun/blueprint/components/force_iterations.py new file mode 100644 index 000000000000..f9bf7f7a0e24 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/force_iterations.py @@ -0,0 +1,37 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/blueprint/components/force_iterations.fbs". + +# You can extend this class by creating a "ForceIterationsExt" class in "force_iterations_ext.py". + +from __future__ import annotations + +from ... import datatypes +from ..._baseclasses import ( + ComponentBatchMixin, + ComponentDescriptor, + ComponentMixin, +) + +__all__ = ["ForceIterations", "ForceIterationsBatch"] + + +class ForceIterations(datatypes.UInt64, ComponentMixin): + """ + **Component**: Specifies how often this force should be applied per iteration. + + Increasing this parameter can lead to better results at the cost of longer computation time. + """ + + _BATCH_TYPE = None + # You can define your own __init__ function as a member of ForceIterationsExt in force_iterations_ext.py + + # Note: there are no fields here because ForceIterations delegates to datatypes.UInt64 + pass + + +class ForceIterationsBatch(datatypes.UInt64Batch, ComponentBatchMixin): + _COMPONENT_DESCRIPTOR: ComponentDescriptor = ComponentDescriptor("rerun.blueprint.components.ForceIterations") + + +# This is patched in late to avoid circular dependencies. +ForceIterations._BATCH_TYPE = ForceIterationsBatch # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/force_strength.py b/rerun_py/rerun_sdk/rerun/blueprint/components/force_strength.py new file mode 100644 index 000000000000..8a475f2d7bb4 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/force_strength.py @@ -0,0 +1,37 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/blueprint/components/force_strength.fbs". + +# You can extend this class by creating a "ForceStrengthExt" class in "force_strength_ext.py". + +from __future__ import annotations + +from ... import datatypes +from ..._baseclasses import ( + ComponentBatchMixin, + ComponentDescriptor, + ComponentMixin, +) + +__all__ = ["ForceStrength", "ForceStrengthBatch"] + + +class ForceStrength(datatypes.Float64, ComponentMixin): + """ + **Component**: The strength of a given force. + + Allows to assign different weights to the individual forces, prioritizing one over the other. + """ + + _BATCH_TYPE = None + # You can define your own __init__ function as a member of ForceStrengthExt in force_strength_ext.py + + # Note: there are no fields here because ForceStrength delegates to datatypes.Float64 + pass + + +class ForceStrengthBatch(datatypes.Float64Batch, ComponentBatchMixin): + _COMPONENT_DESCRIPTOR: ComponentDescriptor = ComponentDescriptor("rerun.blueprint.components.ForceStrength") + + +# This is patched in late to avoid circular dependencies. +ForceStrength._BATCH_TYPE = ForceStrengthBatch # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/graph_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/graph_view.py index 4c43bc8e055d..753f74e416d1 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/graph_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/graph_view.py @@ -70,6 +70,11 @@ def __init__( defaults: list[Union[AsComponents, ComponentBatchLike]] = [], overrides: dict[EntityPathLike, list[ComponentBatchLike]] = {}, visual_bounds: blueprint_archetypes.VisualBounds2D | None = None, + force_link: blueprint_archetypes.ForceLink | None = None, + force_many_body: blueprint_archetypes.ForceManyBody | None = None, + force_position: blueprint_archetypes.ForcePosition | None = None, + force_collision_radius: blueprint_archetypes.ForceCollisionRadius | None = None, + force_center: blueprint_archetypes.ForceCenter | None = None, ) -> None: """ Construct a blueprint for a new GraphView view. @@ -104,6 +109,16 @@ def __init__( Everything within these bounds is guaranteed to be visible. Somethings outside of these bounds may also be visible due to letterboxing. + force_link: + Allows to control the interaction between two nodes connected by an edge. + force_many_body: + A force between each pair of nodes that ressembles an electrical charge. + force_position: + Similar to gravity, this force pulls nodes towards a specific position. + force_collision_radius: + Resolves collisions between the bounding spheres, according to the radius of the nodes. + force_center: + Tries to move the center of mass of the graph to the origin. """ @@ -113,6 +128,31 @@ def __init__( visual_bounds = blueprint_archetypes.VisualBounds2D(visual_bounds) properties["VisualBounds2D"] = visual_bounds + if force_link is not None: + if not isinstance(force_link, blueprint_archetypes.ForceLink): + force_link = blueprint_archetypes.ForceLink(force_link) + properties["ForceLink"] = force_link + + if force_many_body is not None: + if not isinstance(force_many_body, blueprint_archetypes.ForceManyBody): + force_many_body = blueprint_archetypes.ForceManyBody(force_many_body) + properties["ForceManyBody"] = force_many_body + + if force_position is not None: + if not isinstance(force_position, blueprint_archetypes.ForcePosition): + force_position = blueprint_archetypes.ForcePosition(force_position) + properties["ForcePosition"] = force_position + + if force_collision_radius is not None: + if not isinstance(force_collision_radius, blueprint_archetypes.ForceCollisionRadius): + force_collision_radius = blueprint_archetypes.ForceCollisionRadius(force_collision_radius) + properties["ForceCollisionRadius"] = force_collision_radius + + if force_center is not None: + if not isinstance(force_center, blueprint_archetypes.ForceCenter): + force_center = blueprint_archetypes.ForceCenter(force_center) + properties["ForceCenter"] = force_center + super().__init__( class_identifier="Graph", origin=origin, diff --git a/tests/python/release_checklist/check_graph_time_layout.py b/tests/python/release_checklist/check_graph_time_layout.py index 3d469e1b72c5..e10bde1053a5 100644 --- a/tests/python/release_checklist/check_graph_time_layout.py +++ b/tests/python/release_checklist/check_graph_time_layout.py @@ -1,5 +1,6 @@ from __future__ import annotations +# TODO(grtlr): Promote to example import os import random from argparse import Namespace @@ -8,6 +9,13 @@ import rerun as rr import rerun.blueprint as rrb +# TODO(grtlr): Clean up the exports +from rerun.blueprint.archetypes.force_collision_radius import ForceCollisionRadius +from rerun.blueprint.archetypes.force_link import ForceLink +from rerun.blueprint.archetypes.force_many_body import ForceManyBody +from rerun.components.color import Color +from rerun.components.show_labels import ShowLabels + README = """\ # Time-varying graph view @@ -18,6 +26,18 @@ * Scrub the timeline to see how the graph layout changes over time. """ +color_scheme = [ + Color([228, 26, 28]), # Red + Color([55, 126, 184]), # Blue + Color([77, 175, 74]), # Green + Color([152, 78, 163]), # Purple + Color([255, 127, 0]), # Orange + Color([255, 255, 51]), # Yellow + Color([166, 86, 40]), # Brown + Color([247, 129, 191]), # Pink + Color([153, 153, 153]), # Gray +] + def log_readme() -> None: rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) @@ -25,22 +45,50 @@ def log_readme() -> None: def log_graphs() -> None: nodes = ["root"] + radii = [42] + colors = [Color([81, 81, 81])] edges = [] + # We want reproducible results + random.seed(42) + # Randomly add nodes and edges to the graph for i in range(50): existing = random.choice(nodes) new_node = str(i) nodes.append(new_node) + radii.append(random.randint(10, 50)) + colors.append(random.choice(color_scheme)) edges.append((existing, new_node)) rr.set_time_sequence("frame", i) - rr.log("graph", rr.GraphNodes(nodes, labels=nodes), rr.GraphEdges(edges, graph_type=rr.GraphType.Directed)) + rr.log( + "node_link", + rr.GraphNodes(nodes, labels=nodes, radii=radii, colors=colors), + rr.GraphEdges(edges, graph_type=rr.GraphType.Directed), + ) + rr.log( + "bubble_chart", + rr.GraphNodes(nodes, labels=nodes, radii=radii, colors=colors), + ) rr.send_blueprint( rrb.Blueprint( rrb.Grid( - rrb.GraphView(origin="graph", name="Graph"), + rrb.GraphView( + origin="node_link", + name="Node-link diagram", + force_link=ForceLink(distance=60), + force_many_body=ForceManyBody(strength=-60), + ), + rrb.GraphView( + origin="bubble_chart", + name="Bubble chart", + force_link=ForceLink(enabled=False), + force_many_body=ForceManyBody(enabled=False), + force_collision_radius=ForceCollisionRadius(enabled=True), + defaults=[ShowLabels(False)], + ), rrb.TextDocumentView(origin="readme", name="Instructions"), ) )