use gizmo_core::World;
use gizmo_core::component::{MeshSource, MaterialSource};
use crate::components::{Mesh, Material, MeshRenderer};
use crate::asset::AssetManager;
use wgpu::Device;
use wgpu::Queue;
use wgpu::BindGroupLayout;
use std::sync::Arc;
pub fn run_asset_loading_system(
world: &mut World,
device: &Device,
queue: &Queue,
texture_bind_group_layout: &BindGroupLayout,
asset_manager: &mut AssetManager,
) {
let mut missing_meshes = Vec::new();
let mut missing_materials = Vec::new();
{
let mesh_sources = world.borrow::<MeshSource>();
let meshes = world.borrow::<Mesh>();
let material_sources = world.borrow::<MaterialSource>();
let materials = world.borrow::<Material>();
for e in world.iter_alive_entities() {
let id = e.id();
if let Some(src) = mesh_sources.get(id) {
if meshes.get(id).is_none() {
missing_meshes.push((id, src.0.clone()));
}
}
if let Some(src) = material_sources.get(id) {
if materials.get(id).is_none() {
missing_materials.push((id, src.clone()));
}
}
}
}
let default_texture_bind_group = asset_manager.create_white_texture(device, queue, texture_bind_group_layout);
for (id, mesh_src) in missing_meshes {
if let Some(entity) = world.get_entity(id) {
let mesh = if mesh_src == "inverted_cube" {
AssetManager::create_inverted_cube(device)
} else if mesh_src == "plane" {
AssetManager::create_plane(device, 200.0)
} else if mesh_src == "standard_cube" {
AssetManager::create_cube(device)
} else if mesh_src == "sphere" {
AssetManager::create_sphere(device, 1.0, 16, 16)
} else if mesh_src == "sprite_quad" {
AssetManager::create_sprite_quad(device, 1.0, 1.0)
} else if mesh_src.starts_with("gltf_mesh_") {
if let Some(cached) = asset_manager.get_cached_mesh(&mesh_src) {
cached
} else {
let file_path = if let Some(idx) = mesh_src.find(".glb") {
Some(&mesh_src["gltf_mesh_".len()..idx + 4])
} else {
mesh_src.find(".gltf").map(|idx| &mesh_src["gltf_mesh_".len()..idx + 5])
};
if let Some(path) = file_path {
let _ = asset_manager.load_gltf_scene(
device,
queue,
texture_bind_group_layout,
default_texture_bind_group.clone(),
path,
);
if let Some(cached) = asset_manager.get_cached_mesh(&mesh_src) {
cached
} else {
asset_manager.loading_placeholder_mesh(device)
}
} else {
asset_manager.loading_placeholder_mesh(device)
}
}
} else if mesh_src.starts_with("obj:") {
let path = mesh_src.trim_start_matches("obj:");
asset_manager.load_obj(device, path)
} else {
asset_manager.load_obj(device, &mesh_src)
};
world.add_component(entity, mesh);
}
}
for (id, mat_data) in missing_materials {
if let Some(entity) = world.get_entity(id) {
let bind_group = if let Some(tex_path) = &mat_data.texture_source {
asset_manager
.load_material_texture(device, queue, texture_bind_group_layout, tex_path)
.unwrap_or_else(|e| {
tracing::info!("Scene Texture error: {}", e);
default_texture_bind_group.clone()
})
} else {
default_texture_bind_group.clone()
};
let mut mat = Material::new(bind_group);
mat.albedo = gizmo_math::Vec4::from(mat_data.albedo);
mat.roughness = mat_data.roughness;
mat.metallic = mat_data.metallic;
mat.material_type = if mat_data.unlit > 1.5 {
crate::components::MaterialType::Skybox
} else if mat_data.unlit > 0.5 {
crate::components::MaterialType::Unlit
} else {
crate::components::MaterialType::Pbr
};
mat.texture_source = mat_data.texture_source;
world.add_component(entity, mat);
world.add_component(entity, MeshRenderer::new());
}
}
}