From e350c7d8754c2659beae75fc4fddb2e58d15cda6 Mon Sep 17 00:00:00 2001 From: Matthew Weatherley Date: Sat, 28 Sep 2024 09:46:23 -0400 Subject: [PATCH 1/7] Improve reflection implementations for sample-based curves with explicit interpolation --- crates/bevy_math/src/curve/mod.rs | 201 +---------- crates/bevy_math/src/curve/sample_curves.rs | 365 ++++++++++++++++++++ 2 files changed, 371 insertions(+), 195 deletions(-) create mode 100644 crates/bevy_math/src/curve/sample_curves.rs diff --git a/crates/bevy_math/src/curve/mod.rs b/crates/bevy_math/src/curve/mod.rs index 608027ba33f3a..23fc743ede4d2 100644 --- a/crates/bevy_math/src/curve/mod.rs +++ b/crates/bevy_math/src/curve/mod.rs @@ -4,14 +4,18 @@ pub mod cores; pub mod interval; +pub mod sample_curves; +// bevy_math::curve re-exports all commonly-needed curve-related items. pub use interval::{interval, Interval}; -use itertools::Itertools; +pub use sample_curves::*; + +use cores::{EvenCore, UnevenCore}; use crate::StableInterpolate; use core::{marker::PhantomData, ops::Deref}; -use cores::{EvenCore, EvenCoreError, UnevenCore, UnevenCoreError}; use interval::InvalidIntervalError; +use itertools::Itertools; use thiserror::Error; #[cfg(feature = "bevy_reflect")] @@ -805,199 +809,6 @@ where } } -/// A curve that is defined by explicit neighbor interpolation over a set of samples. -#[derive(Clone, Debug)] -#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr(feature = "bevy_reflect", derive(Reflect))] -pub struct SampleCurve { - core: EvenCore, - interpolation: I, -} - -impl Curve for SampleCurve -where - T: Clone, - I: Fn(&T, &T, f32) -> T, -{ - #[inline] - fn domain(&self) -> Interval { - self.core.domain() - } - - #[inline] - fn sample_unchecked(&self, t: f32) -> T { - self.core.sample_with(t, &self.interpolation) - } -} - -impl SampleCurve { - /// Create a new [`SampleCurve`] using the specified `interpolation` to interpolate between - /// the given `samples`. An error is returned if there are not at least 2 samples or if the - /// given `domain` is unbounded. - /// - /// The interpolation takes two values by reference together with a scalar parameter and - /// produces an owned value. The expectation is that `interpolation(&x, &y, 0.0)` and - /// `interpolation(&x, &y, 1.0)` are equivalent to `x` and `y` respectively. - pub fn new( - domain: Interval, - samples: impl IntoIterator, - interpolation: I, - ) -> Result - where - I: Fn(&T, &T, f32) -> T, - { - Ok(Self { - core: EvenCore::new(domain, samples)?, - interpolation, - }) - } -} - -/// A curve that is defined by neighbor interpolation over a set of samples. -#[derive(Clone, Debug)] -#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr(feature = "bevy_reflect", derive(Reflect))] -pub struct SampleAutoCurve { - core: EvenCore, -} - -impl Curve for SampleAutoCurve -where - T: StableInterpolate, -{ - #[inline] - fn domain(&self) -> Interval { - self.core.domain() - } - - #[inline] - fn sample_unchecked(&self, t: f32) -> T { - self.core - .sample_with(t, ::interpolate_stable) - } -} - -impl SampleAutoCurve { - /// Create a new [`SampleCurve`] using type-inferred interpolation to interpolate between - /// the given `samples`. An error is returned if there are not at least 2 samples or if the - /// given `domain` is unbounded. - pub fn new( - domain: Interval, - samples: impl IntoIterator, - ) -> Result { - Ok(Self { - core: EvenCore::new(domain, samples)?, - }) - } -} - -/// A curve that is defined by interpolation over unevenly spaced samples with explicit -/// interpolation. -#[derive(Clone, Debug)] -#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr(feature = "bevy_reflect", derive(Reflect))] -pub struct UnevenSampleCurve { - core: UnevenCore, - interpolation: I, -} - -impl Curve for UnevenSampleCurve -where - T: Clone, - I: Fn(&T, &T, f32) -> T, -{ - #[inline] - fn domain(&self) -> Interval { - self.core.domain() - } - - #[inline] - fn sample_unchecked(&self, t: f32) -> T { - self.core.sample_with(t, &self.interpolation) - } -} - -impl UnevenSampleCurve { - /// Create a new [`UnevenSampleCurve`] using the provided `interpolation` to interpolate - /// between adjacent `timed_samples`. The given samples are filtered to finite times and - /// sorted internally; if there are not at least 2 valid timed samples, an error will be - /// returned. - /// - /// The interpolation takes two values by reference together with a scalar parameter and - /// produces an owned value. The expectation is that `interpolation(&x, &y, 0.0)` and - /// `interpolation(&x, &y, 1.0)` are equivalent to `x` and `y` respectively. - pub fn new( - timed_samples: impl IntoIterator, - interpolation: I, - ) -> Result { - Ok(Self { - core: UnevenCore::new(timed_samples)?, - interpolation, - }) - } - - /// This [`UnevenSampleAutoCurve`], but with the sample times moved by the map `f`. - /// In principle, when `f` is monotone, this is equivalent to [`Curve::reparametrize`], - /// but the function inputs to each are inverses of one another. - /// - /// The samples are re-sorted by time after mapping and deduplicated by output time, so - /// the function `f` should generally be injective over the sample times of the curve. - pub fn map_sample_times(self, f: impl Fn(f32) -> f32) -> UnevenSampleCurve { - Self { - core: self.core.map_sample_times(f), - interpolation: self.interpolation, - } - } -} - -/// A curve that is defined by interpolation over unevenly spaced samples. -#[derive(Clone, Debug)] -#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr(feature = "bevy_reflect", derive(Reflect))] -pub struct UnevenSampleAutoCurve { - core: UnevenCore, -} - -impl Curve for UnevenSampleAutoCurve -where - T: StableInterpolate, -{ - #[inline] - fn domain(&self) -> Interval { - self.core.domain() - } - - #[inline] - fn sample_unchecked(&self, t: f32) -> T { - self.core - .sample_with(t, ::interpolate_stable) - } -} - -impl UnevenSampleAutoCurve { - /// Create a new [`UnevenSampleAutoCurve`] from a given set of timed samples, interpolated - /// using the The samples are filtered to finite times and - /// sorted internally; if there are not at least 2 valid timed samples, an error will be - /// returned. - pub fn new(timed_samples: impl IntoIterator) -> Result { - Ok(Self { - core: UnevenCore::new(timed_samples)?, - }) - } - - /// This [`UnevenSampleAutoCurve`], but with the sample times moved by the map `f`. - /// In principle, when `f` is monotone, this is equivalent to [`Curve::reparametrize`], - /// but the function inputs to each are inverses of one another. - /// - /// The samples are re-sorted by time after mapping and deduplicated by output time, so - /// the function `f` should generally be injective over the sample times of the curve. - pub fn map_sample_times(self, f: impl Fn(f32) -> f32) -> UnevenSampleAutoCurve { - Self { - core: self.core.map_sample_times(f), - } - } -} - /// Create a [`Curve`] that constantly takes the given `value` over the given `domain`. pub fn constant_curve(domain: Interval, value: T) -> ConstantCurve { ConstantCurve { domain, value } diff --git a/crates/bevy_math/src/curve/sample_curves.rs b/crates/bevy_math/src/curve/sample_curves.rs new file mode 100644 index 0000000000000..ec7c31c839a4f --- /dev/null +++ b/crates/bevy_math/src/curve/sample_curves.rs @@ -0,0 +1,365 @@ +//! Sample-interpolated curves constructed using the [`Curve`] API. + +use super::cores::{EvenCore, EvenCoreError, UnevenCore, UnevenCoreError}; +use super::{Curve, Interval}; + +use crate::StableInterpolate; +use core::any::type_name; +use core::fmt::{self, Debug}; + +#[cfg(feature = "bevy_reflect")] +use bevy_reflect::{utility::GenericTypePathCell, Reflect, TypePath}; + +const THIS_MODULE: &str = "bevy_math::curve::sample_curves"; +const THIS_CRATE: &str = "bevy_math"; + +/// A curve that is defined by explicit neighbor interpolation over a set of evenly-spaced samples. +#[derive(Clone)] +#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr( + feature = "bevy_reflect", + derive(Reflect), + reflect(where T: TypePath), + reflect(from_reflect = false, type_path = false), +)] +pub struct SampleCurve { + pub(crate) core: EvenCore, + #[cfg_attr(feature = "bevy_reflect", reflect(ignore))] + pub(crate) interpolation: I, +} + +impl Debug for SampleCurve +where + EvenCore: Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SampleCurve") + .field("core", &self.core) + .field("interpolation", &type_name::()) + .finish() + } +} + +impl TypePath for SampleCurve +where + T: TypePath, + I: 'static, +{ + fn type_path() -> &'static str { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| { + format!( + "{}::SampleCurve<{},{}>", + THIS_MODULE, + T::type_path(), + type_name::() + ) + }) + } + + fn short_type_path() -> &'static str { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| { + format!("SampleCurve<{},{}>", T::type_path(), type_name::()) + }) + } + + fn type_ident() -> Option<&'static str> { + Some("SampleCurve") + } + + fn crate_name() -> Option<&'static str> { + Some(THIS_CRATE) + } + + fn module_path() -> Option<&'static str> { + Some(THIS_MODULE) + } +} + +impl Curve for SampleCurve +where + T: Clone, + I: Fn(&T, &T, f32) -> T, +{ + #[inline] + fn domain(&self) -> Interval { + self.core.domain() + } + + #[inline] + fn sample_unchecked(&self, t: f32) -> T { + self.core.sample_with(t, &self.interpolation) + } +} + +impl SampleCurve { + /// Create a new [`SampleCurve`] using the specified `interpolation` to interpolate between + /// the given `samples`. An error is returned if there are not at least 2 samples or if the + /// given `domain` is unbounded. + /// + /// The interpolation takes two values by reference together with a scalar parameter and + /// produces an owned value. The expectation is that `interpolation(&x, &y, 0.0)` and + /// `interpolation(&x, &y, 1.0)` are equivalent to `x` and `y` respectively. + pub fn new( + domain: Interval, + samples: impl IntoIterator, + interpolation: I, + ) -> Result + where + I: Fn(&T, &T, f32) -> T, + { + Ok(Self { + core: EvenCore::new(domain, samples)?, + interpolation, + }) + } +} + +/// A curve that is defined by neighbor interpolation over a set of evenly-spaced samples, +/// interpolated automatically using [a particularly well-behaved interpolation]. +/// +/// [a particularly well-behaved interpolation]: StableInterpolate +#[derive(Clone, Debug)] +#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "bevy_reflect", derive(Reflect))] +pub struct SampleAutoCurve { + pub(crate) core: EvenCore, +} + +impl Curve for SampleAutoCurve +where + T: StableInterpolate, +{ + #[inline] + fn domain(&self) -> Interval { + self.core.domain() + } + + #[inline] + fn sample_unchecked(&self, t: f32) -> T { + self.core + .sample_with(t, ::interpolate_stable) + } +} + +impl SampleAutoCurve { + /// Create a new [`SampleCurve`] using type-inferred interpolation to interpolate between + /// the given `samples`. An error is returned if there are not at least 2 samples or if the + /// given `domain` is unbounded. + pub fn new( + domain: Interval, + samples: impl IntoIterator, + ) -> Result { + Ok(Self { + core: EvenCore::new(domain, samples)?, + }) + } +} + +/// A curve that is defined by interpolation over unevenly spaced samples with explicit +/// interpolation. +#[derive(Clone)] +#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr( + feature = "bevy_reflect", + derive(Reflect), + reflect(where T: TypePath), + reflect(from_reflect = false, type_path = false), +)] +pub struct UnevenSampleCurve { + pub(crate) core: UnevenCore, + #[cfg_attr(feature = "bevy_reflect", reflect(ignore))] + pub(crate) interpolation: I, +} + +impl Debug for UnevenSampleCurve +where + UnevenCore: Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SampleCurve") + .field("core", &self.core) + .field("interpolation", &type_name::()) + .finish() + } +} + +impl TypePath for UnevenSampleCurve +where + T: TypePath, + I: 'static, +{ + fn type_path() -> &'static str { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| { + format!( + "{}::UnevenSampleCurve<{},{}>", + THIS_MODULE, + T::type_path(), + type_name::() + ) + }) + } + + fn short_type_path() -> &'static str { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| { + format!("UnevenSampleCurve<{},{}>", T::type_path(), type_name::()) + }) + } + + fn type_ident() -> Option<&'static str> { + Some("UnevenSampleCurve") + } + + fn crate_name() -> Option<&'static str> { + Some(THIS_CRATE) + } + + fn module_path() -> Option<&'static str> { + Some(THIS_MODULE) + } +} + +impl Curve for UnevenSampleCurve +where + T: Clone, + I: Fn(&T, &T, f32) -> T, +{ + #[inline] + fn domain(&self) -> Interval { + self.core.domain() + } + + #[inline] + fn sample_unchecked(&self, t: f32) -> T { + self.core.sample_with(t, &self.interpolation) + } +} + +impl UnevenSampleCurve { + /// Create a new [`UnevenSampleCurve`] using the provided `interpolation` to interpolate + /// between adjacent `timed_samples`. The given samples are filtered to finite times and + /// sorted internally; if there are not at least 2 valid timed samples, an error will be + /// returned. + /// + /// The interpolation takes two values by reference together with a scalar parameter and + /// produces an owned value. The expectation is that `interpolation(&x, &y, 0.0)` and + /// `interpolation(&x, &y, 1.0)` are equivalent to `x` and `y` respectively. + pub fn new( + timed_samples: impl IntoIterator, + interpolation: I, + ) -> Result { + Ok(Self { + core: UnevenCore::new(timed_samples)?, + interpolation, + }) + } + + /// This [`UnevenSampleAutoCurve`], but with the sample times moved by the map `f`. + /// In principle, when `f` is monotone, this is equivalent to [`Curve::reparametrize`], + /// but the function inputs to each are inverses of one another. + /// + /// The samples are re-sorted by time after mapping and deduplicated by output time, so + /// the function `f` should generally be injective over the sample times of the curve. + pub fn map_sample_times(self, f: impl Fn(f32) -> f32) -> UnevenSampleCurve { + Self { + core: self.core.map_sample_times(f), + interpolation: self.interpolation, + } + } +} + +/// A curve that is defined by interpolation over unevenly spaced samples, +/// interpolated automatically using [a particularly well-behaved interpolation]. +/// +/// [a particularly well-behaved interpolation]: StableInterpolate +#[derive(Clone, Debug)] +#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "bevy_reflect", derive(Reflect))] +pub struct UnevenSampleAutoCurve { + pub(crate) core: UnevenCore, +} + +impl Curve for UnevenSampleAutoCurve +where + T: StableInterpolate, +{ + #[inline] + fn domain(&self) -> Interval { + self.core.domain() + } + + #[inline] + fn sample_unchecked(&self, t: f32) -> T { + self.core + .sample_with(t, ::interpolate_stable) + } +} + +impl UnevenSampleAutoCurve { + /// Create a new [`UnevenSampleAutoCurve`] from a given set of timed samples, interpolated + /// using the The samples are filtered to finite times and + /// sorted internally; if there are not at least 2 valid timed samples, an error will be + /// returned. + pub fn new(timed_samples: impl IntoIterator) -> Result { + Ok(Self { + core: UnevenCore::new(timed_samples)?, + }) + } + + /// This [`UnevenSampleAutoCurve`], but with the sample times moved by the map `f`. + /// In principle, when `f` is monotone, this is equivalent to [`Curve::reparametrize`], + /// but the function inputs to each are inverses of one another. + /// + /// The samples are re-sorted by time after mapping and deduplicated by output time, so + /// the function `f` should generally be injective over the sample times of the curve. + pub fn map_sample_times(self, f: impl Fn(f32) -> f32) -> UnevenSampleAutoCurve { + Self { + core: self.core.map_sample_times(f), + } + } +} + +#[cfg(test)] +mod tests { + //! These tests should guarantee (by even compiling) that SampleCurve and UnevenSampleCurve + //! can be Reflect under reasonable circumstances where their interpolation is defined by: + //! - function items + //! - 'static closures + //! - function pointers + use super::{SampleCurve, UnevenSampleCurve}; + use crate::{curve::Interval, VectorSpace}; + use bevy_reflect::Reflect; + + #[test] + fn reflect_sample_curve() { + fn foo(x: &f32, y: &f32, t: f32) -> f32 { + x.lerp(*y, t) + } + let bar = |x: &f32, y: &f32, t: f32| x.lerp(*y, t); + let baz: fn(&f32, &f32, f32) -> f32 = bar; + + let samples = [0.0, 1.0, 2.0]; + + let _: Box = Box::new(SampleCurve::new(Interval::UNIT, samples, foo).unwrap()); + let _: Box = Box::new(SampleCurve::new(Interval::UNIT, samples, bar).unwrap()); + let _: Box = Box::new(SampleCurve::new(Interval::UNIT, samples, baz).unwrap()); + } + + #[test] + fn reflect_uneven_sample_curve() { + fn foo(x: &f32, y: &f32, t: f32) -> f32 { + x.lerp(*y, t) + } + let bar = |x: &f32, y: &f32, t: f32| x.lerp(*y, t); + let baz: fn(&f32, &f32, f32) -> f32 = bar; + + let keyframes = [(0.0, 1.0), (1.0, 0.0), (2.0, -1.0)]; + + let _: Box = Box::new(UnevenSampleCurve::new(keyframes, foo).unwrap()); + let _: Box = Box::new(UnevenSampleCurve::new(keyframes, bar).unwrap()); + let _: Box = Box::new(UnevenSampleCurve::new(keyframes, baz).unwrap()); + } +} From bbb5b81601301b9f83c8120621eec156570f138a Mon Sep 17 00:00:00 2001 From: Matthew Weatherley Date: Sat, 28 Sep 2024 10:09:10 -0400 Subject: [PATCH 2/7] Lint --- crates/bevy_math/src/curve/sample_curves.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_math/src/curve/sample_curves.rs b/crates/bevy_math/src/curve/sample_curves.rs index ec7c31c839a4f..e12bed8933b96 100644 --- a/crates/bevy_math/src/curve/sample_curves.rs +++ b/crates/bevy_math/src/curve/sample_curves.rs @@ -324,8 +324,8 @@ impl UnevenSampleAutoCurve { #[cfg(test)] mod tests { - //! These tests should guarantee (by even compiling) that SampleCurve and UnevenSampleCurve - //! can be Reflect under reasonable circumstances where their interpolation is defined by: + //! These tests should guarantee (by even compiling) that `SampleCurve` and `UnevenSampleCurve` + //! can be `Reflect` under reasonable circumstances where their interpolation is defined by: //! - function items //! - 'static closures //! - function pointers From 2089667f61c000006553535ad01ee844b25f79cc Mon Sep 17 00:00:00 2001 From: Matthew Weatherley Date: Sat, 28 Sep 2024 10:12:48 -0400 Subject: [PATCH 3/7] Wrangle features --- crates/bevy_math/src/curve/sample_curves.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_math/src/curve/sample_curves.rs b/crates/bevy_math/src/curve/sample_curves.rs index e12bed8933b96..1e35d6ba628a2 100644 --- a/crates/bevy_math/src/curve/sample_curves.rs +++ b/crates/bevy_math/src/curve/sample_curves.rs @@ -40,6 +40,7 @@ where } } +#[cfg(feature = "bevy_reflect")] impl TypePath for SampleCurve where T: TypePath, @@ -185,6 +186,7 @@ where } } +#[cfg(feature = "bevy_reflect")] impl TypePath for UnevenSampleCurve where T: TypePath, From 7c4fd9d58c4c8b9dde06561f6881ae5cd6dd56d8 Mon Sep 17 00:00:00 2001 From: Matty Date: Sat, 28 Sep 2024 13:18:27 -0400 Subject: [PATCH 4/7] Apply `#[reflect(Debug)]` Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com> --- crates/bevy_math/src/curve/sample_curves.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/bevy_math/src/curve/sample_curves.rs b/crates/bevy_math/src/curve/sample_curves.rs index 1e35d6ba628a2..766352a0f5117 100644 --- a/crates/bevy_math/src/curve/sample_curves.rs +++ b/crates/bevy_math/src/curve/sample_curves.rs @@ -21,6 +21,7 @@ const THIS_CRATE: &str = "bevy_math"; derive(Reflect), reflect(where T: TypePath), reflect(from_reflect = false, type_path = false), + reflect(Debug), )] pub struct SampleCurve { pub(crate) core: EvenCore, @@ -123,7 +124,7 @@ impl SampleCurve { /// [a particularly well-behaved interpolation]: StableInterpolate #[derive(Clone, Debug)] #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr(feature = "bevy_reflect", derive(Reflect))] +#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug))] pub struct SampleAutoCurve { pub(crate) core: EvenCore, } @@ -167,6 +168,7 @@ impl SampleAutoCurve { derive(Reflect), reflect(where T: TypePath), reflect(from_reflect = false, type_path = false), + reflect(Debug), )] pub struct UnevenSampleCurve { pub(crate) core: UnevenCore, @@ -279,7 +281,7 @@ impl UnevenSampleCurve { /// [a particularly well-behaved interpolation]: StableInterpolate #[derive(Clone, Debug)] #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr(feature = "bevy_reflect", derive(Reflect))] +#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug))] pub struct UnevenSampleAutoCurve { pub(crate) core: UnevenCore, } From fd0709b70b260ea640b3c1ee967f456c807f96cc Mon Sep 17 00:00:00 2001 From: Matthew Weatherley Date: Sat, 28 Sep 2024 13:24:36 -0400 Subject: [PATCH 5/7] Hide paths behind bevy_reflect feature --- crates/bevy_math/src/curve/sample_curves.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/crates/bevy_math/src/curve/sample_curves.rs b/crates/bevy_math/src/curve/sample_curves.rs index 766352a0f5117..c0228c879e6cb 100644 --- a/crates/bevy_math/src/curve/sample_curves.rs +++ b/crates/bevy_math/src/curve/sample_curves.rs @@ -10,8 +10,11 @@ use core::fmt::{self, Debug}; #[cfg(feature = "bevy_reflect")] use bevy_reflect::{utility::GenericTypePathCell, Reflect, TypePath}; -const THIS_MODULE: &str = "bevy_math::curve::sample_curves"; -const THIS_CRATE: &str = "bevy_math"; +#[cfg(feature = "bevy_reflect")] +mod paths { + pub(super) const THIS_MODULE: &str = "bevy_math::curve::sample_curves"; + pub(super) const THIS_CRATE: &str = "bevy_math"; +} /// A curve that is defined by explicit neighbor interpolation over a set of evenly-spaced samples. #[derive(Clone)] @@ -52,7 +55,7 @@ where CELL.get_or_insert::(|| { format!( "{}::SampleCurve<{},{}>", - THIS_MODULE, + paths::THIS_MODULE, T::type_path(), type_name::() ) @@ -71,11 +74,11 @@ where } fn crate_name() -> Option<&'static str> { - Some(THIS_CRATE) + Some(paths::THIS_CRATE) } fn module_path() -> Option<&'static str> { - Some(THIS_MODULE) + Some(paths::THIS_MODULE) } } @@ -199,7 +202,7 @@ where CELL.get_or_insert::(|| { format!( "{}::UnevenSampleCurve<{},{}>", - THIS_MODULE, + paths::THIS_MODULE, T::type_path(), type_name::() ) @@ -218,11 +221,11 @@ where } fn crate_name() -> Option<&'static str> { - Some(THIS_CRATE) + Some(paths::THIS_CRATE) } fn module_path() -> Option<&'static str> { - Some(THIS_MODULE) + Some(paths::THIS_MODULE) } } From 74165492c7be834747b5a02425d67c2f80352c17 Mon Sep 17 00:00:00 2001 From: Matthew Weatherley Date: Sat, 28 Sep 2024 13:28:29 -0400 Subject: [PATCH 6/7] Revert nonfunctional Debug reflects --- crates/bevy_math/src/curve/sample_curves.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/bevy_math/src/curve/sample_curves.rs b/crates/bevy_math/src/curve/sample_curves.rs index c0228c879e6cb..58190f4d169a2 100644 --- a/crates/bevy_math/src/curve/sample_curves.rs +++ b/crates/bevy_math/src/curve/sample_curves.rs @@ -24,7 +24,6 @@ mod paths { derive(Reflect), reflect(where T: TypePath), reflect(from_reflect = false, type_path = false), - reflect(Debug), )] pub struct SampleCurve { pub(crate) core: EvenCore, @@ -127,7 +126,7 @@ impl SampleCurve { /// [a particularly well-behaved interpolation]: StableInterpolate #[derive(Clone, Debug)] #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug))] +#[cfg_attr(feature = "bevy_reflect", derive(Reflect))] pub struct SampleAutoCurve { pub(crate) core: EvenCore, } @@ -171,7 +170,6 @@ impl SampleAutoCurve { derive(Reflect), reflect(where T: TypePath), reflect(from_reflect = false, type_path = false), - reflect(Debug), )] pub struct UnevenSampleCurve { pub(crate) core: UnevenCore, @@ -284,7 +282,7 @@ impl UnevenSampleCurve { /// [a particularly well-behaved interpolation]: StableInterpolate #[derive(Clone, Debug)] #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug))] +#[cfg_attr(feature = "bevy_reflect", derive(Reflect))] pub struct UnevenSampleAutoCurve { pub(crate) core: UnevenCore, } From a88109e8dee106a9ad380b0d872ddcab1f208375 Mon Sep 17 00:00:00 2001 From: Matthew Weatherley Date: Sat, 28 Sep 2024 13:31:32 -0400 Subject: [PATCH 7/7] Added comments on instability of TypeName implementations --- crates/bevy_math/src/curve/sample_curves.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/bevy_math/src/curve/sample_curves.rs b/crates/bevy_math/src/curve/sample_curves.rs index 58190f4d169a2..255fa84d10275 100644 --- a/crates/bevy_math/src/curve/sample_curves.rs +++ b/crates/bevy_math/src/curve/sample_curves.rs @@ -43,6 +43,8 @@ where } } +/// Note: This is not a fully stable implementation of `TypePath` due to usage of `type_name` +/// for function members. #[cfg(feature = "bevy_reflect")] impl TypePath for SampleCurve where @@ -189,6 +191,8 @@ where } } +/// Note: This is not a fully stable implementation of `TypePath` due to usage of `type_name` +/// for function members. #[cfg(feature = "bevy_reflect")] impl TypePath for UnevenSampleCurve where