diff --git a/Cargo.lock b/Cargo.lock index fd75e965..33c4e477 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1054,6 +1054,15 @@ dependencies = [ "glam", ] +[[package]] +name = "bevy_mod_index" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0576202d36d8d6393b71e34a09e55301a4901825367d7bff35d47104286e4463" +dependencies = [ + "bevy", +] + [[package]] name = "bevy_pbr" version = "0.13.1" @@ -5186,6 +5195,7 @@ dependencies = [ "bevy_app", "bevy_ecs", "bevy_math", + "bevy_mod_index", "bevy_reflect", "bevy_utils", "derive_more", diff --git a/crates/ryot_ray_casting/Cargo.toml b/crates/ryot_ray_casting/Cargo.toml index 0bd22aa7..507b60aa 100644 --- a/crates/ryot_ray_casting/Cargo.toml +++ b/crates/ryot_ray_casting/Cargo.toml @@ -19,6 +19,7 @@ rustdoc-args = ["-Zunstable-options", "--cfg", "docsrs"] all-features = true [dependencies] +bevy_mod_index = "0.4" bevy_app.workspace = true bevy_ecs.workspace = true bevy_math.workspace = true diff --git a/crates/ryot_ray_casting/examples/basic.rs b/crates/ryot_ray_casting/examples/basic.rs index 5bab58b8..5348527f 100644 --- a/crates/ryot_ray_casting/examples/basic.rs +++ b/crates/ryot_ray_casting/examples/basic.rs @@ -21,14 +21,16 @@ fn main() { .add_systems( Update, ( - draw_area_of_interest, - draw_collisions, update_ray_casting, change_area_type, builder.move_obstacles(), - draw_obstacles, ), ) + .add_systems( + Update, + (draw_area_of_interest, draw_collisions, draw_obstacles) + .after(RayCastingSystems::Process), + ) .init_resource::() .run(); } diff --git a/crates/ryot_ray_casting/src/request.rs b/crates/ryot_ray_casting/src/request.rs index 32ec894c..11166e1f 100644 --- a/crates/ryot_ray_casting/src/request.rs +++ b/crates/ryot_ray_casting/src/request.rs @@ -1,5 +1,6 @@ use crate::prelude::*; use bevy_ecs::prelude::*; +use bevy_mod_index::prelude::*; use bevy_utils::HashSet; use ryot_core::prelude::{Navigable, Point}; use std::collections::VecDeque; @@ -209,3 +210,41 @@ pub fn visible_ray_casting(area: RadialArea

) -> RayCasting pub fn walkable_ray_casting(area: RadialArea

) -> RayCasting { RayCasting::::new(area, |_, flags, _pos| flags.is_walkable()) } + +pub struct SharedWith(PhantomData<(T, P)>); + +impl Default for SharedWith { + fn default() -> Self { + Self(PhantomData) + } +} + +impl IndexInfo for SharedWith { + type Component = RayCasting; + type Value = bool; + type Storage = HashmapStorage; + type RefreshPolicy = NoDespawnRefreshPolicy; + + fn value(ray_casting: &RayCasting) -> bool { + !ray_casting.shared_with.is_empty() + } +} + +pub struct StaleRequest(PhantomData<(T, P)>); + +impl Default for StaleRequest { + fn default() -> Self { + Self(PhantomData) + } +} + +impl IndexInfo for StaleRequest { + type Component = RayCasting; + type Value = bool; + type Storage = HashmapStorage; + type RefreshPolicy = NoDespawnRefreshPolicy; + + fn value(ray_casting: &RayCasting) -> bool { + ray_casting.execution_type == ExecutionType::Once && ray_casting.last_executed_at.is_some() + } +} diff --git a/crates/ryot_ray_casting/src/stubs/example_builder.rs b/crates/ryot_ray_casting/src/stubs/example_builder.rs index b9f963b7..e0ee1822 100644 --- a/crates/ryot_ray_casting/src/stubs/example_builder.rs +++ b/crates/ryot_ray_casting/src/stubs/example_builder.rs @@ -9,7 +9,7 @@ use bevy::prelude::{Camera2dBundle, Color, Gizmos, Time, Timer, TimerMode}; use bevy::{DefaultPlugins, MinimalPlugins}; use bevy_app::*; use bevy_ecs::change_detection::{Res, ResMut}; -use bevy_ecs::prelude::{Commands, Component, Local, Query, With}; +use bevy_ecs::prelude::*; use glam::{UVec2, Vec2}; use ryot_core::prelude::*; use ryot_utils::app::OptionalPlugin; diff --git a/crates/ryot_ray_casting/src/systems.rs b/crates/ryot_ray_casting/src/systems.rs index 6c2c8a7b..5e31ec8f 100644 --- a/crates/ryot_ray_casting/src/systems.rs +++ b/crates/ryot_ray_casting/src/systems.rs @@ -3,7 +3,9 @@ //! It leverages RadialAreas to calculate potential intersections and updates //! entities' visible positions accordingly. use crate::prelude::*; +use crate::request::{SharedWith, StaleRequest}; use bevy_ecs::prelude::*; +use bevy_mod_index::prelude::Index; use ryot_core::prelude::Navigable; use ryot_utils::prelude::*; use std::sync::mpsc; @@ -88,14 +90,17 @@ pub fn process_ray_casting< /// requests across multiple entities. pub fn share_results( mut commands: Commands, + mut index: Index>, mut q_propagation: Query<(&RayCasting, &mut RayPropagation)>, mut q_results: Query<&mut RayPropagation, Without>>, ) { let (tx, rx) = mpsc::channel::<(Entity, RayPropagation)>(); - q_propagation.iter().for_each(|(ray_casting, propagation)| { - for shared_entity in &ray_casting.shared_with { - tx.send((*shared_entity, propagation.clone())).ok(); + index.lookup(&true).for_each(|entity| { + if let Ok((ray_casting, propagation)) = q_propagation.get_mut(entity) { + for shared_entity in &ray_casting.shared_with { + tx.send((*shared_entity, propagation.clone())).ok(); + } } }); @@ -126,18 +131,9 @@ pub fn remove_stale_results /// type and last execution time. pub fn remove_stale_requests( mut commands: Commands, - q_ray_casting: Query<(Entity, &RayCasting)>, + mut index: Index>, ) { - q_ray_casting.iter().for_each(|(entity, ray_casting)| { - if ray_casting.last_execution().is_none() { - return; - } - - match ray_casting.execution_type() { - ExecutionType::Once => { - commands.entity(entity).remove::>(); - } - ExecutionType::TimeBased(_) => (), - } + index.lookup(&true).for_each(|entity| { + commands.entity(entity).remove::>(); }); }