generalize with generics

This commit is contained in:
yuni 2024-04-05 19:34:01 +02:00
parent d90c2f82a6
commit 4512b63681
2 changed files with 28 additions and 27 deletions

View file

@ -336,33 +336,31 @@ fn apply_input_to_player(
} }
// Find the closest world object that the player is looking at // Find the closest world object that the player is looking at
pub fn find_closest_target( pub fn find_closest_target<TargetSpecifier>(
q_objects: Query<(Entity, &Transform), (With<hud::IsClickable>, Without<hud::IsTargeted>)>, objects: Vec<(TargetSpecifier, &Transform)>,
q_camera: Query<&Transform, With<Camera>>, camera_transform: &Transform,
) -> (Option<Entity>, f32) ) -> (Option<TargetSpecifier>, f32)
{ {
let mut closest_entity: Option<Entity> = None; let mut closest_entity: Option<TargetSpecifier> = None;
let mut closest_distance: f32 = f32::MAX; let mut closest_distance: f32 = f32::MAX;
if let Ok(camtrans) = q_camera.get_single() { let target_vector = (camera_transform.rotation * Vec3::new(0.0, 0.0, -1.0))
let target_vector = (camtrans.rotation * Vec3::new(0.0, 0.0, -1.0)) .normalize_or_zero();
let field_of_view = 20.0f32.to_radians();
let max_angle = field_of_view / 2.0;
for (entity, trans) in objects {
// Use Transform instead of Position because we're basing this
// not on the player mesh but on the camera, which doesn't have a position.
let pos_vector = (trans.translation - camera_transform.translation)
.normalize_or_zero(); .normalize_or_zero();
let field_of_view = 20.0f32.to_radians(); let cosine_of_angle = target_vector.dot(pos_vector);
let max_angle = field_of_view / 2.0; let angle = cosine_of_angle.acos();
for (entity, trans) in &q_objects { if angle <= max_angle {
// Use Transform instead of Position because we're basing this // It's in the field of view!
// not on the player mesh but on the camera, which doesn't have a position. //commands.entity(entity).insert(IsTargeted);
let pos_vector = (trans.translation - camtrans.translation) let distance = trans.translation.distance(camera_transform.translation);
.normalize_or_zero(); if distance < closest_distance {
let cosine_of_angle = target_vector.dot(pos_vector); closest_distance = distance;
let angle = cosine_of_angle.acos(); closest_entity = Some(entity);
if angle <= max_angle {
// It's in the field of view!
//commands.entity(entity).insert(IsTargeted);
let distance = trans.translation.distance(camtrans.translation);
if distance < closest_distance {
closest_distance = distance;
closest_entity = Some(entity);
}
} }
} }
} }

View file

@ -489,7 +489,7 @@ fn update(
// Target display // Target display
let target: Option<DVec3>; let target: Option<DVec3>;
if let Ok((targetpos, actr)) = q_target.get_single() { if let Ok((targetpos, _actr)) = q_target.get_single() {
target = Some(targetpos.0); target = Some(targetpos.0);
} }
else if q_target.is_empty() { else if q_target.is_empty() {
@ -600,8 +600,11 @@ fn handle_input(
if mouse_input.just_pressed(settings.key_selectobject) { if mouse_input.just_pressed(settings.key_selectobject) {
//ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::Switch)); //ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::Switch));
if q_target.is_empty() { if q_target.is_empty() {
if let (Some(entity), _dist) = camera::find_closest_target(q_objects, q_camera) { if let Ok(camtrans) = q_camera.get_single() {
commands.entity(entity).insert(IsTargeted); let objects: Vec<(Entity, &Transform)> = q_objects.iter().collect();
if let (Some(entity), _dist) = camera::find_closest_target::<Entity>(objects, camtrans) {
commands.entity(entity).insert(IsTargeted);
}
} }
} }
else { else {