mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-17 00:13:17 +00:00
Refined rotator gizmo
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
use std::f32::consts;
|
||||
|
||||
use bevy::{prelude::*, window::PrimaryWindow};
|
||||
|
||||
use crate::design_system;
|
||||
@@ -33,10 +35,10 @@ pub(super) fn draw(
|
||||
let dist = Vec3::distance(camera_xform.translation, xform.translation);
|
||||
|
||||
if transform.contains(InteractionTransform::TRANSLATE) {
|
||||
draw_translate_gizmo(&xform, &mut gizmos, space, dist / 14.);
|
||||
draw_translate_gizmo(&xform, &mut gizmos, space, dist / 12.5);
|
||||
}
|
||||
if transform.contains(InteractionTransform::ROTATE) {
|
||||
draw_rotate_gizmo(&xform, &mut gizmos, space, dist / 20.);
|
||||
draw_rotate_gizmo(&xform, camera_xform, &mut gizmos, space, dist / 20.);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,14 +63,55 @@ fn draw_translate_gizmo(xform: &Transform, gizmos: &mut Gizmos, space: Transform
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn draw_rotate_gizmo(xform: &Transform, gizmos: &mut Gizmos, space: TransformSpace, radius: f32) {
|
||||
fn draw_rotate_gizmo(
|
||||
xform: &Transform,
|
||||
camera_xform: &Transform,
|
||||
gizmos: &mut Gizmos,
|
||||
space: TransformSpace,
|
||||
radius: f32,
|
||||
) {
|
||||
let origin = xform.translation;
|
||||
let basis = match space {
|
||||
TransformSpace::Local => xform,
|
||||
TransformSpace::World => &Transform::IDENTITY,
|
||||
};
|
||||
|
||||
gizmos.circle(origin, basis.local_x(), radius, design_system::Color::RED);
|
||||
gizmos.circle(origin, basis.local_y(), radius, design_system::Color::GREEN);
|
||||
gizmos.circle(origin, basis.local_z(), radius, design_system::Color::BLUE);
|
||||
// Draw a screen-space rotator ring
|
||||
gizmos.circle(origin, camera_xform.forward(), radius * 1.2, Color::WHITE);
|
||||
|
||||
// Draw a semicircle for each of the X, Y and Z axes
|
||||
for (normal, color) in [
|
||||
(basis.local_x(), design_system::Color::RED),
|
||||
(basis.local_y(), design_system::Color::GREEN),
|
||||
(basis.local_z(), design_system::Color::BLUE),
|
||||
] {
|
||||
let perp = Vec3::cross(normal, camera_xform.forward()).normalize();
|
||||
let start = origin + perp * radius;
|
||||
|
||||
gizmos.arc(origin, normal, start, consts::PI, color);
|
||||
}
|
||||
}
|
||||
|
||||
trait Arc {
|
||||
/// Draw an arc around `center` with angular `length` (in radians),
|
||||
/// beginning at `point` and progressing counter-clockwise around `axis`
|
||||
/// (if axis were pointed toward the viewer). The radius is derived from the
|
||||
/// distance between `center` and `start`.
|
||||
fn arc(&mut self, center: Vec3, axis: Vec3, start: Vec3, length: f32, color: Color);
|
||||
}
|
||||
|
||||
impl<'a> Arc for Gizmos<'a> {
|
||||
fn arc(&mut self, center: Vec3, normal: Vec3, start: Vec3, length: f32, color: Color) {
|
||||
let two_pi = consts::PI * 2.;
|
||||
let segments = f32::round(32. * (length / two_pi));
|
||||
let angle_inc = length / segments;
|
||||
let rotator = Mat3::from_axis_angle(normal, angle_inc);
|
||||
|
||||
let mut vector = start - center;
|
||||
for _ in 0..(segments as usize) {
|
||||
let next = rotator * vector;
|
||||
self.line(center + vector, center + next, color);
|
||||
vector = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user