Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: experiment with bevy-mod-index #118

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/ryot_ray_casting/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 5 additions & 3 deletions crates/ryot_ray_casting/examples/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<AreaType>()
.run();
}
Expand Down
39 changes: 39 additions & 0 deletions crates/ryot_ray_casting/src/request.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -209,3 +210,41 @@ pub fn visible_ray_casting<T, P: Point>(area: RadialArea<P>) -> RayCasting<T, P>
pub fn walkable_ray_casting<T, P: Point>(area: RadialArea<P>) -> RayCasting<T, P> {
RayCasting::<T, P>::new(area, |_, flags, _pos| flags.is_walkable())
}

pub struct SharedWith<T, P>(PhantomData<(T, P)>);

impl<T, P> Default for SharedWith<T, P> {
fn default() -> Self {
Self(PhantomData)
}
}

impl<T: Send + Sync + 'static, P: Send + Sync + 'static> IndexInfo for SharedWith<T, P> {
type Component = RayCasting<T, P>;
type Value = bool;
type Storage = HashmapStorage<Self>;
type RefreshPolicy = NoDespawnRefreshPolicy;

fn value(ray_casting: &RayCasting<T, P>) -> bool {
!ray_casting.shared_with.is_empty()
}
}

pub struct StaleRequest<T, P>(PhantomData<(T, P)>);

impl<T, P> Default for StaleRequest<T, P> {
fn default() -> Self {
Self(PhantomData)
}
}

impl<T: Send + Sync + 'static, P: Send + Sync + 'static> IndexInfo for StaleRequest<T, P> {
type Component = RayCasting<T, P>;
type Value = bool;
type Storage = HashmapStorage<Self>;
type RefreshPolicy = NoDespawnRefreshPolicy;

fn value(ray_casting: &RayCasting<T, P>) -> bool {
ray_casting.execution_type == ExecutionType::Once && ray_casting.last_executed_at.is_some()
}
}
2 changes: 1 addition & 1 deletion crates/ryot_ray_casting/src/stubs/example_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
26 changes: 11 additions & 15 deletions crates/ryot_ray_casting/src/systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -88,14 +90,17 @@ pub fn process_ray_casting<
/// requests across multiple entities.
pub fn share_results<T: Copy + Send + Sync + 'static, P: RayCastingPoint>(
mut commands: Commands,
mut index: Index<SharedWith<T, P>>,
mut q_propagation: Query<(&RayCasting<T, P>, &mut RayPropagation<T, P>)>,
mut q_results: Query<&mut RayPropagation<T, P>, Without<RayCasting<T, P>>>,
) {
let (tx, rx) = mpsc::channel::<(Entity, RayPropagation<T, P>)>();

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();
}
}
});

Expand Down Expand Up @@ -126,18 +131,9 @@ pub fn remove_stale_results<T: Copy + Send + Sync + 'static, P: RayCastingPoint>
/// type and last execution time.
pub fn remove_stale_requests<T: Copy + Send + Sync + 'static, P: RayCastingPoint>(
mut commands: Commands,
q_ray_casting: Query<(Entity, &RayCasting<T, P>)>,
mut index: Index<StaleRequest<T, P>>,
) {
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::<RayCasting<T, P>>();
}
ExecutionType::TimeBased(_) => (),
}
index.lookup(&true).for_each(|entity| {
commands.entity(entity).remove::<RayCasting<T, P>>();
});
}
Loading