use spacecurve::{curve_from_name, registry};
#[derive(Clone)]
pub struct CurveSelection<const D: usize> {
pub name: String,
pub size: u32,
pub snake_offset: f32,
pub info_open: bool,
cached_name: String,
cached_size: u32,
cached_points: Vec<[u32; D]>,
cached_length: Option<u32>,
}
impl<const D: usize> Default for CurveSelection<D> {
fn default() -> Self {
let default_name = registry::curve_names(false)
.first()
.copied()
.unwrap_or(registry::CURVE_NAMES[0]);
Self::with_name(default_name)
}
}
impl<const D: usize> CurveSelection<D> {
pub fn with_name(name: &str) -> Self {
Self {
name: name.to_string(),
size: if D == 2 { 64 } else { 8 },
snake_offset: 0.0,
info_open: false,
cached_name: String::new(),
cached_size: 0,
cached_points: Vec::new(),
cached_length: None,
}
}
fn invalidate_if_changed(&mut self) {
if self.cached_name != self.name || self.cached_size != self.size {
self.cached_points.clear();
self.cached_length = None;
}
}
pub fn ensure_curve_length(&mut self) -> Option<u32> {
self.invalidate_if_changed();
if let Some(len) = self.cached_length {
return Some(len);
}
if !self.cached_points.is_empty() {
let len = self.cached_points.len() as u32;
self.cached_length = Some(len);
return Some(len);
}
match curve_from_name(&self.name, D as u32, self.size) {
Ok(pattern) => {
let len = pattern.length();
self.cached_length = Some(len);
self.cached_name = self.name.clone();
self.cached_size = self.size;
Some(len)
}
Err(_) => None,
}
}
pub fn ensure_cached_points(&mut self) -> Option<&[[u32; D]]> {
self.invalidate_if_changed();
if self.cached_name != self.name
|| self.cached_size != self.size
|| self.cached_points.is_empty()
{
if let Ok(pattern) = curve_from_name(&self.name, D as u32, self.size) {
let mut pts = Vec::with_capacity(pattern.length() as usize);
for i in 0..pattern.length() {
let p = pattern.point(i);
let mut arr = [0u32; D];
for d in 0..D {
arr[d] = p[d];
}
pts.push(arr);
}
self.cached_points = pts;
self.cached_name = self.name.clone();
self.cached_size = self.size;
self.cached_length = Some(pattern.length());
} else {
return None;
}
}
Some(&self.cached_points)
}
}
pub type SelectedCurve = CurveSelection<2>;
pub type Selected3DCurve = CurveSelection<3>;