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)]
pub struct RevealedTiles(pub Vec<bool>);
#[derive(Clone, Debug)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Viewshed {
pub visible: HashSet<(i32, i32)>,
pub range: u32,
@ -100,11 +100,11 @@ pub(crate) fn set_visibility_blocked(
}
#[derive(Default, Deref, DerefMut)]
struct PreviousIndex(HashMap<Entity, usize>);
struct PrevIndex(HashMap<Entity, usize>);
fn map_visibility_indexing(
mut map: Query<(&Map, &mut VisibilityBlocked)>,
mut prev_index: ResMut<PreviousIndex>,
mut prev_index: ResMut<PrevIndex>,
query: Query<
(Entity, &Coordinates),
(
@ -135,7 +135,7 @@ fn map_visibility_indexing(
}
fn remove_blocks_visibility(
mut prev_index: ResMut<PreviousIndex>,
mut prev_index: ResMut<PrevIndex>,
mut map: Query<(&Map, &mut VisibilityBlocked)>,
removed: RemovedComponents<BlocksVisibility>,
coordinates: Query<&Coordinates>,
@ -184,33 +184,89 @@ impl InputGrid for VisibilityGrid {
}
fn update_viewshed(
mut viewers: Query<
(&mut Viewshed, &Coordinates),
Or<(Changed<VisibilityBlocked>, Changed<Coordinates>)>,
>,
viewshed: &mut Viewshed,
start: &Coordinates,
map: &Map,
visibility_blocked: &VisibilityBlocked,
) {
let mut context: Context<u8> = Context::default();
let vision_distance = vision_distance::Circle::new(viewshed.range);
let coord = Coord::new(start.x_i32(), start.y_i32());
viewshed.visible.clear();
let visibility_grid = VisibilityGrid(map.clone(), visibility_blocked.clone());
context.for_each_visible(
coord,
&visibility_grid,
&visibility_grid,
vision_distance,
255,
|coord, _directions, _visibility| {
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() {
let mut context: Context<u8> = Context::default();
let vision_distance = vision_distance::Circle::new(viewshed.range);
let coord = Coord::new(start.x_i32(), start.y_i32());
viewshed.visible.clear();
let visibility_grid = VisibilityGrid(map.clone(), visibility_blocked.clone());
context.for_each_visible(
coord,
&visibility_grid,
&visibility_grid,
vision_distance,
255,
|coord, _directions, _visibility| {
viewshed.visible.insert((coord.x, coord.y));
},
);
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(
mut map: Query<
(&Map, &mut RevealedTiles, &mut VisibleTiles),
@ -301,7 +357,10 @@ impl Plugin for VisibilityPlugin {
const UPDATE_VISIBILITY_INDEX: &str = "UPDATE_VISIBILITY_INDEX";
const UPDATE_VIEWSHED: &str = "UPDATE_VIEWSHED";
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_to_stage(
CoreStage::PostUpdate,
@ -324,7 +383,14 @@ impl Plugin for VisibilityPlugin {
)
.add_system_to_stage(
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()
.label(UPDATE_VIEWSHED)
.after(UPDATE_VISIBILITY_INDEX),