WIP targeting world objects with mouse click

This commit is contained in:
yuni 2024-04-05 18:14:12 +02:00
parent c12dd41845
commit a37ba60eaf
4 changed files with 62 additions and 3 deletions

View file

@ -3,7 +3,7 @@ extern crate regex;
use bevy::prelude::*; use bevy::prelude::*;
use bevy_xpbd_3d::prelude::*; use bevy_xpbd_3d::prelude::*;
use bevy::math::DVec3; use bevy::math::DVec3;
use crate::{actor, chat, nature, world}; use crate::{actor, chat, hud, nature, world};
use regex::Regex; use regex::Regex;
use std::f32::consts::PI; use std::f32::consts::PI;
use std::f64::consts::PI as PI64; use std::f64::consts::PI as PI64;
@ -49,6 +49,7 @@ struct ParserState {
is_alive: bool, is_alive: bool,
is_suited: bool, is_suited: bool,
is_vehicle: bool, is_vehicle: bool,
is_clickable: bool,
has_physics: bool, has_physics: bool,
wants_maxrotation: Option<f64>, wants_maxrotation: Option<f64>,
wants_maxvelocity: Option<f64>, wants_maxvelocity: Option<f64>,
@ -102,6 +103,7 @@ impl Default for ParserState {
is_alive: false, is_alive: false,
is_suited: false, is_suited: false,
is_vehicle: false, is_vehicle: false,
is_clickable: true,
has_physics: true, has_physics: true,
wants_maxrotation: None, wants_maxrotation: None,
wants_maxvelocity: None, wants_maxvelocity: None,
@ -263,6 +265,9 @@ pub fn load_defs(
["vehicle", "yes"] => { ["vehicle", "yes"] => {
state.is_vehicle = true; state.is_vehicle = true;
} }
["clickable", "no"] => {
state.is_clickable = false;
}
["moon", "yes"] => { ["moon", "yes"] => {
state.model_scale *= 3.0; state.model_scale *= 3.0;
} }
@ -652,6 +657,9 @@ fn spawn_entities(
..default() ..default()
}); });
} }
if state.is_clickable {
actor.insert(hud::IsClickable);
}
if let Some(value) = state.wants_maxrotation { if let Some(value) = state.wants_maxrotation {
actor.insert(actor::WantsMaxRotation(value)); actor.insert(actor::WantsMaxRotation(value));
} }

View file

@ -21,6 +21,7 @@ actor 0 593051 0 suit
thrust 1.2 1 1 300 1.5 thrust 1.2 1 1 300 1.5
rotationy 0.65 rotationy 0.65
engine monopropellant engine monopropellant
clickable no
actor 10 -30 20 MeteorAceGT actor 10 -30 20 MeteorAceGT
relativeto player relativeto player
@ -32,6 +33,7 @@ actor 10 -30 20 MeteorAceGT
camdistance 50 camdistance 50
mass 3000 mass 3000
angularmomentum 0.1 0.1 0.3 angularmomentum 0.1 0.1 0.3
clickable no
actor 0 0 0 io actor 0 0 0 io
relativeto jupiter relativeto jupiter

View file

