use palette::{Gradient, LinSrgba};
use serde::Deserialize;
use std::{collections::HashMap, path::PathBuf};
use crate::{
dom::{Surface, SurfaceBuilder, Tree, TreeBuilder},
geom::Mesh,
parse::{json, wavefront},
render::{Attribute, AttributeBuilder, GradientBuilder, Settings, Shader, ShaderBuilder},
rt::{Camera, CameraBuilder},
};
#[derive(Deserialize)]
pub struct Parameters {
resources_dir: PathBuf,
tree: TreeBuilder,
settings: Settings,
shader: ShaderBuilder,
camera: CameraBuilder,
surfaces: Vec<SurfaceBuilder>,
}
impl Parameters {
#[inline]
#[must_use]
pub fn used_gradient_names(&self) -> Vec<String> {
let mut gradient_names = Vec::new();
gradient_names.extend(self.shader.used_gradient_names());
gradient_names.extend(&mut self.used_attribute_names().iter().flat_map(|n| {
json::load::<AttributeBuilder>(
&self
.resources_dir
.join("attributes")
.join(n)
.with_extension("json"),
)
.used_gradient_names()
}));
gradient_names.sort();
gradient_names.dedup();
gradient_names
}
#[inline]
#[must_use]
pub fn used_attribute_names(&self) -> Vec<String> {
let mut names = Vec::new();
for surf in &self.surfaces {
names.push(surf.1.clone());
}
names.sort();
names.dedup();
names
}
#[inline]
#[must_use]
pub fn used_mesh_names(&self) -> Vec<String> {
let mut names = Vec::new();
for surf in &self.surfaces {
names.push(surf.0.clone());
}
names.sort();
names.dedup();
names
}
#[inline]
#[must_use]
pub fn load_gradients(&self) -> HashMap<String, Gradient<LinSrgba>> {
let mut grads = HashMap::new();
for name in self.used_gradient_names() {
let grad = json::load::<GradientBuilder>(
&self
.resources_dir
.join("gradients")
.join(name.clone())
.with_extension("json"),
)
.build();
grads.insert(name, grad);
}
grads
}
#[inline]
#[must_use]
pub fn load_attributes<'a>(
&self,
grads: &'a HashMap<String, Gradient<LinSrgba>>,
) -> HashMap<String, Attribute<'a>> {
let mut attrs = HashMap::new();
for name in self.used_attribute_names() {
let attr = json::load::<AttributeBuilder>(
&self
.resources_dir
.join("attributes")
.join(name.clone())
.with_extension("json"),
)
.build(grads);
attrs.insert(name, attr);
}
attrs
}
#[inline]
#[must_use]
pub fn load_meshes(&self) -> HashMap<String, Mesh> {
let mut meshes = HashMap::new();
for name in self.used_mesh_names() {
let mesh = wavefront::load(
&self
.resources_dir
.join("meshes")
.join(name.clone())
.with_extension("obj"),
);
meshes.insert(name, mesh);
}
meshes
}
#[inline]
#[must_use]
pub fn load_surfaces<'a>(
&self,
meshes: &HashMap<String, Mesh>,
attributes: &'a HashMap<String, Attribute>,
) -> Vec<Surface<Attribute<'a>>> {
self.surfaces
.iter()
.map(|s| s.clone().build(meshes, attributes))
.collect()
}
#[inline]
#[must_use]
pub fn build_shader<'a>(&self, grads: &'a HashMap<String, Gradient<LinSrgba>>) -> Shader<'a> {
self.shader.build(grads)
}
#[inline]
#[must_use]
pub fn build_settings(&self) -> Settings {
self.settings.clone()
}
#[inline]
#[must_use]
pub fn build_camera(&self) -> Camera {
self.camera.clone().build()
}
#[inline]
#[must_use]
pub fn build_tree<'a, T>(&self, surfs: &'a [Surface<T>]) -> Tree<'a, T> {
self.tree.build(surfs)
}
}