diff --git a/src/visibility.rs b/src/visibility.rs index 097129a..308bd78 100644 --- a/src/visibility.rs +++ b/src/visibility.rs @@ -86,6 +86,12 @@ pub enum VisibilityChanged { Lost { viewer: Entity, viewed: Entity }, } +#[derive(Clone, Debug, Default, Deref, DerefMut)] +struct VisibilityColliderToViewshed(HashMap); + +#[derive(Clone, Debug, Default, Deref, DerefMut)] +struct ViewshedToVisibilityCollider(HashMap); + impl PointLike for Coord { fn x(&self) -> f32 { self.x as f32 @@ -112,49 +118,59 @@ fn add_visibility_indices( } } -fn viewshed_added(mut commands: Commands, query: Query>) { +fn viewshed_added( + mut commands: Commands, + mut collider_to_viewshed: ResMut, + mut viewshed_to_collider: ResMut, + query: Query>, +) { for entity in query.iter() { - let id = commands.spawn().insert(VisibilityCollider).id(); - commands.entity(entity).push_children(&[id]); + let id = commands + .spawn_bundle(ColliderBundle { + collider_type: ColliderType::Sensor, + flags: ColliderFlags { + active_collision_types: ActiveCollisionTypes::all(), + active_events: ActiveEvents::INTERSECTION_EVENTS, + ..Default::default() + }, + ..Default::default() + }) + .insert(VisibilityCollider) + .id(); + viewshed_to_collider.insert(entity, id); + collider_to_viewshed.insert(id, entity); } } fn viewshed_changed( mut commands: Commands, + viewshed_to_collider: Res, query: Query<(Entity, &Viewshed, &RigidBodyPosition), Changed>, mut collider_data: Query< - (&Parent, Entity, Option<&mut ColliderShape>), + (Option<&mut ColliderShape>, Option<&mut ColliderPosition>), With, >, ) { for (entity, viewshed, position) in query.iter() { - for (parent, child_entity, collider_shape) in collider_data.iter_mut() { - if **parent != entity { - continue; - } - if viewshed.visible_points.len() < 2 { - commands.entity(child_entity).remove::(); - } else { - let position = position.position; - let mut points = vec![]; - for p in &viewshed.visible_points { - points.push(point!( - position.translation.x - p.x(), - position.translation.y - p.y() - )); - } - if let Some(shape) = ColliderShape::convex_hull(&points) { - //println!("Shape for {:?}", points); - if let Some(mut collider_shape) = collider_shape { - *collider_shape = shape; - } else { - //println!("Creating collider at {:?}", coordinates.i32()); - commands.entity(child_entity).insert_bundle(ColliderBundle { - collider_type: ColliderType::Sensor, - shape, - flags: ActiveEvents::INTERSECTION_EVENTS.into(), - ..Default::default() - }); + if let Some(collider_entity) = viewshed_to_collider.get(&entity) { + if let Ok((collider_shape, collider_position)) = collider_data.get_mut(*collider_entity) + { + if viewshed.visible_points.len() < 2 { + println!("Too few points, removing"); + commands.entity(*collider_entity).remove::(); + } else { + let translation = position.position.translation; + let mut points = vec![]; + for p in &viewshed.visible_points { + points.push(point!(p.x() - translation.x, p.y() - translation.y)); + } + if let Some(shape) = ColliderShape::convex_hull(&points) { + if let (Some(mut collider_shape), Some(mut collider_position)) = + (collider_shape, collider_position) + { + *collider_shape = shape; + *collider_position = translation.into(); + } } } } @@ -162,37 +178,16 @@ fn viewshed_changed( } } -fn lock_rotation( - mut query: Query<(&Parent, &mut ColliderPosition), With>, - positions: Query<&RigidBodyPosition>, -) { - for (parent, mut position) in query.iter_mut() { - if let Ok(parent_position) = positions.get(**parent) { - let delta = parent_position - .position - .rotation - .angle_to(&UnitComplex::new(0.)); - println!("Syncing: {:?}", delta); - position.rotation = UnitComplex::new(delta); - } - } -} - fn viewshed_removed( - mut commands: Commands, + mut collider_to_viewshed: ResMut, + mut viewshed_to_collider: ResMut, query: RemovedComponents, - children: Query<&Children>, - collider_shapes: Query>, ) { for entity in query.iter() { - if let Ok(children) = children.get(entity) { - for child in children.iter() { - if collider_shapes.get(*child).is_ok() { - commands.entity(*child).despawn_recursive(); - break; - } - } + if let Some(collider) = viewshed_to_collider.get(&entity) { + collider_to_viewshed.remove(&collider); } + viewshed_to_collider.remove(&entity); } } @@ -245,10 +240,9 @@ fn update_viewshed( |handle| { if let Ok(blocks_visibility) = blocks_visibility.get(handle.entity()) { opacity = **blocks_visibility; - false } else { - true } + true }, ); opacity @@ -373,38 +367,35 @@ fn update_visible_and_revealed_tiles( fn intersection( mut events: EventReader, - colliders: Query<&Parent, With>, + collider_to_viewshed: Res, + colliders: Query>, mut viewers: Query<&mut VisibleEntities>, - names: Query<&Name>, - parents: Query<&Parent>, mut visibility_changed: EventWriter, ) { for event in events.iter() { - println!("{:?}", event); if let Some((visibility_collider, other)) = target_and_other(event.collider1.entity(), event.collider2.entity(), |v| { colliders.get(v).is_ok() }) { - if let Ok(parent) = colliders.get(visibility_collider) { - if let Ok(mut visible_entities) = viewers.get_mut(**parent) { + if let Some(viewshed_entity) = collider_to_viewshed.get(&visibility_collider) { + if let Ok(mut visible_entities) = viewers.get_mut(*viewshed_entity) { if event.intersecting { - println!("{:?} is visible: {:?}", other, names.get(other)); - if let Ok(p) = parents.get(other) { - println!("{:?}", names.get(**p)); - } visibility_changed.send(VisibilityChanged::Gained { - viewer: **parent, + viewer: *viewshed_entity, viewed: other, }); visible_entities.insert(other); } else { - println!("{:?} is not visible", other); visibility_changed.send(VisibilityChanged::Lost { - viewer: **parent, + viewer: *viewshed_entity, viewed: other, }); - visible_entities.remove(&other); + if visible_entities.contains(&other) { + visible_entities.remove(&other); + } else { + println!("Making invisible something that was never visible"); + } } } } @@ -413,65 +404,42 @@ fn intersection( } fn log_visible( - time: Res