Added arc_2d function for gizmos (#8448)

# Objective

Added the possibility to draw arcs in 2d via gizmos

## Solution

- Added `arc_2d` function to `Gizmos`
- Added `arc_inner` function
- Added `Arc2dBuilder<'a, 's>`
- Updated `2d_gizmos.rs` example to draw an arc

---------

Co-authored-by: kjolnyr <kjolnyr@protonmail.ch>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: ira <JustTheCoolDude@gmail.com>
This commit is contained in:
Kjolnyr 2023-04-21 17:34:07 +02:00 committed by GitHub
parent 0cf3000ee0
commit ddefc246b2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 99 additions and 0 deletions

View file

@ -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,
radius: f32,
color: Color,
) -> Arc2dBuilder<'_, 's> {
Arc2dBuilder {
gizmos: self,
position,
direction_angle,
arc_angle,
radius,
color,
segments: None,
}
}
/// Draw a wireframe rectangle.
///
/// # Example
@ -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 {
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;

View file

@ -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() {
@ -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);
}