use super::super::simulation::SourceWithInputs;
use super::{SimulationStep, SimulationStepError, SourceEntries};
use crate::effect::PathEffectParams;
use crate::ray_tracing::RayTracer;
use crate::simulation::{
DirectCompatible, Pathing, ReflectionEffectCompatible, ReflectionsCompatible,
SimulationFlagsProvider, SimulationSharedInputs, Simulator,
};
use std::collections::HashMap;
use std::hash::Hash;
use std::marker::PhantomData;
pub struct PathingStep<SourceId, T, D, R, RE>
where
T: RayTracer,
{
simulator: Simulator<T, D, R, Pathing, RE>,
_source_id: PhantomData<fn() -> SourceId>,
}
impl<T, D, R, RE> PathingStep<(), T, D, R, RE>
where
T: RayTracer,
{
pub fn new<SourceId>(
simulator: Simulator<T, D, R, Pathing, RE>,
) -> PathingStep<SourceId, T, D, R, RE> {
PathingStep {
simulator,
_source_id: PhantomData,
}
}
}
impl<SourceId, T, D, R, RE, I> SimulationStep<I> for PathingStep<SourceId, T, D, R, RE>
where
T: 'static + RayTracer,
D: 'static + Send + Sync + DirectCompatible<D> + SimulationFlagsProvider,
R: 'static + Send + Sync + ReflectionsCompatible<R> + SimulationFlagsProvider,
RE: 'static + Send + Sync + ReflectionEffectCompatible<R, RE>,
(): DirectCompatible<D> + ReflectionsCompatible<R>,
SourceId: 'static + Clone + Send + Sync + Hash + Eq,
I: AsPathingInput<SourceId, D, R, Pathing, RE>,
{
type Output = HashMap<SourceId, PathEffectParams>;
type Error = SimulationStepError;
fn run(&mut self, frame: &I, output: &mut Self::Output) -> Result<(), Self::Error> {
let input = frame.as_pathing_input();
self.simulator
.set_shared_pathing_inputs(input.shared_inputs)?;
for (
_,
SourceWithInputs {
source,
simulation_inputs,
},
) in input.sources
{
source.set_pathing_inputs(simulation_inputs)?;
}
self.simulator.run_pathing()?;
for (id, SourceWithInputs { source, .. }) in input.sources.iter() {
output.insert(id.clone(), source.get_pathing_outputs()?);
}
Ok(())
}
}
#[derive(Debug)]
pub struct PathingInput<'a, SourceId, D, R, P, RE>
where
RE: ReflectionEffectCompatible<R, RE>,
{
pub sources: &'a SourceEntries<SourceId, D, R, P, RE>,
pub shared_inputs: &'a SimulationSharedInputs<D, R, P>,
}
pub trait AsPathingInput<SourceId, D, R, P, RE>
where
RE: ReflectionEffectCompatible<R, RE>,
{
fn as_pathing_input(&self) -> PathingInput<'_, SourceId, D, R, P, RE>;
}
pub struct PathingInputOwned<SourceId, D, R, P, RE>
where
RE: ReflectionEffectCompatible<R, RE>,
{
pub sources: Vec<(SourceId, SourceWithInputs<D, R, P, RE>)>,
pub shared_inputs: SimulationSharedInputs<D, R, P>,
}
impl<SourceId, D, R, P, RE> AsPathingInput<SourceId, D, R, P, RE>
for PathingInputOwned<SourceId, D, R, P, RE>
where
RE: ReflectionEffectCompatible<R, RE>,
{
fn as_pathing_input(&self) -> PathingInput<'_, SourceId, D, R, P, RE> {
PathingInput {
sources: self.sources.as_slice(),
shared_inputs: &self.shared_inputs,
}
}
}