
# Objective - Contributes to #15460 ## Solution - Added the following features: - `std` (default) - `async_executor` (default) - `edge_executor` - `critical-section` - `portable-atomic` - Gated `tracing` in `bevy_utils` to allow compilation on certain platforms - Switched from `tracing` to `log` for simple message logging within `bevy_ecs`. Note that `tracing` supports capturing from `log` so this should be an uncontroversial change. - Fixed imports and added feature gates as required - Made `bevy_tasks` optional within `bevy_ecs`. Turns out it's only needed for parallel operations which are already gated behind `multi_threaded` anyway. ## Testing - Added to `compile-check-no-std` CI command - `cargo check -p bevy_ecs --no-default-features --features edge_executor,critical-section,portable-atomic --target thumbv6m-none-eabi` - `cargo check -p bevy_ecs --no-default-features --features edge_executor,critical-section` - `cargo check -p bevy_ecs --no-default-features` ## Draft Release Notes Bevy's core ECS now supports `no_std` platforms. In prior versions of Bevy, it was not possible to work with embedded or niche platforms due to our reliance on the standard library, `std`. This has blocked a number of novel use-cases for Bevy, such as an embedded database for IoT devices, or for creating games on retro consoles. With this release, `bevy_ecs` no longer requires `std`. To use Bevy on a `no_std` platform, you must disable default features and enable the new `edge_executor` and `critical-section` features. You may also need to enable `portable-atomic` and `critical-section` if your platform does not natively support all atomic types and operations used by Bevy. ```toml [dependencies] bevy_ecs = { version = "0.16", default-features = false, features = [ # Required for platforms with incomplete atomics (e.g., Raspberry Pi Pico) "portable-atomic", "critical-section", # Optional "bevy_reflect", "serialize", "bevy_debug_stepping", "edge_executor" ] } ``` Currently, this has been tested on bare-metal x86 and the Raspberry Pi Pico. If you have trouble using `bevy_ecs` on a particular platform, please reach out either through a GitHub issue or in the `no_std` working group on the Bevy Discord server. Keep an eye out for future `no_std` updates as we continue to improve the parity between `std` and `no_std`. We look forward to seeing what kinds of applications are now possible with Bevy! ## Notes - Creating PR in draft to ensure CI is passing before requesting reviews. - This implementation has no support for multithreading in `no_std`, especially due to `NonSend` being unsound if allowed in multithreading. The reason is we cannot check the `ThreadId` in `no_std`, so we have no mechanism to at-runtime determine if access is sound. --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: Vic <59878206+Victoronz@users.noreply.github.com>
88 lines
3.3 KiB
Rust
88 lines
3.3 KiB
Rust
//! Definitions for [`FromWorld`] reflection.
|
|
//! This allows creating instances of types that are known only at runtime and
|
|
//! require an `&mut World` to be initialized.
|
|
//!
|
|
//! This module exports two types: [`ReflectFromWorldFns`] and [`ReflectFromWorld`].
|
|
//!
|
|
//! Same as [`super::component`], but for [`FromWorld`].
|
|
|
|
use alloc::boxed::Box;
|
|
use bevy_reflect::{FromType, Reflect};
|
|
|
|
use crate::world::{FromWorld, World};
|
|
|
|
/// A struct used to operate on the reflected [`FromWorld`] trait of a type.
|
|
///
|
|
/// A [`ReflectFromWorld`] for type `T` can be obtained via
|
|
/// [`bevy_reflect::TypeRegistration::data`].
|
|
#[derive(Clone)]
|
|
pub struct ReflectFromWorld(ReflectFromWorldFns);
|
|
|
|
/// The raw function pointers needed to make up a [`ReflectFromWorld`].
|
|
#[derive(Clone)]
|
|
pub struct ReflectFromWorldFns {
|
|
/// Function pointer implementing [`ReflectFromWorld::from_world()`].
|
|
pub from_world: fn(&mut World) -> Box<dyn Reflect>,
|
|
}
|
|
|
|
impl ReflectFromWorldFns {
|
|
/// Get the default set of [`ReflectFromWorldFns`] for a specific type using its
|
|
/// [`FromType`] implementation.
|
|
///
|
|
/// This is useful if you want to start with the default implementation before overriding some
|
|
/// of the functions to create a custom implementation.
|
|
pub fn new<T: Reflect + FromWorld>() -> Self {
|
|
<ReflectFromWorld as FromType<T>>::from_type().0
|
|
}
|
|
}
|
|
|
|
impl ReflectFromWorld {
|
|
/// Constructs default reflected [`FromWorld`] from world using [`from_world()`](FromWorld::from_world).
|
|
pub fn from_world(&self, world: &mut World) -> Box<dyn Reflect> {
|
|
(self.0.from_world)(world)
|
|
}
|
|
|
|
/// Create a custom implementation of [`ReflectFromWorld`].
|
|
///
|
|
/// This is an advanced feature,
|
|
/// useful for scripting implementations,
|
|
/// that should not be used by most users
|
|
/// unless you know what you are doing.
|
|
///
|
|
/// Usually you should derive [`Reflect`] and add the `#[reflect(FromWorld)]` bundle
|
|
/// to generate a [`ReflectFromWorld`] implementation automatically.
|
|
///
|
|
/// See [`ReflectFromWorldFns`] for more information.
|
|
pub fn new(fns: ReflectFromWorldFns) -> Self {
|
|
Self(fns)
|
|
}
|
|
|
|
/// The underlying function pointers implementing methods on `ReflectFromWorld`.
|
|
///
|
|
/// This is useful when you want to keep track locally of an individual
|
|
/// function pointer.
|
|
///
|
|
/// Calling [`TypeRegistry::get`] followed by
|
|
/// [`TypeRegistration::data::<ReflectFromWorld>`] can be costly if done several
|
|
/// times per frame. Consider cloning [`ReflectFromWorld`] and keeping it
|
|
/// between frames, cloning a `ReflectFromWorld` is very cheap.
|
|
///
|
|
/// If you only need a subset of the methods on `ReflectFromWorld`,
|
|
/// use `fn_pointers` to get the underlying [`ReflectFromWorldFns`]
|
|
/// and copy the subset of function pointers you care about.
|
|
///
|
|
/// [`TypeRegistration::data::<ReflectFromWorld>`]: bevy_reflect::TypeRegistration::data
|
|
/// [`TypeRegistry::get`]: bevy_reflect::TypeRegistry::get
|
|
pub fn fn_pointers(&self) -> &ReflectFromWorldFns {
|
|
&self.0
|
|
}
|
|
}
|
|
|
|
impl<B: Reflect + FromWorld> FromType<B> for ReflectFromWorld {
|
|
fn from_type() -> Self {
|
|
ReflectFromWorld(ReflectFromWorldFns {
|
|
from_world: |world| Box::new(B::from_world(world)),
|
|
})
|
|
}
|
|
}
|