Files
HEDZReloaded/crates/shared/src/utils/billboards.rs

75 lines
2.0 KiB
Rust

use crate::camera::MainCamera;
use bevy::prelude::*;
use bevy_sprite3d::Sprite3dPlugin;
#[derive(Component, Reflect, Default, PartialEq, Eq)]
#[reflect(Component)]
pub enum Billboard {
#[default]
All,
XZ,
}
pub fn plugin(app: &mut App) {
if !app.is_plugin_added::<Sprite3dPlugin>() {
app.add_plugins(Sprite3dPlugin);
}
app.register_type::<Billboard>();
app.add_systems(Update, (face_camera, face_camera_no_parent));
}
fn face_camera(
cam_query: Query<&GlobalTransform, With<MainCamera>>,
mut query: Query<
(&mut Transform, &ChildOf, &InheritedVisibility, &Billboard),
Without<MainCamera>,
>,
parent_transform: Query<&GlobalTransform>,
) {
let Ok(cam_transform) = cam_query.single() else {
return;
};
for (mut transform, parent, visible, billboard) in query.iter_mut() {
if !matches!(*visible, InheritedVisibility::VISIBLE) {
continue;
}
let Ok(parent_global) = parent_transform.get(parent.parent()) else {
continue;
};
let target = cam_transform.reparented_to(parent_global);
let target = match *billboard {
Billboard::All => target.translation,
Billboard::XZ => Vec3::new(
target.translation.x,
transform.translation.y,
target.translation.z,
),
};
transform.look_at(target, Vec3::Y);
}
}
fn face_camera_no_parent(
cam_query: Query<&GlobalTransform, With<MainCamera>>,
mut query: Query<(&mut Transform, &Billboard), (Without<MainCamera>, Without<ChildOf>)>,
) {
let Ok(cam_transform) = cam_query.single() else {
return;
};
for (mut transform, billboard) in query.iter_mut() {
let target = cam_transform.translation();
let target = match *billboard {
Billboard::All => cam_transform.translation(),
Billboard::XZ => Vec3::new(target.x, transform.translation.y, target.z),
};
transform.look_at(target, Vec3::Y);
}
}