Skip to content

Commit

Permalink
Add no_std support to bevy_input (bevyengine#16995)
Browse files Browse the repository at this point in the history
# Objective

- Contributes to bevyengine#15460

## Solution

- Added the following features:
  - `std` (default)
  - `smol_str` (default)
  - `portable-atomic`
  - `critical-section`
  - `libm`
- Fixed an existing issue where `bevy_reflect` wasn't properly feature
gated.

## Testing

- CI

## Notes

- There were some minor issues with `bevy_math` and `bevy_ecs` noticed
in this PR which I have also resolved here. I can split these out if
desired, but I've left them here for now as they're very small changes
and I don't consider this PR itself to be very controversial.
- `libm`, `portable-atomic`, and `critical-section` are shortcuts to
enable the relevant features in dependencies, making the usage of this
crate on atomically challenged platforms possible and simpler.
- `smol_str` is gated as it doesn't support atomically challenged
platforms (e.g., Raspberry Pi Pico). I have an issue and a
[PR](rust-analyzer/smol_str#91) to discuss this
upstream.
  • Loading branch information
bushrat011899 authored and ecoskey committed Jan 6, 2025
1 parent af7b55f commit 8734b66
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 54 deletions.
9 changes: 6 additions & 3 deletions crates/bevy_ecs/src/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ use core::{
};

#[cfg(feature = "serialize")]
use serde::{
de::{Error, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
use {
alloc::string::ToString,
serde::{
de::{Error, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
},
};

#[cfg(feature = "bevy_reflect")]
Expand Down
64 changes: 50 additions & 14 deletions crates/bevy_input/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,72 @@ license = "MIT OR Apache-2.0"
keywords = ["bevy"]

[features]
default = ["bevy_reflect"]
default = ["std", "bevy_reflect", "bevy_ecs/async_executor", "smol_str"]

# Functionality

## Adds runtime reflection support using `bevy_reflect`.
bevy_reflect = [
"dep:bevy_reflect",
"bevy_app/bevy_reflect",
"bevy_ecs/bevy_reflect",
"bevy_math/bevy_reflect",
]
serialize = ["serde", "smol_str/serde"]

## Adds serialization support through `serde`.
serialize = [
"serde",
"smol_str/serde",
"bevy_ecs/serialize",
"bevy_math/serialize",
]

## Uses the small-string optimization provided by `smol_str`.
smol_str = ["dep:smol_str", "bevy_reflect/smol_str"]

# 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 = [
"bevy_app/std",
"bevy_ecs/std",
"bevy_math/std",
"bevy_utils/std",
"bevy_reflect/std",
]

## `critical-section` provides the building blocks for synchronization primitives
## on all platforms, including `no_std`.
critical-section = ["bevy_app/critical-section", "bevy_ecs/critical-section"]

## `portable-atomic` provides additional platform support for atomic types and
## operations, even on targets without native support.
portable-atomic = ["bevy_app/portable-atomic", "bevy_ecs/portable-atomic"]

## Uses the `libm` maths library instead of the one provided in `std` and `core`.
libm = ["bevy_math/libm"]

[dependencies]
# bevy
bevy_app = { path = "../bevy_app", version = "0.15.0-dev", default-features = false }
bevy_ecs = { path = "../bevy_ecs", version = "0.15.0-dev", default-features = false, features = [
"serialize",
] }
bevy_math = { path = "../bevy_math", version = "0.15.0-dev", default-features = false, features = [
"rand",
"serialize",
] }
bevy_utils = { path = "../bevy_utils", version = "0.15.0-dev" }
bevy_ecs = { path = "../bevy_ecs", version = "0.15.0-dev", default-features = false }
bevy_math = { path = "../bevy_math", version = "0.15.0-dev", default-features = false }
bevy_utils = { path = "../bevy_utils", version = "0.15.0-dev", default-features = false }
bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev", features = [
"glam",
"smol_str",
], optional = true }
], default-features = false, optional = true }

# other
serde = { version = "1", features = ["derive"], optional = true }
serde = { version = "1", features = [
"alloc",
"derive",
], default-features = false, optional = true }
thiserror = { version = "2", default-features = false }
derive_more = { version = "1", default-features = false, features = ["from"] }
smol_str = "0.2"
smol_str = { version = "0.2", default-features = false, optional = true }
log = { version = "0.4", default-features = false }

