diff --git a/src/resource_manager/material_resource_handler.rs b/src/resource_manager/material_resource_handler.rs index 9c4888eb..aa31a317 100644 --- a/src/resource_manager/material_resource_handler.rs +++ b/src/resource_manager/material_resource_handler.rs @@ -75,6 +75,8 @@ impl ResourceHandler for MaterialResourcerHandler { fn can_handle_type(&self, resource_type: &str) -> bool { match resource_type { "json" => true, + "glsl" => true, + "besl" => true, _ => false } } @@ -83,7 +85,9 @@ impl ResourceHandler for MaterialResourcerHandler { file.read_exact(buffers[0].buffer).unwrap(); } - fn process(&self, resource_manager: &ResourceManager, asset_url: &str, bytes: &[u8]) -> Result, String> { + fn process(&self, resource_manager: &ResourceManager, asset_url: &str,) -> Result, String> { + let (bytes, _) = resource_manager.read_asset_from_source(asset_url).unwrap(); + let asset_json = json::parse(std::str::from_utf8(&bytes).unwrap()).unwrap(); let is_material = asset_json["parent"].is_null(); diff --git a/src/resource_manager/mesh_resource_handler.rs b/src/resource_manager/mesh_resource_handler.rs index 60686ee0..f79a637c 100644 --- a/src/resource_manager/mesh_resource_handler.rs +++ b/src/resource_manager/mesh_resource_handler.rs @@ -25,8 +25,8 @@ impl ResourceHandler for MeshResourceHandler { } } - fn process(&self, _: &ResourceManager, asset_url: &str, bytes: &[u8]) -> Result, String> { - let (gltf, buffers, _) = gltf::import_slice(bytes).unwrap(); + fn process(&self, resource_manager: &ResourceManager, asset_url: &str) -> Result, String> { + let (gltf, buffers, _) = gltf::import(resource_manager.realize_asset_path(asset_url).unwrap()).unwrap(); let mut buf: Vec = Vec::with_capacity(4096 * 1024 * 3); @@ -358,6 +358,36 @@ mod tests { } } + #[test] + fn load_local_gltf_mesh_with_external_binaries() { + let mut resource_manager = ResourceManager::new(); + + let (response, _) = resource_manager.get("Suzanne").expect("Failed to get resource"); + + assert_eq!(response.resources.len(), 1); + + let resource_container = &response.resources[0]; + let resource = &resource_container.resource; + + assert_eq!(resource.type_id(), std::any::TypeId::of::()); + + // assert_eq!(buffer.len(), (11808 /* vertices */ * (3 /* components per position */ * 4 /* float size */ + 3/*normals */ * 4) as usize).next_multiple_of(16) + 6/* cube faces */ * 2 /* triangles per face */ * 3 /* indices per triangle */ * 2 /* bytes per index */); + + let mesh = resource.downcast_ref::().unwrap(); + + // assert_eq!(mesh.bounding_box, [[-0.5f32, -0.5f32, -0.5f32], [0.5f32, 0.5f32, 0.5f32]]); + assert_eq!(mesh.vertex_count, 11808); + assert_eq!(mesh.index_count, 3936 * 3); + assert_eq!(mesh.index_type, IntegralTypes::U16); + assert_eq!(mesh.vertex_components.len(), 4); + assert_eq!(mesh.vertex_components[0].semantic, VertexSemantics::Position); + assert_eq!(mesh.vertex_components[0].format, "vec3f"); + assert_eq!(mesh.vertex_components[0].channel, 0); + assert_eq!(mesh.vertex_components[1].semantic, VertexSemantics::Normal); + assert_eq!(mesh.vertex_components[1].format, "vec3f"); + assert_eq!(mesh.vertex_components[1].channel, 1); + } + #[test] fn load_with_manager_buffer() { let mut resource_manager = ResourceManager::new(); diff --git a/src/resource_manager/resource_handler.rs b/src/resource_manager/resource_handler.rs index 9fe81bf7..eed0b9f8 100644 --- a/src/resource_manager/resource_handler.rs +++ b/src/resource_manager/resource_handler.rs @@ -14,7 +14,7 @@ pub trait ResourceHandler { /// - **resource**: The resource data. Can look like anything. /// - **hash**(optional): The resource hash. This is used to identify the resource data. If the resource handler wants to generate a hash for the resource it can do so else the resource manager will generate a hash for it. This is because some resources can generate hashes inteligently (EJ: code generators can output same hash for different looking code if the code is semantically identical). /// - **required_resources**(optional): A list of resources that this resource depends on. This is used to load resources that depend on other resources. - fn process(&self, resource_manager: &resource_manager::ResourceManager, asset_url: &str, bytes: &[u8]) -> Result, String>; + fn process(&self, resource_manager: &resource_manager::ResourceManager, asset_url: &str) -> Result, String>; fn get_deserializers(&self) -> Vec<(&'static str, Box Box + Send>)>; diff --git a/src/resource_manager/resource_manager.rs b/src/resource_manager/resource_manager.rs index 219151ed..7f02216d 100644 --- a/src/resource_manager/resource_manager.rs +++ b/src/resource_manager/resource_manager.rs @@ -190,14 +190,16 @@ impl ResourceManager { documents } else { - let r = self.read_asset_from_source(url).unwrap(); + // let r = self.read_asset_from_source(url).unwrap(); let mut loaded_resource_documents = Vec::new(); - let resource_handlers = self.resource_handlers.iter().filter(|h| h.can_handle_type(r.1.as_str())); + let asset_type = self.get_url_type(url); + + let resource_handlers = self.resource_handlers.iter().filter(|h| h.can_handle_type(&asset_type)); for resource_handler in resource_handlers { - let gg = resource_handler.process(self, url, &r.0).unwrap(); + let gg = resource_handler.process(self, url,).unwrap(); for g in gg { match g { @@ -394,23 +396,11 @@ impl ResourceManager { request.into_reader().read_to_end(&mut source_bytes); }, "local" => { - let path = std::path::Path::new("assets/"); - - let url_as_path = std::path::Path::new(url); - - let url_as_path_parent = url_as_path.parent().ok_or(None)?; - - let path = path.join(url_as_path_parent); + let path = self.realize_asset_path(url).unwrap(); - let (mut file, extension) = if let Ok(dir) = std::fs::read_dir(path) { - let files = dir.filter(|f| if let Ok(f) = f { f.path().file_stem().unwrap().eq(url_as_path.file_name().unwrap()) } else { false }); + let mut file = std::fs::File::open(&path).unwrap(); - let file_path = files.last().ok_or(None)?.or(Err(None))?.path(); - - (std::fs::File::open(&file_path).unwrap(), file_path.extension().unwrap().to_str().unwrap().to_string()) - } else { return Err(None); }; - - format = extension.to_string(); + format = path.extension().unwrap().to_str().unwrap().to_string(); source_bytes = Vec::with_capacity(file.metadata().unwrap().len() as usize); @@ -426,6 +416,63 @@ impl ResourceManager { Ok((source_bytes, format)) } + + pub fn realize_asset_path(&self, url:&str) -> Option { + let path = std::path::Path::new("assets/"); + + let url_as_path = std::path::Path::new(url); + + let url_as_path_parent = url_as_path.parent().or(None)?; + + let path = path.join(url_as_path_parent); + + let path = if let Ok(dir) = std::fs::read_dir(path) { + let files = dir.filter(|f| + if let Ok(f) = f { + let path = if f.path().is_file() { f.path() } else { return false; }; + // Do this to only try loading files that have supported extensions + // Take this case + // Suzanne.gltf Suzanne.bin + // We want to load Suzanne.gltf and not Suzanne.bin + let extension = path.extension().unwrap().to_str().unwrap(); + self.resource_handlers.iter().any(|rm| rm.can_handle_type(extension)) && f.path().file_stem().unwrap().eq(url_as_path.file_name().unwrap()) + } else { + false + } + ); + + let file_path = files.last()?.unwrap().path(); + + file_path + } else { return None; }; + + Some(path) + } + + fn get_url_type(&self, url:&str) -> String { + let origin = if url.starts_with("http://") || url.starts_with("https://") { + "network".to_string() + } else { + "local".to_string() + }; + + match origin.as_str() { + "network" => { + let request = if let Ok(request) = ureq::get(url).call() { request } else { return "unknown".to_string(); }; + let content_type = if let Some(e) = request.header("content-type") { e.to_string() } else { return "unknown".to_string(); }; + content_type + }, + "local" => { + let path = self.realize_asset_path(url).unwrap(); + + path.extension().unwrap().to_str().unwrap().to_string() + }, + _ => { + // Could not resolve how to get raw resource, return empty bytes + return "unknown".to_string(); + } + } + } } // TODO: test resource caching diff --git a/src/resource_manager/texture_resource_handler.rs b/src/resource_manager/texture_resource_handler.rs index 9d02bb78..e896c34d 100644 --- a/src/resource_manager/texture_resource_handler.rs +++ b/src/resource_manager/texture_resource_handler.rs @@ -25,8 +25,9 @@ impl ResourceHandler for ImageResourceHandler { } } - fn process(&self, _: &ResourceManager, asset_url: &str, bytes: &[u8]) -> Result, String> { - let mut decoder = png::Decoder::new(bytes); + fn process(&self, resource_manager: &ResourceManager, asset_url: &str,) -> Result, String> { + let (bytes, _) = resource_manager.read_asset_from_source(asset_url).unwrap(); + let mut decoder = png::Decoder::new(bytes.as_slice()); decoder.set_transformations(png::Transformations::normalize_to_color8()); let mut reader = decoder.read_info().unwrap(); let mut buffer = vec![0; reader.output_buffer_size()];