diff --git a/crates/bevy_gizmos/src/gizmos.rs b/crates/bevy_gizmos/src/gizmos.rs index 34f9f476dcaf7..3d666cbbf51fe 100644 --- a/crates/bevy_gizmos/src/gizmos.rs +++ b/crates/bevy_gizmos/src/gizmos.rs @@ -727,6 +727,46 @@ where self.linestrip(positions.into_iter().map(|vec2| vec2.extend(0.)), color); } + /// Draw a line in 2D made of straight segments between the points, with the first and last connected. + /// + /// # Example + /// ``` + /// # use bevy_gizmos::prelude::*; + /// # use bevy_math::prelude::*; + /// # use bevy_color::palettes::basic::GREEN; + /// fn system(mut gizmos: Gizmos) { + /// gizmos.lineloop_2d([Vec2::ZERO, Vec2::X, Vec2::Y], GREEN); + /// } + /// # bevy_ecs::system::assert_is_system(system); + /// ``` + #[inline] + pub fn lineloop_2d( + &mut self, + positions: impl IntoIterator, + color: impl Into, + ) { + if !self.enabled { + return; + } + + // Loop back to the start; second is needed to ensure that + // the joint on the first corner is drawn. + let mut positions = positions.into_iter(); + let first = positions.next(); + let second = positions.next(); + + self.linestrip( + first + .into_iter() + .chain(second) + .chain(positions) + .chain(first) + .chain(second) + .map(|vec2| vec2.extend(0.)), + color, + ); + } + /// Draw a line in 2D made of straight segments between the points, with a color gradient. /// /// # Example @@ -833,7 +873,7 @@ where } let isometry = isometry.into(); let [tl, tr, br, bl] = rect_inner(size).map(|vec2| isometry * vec2); - self.linestrip_2d([tl, tr, br, bl, tl], color); + self.lineloop_2d([tl, tr, br, bl], color); } #[inline] diff --git a/crates/bevy_gizmos/src/primitives/dim2.rs b/crates/bevy_gizmos/src/primitives/dim2.rs index 41b5e0a60a056..a8f25dcac78d8 100644 --- a/crates/bevy_gizmos/src/primitives/dim2.rs +++ b/crates/bevy_gizmos/src/primitives/dim2.rs @@ -358,8 +358,8 @@ where primitive.half_diagonals.y * sign_y, ) }); - let positions = [a, b, c, d, a].map(|vec2| isometry * vec2); - self.linestrip_2d(positions, color); + let positions = [a, b, c, d].map(|vec2| isometry * vec2); + self.lineloop_2d(positions, color); } } @@ -706,8 +706,8 @@ where let isometry = isometry.into(); let [a, b, c] = primitive.vertices; - let positions = [a, b, c, a].map(|vec2| isometry * vec2); - self.linestrip_2d(positions, color); + let positions = [a, b, c].map(|vec2| isometry * vec2); + self.lineloop_2d(positions, color); } } @@ -742,8 +742,8 @@ where primitive.half_size.y * sign_y, ) }); - let positions = [a, b, c, d, a].map(|vec2| isometry * vec2); - self.linestrip_2d(positions, color); + let positions = [a, b, c, d].map(|vec2| isometry * vec2); + self.lineloop_2d(positions, color); } } @@ -771,24 +771,14 @@ where let isometry = isometry.into(); - // Check if the polygon needs a closing point - let closing_point = { - let first = primitive.vertices.first(); - (primitive.vertices.last() != first) - .then_some(first) - .flatten() - .cloned() + let vertices = if primitive.vertices.first() == primitive.vertices.last() { + // Strip closing point if there is one + &primitive.vertices[..primitive.vertices.len() - 1] + } else { + &primitive.vertices[..] }; - self.linestrip_2d( - primitive - .vertices - .iter() - .copied() - .chain(closing_point) - .map(|vec2| isometry * vec2), - color, - ); + self.lineloop_2d(vertices.iter().map(|&vec2| isometry * vec2), color); } } @@ -816,9 +806,9 @@ where let isometry = isometry.into(); - let points = (0..=primitive.sides) + let points = (0..primitive.sides) .map(|n| single_circle_coordinate(primitive.circumcircle.radius, primitive.sides, n)) .map(|vec2| isometry * vec2); - self.linestrip_2d(points, color); + self.lineloop_2d(points, color); } }