[lints]
workspace = true
Expand Down
68 changes: 34 additions & 34 deletions crates/bevy_input/src/gamepad.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! The gamepad input functionality.
use crate::{Axis, ButtonInput, ButtonState};
use alloc::string::String;
#[cfg(feature = "bevy_reflect")]
use bevy_ecs::prelude::ReflectComponent;
use bevy_ecs::{
Expand All @@ -12,16 +13,15 @@ use bevy_ecs::{
prelude::require,
system::{Commands, Query},
};
use bevy_math::ops;
use bevy_math::Vec2;
#[cfg(feature = "bevy_reflect")]
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
#[cfg(all(feature = "serialize", feature = "bevy_reflect"))]
use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
use bevy_utils::{
tracing::{info, warn},
Duration, HashMap,
};
use bevy_utils::{Duration, HashMap};
use derive_more::derive::From;
use log::{info, warn};
use thiserror::Error;

/// A gamepad event.
Expand Down Expand Up @@ -54,11 +54,11 @@ pub enum GamepadEvent {
/// the in-frame relative ordering of events is important.
///
/// This event type is used by `bevy_input` to feed its components.
#[derive(Event, Debug, Clone, PartialEq, Reflect, From)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq, From)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub enum RawGamepadEvent {
Expand All @@ -71,11 +71,11 @@ pub enum RawGamepadEvent {
}

/// [`GamepadButton`] changed event unfiltered by [`GamepadSettings`]
#[derive(Event, Debug, Copy, Clone, PartialEq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct RawGamepadButtonChangedEvent {
Expand All @@ -99,11 +99,11 @@ impl RawGamepadButtonChangedEvent {
}

/// [`GamepadAxis`] changed event unfiltered by [`GamepadSettings`]
#[derive(Event, Debug, Copy, Clone, PartialEq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct RawGamepadAxisChangedEvent {
Expand All @@ -128,11 +128,11 @@ impl RawGamepadAxisChangedEvent {

/// A Gamepad connection event. Created when a connection to a gamepad
/// is established and when a gamepad is disconnected.
#[derive(Event, Debug, Clone, PartialEq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct GamepadConnectionEvent {
Expand Down Expand Up @@ -163,11 +163,11 @@ impl GamepadConnectionEvent {
}

/// [`GamepadButton`] event triggered by a digital state change
#[derive(Event, Debug, Clone, Copy, PartialEq, Eq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct GamepadButtonStateChangedEvent {
Expand All @@ -191,11 +191,11 @@ impl GamepadButtonStateChangedEvent {
}

/// [`GamepadButton`] event triggered by an analog state change
#[derive(Event, Debug, Clone, Copy, PartialEq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct GamepadButtonChangedEvent {
Expand All @@ -222,11 +222,11 @@ impl GamepadButtonChangedEvent {
}

/// [`GamepadAxis`] event triggered by an analog state change
#[derive(Event, Debug, Clone, Copy, PartialEq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "bevy_reflect", feature = "serialize"),
reflect(Serialize, Deserialize)
)]
pub struct GamepadAxisChangedEvent {
Expand Down Expand Up @@ -1232,7 +1232,7 @@ impl AxisSettings {
return true;
}

f32::abs(new_value - old_value.unwrap()) > self.threshold
ops::abs(new_value - old_value.unwrap()) > self.threshold
}

/// Filters the `new_value` based on the `old_value`, according to the [`AxisSettings`].
Expand Down Expand Up @@ -1307,7 +1307,7 @@ impl ButtonAxisSettings {
return true;
}

f32::abs(new_value - old_value.unwrap()) > self.threshold
ops::abs(new_value - old_value.unwrap()) > self.threshold
}

/// Filters the `new_value` based on the `old_value`, according to the [`ButtonAxisSettings`].
Expand Down
6 changes: 6 additions & 0 deletions crates/bevy_input/src/keyboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,14 @@ use bevy_ecs::{
event::{Event, EventReader},
system::ResMut,
};

#[cfg(feature = "bevy_reflect")]
use bevy_reflect::Reflect;

#[cfg(not(feature = "smol_str"))]
use alloc::string::String as SmolStr;

#[cfg(feature = "smol_str")]
use smol_str::SmolStr;

#[cfg(all(feature = "serialize", feature = "bevy_reflect"))]
Expand Down
3 changes: 3 additions & 0 deletions crates/bevy_input/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
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)]

//! Input functionality for the [Bevy game engine](https://bevyengine.org/).
//!
//! # Supported input devices
//!
//! `bevy` currently supports keyboard, mouse, gamepad, and touch inputs.
extern crate alloc;

mod axis;
mod button_input;
/// Common run conditions
Expand Down
7 changes: 4 additions & 3 deletions crates/bevy_math/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ approx = { version = "0.5", default-features = false, optional = true }
rand = { version = "0.8", default-features = false, optional = true }
rand_distr = { version = "0.4.3", optional = true }
smallvec = { version = "1.11" }
bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev", features = [
bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev", default-features = false, features = [
"glam",
], optional = true }
variadics_please = "1.1"
Expand All @@ -52,6 +52,7 @@ std = [
"approx?/std",
"rand?/std",
"rand_distr?/std",
"bevy_reflect?/std",
]
alloc = [
"itertools/use_alloc",
Expand All @@ -76,8 +77,8 @@ debug_glam_assert = ["glam/debug-glam-assert"]
rand = ["dep:rand", "dep:rand_distr", "glam/rand"]
# Include code related to the Curve trait
curve = []
# Enable bevy_reflect (requires std)
bevy_reflect = ["dep:bevy_reflect", "std"]
# Enable bevy_reflect (requires alloc)
bevy_reflect = ["dep:bevy_reflect", "alloc"]

[lints]
workspace = true
Expand Down
8 changes: 8 additions & 0 deletions tools/ci/src/commands/compile_check_no_std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,14 @@ impl Prepare for CompileCheckNoStdCommand {
"Please fix compiler errors in output above for bevy_hierarchy no_std compatibility.",
));

commands.push(PreparedCommand::new::<Self>(
cmd!(
sh,
"cargo check -p bevy_input --no-default-features --features libm,serialize,bevy_reflect --target {target}"
),
"Please fix compiler errors in output above for bevy_input no_std compatibility.",
));

commands
}
}

0 comments on commit 8734b66

Please sign in to comment.