More gizmos builders (#13261)

# Objective

- Add GizmoBuilders for some primitives as discussed in #13233

## Solution

- `gizmos.primitive_2d(CIRCLE)` and `gizmos.primitive_2d(ELLIPSE)` now
return `Ellipse2dBuilder` aswell.
- `gizmos.primitive_3d(SPHERE)` and `gizmos.sphere()` now return the
same `SphereBuilder`.
- the `.circle_segments` method on the `SphereBuilder` that used to be
returned by `.sphere()` is now called `.segments`
  - the sphere primitive gizmo now matches the `gizmos.sphere` gizmo
- `gizmos.primitive_2d(ANNULUS)` now returns a `Annulus2dBuilder`
allowing the configuration of the `segments`
- gizmos cylinders and capsules now have only 1 line per axis, similar
to `gizmos.sphere`

## Migration Guide

- Some `gizmos.primitive_nd` methods now return some or different
builders. You may need to adjust types and match statements
- Replace any calls to `circle_segments()` with `.segments()`

---------

Co-authored-by: Raphael Büttgenbach <62256001+solis-lumine-vorago@users.noreply.github.com>
This commit is contained in:
Lynn 2024-06-03 18:10:14 +02:00 committed by GitHub
parent cca4fc76de
commit e6a0f75a63
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 259 additions and 285 deletions

View File

@ -178,6 +178,45 @@ where
resolution: DEFAULT_CIRCLE_RESOLUTION, resolution: DEFAULT_CIRCLE_RESOLUTION,
} }
} }
/// Draw a wireframe sphere in 3D made out of 3 circles around the axes.
///
/// This should be called for each frame the sphere needs to be rendered.
///
/// # Example
/// ```
/// # use bevy_gizmos::prelude::*;
/// # use bevy_render::prelude::*;
/// # use bevy_math::prelude::*;
/// # use bevy_color::Color;
/// fn system(mut gizmos: Gizmos) {
/// gizmos.sphere(Vec3::ZERO, Quat::IDENTITY, 1., Color::BLACK);
///
/// // Each circle has 32 line-segments by default.
/// // You may want to increase this for larger spheres.
/// gizmos
/// .sphere(Vec3::ZERO, Quat::IDENTITY, 5., Color::BLACK)
/// .resolution(64);
/// }
/// # bevy_ecs::system::assert_is_system(system);
/// ```
#[inline]
pub fn sphere(
&mut self,
position: Vec3,
rotation: Quat,
radius: f32,
color: impl Into<Color>,
) -> SphereBuilder<'_, 'w, 's, Config, Clear> {
SphereBuilder {
gizmos: self,
radius,
position,
rotation,
color: color.into(),
resolution: DEFAULT_CIRCLE_RESOLUTION,
}
}
} }
/// A builder returned by [`Gizmos::ellipse`]. /// A builder returned by [`Gizmos::ellipse`].
@ -266,3 +305,66 @@ where
self.gizmos.linestrip_2d(positions, self.color); self.gizmos.linestrip_2d(positions, self.color);
} }
} }
/// Builder for configuring the drawing options of [`Sphere`].
pub struct SphereBuilder<'a, 'w, 's, Config, Clear>
where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
{
gizmos: &'a mut Gizmos<'w, 's, Config, Clear>,
// Radius of the sphere
radius: f32,
// Rotation of the sphere around the origin in 3D space
rotation: Quat,
// Center position of the sphere in 3D space
position: Vec3,
// Color of the sphere
color: Color,
// Number of line-segments used to approximate the sphere geometry
resolution: usize,
}
impl<Config, Clear> SphereBuilder<'_, '_, '_, Config, Clear>
where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
{
/// Set the number of line-segments used to approximate the sphere geometry.
pub fn resolution(mut self, resolution: usize) -> Self {
self.resolution = resolution;
self
}
}
impl<Config, Clear> Drop for SphereBuilder<'_, '_, '_, Config, Clear>
where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
{
fn drop(&mut self) {
if !self.gizmos.enabled {
return;
}
let SphereBuilder {
radius,
position: center,
rotation,
color,
resolution,
..
} = self;
// draws one great circle around each of the local axes
Vec3::AXES.into_iter().for_each(|axis| {
let normal = *rotation * axis;
self.gizmos
.circle(*center, Dir3::new_unchecked(normal), *radius, *color)
.resolution(*resolution);
});
}
}

