pub mod adaptor_impls;
use crate::{
common_traits::{HasTangent, WithDerivative, WithTwoDerivatives},
curve::{Curve, Interval},
};
use core::ops::Deref;
#[cfg(feature = "bevy_reflect")]
use bevy_reflect::{FromReflect, Reflect};
pub trait CurveWithDerivative<T>: SampleDerivative<T> + Sized
where
T: HasTangent,
{
fn with_derivative(self) -> SampleDerivativeWrapper<Self>;
}
pub trait CurveWithTwoDerivatives<T>: SampleTwoDerivatives<T> + Sized
where
T: HasTangent,
{
fn with_two_derivatives(self) -> SampleTwoDerivativesWrapper<Self>;
}
pub trait SampleDerivative<T>: Curve<T>
where
T: HasTangent,
{
fn sample_with_derivative_unchecked(&self, t: f32) -> WithDerivative<T>;
fn sample_with_derivative(&self, t: f32) -> Option<WithDerivative<T>> {
match self.domain().contains(t) {
true => Some(self.sample_with_derivative_unchecked(t)),
false => None,
}
}
fn sample_with_derivative_clamped(&self, t: f32) -> WithDerivative<T> {
let t = self.domain().clamp(t);
self.sample_with_derivative_unchecked(t)
}
}
impl<T, C, D> SampleDerivative<T> for D
where
T: HasTangent,
C: SampleDerivative<T> + ?Sized,
D: Deref<Target = C>,
{
fn sample_with_derivative_unchecked(&self, t: f32) -> WithDerivative<T> {
<C as SampleDerivative<T>>::sample_with_derivative_unchecked(self, t)
}
}
pub trait SampleTwoDerivatives<T>: Curve<T>
where
T: HasTangent,
{
fn sample_with_two_derivatives_unchecked(&self, t: f32) -> WithTwoDerivatives<T>;
fn sample_with_two_derivatives(&self, t: f32) -> Option<WithTwoDerivatives<T>> {
match self.domain().contains(t) {
true => Some(self.sample_with_two_derivatives_unchecked(t)),
false => None,
}
}
fn sample_with_two_derivatives_clamped(&self, t: f32) -> WithTwoDerivatives<T> {
let t = self.domain().clamp(t);
self.sample_with_two_derivatives_unchecked(t)
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "bevy_reflect",
derive(Reflect, FromReflect),
reflect(from_reflect = false)
)]
pub struct SampleDerivativeWrapper<C>(C);
impl<T, C> Curve<WithDerivative<T>> for SampleDerivativeWrapper<C>
where
T: HasTangent,
C: SampleDerivative<T>,
{
fn domain(&self) -> Interval {
self.0.domain()
}
fn sample_unchecked(&self, t: f32) -> WithDerivative<T> {
self.0.sample_with_derivative_unchecked(t)
}
fn sample(&self, t: f32) -> Option<WithDerivative<T>> {
self.0.sample_with_derivative(t)
}
fn sample_clamped(&self, t: f32) -> WithDerivative<T> {
self.0.sample_with_derivative_clamped(t)
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "bevy_reflect",
derive(Reflect, FromReflect),
reflect(from_reflect = false)
)]
pub struct SampleTwoDerivativesWrapper<C>(C);
impl<T, C> Curve<WithTwoDerivatives<T>> for SampleTwoDerivativesWrapper<C>
where
T: HasTangent,
C: SampleTwoDerivatives<T>,
{
fn domain(&self) -> Interval {
self.0.domain()
}
fn sample_unchecked(&self, t: f32) -> WithTwoDerivatives<T> {
self.0.sample_with_two_derivatives_unchecked(t)
}
fn sample(&self, t: f32) -> Option<WithTwoDerivatives<T>> {
self.0.sample_with_two_derivatives(t)
}
fn sample_clamped(&self, t: f32) -> WithTwoDerivatives<T> {
self.0.sample_with_two_derivatives_clamped(t)
}
}
impl<T, C> CurveWithDerivative<T> for C
where
T: HasTangent,
C: SampleDerivative<T>,
{
fn with_derivative(self) -> SampleDerivativeWrapper<Self> {
SampleDerivativeWrapper(self)
}
}
impl<T, C> CurveWithTwoDerivatives<T> for C
where
T: HasTangent,
C: SampleTwoDerivatives<T> + CurveWithDerivative<T>,
{
fn with_two_derivatives(self) -> SampleTwoDerivativesWrapper<Self> {
SampleTwoDerivativesWrapper(self)
}
}