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::resources::material_registry_iter;
7use nightshade::prelude::*;
8use nightshade::render::material::Material;
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> = material_registry_iter(
21        &world
22            .res::<nightshade::ecs::asset_state::AssetState>()
23            .material_registry,
24    )
25    .map(|(name, material)| MaterialEntry {
26        name: name.clone(),
27        material: material.clone(),
28    })
29    .collect();
30    entries.sort_by(|a, b| a.name.cmp(&b.name));
31    entries
32}
33
34/// The material registered under `name`, if any.
35pub fn material(world: &World, name: &str) -> Option<Material> {
36    registry_entry_by_name(
37        &world
38            .res::<nightshade::ecs::asset_state::AssetState>()
39            .material_registry
40            .registry,
41        name,
42    )
43    .cloned()
44}
45
46/// Replaces the material registered under `name`, reuploading it so every
47/// entity that references it updates. The change runs through the ECS command
48/// queue, so it applies on the next frame setup.
49pub fn update_material(world: &mut World, name: &str, material: Material) {
50    queue_ecs_command(
51        world,
52        nightshade::ecs::world::commands::EcsCommand::ReloadMaterial {
53            name: name.to_string(),
54            material: Box::new(material),
55        },
56    );
57}
58
59/// Registers a named material in the shared registry so instanced meshes and
60/// models can reference it by name, returning the name it was stored under. Build
61/// the [`Material`] with the fields you need (base color, metallic, roughness,
62/// emissive, textures). If a material with this name already exists it is kept
63/// and its name returned, so calling this once at setup is idempotent.
64pub fn register_material(world: &mut World, name: &str, material: Material) -> String {
65    nightshade::ecs::material::resources::material_registry_find_or_insert(
66        &mut world
67            .res_mut::<nightshade::ecs::asset_state::AssetState>()
68            .material_registry,
69        name.to_string(),
70        material,
71    )
72}
73
74/// Activates a material variant by name across the scene, or the base materials
75/// with `None`. Returns the number of entities affected.
76pub fn set_material_variant(world: &mut World, variant: Option<&str>) -> usize {
77    nightshade::ecs::material::commands::material_variant_apply(world, variant)
78}