use re_arrow_store::LatestAtQuery;
use re_log_types::{DeserializableComponent, EntityPath};
use crate::log_db::EntityDb;
#[cfg(feature = "serde")]
use crate::EditableAutoValue;
#[cfg(feature = "serde")]
#[derive(Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct EntityPropertyMap {
props: nohash_hasher::IntMap<EntityPath, EntityProperties>,
}
#[cfg(feature = "serde")]
impl EntityPropertyMap {
pub fn get(&self, entity_path: &EntityPath) -> EntityProperties {
self.props.get(entity_path).cloned().unwrap_or_default()
}
pub fn set(&mut self, entity_path: EntityPath, prop: EntityProperties) {
if prop == EntityProperties::default() {
self.props.remove(&entity_path); } else {
self.props.insert(entity_path, prop);
}
}
}
#[cfg(feature = "serde")]
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct EntityProperties {
pub visible: bool,
pub visible_history: ExtraQueryHistory,
pub interactive: bool,
pub color_mapper: EditableAutoValue<ColorMapper>,
pub pinhole_image_plane_distance: EditableAutoValue<f32>,
pub backproject_depth: EditableAutoValue<bool>,
pub depth_from_world_scale: EditableAutoValue<f32>,
pub backproject_radius_scale: EditableAutoValue<f32>,
}
#[cfg(feature = "serde")]
impl Default for EntityProperties {
fn default() -> Self {
Self {
visible: true,
visible_history: ExtraQueryHistory::default(),
interactive: true,
color_mapper: EditableAutoValue::default(),
pinhole_image_plane_distance: EditableAutoValue::default(),
backproject_depth: EditableAutoValue::Auto(true),
depth_from_world_scale: EditableAutoValue::default(),
backproject_radius_scale: EditableAutoValue::Auto(1.0),
}
}
}
#[cfg(feature = "serde")]
impl EntityProperties {
pub fn with_child(&self, child: &Self) -> Self {
Self {
visible: self.visible && child.visible,
visible_history: self.visible_history.with_child(&child.visible_history),
interactive: self.interactive && child.interactive,
color_mapper: self.color_mapper.or(&child.color_mapper).clone(),
pinhole_image_plane_distance: self
.pinhole_image_plane_distance
.or(&child.pinhole_image_plane_distance)
.clone(),
backproject_depth: self.backproject_depth.or(&child.backproject_depth).clone(),
depth_from_world_scale: self
.depth_from_world_scale
.or(&child.depth_from_world_scale)
.clone(),
backproject_radius_scale: self
.backproject_radius_scale
.or(&child.backproject_radius_scale)
.clone(),
}
}
}
#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct ExtraQueryHistory {
pub nanos: i64,
pub sequences: i64,
}
impl ExtraQueryHistory {
#[allow(dead_code)]
fn with_child(&self, child: &Self) -> Self {
Self {
nanos: self.nanos.max(child.nanos),
sequences: self.sequences.max(child.sequences),
}
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum Colormap {
Grayscale,
Inferno,
Magma,
Plasma,
#[default]
Turbo,
Viridis,
}
impl std::fmt::Display for Colormap {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
Colormap::Grayscale => "Grayscale",
Colormap::Inferno => "Inferno",
Colormap::Magma => "Magma",
Colormap::Plasma => "Plasma",
Colormap::Turbo => "Turbo",
Colormap::Viridis => "Viridis",
})
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum ColorMapper {
Colormap(Colormap),
}
impl std::fmt::Display for ColorMapper {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ColorMapper::Colormap(colormap) => colormap.fmt(f),
}
}
}
impl Default for ColorMapper {
#[inline]
fn default() -> Self {
Self::Colormap(Colormap::default())
}
}
pub fn query_latest_single<C: DeserializableComponent>(
entity_db: &EntityDb,
entity_path: &EntityPath,
query: &LatestAtQuery,
) -> Option<C>
where
for<'b> &'b C::ArrayType: IntoIterator,
{
crate::profile_function!();
let data_store = &entity_db.data_store;
let (_, cells) = data_store.latest_at(query, entity_path, C::name(), &[C::name()])?;
let cell = cells.get(0)?.as_ref()?;
let mut iter = cell.try_to_native::<C>().ok()?;
let component = iter.next();
if iter.next().is_some() {
re_log::warn_once!("Unexpected batch for {} at: {}", C::name(), entity_path);
}
component
}