use crate::assets::{MaterialHandle, MaterialVariantBinding};
use crate::diagnostics::LookupError;
use crate::scene::{NodeKey, Scene};
use super::SceneImport;
impl SceneImport {
pub fn material_variants(&self) -> &[String] {
&self.material_variants
}
pub fn active_variant(&self) -> Option<String> {
let lock = self
.active_variant
.lock()
.expect("variant lock should not be poisoned");
let index = (*lock)?;
self.material_variants.get(index as usize).cloned()
}
pub(crate) fn variant_index_for(&self, name: &str) -> Option<u32> {
self.material_variants
.iter()
.position(|candidate| candidate == name)
.map(|index| index as u32)
}
pub(crate) fn write_active_variant(&self, index: Option<u32>) {
let mut lock = self
.active_variant
.lock()
.expect("variant lock should not be poisoned");
*lock = index;
}
pub(crate) fn variant_records(&self) -> &[MeshVariantRecord] {
&self.variant_records
}
}
impl Scene {
pub fn set_active_variant(
&mut self,
import: &SceneImport,
name: Option<&str>,
) -> Result<(), LookupError> {
let new_index = match name {
Some(name) => Some(import.variant_index_for(name).ok_or_else(|| {
LookupError::VariantNotFound {
name: name.to_string(),
}
})?),
None => None,
};
import.write_active_variant(new_index);
for record in import.variant_records() {
let new_material = record.material_for(new_index);
let _ = self.set_mesh_material(record.node, new_material);
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub(crate) struct MeshVariantRecord {
pub(crate) node: NodeKey,
pub(crate) default_material: MaterialHandle,
pub(crate) bindings: Vec<MaterialVariantBinding>,
}
impl MeshVariantRecord {
pub(crate) fn material_for(&self, active_index: Option<u32>) -> MaterialHandle {
let Some(index) = active_index else {
return self.default_material;
};
self.bindings
.iter()
.find(|binding| binding.variants().contains(&index))
.map(|binding| binding.material())
.unwrap_or(self.default_material)
}
}