use std::rc::Rc;
use ambassador::Delegate;
use derive_more::derive::From;
use crate::{
common::DimensionMarker,
internal::{block_repr, modifier_repr},
prelude::{Color, Difference, Hull, Intersection, Minkowski, Union},
scad_display::{ambassador_impl_ScadDisplay, ScadDisplay},
};
#[derive(Debug, Clone, From)]
pub enum ScadObjectMixed {
Modifier(ScadModifierMixed),
Block(ScadBlockMixed),
}
impl ScadDisplay for ScadObjectMixed {
fn repr_scad(&self) -> String {
match self {
Self::Modifier(m) => m.repr_scad(),
Self::Block(b) => b.repr_scad(),
}
}
}
#[derive(Debug, Clone, From)]
pub struct ScadModifierMixed {
pub body: ScadModifierBodyMixed,
pub child: Rc<crate::common::ScadObjectImpl>,
}
impl ScadModifierMixed {
pub const fn new(
body: ScadModifierBodyMixed,
child: Rc<crate::common::ScadObjectImpl>,
) -> Self {
Self { body, child }
}
pub fn try_new(
body: ScadModifierBodyMixed,
child: Rc<crate::common::ScadObjectImpl>,
) -> Option<Self> {
(child.get_type() == body.get_children_type()).then_some(Self { body, child })
}
}
impl ScadDisplay for ScadModifierMixed {
fn repr_scad(&self) -> String {
modifier_repr(&self.body, &self.child)
}
}
#[derive(Debug, Clone, From)]
pub struct ScadBlockMixed {
pub objects: Vec<crate::common::ScadObjectImpl>,
}
impl ScadDisplay for ScadBlockMixed {
fn repr_scad(&self) -> String {
block_repr(&self.objects)
}
}
impl ScadBlockMixed {
pub fn new(objects: &[crate::common::ScadObjectImpl]) -> Self {
Self {
objects: objects.to_vec(),
}
}
pub fn try_new(objects: &[crate::common::ScadObjectImpl]) -> Option<Self> {
objects
.iter()
.all(|o| o.get_type() == DimensionMarker::ObjectMixed)
.then_some(Self {
objects: objects.to_vec(),
})
}
}
__impl_from_scad_for_collection_with_try_new!(
crate::common::DMixed,
ScadBlockMixed,
ScadObjectMixed,
crate::common::ScadObjectImpl::ObjectMixed,
"Internal error: Vec<T> or &[T] for DMixed should always produce a valid ScadBlockMixed"
);
impl From<ScadObjectMixed> for crate::common::ScadObjectGeneric<crate::common::DMixed> {
fn from(val: ScadObjectMixed) -> Self {
let rc_o = Rc::new(val);
let rc_impl = Rc::new(crate::common::ScadObjectImpl::ObjectMixed(rc_o));
Self::from_impl(rc_impl)
}
}
#[derive(Debug, Clone, Delegate, From)]
#[delegate(ScadDisplay)]
pub enum ScadModifierBodyMixed {
Color(Color),
Hull(Hull),
Minkowski(Minkowski),
Union(Union),
Difference(Difference),
Intersection(Intersection),
}
impl ScadModifierBodyMixed {
pub(crate) const fn get_children_type(&self) -> DimensionMarker {
DimensionMarker::ObjectMixed
}
}