diff --git a/crates/store/re_types/definitions/rerun/archetypes/image.fbs b/crates/store/re_types/definitions/rerun/archetypes/image.fbs
index bd73ee273b01..4ce305f96ab4 100644
--- a/crates/store/re_types/definitions/rerun/archetypes/image.fbs
+++ b/crates/store/re_types/definitions/rerun/archetypes/image.fbs
@@ -24,7 +24,7 @@ namespace rerun.archetypes;
/// \example archetypes/image_formats title="Logging images with various formats" image="https://static.rerun.io/image_formats/7b8a162fcfd266f303980439beea997dc8544c24/full.png"
/// \example archetypes/image_send_columns !api title="Image from file, PIL & OpenCV" image="https://static.rerun.io/image_advanced/81fc8a255488615510790ee41be314e054978d51/full.png"
table Image (
- // TODO(#7245): "attr.rust.archetype_eager",
+ "attr.rust.archetype_eager",
"attr.rust.derive": "PartialEq",
"attr.cpp.no_field_ctors",
"attr.docs.category": "Image & tensor",
diff --git a/crates/store/re_types/definitions/rerun/archetypes/mesh3d.fbs b/crates/store/re_types/definitions/rerun/archetypes/mesh3d.fbs
index a3472cefb4b9..9451497bb49e 100644
--- a/crates/store/re_types/definitions/rerun/archetypes/mesh3d.fbs
+++ b/crates/store/re_types/definitions/rerun/archetypes/mesh3d.fbs
@@ -13,7 +13,7 @@ namespace rerun.archetypes;
/// \example archetypes/mesh3d_partial_updates !api title="3D mesh with partial updates" image="https://static.rerun.io/mesh3d_partial_updates/7de33d26220585691a403098c953cd46f94c3262/1200w.png"
/// \example archetypes/mesh3d_instancing title="3D mesh with instancing" image="https://static.rerun.io/mesh3d_leaf_transforms3d/c2d0ee033129da53168f5705625a9b033f3a3d61/1200w.png"
table Mesh3D (
- // TODO(#7245): "attr.rust.archetype_eager",
+ "attr.rust.archetype_eager",
"attr.rust.derive": "PartialEq",
"attr.docs.category": "Spatial 3D",
"attr.docs.view_types": "Spatial3DView, Spatial2DView: if logged above active projection"
diff --git a/crates/store/re_types/src/archetypes/image.rs b/crates/store/re_types/src/archetypes/image.rs
index e01ce1dc934a..d79223345513 100644
--- a/crates/store/re_types/src/archetypes/image.rs
+++ b/crates/store/re_types/src/archetypes/image.rs
@@ -126,23 +126,23 @@ use ::re_types_core::{DeserializationError, DeserializationResult};
///
///
///
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, Default)]
pub struct Image {
/// The raw image data.
- pub buffer: crate::components::ImageBuffer,
+ pub buffer: Option,
/// The format of the image.
- pub format: crate::components::ImageFormat,
+ pub format: Option,
/// Opacity of the image, useful for layering several images.
///
/// Defaults to 1.0 (fully opaque).
- pub opacity: Option,
+ pub opacity: Option,
/// An optional floating point value that specifies the 2D drawing order.
///
/// Objects with higher values are drawn on top of those with lower values.
- pub draw_order: Option,
+ pub draw_order: Option,
}
impl Image {
@@ -271,50 +271,20 @@ impl ::re_types_core::Archetype for Image {
re_tracing::profile_function!();
use ::re_types_core::{Loggable as _, ResultExt as _};
let arrays_by_descr: ::nohash_hasher::IntMap<_, _> = arrow_data.into_iter().collect();
- let buffer = {
- let array = arrays_by_descr
- .get(&Self::descriptor_buffer())
- .ok_or_else(DeserializationError::missing_data)
- .with_context("rerun.archetypes.Image#buffer")?;
- ::from_arrow_opt(&**array)
- .with_context("rerun.archetypes.Image#buffer")?
- .into_iter()
- .next()
- .flatten()
- .ok_or_else(DeserializationError::missing_data)
- .with_context("rerun.archetypes.Image#buffer")?
- };
- let format = {
- let array = arrays_by_descr
- .get(&Self::descriptor_format())
- .ok_or_else(DeserializationError::missing_data)
- .with_context("rerun.archetypes.Image#format")?;
- ::from_arrow_opt(&**array)
- .with_context("rerun.archetypes.Image#format")?
- .into_iter()
- .next()
- .flatten()
- .ok_or_else(DeserializationError::missing_data)
- .with_context("rerun.archetypes.Image#format")?
- };
- let opacity = if let Some(array) = arrays_by_descr.get(&Self::descriptor_opacity()) {
- ::from_arrow_opt(&**array)
- .with_context("rerun.archetypes.Image#opacity")?
- .into_iter()
- .next()
- .flatten()
- } else {
- None
- };
- let draw_order = if let Some(array) = arrays_by_descr.get(&Self::descriptor_draw_order()) {
- ::from_arrow_opt(&**array)
- .with_context("rerun.archetypes.Image#draw_order")?
- .into_iter()
- .next()
- .flatten()
- } else {
- None
- };
+ let buffer = arrays_by_descr
+ .get(&Self::descriptor_buffer())
+ .map(|array| SerializedComponentBatch::new(array.clone(), Self::descriptor_buffer()));
+ let format = arrays_by_descr
+ .get(&Self::descriptor_format())
+ .map(|array| SerializedComponentBatch::new(array.clone(), Self::descriptor_format()));
+ let opacity = arrays_by_descr
+ .get(&Self::descriptor_opacity())
+ .map(|array| SerializedComponentBatch::new(array.clone(), Self::descriptor_opacity()));
+ let draw_order = arrays_by_descr
+ .get(&Self::descriptor_draw_order())
+ .map(|array| {
+ SerializedComponentBatch::new(array.clone(), Self::descriptor_draw_order())
+ });
Ok(Self {
buffer,
format,
@@ -325,39 +295,15 @@ impl ::re_types_core::Archetype for Image {
}
impl ::re_types_core::AsComponents for Image {
- fn as_component_batches(&self) -> Vec> {
- re_tracing::profile_function!();
+ #[inline]
+ fn as_serialized_batches(&self) -> Vec {
use ::re_types_core::Archetype as _;
[
- Some(Self::indicator()),
- (Some(&self.buffer as &dyn ComponentBatch)).map(|batch| {
- ::re_types_core::ComponentBatchCowWithDescriptor {
- batch: batch.into(),
- descriptor_override: Some(Self::descriptor_buffer()),
- }
- }),
- (Some(&self.format as &dyn ComponentBatch)).map(|batch| {
- ::re_types_core::ComponentBatchCowWithDescriptor {
- batch: batch.into(),
- descriptor_override: Some(Self::descriptor_format()),
- }
- }),
- (self
- .opacity
- .as_ref()
- .map(|comp| (comp as &dyn ComponentBatch)))
- .map(|batch| ::re_types_core::ComponentBatchCowWithDescriptor {
- batch: batch.into(),
- descriptor_override: Some(Self::descriptor_opacity()),
- }),
- (self
- .draw_order
- .as_ref()
- .map(|comp| (comp as &dyn ComponentBatch)))
- .map(|batch| ::re_types_core::ComponentBatchCowWithDescriptor {
- batch: batch.into(),
- descriptor_override: Some(Self::descriptor_draw_order()),
- }),
+ Self::indicator().serialized(),
+ self.buffer.clone(),
+ self.format.clone(),
+ self.opacity.clone(),
+ self.draw_order.clone(),
]
.into_iter()
.flatten()
@@ -375,19 +321,160 @@ impl Image {
format: impl Into,
) -> Self {
Self {
- buffer: buffer.into(),
- format: format.into(),
+ buffer: try_serialize_field(Self::descriptor_buffer(), [buffer]),
+ format: try_serialize_field(Self::descriptor_format(), [format]),
opacity: None,
draw_order: None,
}
}
+ /// Update only some specific fields of a `Image`.
+ #[inline]
+ pub fn update_fields() -> Self {
+ Self::default()
+ }
+
+ /// Clear all the fields of a `Image`.
+ #[inline]
+ pub fn clear_fields() -> Self {
+ use ::re_types_core::Loggable as _;
+ Self {
+ buffer: Some(SerializedComponentBatch::new(
+ crate::components::ImageBuffer::arrow_empty(),
+ Self::descriptor_buffer(),
+ )),
+ format: Some(SerializedComponentBatch::new(
+ crate::components::ImageFormat::arrow_empty(),
+ Self::descriptor_format(),
+ )),
+ opacity: Some(SerializedComponentBatch::new(
+ crate::components::Opacity::arrow_empty(),
+ Self::descriptor_opacity(),
+ )),
+ draw_order: Some(SerializedComponentBatch::new(
+ crate::components::DrawOrder::arrow_empty(),
+ Self::descriptor_draw_order(),
+ )),
+ }
+ }
+
+ /// Partitions the component data into multiple sub-batches.
+ ///
+ /// Specifically, this transforms the existing [`SerializedComponentBatch`]es data into [`SerializedComponentColumn`]s
+ /// instead, via [`SerializedComponentBatch::partitioned`].
+ ///
+ /// This makes it possible to use `RecordingStream::send_columns` to send columnar data directly into Rerun.
+ ///
+ /// The specified `lengths` must sum to the total length of the component batch.
+ ///
+ /// [`SerializedComponentColumn`]: [::re_types_core::SerializedComponentColumn]
+ #[inline]
+ pub fn columns(
+ self,
+ _lengths: I,
+ ) -> SerializationResult>
+ where
+ I: IntoIterator- + Clone,
+ {
+ let columns = [
+ self.buffer
+ .map(|buffer| buffer.partitioned(_lengths.clone()))
+ .transpose()?,
+ self.format
+ .map(|format| format.partitioned(_lengths.clone()))
+ .transpose()?,
+ self.opacity
+ .map(|opacity| opacity.partitioned(_lengths.clone()))
+ .transpose()?,
+ self.draw_order
+ .map(|draw_order| draw_order.partitioned(_lengths.clone()))
+ .transpose()?,
+ ];
+ let indicator_column =
+ ::re_types_core::indicator_column::(_lengths.into_iter().count())?;
+ Ok(columns.into_iter().chain([indicator_column]).flatten())
+ }
+
+ /// Helper to partition the component data into unit-length sub-batches.
+ ///
+ /// This is semantically similar to calling [`Self::columns`] with `std::iter::take(1).repeat(n)`,
+ /// where `n` is automatically guessed.
+ #[inline]
+ pub fn columns_of_unit_batches(
+ self,
+ ) -> SerializationResult> {
+ let len_buffer = self.buffer.as_ref().map(|b| b.array.len());
+ let len_format = self.format.as_ref().map(|b| b.array.len());
+ let len_opacity = self.opacity.as_ref().map(|b| b.array.len());
+ let len_draw_order = self.draw_order.as_ref().map(|b| b.array.len());
+ let len = None
+ .or(len_buffer)
+ .or(len_format)
+ .or(len_opacity)
+ .or(len_draw_order)
+ .unwrap_or(0);
+ self.columns(std::iter::repeat(1).take(len))
+ }
+
+ /// The raw image data.
+ #[inline]
+ pub fn with_buffer(mut self, buffer: impl Into) -> Self {
+ self.buffer = try_serialize_field(Self::descriptor_buffer(), [buffer]);
+ self
+ }
+
+ /// This method makes it possible to pack multiple [`crate::components::ImageBuffer`] in a single component batch.
+ ///
+ /// This only makes sense when used in conjunction with [`Self::columns`]. [`Self::with_buffer`] should
+ /// be used when logging a single row's worth of data.
+ #[inline]
+ pub fn with_many_buffer(
+ mut self,
+ buffer: impl IntoIterator
- >,
+ ) -> Self {
+ self.buffer = try_serialize_field(Self::descriptor_buffer(), buffer);
+ self
+ }
+
+ /// The format of the image.
+ #[inline]
+ pub fn with_format(mut self, format: impl Into) -> Self {
+ self.format = try_serialize_field(Self::descriptor_format(), [format]);
+ self
+ }
+
+ /// This method makes it possible to pack multiple [`crate::components::ImageFormat`] in a single component batch.
+ ///
+ /// This only makes sense when used in conjunction with [`Self::columns`]. [`Self::with_format`] should
+ /// be used when logging a single row's worth of data.
+ #[inline]
+ pub fn with_many_format(
+ mut self,
+ format: impl IntoIterator
- >,
+ ) -> Self {
+ self.format = try_serialize_field(Self::descriptor_format(), format);
+ self
+ }
+
/// Opacity of the image, useful for layering several images.
///
/// Defaults to 1.0 (fully opaque).
#[inline]
pub fn with_opacity(mut self, opacity: impl Into) -> Self {
- self.opacity = Some(opacity.into());
+ self.opacity = try_serialize_field(Self::descriptor_opacity(), [opacity]);
+ self
+ }
+
+ /// This method makes it possible to pack multiple [`crate::components::Opacity`] in a single component batch.
+ ///
+ /// This only makes sense when used in conjunction with [`Self::columns`]. [`Self::with_opacity`] should
+ /// be used when logging a single row's worth of data.
+ #[inline]
+ pub fn with_many_opacity(
+ mut self,
+ opacity: impl IntoIterator
- >,
+ ) -> Self {
+ self.opacity = try_serialize_field(Self::descriptor_opacity(), opacity);
self
}
@@ -396,7 +483,20 @@ impl Image {
/// Objects with higher values are drawn on top of those with lower values.
#[inline]
pub fn with_draw_order(mut self, draw_order: impl Into) -> Self {
- self.draw_order = Some(draw_order.into());
+ self.draw_order = try_serialize_field(Self::descriptor_draw_order(), [draw_order]);
+ self
+ }
+
+ /// This method makes it possible to pack multiple [`crate::components::DrawOrder`] in a single component batch.
+ ///
+ /// This only makes sense when used in conjunction with [`Self::columns`]. [`Self::with_draw_order`] should
+ /// be used when logging a single row's worth of data.
+ #[inline]
+ pub fn with_many_draw_order(
+ mut self,
+ draw_order: impl IntoIterator
- >,
+ ) -> Self {
+ self.draw_order = try_serialize_field(Self::descriptor_draw_order(), draw_order);
self
}
}
@@ -409,12 +509,4 @@ impl ::re_byte_size::SizeBytes for Image {
+ self.opacity.heap_size_bytes()
+ self.draw_order.heap_size_bytes()
}
-
- #[inline]
- fn is_pod() -> bool {
- ::is_pod()
- && ::is_pod()
- &&