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}