use super::super::simulation::SourceWithInputs;
use super::{SimulationStep, SimulationStepError, SourceEntries};
use crate::effect::DirectEffectParams;
use crate::ray_tracing::RayTracer;
use crate::simulation::{
Direct, PathingCompatible, ReflectionEffectCompatible, ReflectionsCompatible,
SimulationFlagsProvider, SimulationSharedInputs, Simulator,
};
use std::collections::HashMap;
use std::hash::Hash;
use std::marker::PhantomData;
pub struct DirectStep<SourceId, T, R, P, RE>
where
T: RayTracer,
{
simulator: Simulator<T, Direct, R, P, RE>,
_source_id: PhantomData<fn() -> SourceId>,
}
impl<T, R, P, RE> DirectStep<(), T, R, P, RE>
where
T: RayTracer,
{
pub fn new<SourceId>(
simulator: Simulator<T, Direct, R, P, RE>,
) -> DirectStep<SourceId, T, R, P, RE> {
DirectStep {
simulator,
_source_id: PhantomData,
}
}
}
impl<SourceId, T, R, P, RE, I> SimulationStep<I> for DirectStep<SourceId, T, R, P, RE>
where
T: 'static + RayTracer,
R: 'static + Send + Sync + ReflectionsCompatible<R> + SimulationFlagsProvider,
P: 'static + Send + Sync + PathingCompatible<P> + SimulationFlagsProvider,
RE: 'static + Send + Sync + ReflectionEffectCompatible<R, RE>,
(): ReflectionsCompatible<R> + PathingCompatible<P>,
I: AsDirectInput<SourceId, Direct, R, P, RE>,
SourceId: 'static + Clone + Send + Sync + Hash + Eq,
{
type Output = HashMap<SourceId, DirectEffectParams>;
type Error = SimulationStepError;
fn run(&mut self, frame: &I, output: &mut Self::Output) -> Result<(), Self::Error> {
let input = frame.as_direct_input();
self.simulator
.set_shared_direct_inputs(input.shared_inputs)?;
for (
_,
SourceWithInputs {
source,
simulation_inputs,
},
) in input.sources
{
source.set_direct_inputs(simulation_inputs)?;
}
self.simulator.run_direct();
for (id, SourceWithInputs { source, .. }) in input.sources.iter() {
output.insert(id.clone(), source.get_direct_outputs()?);
}
Ok(())
}
}
#[derive(Debug)]
pub struct DirectInput<'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 AsDirectInput<SourceId, D, R, P, RE>
where
RE: ReflectionEffectCompatible<R, RE>,
{
fn as_direct_input(&self) -> DirectInput<'_, SourceId, D, R, P, RE>;
}
pub struct DirectInputOwned<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> AsDirectInput<SourceId, D, R, P, RE>
for DirectInputOwned<SourceId, D, R, P, RE>
where
RE: ReflectionEffectCompatible<R, RE>,
{
fn as_direct_input(&self) -> DirectInput<'_, SourceId, D, R, P, RE> {
DirectInput {
sources: self.sources.as_slice(),
shared_inputs: &self.shared_inputs,
}
}
}