nightshade 0.8.0

A cross-platform data-oriented game engine.
Documentation
use super::TreeCache;
use crate::ecs::prefab::{import_gltf_from_path, spawn_prefab_node};
use crate::ecs::world::PREFAB_SOURCE;
use crate::prelude::*;
use std::path::Path;

pub fn instantiate_prefab(world: &mut World, tree_cache: &mut TreeCache, entity: Entity) {
    let prefab_source = match world.get_prefab_source(entity) {
        Some(source) => source.clone(),
        None => return,
    };

    let Some(source_path) = &prefab_source.source_path else {
        tracing::warn!(
            "Cannot instantiate prefab '{}': no source path",
            prefab_source.prefab_name
        );
        return;
    };

    let gltf_path = Path::new(source_path);
    let result = match import_gltf_from_path(gltf_path) {
        Ok(result) => result,
        Err(error) => {
            tracing::error!("Failed to load prefab from '{}': {}", source_path, error);
            return;
        }
    };

    crate::editor::asset_loading::load_gltf_resources(world, result.textures, result.meshes);

    let mut prefabs = result.prefabs;
    let prefab_index = prefabs
        .iter()
        .position(|p| p.name == prefab_source.prefab_name);
    let prefab = if let Some(index) = prefab_index {
        prefabs.remove(index)
    } else if !prefabs.is_empty() {
        tracing::warn!(
            "Prefab '{}' not found in '{}', using first available",
            prefab_source.prefab_name,
            source_path
        );
        prefabs.remove(0)
    } else {
        tracing::error!("No prefabs found in '{}'", source_path);
        return;
    };

    for root_node in &prefab.root_nodes {
        spawn_prefab_node(world, root_node, nalgebra_glm::Vec3::zeros(), Some(entity));
    }

    world.remove_components(entity, PREFAB_SOURCE);
    tree_cache.mark_dirty();
}