diff --git a/src/camera.rs b/src/camera.rs index 923b6c7..31da49f 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -8,7 +8,7 @@ use bevy::transform::TransformSystem; use bevy::math::{DVec3, DQuat}; use bevy_xpbd_3d::prelude::*; use std::f32::consts::PI; -use crate::{settings, audio, actor}; +use crate::{actor, audio, hud, settings}; pub struct CameraPlugin; @@ -334,3 +334,37 @@ fn apply_input_to_player( } } } + +// Find the closest world object that the player is looking at +pub fn find_closest_target( + q_objects: Query<(Entity, &Transform), (With, Without)>, + q_camera: Query<&Transform, With>, +) -> (Option, f32) +{ + let mut closest_entity: Option = None; + let mut closest_distance: f32 = f32::MAX; + if let Ok(camtrans) = q_camera.get_single() { + 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 &q_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 - camtrans.translation) + .normalize_or_zero(); + let cosine_of_angle = target_vector.dot(pos_vector); + let angle = cosine_of_angle.acos(); + 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); + } + } + } + } + return (closest_entity, closest_distance); +} diff --git a/src/hud.rs b/src/hud.rs index 5f65c5c..e25b36a 100644 --- a/src/hud.rs +++ b/src/hud.rs @@ -1,4 +1,4 @@ -use crate::{actor, audio, chat, nature, settings}; +use crate::{actor, audio, camera, chat, nature, settings}; use bevy::prelude::*; use bevy::diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin}; use bevy_xpbd_3d::prelude::*; @@ -600,35 +600,8 @@ fn handle_input( if mouse_input.just_pressed(settings.key_selectobject) { //ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::Switch)); if q_target.is_empty() { - if let Ok(camtrans) = q_camera.get_single() { - let mut closest_entity: Option = None; - let mut closest_distance: f32 = f32::MAX; - 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; - let max_cosine_of_angle = max_angle.cos(); - //let maximum_cosine_of_angle = (field_of_view / 2.0).cos(); - for (entity, trans) in &q_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 - camtrans.translation) - .normalize_or_zero(); - let cosine_of_angle = target_vector.dot(pos_vector); - let angle = cosine_of_angle.acos(); - 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); - } - } - } - if let Some(entity) = closest_entity { - commands.entity(entity).insert(IsTargeted); - } + if let (Some(entity), _dist) = camera::find_closest_target(q_objects, q_camera) { + commands.entity(entity).insert(IsTargeted); } } else {