use crate::prelude::*;
use bevy_app::prelude::*;
use bevy_ecs::prelude::*;
use bevy_gizmos::prelude::*;
use bevy_math::prelude::*;
use bevy_reflect::prelude::*;
use bevy_render::prelude::*;
use bevy_transform::prelude::*;
pub struct AnchorIndicatorPlugin;
impl Plugin for AnchorIndicatorPlugin {
fn build(&self, app: &mut App) {
app.add_systems(
PostUpdate,
draw_anchor
.after(bevy_transform::TransformSystem::TransformPropagate)
.after(bevy_render::camera::CameraUpdateSystem),
)
.register_type::<AnchorIndicator>();
}
}
#[derive(Debug, Component, Reflect)]
pub struct AnchorIndicator {
pub enabled: bool,
}
impl Default for AnchorIndicator {
fn default() -> Self {
Self { enabled: true }
}
}
pub fn draw_anchor(
cameras: Query<(
&EditorCam,
&GlobalTransform,
&Camera,
Option<&AnchorIndicator>,
)>,
mut gizmos: Gizmos,
) {
for (editor_cam, cam_transform, cam, _) in cameras
.iter()
.filter(|(.., anchor_indicator)| anchor_indicator.map(|a| a.enabled).unwrap_or(true))
{
let Some(anchor_world) = editor_cam.anchor_world_space(cam_transform) else {
continue;
};
let p1 = cam
.world_to_viewport(cam_transform, anchor_world.as_vec3())
.unwrap_or_default();
let p2 = cam
.world_to_viewport(
cam_transform,
anchor_world.as_vec3() + cam_transform.right(),
)
.unwrap_or_default();
let scale = 8.0 / (p2 - p1).length();
let shift = (cam_transform.translation() - anchor_world.as_vec3()).normalize() * scale;
let anchor_world = anchor_world.as_vec3() + shift;
if editor_cam.current_motion.is_orbiting() {
let gizmo_color = || Color::rgb(1.0, 1.0, 1.0);
let arm_length = 0.4;
gizmos.circle(
anchor_world,
Direction3d::new_unchecked(cam_transform.forward().normalize()),
scale,
gizmo_color(),
);
let offset = 1.5 * scale;
gizmos.ray(
anchor_world + offset * cam_transform.left(),
offset * arm_length * cam_transform.left(),
gizmo_color(),
);
gizmos.ray(
anchor_world + offset * cam_transform.right(),
offset * arm_length * cam_transform.right(),
gizmo_color(),
);
gizmos.ray(
anchor_world + offset * cam_transform.up(),
offset * arm_length * cam_transform.up(),
gizmo_color(),
);
gizmos.ray(
anchor_world + offset * cam_transform.down(),
offset * arm_length * cam_transform.down(),
gizmo_color(),
);
}
}
}