gizmo-engine 0.1.7

A custom ECS and physics engine aimed for realistic simulations.
Documentation
use crate::core::asset::Handle;
use crate::renderer::async_assets::AsyncAssetLoader;
use crate::renderer::components::{Material, Mesh};
use wgpu::util::DeviceExt;

pub struct AssetServer {
    pub loader: AsyncAssetLoader,
    mesh_paths: std::collections::HashMap<String, Handle<Mesh>>,
    _material_paths: std::collections::HashMap<String, Handle<Material>>,
    pub completed_gltfs: Vec<crate::renderer::async_assets::GltfImportCompletion>,
    pub completed_gltf_errors: Vec<crate::renderer::async_assets::GltfImportError>,
    #[cfg(all(feature = "render", not(target_arch = "wasm32")))]
    pub watcher: Option<crate::renderer::hot_reload::AssetWatcher>,
}

impl Default for AssetServer {
    fn default() -> Self {
        Self::new()
    }
}

impl AssetServer {
    pub fn new() -> Self {
        #[cfg(all(feature = "render", not(target_arch = "wasm32")))]
        let watcher = crate::renderer::hot_reload::AssetWatcher::new(&["assets", "demo/assets"]);

        Self {
            loader: AsyncAssetLoader::new(),
            mesh_paths: std::collections::HashMap::new(),
            _material_paths: std::collections::HashMap::new(),
            completed_gltfs: Vec::new(),
            completed_gltf_errors: Vec::new(),
            #[cfg(all(feature = "render", not(target_arch = "wasm32")))]
            watcher,
        }
    }

    pub fn load_mesh(&mut self, path: &str) -> Handle<Mesh> {
        if let Some(handle) = self.mesh_paths.get(path) {
            return handle.clone();
        }
        let handle = crate::core::asset::Handle::weak(crate::core::asset::HandleId::new());
        self.loader.request_obj_load(path.to_string(), handle.id.0);
        self.mesh_paths.insert(path.to_string(), handle.clone());
        handle
    }
}

pub fn asset_server_update_system(
    mut server: crate::core::system::ResMut<AssetServer>,
    renderer: crate::core::system::ResMut<crate::renderer::Renderer>,
    mut meshes: crate::core::system::ResMut<crate::core::asset::Assets<Mesh>>,
) {
    // Process Hot Reloading
    #[cfg(all(feature = "render", not(target_arch = "wasm32")))]
    if let Some(watcher) = &server.watcher {
        let changed = watcher.poll_changes();
        for path in changed {
            let path_str = path.to_string_lossy().to_string();
            // Check if mesh needs reloading
            if let Some(handle) = server.mesh_paths.get(&path_str) {
                tracing::info!("AssetWatcher: Reloading mesh {:?}", path_str);
                server.loader.request_obj_load(path_str.clone(), handle.id.0);
            }
        }
    }

    // Process garbage collection
    meshes.process_drops();

    let completed = server.loader.drain_completed();

    server.completed_gltfs.extend(completed.gltfs);
    server.completed_gltf_errors.extend(completed.gltf_errors);

    if completed.objs.is_empty() && completed.textures.is_empty() {
        return;
    }

    for obj in completed.objs {
        let mesh_source = format!("obj:{}", obj.path);
        // Create wgpu buffer
        let vbuf = renderer
            .device
            .create_buffer_init(&wgpu::util::BufferInitDescriptor {
                label: Some(&format!("Obj VBuf: {}", obj.path)),
                contents: bytemuck::cast_slice(&obj.vertices),
                usage: wgpu::BufferUsages::VERTEX,
            });
        let mesh = Mesh::new(
            &renderer.device,
            std::sync::Arc::new(vbuf),
            &obj.vertices,
            gizmo_math::Vec3::ZERO,
            mesh_source,
        );
        for handle_id in obj.handle_ids {
            let handle = crate::core::asset::Handle::weak(crate::core::asset::HandleId(handle_id));
            meshes.insert(&handle, mesh.clone());
        }
    }
}

pub struct AssetServerPlugin;

impl<State: 'static> crate::app::Plugin<State> for AssetServerPlugin {
    fn build(&self, app: &mut crate::app::App<State>) {
        app.world.insert_resource(AssetServer::new());
        app.schedule.add_di_system(asset_server_update_system);
    }
}