View File

@ -2,14 +2,13 @@
use std::{iter, marker::PhantomData, mem}; use std::{iter, marker::PhantomData, mem};
use crate::circles::DEFAULT_CIRCLE_RESOLUTION;
use bevy_color::{Color, LinearRgba}; use bevy_color::{Color, LinearRgba};
use bevy_ecs::{ use bevy_ecs::{
component::Tick, component::Tick,
system::{Deferred, ReadOnlySystemParam, Res, Resource, SystemBuffer, SystemMeta, SystemParam}, system::{Deferred, ReadOnlySystemParam, Res, Resource, SystemBuffer, SystemMeta, SystemParam},
world::{unsafe_world_cell::UnsafeWorldCell, World}, world::{unsafe_world_cell::UnsafeWorldCell, World},
}; };
use bevy_math::{Dir3, Quat, Rotation2d, Vec2, Vec3}; use bevy_math::{Quat, Rotation2d, Vec2, Vec3};
use bevy_transform::TransformPoint; use bevy_transform::TransformPoint;
use bevy_utils::default; use bevy_utils::default;
@ -459,45 +458,6 @@ where
strip_colors.push(LinearRgba::NAN); strip_colors.push(LinearRgba::NAN);
} }
/// Draw a wireframe sphere in 3D made out of 3 circles around the axes.
///
/// This should be called for each frame the sphere needs to be rendered.
///
/// # Example
/// ```
/// # use bevy_gizmos::prelude::*;
/// # use bevy_render::prelude::*;
/// # use bevy_math::prelude::*;
/// # use bevy_color::Color;
/// fn system(mut gizmos: Gizmos) {
/// gizmos.sphere(Vec3::ZERO, Quat::IDENTITY, 1., Color::BLACK);
///
/// // Each circle has 32 line-segments by default.
/// // You may want to increase this for larger spheres.
/// gizmos
/// .sphere(Vec3::ZERO, Quat::IDENTITY, 5., Color::BLACK)
/// .resolution(64);
/// }
/// # bevy_ecs::system::assert_is_system(system);
/// ```
#[inline]
pub fn sphere(
&mut self,
position: Vec3,
rotation: Quat,
radius: f32,
color: impl Into<Color>,
) -> SphereBuilder<'_, 'w, 's, Config, Clear> {
SphereBuilder {
gizmos: self,
position,
rotation: rotation.normalize(),
radius,
color: color.into(),
resolution: DEFAULT_CIRCLE_RESOLUTION,
}
}
/// Draw a wireframe rectangle in 3D. /// Draw a wireframe rectangle in 3D.
/// ///
/// This should be called for each frame the rectangle needs to be rendered. /// This should be called for each frame the rectangle needs to be rendered.
@ -790,49 +750,6 @@ where
} }
} }
/// A builder returned by [`Gizmos::sphere`].
pub struct SphereBuilder<'a, 'w, 's, Config, Clear = ()>
where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
{
gizmos: &'a mut Gizmos<'w, 's, Config, Clear>,
position: Vec3,
rotation: Quat,
radius: f32,
color: Color,
resolution: usize,
}
impl<Config, Clear> SphereBuilder<'_, '_, '_, Config, Clear>
where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
{
/// Set the number of line-segments per circle for this sphere.
pub fn resolution(mut self, resolution: usize) -> Self {
self.resolution = resolution;
self
}
}
impl<Config, Clear> Drop for SphereBuilder<'_, '_, '_, Config, Clear>
where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
{
fn drop(&mut self) {
if !self.gizmos.enabled {
return;
}
for axis in Dir3::AXES {
self.gizmos
.circle(self.position, self.rotation * axis, self.radius, self.color)
.resolution(self.resolution);
}
}
}
fn rect_inner(size: Vec2) -> [Vec2; 4] { fn rect_inner(size: Vec2) -> [Vec2; 4] {
let half_size = size / 2.; let half_size = size / 2.;
let tl = Vec2::new(-half_size.x, half_size.y); let tl = Vec2::new(-half_size.x, half_size.y);

View File

@ -102,7 +102,7 @@ where
Config: GizmoConfigGroup, Config: GizmoConfigGroup,
Clear: 'static + Send + Sync, Clear: 'static + Send + Sync,
{ {
type Output<'a> = () where Self: 'a; type Output<'a> = crate::circles::Ellipse2dBuilder<'a, 'w, 's, Config, Clear> where Self: 'a;
fn primitive_2d( fn primitive_2d(
&mut self, &mut self,
@ -111,11 +111,7 @@ where
_angle: f32, _angle: f32,
color: impl Into<Color>, color: impl Into<Color>,
) -> Self::Output<'_> { ) -> Self::Output<'_> {
if !self.enabled { self.circle_2d(position, primitive.radius, color)
return;
}
self.circle_2d(position, primitive.radius, color);
} }
} }
@ -205,46 +201,114 @@ where
Config: GizmoConfigGroup, Config: GizmoConfigGroup,
Clear: 'static + Send + Sync, Clear: 'static + Send + Sync,
{ {
type Output<'a> = () where Self: 'a; type Output<'a> = crate::circles::Ellipse2dBuilder<'a, 'w, 's, Config, Clear> where Self: 'a;
fn primitive_2d( fn primitive_2d<'a>(
&mut self, &mut self,
primitive: &Ellipse, primitive: &Ellipse,
position: Vec2, position: Vec2,
angle: f32, angle: f32,
color: impl Into<Color>, color: impl Into<Color>,
) -> Self::Output<'_> { ) -> Self::Output<'_> {
if !self.enabled { self.ellipse_2d(position, angle, primitive.half_size, color)
return;
}
self.ellipse_2d(position, angle, primitive.half_size, color);
} }
} }
// annulus 2d // annulus 2d
/// Builder for configuring the drawing options of [`Annulus`].
pub struct Annulus2dBuilder<'a, 'w, 's, Config, Clear>
where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
{
gizmos: &'a mut Gizmos<'w, 's, Config, Clear>,
position: Vec2,
inner_radius: f32,
outer_radius: f32,
color: Color,
inner_resolution: usize,
outer_resolution: usize,
}
impl<Config, Clear> Annulus2dBuilder<'_, '_, '_, Config, Clear>
where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
{
/// Set the number of line-segments for each circle of the annulus.
pub fn resolution(mut self, resolution: usize) -> Self {
self.outer_resolution = resolution;
self.inner_resolution = resolution;
self
}
/// Set the number of line-segments for the outer circle of the annulus.
pub fn outer_resolution(mut self, resolution: usize) -> Self {
self.outer_resolution = resolution;
self
}
/// Set the number of line-segments for the inner circle of the annulus.
pub fn inner_resolution(mut self, resolution: usize) -> Self {
self.inner_resolution = resolution;
self
}
}
impl<'w, 's, Config, Clear> GizmoPrimitive2d<Annulus> for Gizmos<'w, 's, Config, Clear> impl<'w, 's, Config, Clear> GizmoPrimitive2d<Annulus> for Gizmos<'w, 's, Config, Clear>
where where
Config: GizmoConfigGroup, Config: GizmoConfigGroup,
Clear: 'static + Send + Sync, Clear: 'static + Send + Sync,
{ {
type Output<'a> = () where Self: 'a; type Output<'a> = Annulus2dBuilder<'a, 'w, 's, Config, Clear> where Self: 'a;
fn primitive_2d( fn primitive_2d(
&mut self, &mut self,
primitive: &Annulus, primitive: &Annulus,
position: Vec2, position: Vec2,
angle: f32, _angle: f32,
color: impl Into<Color>, color: impl Into<Color>,
) -> Self::Output<'_> { ) -> Self::Output<'_> {
if !self.enabled { Annulus2dBuilder {
gizmos: self,
position,
inner_radius: primitive.inner_circle.radius,
outer_radius: primitive.outer_circle.radius,
color: color.into(),
inner_resolution: crate::circles::DEFAULT_CIRCLE_RESOLUTION,
outer_resolution: crate::circles::DEFAULT_CIRCLE_RESOLUTION,
}
}
}
impl<Config, Clear> Drop for Annulus2dBuilder<'_, '_, '_, Config, Clear>
where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
{
fn drop(&mut self) {
if !self.gizmos.enabled {
return; return;
} }
let color = color.into(); let Annulus2dBuilder {
self.primitive_2d(&primitive.inner_circle, position, angle, color); gizmos,
self.primitive_2d(&primitive.outer_circle, position, angle, color); position,
inner_radius,
outer_radius,
inner_resolution,
outer_resolution,
color,
..
} = self;
gizmos
.circle_2d(*position, *outer_radius, *color)
.resolution(*outer_resolution);
gizmos
.circle_2d(*position, *inner_radius, *color)
.resolution(*inner_resolution);
} }
} }
@ -266,8 +330,7 @@ where
) -> Self::Output<'_> { ) -> Self::Output<'_> {
if !self.enabled { if !self.enabled {
return; return;
} };
let [a, b, c, d] = let [a, b, c, d] =
[(1.0, 0.0), (0.0, 1.0), (-1.0, 0.0), (0.0, -1.0)].map(|(sign_x, sign_y)| { [(1.0, 0.0), (0.0, 1.0), (-1.0, 0.0), (0.0, -1.0)].map(|(sign_x, sign_y)| {
Vec2::new( Vec2::new(

View File

@ -1,7 +1,7 @@
//! A module for rendering each of the 3D [`bevy_math::primitives`] with [`Gizmos`]. //! A module for rendering each of the 3D [`bevy_math::primitives`] with [`Gizmos`].
use super::helpers::*; use super::helpers::*;
use std::f32::consts::TAU; use std::f32::consts::{FRAC_PI_2, PI, TAU};
use bevy_color::Color; use bevy_color::Color;
use bevy_math::primitives::{ use bevy_math::primitives::{
@ -10,6 +10,7 @@ use bevy_math::primitives::{
}; };
use bevy_math::{Dir3, Quat, Vec3}; use bevy_math::{Dir3, Quat, Vec3};
use crate::circles::SphereBuilder;
use crate::prelude::{GizmoConfigGroup, Gizmos}; use crate::prelude::{GizmoConfigGroup, Gizmos};
const DEFAULT_RESOLUTION: usize = 5; const DEFAULT_RESOLUTION: usize = 5;
@ -55,41 +56,6 @@ where
// sphere // sphere
/// Builder for configuring the drawing options of [`Sphere`].
pub struct SphereBuilder<'a, 'w, 's, Config, Clear>
where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
{
gizmos: &'a mut Gizmos<'w, 's, Config, Clear>,
// Radius of the sphere
radius: f32,
// Rotation of the sphere around the origin in 3D space
rotation: Quat,
// Center position of the sphere in 3D space
position: Vec3,
// Color of the sphere
color: Color,
// Resolution of the gizmos used to approximate the sphere geometry
// The number of vertices used to approximate the sphere geometry.
resolution: usize,
}
impl<Config, Clear> SphereBuilder<'_, '_, '_, Config, Clear>
where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
{
/// Set the number of lines used to approximate the sphere geometry.
pub fn resolution(mut self, resolution: usize) -> Self {
self.resolution = resolution;
self
}
}
impl<'w, 's, Config, Clear> GizmoPrimitive3d<Sphere> for Gizmos<'w, 's, Config, Clear> impl<'w, 's, Config, Clear> GizmoPrimitive3d<Sphere> for Gizmos<'w, 's, Config, Clear>
where where
Config: GizmoConfigGroup, Config: GizmoConfigGroup,
@ -104,59 +70,7 @@ where
rotation: Quat, rotation: Quat,
color: impl Into<Color>, color: impl Into<Color>,
) -> Self::Output<'_> { ) -> Self::Output<'_> {
SphereBuilder { self.sphere(position, rotation, primitive.radius, color)
gizmos: self,
radius: primitive.radius,
position,
rotation,
color: color.into(),
resolution: DEFAULT_RESOLUTION,
}
}
}
impl<Config, Clear> Drop for SphereBuilder<'_, '_, '_, Config, Clear>
where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
{
fn drop(&mut self) {
if !self.gizmos.enabled {
return;
}
let SphereBuilder {
radius,
position: center,
rotation,
color,
resolution,
..
} = self;
// draws the upper and lower semi spheres
[-1.0, 1.0].into_iter().for_each(|sign| {
let top = *center + (*rotation * Vec3::Y) * sign * *radius;
draw_semi_sphere(
self.gizmos,
*radius,
*resolution,
*rotation,
*center,
top,
*color,
);
});
// draws one great circle of the sphere
draw_circle_3d(
self.gizmos,
*radius,
*resolution,
*rotation,
*center,
*color,
);
} }
} }
@ -578,30 +492,27 @@ where
resolution, resolution,
} = self; } = self;
let normal = *rotation * Vec3::Y; let normal = Dir3::new_unchecked(*rotation * Vec3::Y);
let up = normal.as_vec3() * *half_height;
// draw upper and lower circle of the cylinder // draw upper and lower circle of the cylinder
[-1.0, 1.0].into_iter().for_each(|sign| { [-1.0, 1.0].into_iter().for_each(|sign| {
draw_circle_3d( gizmos
gizmos, .circle(*position + sign * up, normal, *radius, *color)
*radius, .resolution(*resolution);
*resolution,
*rotation,
*position + sign * *half_height * normal,
*color,
);
}); });
// draw lines connecting the two cylinder circles // draw lines connecting the two cylinder circles
draw_cylinder_vertical_lines( [Vec3::NEG_X, Vec3::NEG_Z, Vec3::X, Vec3::Z]
gizmos, .into_iter()
*radius, .for_each(|axis| {
*resolution, let axis = *rotation * axis;
*half_height, gizmos.line(
*rotation, *position + up + axis * *radius,
*position, *position - up + axis * *radius,
*color, *color,
); );
});
} }
} }
@ -691,26 +602,57 @@ where
resolution, resolution,
} = self; } = self;
let normal = *rotation * Vec3::Y; // Draw the circles at the top and bottom of the cylinder
let y_offset = *rotation * Vec3::Y;
gizmos
.circle(
*position + y_offset * *half_length,
Dir3::new_unchecked(y_offset),
*radius,
*color,
)
.resolution(*resolution);
gizmos
.circle(
*position - y_offset * *half_length,
Dir3::new_unchecked(y_offset),
*radius,
*color,
)
.resolution(*resolution);
let y_offset = y_offset * *half_length;
// draw two semi spheres for the capsule // Draw the vertical lines and the cap semicircles
[1.0, -1.0].into_iter().for_each(|sign| { [Vec3::X, Vec3::Z].into_iter().for_each(|axis| {
let center = *position + sign * *half_length * normal; let normal = *rotation * axis;
let top = center + sign * *radius * normal;
draw_semi_sphere(gizmos, *radius, *resolution, *rotation, center, top, *color); gizmos.line(
draw_circle_3d(gizmos, *radius, *resolution, *rotation, center, *color); *position + normal * *radius + y_offset,
*position + normal * *radius - y_offset,
*color,
);
gizmos.line(
*position - normal * *radius + y_offset,
*position - normal * *radius - y_offset,
*color,
);
let rotation = *rotation
* Quat::from_euler(bevy_math::EulerRot::ZYX, 0., axis.z * FRAC_PI_2, FRAC_PI_2);
gizmos
.arc_3d(PI, *radius, *position + y_offset, rotation, *color)
.resolution(*resolution / 2);
gizmos
.arc_3d(
PI,
*radius,
*position - y_offset,
rotation * Quat::from_rotation_y(PI),
*color,
)
.resolution(*resolution / 2);
}); });
// connect the two semi spheres with lines
draw_cylinder_vertical_lines(
gizmos,
*radius,
*resolution,
*half_length,
*rotation,
*position,
*color,
);
} }
} }

