diff --git a/crates/bevy_gizmos/src/arrows.rs b/crates/bevy_gizmos/src/arrows.rs index f15c88c6d5925..9a1325c821302 100644 --- a/crates/bevy_gizmos/src/arrows.rs +++ b/crates/bevy_gizmos/src/arrows.rs @@ -1,9 +1,13 @@ -//! Additional Gizmo Functions -- Arrows +//! Additional [`Gizmos`] Functions -- Arrows +//! +//! Includes the implementation of [`Gizmos::arrow`] and [`Gizmos::arrow_2d`], +//! and assorted support items. use crate::prelude::Gizmos; use bevy_math::{Quat, Vec2, Vec3}; use bevy_render::color::Color; +/// A builder returned by [`Gizmos::arrow`] and [`Gizmos::arrow_2d`] pub struct ArrowBuilder<'a, 's> { gizmos: &'a mut Gizmos<'s>, start: Vec3, @@ -12,7 +16,6 @@ pub struct ArrowBuilder<'a, 's> { tip_length: f32, } -/// A builder returned by [`Gizmos::arrow`] and [`Gizmos::arrow_2d`] impl ArrowBuilder<'_, '_> { /// Change the length of the tips to be `length`. /// The default tip length is [length of the arrow]/10. diff --git a/crates/bevy_gizmos/src/circles.rs b/crates/bevy_gizmos/src/circles.rs new file mode 100644 index 0000000000000..1b4948b198c1c --- /dev/null +++ b/crates/bevy_gizmos/src/circles.rs @@ -0,0 +1,145 @@ +//! Additional [`Gizmos`] Functions -- Circles +//! +//! Includes the implementation of [`Gizmos::circle`] and [`Gizmos::circle_2d`], +//! and assorted support items. + +use crate::prelude::Gizmos; +use bevy_math::{Quat, Vec2, Vec3}; +use bevy_render::color::Color; +use std::f32::consts::TAU; + +pub(crate) const DEFAULT_CIRCLE_SEGMENTS: usize = 32; + +fn circle_inner(radius: f32, segments: usize) -> impl Iterator { + (0..segments + 1).map(move |i| { + let angle = i as f32 * TAU / segments as f32; + Vec2::from(angle.sin_cos()) * radius + }) +} + +impl<'s> Gizmos<'s> { + /// Draw a circle in 3D at `position` with the flat side facing `normal`. + /// + /// This should be called for each frame the circle needs to be rendered. + /// + /// # Example + /// ``` + /// # use bevy_gizmos::prelude::*; + /// # use bevy_render::prelude::*; + /// # use bevy_math::prelude::*; + /// fn system(mut gizmos: Gizmos) { + /// gizmos.circle(Vec3::ZERO, Vec3::Z, 1., Color::GREEN); + /// + /// // Circles have 32 line-segments by default. + /// // You may want to increase this for larger circles. + /// gizmos + /// .circle(Vec3::ZERO, Vec3::Z, 5., Color::RED) + /// .segments(64); + /// } + /// # bevy_ecs::system::assert_is_system(system); + /// ``` + #[inline] + pub fn circle( + &mut self, + position: Vec3, + normal: Vec3, + radius: f32, + color: Color, + ) -> CircleBuilder<'_, 's> { + CircleBuilder { + gizmos: self, + position, + normal, + radius, + color, + segments: DEFAULT_CIRCLE_SEGMENTS, + } + } + + /// Draw a circle in 2D. + /// + /// This should be called for each frame the circle needs to be rendered. + /// + /// # Example + /// ``` + /// # use bevy_gizmos::prelude::*; + /// # use bevy_render::prelude::*; + /// # use bevy_math::prelude::*; + /// fn system(mut gizmos: Gizmos) { + /// gizmos.circle_2d(Vec2::ZERO, 1., Color::GREEN); + /// + /// // Circles have 32 line-segments by default. + /// // You may want to increase this for larger circles. + /// gizmos + /// .circle_2d(Vec2::ZERO, 5., Color::RED) + /// .segments(64); + /// } + /// # bevy_ecs::system::assert_is_system(system); + /// ``` + #[inline] + pub fn circle_2d( + &mut self, + position: Vec2, + radius: f32, + color: Color, + ) -> Circle2dBuilder<'_, 's> { + Circle2dBuilder { + gizmos: self, + position, + radius, + color, + segments: DEFAULT_CIRCLE_SEGMENTS, + } + } +} + +/// A builder returned by [`Gizmos::circle`]. +pub struct CircleBuilder<'a, 's> { + gizmos: &'a mut Gizmos<'s>, + position: Vec3, + normal: Vec3, + radius: f32, + color: Color, + segments: usize, +} + +impl CircleBuilder<'_, '_> { + /// Set the number of line-segments for this circle. + pub fn segments(mut self, segments: usize) -> Self { + self.segments = segments; + self + } +} + +impl Drop for CircleBuilder<'_, '_> { + fn drop(&mut self) { + let rotation = Quat::from_rotation_arc(Vec3::Z, self.normal); + let positions = circle_inner(self.radius, self.segments) + .map(|vec2| (self.position + rotation * vec2.extend(0.))); + self.gizmos.linestrip(positions, self.color); + } +} + +/// A builder returned by [`Gizmos::circle_2d`]. +pub struct Circle2dBuilder<'a, 's> { + gizmos: &'a mut Gizmos<'s>, + position: Vec2, + radius: f32, + color: Color, + segments: usize, +} + +impl Circle2dBuilder<'_, '_> { + /// Set the number of line-segments for this circle. + pub fn segments(mut self, segments: usize) -> Self { + self.segments = segments; + self + } +} + +impl Drop for Circle2dBuilder<'_, '_> { + fn drop(&mut self) { + let positions = circle_inner(self.radius, self.segments).map(|vec2| (vec2 + self.position)); + self.gizmos.linestrip_2d(positions, self.color); + } +} diff --git a/crates/bevy_gizmos/src/gizmos.rs b/crates/bevy_gizmos/src/gizmos.rs index 34c02ab3b98a9..dc1c998470fa3 100644 --- a/crates/bevy_gizmos/src/gizmos.rs +++ b/crates/bevy_gizmos/src/gizmos.rs @@ -2,6 +2,7 @@ use std::{f32::consts::TAU, iter}; +use crate::circles::DEFAULT_CIRCLE_SEGMENTS; use bevy_ecs::{ system::{Deferred, Resource, SystemBuffer, SystemMeta, SystemParam}, world::World, @@ -13,8 +14,6 @@ use bevy_transform::TransformPoint; type PositionItem = [f32; 3]; type ColorItem = [f32; 4]; -const DEFAULT_CIRCLE_SEGMENTS: usize = 32; - #[derive(Resource, Default)] pub(crate) struct GizmoStorage { pub list_positions: Vec, @@ -201,44 +200,6 @@ impl<'s> Gizmos<'s> { strip_colors.push([f32::NAN; 4]); } - /// Draw a circle in 3D at `position` with the flat side facing `normal`. - /// - /// This should be called for each frame the circle needs to be rendered. - /// - /// # Example - /// ``` - /// # use bevy_gizmos::prelude::*; - /// # use bevy_render::prelude::*; - /// # use bevy_math::prelude::*; - /// fn system(mut gizmos: Gizmos) { - /// gizmos.circle(Vec3::ZERO, Vec3::Z, 1., Color::GREEN); - /// - /// // Circles have 32 line-segments by default. - /// // You may want to increase this for larger circles. - /// gizmos - /// .circle(Vec3::ZERO, Vec3::Z, 5., Color::RED) - /// .segments(64); - /// } - /// # bevy_ecs::system::assert_is_system(system); - /// ``` - #[inline] - pub fn circle( - &mut self, - position: Vec3, - normal: Vec3, - radius: f32, - color: Color, - ) -> CircleBuilder<'_, 's> { - CircleBuilder { - gizmos: self, - position, - normal, - radius, - color, - segments: DEFAULT_CIRCLE_SEGMENTS, - } - } - /// 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. @@ -466,42 +427,6 @@ impl<'s> Gizmos<'s> { self.line_gradient_2d(start, start + vector, start_color, end_color); } - /// Draw a circle in 2D. - /// - /// This should be called for each frame the circle needs to be rendered. - /// - /// # Example - /// ``` - /// # use bevy_gizmos::prelude::*; - /// # use bevy_render::prelude::*; - /// # use bevy_math::prelude::*; - /// fn system(mut gizmos: Gizmos) { - /// gizmos.circle_2d(Vec2::ZERO, 1., Color::GREEN); - /// - /// // Circles have 32 line-segments by default. - /// // You may want to increase this for larger circles. - /// gizmos - /// .circle_2d(Vec2::ZERO, 5., Color::RED) - /// .segments(64); - /// } - /// # bevy_ecs::system::assert_is_system(system); - /// ``` - #[inline] - pub fn circle_2d( - &mut self, - position: Vec2, - radius: f32, - color: Color, - ) -> Circle2dBuilder<'_, 's> { - Circle2dBuilder { - gizmos: self, - position, - radius, - color, - segments: DEFAULT_CIRCLE_SEGMENTS, - } - } - /// Draw an arc, which is a part of the circumference of a circle, in 2D. /// /// This should be called for each frame the arc needs to be rendered. @@ -603,33 +528,6 @@ impl<'s> Gizmos<'s> { } } -/// A builder returned by [`Gizmos::circle`]. -pub struct CircleBuilder<'a, 's> { - gizmos: &'a mut Gizmos<'s>, - position: Vec3, - normal: Vec3, - radius: f32, - color: Color, - segments: usize, -} - -impl CircleBuilder<'_, '_> { - /// Set the number of line-segments for this circle. - pub fn segments(mut self, segments: usize) -> Self { - self.segments = segments; - self - } -} - -impl Drop for CircleBuilder<'_, '_> { - fn drop(&mut self) { - let rotation = Quat::from_rotation_arc(Vec3::Z, self.normal); - let positions = circle_inner(self.radius, self.segments) - .map(|vec2| (self.position + rotation * vec2.extend(0.))); - self.gizmos.linestrip(positions, self.color); - } -} - /// A builder returned by [`Gizmos::sphere`]. pub struct SphereBuilder<'a, 's> { gizmos: &'a mut Gizmos<'s>, @@ -658,30 +556,6 @@ impl Drop for SphereBuilder<'_, '_> { } } -/// A builder returned by [`Gizmos::circle_2d`]. -pub struct Circle2dBuilder<'a, 's> { - gizmos: &'a mut Gizmos<'s>, - position: Vec2, - radius: f32, - color: Color, - segments: usize, -} - -impl Circle2dBuilder<'_, '_> { - /// Set the number of line-segments for this circle. - pub fn segments(mut self, segments: usize) -> Self { - self.segments = segments; - self - } -} - -impl Drop for Circle2dBuilder<'_, '_> { - fn drop(&mut self) { - let positions = circle_inner(self.radius, self.segments).map(|vec2| (vec2 + self.position)); - self.gizmos.linestrip_2d(positions, self.color); - } -} - /// A builder returned by [`Gizmos::arc_2d`]. pub struct Arc2dBuilder<'a, 's> { gizmos: &'a mut Gizmos<'s>, @@ -730,13 +604,6 @@ fn arc_inner( }) } -fn circle_inner(radius: f32, segments: usize) -> impl Iterator { - (0..segments + 1).map(move |i| { - let angle = i as f32 * TAU / segments as f32; - Vec2::from(angle.sin_cos()) * radius - }) -} - fn rect_inner(size: Vec2) -> [Vec2; 4] { let half_size = size / 2.; let tl = Vec2::new(-half_size.x, half_size.y); diff --git a/crates/bevy_gizmos/src/lib.rs b/crates/bevy_gizmos/src/lib.rs index 5ad9d8934db06..2f41ff9193712 100644 --- a/crates/bevy_gizmos/src/lib.rs +++ b/crates/bevy_gizmos/src/lib.rs @@ -16,7 +16,8 @@ //! //! See the documentation on [`Gizmos`] for more examples. -mod arrows; +pub mod arrows; +pub mod circles; pub mod gizmos; #[cfg(feature = "bevy_sprite")]