use super::SdfNode;
use std::sync::{Arc, OnceLock};
fn leaf_sentinel() -> Arc<SdfNode> {
static LEAF: OnceLock<Arc<SdfNode>> = OnceLock::new();
Arc::clone(LEAF.get_or_init(|| Arc::new(SdfNode::Sphere { radius: 0.0 })))
}
impl SdfNode {
pub(crate) fn take_children_into(&mut self, out: &mut Vec<Arc<Self>>) {
match self {
Self::Union { a, b, .. }
| Self::Intersection { a, b, .. }
| Self::Subtraction { a, b, .. }
| Self::SmoothUnion { a, b, .. }
| Self::SmoothIntersection { a, b, .. }
| Self::SmoothSubtraction { a, b, .. }
| Self::ChamferUnion { a, b, .. }
| Self::ChamferIntersection { a, b, .. }
| Self::ChamferSubtraction { a, b, .. }
| Self::StairsUnion { a, b, .. }
| Self::StairsIntersection { a, b, .. }
| Self::StairsSubtraction { a, b, .. }
| Self::ColumnsUnion { a, b, .. }
| Self::ColumnsIntersection { a, b, .. }
| Self::ColumnsSubtraction { a, b, .. }
| Self::ExpSmoothUnion { a, b, .. }
| Self::ExpSmoothIntersection { a, b, .. }
| Self::ExpSmoothSubtraction { a, b, .. }
| Self::XOR { a, b, .. }
| Self::Pipe { a, b, .. }
| Self::Engrave { a, b, .. }
| Self::Groove { a, b, .. }
| Self::Tongue { a, b, .. }
| Self::Morph { a, b, .. } => {
out.push(std::mem::replace(a, leaf_sentinel()));
out.push(std::mem::replace(b, leaf_sentinel()));
}
Self::Translate { child, .. }
| Self::Rotate { child, .. }
| Self::Scale { child, .. }
| Self::ScaleNonUniform { child, .. }
| Self::Shear { child, .. }
| Self::ProjectiveTransform { child, .. }
| Self::SdfSkinning { child, .. }
| Self::Round { child, .. }
| Self::Onion { child, .. }
| Self::Elongate { child, .. }
| Self::Twist { child, .. }
| Self::Bend { child, .. }
| Self::Taper { child, .. }
| Self::Mirror { child, .. }
| Self::OctantMirror { child, .. }
| Self::IcosahedralSymmetry { child, .. }
| Self::RepeatInfinite { child, .. }
| Self::RepeatFinite { child, .. }
| Self::PolarRepeat { child, .. }
| Self::Displacement { child, .. }
| Self::SineDisplacement { child, .. }
| Self::HeightmapDisplacement { child, .. }
| Self::Noise { child, .. }
| Self::SurfaceRoughness { child, .. }
| Self::Revolution { child, .. }
| Self::Extrude { child, .. }
| Self::SweepBezier { child, .. }
| Self::LatticeDeform { child, .. }
| Self::IFS { child, .. }
| Self::WithMaterial { child, .. }
| Self::Animated { child, .. } => {
out.push(std::mem::replace(child, leaf_sentinel()));
}
_ => {}
}
}
}
impl Drop for SdfNode {
fn drop(&mut self) {
let mut stack: Vec<Arc<Self>> = Vec::new();
self.take_children_into(&mut stack);
if stack.is_empty() {
return;
}
while let Some(child) = stack.pop() {
if let Ok(mut node) = Arc::try_unwrap(child) {
node.take_children_into(&mut stack);
}
}
}
}