Separate viewshed updates based on coordinate and visibility_blocked.

This commit is contained in:
Nolan Darilek 2021-05-26 14:57:55 -05:00
parent 3050235926
commit 3084d02f66

View File

@ -23,7 +23,7 @@ pub struct DontLogWhenVisible;
#[reflect(Component)] #[reflect(Component)]
pub struct RevealedTiles(pub Vec<bool>); pub struct RevealedTiles(pub Vec<bool>);
#[derive(Clone, Debug)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct Viewshed { pub struct Viewshed {
pub visible: HashSet<(i32, i32)>, pub visible: HashSet<(i32, i32)>,
pub range: u32, pub range: u32,
@ -100,11 +100,11 @@ pub(crate) fn set_visibility_blocked(
} }
#[derive(Default, Deref, DerefMut)] #[derive(Default, Deref, DerefMut)]
struct PreviousIndex(HashMap<Entity, usize>); struct PrevIndex(HashMap<Entity, usize>);
fn map_visibility_indexing( fn map_visibility_indexing(
mut map: Query<(&Map, &mut VisibilityBlocked)>, mut map: Query<(&Map, &mut VisibilityBlocked)>,
mut prev_index: ResMut<PreviousIndex>, mut prev_index: ResMut<PrevIndex>,
query: Query< query: Query<
(Entity, &Coordinates), (Entity, &Coordinates),
( (
@ -135,7 +135,7 @@ fn map_visibility_indexing(
} }
fn remove_blocks_visibility( fn remove_blocks_visibility(
mut prev_index: ResMut<PreviousIndex>, mut prev_index: ResMut<PrevIndex>,
mut map: Query<(&Map, &mut VisibilityBlocked)>, mut map: Query<(&Map, &mut VisibilityBlocked)>,
removed: RemovedComponents<BlocksVisibility>, removed: RemovedComponents<BlocksVisibility>,
coordinates: Query<&Coordinates>, coordinates: Query<&Coordinates>,
@ -184,14 +184,11 @@ impl InputGrid for VisibilityGrid {
} }
fn update_viewshed( fn update_viewshed(
mut viewers: Query< viewshed: &mut Viewshed,
(&mut Viewshed, &Coordinates), start: &Coordinates,
Or<(Changed<VisibilityBlocked>, Changed<Coordinates>)>, map: &Map,
>, visibility_blocked: &VisibilityBlocked,
map: Query<(&Map, &VisibilityBlocked)>,
) { ) {
for (mut viewshed, start) in viewers.iter_mut() {
for (map, visibility_blocked) in map.iter() {
let mut context: Context<u8> = Context::default(); let mut context: Context<u8> = Context::default();
let vision_distance = vision_distance::Circle::new(viewshed.range); let vision_distance = vision_distance::Circle::new(viewshed.range);
let coord = Coord::new(start.x_i32(), start.y_i32()); let coord = Coord::new(start.x_i32(), start.y_i32());
@ -207,10 +204,69 @@ fn update_viewshed(
viewshed.visible.insert((coord.x, coord.y)); viewshed.visible.insert((coord.x, coord.y));
}, },
); );
}
fn update_viewshed_for_coordinates(
mut viewers: Query<(&mut Viewshed, &Coordinates), Changed<Coordinates>>,
map: Query<(&Map, &VisibilityBlocked)>,
) {
for (mut viewshed, start) in viewers.iter_mut() {
for (map, visibility_blocked) in map.iter() {
update_viewshed(&mut viewshed, start, &map, &visibility_blocked);
} }
} }
} }
#[derive(Clone, Debug, Default, Deref, DerefMut)]
struct PrevVisibilityBlocked(Vec<bool>);
fn visibility_blocked_added(mut prev_visibility_blocked: ResMut<PrevVisibilityBlocked>, added: Query<&VisibilityBlocked, Added<VisibilityBlocked>>) {
for visibility_blocked in added.iter() {
**prev_visibility_blocked = visibility_blocked.to_vec();
}
}
fn visibility_blocked_removed(mut prev_visibility_blocked: ResMut<PrevVisibilityBlocked>, removed: RemovedComponents<VisibilityBlocked>) {
for _ in removed.iter() {
prev_visibility_blocked.clear();
}
}
fn update_viewshed_for_visibility_blocked(
mut prev_visibility_blocked: ResMut<PrevVisibilityBlocked>,
map: Query<(&Map, &VisibilityBlocked), Changed<VisibilityBlocked>>,
mut queryset: QuerySet<(
Query<(Entity, &Viewshed)>,
Query<(&mut Viewshed, &Coordinates)>,
)>,
) {
for (map, visibility_blocked) in map.iter() {
let mut to_check = vec![];
for (index, new) in visibility_blocked.iter().enumerate() {
let changed = if let Some(prev) = prev_visibility_blocked.get(index) {
prev != new
} else {
true
};
if changed {
let coords = (index % map.width(), index / map.width());
for (entity, viewshed) in queryset.q0().iter() {
if viewshed.is_visible(&coords) {
to_check.push(entity);
}
}
}
}
to_check.dedup();
for entity in to_check {
if let Ok((mut viewshed, coordinates)) = queryset.q1_mut().get_mut(entity) {
update_viewshed(&mut viewshed, coordinates, &map, &visibility_blocked);
}
}
**prev_visibility_blocked = visibility_blocked.to_vec();
}
}
fn update_visible_and_revealed_tiles( fn update_visible_and_revealed_tiles(
mut map: Query< mut map: Query<
(&Map, &mut RevealedTiles, &mut VisibleTiles), (&Map, &mut RevealedTiles, &mut VisibleTiles),
@ -301,7 +357,10 @@ impl Plugin for VisibilityPlugin {
const UPDATE_VISIBILITY_INDEX: &str = "UPDATE_VISIBILITY_INDEX"; const UPDATE_VISIBILITY_INDEX: &str = "UPDATE_VISIBILITY_INDEX";
const UPDATE_VIEWSHED: &str = "UPDATE_VIEWSHED"; const UPDATE_VIEWSHED: &str = "UPDATE_VIEWSHED";
const MAP_VISIBILITY: &str = "MAP_VISIBILITY"; const MAP_VISIBILITY: &str = "MAP_VISIBILITY";
app.insert_resource(PreviousIndex::default()) app.init_resource::<PrevVisibilityBlocked>()
.init_resource::<PrevIndex>()
.add_system(visibility_blocked_added.system())
.add_system_to_stage(CoreStage::PostUpdate, visibility_blocked_removed.system())
.add_system(add_visibility_indices.system()) .add_system(add_visibility_indices.system())
.add_system_to_stage( .add_system_to_stage(
CoreStage::PostUpdate, CoreStage::PostUpdate,
@ -324,7 +383,14 @@ impl Plugin for VisibilityPlugin {
) )
.add_system_to_stage( .add_system_to_stage(
CoreStage::PostUpdate, CoreStage::PostUpdate,
update_viewshed update_viewshed_for_coordinates
.system()
.label(UPDATE_VIEWSHED)
.after(UPDATE_VISIBILITY_INDEX),
)
.add_system_to_stage(
CoreStage::PostUpdate,
update_viewshed_for_visibility_blocked
.system() .system()
.label(UPDATE_VIEWSHED) .label(UPDATE_VIEWSHED)
.after(UPDATE_VISIBILITY_INDEX), .after(UPDATE_VISIBILITY_INDEX),