use crate::{CoreError, Primitive, PrimitiveHandle, Scene};
impl Scene {
pub fn add_primitives(
&mut self,
values: &[Primitive],
) -> Result<Option<PrimitiveHandle>, CoreError> {
for value in values {
self.validate_primitive(*value)?;
}
self.primitive.reserve(values.len());
let mut last = None;
for value in values {
last = Some(PrimitiveHandle(self.primitive.insert(*value)));
}
if !values.is_empty() {
self.primitive_revision = self.primitive_revision.wrapping_add(1);
}
Ok(last)
}
#[must_use]
pub fn primitive(&self, handle: PrimitiveHandle) -> Option<&Primitive> {
self.primitive.get(handle.0)
}
pub fn primitive_mut(&mut self, handle: PrimitiveHandle) -> Option<&mut Primitive> {
let value = self.primitive.get_mut(handle.0)?;
self.primitive_revision = self.primitive_revision.wrapping_add(1);
Some(value)
}
pub fn remove_primitive(&mut self, handle: PrimitiveHandle) -> Option<Primitive> {
let value = self.primitive.remove(handle.0)?;
self.primitive_revision = self.primitive_revision.wrapping_add(1);
Some(value)
}
pub fn primitives(&self) -> impl Iterator<Item = (PrimitiveHandle, &Primitive)> + '_ {
self.primitive
.iter()
.map(|(handle, value)| (PrimitiveHandle(handle), value))
}
#[must_use]
pub const fn primitive_revision(&self) -> u64 {
self.primitive_revision
}
#[must_use]
pub const fn primitive_row(handle: PrimitiveHandle) -> u32 {
handle.row()
}
#[must_use]
pub fn primitive_for_entity(&self, entity: crate::EntityRef) -> Option<&Primitive> {
if entity.kind != crate::EntityKind::Primitive {
return None;
}
self.primitive
.get_index(entity.index)
.map(|(_, value)| value)
}
fn validate_primitive(&self, value: Primitive) -> Result<(), CoreError> {
if self.structure(value.owner()).is_none() {
return Err(CoreError::StaleHandle);
}
let opacity = match value {
Primitive::Ellipsoid { opacity, .. } | Primitive::Planar { opacity, .. } => opacity,
Primitive::Particle(value) => value.opacity,
Primitive::Carbohydrate(_) => return Ok(()),
};
if valid_opacity(opacity) {
Ok(())
} else {
Err(CoreError::InvalidPrimitive {
reason: "primitive opacity must be finite in [0, 1]",
})
}
}
}
const fn valid_opacity(opacity: f32) -> bool {
opacity.is_finite() && opacity >= 0.0 && opacity <= 1.0
}