use std::collections::HashMap;
use std::path::{Path, PathBuf};
use super::asset_uuid::AssetUuid;
use super::manifest::{AssetEntry, AssetManifest, AssetType};
#[derive(Debug, Clone, Default)]
pub struct AssetRegistry {
pub manifests: Vec<AssetManifest>,
pub uuid_to_manifest: HashMap<AssetUuid, usize>,
pub path_to_uuid: HashMap<String, AssetUuid>,
pub name_to_uuid: HashMap<String, AssetUuid>,
pub base_paths: Vec<PathBuf>,
}
pub fn asset_registry_add_manifest(
registry: &mut AssetRegistry,
manifest: AssetManifest,
base_path: impl Into<PathBuf>,
) {
let manifest_index = registry.manifests.len();
let base_path = base_path.into();
for entry in &manifest.assets {
registry.uuid_to_manifest.insert(entry.uuid, manifest_index);
registry.path_to_uuid.insert(entry.path.clone(), entry.uuid);
if let Some(name) = &entry.name {
registry.name_to_uuid.insert(name.clone(), entry.uuid);
}
}
registry.manifests.push(manifest);
registry.base_paths.push(base_path);
}
pub fn asset_registry_resolve_uuid(registry: &AssetRegistry, uuid: AssetUuid) -> Option<PathBuf> {
let manifest_index = registry.uuid_to_manifest.get(&uuid)?;
let manifest = registry.manifests.get(*manifest_index)?;
let entry = manifest.get_by_uuid(uuid)?;
let base_path = registry.base_paths.get(*manifest_index)?;
Some(base_path.join(&entry.path))
}
pub fn asset_registry_resolve_path(registry: &AssetRegistry, path: &str) -> Option<AssetUuid> {
registry.path_to_uuid.get(path).copied()
}
pub fn asset_registry_resolve_name(registry: &AssetRegistry, name: &str) -> Option<AssetUuid> {
registry.name_to_uuid.get(name).copied()
}
pub fn asset_registry_get_entry(registry: &AssetRegistry, uuid: AssetUuid) -> Option<&AssetEntry> {
let manifest_index = registry.uuid_to_manifest.get(&uuid)?;
let manifest = registry.manifests.get(*manifest_index)?;
manifest.get_by_uuid(uuid)
}
pub fn asset_registry_get_base_path(registry: &AssetRegistry, uuid: AssetUuid) -> Option<&Path> {
let manifest_index = registry.uuid_to_manifest.get(&uuid)?;
registry
.base_paths
.get(*manifest_index)
.map(|path| path.as_path())
}
pub fn asset_registry_assets_of_type(
registry: &AssetRegistry,
asset_type: AssetType,
) -> impl Iterator<Item = &AssetEntry> {
registry
.manifests
.iter()
.flat_map(move |manifest| manifest.assets_of_type(asset_type))
}
pub fn asset_registry_all_assets(registry: &AssetRegistry) -> impl Iterator<Item = &AssetEntry> {
registry
.manifests
.iter()
.flat_map(|manifest| &manifest.assets)
}
pub fn asset_registry_uuid_exists(registry: &AssetRegistry, uuid: AssetUuid) -> bool {
registry.uuid_to_manifest.contains_key(&uuid)
}
pub fn asset_registry_path_exists(registry: &AssetRegistry, path: &str) -> bool {
registry.path_to_uuid.contains_key(path)
}
pub fn asset_registry_name_exists(registry: &AssetRegistry, name: &str) -> bool {
registry.name_to_uuid.contains_key(name)
}
pub fn asset_registry_clear(registry: &mut AssetRegistry) {
registry.manifests.clear();
registry.uuid_to_manifest.clear();
registry.path_to_uuid.clear();
registry.name_to_uuid.clear();
registry.base_paths.clear();
}
pub fn asset_registry_manifest_count(registry: &AssetRegistry) -> usize {
registry.manifests.len()
}
pub fn asset_registry_asset_count(registry: &AssetRegistry) -> usize {
registry
.manifests
.iter()
.map(|manifest| manifest.len())
.sum()
}
#[derive(Debug, Clone)]
pub struct RuntimeAssetEntry {
pub uuid: AssetUuid,
pub name: String,
pub asset_type: AssetType,
pub loaded: bool,
}
#[derive(Debug, Clone, Default)]
pub struct RuntimeAssetRegistry {
pub entries: HashMap<AssetUuid, RuntimeAssetEntry>,
pub name_to_uuid: HashMap<String, AssetUuid>,
pub type_to_uuids: HashMap<AssetType, Vec<AssetUuid>>,
}
pub fn runtime_asset_registry_register(
registry: &mut RuntimeAssetRegistry,
uuid: AssetUuid,
name: impl Into<String>,
asset_type: AssetType,
) {
let name = name.into();
let entry = RuntimeAssetEntry {
uuid,
name: name.clone(),
asset_type,
loaded: false,
};
registry.name_to_uuid.insert(name, uuid);
registry
.type_to_uuids
.entry(asset_type)
.or_default()
.push(uuid);
registry.entries.insert(uuid, entry);
}
pub fn runtime_asset_registry_mark_loaded(registry: &mut RuntimeAssetRegistry, uuid: AssetUuid) {
if let Some(entry) = registry.entries.get_mut(&uuid) {
entry.loaded = true;
}
}
pub fn runtime_asset_registry_mark_unloaded(registry: &mut RuntimeAssetRegistry, uuid: AssetUuid) {
if let Some(entry) = registry.entries.get_mut(&uuid) {
entry.loaded = false;
}
}
pub fn runtime_asset_registry_is_loaded(registry: &RuntimeAssetRegistry, uuid: AssetUuid) -> bool {
registry
.entries
.get(&uuid)
.is_some_and(|entry| entry.loaded)
}
pub fn runtime_asset_registry_get(
registry: &RuntimeAssetRegistry,
uuid: AssetUuid,
) -> Option<&RuntimeAssetEntry> {
registry.entries.get(&uuid)
}
pub fn runtime_asset_registry_get_by_name<'a>(
registry: &'a RuntimeAssetRegistry,
name: &str,
) -> Option<&'a RuntimeAssetEntry> {
registry
.name_to_uuid
.get(name)
.and_then(|uuid| registry.entries.get(uuid))
}
pub fn runtime_asset_registry_resolve_name(
registry: &RuntimeAssetRegistry,
name: &str,
) -> Option<AssetUuid> {
registry.name_to_uuid.get(name).copied()
}
pub fn runtime_asset_registry_unregister(registry: &mut RuntimeAssetRegistry, uuid: AssetUuid) {
if let Some(entry) = registry.entries.remove(&uuid) {
registry.name_to_uuid.remove(&entry.name);
if let Some(uuids) = registry.type_to_uuids.get_mut(&entry.asset_type) {
uuids.retain(|other| *other != uuid);
}
}
}
pub fn runtime_asset_registry_clear(registry: &mut RuntimeAssetRegistry) {
registry.entries.clear();
registry.name_to_uuid.clear();
registry.type_to_uuids.clear();
}