View File

@ -46,33 +46,6 @@ pub(crate) fn circle_coordinates(radius: f32, resolution: usize) -> impl Iterato
.take(resolution) .take(resolution)
} }
/// Draws a semi-sphere.
///
/// This function draws a semi-sphere at the specified `center` point with the given `rotation`,
/// `radius`, and `color`. The `resolution` parameter determines the level of detail, and the `top`
/// argument specifies the shape of the semi-sphere's tip.
pub(crate) fn draw_semi_sphere<Config, Clear>(
gizmos: &mut Gizmos<'_, '_, Config, Clear>,
radius: f32,
resolution: usize,
rotation: Quat,
center: Vec3,
top: Vec3,
color: Color,
) where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
{
circle_coordinates(radius, resolution)
.map(|p| Vec3::new(p.x, 0.0, p.y))
.map(rotate_then_translate_3d(rotation, center))
.for_each(|from| {
gizmos
.short_arc_3d_between(center, from, top, color)
.resolution(resolution / 2);
});
}
/// Draws a circle in 3D space. /// Draws a circle in 3D space.
/// ///
/// # Note /// # Note
@ -97,28 +70,3 @@ pub(crate) fn draw_circle_3d<Config, Clear>(
.map(rotate_then_translate_3d(rotation, translation)); .map(rotate_then_translate_3d(rotation, translation));
gizmos.linestrip(positions, color); gizmos.linestrip(positions, color);
} }
/// Draws the connecting lines of a cylinder between the top circle and the bottom circle.
pub(crate) fn draw_cylinder_vertical_lines<Config, Clear>(
gizmos: &mut Gizmos<'_, '_, Config, Clear>,
radius: f32,
resolution: usize,
half_height: f32,
rotation: Quat,
center: Vec3,
color: Color,
) where
Config: GizmoConfigGroup,
Clear: 'static + Send + Sync,
{
circle_coordinates(radius, resolution)
.map(move |point_2d| {
[1.0, -1.0]
.map(|sign| sign * half_height)
.map(|height| Vec3::new(point_2d.x, height, point_2d.y))
})
.map(|ps| ps.map(rotate_then_translate_3d(rotation, center)))
.for_each(|[start, end]| {
gizmos.line(start, end, color);
});
}

