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