diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5d415a4cf7c5590bbe128d343a549e40feb3a7bd..2aba7b6b5c99b142758319b83850b7282e59179c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -44,10 +44,22 @@ jobs: sudo apt-get update sudo apt install -y xvfb libegl1-mesa libgl1-mesa-dri libxcb-xfixes0-dev mesa-vulkan-drivers if: runner.os == 'linux' - - name: Build & run tests - run: cargo test + - name: Build & run tests (slim) + run: cargo test --no-default-features env: CARGO_INCREMENTAL: 0 + - name: Build & run tests (ui) + run: cargo test --no-default-features --features="bevy_ui" + env: + CARGO_INCREMENTAL: 1 + - name: Build & run tests (sprite) + run: cargo test --no-default-features --features="bevy_sprite" + env: + CARGO_INCREMENTAL: 1 + - name: Build & run tests (all) + run: cargo test --all-features + env: + CARGO_INCREMENTAL: 1 coverage: name: Coverage @@ -87,7 +99,7 @@ jobs: RUST_BACKTRACE=1 cargo install --version 0.19.1 cargo-tarpaulin - name: Generate code coverage run: | - RUST_BACKTRACE=1 cargo tarpaulin --verbose --timeout 120 --out Lcov --workspace + RUST_BACKTRACE=1 cargo tarpaulin --all-features --verbose --timeout 120 --out Lcov --workspace ls -la - name: Upload code coverage uses: coverallsapp/github-action@master diff --git a/CHANGELOG.md b/CHANGELOG.md index 1237b9299867092e9519518a781518030b940b3c..5c81f0827d9fca8bb6ec447e9ab598004d2e7fff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Changed + +- Better dependencies: Introduced features `bevy_sprite` and `bevy_ui` taking a dependency on the same-named crates of Bevy, and removed the forced dependency on `bevy/render`. The new features are enabled by default, for discoverability, and only impact the prebuilt lenses. The library now builds without any Bevy optional feature. + ## [0.3.3] - 2022-03-05 ### Added diff --git a/Cargo.toml b/Cargo.toml index 8645e906fef77c57408fcc108a374a04b3999d7e..ed26c9c863ddee418f555933aee9faf2bc013ccf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,9 +12,16 @@ license = "MIT OR Apache-2.0" readme = "README.md" exclude = ["examples/*.gif", ".github", "release.md"] +[features] +default = ["bevy_sprite", "bevy_ui"] +# Enable built-in lenses for Bevy sprites +bevy_sprite = ["bevy/bevy_sprite", "bevy/bevy_render"] +# Enable built-in lenses for Bevy UI +bevy_ui = ["bevy/bevy_ui", "bevy/bevy_text", "bevy/bevy_render"] + [dependencies] interpolation = "0.2" -bevy = { version = "0.6", default-features = false, features = [ "render" ] } +bevy = { version = "0.6", default-features = false } [dev-dependencies] bevy-inspector-egui = "0.8" @@ -25,11 +32,11 @@ required-features = [ "bevy/bevy_winit" ] [[example]] name = "colormaterial_color" -required-features = [ "bevy/bevy_winit" ] +required-features = [ "bevy_sprite", "bevy/bevy_winit" ] [[example]] name = "sprite_color" -required-features = [ "bevy/bevy_winit" ] +required-features = [ "bevy_sprite", "bevy/bevy_winit" ] [[example]] name = "transform_translation" @@ -41,11 +48,11 @@ required-features = [ "bevy/bevy_winit" ] [[example]] name = "ui_position" -required-features = [ "bevy/bevy_winit" ] +required-features = [ "bevy_ui", "bevy/bevy_winit" ] [[example]] name = "text_color" -required-features = [ "bevy/bevy_winit" ] +required-features = [ "bevy_ui", "bevy/bevy_winit" ] [[example]] name = "sequence" diff --git a/src/lens.rs b/src/lens.rs index 7e9a90864891afc869c9ab9d8ed719326f5c9d3c..d59a84e3ca95ea0e5e80825608c268ddffacfa59 100644 --- a/src/lens.rs +++ b/src/lens.rs @@ -76,6 +76,7 @@ pub trait Lens<T> { /// /// [`color`]: https://docs.rs/bevy/0.6.1/bevy/text/struct.TextStyle.html#structfield.color /// [`Text`]: https://docs.rs/bevy/0.6.1/bevy/text/struct.Text.html +#[cfg(feature = "bevy_ui")] #[derive(Debug, Copy, Clone, PartialEq)] pub struct TextColorLens { /// Start color. @@ -86,6 +87,7 @@ pub struct TextColorLens { pub section: usize, } +#[cfg(feature = "bevy_ui")] impl Lens<Text> for TextColorLens { fn lerp(&mut self, target: &mut Text, ratio: f32) { // Note: Add<f32> for Color affects alpha, but not Mul<f32>. So use Vec4 for consistency. @@ -277,6 +279,7 @@ impl Lens<Transform> for TransformScaleLens { /// /// [`position`]: https://docs.rs/bevy/0.6.1/bevy/ui/struct.Style.html#structfield.position /// [`Style`]: https://docs.rs/bevy/0.6.1/bevy/ui/struct.Style.html +#[cfg(feature = "bevy_ui")] #[derive(Debug, Copy, Clone, PartialEq)] pub struct UiPositionLens { /// Start position. @@ -285,6 +288,7 @@ pub struct UiPositionLens { pub end: Rect<Val>, } +#[cfg(feature = "bevy_ui")] fn lerp_val(start: &Val, end: &Val, ratio: f32) -> Val { match (start, end) { (Val::Percent(start), Val::Percent(end)) => Val::Percent(start + (end - start) * ratio), @@ -293,6 +297,7 @@ fn lerp_val(start: &Val, end: &Val, ratio: f32) -> Val { } } +#[cfg(feature = "bevy_ui")] impl Lens<Style> for UiPositionLens { fn lerp(&mut self, target: &mut Style, ratio: f32) { target.position = Rect { @@ -308,6 +313,7 @@ impl Lens<Style> for UiPositionLens { /// /// [`color`]: https://docs.rs/bevy/0.6.1/bevy/sprite/struct.ColorMaterial.html#structfield.color /// [`ColorMaterial`]: https://docs.rs/bevy/0.6.1/bevy/sprite/struct.ColorMaterial.html +#[cfg(feature = "bevy_sprite")] #[derive(Debug, Copy, Clone, PartialEq)] pub struct ColorMaterialColorLens { /// Start color. @@ -316,6 +322,7 @@ pub struct ColorMaterialColorLens { pub end: Color, } +#[cfg(feature = "bevy_sprite")] impl Lens<ColorMaterial> for ColorMaterialColorLens { fn lerp(&mut self, target: &mut ColorMaterial, ratio: f32) { // Note: Add<f32> for Color affects alpha, but not Mul<f32>. So use Vec4 for consistency. @@ -330,6 +337,7 @@ impl Lens<ColorMaterial> for ColorMaterialColorLens { /// /// [`color`]: https://docs.rs/bevy/0.6.1/bevy/sprite/struct.Sprite.html#structfield.color /// [`Sprite`]: https://docs.rs/bevy/0.6.1/bevy/sprite/struct.Sprite.html +#[cfg(feature = "bevy_sprite")] #[derive(Debug, Copy, Clone, PartialEq)] pub struct SpriteColorLens { /// Start color. @@ -338,6 +346,7 @@ pub struct SpriteColorLens { pub end: Color, } +#[cfg(feature = "bevy_sprite")] impl Lens<Sprite> for SpriteColorLens { fn lerp(&mut self, target: &mut Sprite, ratio: f32) { // Note: Add<f32> for Color affects alpha, but not Mul<f32>. So use Vec4 for consistency. @@ -353,6 +362,7 @@ mod tests { use super::*; use std::f32::consts::TAU; + #[cfg(feature = "bevy_ui")] #[test] fn text_color() { let mut lens = TextColorLens { @@ -582,6 +592,7 @@ mod tests { assert!(transform.scale.abs_diff_eq(Vec3::new(0.3, 0.6, -1.2), 1e-5)); } + #[cfg(feature = "bevy_sprite")] #[test] fn colormaterial_color() { let mut lens = ColorMaterialColorLens { @@ -603,6 +614,7 @@ mod tests { assert_eq!(mat.color, Color::rgba(0.7, 0., 0.3, 1.0)); } + #[cfg(feature = "bevy_sprite")] #[test] fn sprite_color() { let mut lens = SpriteColorLens { diff --git a/src/lib.rs b/src/lib.rs index a98631a14374138ab191ec21a975a8f22995a41c..6148b6eb3aeec3e2bee0daa125659571f0062030 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -525,6 +525,35 @@ impl<T: Asset> AssetAnimator<T> { #[cfg(test)] mod tests { use super::{lens::*, *}; + use bevy::reflect::TypeUuid; + + struct DummyLens { + start: f32, + end: f32, + } + + #[derive(Component)] + struct DummyComponent { + value: f32, + } + + #[derive(Reflect, TypeUuid)] + #[uuid = "a33abc11-264e-4bbb-82e8-b87226bb4383"] + struct DummyAsset { + value: f32, + } + + impl Lens<DummyComponent> for DummyLens { + fn lerp(&mut self, target: &mut DummyComponent, ratio: f32) { + target.value = self.start.lerp(&self.end, &ratio); + } + } + + impl Lens<DummyAsset> for DummyLens { + fn lerp(&mut self, target: &mut DummyAsset, ratio: f32) { + target.value = self.start.lerp(&self.end, &ratio); + } + } #[test] fn tweening_type() { @@ -581,12 +610,9 @@ mod tests { EaseFunction::QuadraticInOut, TweeningType::PingPong, std::time::Duration::from_secs(1), - TransformRotationLens { - start: Quat::IDENTITY, - end: Quat::from_axis_angle(Vec3::Z, std::f32::consts::PI / 2.), - }, + DummyLens { start: 0., end: 1. }, ); - let animator = Animator::new(tween); + let animator = Animator::<DummyComponent>::new(tween); assert_eq!(animator.state, AnimatorState::default()); let tween = animator.tweenable().unwrap(); assert_eq!(tween.progress(), 0.); @@ -596,14 +622,11 @@ mod tests { #[test] fn animator_with_state() { for state in [AnimatorState::Playing, AnimatorState::Paused] { - let tween = Tween::new( + let tween = Tween::<DummyComponent>::new( EaseFunction::QuadraticInOut, TweeningType::PingPong, std::time::Duration::from_secs(1), - TransformRotationLens { - start: Quat::IDENTITY, - end: Quat::from_axis_angle(Vec3::Z, std::f32::consts::PI / 2.), - }, + DummyLens { start: 0., end: 1. }, ); let animator = Animator::new(tween).with_state(state); assert_eq!(animator.state, state); @@ -613,18 +636,15 @@ mod tests { /// Animator::default() + Animator::set_tweenable() #[test] fn animator_default() { - let mut animator = Animator::<Transform>::default(); + let mut animator = Animator::<DummyComponent>::default(); assert!(animator.tweenable().is_none()); assert!(animator.tweenable_mut().is_none()); - let tween = Tween::new( + let tween = Tween::<DummyComponent>::new( EaseFunction::QuadraticInOut, TweeningType::PingPong, std::time::Duration::from_secs(1), - TransformRotationLens { - start: Quat::IDENTITY, - end: Quat::from_axis_angle(Vec3::Z, std::f32::consts::PI / 2.), - }, + DummyLens { start: 0., end: 1. }, ); animator.set_tweenable(tween); assert!(animator.tweenable().is_some()); @@ -634,14 +654,11 @@ mod tests { /// Animator control playback #[test] fn animator_controls() { - let tween = Tween::new( + let tween = Tween::<DummyComponent>::new( EaseFunction::QuadraticInOut, TweeningType::PingPong, std::time::Duration::from_secs(1), - TransformRotationLens { - start: Quat::IDENTITY, - end: Quat::from_axis_angle(Vec3::Z, std::f32::consts::PI / 2.), - }, + DummyLens { start: 0., end: 1. }, ); let mut animator = Animator::new(tween); assert_eq!(animator.state, AnimatorState::Playing); @@ -676,16 +693,13 @@ mod tests { /// AssetAnimator::new() #[test] fn asset_animator_new() { - let tween = Tween::new( + let tween = Tween::<DummyAsset>::new( EaseFunction::QuadraticInOut, TweeningType::PingPong, std::time::Duration::from_secs(1), - ColorMaterialColorLens { - start: Color::RED, - end: Color::BLUE, - }, + DummyLens { start: 0., end: 1. }, ); - let animator = AssetAnimator::new(Handle::<ColorMaterial>::default(), tween); + let animator = AssetAnimator::new(Handle::<DummyAsset>::default(), tween); assert_eq!(animator.state, AnimatorState::default()); let tween = animator.tweenable().unwrap(); assert_eq!(tween.progress(), 0.); @@ -695,17 +709,14 @@ mod tests { #[test] fn asset_animator_with_state() { for state in [AnimatorState::Playing, AnimatorState::Paused] { - let tween = Tween::new( + let tween = Tween::<DummyAsset>::new( EaseFunction::QuadraticInOut, TweeningType::PingPong, std::time::Duration::from_secs(1), - ColorMaterialColorLens { - start: Color::RED, - end: Color::BLUE, - }, + DummyLens { start: 0., end: 1. }, ); let animator = - AssetAnimator::new(Handle::<ColorMaterial>::default(), tween).with_state(state); + AssetAnimator::new(Handle::<DummyAsset>::default(), tween).with_state(state); assert_eq!(animator.state, state); } } @@ -713,24 +724,21 @@ mod tests { /// AssetAnimator::default() + AssetAnimator::set_tweenable() #[test] fn asset_animator_default() { - let mut animator = AssetAnimator::<ColorMaterial>::default(); + let mut animator = AssetAnimator::<DummyAsset>::default(); assert!(animator.tweenable().is_none()); assert!(animator.tweenable_mut().is_none()); - assert_eq!(animator.handle(), Handle::<ColorMaterial>::default()); + assert_eq!(animator.handle(), Handle::<DummyAsset>::default()); let tween = Tween::new( EaseFunction::QuadraticInOut, TweeningType::PingPong, std::time::Duration::from_secs(1), - ColorMaterialColorLens { - start: Color::RED, - end: Color::BLUE, - }, + DummyLens { start: 0., end: 1. }, ); animator.set_tweenable(tween); assert!(animator.tweenable().is_some()); assert!(animator.tweenable_mut().is_some()); - assert_eq!(animator.handle(), Handle::<ColorMaterial>::default()); + assert_eq!(animator.handle(), Handle::<DummyAsset>::default()); } /// AssetAnimator control playback @@ -740,12 +748,9 @@ mod tests { EaseFunction::QuadraticInOut, TweeningType::PingPong, std::time::Duration::from_secs(1), - ColorMaterialColorLens { - start: Color::RED, - end: Color::BLUE, - }, + DummyLens { start: 0., end: 1. }, ); - let mut animator = AssetAnimator::new(Handle::<ColorMaterial>::default(), tween); + let mut animator = AssetAnimator::new(Handle::<DummyAsset>::default(), tween); assert_eq!(animator.state, AnimatorState::Playing); assert!(animator.progress().abs() <= 1e-5); diff --git a/src/plugin.rs b/src/plugin.rs index 9fe526e195faa0d9c5e686b78a1672f6b4f2910a..7d0b70cd4f13cc7be97674d3b0a91fb639460827 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -34,10 +34,14 @@ pub struct TweeningPlugin; impl Plugin for TweeningPlugin { fn build(&self, app: &mut App) { app.add_event::<TweenCompleted>() - .add_system(component_animator_system::<Transform>) - .add_system(component_animator_system::<Text>) - .add_system(component_animator_system::<Style>) - .add_system(component_animator_system::<Sprite>) + .add_system(component_animator_system::<Transform>); + + #[cfg(eature = "bevy_ui")] + app.add_system(component_animator_system::<Text>) + .add_system(component_animator_system::<Style>); + + #[cfg(eature = "bevy_sprite")] + app.add_system(component_animator_system::<Sprite>) .add_system(asset_animator_system::<ColorMaterial>); } }