use super::time::InstantWrapperImpl;
use super::{InstantWrapperFactoryFn, World, WorldInteractorFactoryFn};
use crate::object::AssociatedObjectData;
use crate::simulation::simulation_impl::world::builder::NphysicsWorldBuilder;
use crate::simulation::simulation_impl::SimulationImpl;
use crate::simulation::Simulation;
use crate::world_interactor::WorldInteractorImpl;
use nameof::name_of_type;
use std::fmt;
use std::fmt::Debug;
use std::time::Instant;
pub struct SimulationBuilder<T> {
world: Option<Box<dyn World>>,
world_interactor_factory_fn: Option<Box<WorldInteractorFactoryFn<T>>>,
instant_wrapper_factory_fn: Option<Box<InstantWrapperFactoryFn>>,
}
impl<T> Debug for SimulationBuilder<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct(name_of_type!(SimulationBuilder<T>))
.field("world", &self.world)
.finish()
}
}
impl<T> Default for SimulationBuilder<T> {
fn default() -> Self {
Self {
world: None,
world_interactor_factory_fn: None,
instant_wrapper_factory_fn: None,
}
}
}
impl<T> SimulationBuilder<T>
where
T: AssociatedObjectData,
{
pub fn new() -> Self {
Self::default()
}
pub fn world(&mut self, world: Box<dyn World>) {
self.world = Some(world)
}
pub fn world_interactor_factory_fn(
&mut self,
world_interactor_factory_fn: Box<WorldInteractorFactoryFn<T>>,
) {
self.world_interactor_factory_fn = Some(world_interactor_factory_fn)
}
pub fn instant_wrapper_factory_fn(
&mut self,
instant_wrapper_factory_fn: Box<InstantWrapperFactoryFn>,
) {
self.instant_wrapper_factory_fn = Some(instant_wrapper_factory_fn)
}
pub fn build<'a>(self) -> Box<dyn Simulation<T> + 'a>
where
T: 'a,
{
box SimulationImpl::new(
self.world
.unwrap_or_else(|| box NphysicsWorldBuilder::default().build()),
self.world_interactor_factory_fn.unwrap_or_else(|| {
box |simulation, id| box WorldInteractorImpl::new(simulation, id)
}),
self.instant_wrapper_factory_fn
.unwrap_or_else(|| box || box InstantWrapperImpl::new(Instant::now())),
)
}
}