use std::collections::HashMap;
use uuid::Uuid;
use re_log_types::EntityPath;
use re_sdk_types::blueprint::archetypes::{
ActiveVisualizers, MapBackground, ViewBlueprint, ViewContents, VisualizerInstruction,
};
use re_sdk_types::blueprint::components::{QueryExpression, ViewClass};
use re_sdk_types::components::{Name, Visible};
use re_sdk_types::datatypes::Bool;
use re_sdk_types::{AsComponents, SerializedComponentBatch, Visualizer};
#[derive(Debug)]
pub struct View {
pub(crate) id: Uuid,
pub(crate) class_identifier: String,
pub(crate) name: Option<String>,
pub(crate) origin: EntityPath,
pub(crate) contents: Vec<String>,
pub(crate) visible: Option<bool>,
pub(crate) properties: HashMap<String, Vec<SerializedComponentBatch>>,
pub(crate) defaults: Vec<Vec<SerializedComponentBatch>>,
pub(crate) overrides: HashMap<EntityPath, Vec<Visualizer>>,
}
impl Default for View {
fn default() -> Self {
Self {
id: Uuid::new_v4(),
class_identifier: String::new(),
name: None,
origin: "/".into(),
contents: vec!["$origin/**".into()],
visible: None,
properties: HashMap::new(),
defaults: Vec::new(),
overrides: HashMap::new(),
}
}
}
impl View {
pub fn blueprint_path(&self) -> EntityPath {
format!("view/{}", self.id).into()
}
pub(crate) fn add_property(&mut self, name: &str, archetype: &dyn AsComponents) {
self.properties
.insert(name.to_owned(), archetype.as_serialized_batches());
}
pub(crate) fn add_defaults(&mut self, archetype: &dyn AsComponents) {
self.defaults.push(archetype.as_serialized_batches());
}
pub(crate) fn add_overrides(
&mut self,
entity_path: impl Into<EntityPath>,
visualizers: impl IntoIterator<Item = impl Into<Visualizer>>,
) {
self.overrides
.entry(entity_path.into())
.or_default()
.extend(visualizers.into_iter().map(Into::into));
}
pub(crate) fn log_to_stream(
&self,
stream: &crate::RecordingStream,
) -> crate::RecordingStreamResult<()> {
let view_contents = ViewContents::new(
self.contents
.iter()
.map(|q| QueryExpression(q.clone().into())),
);
stream.log(
format!("{}/ViewContents", self.blueprint_path()),
&view_contents,
)?;
let mut arch = ViewBlueprint::new(ViewClass(self.class_identifier.clone().into()));
if let Some(ref name) = self.name {
arch = arch.with_display_name(Name(name.clone().into()));
}
arch = arch.with_space_origin(self.origin.to_string());
if let Some(visible) = self.visible {
arch = arch.with_visible(Visible(Bool(visible)));
}
stream.log(self.blueprint_path(), &arch)?;
for (prop_name, prop_batches) in &self.properties {
stream.log_serialized_batches(
format!("{}/{}", self.blueprint_path(), prop_name),
false,
prop_batches.iter().cloned(),
)?;
}
for default_batches in &self.defaults {
stream.log_serialized_batches(
format!("{}/defaults", self.blueprint_path()),
false,
default_batches.iter().cloned(),
)?;
}
for (entity_path, visualizers) in &self.overrides {
let base_visualizer_path =
ViewContents::blueprint_base_visualizer_path_for_entity(self.id, entity_path);
let mut visualizer_ids = Vec::new();
for visualizer in visualizers {
let visualizer_path = base_visualizer_path
.join(&EntityPath::from_single_string(visualizer.id.0.to_string()));
let mut instruction =
VisualizerInstruction::new(visualizer.visualizer_type.clone());
if !visualizer.mappings.is_empty() {
instruction = instruction.with_component_map(visualizer.mappings.clone());
}
stream.log(visualizer_path.clone(), &instruction)?;
if !visualizer.overrides.is_empty() {
stream.log_serialized_batches(
visualizer_path,
false,
visualizer.overrides.iter().cloned(),
)?;
}
visualizer_ids.push(visualizer.id);
}
if !visualizer_ids.is_empty() {
stream.log(
base_visualizer_path,
&ActiveVisualizers::new(visualizer_ids),
)?;
}
}
Ok(())
}
}
pub struct TimeSeriesView(pub(crate) View);
impl TimeSeriesView {
pub fn new(name: impl Into<String>) -> Self {
Self(View {
class_identifier: "TimeSeries".into(),
name: Some(name.into()),
..Default::default()
})
}
pub fn with_origin(mut self, origin: impl Into<EntityPath>) -> Self {
self.0.origin = origin.into();
self
}
pub fn with_contents(mut self, queries: impl IntoIterator<Item = impl Into<String>>) -> Self {
self.0.contents = queries.into_iter().map(Into::into).collect();
self
}
pub fn with_visible(mut self, visible: bool) -> Self {
self.0.visible = Some(visible);
self
}
pub fn with_defaults(mut self, archetype: &dyn AsComponents) -> Self {
self.0.add_defaults(archetype);
self
}
pub fn with_override(
self,
entity_path: impl Into<EntityPath>,
visualizers: impl Into<Visualizer>,
) -> Self {
self.with_overrides(entity_path, [visualizers])
}
pub fn with_overrides(
mut self,
entity_path: impl Into<EntityPath>,
visualizers: impl IntoIterator<Item = impl Into<Visualizer>>,
) -> Self {
self.0.add_overrides(entity_path, visualizers);
self
}
}
pub struct Spatial2DView(pub(crate) View);
impl Spatial2DView {
pub fn new(name: impl Into<String>) -> Self {
Self(View {
class_identifier: "2D".into(),
name: Some(name.into()),
..Default::default()
})
}
pub fn with_origin(mut self, origin: impl Into<EntityPath>) -> Self {
self.0.origin = origin.into();
self
}
pub fn with_contents(mut self, queries: impl IntoIterator<Item = impl Into<String>>) -> Self {
self.0.contents = queries.into_iter().map(Into::into).collect();
self
}
pub fn with_visible(mut self, visible: bool) -> Self {
self.0.visible = Some(visible);
self
}
pub fn with_defaults(mut self, archetype: &dyn AsComponents) -> Self {
self.0.add_defaults(archetype);
self
}
pub fn with_override(
self,
entity_path: impl Into<EntityPath>,
visualizers: impl Into<Visualizer>,
) -> Self {
self.with_overrides(entity_path, [visualizers])
}
pub fn with_overrides(
mut self,
entity_path: impl Into<EntityPath>,
visualizers: impl IntoIterator<Item = impl Into<Visualizer>>,
) -> Self {
self.0.add_overrides(entity_path, visualizers);
self
}
}
pub struct Spatial3DView(pub(crate) View);
impl Spatial3DView {
pub fn new(name: impl Into<String>) -> Self {
Self(View {
class_identifier: "3D".into(),
name: Some(name.into()),
..Default::default()
})
}
pub fn with_origin(mut self, origin: impl Into<EntityPath>) -> Self {
self.0.origin = origin.into();
self
}
pub fn with_contents(mut self, queries: impl IntoIterator<Item = impl Into<String>>) -> Self {
self.0.contents = queries.into_iter().map(Into::into).collect();
self
}
pub fn with_visible(mut self, visible: bool) -> Self {
self.0.visible = Some(visible);
self
}
pub fn with_defaults(mut self, archetype: &dyn AsComponents) -> Self {
self.0.add_defaults(archetype);
self
}
pub fn with_override(
self,
entity_path: impl Into<EntityPath>,
visualizers: impl Into<Visualizer>,
) -> Self {
self.with_overrides(entity_path, [visualizers])
}
pub fn with_overrides(
mut self,
entity_path: impl Into<EntityPath>,
visualizers: impl IntoIterator<Item = impl Into<Visualizer>>,
) -> Self {
self.0.add_overrides(entity_path, visualizers);
self
}
}
pub struct MapView(pub(crate) View);
impl MapView {
pub fn new(name: impl Into<String>) -> Self {
Self(View {
class_identifier: "Map".into(),
name: Some(name.into()),
..Default::default()
})
}
pub fn with_origin(mut self, origin: impl Into<EntityPath>) -> Self {
self.0.origin = origin.into();
self
}
pub fn with_contents(mut self, queries: impl IntoIterator<Item = impl Into<String>>) -> Self {
self.0.contents = queries.into_iter().map(Into::into).collect();
self
}
pub fn with_visible(mut self, visible: bool) -> Self {
self.0.visible = Some(visible);
self
}
pub fn with_defaults(mut self, archetype: &dyn AsComponents) -> Self {
self.0.add_defaults(archetype);
self
}
pub fn with_override(
self,
entity_path: impl Into<EntityPath>,
visualizers: impl Into<Visualizer>,
) -> Self {
self.with_overrides(entity_path, [visualizers])
}
pub fn with_overrides(
mut self,
entity_path: impl Into<EntityPath>,
visualizers: impl IntoIterator<Item = impl Into<Visualizer>>,
) -> Self {
self.0.add_overrides(entity_path, visualizers);
self
}
pub fn with_map_provider(
mut self,
provider: re_sdk_types::blueprint::components::MapProvider,
) -> Self {
self.0
.add_property("MapBackground", &MapBackground::new(provider));
self
}
}
pub struct TextDocumentView(pub(crate) View);
impl TextDocumentView {
pub fn new(name: impl Into<String>) -> Self {
Self(View {
class_identifier: "TextDocument".into(),
name: Some(name.into()),
..Default::default()
})
}
pub fn with_origin(mut self, origin: impl Into<EntityPath>) -> Self {
self.0.origin = origin.into();
self
}
pub fn with_contents(mut self, queries: impl IntoIterator<Item = impl Into<String>>) -> Self {
self.0.contents = queries.into_iter().map(Into::into).collect();
self
}
pub fn with_visible(mut self, visible: bool) -> Self {
self.0.visible = Some(visible);
self
}
pub fn with_defaults(mut self, archetype: &dyn AsComponents) -> Self {
self.0.add_defaults(archetype);
self
}
pub fn with_override(
self,
entity_path: impl Into<EntityPath>,
visualizers: impl Into<Visualizer>,
) -> Self {
self.with_overrides(entity_path, [visualizers])
}
pub fn with_overrides(
mut self,
entity_path: impl Into<EntityPath>,
visualizers: impl IntoIterator<Item = impl Into<Visualizer>>,
) -> Self {
self.0.add_overrides(entity_path, visualizers);
self
}
}