gizmo_engine/
asset_server.rs1use crate::core::asset::Handle;
2use crate::renderer::async_assets::AsyncAssetLoader;
3use crate::renderer::components::{Material, Mesh};
4use wgpu::util::DeviceExt;
5
6pub struct AssetServer {
7 pub loader: AsyncAssetLoader,
8 mesh_paths: std::collections::HashMap<String, Handle<Mesh>>,
9 _material_paths: std::collections::HashMap<String, Handle<Material>>,
10 pub completed_gltfs: Vec<crate::renderer::async_assets::GltfImportCompletion>,
11 pub completed_gltf_errors: Vec<crate::renderer::async_assets::GltfImportError>,
12 pub completed_textures: Vec<crate::renderer::async_assets::TextureReloadCompletion>,
17 #[cfg(all(feature = "render", not(target_arch = "wasm32")))]
18 pub watcher: Option<crate::renderer::hot_reload::AssetWatcher>,
19}
20
21impl Default for AssetServer {
22 fn default() -> Self {
23 Self::new()
24 }
25}
26
27impl AssetServer {
28 pub fn new() -> Self {
29 #[cfg(all(feature = "render", not(target_arch = "wasm32")))]
30 let watcher = crate::renderer::hot_reload::AssetWatcher::new(&["assets", "demo/assets"]);
31
32 Self {
33 loader: AsyncAssetLoader::new(),
34 mesh_paths: std::collections::HashMap::new(),
35 _material_paths: std::collections::HashMap::new(),
36 completed_gltfs: Vec::new(),
37 completed_gltf_errors: Vec::new(),
38 completed_textures: Vec::new(),
39 #[cfg(all(feature = "render", not(target_arch = "wasm32")))]
40 watcher,
41 }
42 }
43
44 pub fn load_mesh(&mut self, path: &str) -> Handle<Mesh> {
45 if let Some(handle) = self.mesh_paths.get(path) {
46 return handle.clone();
47 }
48 let handle = crate::core::asset::Handle::weak(crate::core::asset::HandleId::new());
49 self.loader.request_obj_load(path.to_string(), handle.id.0);
50 self.mesh_paths.insert(path.to_string(), handle.clone());
51 handle
52 }
53}
54
55pub fn asset_server_update_system(
56 mut server: crate::core::system::ResMut<AssetServer>,
57 renderer: crate::core::system::ResMut<crate::renderer::Renderer>,
58 mut meshes: crate::core::system::ResMut<crate::core::asset::Assets<Mesh>>,
59) {
60 #[cfg(all(feature = "render", not(target_arch = "wasm32")))]
62 if let Some(watcher) = &server.watcher {
63 let changed = watcher.poll_changes();
64 for path in changed {
65 let path_str = path.to_string_lossy().to_string();
66 if let Some(handle) = server.mesh_paths.get(&path_str) {
68 tracing::info!("AssetWatcher: Reloading mesh {:?}", path_str);
69 server.loader.request_obj_load(path_str.clone(), handle.id.0);
70 }
71 }
72 }
73
74 meshes.process_drops();
76
77 let completed = server.loader.drain_completed();
78
79 server.completed_gltfs.extend(completed.gltfs);
80 server.completed_gltf_errors.extend(completed.gltf_errors);
81 server.completed_textures.extend(completed.textures);
84
85 if completed.objs.is_empty() {
86 return;
87 }
88
89 for obj in completed.objs {
90 let mesh_source = format!("obj:{}", obj.path);
91 let vbuf = renderer
93 .device
94 .create_buffer_init(&wgpu::util::BufferInitDescriptor {
95 label: Some(&format!("Obj VBuf: {}", obj.path)),
96 contents: bytemuck::cast_slice(&obj.vertices),
97 usage: wgpu::BufferUsages::VERTEX,
98 });
99 let mesh = Mesh::new(
100 &renderer.device,
101 std::sync::Arc::new(vbuf),
102 &obj.vertices,
103 gizmo_math::Vec3::ZERO,
104 mesh_source,
105 );
106 for handle_id in obj.handle_ids {
107 let handle = crate::core::asset::Handle::weak(crate::core::asset::HandleId(handle_id));
108 meshes.insert(&handle, mesh.clone());
109 }
110 }
111}
112
113pub struct AssetServerPlugin;
114
115impl<State: 'static> crate::app::Plugin<State> for AssetServerPlugin {
116 fn build(&self, app: &mut crate::app::App<State>) {
117 app.world.insert_resource(AssetServer::new());
118 app.schedule.add_di_system(asset_server_update_system);
119 app.schedule.add_di_system(
124 gizmo_core::system::SystemConfig::new(Box::new(
125 crate::systems::streaming::TextureStreamingSystem,
126 ))
127 .label("texture_streaming"),
128 );
129 }
130}