use concinnity_cook::compile::sdf_field::CompiledField;
use concinnity_core::components::ShaderSource;
use concinnity_core::render::backend::{PipelineBuilder, PreparedPipelines};
use concinnity_core::render::shader_programs::raymarch::VolumeFlags;
use concinnity_engine::live_edit::sdf_field_sources::SdfFieldEntry;
use std::collections::HashMap;
use crate::debug::hot_reload::report::ReloadFailure;
pub(in crate::debug::hot_reload) type FieldResult = Result<CompiledField, ReloadFailure>;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub(in crate::debug::hot_reload) struct FieldKey {
pub path: String,
pub volumetric: bool,
pub cast_shadows: bool,
}
impl FieldKey {
pub(in crate::debug::hot_reload) fn of(entry: &SdfFieldEntry) -> Self {
Self {
path: entry.resolved_path.clone(),
volumetric: entry.volumetric,
cast_shadows: entry.cast_shadows,
}
}
pub(in crate::debug::hot_reload) fn flags(&self) -> VolumeFlags {
VolumeFlags {
volumetric: self.volumetric,
cast_shadows: self.cast_shadows,
}
}
}
pub(in crate::debug::hot_reload) fn read_field(path: &str) -> Result<ShaderSource, String> {
concinnity_cook::compile::shader::read_shader_source(path)
.map(|text| ShaderSource {
path: path.to_string(),
text,
})
.map_err(|e| e.to_string())
}
pub(in crate::debug::hot_reload) fn compile(
name: &str,
key: &FieldKey,
field: &ShaderSource,
) -> FieldResult {
Ok(concinnity_host::thread::jobs::pool().install(|| {
concinnity_cook::compile::sdf_field::compile_sdf_field(
name,
field.as_file(),
crate::cook_platform(),
key.volumetric,
key.cast_shadows,
)
})?)
}
pub(in crate::debug::hot_reload) struct Rebuilt {
pub compiled: CompiledField,
pub prepared: HashMap<usize, PreparedPipelines>,
}
pub(in crate::debug::hot_reload) type RebuildResult = Result<Rebuilt, ReloadFailure>;
pub(in crate::debug::hot_reload) fn prepare(
compiled: CompiledField,
builder: Option<&dyn PipelineBuilder>,
key: &FieldKey,
volumes: &[(usize, String)],
) -> RebuildResult {
let mut prepared = HashMap::new();
if let Some(builder) = builder {
for (volume, name) in volumes {
let pipelines = builder
.sdf_volume(&compiled.programs, key.flags(), name)
.map_err(|e| ReloadFailure::Rejected(e.to_string()))?;
prepared.insert(*volume, pipelines);
}
}
Ok(Rebuilt { compiled, prepared })
}