photonic 0.1.1

Dynamic light controller and animator
Documentation
use anyhow::Result;

use crate::attr::{Bounded, Bounds};
use crate::{scene, Attr, AttrBuilder, AttrValue, BoundAttrDecl, FreeAttrDecl};

use super::Boxed;

pub trait DynFreeAttrDecl<V>
where V: AttrValue
{
    fn materialize(self: Box<Self>, builder: &mut AttrBuilder) -> Result<BoxedAttr<V>>;
}

impl<T, V> DynFreeAttrDecl<V> for T
where
    T: FreeAttrDecl<V>,
    <T as FreeAttrDecl<V>>::Attr: DynAttr<V> + Sized + 'static,
    V: AttrValue,
{
    fn materialize(self: Box<Self>, builder: &mut AttrBuilder) -> Result<BoxedAttr<V>> {
        let attr = <T as FreeAttrDecl<V>>::materialize(*self, builder)?;
        return Ok(Box::new(attr));
    }
}

impl<T, V> Boxed<dyn DynFreeAttrDecl<V>> for T
where
    V: AttrValue,
    T: FreeAttrDecl<V> + 'static,
    T::Attr: Sized + 'static,
{
    fn boxed(self) -> Box<dyn DynFreeAttrDecl<V>> {
        return Box::new(self);
    }
}

pub type BoxedFreeAttrDecl<V> = Box<dyn DynFreeAttrDecl<V>>;

impl<V> FreeAttrDecl<V> for BoxedFreeAttrDecl<V>
where V: AttrValue
{
    const KIND: &'static str = "boxed";

    type Attr = BoxedAttr<V>;

    fn materialize(self, builder: &mut AttrBuilder) -> Result<Self::Attr> {
        return DynFreeAttrDecl::materialize(self, builder);
    }
}

pub trait DynBoundAttrDecl<V>
where V: AttrValue
{
    fn materialize(self: Box<Self>, bounds: Bounds<V>, builder: &mut AttrBuilder) -> Result<BoxedAttr<V>>;
}

impl<T, V> DynBoundAttrDecl<V> for T
where
    T: BoundAttrDecl<V>,
    <T as BoundAttrDecl<V>>::Attr: DynAttr<V> + Sized + 'static,
    V: AttrValue + Bounded,
{
    fn materialize(self: Box<Self>, bounds: Bounds<V>, builder: &mut AttrBuilder) -> Result<BoxedAttr<V>> {
        let attr = <T as BoundAttrDecl<V>>::materialize(*self, bounds, builder)?;
        return Ok(Box::new(attr));
    }
}

impl<T, V> Boxed<dyn DynBoundAttrDecl<V>> for T
where
    T: BoundAttrDecl<V> + 'static,
    T::Attr: Sized + 'static,
    V: AttrValue + Bounded,
{
    fn boxed(self) -> Box<dyn DynBoundAttrDecl<V>> {
        return Box::new(self);
    }
}

pub type BoxedBoundAttrDecl<V> = Box<dyn DynBoundAttrDecl<V>>;

impl<V> BoundAttrDecl<V> for BoxedBoundAttrDecl<V>
where V: AttrValue + Bounded
{
    const KIND: &'static str = "boxed";

    type Attr = BoxedAttr<V>;

    fn materialize(self, bounds: Bounds<V>, builder: &mut AttrBuilder) -> Result<Self::Attr> {
        return DynBoundAttrDecl::materialize(self, bounds, builder);
    }
}

pub trait DynAttr<V>
where V: AttrValue
{
    fn update(&mut self, ctx: &scene::RenderContext) -> V;
}

impl<T, V> DynAttr<V> for T
where
    T: Attr<V>,
    V: AttrValue,
{
    fn update(&mut self, ctx: &scene::RenderContext) -> V {
        return <T as Attr<V>>::update(self, ctx);
    }
}

pub type BoxedAttr<V> = Box<dyn DynAttr<V>>;

impl<V> Attr<V> for BoxedAttr<V>
where V: AttrValue
{
    fn update(&mut self, ctx: &scene::RenderContext) -> V {
        return DynAttr::update(self.as_mut(), ctx);
    }
}