WIP targeting world objects with mouse click
This commit is contained in:
parent
c12dd41845
commit
a37ba60eaf
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
51
src/hud.rs
51
src/hud.rs
|
@ -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>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue