Add no_std support to bevy_transform (#17030)

# Objective

- Contributes to #15460

## Solution

- Added the following features:
  - `std` (default)
  - `alloc` (default)
  - `bevy_reflect` (default)
  - `libm`

## Testing

- CI

## Notes

- `alloc` feature added to allow using this crate in `no_alloc`
environments.
- `bevy_reflect` was previously always enabled when `bevy-support` was
enabled, which isn't how most other crates handle reflection. I've
brought this in line with how most crates gate `bevy_reflect`.
This commit is contained in:
Zachary Harrold 2024-12-31 08:01:13 +11:00 committed by GitHub
parent 9ac7e17f2e
commit db5c31e1c4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 93 additions and 41 deletions

View File

@ -10,16 +10,16 @@ keywords = ["bevy"]
[dependencies]
# bevy
bevy_app = { path = "../bevy_app", version = "0.15.0-dev", optional = true }
bevy_ecs = { path = "../bevy_ecs", version = "0.15.0-dev", features = [
"bevy_reflect",
bevy_app = { path = "../bevy_app", version = "0.15.0-dev", default-features = false, optional = true }
bevy_ecs = { path = "../bevy_ecs", version = "0.15.0-dev", default-features = false, optional = true }
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.15.0-dev", default-features = false, features = [
"bevy_app",
], optional = true }
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.15.0-dev", optional = true }
bevy_math = { path = "../bevy_math", version = "0.15.0-dev", default-features = false }
bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev", features = [
"bevy",
bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev", default-features = false, optional = true }
serde = { version = "1", default-features = false, features = [
"derive",
], optional = true }
serde = { version = "1", features = ["derive"], optional = true }
thiserror = { version = "2", default-features = false }
derive_more = { version = "1", default-features = false, features = ["from"] }
@ -31,24 +31,51 @@ bevy_math = { path = "../bevy_math", version = "0.15.0-dev", default-features =
approx = "0.5.1"
[features]
# Adds normal Bevy impls like deriving components, bundles, reflection, as well as adding
# systems for transform propagation and more.
# This exists because it allows opting out of all of this, leaving only a bare-bones transform struct,
# which enables users to depend on that without needing the larger Bevy dependency tree.
bevy-support = [
"dep:bevy_app",
"dep:bevy_ecs",
"dep:bevy_hierarchy",
"dep:bevy_reflect",
"bevy_math/bevy_reflect",
]
# Turning off default features leaves you with a barebones
# definition of transform.
default = ["bevy-support"]
default = ["std", "bevy-support", "bevy_reflect"]
# Functionality
## Adds normal Bevy impls like deriving components, bundles, reflection, as well as adding
## systems for transform propagation and more.
## This exists because it allows opting out of all of this, leaving only a bare-bones transform struct,
## which enables users to depend on that without needing the larger Bevy dependency tree.
bevy-support = ["alloc", "dep:bevy_app", "dep:bevy_ecs", "dep:bevy_hierarchy"]
## Adds serialization support through `serde`.
serialize = ["dep:serde", "bevy_math/serialize"]
## Adds runtime reflection support using `bevy_reflect`.
bevy_reflect = [
"bevy-support",
"dep:bevy_reflect",
"bevy_math/bevy_reflect",
"bevy_ecs/bevy_reflect",
"bevy_app/bevy_reflect",
]
# Platform Compatibility
## Allows access to the `std` crate. Enabling this feature will prevent compilation
## on `no_std` targets, but provides access to certain additional features on
## supported platforms.
std = [
"alloc",
"bevy_app?/std",
"bevy_ecs?/std",
"bevy_hierarchy?/std",
"bevy_math/std",
"bevy_reflect?/std",
"serde?/std",
]
## Allows access to the `alloc` crate.
alloc = ["serde?/alloc"]
## Uses the `libm` maths library instead of the one provided in `std` and `core`.
libm = ["bevy_math/libm"]
[lints]
workspace = true

View File

@ -1,13 +1,18 @@
use core::ops::Mul;
use super::Transform;
use bevy_math::{Affine3A, Dir3, Isometry3d, Mat4, Quat, Vec3, Vec3A};
#[cfg(all(feature = "bevy-support", feature = "serialize"))]
use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
use bevy_math::{ops, Affine3A, Dir3, Isometry3d, Mat4, Quat, Vec3, Vec3A};
use derive_more::derive::From;
#[cfg(all(feature = "bevy_reflect", feature = "serialize"))]
use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
#[cfg(feature = "bevy-support")]
use bevy_ecs::component::Component;
#[cfg(feature = "bevy_reflect")]
use {
bevy_ecs::{component::Component, reflect::ReflectComponent},
bevy_ecs::reflect::ReflectComponent,
bevy_reflect::{std_traits::ReflectDefault, Reflect},
};
@ -42,26 +47,27 @@ use {
/// [transform_example]: https://github.com/bevyengine/bevy/blob/latest/examples/transforms/transform.rs
#[derive(Debug, PartialEq, Clone, Copy, From)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "bevy-support", derive(Component))]
#[cfg_attr(
feature = "bevy-support",
derive(Component, Reflect),
feature = "bevy_reflect",
derive(Reflect),
reflect(Component, Default, PartialEq, Debug)
)]
#[cfg_attr(
all(feature = "bevy-support", feature = "serialize"),
all(feature = "bevy_reflect", feature = "serialize"),
reflect(Serialize, Deserialize)
)]
pub struct GlobalTransform(Affine3A);
macro_rules! impl_local_axis {
($pos_name: ident, $neg_name: ident, $axis: ident) => {
#[doc=std::concat!("Return the local ", std::stringify!($pos_name), " vector (", std::stringify!($axis) ,").")]
#[doc=core::concat!("Return the local ", core::stringify!($pos_name), " vector (", core::stringify!($axis) ,").")]
#[inline]
pub fn $pos_name(&self) -> Dir3 {
Dir3::new_unchecked((self.0.matrix3 * Vec3::$axis).normalize())
}
#[doc=std::concat!("Return the local ", std::stringify!($neg_name), " vector (-", std::stringify!($axis) ,").")]
#[doc=core::concat!("Return the local ", core::stringify!($neg_name), " vector (-", core::stringify!($axis) ,").")]
#[inline]
pub fn $neg_name(&self) -> Dir3 {
-self.$pos_name()
@ -235,7 +241,7 @@ impl GlobalTransform {
//Formula based on glam's implementation https://github.com/bitshifter/glam-rs/blob/2e4443e70c709710dfb25958d866d29b11ed3e2b/src/f32/affine3a.rs#L290
let det = self.0.matrix3.determinant();
Vec3::new(
self.0.matrix3.x_axis.length() * det.signum(),
self.0.matrix3.x_axis.length() * ops::copysign(1., det),
self.0.matrix3.y_axis.length(),
self.0.matrix3.z_axis.length(),
)

View File

@ -1,11 +1,12 @@
use super::GlobalTransform;
use bevy_math::{Affine3A, Dir3, Isometry3d, Mat3, Mat4, Quat, Vec3};
use core::ops::Mul;
#[cfg(feature = "bevy-support")]
use {
bevy_ecs::{component::Component, prelude::require, reflect::ReflectComponent},
bevy_reflect::prelude::*,
};
use bevy_ecs::{component::Component, prelude::require};
#[cfg(feature = "bevy_reflect")]
use {bevy_ecs::reflect::ReflectComponent, bevy_reflect::prelude::*};
/// Describe the position of an entity. If the entity has a parent, the position is relative
/// to its parent position.
@ -38,14 +39,14 @@ use {
/// [transform_example]: https://github.com/bevyengine/bevy/blob/latest/examples/transforms/transform.rs
#[derive(Debug, PartialEq, Clone, Copy)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "bevy-support", derive(Component), require(GlobalTransform))]
#[cfg_attr(
feature = "bevy-support",
derive(Component, Reflect),
require(GlobalTransform),
feature = "bevy_reflect",
derive(Reflect),
reflect(Component, Default, PartialEq, Debug)
)]
#[cfg_attr(
all(feature = "bevy-support", feature = "serialize"),
all(feature = "bevy_reflect", feature = "serialize"),
reflect(Serialize, Deserialize)
)]
pub struct Transform {

View File

@ -4,6 +4,10 @@
html_logo_url = "https://bevyengine.org/assets/icon.png",
html_favicon_url = "https://bevyengine.org/assets/icon.png"
)]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "bevy-support")]
pub mod commands;

