ursus_core/assets/
loader_registry.rs1use crate::assets::mesh::CpuMesh;
2use crate::render::gfx::types::Format;
3use std::path::Path;
4use std::sync::Arc;
5
6pub struct LoadedTexture {
7 pub pixels: Vec<u8>,
8 pub width: u32,
9 pub height: u32,
10 pub format: Format,
11}
12
13pub struct LoadedPrimitive {
14 pub mesh: CpuMesh,
15 pub node_translation: [f32; 3],
16 pub node_rotation: [f32; 4],
17 pub node_scale: [f32; 3],
18}
19
20pub struct LoadedMeshSource {
21 pub primitives: Vec<LoadedPrimitive>,
22}
23
24pub trait AssetLoader: Send + Sync {
25 fn extensions(&self) -> &[&str];
26 fn load(&self, path: &Path) -> anyhow::Result<LoadedMeshSource>;
27 fn name(&self) -> &str {
28 "unnamed loader"
29 }
30}
31
32#[derive(Default)]
33pub struct LoaderRegistry {
34 loaders: Vec<Arc<dyn AssetLoader>>,
35}
36
37impl LoaderRegistry {
38 pub fn new() -> Self {
39 Self::default()
40 }
41
42 pub fn register(&mut self, loader: impl AssetLoader + 'static) {
43 self.register_arc(Arc::new(loader));
44 }
45
46 pub fn register_arc(&mut self, loader: Arc<dyn AssetLoader>) {
47 for ext in loader.extensions() {
48 if let Some(existing) = self.find(ext) {
49 if existing.name() == loader.name() {
50 return;
51 }
52 log::warn!(
53 "LoaderRegistry: расширение '{}' уже обрабатывается '{}', переопределяется '{}'",
54 ext,
55 existing.name(),
56 loader.name()
57 );
58 }
59 }
60 self.loaders.push(loader);
61 }
62
63 fn find(&self, ext: &str) -> Option<&Arc<dyn AssetLoader>> {
64 self.loaders.iter().rev().find(|l| l.extensions().contains(&ext))
65 }
66
67 pub fn load(&self, path: &Path) -> anyhow::Result<LoadedMeshSource> {
68 let ext = path.extension().and_then(|e| e.to_str()).unwrap_or("").to_lowercase();
69 let loader = self.find(&ext).ok_or_else(|| {
70 anyhow::anyhow!("нет зарегистрированного загрузчика для расширения '.{}': {:?}", ext, path)
71 })?;
72 loader.load(path)
73 }
74
75 pub fn into_loaders(self) -> Vec<Arc<dyn AssetLoader>> {
76 self.loaders
77 }
78}