nightshade-api 0.45.0

Procedural high level API for the nightshade game engine
Documentation
//! The shared material registry as data: list the named materials, read one,
//! and update one in place so every entity referencing it changes at once. The
//! per-entity [`set_color`](crate::prelude::set_color) family edits an entity's
//! own material; these edit the registry the scene shares.

use nightshade::ecs::material::components::Material;
use nightshade::ecs::material::resources::material_registry_iter;
use nightshade::prelude::*;
use serde::{Deserialize, Serialize};

/// One named entry in the material registry.
#[derive(Clone, Serialize, Deserialize)]
pub struct MaterialEntry {
    pub name: String,
    pub material: Material,
}

/// Every material in the registry, sorted by name.
pub fn list_materials(world: &World) -> Vec<MaterialEntry> {
    let mut entries: Vec<MaterialEntry> =
        material_registry_iter(&world.resources.assets.material_registry)
            .map(|(name, material)| MaterialEntry {
                name: name.clone(),
                material: material.clone(),
            })
            .collect();
    entries.sort_by(|a, b| a.name.cmp(&b.name));
    entries
}

/// The material registered under `name`, if any.
pub fn get_material(world: &World, name: &str) -> Option<Material> {
    registry_entry_by_name(&world.resources.assets.material_registry.registry, name).cloned()
}

/// Replaces the material registered under `name`, reuploading it so every
/// entity that references it updates. The change runs through the ECS command
/// queue, so it applies on the next frame setup.
pub fn update_material(world: &mut World, name: &str, material: Material) {
    queue_ecs_command(
        world,
        nightshade::ecs::world::commands::EcsCommand::ReloadMaterial {
            name: name.to_string(),
            material: Box::new(material),
        },
    );
}

/// Registers a named material in the shared registry so instanced meshes and
/// models can reference it by name, returning the name it was stored under. Build
/// the [`Material`] with the fields you need (base color, metallic, roughness,
/// emissive, textures). If a material with this name already exists it is kept
/// and its name returned, so calling this once at setup is idempotent.
pub fn register_material(world: &mut World, name: &str, material: Material) -> String {
    nightshade::ecs::material::resources::material_registry_find_or_insert(
        &mut world.resources.assets.material_registry,
        name.to_string(),
        material,
    )
}

/// Activates a material variant by name across the scene, or the base materials
/// with `None`. Returns the number of entities affected.
pub fn set_material_variant(world: &mut World, variant: Option<&str>) -> usize {
    nightshade::ecs::material::commands::material_variant_apply(world, variant)
}