kiss3d/resource/
material_manager.rs

1//! A resource manager to load materials.
2
3use crate::builtin::{NormalsMaterial, ObjectMaterial, UvsMaterial};
4use crate::resource::Material;
5use std::cell::RefCell;
6use std::collections::HashMap;
7use std::rc::Rc;
8
9/// The material manager.
10///
11/// Upon construction, it contains:
12/// * the `object` material, used as the default to render objects.
13/// * the `normals` material, used do display an object normals.
14///
15/// It keeps a cache of already-loaded materials. Note that this is only a cache, nothing more.
16/// Thus, its usage is not required to load materials.
17pub struct MaterialManager {
18    default_material: Rc<RefCell<Box<dyn Material + 'static>>>,
19    materials: HashMap<String, Rc<RefCell<Box<dyn Material + 'static>>>>,
20}
21
22impl Default for MaterialManager {
23    fn default() -> Self {
24        Self::new()
25    }
26}
27
28impl MaterialManager {
29    /// Creates a new material manager.
30    pub fn new() -> MaterialManager {
31        // load the default ObjectMaterial and the LineMaterial
32        let mut materials = HashMap::new();
33
34        let om = Rc::new(RefCell::new(
35            Box::new(ObjectMaterial::new()) as Box<dyn Material + 'static>
36        ));
37        let _ = materials.insert("object".to_string(), om.clone());
38
39        let nm = Rc::new(RefCell::new(
40            Box::new(NormalsMaterial::new()) as Box<dyn Material + 'static>
41        ));
42        let _ = materials.insert("normals".to_string(), nm.clone());
43
44        let um = Rc::new(RefCell::new(
45            Box::new(UvsMaterial::new()) as Box<dyn Material + 'static>
46        ));
47        let _ = materials.insert("uvs".to_string(), um.clone());
48
49        MaterialManager {
50            default_material: om,
51            materials,
52        }
53    }
54
55    /// Mutably applies a function to the material manager.
56    pub fn get_global_manager<T, F: FnMut(&mut MaterialManager) -> T>(mut f: F) -> T {
57        crate::window::WINDOW_CACHE
58            .with(|manager| f(&mut *manager.borrow_mut().material_manager.as_mut().unwrap()))
59    }
60
61    /// Gets the default material to draw objects.
62    pub fn get_default(&self) -> Rc<RefCell<Box<dyn Material + 'static>>> {
63        self.default_material.clone()
64    }
65
66    /// Get a material with the specified name. Returns `None` if the material is not registered.
67    pub fn get(&mut self, name: &str) -> Option<Rc<RefCell<Box<dyn Material + 'static>>>> {
68        self.materials.get(name).cloned()
69    }
70
71    /// Adds a material with the specified name to this cache.
72    pub fn add(&mut self, material: Rc<RefCell<Box<dyn Material + 'static>>>, name: &str) {
73        let _ = self.materials.insert(name.to_string(), material);
74    }
75
76    /// Removes a mesh from this cache.
77    pub fn remove(&mut self, name: &str) {
78        let _ = self.materials.remove(name);
79    }
80}