View File

@ -452,8 +452,10 @@ fn draw_gizmos_2d(mut gizmos: Gizmos, state: Res<State<PrimitiveSelected>>, time
PrimitiveSelected::RectangleAndCuboid => { PrimitiveSelected::RectangleAndCuboid => {
gizmos.primitive_2d(&RECTANGLE, POSITION, angle, color); gizmos.primitive_2d(&RECTANGLE, POSITION, angle, color);
} }
PrimitiveSelected::CircleAndSphere => gizmos.primitive_2d(&CIRCLE, POSITION, angle, color), PrimitiveSelected::CircleAndSphere => {
PrimitiveSelected::Ellipse => gizmos.primitive_2d(&ELLIPSE, POSITION, angle, color), gizmos.primitive_2d(&CIRCLE, POSITION, angle, color);
}
PrimitiveSelected::Ellipse => drop(gizmos.primitive_2d(&ELLIPSE, POSITION, angle, color)),
PrimitiveSelected::Triangle => gizmos.primitive_2d(&TRIANGLE_2D, POSITION, angle, color), PrimitiveSelected::Triangle => gizmos.primitive_2d(&TRIANGLE_2D, POSITION, angle, color),
PrimitiveSelected::Plane => gizmos.primitive_2d(&PLANE_2D, POSITION, angle, color), PrimitiveSelected::Plane => gizmos.primitive_2d(&PLANE_2D, POSITION, angle, color),
PrimitiveSelected::Line => drop(gizmos.primitive_2d(&LINE2D, POSITION, angle, color)), PrimitiveSelected::Line => drop(gizmos.primitive_2d(&LINE2D, POSITION, angle, color)),
@ -469,7 +471,7 @@ fn draw_gizmos_2d(mut gizmos: Gizmos, state: Res<State<PrimitiveSelected>>, time
PrimitiveSelected::Cylinder => {} PrimitiveSelected::Cylinder => {}
PrimitiveSelected::Cone => {} PrimitiveSelected::Cone => {}
PrimitiveSelected::ConicalFrustum => {} PrimitiveSelected::ConicalFrustum => {}
PrimitiveSelected::Torus => gizmos.primitive_2d(&ANNULUS, POSITION, angle, color), PrimitiveSelected::Torus => drop(gizmos.primitive_2d(&ANNULUS, POSITION, angle, color)),
PrimitiveSelected::Tetrahedron => {} PrimitiveSelected::Tetrahedron => {}
PrimitiveSelected::Arc => gizmos.primitive_2d(&ARC, POSITION, angle, color), PrimitiveSelected::Arc => gizmos.primitive_2d(&ARC, POSITION, angle, color),
PrimitiveSelected::CircularSector => { PrimitiveSelected::CircularSector => {