Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added arc_2d function for gizmos #8448

Merged
merged 14 commits into from
Apr 21, 2023
93 changes: 93 additions & 0 deletions crates/bevy_gizmos/src/gizmos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,51 @@ impl<'s> Gizmos<'s> {
}
}

/// Draw an arc, which is a part of the circumference of a circle.
///
/// # Arguments
/// - `position` sets the center of this circle.
/// - `radius` controls the distance from `position` to this arc, and thus its curvature.
/// - `direction_angle` sets the angle in radians between `position` and the midpoint of the arc.
/// -`arc_angle` sets the length of this arc, in radians.
///
/// # Example
/// ```
/// # use bevy_gizmos::prelude::*;
/// # use bevy_render::prelude::*;
/// # use bevy_math::prelude::*;
/// # use std::f32::consts::PI;
/// fn system(mut gizmos: Gizmos) {
/// gizmos.arc_2d(Vec2::ZERO, 0., PI / 4., 1., Color::GREEN);
///
/// // Arcs have 32 line-segments by default.
/// // You may want to increase this for larger arcs.
/// gizmos
/// .arc_2d(Vec2::ZERO, 0., PI / 4., 5., Color::RED)
/// .segments(64);
/// }
/// # bevy_ecs::system::assert_is_system(system);
/// ```
#[inline]
pub fn arc_2d(
&mut self,
position: Vec2,
direction_angle: f32,
arc_angle: f32,
Kjolnyr marked this conversation as resolved.
Show resolved Hide resolved
radius: f32,
color: Color,
) -> Arc2dBuilder<'_, 's> {
Arc2dBuilder {
gizmos: self,
position,
direction_angle,
arc_angle,
radius,
color,
segments: None,
}
}

/// Draw a wireframe rectangle.
///
/// # Example
Expand Down Expand Up @@ -589,6 +634,54 @@ impl Drop for Circle2dBuilder<'_, '_> {
}
}

/// A builder returned by [`Gizmos::arc_2d`].
pub struct Arc2dBuilder<'a, 's> {
gizmos: &'a mut Gizmos<'s>,
position: Vec2,
direction_angle: f32,
arc_angle: f32,
radius: f32,
color: Color,
segments: Option<usize>,
}

impl Arc2dBuilder<'_, '_> {
/// Set the number of line-segements for this arc.
pub fn segments(mut self, segments: usize) -> Self {
Kjolnyr marked this conversation as resolved.
Show resolved Hide resolved
self.segments = Some(segments);
self
}
}

impl Drop for Arc2dBuilder<'_, '_> {
fn drop(&mut self) {
let segments = match self.segments {
Some(segments) => segments,
// Do a linear interpolation between 1 and `DEFAULT_CIRCLE_SEGMENTS`
// using the arc angle as scalar.
None => ((self.arc_angle.abs() / TAU) * DEFAULT_CIRCLE_SEGMENTS as f32).ceil() as usize,
};

let positions = arc_inner(self.direction_angle, self.arc_angle, self.radius, segments)
.map(|vec2| (vec2 + self.position));
self.gizmos.linestrip_2d(positions, self.color);
}
}

fn arc_inner(
direction_angle: f32,
arc_angle: f32,
radius: f32,
segments: usize,
) -> impl Iterator<Item = Vec2> {
(0..segments + 1).map(move |i| {
let start = direction_angle - arc_angle / 2.;

let angle = start + (i as f32 * (arc_angle / segments as f32));
Vec2::from(angle.sin_cos()) * radius
})
}

fn circle_inner(radius: f32, segments: usize) -> impl Iterator<Item = Vec2> {
(0..segments + 1).map(move |i| {
let angle = i as f32 * TAU / segments as f32;
Expand Down
6 changes: 6 additions & 0 deletions examples/2d/2d_gizmos.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! This example demonstrates Bevy's immediate mode drawing API intended for visual debugging.

use std::f32::consts::PI;

use bevy::prelude::*;

fn main() {
Expand Down Expand Up @@ -38,4 +40,8 @@ fn system(mut gizmos: Gizmos, time: Res<Time>) {
gizmos.circle_2d(Vec2::ZERO, 120., Color::BLACK);
// You may want to increase this for larger circles.
gizmos.circle_2d(Vec2::ZERO, 300., Color::NAVY).segments(64);

// Arcs default amount of segments is linerarly interpolated between
// 1 and 32, using the arc length as scalar.
gizmos.arc_2d(Vec2::ZERO, sin / 10., PI / 2., 350., Color::ORANGE_RED);
}