From 4b7b4dbe6a77cfe1ca2349b9177cfadf9db33f21 Mon Sep 17 00:00:00 2001 From: mirsella Date: Tue, 6 Jan 2026 09:46:55 +0100 Subject: [PATCH 1/3] Add optional '3d' feature to allow excluding bevy_pbr --- Cargo.toml | 5 +++-- src/animator.rs | 9 +++++---- src/components.rs | 1 + src/components/generator.rs | 5 ++++- src/lib.rs | 4 +++- src/plugin.rs | 19 +++++++++++++------ src/systems.rs | 1 + 7 files changed, 30 insertions(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 13b0c61..aaa5048 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,15 +16,16 @@ default = [ # In practice, this feature flag is not required as we use optional arguments for our Bevy systems. # However, the Github Action's environment does not support winit, which is a transitive dependency of bevy/custom_cursor. # So hiding this behind a feature allows us to run tests with --no-default-features in that specific context and circumvent the issue. - "custom_cursor" + "custom_cursor", + "3d" ] custom_cursor = ["bevy/custom_cursor"] +3d = ["bevy/bevy_pbr"] [dependencies] bevy = { version = "0.17.0", default-features = false, features = [ "bevy_log", "bevy_sprite", - "bevy_pbr", "bevy_ui" ] } diff --git a/src/animator.rs b/src/animator.rs index 01ef243..671308d 100644 --- a/src/animator.rs +++ b/src/animator.rs @@ -23,16 +23,15 @@ use bevy::{ ui::widget::ImageNode, }; +#[cfg(feature = "3d")] +use crate::components::sprite3d::Sprite3d; use crate::{ animation::Animation, animator::{ cache::AnimationCache, iterator::{AnimationIterator, IteratorFrame}, }, - components::{ - sprite3d::Sprite3d, - spritesheet_animation::{AnimationProgress, SpritesheetAnimation}, - }, + components::spritesheet_animation::{AnimationProgress, SpritesheetAnimation}, events::AnimationEvent, }; use iterator::AnimationIteratorEvent; @@ -73,6 +72,7 @@ pub(crate) struct SpritesheetAnimationQuery { entity: Entity, spritesheet_animation: &'static mut SpritesheetAnimation, sprite: Option<&'static mut Sprite>, + #[cfg(feature = "3d")] sprite3d: Option<&'static mut Sprite3d>, image_node: Option<&'static mut ImageNode>, #[cfg(feature = "custom_cursor")] @@ -262,6 +262,7 @@ impl Animator { // 3D sprites + #[cfg(feature = "3d")] if let Some(atlas) = item .sprite3d .as_deref_mut() diff --git a/src/components.rs b/src/components.rs index ecb796b..7779b7f 100644 --- a/src/components.rs +++ b/src/components.rs @@ -1,3 +1,4 @@ pub mod generator; +#[cfg(feature = "3d")] pub mod sprite3d; pub mod spritesheet_animation; diff --git a/src/components/generator.rs b/src/components/generator.rs index 60c4498..2b24f25 100644 --- a/src/components/generator.rs +++ b/src/components/generator.rs @@ -9,7 +9,9 @@ use bevy::{ utils::default, }; -use crate::{components::sprite3d::Sprite3d, spritesheet::Spritesheet}; +#[cfg(feature = "3d")] +use crate::components::sprite3d::Sprite3d; +use crate::spritesheet::Spritesheet; /// A helper to generate animation-ready components such as sprites, texture atlases, UI images and cursors. /// @@ -67,6 +69,7 @@ impl ComponentGenerator { Sprite::from_atlas_image(self.spritesheet.image().clone(), self.atlas(atlas_layouts)) } + #[cfg(feature = "3d")] /// Creates an animation-ready [Sprite3d]. /// /// # Arguments diff --git a/src/lib.rs b/src/lib.rs index 1339d4b..f6d8e2e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,7 +37,6 @@ pub mod prelude { clip::{Clip, ClipId}, components::{ generator::ComponentGenerator, - sprite3d::Sprite3d, spritesheet_animation::{AnimationProgress, SpritesheetAnimation}, }, easing::{Easing, EasingVariety}, @@ -46,6 +45,9 @@ pub mod prelude { plugin::SpritesheetAnimationPlugin, spritesheet::Spritesheet, }; + + #[cfg(feature = "3d")] + pub use crate::components::sprite3d::Sprite3d; } mod animator; diff --git a/src/plugin.rs b/src/plugin.rs index 37f68f3..7e515c7 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -1,18 +1,22 @@ use bevy::prelude::*; use crate::{ - animation::Animation, - animator::Animator, - components::{sprite3d::Sprite3d, spritesheet_animation::SpritesheetAnimation}, - events::AnimationEvent, - systems::{sprite3d, spritesheet_animation}, + animation::Animation, animator::Animator, + components::spritesheet_animation::SpritesheetAnimation, events::AnimationEvent, + systems::spritesheet_animation, }; +#[cfg(feature = "3d")] +use crate::components::sprite3d::Sprite3d; +#[cfg(feature = "3d")] +use crate::systems::sprite3d; + /// Set for systems that update animations #[derive(Debug, PartialEq, Eq, Clone, Hash, SystemSet)] pub struct AnimationSystemSet; /// Set for systems that manage 3D sprites +#[cfg(feature = "3d")] #[derive(Debug, PartialEq, Eq, Clone, Hash, SystemSet)] pub struct Sprite3dSystemSet; @@ -68,7 +72,10 @@ impl Plugin for SpritesheetAnimationPlugin { spritesheet_animation::play_animations.in_set(AnimationSystemSet), ) // Animations events - .add_message::() + .add_message::(); + + #[cfg(feature = "3d")] + app // 3D sprites .init_resource::() .register_type::() diff --git a/src/systems.rs b/src/systems.rs index 2a00f89..9068a77 100644 --- a/src/systems.rs +++ b/src/systems.rs @@ -1,2 +1,3 @@ +#[cfg(feature = "3d")] pub mod sprite3d; pub mod spritesheet_animation; From 000e10ecbf9702c37937015be487b0c99493256b Mon Sep 17 00:00:00 2001 From: mirsella Date: Tue, 6 Jan 2026 10:08:54 +0100 Subject: [PATCH 2/3] Fix intra-doc link warning when 3d feature is disabled --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index f6d8e2e..e17f611 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,7 @@ //! //! # Features //! -//! - Animate 2D sprites, [3D sprites](crate::prelude::Sprite3d), UI images and cursors! 🎉 +//! - Animate 2D sprites, 3D sprites, UI images and cursors! 🎉 //! - [Easily build](crate::prelude::AnimationBuilder) animations from [spritesheets](crate::prelude::Spritesheet) with custom parameters like [duration](crate::prelude::AnimationDuration), [repetitions](crate::prelude::AnimationRepeat), [direction](crate::prelude::AnimationDirection), [easing](crate::prelude::Easing). //! - Trigger [events](crate::prelude::AnimationEvent) when animations end or reach specific points. //! From 1173beaed4680f3ab82a257fcd65b64597d8395b Mon Sep 17 00:00:00 2001 From: mirsella Date: Tue, 6 Jan 2026 10:12:44 +0100 Subject: [PATCH 3/3] Fix tests and examples when '3d' feature is disabled --- Cargo.toml | 15 +++++++++++++++ examples/stress.rs | 29 ++++++++++++++++++----------- tests/context.rs | 15 ++++++++++++--- 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index aaa5048..e0cf70c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,21 @@ bevy = { version = "0.17.0", default-features = false, features = [ "bevy_ui" ] } +[[example]] +name = "3d" +required-features = ["3d"] + +[[example]] +name = "stress" +# stress example uses both 2d and 3d depending on CLI args, +# but we need to guard the 3d code inside it. +# Actually, it's easier to just require 3d feature to run it if we don't want to overcomplicate the code. +# Or we can just guard the code. + +[[example]] +name = "cursor" +required-features = ["custom_cursor"] + [dev-dependencies] approx = "0.5.1" bevy = { version = "0.17.0", features = [ diff --git a/examples/stress.rs b/examples/stress.rs index e183e10..fd1dad4 100644 --- a/examples/stress.rs +++ b/examples/stress.rs @@ -114,17 +114,24 @@ fn spawn_sprites( let transform = Transform::from_translation(random_position(&window)); match cli.mode { - Mode::TwoD => commands.spawn(( - component_generator.sprite(&mut atlas_layouts), - SpritesheetAnimation::new(animation_handle.clone()), - transform, - )), - Mode::ThreeD => commands.spawn(( - component_generator.sprite3d(&mut atlas_layouts), - SpritesheetAnimation::new(animation_handle.clone()), - transform, - )), - }; + Mode::TwoD => { + commands.spawn(( + component_generator.sprite(&mut atlas_layouts), + SpritesheetAnimation::new(animation_handle.clone()), + transform, + )); + } + Mode::ThreeD => { + #[cfg(feature = "3d")] + commands.spawn(( + component_generator.sprite3d(&mut atlas_layouts), + SpritesheetAnimation::new(animation_handle.clone()), + transform, + )); + #[cfg(not(feature = "3d"))] + panic!("3D mode requires the '3d' feature to be enabled"); + } + } } } diff --git a/tests/context.rs b/tests/context.rs index 2bd5412..b707c0b 100644 --- a/tests/context.rs +++ b/tests/context.rs @@ -146,9 +146,18 @@ impl Context { let atlas = entity_ref .get::() .and_then(|sprite| sprite.texture_atlas.as_ref()) - .or(entity_ref - .get::() - .and_then(|sprite| sprite.texture_atlas.as_ref())) + .or_else(|| { + #[cfg(feature = "3d")] + { + entity_ref + .get::() + .and_then(|sprite| sprite.texture_atlas.as_ref()) + } + #[cfg(not(feature = "3d"))] + { + None + } + }) .unwrap(); assert_eq!(atlas.index, expected_atlas_index);