Skip to main content

nightshade_api/
materials.rs

1//! The shared material registry as data: list the named materials, read one,
2//! and update one in place so every entity referencing it changes at once. The
3//! per-entity [`set_color`](crate::prelude::set_color) family edits an entity's
4//! own material; these edit the registry the scene shares.
5
6use nightshade::ecs::material::components::Material;
7use nightshade::ecs::material::resources::material_registry_iter;
8use nightshade::prelude::*;
9use serde::{Deserialize, Serialize};
10
11/// One named entry in the material registry.
12#[derive(Clone, Serialize, Deserialize)]
13pub struct MaterialEntry {
14    pub name: String,
15    pub material: Material,
16}
17
18/// Every material in the registry, sorted by name.
19pub fn list_materials(world: &World) -> Vec<MaterialEntry> {
20    let mut entries: Vec<MaterialEntry> =
21        material_registry_iter(&world.resources.assets.material_registry)
22            .map(|(name, material)| MaterialEntry {
23                name: name.clone(),
24                material: material.clone(),
25            })
26            .collect();
27    entries.sort_by(|a, b| a.name.cmp(&b.name));
28    entries
29}
30
31/// The material registered under `name`, if any.
32pub fn get_material(world: &World, name: &str) -> Option<Material> {
33    registry_entry_by_name(&world.resources.assets.material_registry.registry, name).cloned()
34}
35
36/// Replaces the material registered under `name`, reuploading it so every
37/// entity that references it updates. The change runs through the ECS command
38/// queue, so it applies on the next frame setup.
39pub fn update_material(world: &mut World, name: &str, material: Material) {
40    queue_ecs_command(
41        world,
42        nightshade::ecs::world::commands::EcsCommand::ReloadMaterial {
43            name: name.to_string(),
44            material: Box::new(material),
45        },
46    );
47}
48
49/// Registers a named material in the shared registry so instanced meshes and
50/// models can reference it by name, returning the name it was stored under. Build
51/// the [`Material`] with the fields you need (base color, metallic, roughness,
52/// emissive, textures). If a material with this name already exists it is kept
53/// and its name returned, so calling this once at setup is idempotent.
54pub fn register_material(world: &mut World, name: &str, material: Material) -> String {
55    nightshade::ecs::material::resources::material_registry_find_or_insert(
56        &mut world.resources.assets.material_registry,
57        name.to_string(),
58        material,
59    )
60}
61
62/// Activates a material variant by name across the scene, or the base materials
63/// with `None`. Returns the number of entities affected.
64pub fn set_material_variant(world: &mut World, variant: Option<&str>) -> usize {
65    nightshade::ecs::material::commands::material_variant_apply(world, variant)
66}