use nightshade::prelude::nalgebra_glm::Mat4;
use nightshade::prelude::*;
pub fn bake_navmesh(world: &mut World) {
bake_navmesh_with(world, &RecastNavMeshConfig::default());
}
pub fn bake_navmesh_with(world: &mut World, config: &RecastNavMeshConfig) {
let (vertices, indices) = gather_navmesh_geometry(world);
if let Some(navmesh) = generate_navmesh_recast(&vertices, &indices, config) {
world.resources.navmesh = navmesh;
}
}
fn gather_navmesh_geometry(world: &World) -> (Vec<[f32; 3]>, Vec<[u32; 3]>) {
let mut sources: Vec<(Entity, String, Mat4)> = Vec::new();
for (entity, (render_mesh, global_transform)) in world
.query_ref::<(
&nightshade::ecs::mesh::components::RenderMesh,
&nightshade::ecs::transform::components::GlobalTransform,
)>()
.without_mask(NAVMESH_AGENT | CLOTH)
.iter()
{
sources.push((entity, render_mesh.name.clone(), global_transform.0));
}
let mut vertices: Vec<[f32; 3]> = Vec::new();
let mut indices: Vec<[u32; 3]> = Vec::new();
for (entity, source_mesh_name, matrix) in sources {
if world
.get::<nightshade::ecs::primitives::Visibility>(entity)
.is_some_and(|visibility| !visibility.visible)
{
continue;
}
if world
.get::<nightshade::ecs::primitives::Name>(entity)
.is_some_and(|name| name.0.starts_with(crate::runner::RESERVED_PREFIX))
{
continue;
}
#[cfg(feature = "physics")]
if world
.get::<nightshade::plugins::physics::components::RigidBodyComponent>(entity)
.is_some_and(|body| {
!matches!(
body.body_type,
nightshade::plugins::physics::types::RigidBodyType::Fixed
)
})
{
continue;
}
let Some(mesh) = registry_entry_by_name(
&world.resources.assets.mesh_cache.registry,
&source_mesh_name,
) else {
continue;
};
let base_index = vertices.len() as u32;
for vertex in &mesh.vertices {
let position = matrix
* vec4(
vertex.position[0],
vertex.position[1],
vertex.position[2],
1.0,
);
vertices.push([position.x, position.y, position.z]);
}
for triangle in mesh.indices.chunks_exact(3) {
indices.push([
base_index + triangle[0],
base_index + triangle[1],
base_index + triangle[2],
]);
}
}
(vertices, indices)
}
pub fn spawn_walker(world: &mut World, position: Vec3) -> Entity {
spawn_navmesh_agent(world, position, 3.0)
}
#[inline]
pub fn walk_to(world: &mut World, agent: Entity, destination: Vec3) {
set_agent_destination(world, agent, destination);
}
#[inline]
pub fn set_walk_speed(world: &mut World, agent: Entity, speed: f32) {
set_agent_speed(world, agent, speed);
}
#[inline]
pub fn stop_walking(world: &mut World, agent: Entity) {
stop_agent(world, agent);
}