diff --git a/crates/bevy_gizmos/src/light.rs b/crates/bevy_gizmos/src/light.rs index 1bd6ee3cacb05..796ed2ddfa903 100644 --- a/crates/bevy_gizmos/src/light.rs +++ b/crates/bevy_gizmos/src/light.rs @@ -2,8 +2,6 @@ use core::f32::consts::PI; -use crate::primitives::dim3::GizmoPrimitive3d; - use bevy_app::{Plugin, PostUpdate}; use bevy_color::{ palettes::basic::{BLUE, GREEN, RED}, diff --git a/crates/bevy_gizmos/src/primitives/dim3.rs b/crates/bevy_gizmos/src/primitives/dim3.rs index 898850ddea901..dbd641b147e5b 100644 --- a/crates/bevy_gizmos/src/primitives/dim3.rs +++ b/crates/bevy_gizmos/src/primitives/dim3.rs @@ -18,24 +18,50 @@ const DEFAULT_RESOLUTION: u32 = 5; const INFINITE_LEN: f32 = 10_000.0; /// A trait for rendering 3D geometric primitives (`P`) with [`GizmoBuffer`]. -pub trait GizmoPrimitive3d { - /// The output of `primitive_3d`. This is a builder to set non-default values. +/// +/// This trait is used internally when calling [`gizmos.primitive_3d`]. +/// +/// If you want to implement gizmos support for a custom primitive you should +/// implement this trait. +pub trait GizmoPrimitive3d: Primitive3d +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + /// The output of `gizmos.primitive_3d` and `self.gizmos`. This is a builder to set non-default values. type Output<'a> where Self: 'a; /// Renders a 3D primitive with its associated details. - fn primitive_3d( - &mut self, - primitive: &P, + /// + /// This is identical to `gizmos.primitive_3d`. + fn gizmos<'a, 'b: 'a>( + &'a self, + gizmos: &'b mut GizmoBuffer, + isometry: impl Into, + color: impl Into, + ) -> Self::Output<'a>; +} +impl GizmoBuffer +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + /// Renders a 3D primitive with its associated details. + pub fn primitive_3d<'a, 'b: 'a, P: GizmoPrimitive3d>( + &'b mut self, + primitive: &'a P, isometry: impl Into, color: impl Into, - ) -> Self::Output<'_>; + ) -> P::Output<'a> { + primitive.gizmos(self, isometry, color) + } } // direction 3d -impl GizmoPrimitive3d for GizmoBuffer +impl GizmoPrimitive3d for Dir3 where Config: GizmoConfigGroup, Clear: 'static + Send + Sync, @@ -45,22 +71,22 @@ where where Self: 'a; - fn primitive_3d( - &mut self, - primitive: &Dir3, + fn gizmos<'a, 'b: 'a>( + &'a self, + gizmos: &'b mut GizmoBuffer, isometry: impl Into, color: impl Into, - ) -> Self::Output<'_> { + ) -> Self::Output<'a> { let isometry = isometry.into(); let start = Vec3::ZERO; - let end = primitive.as_vec3(); - self.arrow(isometry * start, isometry * end, color); + let end = self.as_vec3(); + gizmos.arrow(isometry * start, isometry * end, color); } } // sphere -impl GizmoPrimitive3d for GizmoBuffer +impl GizmoPrimitive3d for Sphere where Config: GizmoConfigGroup, Clear: 'static + Send + Sync, @@ -70,13 +96,13 @@ where where Self: 'a; - fn primitive_3d( - &mut self, - primitive: &Sphere, + fn gizmos<'a, 'b: 'a>( + &'a self, + gizmos: &'b mut GizmoBuffer, isometry: impl Into, color: impl Into, - ) -> Self::Output<'_> { - self.sphere(isometry, primitive.radius, color) + ) -> Self::Output<'a> { + gizmos.sphere(isometry, self.radius, color) } } @@ -121,7 +147,7 @@ where } } -impl GizmoPrimitive3d for GizmoBuffer +impl GizmoPrimitive3d for Plane3d where Config: GizmoConfigGroup, Clear: 'static + Send + Sync, @@ -131,15 +157,15 @@ where where Self: 'a; - fn primitive_3d( - &mut self, - primitive: &Plane3d, + fn gizmos<'a, 'b: 'a>( + &'a self, + gizmos: &'b mut GizmoBuffer, isometry: impl Into, color: impl Into, - ) -> Self::Output<'_> { + ) -> Self::Output<'a> { Plane3dBuilder { - gizmos: self, - normal: primitive.normal, + gizmos, + normal: self.normal, isometry: isometry.into(), color: color.into(), cell_count: UVec2::splat(3), @@ -173,7 +199,7 @@ where // line 3d -impl GizmoPrimitive3d for GizmoBuffer +impl GizmoPrimitive3d for Line3d where Config: GizmoConfigGroup, Clear: 'static + Send + Sync, @@ -183,32 +209,32 @@ where where Self: 'a; - fn primitive_3d( - &mut self, - primitive: &Line3d, + fn gizmos<'a, 'b: 'a>( + &'a self, + gizmos: &'b mut GizmoBuffer, isometry: impl Into, color: impl Into, - ) -> Self::Output<'_> { - if !self.enabled { + ) -> Self::Output<'a> { + if !gizmos.enabled { return; } let isometry = isometry.into(); let color = color.into(); - let direction = primitive.direction.as_vec3(); - self.arrow(isometry * Vec3::ZERO, isometry * direction, color); + let direction = self.direction.as_vec3(); + gizmos.arrow(isometry * Vec3::ZERO, isometry * direction, color); let [start, end] = [1.0, -1.0] .map(|sign| sign * INFINITE_LEN) - .map(|length| primitive.direction * length) + .map(|length| self.direction * length) .map(|offset| isometry * offset); - self.line(start, end, color); + gizmos.line(start, end, color); } } // segment 3d -impl GizmoPrimitive3d for GizmoBuffer +impl GizmoPrimitive3d for Segment3d where Config: GizmoConfigGroup, Clear: 'static + Send + Sync, @@ -218,24 +244,24 @@ where where Self: 'a; - fn primitive_3d( - &mut self, - primitive: &Segment3d, + fn gizmos<'a, 'b: 'a>( + &'a self, + gizmos: &'b mut GizmoBuffer, isometry: impl Into, color: impl Into, - ) -> Self::Output<'_> { - if !self.enabled { + ) -> Self::Output<'a> { + if !gizmos.enabled { return; } - let transformed = primitive.transformed(isometry); - self.line(transformed.point1(), transformed.point2(), color); + let transformed = self.transformed(isometry); + gizmos.line(transformed.point1(), transformed.point2(), color); } } // polyline 3d -impl GizmoPrimitive3d> for GizmoBuffer +impl GizmoPrimitive3d for Polyline3d where Config: GizmoConfigGroup, Clear: 'static + Send + Sync, @@ -245,24 +271,24 @@ where where Self: 'a; - fn primitive_3d( - &mut self, - primitive: &Polyline3d, + fn gizmos<'a, 'b: 'a>( + &'a self, + gizmos: &'b mut GizmoBuffer, isometry: impl Into, color: impl Into, - ) -> Self::Output<'_> { - if !self.enabled { + ) -> Self::Output<'a> { + if !gizmos.enabled { return; } let isometry = isometry.into(); - self.linestrip(primitive.vertices.map(|vec3| isometry * vec3), color); + gizmos.linestrip(self.vertices.map(|vec3| isometry * vec3), color); } } // boxed polyline 3d -impl GizmoPrimitive3d for GizmoBuffer +impl GizmoPrimitive3d for BoxedPolyline3d where Config: GizmoConfigGroup, Clear: 'static + Send + Sync, @@ -272,23 +298,19 @@ where where Self: 'a; - fn primitive_3d( - &mut self, - primitive: &BoxedPolyline3d, + fn gizmos<'a, 'b: 'a>( + &'a self, + gizmos: &'b mut GizmoBuffer, isometry: impl Into, color: impl Into, - ) -> Self::Output<'_> { - if !self.enabled { + ) -> Self::Output<'a> { + if !gizmos.enabled { return; } let isometry = isometry.into(); - self.linestrip( - primitive - .vertices - .iter() - .copied() - .map(|vec3| isometry * vec3), + gizmos.linestrip( + self.vertices.iter().copied().map(|vec3| isometry * vec3), color, ); } @@ -296,7 +318,7 @@ where // triangle 3d -impl GizmoPrimitive3d for GizmoBuffer +impl GizmoPrimitive3d for Triangle3d where Config: GizmoConfigGroup, Clear: 'static + Send + Sync, @@ -306,25 +328,25 @@ where where Self: 'a; - fn primitive_3d( - &mut self, - primitive: &Triangle3d, + fn gizmos<'a, 'b: 'a>( + &'a self, + gizmos: &'b mut GizmoBuffer, isometry: impl Into, color: impl Into, - ) -> Self::Output<'_> { - if !self.enabled { + ) -> Self::Output<'a> { + if !gizmos.enabled { return; } let isometry = isometry.into(); - let [a, b, c] = primitive.vertices; - self.linestrip([a, b, c, a].map(|vec3| isometry * vec3), color); + let [a, b, c] = self.vertices; + gizmos.linestrip([a, b, c, a].map(|vec3| isometry * vec3), color); } } // cuboid -impl GizmoPrimitive3d for GizmoBuffer +impl GizmoPrimitive3d for Cuboid where Config: GizmoConfigGroup, Clear: 'static + Send + Sync, @@ -334,13 +356,13 @@ where where Self: 'a; - fn primitive_3d( - &mut self, - primitive: &Cuboid, + fn gizmos<'a, 'b: 'a>( + &'a self, + gizmos: &'b mut GizmoBuffer, isometry: impl Into, color: impl Into, - ) -> Self::Output<'_> { - if !self.enabled { + ) -> Self::Output<'a> { + if !gizmos.enabled { return; } @@ -358,7 +380,7 @@ where [1.0, -1.0, -1.0], ] .map(Vec3::from) - .map(|vec3| vec3 * primitive.half_size) + .map(|vec3| vec3 * self.half_size) .map(|vec3| isometry * vec3); // lines for the upper rectangle of the cuboid @@ -379,7 +401,7 @@ where .chain(lower) .chain(connections) .for_each(|(start, end)| { - self.line(start, end, color); + gizmos.line(start, end, color); }); } } @@ -419,7 +441,7 @@ where } } -impl GizmoPrimitive3d for GizmoBuffer +impl GizmoPrimitive3d for Cylinder where Config: GizmoConfigGroup, Clear: 'static + Send + Sync, @@ -429,16 +451,16 @@ where where Self: 'a; - fn primitive_3d( - &mut self, - primitive: &Cylinder, + fn gizmos<'a, 'b: 'a>( + &'a self, + gizmos: &'b mut GizmoBuffer, isometry: impl Into, color: impl Into, - ) -> Self::Output<'_> { + ) -> Self::Output<'a> { Cylinder3dBuilder { - gizmos: self, - radius: primitive.radius, - half_height: primitive.half_height, + gizmos, + radius: self.radius, + half_height: self.half_height, isometry: isometry.into(), color: color.into(), resolution: DEFAULT_RESOLUTION, @@ -505,7 +527,7 @@ where } } -impl GizmoPrimitive3d for GizmoBuffer +impl GizmoPrimitive3d for Capsule3d where Config: GizmoConfigGroup, Clear: 'static + Send + Sync, @@ -515,16 +537,16 @@ where where Self: 'a; - fn primitive_3d( - &mut self, - primitive: &Capsule3d, + fn gizmos<'a, 'b: 'a>( + &'a self, + gizmos: &'b mut GizmoBuffer, isometry: impl Into, color: impl Into, - ) -> Self::Output<'_> { + ) -> Self::Output<'a> { Capsule3dBuilder { - gizmos: self, - radius: primitive.radius, - half_length: primitive.half_length, + gizmos, + radius: self.radius, + half_length: self.half_length, isometry: isometry.into(), color: color.into(), resolution: DEFAULT_RESOLUTION, @@ -645,7 +667,7 @@ where } } -impl GizmoPrimitive3d for GizmoBuffer +impl GizmoPrimitive3d for Cone where Config: GizmoConfigGroup, Clear: 'static + Send + Sync, @@ -655,16 +677,16 @@ where where Self: 'a; - fn primitive_3d( - &mut self, - primitive: &Cone, + fn gizmos<'a, 'b: 'a>( + &'a self, + gizmos: &'b mut GizmoBuffer, isometry: impl Into, color: impl Into, - ) -> Self::Output<'_> { + ) -> Self::Output<'a> { Cone3dBuilder { - gizmos: self, - radius: primitive.radius, - height: primitive.height, + gizmos, + radius: self.radius, + height: self.height, isometry: isometry.into(), color: color.into(), base_resolution: DEFAULT_RESOLUTION, @@ -747,7 +769,7 @@ where } } -impl GizmoPrimitive3d for GizmoBuffer +impl GizmoPrimitive3d for ConicalFrustum where Config: GizmoConfigGroup, Clear: 'static + Send + Sync, @@ -757,17 +779,17 @@ where where Self: 'a; - fn primitive_3d( - &mut self, - primitive: &ConicalFrustum, + fn gizmos<'a, 'b: 'a>( + &'a self, + gizmos: &'b mut GizmoBuffer, isometry: impl Into, color: impl Into, - ) -> Self::Output<'_> { + ) -> Self::Output<'a> { ConicalFrustum3dBuilder { - gizmos: self, - radius_top: primitive.radius_top, - radius_bottom: primitive.radius_bottom, - height: primitive.height, + gizmos, + radius_top: self.radius_top, + radius_bottom: self.radius_bottom, + height: self.height, isometry: isometry.into(), color: color.into(), resolution: DEFAULT_RESOLUTION, @@ -851,7 +873,7 @@ where } } -impl GizmoPrimitive3d for GizmoBuffer +impl GizmoPrimitive3d for Torus where Config: GizmoConfigGroup, Clear: 'static + Send + Sync, @@ -861,16 +883,16 @@ where where Self: 'a; - fn primitive_3d( - &mut self, - primitive: &Torus, + fn gizmos<'a, 'b: 'a>( + &'a self, + gizmos: &'b mut GizmoBuffer, isometry: impl Into, color: impl Into, - ) -> Self::Output<'_> { + ) -> Self::Output<'a> { Torus3dBuilder { - gizmos: self, - minor_radius: primitive.minor_radius, - major_radius: primitive.major_radius, + gizmos, + minor_radius: self.minor_radius, + major_radius: self.major_radius, isometry: isometry.into(), color: color.into(), minor_resolution: DEFAULT_RESOLUTION, @@ -931,7 +953,7 @@ where // tetrahedron -impl GizmoPrimitive3d for GizmoBuffer +impl GizmoPrimitive3d for Tetrahedron where Config: GizmoConfigGroup, Clear: 'static + Send + Sync, @@ -941,25 +963,25 @@ where where Self: 'a; - fn primitive_3d( - &mut self, - primitive: &Tetrahedron, + fn gizmos<'a, 'b: 'a>( + &'a self, + gizmos: &'b mut GizmoBuffer, isometry: impl Into, color: impl Into, - ) -> Self::Output<'_> { - if !self.enabled { + ) -> Self::Output<'a> { + if !gizmos.enabled { return; } let isometry = isometry.into(); - let [a, b, c, d] = primitive.vertices.map(|vec3| isometry * vec3); + let [a, b, c, d] = self.vertices.map(|vec3| isometry * vec3); let lines = [(a, b), (a, c), (a, d), (b, c), (b, d), (c, d)]; let color = color.into(); lines.into_iter().for_each(|(start, end)| { - self.line(start, end, color); + gizmos.line(start, end, color); }); } } diff --git a/release-content/migration-guides/extendable_gizmos_primitives.md b/release-content/migration-guides/extendable_gizmos_primitives.md new file mode 100644 index 0000000000000..6dc5e46c1f8f3 --- /dev/null +++ b/release-content/migration-guides/extendable_gizmos_primitives.md @@ -0,0 +1,10 @@ +--- +title: Extendable Gizmo-Primitives +authors: ["@lynn-lumen"] +pull_requests: [20049] +--- + +The `GizmoPrimitive3d` trait, which is used to draw primitives using gizmos can now be implemented for custom primitives. +If you did not declare any such primitives, you may need to remove this trait as it will now be unused. + +If you did implement `GizmoPrimitive3d` for a custom `GizmoBuffer`-like struct, you will need to move your implementation for custom primitives to the primitive itself and use that implementation in a separate method on the previously mentioned struct.