Skip to main content

bevy_gizmos/
curves.rs

1//! Additional [`GizmoBuffer`] Functions -- Curves
2//!
3//! Includes the implementation of [`GizmoBuffer::curve_2d`],
4//! [`GizmoBuffer::curve_3d`] and assorted support items.
5
6use bevy_color::Color;
7use bevy_curve::{Curve, CurveExt};
8use bevy_math::{Vec2, Vec3};
9
10use crate::{gizmos::GizmoBuffer, prelude::GizmoConfigGroup};
11
12impl<Config, Clear> GizmoBuffer<Config, Clear>
13where
14    Config: GizmoConfigGroup,
15    Clear: 'static + Send + Sync,
16{
17    /// Draw a curve, at the given time points, sampling in 2D.
18    ///
19    /// Samples of time points outside of the curve's domain will be filtered out and won't
20    /// contribute to the rendering. If you wish to render the curve outside of its domain you need
21    /// to create a new curve with an extended domain.
22    ///
23    /// # Arguments
24    /// - `curve_2d` some type that implements the [`Curve`] trait and samples `Vec2`s
25    /// - `times` some iterable type yielding `f32` which will be used for sampling the curve
26    /// - `color` the color of the curve
27    ///
28    /// # Example
29    /// ```
30    /// # use bevy_gizmos::prelude::*;
31    /// # use bevy_math::prelude::*;
32    /// # use bevy_curve::prelude::*;
33    /// # use bevy_color::palettes::basic::{RED};
34    /// fn system(mut gizmos: Gizmos) {
35    ///     let domain = Interval::UNIT;
36    ///     let curve = FunctionCurve::new(domain, |t| Vec2::from(t.sin_cos()));
37    ///     gizmos.curve_2d(curve, (0..=100).map(|n| n as f32 / 100.0), RED);
38    /// }
39    /// # bevy_ecs::system::assert_is_system(system);
40    /// ```
41    pub fn curve_2d(
42        &mut self,
43        curve_2d: impl Curve<Vec2>,
44        times: impl IntoIterator<Item = f32>,
45        color: impl Into<Color>,
46    ) {
47        self.linestrip_2d(curve_2d.sample_iter(times).flatten(), color);
48    }
49
50    /// Draw a curve, at the given time points, sampling in 3D.
51    ///
52    /// Samples of time points outside of the curve's domain will be filtered out and won't
53    /// contribute to the rendering. If you wish to render the curve outside of its domain you need
54    /// to create a new curve with an extended domain.
55    ///
56    /// # Arguments
57    /// - `curve_3d` some type that implements the [`Curve`] trait and samples `Vec3`s
58    /// - `times` some iterable type yielding `f32` which will be used for sampling the curve
59    /// - `color` the color of the curve
60    ///
61    /// # Example
62    /// ```
63    /// # use bevy_gizmos::prelude::*;
64    /// # use bevy_math::prelude::*;
65    /// # use bevy_curve::prelude::*;
66    /// # use bevy_color::palettes::basic::{RED};
67    /// fn system(mut gizmos: Gizmos) {
68    ///     let domain = Interval::UNIT;
69    ///     let curve = FunctionCurve::new(domain, |t| {
70    ///         let (x,y) = t.sin_cos();
71    ///         Vec3::new(x, y, t)
72    ///     });
73    ///     gizmos.curve_3d(curve, (0..=100).map(|n| n as f32 / 100.0), RED);
74    /// }
75    /// # bevy_ecs::system::assert_is_system(system);
76    /// ```
77    pub fn curve_3d(
78        &mut self,
79        curve_3d: impl Curve<Vec3>,
80        times: impl IntoIterator<Item = f32>,
81        color: impl Into<Color>,
82    ) {
83        self.linestrip(curve_3d.sample_iter(times).flatten(), color);
84    }
85
86    /// Draw a curve, at the given time points, sampling in 2D, with a color gradient.
87    ///
88    /// Samples of time points outside of the curve's domain will be filtered out and won't
89    /// contribute to the rendering. If you wish to render the curve outside of its domain you need
90    /// to create a new curve with an extended domain.
91    ///
92    /// # Arguments
93    /// - `curve_2d` some type that implements the [`Curve`] trait and samples `Vec2`s
94    /// - `times_with_colors` some iterable type yielding `f32` which will be used for sampling
95    ///   the curve together with the color at this position
96    ///
97    /// # Example
98    /// ```
99    /// # use bevy_gizmos::prelude::*;
100    /// # use bevy_math::prelude::*;
101    /// # use bevy_curve::prelude::*;
102    /// # use bevy_color::{Mix, palettes::basic::{GREEN, RED}};
103    /// fn system(mut gizmos: Gizmos) {
104    ///     let domain = Interval::UNIT;
105    ///     let curve = FunctionCurve::new(domain, |t| Vec2::from(t.sin_cos()));
106    ///     gizmos.curve_gradient_2d(
107    ///         curve,
108    ///         (0..=100).map(|n| n as f32 / 100.0)
109    ///                  .map(|t| (t, GREEN.mix(&RED, t)))
110    ///     );
111    /// }
112    /// # bevy_ecs::system::assert_is_system(system);
113    /// ```
114    pub fn curve_gradient_2d<C>(
115        &mut self,
116        curve_2d: impl Curve<Vec2>,
117        times_with_colors: impl IntoIterator<Item = (f32, C)>,
118    ) where
119        C: Into<Color>,
120    {
121        self.linestrip_gradient_2d(
122            times_with_colors
123                .into_iter()
124                .filter_map(|(time, color)| curve_2d.sample(time).map(|sample| (sample, color))),
125        );
126    }
127
128    /// Draw a curve, at the given time points, sampling in 3D, with a color gradient.
129    ///
130    /// Samples of time points outside of the curve's domain will be filtered out and won't
131    /// contribute to the rendering. If you wish to render the curve outside of its domain you need
132    /// to create a new curve with an extended domain.
133    ///
134    /// # Arguments
135    /// - `curve_3d` some type that implements the [`Curve`] trait and samples `Vec3`s
136    /// - `times_with_colors` some iterable type yielding `f32` which will be used for sampling
137    ///   the curve together with the color at this position
138    ///
139    /// # Example
140    /// ```
141    /// # use bevy_gizmos::prelude::*;
142    /// # use bevy_math::prelude::*;
143    /// # use bevy_curve::prelude::*;
144    /// # use bevy_color::{Mix, palettes::basic::{GREEN, RED}};
145    /// fn system(mut gizmos: Gizmos) {
146    ///     let domain = Interval::UNIT;
147    ///     let curve = FunctionCurve::new(domain, |t| {
148    ///         let (x,y) = t.sin_cos();
149    ///         Vec3::new(x, y, t)
150    ///     });
151    ///     gizmos.curve_gradient_3d(
152    ///         curve,
153    ///         (0..=100).map(|n| n as f32 / 100.0)
154    ///                  .map(|t| (t, GREEN.mix(&RED, t)))
155    ///     );
156    /// }
157    /// # bevy_ecs::system::assert_is_system(system);
158    /// ```
159    pub fn curve_gradient_3d<C>(
160        &mut self,
161        curve_3d: impl Curve<Vec3>,
162        times_with_colors: impl IntoIterator<Item = (f32, C)>,
163    ) where
164        C: Into<Color>,
165    {
166        self.linestrip_gradient(
167            times_with_colors
168                .into_iter()
169                .filter_map(|(time, color)| curve_3d.sample(time).map(|sample| (sample, color))),
170        );
171    }
172}