use bevy_transform::prelude::Transform;
use crate::dolly::driver::{RigDriver, RigDriverTraits};
use core::fmt::Debug;
#[derive(Debug)]
pub struct CameraRig {
pub drivers: Vec<Box<dyn RigDriverTraits>>,
pub final_transform: Transform,
}
struct RigUpdateToken;
pub struct RigUpdateParams<'a> {
pub parent: &'a Transform,
pub delta_time_seconds: f32,
_token: RigUpdateToken,
}
impl CameraRig {
pub fn driver_mut<T: RigDriver>(&mut self) -> &mut T {
self.try_driver_mut::<T>().unwrap_or_else(|| {
panic!(
"No {} driver found in the CameraRig",
std::any::type_name::<T>()
)
})
}
pub fn try_driver_mut<T: RigDriver>(&mut self) -> Option<&mut T> {
self.drivers
.iter_mut()
.find_map(|driver| driver.as_mut().as_any_mut().downcast_mut::<T>())
}
pub fn driver<T: RigDriver>(&self) -> &T {
self.try_driver::<T>().unwrap_or_else(|| {
panic!(
"No {} driver found in the CameraRig",
std::any::type_name::<T>()
)
})
}
pub fn try_driver<T: RigDriver>(&self) -> Option<&T> {
self.drivers
.iter()
.find_map(|driver| driver.as_ref().as_any().downcast_ref::<T>())
}
pub fn update(&mut self, delta_time_seconds: f32) -> Transform {
let mut parent_transform = Transform::IDENTITY;
for driver in self.drivers.iter_mut() {
let transform = driver.update(RigUpdateParams {
parent: &parent_transform,
delta_time_seconds,
_token: RigUpdateToken,
});
parent_transform = transform;
}
self.final_transform = parent_transform;
self.final_transform
}
pub fn builder() -> CameraRigBuilder {
CameraRigBuilder {
drivers: Default::default(),
}
}
}
pub struct CameraRigBuilder {
drivers: Vec<Box<dyn RigDriverTraits>>,
}
impl CameraRigBuilder {
pub fn with(mut self, driver: impl RigDriverTraits) -> Self {
self.drivers.push(Box::new(driver));
self
}
pub fn build(self) -> CameraRig {
let mut rig = CameraRig {
drivers: self.drivers,
final_transform: Transform::IDENTITY,
};
rig.update(0.0);
rig
}
}