View File

@ -3,10 +3,13 @@ use bevy_ecs::schedule::{IntoSystemConfigs, IntoSystemSetConfigs, SystemSet};
use bevy_hierarchy::ValidParentCheckPlugin;
use crate::{
prelude::{GlobalTransform, Transform},
components::GlobalTransform,
systems::{propagate_transforms, sync_simple_transforms},
};
#[cfg(feature = "bevy_reflect")]
use crate::components::Transform;
/// Set enum for the systems relating to transform propagation
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
pub enum TransformSystem {
@ -25,9 +28,11 @@ impl Plugin for TransformPlugin {
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
struct PropagateTransformsSet;
#[cfg(feature = "bevy_reflect")]
app.register_type::<Transform>()
.register_type::<GlobalTransform>()
.add_plugins(ValidParentCheckPlugin::<GlobalTransform>::default())
.register_type::<GlobalTransform>();
app.add_plugins(ValidParentCheckPlugin::<GlobalTransform>::default())
.configure_sets(
PostStartup,
PropagateTransformsSet.in_set(TransformSystem::TransformPropagate),

View File

@ -1,4 +1,5 @@
use crate::components::{GlobalTransform, Transform};
use alloc::vec::Vec;
use bevy_ecs::{
change_detection::Ref,
prelude::{Changed, DetectChanges, Entity, Query, With, Without},

View File

@ -134,6 +134,14 @@ impl Prepare for CompileCheckNoStdCommand {
"Please fix compiler errors in output above for bevy_state no_std compatibility.",
));
commands.push(PreparedCommand::new::<Self>(
cmd!(
sh,
"cargo check -p bevy_transform --no-default-features --features bevy-support,serialize,libm --target {target}"
),
"Please fix compiler errors in output above for bevy_transform no_std compatibility.",
));
commands
}
}