diff --git a/CHANGELOG.md b/CHANGELOG.md index e5acf34..60b4207 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ # Changelog -## v0.8.1 - 2025-07-14 +## v0.9.1 - 2025-07-15 + +- Fix color delta interpolation + +### Breaking Change + +- Add a delta flag to the built-in tweens + - This comes instead of the additional XDelta type so that one won't have to register so twice the types + +## v0.9.0 - 2025-07-14 ### Breaking Changes diff --git a/Cargo.lock b/Cargo.lock index 18f7929..706ed30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1276,7 +1276,7 @@ dependencies = [ [[package]] name = "bevy_tween" -version = "0.9.0" +version = "0.9.1" dependencies = [ "bevy", "bevy-inspector-egui", diff --git a/Cargo.toml b/Cargo.toml index 68bcb26..cc52e4d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bevy_tween" description = "Flexible tweening plugin library for Bevy" -version = "0.9.0" +version = "0.9.1" edition = "2024" authors = ["Multirious", "Rabbival"] license = "MIT OR Apache-2.0" @@ -23,7 +23,7 @@ default-features = false features = ["std"] [dependencies.bevy_math] -version = "0.16.0" +version = "0.16.1" default-features = false features = ["curve"] diff --git a/examples/demo/delta_tweens.rs b/examples/demo/delta_tweens.rs index 10cd591..9511080 100644 --- a/examples/demo/delta_tweens.rs +++ b/examples/demo/delta_tweens.rs @@ -2,10 +2,13 @@ use std::time::Duration; use bevy::{ prelude::*, }; +use bevy::color::palettes::basic::WHITE; +use bevy::color::palettes::css::{BLUE, RED}; use bevy_tween::{ combinator::*, prelude::*, tween::AnimationTarget, }; +use bevy_tween::interpolate::{sprite_color_delta_to}; fn secs(secs: f32) -> Duration { Duration::from_secs_f32(secs) @@ -36,13 +39,14 @@ fn spawn_circle_with_tweens( let float_duration = secs(4.0); let circle = AnimationTarget.into_target(); let mut circle_transform_state = circle.transform_state(circle_transform); + let mut circle_sprite_state = circle.state(WHITE.into()); let mut circle_commands = commands .spawn(( - Sprite { - image: circle_filled_image, - ..default() - }, + Sprite { + image: circle_filled_image, + ..default() + }, circle_transform, AnimationTarget, )); @@ -60,6 +64,16 @@ fn spawn_circle_with_tweens( float_duration, EaseKind::SineInOut, circle_transform_state.translation_delta_by(vertical_delta), - ) + ), + tween( + float_duration, + EaseKind::Linear, + circle_sprite_state.with(sprite_color_delta_to(BLUE.into())), + ), + tween( + float_duration, + EaseKind::CubicIn, + circle_sprite_state.with(sprite_color_delta_to(RED.into())), + ) ))); -} +} \ No newline at end of file diff --git a/examples/demo/follow.rs b/examples/demo/follow.rs index afb9588..80659e9 100644 --- a/examples/demo/follow.rs +++ b/examples/demo/follow.rs @@ -21,9 +21,7 @@ fn main() { .add_plugins(( DefaultPlugins, DefaultTweenPlugins, - EguiPlugin { - enable_multipass_for_primary_context: false, - }, + EguiPlugin::default(), ResourceInspectorPlugin::::new(), )) .add_systems(Startup, setup) diff --git a/examples/entity_structure.rs b/examples/entity_structure.rs index 48cca28..4c3b1e9 100644 --- a/examples/entity_structure.rs +++ b/examples/entity_structure.rs @@ -1,5 +1,5 @@ use bevy::prelude::*; -use bevy_tween::interpolate::{AngleZ, Translation}; +use bevy_tween::interpolate::{translation, AngleZ, Translation}; use bevy_tween::prelude::*; use bevy_tween::{ bevy_time_runner::{TimeRunner, TimeSpan}, @@ -52,16 +52,14 @@ fn setup(mut commands: Commands) { EaseKind::QuadraticInOut, ComponentTween::new_target( TargetComponent::marker(), - Translation { - start: Vec3::new(start_x, y, 0.), - end: Vec3::new(end_x, y, 0.), - }, + translation(Vec3::new(start_x, y, 0.), Vec3::new(end_x, y, 0.)) ), ComponentTween::new_target( TargetComponent::marker(), AngleZ { start: angle_start, end: angle_end, + delta: false }, ), )); @@ -93,16 +91,14 @@ fn setup(mut commands: Commands) { EaseKind::QuadraticInOut, ComponentTween::new_target( TargetComponent::marker(), - Translation { - start: Vec3::new(start_x, y, 0.), - end: Vec3::new(end_x, y, 0.), - }, + translation(Vec3::new(start_x, y, 0.), Vec3::new(end_x, y, 0.)) ), ComponentTween::new_target( TargetComponent::marker(), AngleZ { start: angle_start, end: angle_end, + delta: false }, ), )); @@ -132,16 +128,14 @@ fn setup(mut commands: Commands) { EaseKind::QuadraticInOut, ComponentTween::new_target( TargetComponent::marker(), - Translation { - start: Vec3::new(start_x, y, 0.), - end: Vec3::new(end_x, y, 0.), - }, + translation(Vec3::new(start_x, y, 0.), Vec3::new(end_x, y, 0.)) ), ComponentTween::new_target( TargetComponent::marker(), AngleZ { start: angle_start, end: angle_end, + delta: false }, ), )); @@ -176,6 +170,7 @@ fn setup(mut commands: Commands) { Translation { start: Vec3::new(start_x, y, 0.), end: Vec3::new(end_x, y, 0.), + delta: false }, ), ComponentTween::new_target( @@ -183,6 +178,7 @@ fn setup(mut commands: Commands) { AngleZ { start: angle_start, end: angle_end, + delta: false }, ), )); @@ -216,16 +212,14 @@ fn setup(mut commands: Commands) { EaseKind::QuadraticInOut, ComponentTween::new_target( sprite, - Translation { - start: Vec3::new(start_x, y, 0.), - end: Vec3::new(end_x, y, 0.), - }, + translation(Vec3::new(start_x, y, 0.), Vec3::new(end_x, y, 0.)) ), ComponentTween::new_target( sprite, AngleZ { start: angle_start, end: angle_end, + delta: false }, ), )); diff --git a/src/combinator/state.rs b/src/combinator/state.rs index 4ea246d..059a533 100644 --- a/src/combinator/state.rs +++ b/src/combinator/state.rs @@ -172,17 +172,17 @@ impl TransformTargetState { } /// Create delta [`ComponentTween`] of transform's translation tweening by provided input - pub fn translation_delta_by(&mut self, by: Vec3) -> ComponentTween { + pub fn translation_delta_by(&mut self, by: Vec3) -> ComponentTween { self.translation_with(translation_delta_by(by)) } /// Create delta [`ComponentTween`] of transform's rotation tweening by provided input - pub fn rotation_delta_by(&mut self, by: Quat) -> ComponentTween { + pub fn rotation_delta_by(&mut self, by: Quat) -> ComponentTween { self.rotation_with(rotation_delta_by(by)) } /// Create delta [`ComponentTween`] of scale's rotation tweening by provided input - pub fn scale_delta_by(&mut self, by: Vec3) -> ComponentTween { + pub fn scale_delta_by(&mut self, by: Vec3) -> ComponentTween { self.scale_with(scale_delta_by(by)) } } diff --git a/src/interpolate.rs b/src/interpolate.rs index 5951ab7..adf2522 100644 --- a/src/interpolate.rs +++ b/src/interpolate.rs @@ -11,7 +11,6 @@ //! - [`AngleZ`] //! - [`SpriteColor`] //! - [`ColorMaterial`] -//! - All their delta variants (such as [`TranslationDelta`]) //! //! # Your own [`Interpolator`] //! @@ -218,47 +217,31 @@ impl Plugin for DefaultInterpolatorsPlugin { tween::component_tween_system::(), tween::component_tween_system::(), tween::component_tween_system::(), - tween::component_tween_system::(), - tween::component_tween_system::(), - tween::component_tween_system::(), - tween::component_tween_system::() )) .register_type::>() .register_type::>() .register_type::>() - .register_type::>() - .register_type::>() - .register_type::>() - .register_type::>() - .register_type::>(); + .register_type::>(); #[cfg(feature = "bevy_sprite")] app.add_tween_systems(( tween::component_tween_system::(), - tween::component_tween_system::(), )) - .register_type::>() - .register_type::>(); + .register_type::>(); #[cfg(feature = "bevy_ui")] app.add_tween_systems(( tween::component_tween_system::(), tween::component_tween_system::(), - tween::component_tween_system::(), - tween::component_tween_system::(), )) .register_type::>() - .register_type::>() - .register_type::>() - .register_type::>(); + .register_type::>(); #[cfg(all(feature = "bevy_sprite", feature = "bevy_asset",))] app.add_tween_systems(( tween::asset_tween_system::(), - tween::asset_tween_system::(), )) - .register_type::>() - .register_type::>(); + .register_type::>(); } } diff --git a/src/interpolate/sprite.rs b/src/interpolate/sprite.rs index 57b8abc..e57c7f5 100644 --- a/src/interpolate/sprite.rs +++ b/src/interpolate/sprite.rs @@ -11,42 +11,28 @@ pub struct SpriteColor { pub start: Color, #[allow(missing_docs)] pub end: Color, + /// whether it increments by delta or sets absolute values + pub delta: bool } impl Interpolator for SpriteColor { type Item = Sprite; - fn interpolate(&self, item: &mut Self::Item, value: f32, _previous_value: f32) { - item.color = self.start.mix(&self.end, value) - } -} - - -/// delta [`Interpolator`] for [`Sprite`]'s color -#[derive(Debug, Default, Clone, PartialEq, Reflect)] -pub struct SpriteColorDelta { - #[allow(missing_docs)] - pub start: Color, - #[allow(missing_docs)] - pub end: Color, -} - -impl Interpolator for SpriteColorDelta { - type Item = Sprite; - fn interpolate(&self, item: &mut Self::Item, value: f32, previous_value: f32) { - let previous_color_as_vec = self.start.mix(&self.end, previous_value).to_linear().to_vec4(); - let next_color_as_vec = self.start.mix(&self.end, value).to_linear().to_vec4(); - let color_delta = next_color_as_vec - previous_color_as_vec; - let updated_color = item.color.to_linear().to_vec4() + color_delta; - item.color = Color::srgba(updated_color.x, updated_color.y, updated_color.z, updated_color.w); + if self.delta{ + let previous_color_as_vec = self.start.mix(&self.end, previous_value).to_linear(); + let next_color_as_vec = self.start.mix(&self.end, value).to_linear(); + let updated_color = item.color.to_linear() + (next_color_as_vec - previous_color_as_vec); + item.color = updated_color.into(); + }else{ + item.color = self.start.mix(&self.end, value) + } } } - /// Constructor for [`SpriteColor`] pub fn sprite_color(start: Color, end: Color) -> SpriteColor { - SpriteColor { start, end } + SpriteColor { start, end, delta: false } } /// Constructor for [`SpriteColor`] that's relative to previous value using currying. @@ -59,6 +45,16 @@ pub fn sprite_color_to(to: Color) -> impl Fn(&mut Color) -> SpriteColor { } } +/// Constructor for delta [`SpriteColor`] +pub fn sprite_color_delta_to(to: Color) -> impl Fn(&mut Color) -> SpriteColor { + move |state| { + let start = *state; + let end = to; + *state = to; + SpriteColor {start, end, delta: true} + } +} + // type ReflectInterpolatorColorMaterial = // ReflectInterpolator; @@ -70,41 +66,29 @@ pub struct ColorMaterial { pub start: Color, #[allow(missing_docs)] pub end: Color, + /// whether it increments by delta or sets absolute values + pub delta: bool } impl Interpolator for ColorMaterial { type Item = bevy::sprite::ColorMaterial; - fn interpolate(&self, item: &mut Self::Item, value: f32, _previous_value: f32) { - item.color = self.start.mix(&self.end, value); - } -} - -/// delta [`Interpolator`] for [`Sprite`]'s ColorMaterial -#[derive(Debug, Default, Clone, PartialEq, Reflect)] -pub struct ColorMaterialDelta { - #[allow(missing_docs)] - pub start: Color, - #[allow(missing_docs)] - pub end: Color, -} - -impl Interpolator for ColorMaterialDelta { - type Item = bevy::sprite::ColorMaterial; - fn interpolate(&self, item: &mut Self::Item, value: f32, previous_value: f32) { - let previous_color_as_vec = self.start.mix(&self.end, previous_value).to_linear().to_vec4(); - let next_color_as_vec = self.start.mix(&self.end, value).to_linear().to_vec4(); - let color_delta = next_color_as_vec - previous_color_as_vec; - let updated_color = item.color.to_linear().to_vec4() + color_delta; - item.color = Color::srgba(updated_color.x, updated_color.y, updated_color.z, updated_color.w); + if self.delta { + let previous_color_as_vec = self.start.mix(&self.end, previous_value).to_linear(); + let next_color_as_vec = self.start.mix(&self.end, value).to_linear(); + let updated_color = item.color.to_linear() + (next_color_as_vec - previous_color_as_vec); + item.color = updated_color.into(); + }else{ + item.color = self.start.mix(&self.end, value); + } } } /// Constructor for [`ColorMaterial`](crate::interpolate::ColorMaterial) pub fn color_material(start: Color, end: Color) -> ColorMaterial { - ColorMaterial { start, end } + ColorMaterial { start, end, delta: false } } /// Constructor for [`ColorMaterial`](crate::interpolate::ColorMaterial) that's relative to previous value using currying. @@ -116,3 +100,13 @@ pub fn color_material_to(to: Color) -> impl Fn(&mut Color) -> ColorMaterial { color_material(start, end) } } + +/// Constructor for delta [`ColorMaterial`](crate::interpolate::ColorMaterial) +pub fn color_material_delta_to(to: Color) -> impl Fn(&mut Color) -> ColorMaterial { + move |state| { + let start = *state; + let end = to; + *state = to; + ColorMaterial{start, end, delta: true} + } +} diff --git a/src/interpolate/transform.rs b/src/interpolate/transform.rs index ed4d608..cd87781 100644 --- a/src/interpolate/transform.rs +++ b/src/interpolate/transform.rs @@ -11,37 +11,27 @@ pub struct Translation { pub start: Vec3, #[allow(missing_docs)] pub end: Vec3, + /// whether it increments by delta or sets absolute values + pub delta: bool } impl Interpolator for Translation { type Item = Transform; - fn interpolate(&self, item: &mut Self::Item, value: f32, _previous_value: f32) { - item.translation = self.start.lerp(self.end, value); - } -} - -/// delta [`Interpolator`] for [`Transform`]'s translation. -#[derive(Debug, Default, Clone, PartialEq, Reflect)] -pub struct TranslationDelta { - #[allow(missing_docs)] - pub start: Vec3, - #[allow(missing_docs)] - pub end: Vec3, -} -impl Interpolator for TranslationDelta { - type Item = Transform; - fn interpolate(&self, item: &mut Self::Item, value: f32, previous_value: f32) { - let previous_translation = self.start.lerp(self.end, previous_value); - let next_translation = self.start.lerp(self.end, value); - let translation_delta = next_translation - previous_translation; - item.translation += translation_delta; + if self.delta{ + let previous_translation = self.start.lerp(self.end, previous_value); + let next_translation = self.start.lerp(self.end, value); + let translation_delta = next_translation - previous_translation; + item.translation += translation_delta; + }else{ + item.translation = self.start.lerp(self.end, value); + } } } /// Constructor for [`Translation`] pub fn translation(start: Vec3, end: Vec3) -> Translation { - Translation { start, end } + Translation { start, end, delta: false } } /// Constructor for [`Translation`] that's relative to previous value using currying. @@ -64,13 +54,14 @@ pub fn translation_by(by: Vec3) -> impl Fn(&mut Vec3) -> Translation { } } -/// Constructor for [`TranslationDelta`] that's relative to previous value +/// Constructor for [`Translation`] that's relative to previous value /// Since this is a delta tween, it can happen with other ongoing tweens of that type -pub fn translation_delta_by(by: Vec3) -> impl Fn(&mut Vec3) -> TranslationDelta { +pub fn translation_delta_by(by: Vec3) -> impl Fn(&mut Vec3) -> Translation { move |state| { let start = *state; let end = *state + by; - TranslationDelta { start, end } + *state += by; + Translation { start, end, delta: true } } } @@ -82,37 +73,27 @@ pub struct Rotation { pub start: Quat, #[allow(missing_docs)] pub end: Quat, + /// whether it increments by delta or sets absolute values + pub delta: bool } impl Interpolator for Rotation { type Item = Transform; - fn interpolate(&self, item: &mut Self::Item, value: f32, _previous_value: f32) { - item.rotation = self.start.slerp(self.end, value); - } -} - -/// delta [`Interpolator`] for [`Transform`]'s rotation using the [`Quat::slerp`] function. -#[derive(Debug, Default, Clone, PartialEq, Reflect)] -pub struct RotationDelta { - #[allow(missing_docs)] - pub start: Quat, - #[allow(missing_docs)] - pub end: Quat, -} -impl Interpolator for RotationDelta { - type Item = Transform; - fn interpolate(&self, item: &mut Self::Item, value: f32, previous_value: f32) { - let previous_rotation = self.start.slerp(self.end, previous_value); - let next_rotation = self.start.slerp(self.end, value); - let rotation_delta = next_rotation - previous_rotation; - item.rotation = item.rotation.mul_quat(rotation_delta); + if self.delta{ + let previous_rotation = self.start.slerp(self.end, previous_value); + let next_rotation = self.start.slerp(self.end, value); + let rotation_delta = next_rotation - previous_rotation; + item.rotation = item.rotation.mul_quat(rotation_delta); + }else{ + item.rotation = self.start.slerp(self.end, value); + } } } /// Constructor for [`Rotation`] pub fn rotation(start: Quat, end: Quat) -> Rotation { - Rotation { start, end } + Rotation { start, end, delta: false } } /// Constructor for [`Rotation`] that's relative to previous value using currying. @@ -136,14 +117,14 @@ pub fn rotation_by(by: Quat) -> impl Fn(&mut Quat) -> Rotation { } -/// Constructor for [`RotationDelta`] that's relative to previous value +/// Constructor for [`Rotation`] that's relative to previous value /// Since this is a delta tween, it can happen with other ongoing tweens of that type -pub fn rotation_delta_by(by: Quat) -> impl Fn(&mut Quat) -> RotationDelta { +pub fn rotation_delta_by(by: Quat) -> impl Fn(&mut Quat) -> Rotation { move |state| { let start = *state; let end = *state + by; *state = state.mul_quat(by); - RotationDelta { start, end } + Rotation { start, end, delta: true } } } @@ -155,38 +136,28 @@ pub struct Scale { pub start: Vec3, #[allow(missing_docs)] pub end: Vec3, + /// whether it increments by delta or sets absolute values + pub delta: bool } impl Interpolator for Scale { type Item = Transform; - fn interpolate(&self, item: &mut Self::Item, value: f32, _previous_value: f32) { - item.scale = self.start.lerp(self.end, value); - } -} - - -/// delta [`Interpolator`] for [`Transform`]'s scale -#[derive(Debug, Default, Clone, PartialEq, Reflect)] -pub struct ScaleDelta { - #[allow(missing_docs)] - pub start: Vec3, - #[allow(missing_docs)] - pub end: Vec3, -} -impl Interpolator for ScaleDelta { - type Item = Transform; - fn interpolate(&self, item: &mut Self::Item, value: f32, previous_value: f32) { - let previous_scale = self.start.lerp(self.end, previous_value); - let next_scale = self.start.lerp(self.end, value); - let scale_delta = next_scale - previous_scale; - item.scale += scale_delta; + if self.delta{ + let previous_scale = self.start.lerp(self.end, previous_value); + let next_scale = self.start.lerp(self.end, value); + let scale_delta = next_scale - previous_scale; + item.scale += scale_delta; + }else{ + item.scale = self.start.lerp(self.end, value); + } } } + /// Constructor for [`Scale`] pub fn scale(start: Vec3, end: Vec3) -> Scale { - Scale { start, end } + Scale { start, end, delta: false } } /// Constructor for [`Scale`] that's relative to previous value using currying. @@ -209,14 +180,14 @@ pub fn scale_by(by: Vec3) -> impl Fn(&mut Vec3) -> Scale { } } -/// Constructor for [`ScaleDelta`] that's relative to previous value +/// Constructor for [`Scale`] that's relative to previous value /// Since this is a delta tween, it can happen with other ongoing tweens of that type -pub fn scale_delta_by(by: Vec3) -> impl Fn(&mut Vec3) -> ScaleDelta { +pub fn scale_delta_by(by: Vec3) -> impl Fn(&mut Vec3) -> Scale { move |state| { let start = *state; let end = *state + by; *state += by; - ScaleDelta { start, end } + Scale { start, end, delta: true } } } @@ -229,39 +200,29 @@ pub struct AngleZ { pub start: f32, #[allow(missing_docs)] pub end: f32, + /// whether it increments by delta or sets absolute values + pub delta: bool } impl Interpolator for AngleZ { type Item = Transform; - fn interpolate(&self, item: &mut Self::Item, value: f32, _previous_value: f32) { - let angle = (self.end - self.start).mul_add(value, self.start); - item.rotation = Quat::from_rotation_z(angle); - } -} - -/// [`Interpolator`] for [`Transform`]'s rotation at Z axis. -/// Usually used for 2D rotation. -#[derive(Debug, Default, Clone, PartialEq, Reflect)] -pub struct AngleZDelta { - #[allow(missing_docs)] - pub start: f32, - #[allow(missing_docs)] - pub end: f32, -} -impl Interpolator for AngleZDelta { - type Item = Transform; - fn interpolate(&self, item: &mut Self::Item, value: f32, previous_value: f32) { - let previous_angle = (self.end - self.start).mul_add(previous_value, self.start); - let update_angle = (self.end - self.start).mul_add(value, self.start); - let angle_delta_as_quat = Quat::from_rotation_z(update_angle - previous_angle); - item.rotation = item.rotation.mul_quat(angle_delta_as_quat); + if self.delta{ + let previous_angle = (self.end - self.start).mul_add(previous_value, self.start); + let update_angle = (self.end - self.start).mul_add(value, self.start); + let angle_delta_as_quat = Quat::from_rotation_z(update_angle - previous_angle); + item.rotation = item.rotation.mul_quat(angle_delta_as_quat); + }else{ + let angle = (self.end - self.start).mul_add(value, self.start); + item.rotation = Quat::from_rotation_z(angle); + } } } + /// Constructor for [`AngleZ`] pub fn angle_z(start: f32, end: f32) -> AngleZ { - AngleZ { start, end } + AngleZ { start, end, delta: false } } /// Constructor for [`AngleZ`] that's relative to previous value using currying. @@ -284,13 +245,13 @@ pub fn angle_z_by(by: f32) -> impl Fn(&mut f32) -> AngleZ { } } -/// Constructor for [`AngleZDelta`] that's relative to previous value +/// Constructor for [`AngleZ`] that's relative to previous value /// Since this is a delta tween, it can happen with other ongoing tweens of that type -pub fn angle_z_delta_by(by: f32) -> impl Fn(&mut f32) -> AngleZDelta { +pub fn angle_z_delta_by(by: f32) -> impl Fn(&mut f32) -> AngleZ { move |state| { let start = *state; let end = *state + by; *state += by; - AngleZDelta {start, end} + AngleZ {start, end, delta: true} } } diff --git a/src/interpolate/ui.rs b/src/interpolate/ui.rs index 1fd142a..fba116d 100644 --- a/src/interpolate/ui.rs +++ b/src/interpolate/ui.rs @@ -8,40 +8,28 @@ pub struct BackgroundColor { pub start: Color, #[allow(missing_docs)] pub end: Color, + /// whether it increments by delta or sets absolute values + pub delta: bool } impl Interpolator for BackgroundColor { type Item = bevy::prelude::BackgroundColor; - fn interpolate(&self, item: &mut Self::Item, value: f32, _previous_value: f32) { - item.0 = self.start.mix(&self.end, value) - } -} - -/// delta [`Interpolator`] for Bevy's [`BackgroundColor`](bevy::prelude::BackgroundColor) used in UIs. -#[derive(Debug, Default, Clone, PartialEq, Reflect)] -pub struct BackgroundColorDelta { - #[allow(missing_docs)] - pub start: Color, - #[allow(missing_docs)] - pub end: Color, -} - -impl Interpolator for BackgroundColorDelta { - type Item = bevy::prelude::BackgroundColor; - fn interpolate(&self, item: &mut Self::Item, value: f32, previous_value: f32) { - let previous_color_as_vec = self.start.mix(&self.end, previous_value).to_linear().to_vec4(); - let next_color_as_vec = self.start.mix(&self.end, value).to_linear().to_vec4(); - let color_delta = next_color_as_vec - previous_color_as_vec; - let updated_color = item.0.to_linear().to_vec4() + color_delta; - item.0 = Color::srgba(updated_color.x, updated_color.y, updated_color.z, updated_color.w); + if self.delta{ + let previous_color_as_vec = self.start.mix(&self.end, previous_value).to_linear(); + let next_color_as_vec = self.start.mix(&self.end, value).to_linear(); + let updated_color = item.0.to_linear() + (next_color_as_vec - previous_color_as_vec); + item.0 = updated_color.into(); + }else{ + item.0 = self.start.mix(&self.end, value) + } } } /// Constructor for [`BackgroundColor`](crate::interpolate::BackgroundColor) pub fn background_color(start: Color, end: Color) -> BackgroundColor { - BackgroundColor { start, end } + BackgroundColor { start, end, delta: false } } /// Constructor for [`BackgroundColor`](crate::interpolate::BackgroundColor) that's relative to previous value using currying. @@ -56,6 +44,18 @@ pub fn background_color_to( } } +/// Constructor for delta [`BackgroundColor`](crate::interpolate::BackgroundColor) +pub fn background_color_delta_to( + to: Color, +) -> impl Fn(&mut Color) -> BackgroundColor { + move |state| { + let start = *state; + let end = to; + *state = to; + BackgroundColor {start, end, delta: true} + } +} + /// [`Interpolator`] for Bevy's [`BorderColor`](bevy::prelude::BorderColor) used in UIs. #[derive(Debug, Default, Clone, PartialEq, Reflect)] pub struct BorderColor { @@ -63,42 +63,28 @@ pub struct BorderColor { pub start: Color, #[allow(missing_docs)] pub end: Color, + /// whether it increments by delta or sets absolute values + pub delta: bool } impl Interpolator for BorderColor { type Item = bevy::prelude::BorderColor; - fn interpolate(&self, item: &mut Self::Item, value: f32, _previous_value: f32) { - item.0 = self.start.mix(&self.end, value) - } -} - - -/// delta [`Interpolator`] for Bevy's [`BorderColor`](bevy::prelude::BorderColor) used in UIs. -#[derive(Debug, Default, Clone, PartialEq, Reflect)] -pub struct BorderColorDelta { - #[allow(missing_docs)] - pub start: Color, - #[allow(missing_docs)] - pub end: Color, -} - -impl Interpolator for BorderColorDelta { - type Item = bevy::prelude::BackgroundColor; - fn interpolate(&self, item: &mut Self::Item, value: f32, previous_value: f32) { - let previous_color_as_vec = self.start.mix(&self.end, previous_value).to_linear().to_vec4(); - let next_color_as_vec = self.start.mix(&self.end, value).to_linear().to_vec4(); - let color_delta = next_color_as_vec - previous_color_as_vec; - let updated_color = item.0.to_linear().to_vec4() + color_delta; - item.0 = Color::srgba(updated_color.x, updated_color.y, updated_color.z, updated_color.w); + if self.delta { + let previous_color_as_vec = self.start.mix(&self.end, previous_value).to_linear(); + let next_color_as_vec = self.start.mix(&self.end, value).to_linear(); + let updated_color = item.0.to_linear() + (next_color_as_vec - previous_color_as_vec); + item.0 = updated_color.into(); + }else{ + item.0 = self.start.mix(&self.end, value) + } } } - /// Constructor for [`BorderColor`](crate::interpolate::BorderColor) pub fn border_color(start: Color, end: Color) -> BorderColor { - BorderColor { start, end } + BorderColor { start, end, delta: false } } /// Constructor for [`BorderColor`](crate::interpolate::BorderColor) that's relative to previous value using currying. @@ -110,3 +96,13 @@ pub fn border_color_to(to: Color) -> impl Fn(&mut Color) -> BorderColor { border_color(start, end) } } + +/// Constructor for [`BorderColor`](crate::interpolate::BorderColor) that's relative to previous value using currying. +pub fn border_color_delta_to(to: Color) -> impl Fn(&mut Color) -> BorderColor { + move |state| { + let start = *state; + let end = to; + *state = to; + BorderColor {start, end, delta: true} + } +} \ No newline at end of file