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