diff --git a/crates/bevy_gizmos/Cargo.toml b/crates/bevy_gizmos/Cargo.toml index 039151b161..74d12da3a9 100644 --- a/crates/bevy_gizmos/Cargo.toml +++ b/crates/bevy_gizmos/Cargo.toml @@ -27,6 +27,7 @@ bevy_reflect = { path = "../bevy_reflect", version = "0.14.0-dev" } bevy_core_pipeline = { path = "../bevy_core_pipeline", version = "0.14.0-dev" } bevy_transform = { path = "../bevy_transform", version = "0.14.0-dev" } bevy_gizmos_macros = { path = "macros", version = "0.14.0-dev" } +bevy_time = { path = "../bevy_time", version = "0.14.0-dev" } bytemuck = "1.0" diff --git a/crates/bevy_gizmos/src/arcs.rs b/crates/bevy_gizmos/src/arcs.rs index 39a06d5ff5..f94ed26d42 100644 --- a/crates/bevy_gizmos/src/arcs.rs +++ b/crates/bevy_gizmos/src/arcs.rs @@ -11,7 +11,11 @@ use std::f32::consts::TAU; // === 2D === -impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// 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. @@ -50,7 +54,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { arc_angle: f32, radius: f32, color: impl Into, - ) -> Arc2dBuilder<'_, 'w, 's, T> { + ) -> Arc2dBuilder<'_, 'w, 's, Config, Clear> { Arc2dBuilder { gizmos: self, position, @@ -64,8 +68,12 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { } /// A builder returned by [`Gizmos::arc_2d`]. -pub struct Arc2dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { - gizmos: &'a mut Gizmos<'w, 's, T>, +pub struct Arc2dBuilder<'a, 'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, position: Vec2, direction_angle: f32, arc_angle: f32, @@ -74,7 +82,11 @@ pub struct Arc2dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { segments: Option, } -impl Arc2dBuilder<'_, '_, '_, T> { +impl Arc2dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Set the number of line-segments for this arc. pub fn segments(mut self, segments: usize) -> Self { self.segments.replace(segments); @@ -82,7 +94,11 @@ impl Arc2dBuilder<'_, '_, '_, T> { } } -impl Drop for Arc2dBuilder<'_, '_, '_, T> { +impl Drop for Arc2dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ fn drop(&mut self) { if !self.gizmos.enabled { return; @@ -114,7 +130,11 @@ fn arc_2d_inner( // === 3D === -impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Draw an arc, which is a part of the circumference of a circle, in 3D. For default values /// this is drawing a standard arc. A standard arc is defined as /// @@ -169,7 +189,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { position: Vec3, rotation: Quat, color: impl Into, - ) -> Arc3dBuilder<'_, 'w, 's, T> { + ) -> Arc3dBuilder<'_, 'w, 's, Config, Clear> { Arc3dBuilder { gizmos: self, start_vertex: Vec3::X, @@ -226,7 +246,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { from: Vec3, to: Vec3, color: impl Into, - ) -> Arc3dBuilder<'_, 'w, 's, T> { + ) -> Arc3dBuilder<'_, 'w, 's, Config, Clear> { self.arc_from_to(center, from, to, color, |x| x) } @@ -273,7 +293,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { from: Vec3, to: Vec3, color: impl Into, - ) -> Arc3dBuilder<'_, 'w, 's, T> { + ) -> Arc3dBuilder<'_, 'w, 's, Config, Clear> { self.arc_from_to(center, from, to, color, |angle| { if angle > 0.0 { TAU - angle @@ -293,7 +313,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { to: Vec3, color: impl Into, angle_fn: impl Fn(f32) -> f32, - ) -> Arc3dBuilder<'_, 'w, 's, T> { + ) -> Arc3dBuilder<'_, 'w, 's, Config, Clear> { // `from` and `to` can be the same here since in either case nothing gets rendered and the // orientation ambiguity of `up` doesn't matter let from_axis = (from - center).normalize_or_zero(); @@ -320,8 +340,12 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { } /// A builder returned by [`Gizmos::arc_2d`]. -pub struct Arc3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { - gizmos: &'a mut Gizmos<'w, 's, T>, +pub struct Arc3dBuilder<'a, 'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, // this is the vertex the arc starts on in the XZ plane. For the normal arc_3d method this is // always starting at Vec3::X. For the short/long arc methods we actually need a way to start // at the from position and this is where this internal field comes into play. Some implicit @@ -340,7 +364,11 @@ pub struct Arc3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { segments: Option, } -impl Arc3dBuilder<'_, '_, '_, T> { +impl Arc3dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Set the number of line-segments for this arc. pub fn segments(mut self, segments: usize) -> Self { self.segments.replace(segments); @@ -348,7 +376,11 @@ impl Arc3dBuilder<'_, '_, '_, T> { } } -impl Drop for Arc3dBuilder<'_, '_, '_, T> { +impl Drop for Arc3dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ fn drop(&mut self) { if !self.gizmos.enabled { return; diff --git a/crates/bevy_gizmos/src/arrows.rs b/crates/bevy_gizmos/src/arrows.rs index dd333da129..339df992e2 100644 --- a/crates/bevy_gizmos/src/arrows.rs +++ b/crates/bevy_gizmos/src/arrows.rs @@ -12,8 +12,12 @@ use bevy_math::{Quat, Vec2, Vec3}; use bevy_transform::TransformPoint; /// A builder returned by [`Gizmos::arrow`] and [`Gizmos::arrow_2d`] -pub struct ArrowBuilder<'a, 'w, 's, T: GizmoConfigGroup> { - gizmos: &'a mut Gizmos<'w, 's, T>, +pub struct ArrowBuilder<'a, 'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, start: Vec3, end: Vec3, color: Color, @@ -21,7 +25,11 @@ pub struct ArrowBuilder<'a, 'w, 's, T: GizmoConfigGroup> { tip_length: f32, } -impl ArrowBuilder<'_, '_, '_, T> { +impl ArrowBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Change the length of the tips to be `length`. /// The default tip length is [length of the arrow]/10. /// @@ -51,7 +59,11 @@ impl ArrowBuilder<'_, '_, '_, T> { } } -impl Drop for ArrowBuilder<'_, '_, '_, T> { +impl Drop for ArrowBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Draws the arrow, by drawing lines with the stored [`Gizmos`] fn drop(&mut self) { if !self.gizmos.enabled { @@ -90,7 +102,11 @@ impl Drop for ArrowBuilder<'_, '_, '_, T> { } } -impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Draw an arrow in 3D, from `start` to `end`. Has four tips for convenient viewing from any direction. /// /// This should be called for each frame the arrow needs to be rendered. @@ -111,7 +127,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { start: Vec3, end: Vec3, color: impl Into, - ) -> ArrowBuilder<'_, 'w, 's, T> { + ) -> ArrowBuilder<'_, 'w, 's, Config, Clear> { let length = (end - start).length(); ArrowBuilder { gizmos: self, @@ -143,12 +159,16 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { start: Vec2, end: Vec2, color: impl Into, - ) -> ArrowBuilder<'_, 'w, 's, T> { + ) -> ArrowBuilder<'_, 'w, 's, Config, Clear> { self.arrow(start.extend(0.), end.extend(0.), color) } } -impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Draw a set of axes local to the given transform (`transform`), with length scaled by a factor /// of `base_length`. /// diff --git a/crates/bevy_gizmos/src/circles.rs b/crates/bevy_gizmos/src/circles.rs index af22d09527..af94ad9374 100644 --- a/crates/bevy_gizmos/src/circles.rs +++ b/crates/bevy_gizmos/src/circles.rs @@ -19,7 +19,11 @@ fn ellipse_inner(half_size: Vec2, segments: usize) -> impl Iterator }) } -impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Draw an ellipse in 3D at `position` with the flat side facing `normal`. /// /// This should be called for each frame the ellipse needs to be rendered. @@ -48,7 +52,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { rotation: Quat, half_size: Vec2, color: impl Into, - ) -> EllipseBuilder<'_, 'w, 's, T> { + ) -> EllipseBuilder<'_, 'w, 's, Config, Clear> { EllipseBuilder { gizmos: self, position, @@ -87,7 +91,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { angle: f32, half_size: Vec2, color: impl Into, - ) -> Ellipse2dBuilder<'_, 'w, 's, T> { + ) -> Ellipse2dBuilder<'_, 'w, 's, Config, Clear> { Ellipse2dBuilder { gizmos: self, position, @@ -126,7 +130,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { normal: Dir3, radius: f32, color: impl Into, - ) -> EllipseBuilder<'_, 'w, 's, T> { + ) -> EllipseBuilder<'_, 'w, 's, Config, Clear> { EllipseBuilder { gizmos: self, position, @@ -164,7 +168,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { position: Vec2, radius: f32, color: impl Into, - ) -> Ellipse2dBuilder<'_, 'w, 's, T> { + ) -> Ellipse2dBuilder<'_, 'w, 's, Config, Clear> { Ellipse2dBuilder { gizmos: self, position, @@ -177,8 +181,12 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { } /// A builder returned by [`Gizmos::ellipse`]. -pub struct EllipseBuilder<'a, 'w, 's, T: GizmoConfigGroup> { - gizmos: &'a mut Gizmos<'w, 's, T>, +pub struct EllipseBuilder<'a, 'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, position: Vec3, rotation: Quat, half_size: Vec2, @@ -186,7 +194,11 @@ pub struct EllipseBuilder<'a, 'w, 's, T: GizmoConfigGroup> { segments: usize, } -impl EllipseBuilder<'_, '_, '_, T> { +impl EllipseBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Set the number of line-segments for this ellipse. pub fn segments(mut self, segments: usize) -> Self { self.segments = segments; @@ -194,7 +206,11 @@ impl EllipseBuilder<'_, '_, '_, T> { } } -impl Drop for EllipseBuilder<'_, '_, '_, T> { +impl Drop for EllipseBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ fn drop(&mut self) { if !self.gizmos.enabled { return; @@ -208,8 +224,12 @@ impl Drop for EllipseBuilder<'_, '_, '_, T> { } /// A builder returned by [`Gizmos::ellipse_2d`]. -pub struct Ellipse2dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { - gizmos: &'a mut Gizmos<'w, 's, T>, +pub struct Ellipse2dBuilder<'a, 'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, position: Vec2, rotation: Mat2, half_size: Vec2, @@ -217,7 +237,11 @@ pub struct Ellipse2dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { segments: usize, } -impl Ellipse2dBuilder<'_, '_, '_, T> { +impl Ellipse2dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Set the number of line-segments for this ellipse. pub fn segments(mut self, segments: usize) -> Self { self.segments = segments; @@ -225,7 +249,12 @@ impl Ellipse2dBuilder<'_, '_, '_, T> { } } -impl Drop for Ellipse2dBuilder<'_, '_, '_, T> { +impl Drop for Ellipse2dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + /// Set the number of line-segments for this ellipse. fn drop(&mut self) { if !self.gizmos.enabled { return; diff --git a/crates/bevy_gizmos/src/gizmos.rs b/crates/bevy_gizmos/src/gizmos.rs index bf0cc8a9c2..c62e8b25d8 100644 --- a/crates/bevy_gizmos/src/gizmos.rs +++ b/crates/bevy_gizmos/src/gizmos.rs @@ -1,6 +1,6 @@ //! A module for the [`Gizmos`] [`SystemParam`]. -use std::{iter, marker::PhantomData}; +use std::{iter, marker::PhantomData, mem}; use crate::circles::DEFAULT_CIRCLE_SEGMENTS; use bevy_color::{Color, LinearRgba}; @@ -11,6 +11,7 @@ use bevy_ecs::{ }; use bevy_math::{Dir3, Quat, Rotation2d, Vec2, Vec3}; use bevy_transform::TransformPoint; +use bevy_utils::default; use crate::{ config::GizmoConfigGroup, @@ -18,47 +19,157 @@ use crate::{ prelude::GizmoConfig, }; -#[derive(Resource, Default)] -pub(crate) struct GizmoStorage { +/// Storage of gizmo primitives. +#[derive(Resource)] +pub struct GizmoStorage { pub(crate) list_positions: Vec, pub(crate) list_colors: Vec, pub(crate) strip_positions: Vec, pub(crate) strip_colors: Vec, - marker: PhantomData, + marker: PhantomData<(Config, Clear)>, } +impl Default for GizmoStorage { + fn default() -> Self { + Self { + list_positions: default(), + list_colors: default(), + strip_positions: default(), + strip_colors: default(), + marker: PhantomData, + } + } +} + +impl GizmoStorage +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + /// Combine the other gizmo storage with this one. + pub fn append_storage( + &mut self, + other: &GizmoStorage, + ) { + self.list_positions.extend(other.list_positions.iter()); + self.list_colors.extend(other.list_colors.iter()); + self.strip_positions.extend(other.strip_positions.iter()); + self.strip_colors.extend(other.strip_colors.iter()); + } + + pub(crate) fn swap( + &mut self, + other: &mut GizmoStorage, + ) { + mem::swap(&mut self.list_positions, &mut other.list_positions); + mem::swap(&mut self.list_colors, &mut other.list_colors); + mem::swap(&mut self.strip_positions, &mut other.strip_positions); + mem::swap(&mut self.strip_colors, &mut other.strip_colors); + } + + /// Clear this gizmo storage of any requested gizmos. + pub fn clear(&mut self) { + self.list_positions.clear(); + self.list_colors.clear(); + self.strip_positions.clear(); + self.strip_colors.clear(); + } +} + +/// Swap buffer for a specific clearing context. +/// +/// This is to stash/store the default/requested gizmos so another context can +/// be substituted for that duration. +pub struct Swap(PhantomData); + /// A [`SystemParam`] for drawing gizmos. /// /// They are drawn in immediate mode, which means they will be rendered only for -/// the frames in which they are spawned. -/// Gizmos should be spawned before the [`Last`](bevy_app::Last) schedule to ensure they are drawn. -pub struct Gizmos<'w, 's, T: GizmoConfigGroup = DefaultGizmoConfigGroup> { - buffer: Deferred<'s, GizmoBuffer>, +/// the frames, or ticks when in [`FixedMain`](bevy_app::FixedMain), in which +/// they are spawned. +/// +/// A system in [`Main`](bevy_app::Main) will be cleared each rendering +/// frame, while a system in [`FixedMain`](bevy_app::FixedMain) will be +/// cleared each time the [`RunFixedMainLoop`](bevy_app::RunFixedMainLoop) +/// schedule is run. +/// +/// Gizmos should be spawned before the [`Last`](bevy_app::Last) schedule +/// to ensure they are drawn. +/// +/// To set up your own clearing context (useful for custom scheduling similar +/// to [`FixedMain`](bevy_app::FixedMain)): +/// +/// ``` +/// use bevy_gizmos::{prelude::*, *, gizmos::GizmoStorage}; +/// # use bevy_app::prelude::*; +/// # use bevy_ecs::{schedule::ScheduleLabel, prelude::*}; +/// # #[derive(ScheduleLabel, Clone, Debug, PartialEq, Eq, Hash)] +/// # struct StartOfMyContext; +/// # #[derive(ScheduleLabel, Clone, Debug, PartialEq, Eq, Hash)] +/// # struct EndOfMyContext; +/// # #[derive(ScheduleLabel, Clone, Debug, PartialEq, Eq, Hash)] +/// # struct StartOfRun; +/// # #[derive(ScheduleLabel, Clone, Debug, PartialEq, Eq, Hash)] +/// # struct EndOfRun; +/// # struct MyContext; +/// struct ClearContextSetup; +/// impl Plugin for ClearContextSetup { +/// fn build(&self, app: &mut App) { +/// app.init_resource::>() +/// // Make sure this context starts/ends cleanly if inside another context. E.g. it +/// // should start after the parent context starts and end after the parent context ends. +/// .add_systems(StartOfMyContext, start_gizmo_context::) +/// // If not running multiple times, put this with [`start_gizmo_context`]. +/// .add_systems(StartOfRun, clear_gizmo_context::) +/// // If not running multiple times, put this with [`end_gizmo_context`]. +/// .add_systems(EndOfRun, collect_requested_gizmos::) +/// .add_systems(EndOfMyContext, end_gizmo_context::) +/// .add_systems( +/// Last, +/// propagate_gizmos::.before(UpdateGizmoMeshes), +/// ); +/// } +/// } +/// ``` +pub struct Gizmos<'w, 's, Config = DefaultGizmoConfigGroup, Clear = ()> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + buffer: Deferred<'s, GizmoBuffer>, pub(crate) enabled: bool, /// The currently used [`GizmoConfig`] pub config: &'w GizmoConfig, /// The currently used [`GizmoConfigGroup`] - pub config_ext: &'w T, + pub config_ext: &'w Config, } -type GizmosState = ( - Deferred<'static, GizmoBuffer>, +type GizmosState = ( + Deferred<'static, GizmoBuffer>, Res<'static, GizmoConfigStore>, ); #[doc(hidden)] -pub struct GizmosFetchState { - state: as SystemParam>::State, +pub struct GizmosFetchState +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + state: as SystemParam>::State, } #[allow(unsafe_code)] // SAFETY: All methods are delegated to existing `SystemParam` implementations -unsafe impl SystemParam for Gizmos<'_, '_, T> { - type State = GizmosFetchState; - type Item<'w, 's> = Gizmos<'w, 's, T>; +unsafe impl SystemParam for Gizmos<'_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + type State = GizmosFetchState; + type Item<'w, 's> = Gizmos<'w, 's, Config, Clear>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { GizmosFetchState { - state: GizmosState::::init_state(world, system_meta), + state: GizmosState::::init_state(world, system_meta), } } @@ -68,11 +179,13 @@ unsafe impl SystemParam for Gizmos<'_, '_, T> { system_meta: &mut SystemMeta, ) { // SAFETY: The caller ensures that `archetype` is from the World the state was initialized from in `init_state`. - unsafe { GizmosState::::new_archetype(&mut state.state, archetype, system_meta) }; + unsafe { + GizmosState::::new_archetype(&mut state.state, archetype, system_meta); + }; } fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) { - GizmosState::::apply(&mut state.state, system_meta, world); + GizmosState::::apply(&mut state.state, system_meta, world); } unsafe fn get_param<'w, 's>( @@ -83,12 +196,17 @@ unsafe impl SystemParam for Gizmos<'_, '_, T> { ) -> Self::Item<'w, 's> { // SAFETY: Delegated to existing `SystemParam` implementations let (f0, f1) = unsafe { - GizmosState::::get_param(&mut state.state, system_meta, world, change_tick) + GizmosState::::get_param( + &mut state.state, + system_meta, + world, + change_tick, + ) }; // Accessing the GizmoConfigStore in the immediate mode API reduces performance significantly. // Implementing SystemParam manually allows us to do it to here // Having config available allows for early returns when gizmos are disabled - let (config, config_ext) = f1.into_inner().config::(); + let (config, config_ext) = f1.into_inner().config::(); Gizmos { buffer: f0, enabled: config.enabled, @@ -100,25 +218,50 @@ unsafe impl SystemParam for Gizmos<'_, '_, T> { #[allow(unsafe_code)] // Safety: Each field is `ReadOnlySystemParam`, and Gizmos SystemParam does not mutate world -unsafe impl<'w, 's, T: GizmoConfigGroup> ReadOnlySystemParam for Gizmos<'w, 's, T> +unsafe impl<'w, 's, Config, Clear> ReadOnlySystemParam for Gizmos<'w, 's, Config, Clear> where - Deferred<'s, GizmoBuffer>: ReadOnlySystemParam, + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, + Deferred<'s, GizmoBuffer>: ReadOnlySystemParam, Res<'w, GizmoConfigStore>: ReadOnlySystemParam, { } -#[derive(Default)] -struct GizmoBuffer { +struct GizmoBuffer +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ list_positions: Vec, list_colors: Vec, strip_positions: Vec, strip_colors: Vec, - marker: PhantomData, + marker: PhantomData<(Config, Clear)>, } -impl SystemBuffer for GizmoBuffer { +impl Default for GizmoBuffer +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + fn default() -> Self { + Self { + list_positions: default(), + list_colors: default(), + strip_positions: default(), + strip_colors: default(), + marker: PhantomData, + } + } +} + +impl SystemBuffer for GizmoBuffer +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ fn apply(&mut self, _system_meta: &SystemMeta, world: &mut World) { - let mut storage = world.resource_mut::>(); + let mut storage = world.resource_mut::>(); storage.list_positions.append(&mut self.list_positions); storage.list_colors.append(&mut self.list_colors); storage.strip_positions.append(&mut self.strip_positions); @@ -126,7 +269,11 @@ impl SystemBuffer for GizmoBuffer { } } -impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Draw a line in 3D from `start` to `end`. /// /// This should be called for each frame the line needs to be rendered. @@ -340,7 +487,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { rotation: Quat, radius: f32, color: impl Into, - ) -> SphereBuilder<'_, 'w, 's, T> { + ) -> SphereBuilder<'_, 'w, 's, Config, Clear> { SphereBuilder { gizmos: self, position, @@ -644,8 +791,12 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { } /// A builder returned by [`Gizmos::sphere`]. -pub struct SphereBuilder<'a, 'w, 's, T: GizmoConfigGroup> { - gizmos: &'a mut Gizmos<'w, 's, T>, +pub struct SphereBuilder<'a, 'w, 's, Config, Clear = ()> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, position: Vec3, rotation: Quat, radius: f32, @@ -653,7 +804,11 @@ pub struct SphereBuilder<'a, 'w, 's, T: GizmoConfigGroup> { circle_segments: usize, } -impl SphereBuilder<'_, '_, '_, T> { +impl SphereBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Set the number of line-segments per circle for this sphere. pub fn circle_segments(mut self, segments: usize) -> Self { self.circle_segments = segments; @@ -661,7 +816,11 @@ impl SphereBuilder<'_, '_, '_, T> { } } -impl Drop for SphereBuilder<'_, '_, '_, T> { +impl Drop for SphereBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ fn drop(&mut self) { if !self.gizmos.enabled { return; diff --git a/crates/bevy_gizmos/src/grid.rs b/crates/bevy_gizmos/src/grid.rs index a00a8c4fa1..7c7e3b5fa7 100644 --- a/crates/bevy_gizmos/src/grid.rs +++ b/crates/bevy_gizmos/src/grid.rs @@ -8,8 +8,12 @@ use bevy_color::LinearRgba; use bevy_math::{Quat, UVec2, UVec3, Vec2, Vec3}; /// A builder returned by [`Gizmos::grid_3d`] -pub struct GridBuilder3d<'a, 'w, 's, T: GizmoConfigGroup> { - gizmos: &'a mut Gizmos<'w, 's, T>, +pub struct GridBuilder3d<'a, 'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, position: Vec3, rotation: Quat, spacing: Vec3, @@ -19,8 +23,12 @@ pub struct GridBuilder3d<'a, 'w, 's, T: GizmoConfigGroup> { color: LinearRgba, } /// A builder returned by [`Gizmos::grid`] and [`Gizmos::grid_2d`] -pub struct GridBuilder2d<'a, 'w, 's, T: GizmoConfigGroup> { - gizmos: &'a mut Gizmos<'w, 's, T>, +pub struct GridBuilder2d<'a, 'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, position: Vec3, rotation: Quat, spacing: Vec2, @@ -30,7 +38,11 @@ pub struct GridBuilder2d<'a, 'w, 's, T: GizmoConfigGroup> { color: LinearRgba, } -impl GridBuilder3d<'_, '_, '_, T> { +impl GridBuilder3d<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Skews the grid by `tan(skew)` in the x direction. /// `skew` is in radians pub fn skew_x(mut self, skew: f32) -> Self { @@ -81,7 +93,12 @@ impl GridBuilder3d<'_, '_, '_, T> { self } } -impl GridBuilder2d<'_, '_, '_, T> { + +impl GridBuilder2d<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Skews the grid by `tan(skew)` in the x direction. /// `skew` is in radians pub fn skew_x(mut self, skew: f32) -> Self { @@ -121,7 +138,12 @@ impl GridBuilder2d<'_, '_, '_, T> { } } -impl Drop for GridBuilder3d<'_, '_, '_, T> { +impl Drop for GridBuilder3d<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + /// Draws a grid, by drawing lines with the stored [`Gizmos`] fn drop(&mut self) { draw_grid( self.gizmos, @@ -135,7 +157,12 @@ impl Drop for GridBuilder3d<'_, '_, '_, T> { ); } } -impl Drop for GridBuilder2d<'_, '_, '_, T> { + +impl Drop for GridBuilder2d<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ fn drop(&mut self) { draw_grid( self.gizmos, @@ -149,7 +176,11 @@ impl Drop for GridBuilder2d<'_, '_, '_, T> { ); } } -impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Draw a 2D grid in 3D. /// /// This should be called for each frame the grid needs to be rendered. @@ -193,7 +224,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { cell_count: UVec2, spacing: Vec2, color: impl Into, - ) -> GridBuilder2d<'_, 'w, 's, T> { + ) -> GridBuilder2d<'_, 'w, 's, Config, Clear> { GridBuilder2d { gizmos: self, position, @@ -249,7 +280,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { cell_count: UVec3, spacing: Vec3, color: impl Into, - ) -> GridBuilder3d<'_, 'w, 's, T> { + ) -> GridBuilder3d<'_, 'w, 's, Config, Clear> { GridBuilder3d { gizmos: self, position, @@ -305,7 +336,7 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { cell_count: UVec2, spacing: Vec2, color: impl Into, - ) -> GridBuilder2d<'_, 'w, 's, T> { + ) -> GridBuilder2d<'_, 'w, 's, Config, Clear> { GridBuilder2d { gizmos: self, position: position.extend(0.), @@ -320,8 +351,8 @@ impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> { } #[allow(clippy::too_many_arguments)] -fn draw_grid( - gizmos: &mut Gizmos<'_, '_, T>, +fn draw_grid( + gizmos: &mut Gizmos<'_, '_, Config, Clear>, position: Vec3, rotation: Quat, spacing: Vec3, @@ -329,7 +360,10 @@ fn draw_grid( skew: Vec3, outer_edges: [bool; 3], color: LinearRgba, -) { +) where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ if !gizmos.enabled { return; } diff --git a/crates/bevy_gizmos/src/lib.rs b/crates/bevy_gizmos/src/lib.rs index 06f9d762d8..d523f0dd54 100644 --- a/crates/bevy_gizmos/src/lib.rs +++ b/crates/bevy_gizmos/src/lib.rs @@ -67,7 +67,7 @@ pub mod prelude { } use aabb::AabbGizmoPlugin; -use bevy_app::{App, Last, Plugin}; +use bevy_app::{App, FixedFirst, FixedLast, Last, Plugin, RunFixedMainLoop}; use bevy_asset::{load_internal_asset, Asset, AssetApp, Assets, Handle}; use bevy_color::LinearRgba; use bevy_ecs::{ @@ -93,13 +93,14 @@ use bevy_render::{ renderer::RenderDevice, Extract, ExtractSchedule, Render, RenderApp, RenderSet, }; +use bevy_time::Fixed; use bevy_utils::TypeIdMap; use bytemuck::cast_slice; use config::{ DefaultGizmoConfigGroup, GizmoConfig, GizmoConfigGroup, GizmoConfigStore, GizmoLineJoint, GizmoMeshConfig, }; -use gizmos::GizmoStorage; +use gizmos::{GizmoStorage, Swap}; #[cfg(feature = "bevy_pbr")] use light::LightGizmoPlugin; use std::{any::TypeId, mem}; @@ -186,67 +187,75 @@ impl Plugin for GizmoPlugin { } } -/// A trait adding `init_gizmo_group()` to the app +/// A extension trait adding `App::init_gizmo_group` and `App::insert_gizmo_config`. pub trait AppGizmoBuilder { - /// Registers [`GizmoConfigGroup`] `T` in the app enabling the use of [Gizmos<T>](crate::gizmos::Gizmos). + /// Registers [`GizmoConfigGroup`] in the app enabling the use of [Gizmos<Config>](crate::gizmos::Gizmos). /// /// Configurations can be set using the [`GizmoConfigStore`] [`Resource`]. - fn init_gizmo_group(&mut self) -> &mut Self; + fn init_gizmo_group(&mut self) -> &mut Self; - /// Insert the [`GizmoConfigGroup`] in the app with the given value and [`GizmoConfig`]. + /// Insert a [`GizmoConfig`] into a specific [`GizmoConfigGroup`]. /// /// This method should be preferred over [`AppGizmoBuilder::init_gizmo_group`] if and only if you need to configure fields upon initialization. - fn insert_gizmo_group( + fn insert_gizmo_config( &mut self, - group: T, + group: Config, config: GizmoConfig, ) -> &mut Self; } impl AppGizmoBuilder for App { - fn init_gizmo_group(&mut self) -> &mut Self { - if self.world().contains_resource::>() { + fn init_gizmo_group(&mut self) -> &mut Self { + if self.world().contains_resource::>() { return self; } + self.world_mut() + .get_resource_or_insert_with::(Default::default) + .register::(); + let mut handles = self .world_mut() .get_resource_or_insert_with::(Default::default); - handles.list.insert(TypeId::of::(), None); - handles.strip.insert(TypeId::of::(), None); - self.init_resource::>() - .add_systems(Last, update_gizmo_meshes::); + handles.list.insert(TypeId::of::(), None); + handles.strip.insert(TypeId::of::(), None); - self.world_mut() - .get_resource_or_insert_with::(Default::default) - .register::(); + self.init_resource::>() + .init_resource::>() + .init_resource::>>() + .add_systems( + RunFixedMainLoop, + start_gizmo_context::.before(bevy_time::run_fixed_main_schedule), + ) + .add_systems(FixedFirst, clear_gizmo_context::) + .add_systems(FixedLast, collect_requested_gizmos::) + .add_systems( + RunFixedMainLoop, + end_gizmo_context::.after(bevy_time::run_fixed_main_schedule), + ) + .add_systems( + Last, + ( + propagate_gizmos::.before(UpdateGizmoMeshes), + update_gizmo_meshes::.in_set(UpdateGizmoMeshes), + ), + ); self } - fn insert_gizmo_group( + fn insert_gizmo_config( &mut self, - group: T, + group: Config, config: GizmoConfig, ) -> &mut Self { + self.init_gizmo_group::(); + self.world_mut() .get_resource_or_insert_with::(Default::default) .insert(config, group); - if self.world().contains_resource::>() { - return self; - } - - let mut handles = self - .world_mut() - .get_resource_or_insert_with::(Default::default); - handles.list.insert(TypeId::of::(), None); - handles.strip.insert(TypeId::of::(), None); - - self.init_resource::>() - .add_systems(Last, update_gizmo_meshes::); - self } } @@ -262,15 +271,87 @@ struct LineGizmoHandles { strip: TypeIdMap>>, } -fn update_gizmo_meshes( +/// Start a new gizmo clearing context. +/// +/// Internally this pushes the parent default context into a swap buffer. +/// Gizmo contexts should be handled like a stack, so if you push a new context, +/// you must pop the context before the parent context ends. +pub fn start_gizmo_context( + mut swap: ResMut>>, + mut default: ResMut>, +) where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + default.swap(&mut *swap); +} + +/// End this gizmo clearing context. +/// +/// Pop the default gizmos context out of the [`Swap`] gizmo storage. +/// +/// This must be called before [`UpdateGizmoMeshes`] in the [`Last`] schedule. +pub fn end_gizmo_context( + mut swap: ResMut>>, + mut default: ResMut>, +) where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + default.clear(); + default.swap(&mut *swap); +} + +/// Collect the requested gizmos into a specific clear context. +pub fn collect_requested_gizmos( + mut update: ResMut>, + mut context: ResMut>, +) where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + context.append_storage(&update); + update.clear(); +} + +/// Clear out the contextual gizmos. +pub fn clear_gizmo_context(mut context: ResMut>) +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + context.clear(); +} + +/// Propagate the contextual gizmo into the `Update` storage for rendering. +/// +/// This should be before [`UpdateGizmoMeshes`]. +pub fn propagate_gizmos( + mut update_storage: ResMut>, + contextual_storage: Res>, +) where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + update_storage.append_storage(&*contextual_storage); +} + +/// System set for updating the rendering meshes for drawing gizmos. +#[derive(SystemSet, Clone, Debug, PartialEq, Eq, Hash)] +pub struct UpdateGizmoMeshes; + +/// Prepare gizmos for rendering. +/// +/// This also clears the default `GizmoStorage`. +fn update_gizmo_meshes( mut line_gizmos: ResMut>, mut handles: ResMut, - mut storage: ResMut>, + mut storage: ResMut>, config_store: Res, ) { if storage.list_positions.is_empty() { - handles.list.insert(TypeId::of::(), None); - } else if let Some(handle) = handles.list.get_mut(&TypeId::of::()) { + handles.list.insert(TypeId::of::(), None); + } else if let Some(handle) = handles.list.get_mut(&TypeId::of::()) { if let Some(handle) = handle { let list = line_gizmos.get_mut(handle.id()).unwrap(); @@ -289,10 +370,10 @@ fn update_gizmo_meshes( } } - let (config, _) = config_store.config::(); + let (config, _) = config_store.config::(); if storage.strip_positions.is_empty() { - handles.strip.insert(TypeId::of::(), None); - } else if let Some(handle) = handles.strip.get_mut(&TypeId::of::()) { + handles.strip.insert(TypeId::of::(), None); + } else if let Some(handle) = handles.strip.get_mut(&TypeId::of::()) { if let Some(handle) = handle { let strip = line_gizmos.get_mut(handle.id()).unwrap(); diff --git a/crates/bevy_gizmos/src/primitives/dim2.rs b/crates/bevy_gizmos/src/primitives/dim2.rs index dfc2813b5e..1162df7da9 100644 --- a/crates/bevy_gizmos/src/primitives/dim2.rs +++ b/crates/bevy_gizmos/src/primitives/dim2.rs @@ -38,7 +38,11 @@ pub trait GizmoPrimitive2d { // direction 2d -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> GizmoPrimitive2d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ type Output<'a> = () where Self : 'a; fn primitive_2d( @@ -62,7 +66,11 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's, T> { // circle 2d -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> GizmoPrimitive2d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ type Output<'a> = () where Self: 'a; fn primitive_2d( @@ -82,7 +90,11 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's, T> // ellipse 2d -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> GizmoPrimitive2d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ type Output<'a> = () where Self: 'a; fn primitive_2d( @@ -102,7 +114,11 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's, T // capsule 2d -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> GizmoPrimitive2d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ type Output<'a> = () where Self: 'a; fn primitive_2d( @@ -168,8 +184,12 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's, // line 2d // /// Builder for configuring the drawing options of [`Line2d`]. -pub struct Line2dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { - gizmos: &'a mut Gizmos<'w, 's, T>, +pub struct Line2dBuilder<'a, 'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, direction: Dir2, // Direction of the line @@ -180,7 +200,11 @@ pub struct Line2dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { draw_arrow: bool, // decides whether to indicate the direction of the line with an arrow } -impl Line2dBuilder<'_, '_, '_, T> { +impl Line2dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Set the drawing mode of the line (arrow vs. plain line) pub fn draw_arrow(mut self, is_enabled: bool) -> Self { self.draw_arrow = is_enabled; @@ -188,8 +212,12 @@ impl Line2dBuilder<'_, '_, '_, T> { } } -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's, T> { - type Output<'a> = Line2dBuilder<'a, 'w, 's, T> where Self: 'a; +impl<'w, 's, Config, Clear> GizmoPrimitive2d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + type Output<'a> = Line2dBuilder<'a, 'w, 's, Config, Clear> where Self: 'a; fn primitive_2d( &mut self, @@ -209,7 +237,11 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's, T> } } -impl Drop for Line2dBuilder<'_, '_, '_, T> { +impl Drop for Line2dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ fn drop(&mut self) { if !self.gizmos.enabled { return; @@ -239,7 +271,11 @@ impl Drop for Line2dBuilder<'_, '_, '_, T> { // plane 2d -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> GizmoPrimitive2d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ type Output<'a> = () where Self: 'a; fn primitive_2d( @@ -289,8 +325,12 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's, T // segment 2d /// Builder for configuring the drawing options of [`Segment2d`]. -pub struct Segment2dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { - gizmos: &'a mut Gizmos<'w, 's, T>, +pub struct Segment2dBuilder<'a, 'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, direction: Dir2, // Direction of the line segment half_length: f32, // Half-length of the line segment @@ -302,7 +342,11 @@ pub struct Segment2dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { draw_arrow: bool, // decides whether to draw just a line or an arrow } -impl Segment2dBuilder<'_, '_, '_, T> { +impl Segment2dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Set the drawing mode of the line (arrow vs. plain line) pub fn draw_arrow(mut self, is_enabled: bool) -> Self { self.draw_arrow = is_enabled; @@ -310,8 +354,12 @@ impl Segment2dBuilder<'_, '_, '_, T> { } } -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's, T> { - type Output<'a> = Segment2dBuilder<'a, 'w, 's, T> where Self: 'a; +impl<'w, 's, Config, Clear> GizmoPrimitive2d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + type Output<'a> = Segment2dBuilder<'a, 'w, 's, Config, Clear> where Self: 'a; fn primitive_2d( &mut self, @@ -334,7 +382,11 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's, } } -impl Drop for Segment2dBuilder<'_, '_, '_, T> { +impl Drop for Segment2dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ fn drop(&mut self) { if !self.gizmos.enabled { return; @@ -354,8 +406,11 @@ impl Drop for Segment2dBuilder<'_, '_, '_, T> { // polyline 2d -impl<'w, 's, const N: usize, T: GizmoConfigGroup> GizmoPrimitive2d> - for Gizmos<'w, 's, T> +impl<'w, 's, const N: usize, Config, Clear> GizmoPrimitive2d> + for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, { type Output<'a> = () where Self: 'a; @@ -383,7 +438,11 @@ impl<'w, 's, const N: usize, T: GizmoConfigGroup> GizmoPrimitive2d // boxed polyline 2d -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> GizmoPrimitive2d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ type Output<'a> = () where Self: 'a; fn primitive_2d( @@ -410,7 +469,11 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<' // triangle 2d -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> GizmoPrimitive2d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ type Output<'a> = () where Self: 'a; fn primitive_2d( @@ -431,7 +494,11 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's // rectangle 2d -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> GizmoPrimitive2d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ type Output<'a> = () where Self: 'a; fn primitive_2d( @@ -459,8 +526,11 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's, // polygon 2d -impl<'w, 's, const N: usize, T: GizmoConfigGroup> GizmoPrimitive2d> - for Gizmos<'w, 's, T> +impl<'w, 's, const N: usize, Config, Clear> GizmoPrimitive2d> + for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, { type Output<'a> = () where Self: 'a; @@ -498,7 +568,11 @@ impl<'w, 's, const N: usize, T: GizmoConfigGroup> GizmoPrimitive2d> // boxed polygon 2d -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> GizmoPrimitive2d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ type Output<'a> = () where Self: 'a; fn primitive_2d( @@ -533,7 +607,11 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, // regular polygon 2d -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive2d for Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> GizmoPrimitive2d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ type Output<'a> = () where Self: 'a; fn primitive_2d( diff --git a/crates/bevy_gizmos/src/primitives/dim3.rs b/crates/bevy_gizmos/src/primitives/dim3.rs index 025b2f74fa..66924fbb3f 100644 --- a/crates/bevy_gizmos/src/primitives/dim3.rs +++ b/crates/bevy_gizmos/src/primitives/dim3.rs @@ -35,7 +35,11 @@ pub trait GizmoPrimitive3d { // direction 3d -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> GizmoPrimitive3d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ type Output<'a> = () where Self: 'a; fn primitive_3d( @@ -52,8 +56,12 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, T> { // sphere /// Builder for configuring the drawing options of [`Sphere`]. -pub struct SphereBuilder<'a, 'w, 's, T: GizmoConfigGroup> { - gizmos: &'a mut Gizmos<'w, 's, T>, +pub struct SphereBuilder<'a, 'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, // Radius of the sphere radius: f32, @@ -69,7 +77,11 @@ pub struct SphereBuilder<'a, 'w, 's, T: GizmoConfigGroup> { segments: usize, } -impl SphereBuilder<'_, '_, '_, T> { +impl SphereBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Set the number of segments used to approximate the sphere geometry. pub fn segments(mut self, segments: usize) -> Self { self.segments = segments; @@ -77,8 +89,12 @@ impl SphereBuilder<'_, '_, '_, T> { } } -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, T> { - type Output<'a> = SphereBuilder<'a, 'w, 's, T> where Self: 'a; +impl<'w, 's, Config, Clear> GizmoPrimitive3d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + type Output<'a> = SphereBuilder<'a, 'w, 's, Config, Clear> where Self: 'a; fn primitive_3d( &mut self, @@ -98,7 +114,11 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, T> } } -impl Drop for SphereBuilder<'_, '_, '_, T> { +impl Drop for SphereBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ fn drop(&mut self) { if !self.gizmos.enabled { return; @@ -135,8 +155,12 @@ impl Drop for SphereBuilder<'_, '_, '_, T> { // plane 3d /// Builder for configuring the drawing options of [`Plane3d`]. -pub struct Plane3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { - gizmos: &'a mut Gizmos<'w, 's, T>, +pub struct Plane3dBuilder<'a, 'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, // direction of the normal orthogonal to the plane normal: Dir3, @@ -156,7 +180,11 @@ pub struct Plane3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { segment_length: f32, } -impl Plane3dBuilder<'_, '_, '_, T> { +impl Plane3dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Set the number of segments used to hint the plane. pub fn segment_count(mut self, count: usize) -> Self { self.segment_count = count; @@ -176,8 +204,12 @@ impl Plane3dBuilder<'_, '_, '_, T> { } } -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, T> { - type Output<'a> = Plane3dBuilder<'a, 'w, 's, T> where Self: 'a; +impl<'w, 's, Config, Clear> GizmoPrimitive3d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + type Output<'a> = Plane3dBuilder<'a, 'w, 's, Config, Clear> where Self: 'a; fn primitive_3d( &mut self, @@ -199,7 +231,11 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, T } } -impl Drop for Plane3dBuilder<'_, '_, '_, T> { +impl Drop for Plane3dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ fn drop(&mut self) { if !self.gizmos.enabled { return; @@ -243,7 +279,11 @@ impl Drop for Plane3dBuilder<'_, '_, '_, T> { // line 3d -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> GizmoPrimitive3d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ type Output<'a> = () where Self: 'a; fn primitive_3d( @@ -271,7 +311,11 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, T> // segment 3d -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> GizmoPrimitive3d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ type Output<'a> = () where Self: 'a; fn primitive_3d( @@ -294,8 +338,11 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, // polyline 3d -impl<'w, 's, const N: usize, T: GizmoConfigGroup> GizmoPrimitive3d> - for Gizmos<'w, 's, T> +impl<'w, 's, const N: usize, Config, Clear> GizmoPrimitive3d> + for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, { type Output<'a> = () where Self: 'a; @@ -321,7 +368,11 @@ impl<'w, 's, const N: usize, T: GizmoConfigGroup> GizmoPrimitive3d // boxed polyline 3d -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> GizmoPrimitive3d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ type Output<'a> = () where Self: 'a; fn primitive_3d( @@ -348,7 +399,11 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<' // cuboid -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, T> { +impl<'w, 's, Config, Clear> GizmoPrimitive3d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ type Output<'a> = () where Self: 'a; fn primitive_3d( @@ -404,8 +459,12 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, T> // cylinder 3d /// Builder for configuring the drawing options of [`Cylinder`]. -pub struct Cylinder3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { - gizmos: &'a mut Gizmos<'w, 's, T>, +pub struct Cylinder3dBuilder<'a, 'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, // Radius of the cylinder radius: f32, @@ -425,7 +484,11 @@ pub struct Cylinder3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { segments: usize, } -impl Cylinder3dBuilder<'_, '_, '_, T> { +impl Cylinder3dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Set the number of segments used to approximate the cylinder geometry. pub fn segments(mut self, segments: usize) -> Self { self.segments = segments; @@ -433,8 +496,12 @@ impl Cylinder3dBuilder<'_, '_, '_, T> { } } -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, T> { - type Output<'a> = Cylinder3dBuilder<'a, 'w, 's, T> where Self: 'a; +impl<'w, 's, Config, Clear> GizmoPrimitive3d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + type Output<'a> = Cylinder3dBuilder<'a, 'w, 's, Config, Clear> where Self: 'a; fn primitive_3d( &mut self, @@ -455,7 +522,11 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, } } -impl Drop for Cylinder3dBuilder<'_, '_, '_, T> { +impl Drop for Cylinder3dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ fn drop(&mut self) { if !self.gizmos.enabled { return; @@ -501,8 +572,12 @@ impl Drop for Cylinder3dBuilder<'_, '_, '_, T> { // capsule 3d /// Builder for configuring the drawing options of [`Capsule3d`]. -pub struct Capsule3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { - gizmos: &'a mut Gizmos<'w, 's, T>, +pub struct Capsule3dBuilder<'a, 'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, // Radius of the capsule radius: f32, @@ -522,7 +597,11 @@ pub struct Capsule3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { segments: usize, } -impl Capsule3dBuilder<'_, '_, '_, T> { +impl Capsule3dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Set the number of segments used to approximate the capsule geometry. pub fn segments(mut self, segments: usize) -> Self { self.segments = segments; @@ -530,8 +609,12 @@ impl Capsule3dBuilder<'_, '_, '_, T> { } } -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, T> { - type Output<'a> = Capsule3dBuilder<'a, 'w, 's, T> where Self: 'a; +impl<'w, 's, Config, Clear> GizmoPrimitive3d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + type Output<'a> = Capsule3dBuilder<'a, 'w, 's, Config, Clear> where Self: 'a; fn primitive_3d( &mut self, @@ -552,7 +635,11 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, } } -impl Drop for Capsule3dBuilder<'_, '_, '_, T> { +impl Drop for Capsule3dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ fn drop(&mut self) { if !self.gizmos.enabled { return; @@ -594,8 +681,12 @@ impl Drop for Capsule3dBuilder<'_, '_, '_, T> { // cone 3d /// Builder for configuring the drawing options of [`Cone`]. -pub struct Cone3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { - gizmos: &'a mut Gizmos<'w, 's, T>, +pub struct Cone3dBuilder<'a, 'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, // Radius of the cone radius: f32, @@ -618,7 +709,11 @@ pub struct Cone3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { height_segments: usize, } -impl Cone3dBuilder<'_, '_, '_, T> { +impl Cone3dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Set the number of segments used to approximate the cone geometry for its base and height. pub fn segments(mut self, segments: usize) -> Self { self.base_segments = segments; @@ -645,8 +740,12 @@ impl Cone3dBuilder<'_, '_, '_, T> { } } -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, T> { - type Output<'a> = Cone3dBuilder<'a, 'w, 's, T> where Self: 'a; +impl<'w, 's, Config, Clear> GizmoPrimitive3d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + type Output<'a> = Cone3dBuilder<'a, 'w, 's, Config, Clear> where Self: 'a; fn primitive_3d( &mut self, @@ -668,7 +767,11 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, T> { } } -impl Drop for Cone3dBuilder<'_, '_, '_, T> { +impl Drop for Cone3dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ fn drop(&mut self) { if !self.gizmos.enabled { return; @@ -712,8 +815,12 @@ impl Drop for Cone3dBuilder<'_, '_, '_, T> { // conical frustum 3d /// Builder for configuring the drawing options of [`ConicalFrustum`]. -pub struct ConicalFrustum3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { - gizmos: &'a mut Gizmos<'w, 's, T>, +pub struct ConicalFrustum3dBuilder<'a, 'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, // Radius of the top circle radius_top: f32, @@ -735,7 +842,11 @@ pub struct ConicalFrustum3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { segments: usize, } -impl ConicalFrustum3dBuilder<'_, '_, '_, T> { +impl ConicalFrustum3dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Set the number of segments used to approximate the curved surfaces. pub fn segments(mut self, segments: usize) -> Self { self.segments = segments; @@ -743,8 +854,12 @@ impl ConicalFrustum3dBuilder<'_, '_, '_, T> { } } -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, T> { - type Output<'a> = ConicalFrustum3dBuilder<'a, 'w, 's, T> where Self: 'a; +impl<'w, 's, Config, Clear> GizmoPrimitive3d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + type Output<'a> = ConicalFrustum3dBuilder<'a, 'w, 's, Config, Clear> where Self: 'a; fn primitive_3d( &mut self, @@ -766,7 +881,11 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w } } -impl Drop for ConicalFrustum3dBuilder<'_, '_, '_, T> { +impl Drop for ConicalFrustum3dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ fn drop(&mut self) { if !self.gizmos.enabled { return; @@ -818,8 +937,12 @@ impl Drop for ConicalFrustum3dBuilder<'_, '_, '_, T> { // torus 3d /// Builder for configuring the drawing options of [`Torus`]. -pub struct Torus3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { - gizmos: &'a mut Gizmos<'w, 's, T>, +pub struct Torus3dBuilder<'a, 'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, // Radius of the minor circle (tube) minor_radius: f32, @@ -841,7 +964,11 @@ pub struct Torus3dBuilder<'a, 'w, 's, T: GizmoConfigGroup> { major_segments: usize, } -impl Torus3dBuilder<'_, '_, '_, T> { +impl Torus3dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ /// Set the number of segments in the minor (tube) direction. pub fn minor_segments(mut self, minor_segments: usize) -> Self { self.minor_segments = minor_segments; @@ -855,8 +982,12 @@ impl Torus3dBuilder<'_, '_, '_, T> { } } -impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, T> { - type Output<'a> = Torus3dBuilder<'a, 'w, 's, T> where Self: 'a; +impl<'w, 's, Config, Clear> GizmoPrimitive3d for Gizmos<'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + type Output<'a> = Torus3dBuilder<'a, 'w, 's, Config, Clear> where Self: 'a; fn primitive_3d( &mut self, @@ -878,7 +1009,11 @@ impl<'w, 's, T: GizmoConfigGroup> GizmoPrimitive3d for Gizmos<'w, 's, T> } } -impl Drop for Torus3dBuilder<'_, '_, '_, T> { +impl Drop for Torus3dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ fn drop(&mut self) { if !self.gizmos.enabled { return; diff --git a/crates/bevy_gizmos/src/primitives/helpers.rs b/crates/bevy_gizmos/src/primitives/helpers.rs index 3de0502829..a60d079066 100644 --- a/crates/bevy_gizmos/src/primitives/helpers.rs +++ b/crates/bevy_gizmos/src/primitives/helpers.rs @@ -51,15 +51,18 @@ pub(crate) fn circle_coordinates(radius: f32, segments: usize) -> impl Iterator< /// This function draws a semi-sphere at the specified `center` point with the given `rotation`, /// `radius`, and `color`. The `segments` parameter determines the level of detail, and the `top` /// argument specifies the shape of the semi-sphere's tip. -pub(crate) fn draw_semi_sphere( - gizmos: &mut Gizmos<'_, '_, T>, +pub(crate) fn draw_semi_sphere( + gizmos: &mut Gizmos<'_, '_, Config, Clear>, radius: f32, segments: usize, rotation: Quat, center: Vec3, top: Vec3, color: Color, -) { +) where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ circle_coordinates(radius, segments) .map(|p| Vec3::new(p.x, 0.0, p.y)) .map(rotate_then_translate_3d(rotation, center)) @@ -75,14 +78,17 @@ pub(crate) fn draw_semi_sphere( /// # Note /// /// This function is necessary to use instead of `gizmos.circle` for certain primitives to ensure that points align correctly. For example, the major circles of a torus are drawn with this method, and using `gizmos.circle` would result in the minor circles not being positioned precisely on the major circles' segment points. -pub(crate) fn draw_circle_3d( - gizmos: &mut Gizmos<'_, '_, T>, +pub(crate) fn draw_circle_3d( + gizmos: &mut Gizmos<'_, '_, Config, Clear>, radius: f32, segments: usize, rotation: Quat, translation: Vec3, color: Color, -) { +) where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ let positions = (0..=segments) .map(|frac| frac as f32 / segments as f32) .map(|percentage| percentage * TAU) @@ -93,15 +99,18 @@ pub(crate) fn draw_circle_3d( } /// Draws the connecting lines of a cylinder between the top circle and the bottom circle. -pub(crate) fn draw_cylinder_vertical_lines( - gizmos: &mut Gizmos<'_, '_, T>, +pub(crate) fn draw_cylinder_vertical_lines( + gizmos: &mut Gizmos<'_, '_, Config, Clear>, radius: f32, segments: usize, half_height: f32, rotation: Quat, center: Vec3, color: Color, -) { +) where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ circle_coordinates(radius, segments) .map(move |point_2d| { [1.0, -1.0]