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}