use crate::ecs::animation::components::AnimationClip;
use crate::ecs::asset_id::MeshId;
use crate::ecs::generational_registry::GenerationalRegistry;
use crate::ecs::mesh::components::Mesh;
#[cfg(feature = "assets")]
use crate::ecs::prefab::components::Prefab;
use std::collections::{HashMap, HashSet};
#[derive(Clone)]
pub struct MeshCache {
pub registry: GenerationalRegistry<Mesh>,
pub dirty_meshes: HashSet<String>,
pub dirty_skinned_meshes: HashSet<String>,
}
#[derive(Default, Clone)]
pub struct AnimationCache {
pub clips: HashMap<String, AnimationClip>,
}
#[derive(Default, Clone)]
pub struct PrefabCache {
#[cfg(feature = "assets")]
pub prefabs: HashMap<String, CachedPrefab>,
#[cfg(not(feature = "assets"))]
pub prefabs: HashMap<String, ()>,
}
#[cfg(feature = "assets")]
#[derive(Clone)]
pub struct CachedPrefab {
pub prefab: Prefab,
pub animations: Vec<AnimationClip>,
pub skins: Vec<crate::ecs::prefab::GltfSkin>,
pub source_path: Option<String>,
}
pub fn animation_cache_insert(cache: &mut AnimationCache, name: String, clip: AnimationClip) {
cache.clips.insert(name, clip);
}
pub fn animation_cache_names(cache: &AnimationCache) -> impl Iterator<Item = &String> + '_ {
cache.clips.keys()
}
#[cfg(feature = "assets")]
pub fn prefab_cache_insert(cache: &mut PrefabCache, name: String, cached: CachedPrefab) {
cache.prefabs.insert(name, cached);
}
#[cfg(feature = "assets")]
pub fn prefab_cache_get<'a>(cache: &'a PrefabCache, name: &str) -> Option<&'a CachedPrefab> {
cache.prefabs.get(name)
}
#[cfg(feature = "assets")]
pub fn prefab_cache_names(cache: &PrefabCache) -> impl Iterator<Item = &String> + '_ {
cache.prefabs.keys()
}
impl Default for MeshCache {
fn default() -> Self {
Self {
registry: GenerationalRegistry::new(),
dirty_meshes: HashSet::new(),
dirty_skinned_meshes: HashSet::new(),
}
}
}
pub fn mesh_cache_insert(cache: &mut MeshCache, name: String, mesh: Mesh) -> MeshId {
if let Some((index, generation)) = cache.registry.lookup_index(&name) {
if let Some(entry) = cache.registry.entries.get_mut(index as usize) {
*entry = Some(mesh);
}
cache.dirty_meshes.insert(name);
return MeshId { index, generation };
}
let (index, generation) = cache.registry.insert(name.clone(), mesh);
cache.registry.add_reference(index);
cache.dirty_meshes.insert(name);
MeshId { index, generation }
}
pub fn mesh_cache_take_dirty(cache: &mut MeshCache) -> HashSet<String> {
std::mem::take(&mut cache.dirty_meshes)
}
pub fn mesh_cache_mark_dirty(cache: &mut MeshCache, name: String) {
cache.dirty_meshes.insert(name);
}
pub fn mesh_cache_take_dirty_skinned(cache: &mut MeshCache) -> HashSet<String> {
std::mem::take(&mut cache.dirty_skinned_meshes)
}
pub fn mesh_cache_lookup_id(cache: &MeshCache, name: &str) -> Option<MeshId> {
cache
.registry
.lookup_index(name)
.map(|(index, generation)| MeshId { index, generation })
}
pub fn mesh_cache_iter(cache: &MeshCache) -> impl Iterator<Item = (&String, &Mesh)> {
cache
.registry
.index_to_name
.iter()
.enumerate()
.filter_map(|(index, name_opt)| {
name_opt.as_ref().and_then(|name| {
cache.registry.entries[index]
.as_ref()
.map(|mesh| (name, mesh))
})
})
}