@ -2,6 +2,7 @@ use crate::{actor, audio, chat, nature, settings};
use bevy::prelude::*; use bevy::prelude::*;
use bevy::diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin}; use bevy::diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin};
use bevy_xpbd_3d::prelude::*; use bevy_xpbd_3d::prelude::*;
use bevy::math::DVec3;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::time::SystemTime; use std::time::SystemTime;
@ -34,6 +35,8 @@ impl Plugin for HudPlugin {
#[derive(Component)] struct ChatText; #[derive(Component)] struct ChatText;
#[derive(Component)] struct Reticule; #[derive(Component)] struct Reticule;
#[derive(Component)] struct ToggleableHudElement; #[derive(Component)] struct ToggleableHudElement;
#[derive(Component)] pub struct IsClickable;
#[derive(Component)] pub struct IsTargeted;
#[derive(Resource)] #[derive(Resource)]
struct FPSUpdateTimer(Timer); struct FPSUpdateTimer(Timer);
@ -424,6 +427,7 @@ fn update(
mut query_chat: Query<&mut Text, (With<ChatText>, Without<GaugesText>)>, mut query_chat: Query<&mut Text, (With<ChatText>, Without<GaugesText>)>,
query_all_actors: Query<&actor::Actor>, query_all_actors: Query<&actor::Actor>,
settings: Res<settings::Settings>, settings: Res<settings::Settings>,
q_target: Query<&Position, With<IsTargeted>>,
) { ) {
// TODO only when hud is actually on // TODO only when hud is actually on
if timer.0.tick(time.delta()).just_finished() || log.needs_rerendering { if timer.0.tick(time.delta()).just_finished() || log.needs_rerendering {
@ -459,13 +463,31 @@ fn update(
text.sections[13].value = format!("{vitals:.0}%"); text.sections[13].value = format!("{vitals:.0}%");
let all_actors = query_all_actors.iter().len(); let all_actors = query_all_actors.iter().len();
text.sections[15].value = format!("{all_actors:.0}"); text.sections[15].value = format!("{all_actors:.0}");
let (x, y, z) = (pos.x / 1.0e3, pos.y / 1.0e3, pos.z / 1.0e3);
text.sections[7].value = format!("{x:.0}km / {z:.0}km / {y:.0}km");
let integrity = suit.integrity * 100.0; let integrity = suit.integrity * 100.0;
text.sections[17].value = format!("{integrity:.0}%"); text.sections[17].value = format!("{integrity:.0}%");
let speed = cam_v.length(); let speed = cam_v.length();
let kmh = speed * 60.0 * 60.0 / 1000.0; let kmh = speed * 60.0 * 60.0 / 1000.0;
text.sections[19].value = format!("{speed:.0}m/s | {kmh:.0}km/h"); text.sections[19].value = format!("{speed:.0}m/s | {kmh:.0}km/h");
// Target display
let target: Option<DVec3>;
if let Ok(targetpos) = q_target.get_single() {
target = Some(targetpos.0);
}
else if q_target.is_empty() {
target = Some(DVec3::new(0.0, 0.0, 0.0));
}
else {
target = None;
}
if let Some(target_pos) = target {
let dist = pos.0 - target_pos;
let (x, y, z) = (dist.x, dist.y, dist.z);
text.sections[7].value = format!("{x:.0}m / {z:.0}m / {y:.0}m");
}
else {
text.sections[7].value = format!("ERROR: MULTIPLE TARGETS");
}
} }
} }
@ -517,12 +539,17 @@ fn update(
} }
fn handle_input( fn handle_input(
mut commands: Commands,
keyboard_input: Res<ButtonInput<KeyCode>>, keyboard_input: Res<ButtonInput<KeyCode>>,
mouse_input: Res<ButtonInput<MouseButton>>,
mut settings: ResMut<settings::Settings>, mut settings: ResMut<settings::Settings>,
mut q_hud: Query<&mut Visibility, With<ToggleableHudElement>>, mut q_hud: Query<&mut Visibility, With<ToggleableHudElement>>,
mut ew_sfx: EventWriter<audio::PlaySfxEvent>, mut ew_sfx: EventWriter<audio::PlaySfxEvent>,
mut ew_togglemusic: EventWriter<audio::ToggleMusicEvent>, mut ew_togglemusic: EventWriter<audio::ToggleMusicEvent>,
mut ambient_light: ResMut<AmbientLight>, mut ambient_light: ResMut<AmbientLight>,
q_objects: Query<(Entity, &Transform), (With<IsClickable>, Without<IsTargeted>)>,
q_target: Query<Entity, With<IsTargeted>>,
q_camera: Query<&Transform, With<Camera>>,
) { ) {
if keyboard_input.just_pressed(settings.key_togglehud) { if keyboard_input.just_pressed(settings.key_togglehud) {
if settings.hud_active { if settings.hud_active {
@ -542,4 +569,24 @@ fn handle_input(
ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::Switch)); ew_sfx.send(audio::PlaySfxEvent(audio::Sfx::Switch));
ew_togglemusic.send(audio::ToggleMusicEvent()); ew_togglemusic.send(audio::ToggleMusicEvent());
} }
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() {
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.
if trans.translation.distance(camtrans.translation) < 50.0 {
commands.entity(entity).insert(IsTargeted);
break;
}
}
}
}
else {
for entity in &q_target {
commands.entity(entity).remove::<IsTargeted>();
}
}
}
} }

View file

@ -13,6 +13,7 @@ pub struct Settings {
pub font_size_conversations: f32, pub font_size_conversations: f32,
pub hud_active: bool, pub hud_active: bool,
pub third_person: bool, pub third_person: bool,
pub key_selectobject: MouseButton,
pub key_togglehud: KeyCode, pub key_togglehud: KeyCode,
pub key_exit: KeyCode, pub key_exit: KeyCode,
pub key_restart: KeyCode, pub key_restart: KeyCode,
@ -86,6 +87,7 @@ impl Default for Settings {
font_size_conversations: 32.0, font_size_conversations: 32.0,
hud_active: false, hud_active: false,
third_person: false, third_person: false,
key_selectobject: MouseButton::Left,
key_togglehud: KeyCode::Tab, key_togglehud: KeyCode::Tab,
key_exit: KeyCode::Escape, key_exit: KeyCode::Escape,
key_restart: KeyCode::F12, key_restart: KeyCode::F12,