Create bevy_platform_support
Crate (#17250)
# Objective - Contributes to #16877 ## Solution - Initial creation of `bevy_platform_support` crate. - Moved `bevy_utils::Instant` into new `bevy_platform_support` crate. - Moved `portable-atomic`, `portable-atomic-util`, and `critical-section` into new `bevy_platform_support` crate. ## Testing - CI --- ## Showcase Instead of needing code like this to import an `Arc`: ```rust #[cfg(feature = "portable-atomic")] use portable_atomic_util::Arc; #[cfg(not(feature = "portable-atomic"))] use alloc::sync::Arc; ``` We can now use: ```rust use bevy_platform_support::sync::Arc; ``` This applies to many other types, but the goal is overall the same: allowing crates to use `std`-like types without the boilerplate of conditional compilation and platform-dependencies. ## Migration Guide - Replace imports of `bevy_utils::Instant` with `bevy_platform_support::time::Instant` - Replace imports of `bevy::utils::Instant` with `bevy::platform_support::time::Instant` ## Notes - `bevy_platform_support` hasn't been reserved on `crates.io` - ~~`bevy_platform_support` is not re-exported from `bevy` at this time. It may be worthwhile exporting this crate, but I am unsure of a reasonable name to export it under (`platform_support` may be a bit wordy for user-facing).~~ - I've included an implementation of `Instant` which is suitable for `no_std` platforms that are not Wasm for the sake of eliminating feature gates around its use. It may be a controversial inclusion, so I'm happy to remove it if required. - There are many other items (`spin`, `bevy_utils::Sync(Unsafe)Cell`, etc.) which should be added to this crate. I have kept the initial scope small to demonstrate utility without making this too unwieldy. --------- Co-authored-by: TimJentzsch <TimJentzsch@users.noreply.github.com> Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com> Co-authored-by: François Mockers <francois.mockers@vleue.com>
This commit is contained in:
parent
edb34cd2dd
commit
a64446b77e
@ -48,23 +48,25 @@ std = [
|
|||||||
"downcast-rs/std",
|
"downcast-rs/std",
|
||||||
"bevy_utils/std",
|
"bevy_utils/std",
|
||||||
"bevy_tasks?/std",
|
"bevy_tasks?/std",
|
||||||
|
"bevy_platform_support/std",
|
||||||
]
|
]
|
||||||
|
|
||||||
## `critical-section` provides the building blocks for synchronization primitives
|
## `critical-section` provides the building blocks for synchronization primitives
|
||||||
## on all platforms, including `no_std`.
|
## on all platforms, including `no_std`.
|
||||||
critical-section = [
|
critical-section = [
|
||||||
"portable-atomic?/critical-section",
|
|
||||||
"bevy_tasks?/critical-section",
|
"bevy_tasks?/critical-section",
|
||||||
"bevy_ecs/critical-section",
|
"bevy_ecs/critical-section",
|
||||||
|
"bevy_platform_support/critical-section",
|
||||||
|
"bevy_reflect?/critical-section",
|
||||||
]
|
]
|
||||||
|
|
||||||
## `portable-atomic` provides additional platform support for atomic types and
|
## `portable-atomic` provides additional platform support for atomic types and
|
||||||
## operations, even on targets without native support.
|
## operations, even on targets without native support.
|
||||||
portable-atomic = [
|
portable-atomic = [
|
||||||
"dep:portable-atomic",
|
|
||||||
"dep:portable-atomic-util",
|
|
||||||
"bevy_tasks?/portable-atomic",
|
"bevy_tasks?/portable-atomic",
|
||||||
"bevy_ecs/portable-atomic",
|
"bevy_ecs/portable-atomic",
|
||||||
|
"bevy_platform_support/portable-atomic",
|
||||||
|
"bevy_reflect?/portable-atomic",
|
||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
@ -76,6 +78,7 @@ bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev", default-features
|
|||||||
"alloc",
|
"alloc",
|
||||||
] }
|
] }
|
||||||
bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev", default-features = false, optional = true }
|
bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev", default-features = false, optional = true }
|
||||||
|
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false }
|
||||||
|
|
||||||
# other
|
# other
|
||||||
downcast-rs = { version = "2", default-features = false }
|
downcast-rs = { version = "2", default-features = false }
|
||||||
@ -83,12 +86,6 @@ thiserror = { version = "2", default-features = false }
|
|||||||
variadics_please = "1.1"
|
variadics_please = "1.1"
|
||||||
tracing = { version = "0.1", default-features = false, optional = true }
|
tracing = { version = "0.1", default-features = false, optional = true }
|
||||||
log = { version = "0.4", default-features = false }
|
log = { version = "0.4", default-features = false }
|
||||||
portable-atomic = { version = "1", default-features = false, features = [
|
|
||||||
"fallback",
|
|
||||||
], optional = true }
|
|
||||||
portable-atomic-util = { version = "0.2.4", features = [
|
|
||||||
"alloc",
|
|
||||||
], optional = true }
|
|
||||||
|
|
||||||
[target.'cfg(any(unix, windows))'.dependencies]
|
[target.'cfg(any(unix, windows))'.dependencies]
|
||||||
ctrlc = { version = "3.4.4", optional = true }
|
ctrlc = { version = "3.4.4", optional = true }
|
||||||
|
@ -3,11 +3,9 @@ use crate::{
|
|||||||
plugin::Plugin,
|
plugin::Plugin,
|
||||||
PluginsState,
|
PluginsState,
|
||||||
};
|
};
|
||||||
|
use bevy_platform_support::time::Instant;
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
|
|
||||||
#[cfg(any(target_arch = "wasm32", feature = "std"))]
|
|
||||||
use bevy_utils::Instant;
|
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use {
|
use {
|
||||||
alloc::{boxed::Box, rc::Rc},
|
alloc::{boxed::Box, rc::Rc},
|
||||||
@ -100,7 +98,6 @@ impl Plugin for ScheduleRunnerPlugin {
|
|||||||
let tick = move |app: &mut App,
|
let tick = move |app: &mut App,
|
||||||
_wait: Option<Duration>|
|
_wait: Option<Duration>|
|
||||||
-> Result<Option<Duration>, AppExit> {
|
-> Result<Option<Duration>, AppExit> {
|
||||||
#[cfg(any(target_arch = "wasm32", feature = "std"))]
|
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
|
|
||||||
app.update();
|
app.update();
|
||||||
@ -109,10 +106,8 @@ impl Plugin for ScheduleRunnerPlugin {
|
|||||||
return Err(exit);
|
return Err(exit);
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(any(target_arch = "wasm32", feature = "std"))]
|
|
||||||
let end_time = Instant::now();
|
let end_time = Instant::now();
|
||||||
|
|
||||||
#[cfg(any(target_arch = "wasm32", feature = "std"))]
|
|
||||||
if let Some(wait) = _wait {
|
if let Some(wait) = _wait {
|
||||||
let exe_time = end_time - start_time;
|
let exe_time = end_time - start_time;
|
||||||
if exe_time < wait {
|
if exe_time < wait {
|
||||||
|
@ -2,13 +2,14 @@
|
|||||||
feature = "portable-atomic",
|
feature = "portable-atomic",
|
||||||
expect(
|
expect(
|
||||||
clippy::redundant_closure,
|
clippy::redundant_closure,
|
||||||
reason = "portable_atomic_util::Arc has subtly different implicit behavior"
|
reason = "bevy_platform_support::sync::Arc has subtly different implicit behavior"
|
||||||
)
|
)
|
||||||
)]
|
)]
|
||||||
|
|
||||||
use crate::{App, Plugin};
|
use crate::{App, Plugin};
|
||||||
|
|
||||||
use alloc::string::ToString;
|
use alloc::string::ToString;
|
||||||
|
use bevy_platform_support::sync::Arc;
|
||||||
use bevy_tasks::{AsyncComputeTaskPool, ComputeTaskPool, IoTaskPool, TaskPoolBuilder};
|
use bevy_tasks::{AsyncComputeTaskPool, ComputeTaskPool, IoTaskPool, TaskPoolBuilder};
|
||||||
use core::{fmt::Debug, marker::PhantomData};
|
use core::{fmt::Debug, marker::PhantomData};
|
||||||
use log::trace;
|
use log::trace;
|
||||||
@ -16,12 +17,6 @@ use log::trace;
|
|||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use {crate::Last, bevy_ecs::prelude::NonSend};
|
use {crate::Last, bevy_ecs::prelude::NonSend};
|
||||||
|
|
||||||
#[cfg(feature = "portable-atomic")]
|
|
||||||
use portable_atomic_util::Arc;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "portable-atomic"))]
|
|
||||||
use alloc::sync::Arc;
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use bevy_tasks::tick_global_task_pools_on_main_thread;
|
use bevy_tasks::tick_global_task_pools_on_main_thread;
|
||||||
|
|
||||||
|
@ -35,6 +35,9 @@ bevy_transform = { path = "../bevy_transform", version = "0.16.0-dev" }
|
|||||||
bevy_math = { path = "../bevy_math", version = "0.16.0-dev" }
|
bevy_math = { path = "../bevy_math", version = "0.16.0-dev" }
|
||||||
bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev" }
|
bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev" }
|
||||||
bevy_window = { path = "../bevy_window", version = "0.16.0-dev" }
|
bevy_window = { path = "../bevy_window", version = "0.16.0-dev" }
|
||||||
|
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [
|
||||||
|
"std",
|
||||||
|
] }
|
||||||
|
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
bitflags = "2.3"
|
bitflags = "2.3"
|
||||||
|
@ -4,6 +4,7 @@ use bevy_app::prelude::*;
|
|||||||
use bevy_asset::{load_internal_asset, Handle};
|
use bevy_asset::{load_internal_asset, Handle};
|
||||||
use bevy_ecs::{component::*, prelude::*};
|
use bevy_ecs::{component::*, prelude::*};
|
||||||
use bevy_math::UVec2;
|
use bevy_math::UVec2;
|
||||||
|
use bevy_platform_support::time::Instant;
|
||||||
use bevy_reflect::Reflect;
|
use bevy_reflect::Reflect;
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
camera::{Camera, ExtractedCamera},
|
camera::{Camera, ExtractedCamera},
|
||||||
@ -16,7 +17,7 @@ use bevy_render::{
|
|||||||
view::Msaa,
|
view::Msaa,
|
||||||
Render, RenderApp, RenderSet,
|
Render, RenderApp, RenderSet,
|
||||||
};
|
};
|
||||||
use bevy_utils::{HashSet, Instant};
|
use bevy_utils::HashSet;
|
||||||
use bevy_window::PrimaryWindow;
|
use bevy_window::PrimaryWindow;
|
||||||
use resolve::{
|
use resolve::{
|
||||||
node::{OitResolveNode, OitResolvePass},
|
node::{OitResolveNode, OitResolvePass},
|
||||||
|
@ -21,6 +21,9 @@ bevy_ecs = { path = "../bevy_ecs", version = "0.16.0-dev" }
|
|||||||
bevy_time = { path = "../bevy_time", version = "0.16.0-dev" }
|
bevy_time = { path = "../bevy_time", version = "0.16.0-dev" }
|
||||||
bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev" }
|
bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev" }
|
||||||
bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev" }
|
bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev" }
|
||||||
|
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [
|
||||||
|
"std",
|
||||||
|
] }
|
||||||
|
|
||||||
# other
|
# other
|
||||||
const-fnv1a-hash = "1.1.0"
|
const-fnv1a-hash = "1.1.0"
|
||||||
|
@ -6,7 +6,8 @@ use core::{
|
|||||||
|
|
||||||
use bevy_app::{App, SubApp};
|
use bevy_app::{App, SubApp};
|
||||||
use bevy_ecs::system::{Deferred, Res, Resource, SystemBuffer, SystemParam};
|
use bevy_ecs::system::{Deferred, Res, Resource, SystemBuffer, SystemParam};
|
||||||
use bevy_utils::{HashMap, Instant, PassHash};
|
use bevy_platform_support::time::Instant;
|
||||||
|
use bevy_utils::{HashMap, PassHash};
|
||||||
use const_fnv1a_hash::fnv1a_hash_str_64;
|
use const_fnv1a_hash::fnv1a_hash_str_64;
|
||||||
|
|
||||||
use crate::DEFAULT_MAX_HISTORY_LENGTH;
|
use crate::DEFAULT_MAX_HISTORY_LENGTH;
|
||||||
|
@ -76,24 +76,25 @@ std = [
|
|||||||
"nonmax/std",
|
"nonmax/std",
|
||||||
"arrayvec?/std",
|
"arrayvec?/std",
|
||||||
"log/std",
|
"log/std",
|
||||||
|
"bevy_platform_support/std",
|
||||||
]
|
]
|
||||||
|
|
||||||
## `critical-section` provides the building blocks for synchronization primitives
|
## `critical-section` provides the building blocks for synchronization primitives
|
||||||
## on all platforms, including `no_std`.
|
## on all platforms, including `no_std`.
|
||||||
critical-section = [
|
critical-section = [
|
||||||
"dep:critical-section",
|
|
||||||
"bevy_tasks?/critical-section",
|
"bevy_tasks?/critical-section",
|
||||||
"portable-atomic?/critical-section",
|
"bevy_platform_support/critical-section",
|
||||||
|
"bevy_reflect?/critical-section",
|
||||||
]
|
]
|
||||||
|
|
||||||
## `portable-atomic` provides additional platform support for atomic types and
|
## `portable-atomic` provides additional platform support for atomic types and
|
||||||
## operations, even on targets without native support.
|
## operations, even on targets without native support.
|
||||||
portable-atomic = [
|
portable-atomic = [
|
||||||
"dep:portable-atomic",
|
|
||||||
"dep:portable-atomic-util",
|
|
||||||
"bevy_tasks?/portable-atomic",
|
"bevy_tasks?/portable-atomic",
|
||||||
|
"bevy_platform_support/portable-atomic",
|
||||||
"concurrent-queue/portable-atomic",
|
"concurrent-queue/portable-atomic",
|
||||||
"spin/portable_atomic",
|
"spin/portable_atomic",
|
||||||
|
"bevy_reflect?/portable-atomic",
|
||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
@ -104,6 +105,9 @@ bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev", default-features
|
|||||||
"alloc",
|
"alloc",
|
||||||
] }
|
] }
|
||||||
bevy_ecs_macros = { path = "macros", version = "0.16.0-dev" }
|
bevy_ecs_macros = { path = "macros", version = "0.16.0-dev" }
|
||||||
|
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [
|
||||||
|
"alloc",
|
||||||
|
] }
|
||||||
|
|
||||||
bitflags = { version = "2.3", default-features = false }
|
bitflags = { version = "2.3", default-features = false }
|
||||||
concurrent-queue = { version = "2.5.0", default-features = false }
|
concurrent-queue = { version = "2.5.0", default-features = false }
|
||||||
@ -124,13 +128,6 @@ arrayvec = { version = "0.7.4", default-features = false, optional = true }
|
|||||||
smallvec = { version = "1", features = ["union"] }
|
smallvec = { version = "1", features = ["union"] }
|
||||||
indexmap = { version = "2.5.0", default-features = false }
|
indexmap = { version = "2.5.0", default-features = false }
|
||||||
variadics_please = { version = "1.1", default-features = false }
|
variadics_please = { version = "1.1", default-features = false }
|
||||||
critical-section = { version = "1.2.0", optional = true }
|
|
||||||
portable-atomic = { version = "1", default-features = false, features = [
|
|
||||||
"fallback",
|
|
||||||
], optional = true }
|
|
||||||
portable-atomic-util = { version = "0.2.4", features = [
|
|
||||||
"alloc",
|
|
||||||
], optional = true }
|
|
||||||
spin = { version = "0.9.8", default-features = false, features = [
|
spin = { version = "0.9.8", default-features = false, features = [
|
||||||
"spin_mutex",
|
"spin_mutex",
|
||||||
"rwlock",
|
"rwlock",
|
||||||
|
@ -15,6 +15,7 @@ use crate::{
|
|||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::{borrow::Cow, format, vec::Vec};
|
use alloc::{borrow::Cow, format, vec::Vec};
|
||||||
pub use bevy_ecs_macros::Component;
|
pub use bevy_ecs_macros::Component;
|
||||||
|
use bevy_platform_support::sync::Arc;
|
||||||
use bevy_ptr::{OwningPtr, UnsafeCellDeref};
|
use bevy_ptr::{OwningPtr, UnsafeCellDeref};
|
||||||
#[cfg(feature = "bevy_reflect")]
|
#[cfg(feature = "bevy_reflect")]
|
||||||
use bevy_reflect::Reflect;
|
use bevy_reflect::Reflect;
|
||||||
@ -32,12 +33,6 @@ use core::{
|
|||||||
use disqualified::ShortName;
|
use disqualified::ShortName;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[cfg(feature = "portable-atomic")]
|
|
||||||
use portable_atomic_util::Arc;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "portable-atomic"))]
|
|
||||||
use alloc::sync::Arc;
|
|
||||||
|
|
||||||
pub use bevy_ecs_macros::require;
|
pub use bevy_ecs_macros::require;
|
||||||
|
|
||||||
/// A data type that can be used to store data for an [entity].
|
/// A data type that can be used to store data for an [entity].
|
||||||
|
@ -1,19 +1,13 @@
|
|||||||
use alloc::{borrow::ToOwned, vec::Vec};
|
use alloc::{borrow::ToOwned, vec::Vec};
|
||||||
|
use bevy_platform_support::sync::Arc;
|
||||||
use bevy_ptr::{Ptr, PtrMut};
|
use bevy_ptr::{Ptr, PtrMut};
|
||||||
|
use bevy_utils::{HashMap, HashSet};
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use core::{any::TypeId, ptr::NonNull};
|
use core::{any::TypeId, ptr::NonNull};
|
||||||
|
|
||||||
use bevy_utils::{HashMap, HashSet};
|
|
||||||
|
|
||||||
#[cfg(feature = "bevy_reflect")]
|
#[cfg(feature = "bevy_reflect")]
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
|
|
||||||
#[cfg(feature = "portable-atomic")]
|
|
||||||
use portable_atomic_util::Arc;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "portable-atomic"))]
|
|
||||||
use alloc::sync::Arc;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bundle::Bundle,
|
bundle::Bundle,
|
||||||
component::{Component, ComponentCloneHandler, ComponentId, ComponentInfo, Components},
|
component::{Component, ComponentCloneHandler, ComponentId, ComponentInfo, Components},
|
||||||
|
@ -13,11 +13,7 @@ use core::{
|
|||||||
|
|
||||||
use super::Entity;
|
use super::Entity;
|
||||||
|
|
||||||
#[cfg(feature = "portable-atomic")]
|
use bevy_platform_support::sync::Arc;
|
||||||
use portable_atomic_util::Arc;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "portable-atomic"))]
|
|
||||||
use alloc::sync::Arc;
|
|
||||||
|
|
||||||
/// A trait for entity borrows.
|
/// A trait for entity borrows.
|
||||||
///
|
///
|
||||||
|
@ -70,6 +70,7 @@ use crate::{
|
|||||||
storage::{SparseSetIndex, TableId, TableRow},
|
storage::{SparseSetIndex, TableId, TableRow},
|
||||||
};
|
};
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
use bevy_platform_support::sync::atomic::Ordering;
|
||||||
use core::{fmt, hash::Hash, mem, num::NonZero};
|
use core::{fmt, hash::Hash, mem, num::NonZero};
|
||||||
use log::warn;
|
use log::warn;
|
||||||
|
|
||||||
@ -79,26 +80,16 @@ use core::panic::Location;
|
|||||||
#[cfg(feature = "serialize")]
|
#[cfg(feature = "serialize")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[cfg(not(feature = "portable-atomic"))]
|
#[cfg(target_has_atomic = "64")]
|
||||||
use core::sync::atomic::Ordering;
|
use bevy_platform_support::sync::atomic::AtomicI64 as AtomicIdCursor;
|
||||||
|
|
||||||
#[cfg(feature = "portable-atomic")]
|
|
||||||
use portable_atomic::Ordering;
|
|
||||||
|
|
||||||
#[cfg(all(target_has_atomic = "64", not(feature = "portable-atomic")))]
|
|
||||||
use core::sync::atomic::AtomicI64 as AtomicIdCursor;
|
|
||||||
#[cfg(all(target_has_atomic = "64", feature = "portable-atomic"))]
|
|
||||||
use portable_atomic::AtomicI64 as AtomicIdCursor;
|
|
||||||
#[cfg(target_has_atomic = "64")]
|
#[cfg(target_has_atomic = "64")]
|
||||||
type IdCursor = i64;
|
type IdCursor = i64;
|
||||||
|
|
||||||
/// Most modern platforms support 64-bit atomics, but some less-common platforms
|
/// Most modern platforms support 64-bit atomics, but some less-common platforms
|
||||||
/// do not. This fallback allows compilation using a 32-bit cursor instead, with
|
/// do not. This fallback allows compilation using a 32-bit cursor instead, with
|
||||||
/// the caveat that some conversions may fail (and panic) at runtime.
|
/// the caveat that some conversions may fail (and panic) at runtime.
|
||||||
#[cfg(all(not(target_has_atomic = "64"), not(feature = "portable-atomic")))]
|
#[cfg(not(target_has_atomic = "64"))]
|
||||||
use core::sync::atomic::AtomicIsize as AtomicIdCursor;
|
use bevy_platform_support::sync::atomic::AtomicIsize as AtomicIdCursor;
|
||||||
#[cfg(all(not(target_has_atomic = "64"), feature = "portable-atomic"))]
|
|
||||||
use portable_atomic::AtomicIsize as AtomicIdCursor;
|
|
||||||
#[cfg(not(target_has_atomic = "64"))]
|
#[cfg(not(target_has_atomic = "64"))]
|
||||||
type IdCursor = isize;
|
type IdCursor = isize;
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use alloc::{boxed::Box, vec::Vec};
|
use alloc::{boxed::Box, vec::Vec};
|
||||||
|
use bevy_platform_support::sync::Arc;
|
||||||
use bevy_tasks::{ComputeTaskPool, Scope, TaskPool, ThreadExecutor};
|
use bevy_tasks::{ComputeTaskPool, Scope, TaskPool, ThreadExecutor};
|
||||||
use bevy_utils::{default, syncunsafecell::SyncUnsafeCell};
|
use bevy_utils::{default, syncunsafecell::SyncUnsafeCell};
|
||||||
use concurrent_queue::ConcurrentQueue;
|
use concurrent_queue::ConcurrentQueue;
|
||||||
@ -12,12 +13,6 @@ use std::{
|
|||||||
#[cfg(feature = "trace")]
|
#[cfg(feature = "trace")]
|
||||||
use tracing::{info_span, Span};
|
use tracing::{info_span, Span};
|
||||||
|
|
||||||
#[cfg(feature = "portable-atomic")]
|
|
||||||
use portable_atomic_util::Arc;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "portable-atomic"))]
|
|
||||||
use alloc::sync::Arc;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
archetype::ArchetypeComponentId,
|
archetype::ArchetypeComponentId,
|
||||||
prelude::Resource,
|
prelude::Resource,
|
||||||
|
@ -4,12 +4,7 @@ use crate::{
|
|||||||
system::{ExclusiveSystemParam, ReadOnlySystemParam, SystemMeta, SystemParam},
|
system::{ExclusiveSystemParam, ReadOnlySystemParam, SystemMeta, SystemParam},
|
||||||
world::{FromWorld, World},
|
world::{FromWorld, World},
|
||||||
};
|
};
|
||||||
|
use bevy_platform_support::sync::atomic::{AtomicUsize, Ordering};
|
||||||
#[cfg(not(feature = "portable-atomic"))]
|
|
||||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
|
||||||
|
|
||||||
#[cfg(feature = "portable-atomic")]
|
|
||||||
use portable_atomic::{AtomicUsize, Ordering};
|
|
||||||
|
|
||||||
use super::unsafe_world_cell::UnsafeWorldCell;
|
use super::unsafe_world_cell::UnsafeWorldCell;
|
||||||
|
|
||||||
|
@ -53,23 +53,15 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use alloc::{boxed::Box, vec::Vec};
|
use alloc::{boxed::Box, vec::Vec};
|
||||||
|
use bevy_platform_support::sync::atomic::{AtomicU32, Ordering};
|
||||||
use bevy_ptr::{OwningPtr, Ptr};
|
use bevy_ptr::{OwningPtr, Ptr};
|
||||||
use core::{any::TypeId, fmt};
|
use core::{any::TypeId, fmt, panic::Location};
|
||||||
use log::warn;
|
use log::warn;
|
||||||
|
use unsafe_world_cell::{UnsafeEntityCell, UnsafeWorldCell};
|
||||||
#[cfg(not(feature = "portable-atomic"))]
|
|
||||||
use core::sync::atomic::{AtomicU32, Ordering};
|
|
||||||
|
|
||||||
#[cfg(feature = "portable-atomic")]
|
|
||||||
use portable_atomic::{AtomicU32, Ordering};
|
|
||||||
|
|
||||||
#[cfg(feature = "track_location")]
|
#[cfg(feature = "track_location")]
|
||||||
use bevy_ptr::UnsafeCellDeref;
|
use bevy_ptr::UnsafeCellDeref;
|
||||||
|
|
||||||
use core::panic::Location;
|
|
||||||
|
|
||||||
use unsafe_world_cell::{UnsafeEntityCell, UnsafeWorldCell};
|
|
||||||
|
|
||||||
/// Stores and exposes operations on [entities](Entity), [components](Component), resources,
|
/// Stores and exposes operations on [entities](Entity), [components](Component), resources,
|
||||||
/// and their associated metadata.
|
/// and their associated metadata.
|
||||||
///
|
///
|
||||||
|
@ -15,19 +15,13 @@ use crate::{
|
|||||||
system::Resource,
|
system::Resource,
|
||||||
world::RawCommandQueue,
|
world::RawCommandQueue,
|
||||||
};
|
};
|
||||||
|
use bevy_platform_support::sync::atomic::Ordering;
|
||||||
use bevy_ptr::Ptr;
|
use bevy_ptr::Ptr;
|
||||||
#[cfg(feature = "track_location")]
|
|
||||||
use bevy_ptr::UnsafeCellDeref;
|
|
||||||
#[cfg(feature = "track_location")]
|
|
||||||
use core::panic::Location;
|
|
||||||
use core::{any::TypeId, cell::UnsafeCell, fmt::Debug, marker::PhantomData, ptr};
|
use core::{any::TypeId, cell::UnsafeCell, fmt::Debug, marker::PhantomData, ptr};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[cfg(not(feature = "portable-atomic"))]
|
#[cfg(feature = "track_location")]
|
||||||
use core::sync::atomic::Ordering;
|
use {bevy_ptr::UnsafeCellDeref, core::panic::Location};
|
||||||
|
|
||||||
#[cfg(feature = "portable-atomic")]
|
|
||||||
use portable_atomic::Ordering;
|
|
||||||
|
|
||||||
/// Variant of the [`World`] where resource and component accesses take `&self`, and the responsibility to avoid
|
/// Variant of the [`World`] where resource and component accesses take `&self`, and the responsibility to avoid
|
||||||
/// aliasing violations are given to the caller instead of being checked at compile-time by rust's unique XOR shared rule.
|
/// aliasing violations are given to the caller instead of being checked at compile-time by rust's unique XOR shared rule.
|
||||||
|
@ -47,11 +47,19 @@ std = [
|
|||||||
|
|
||||||
## `critical-section` provides the building blocks for synchronization primitives
|
## `critical-section` provides the building blocks for synchronization primitives
|
||||||
## on all platforms, including `no_std`.
|
## on all platforms, including `no_std`.
|
||||||
critical-section = ["bevy_app/critical-section", "bevy_ecs/critical-section"]
|
critical-section = [
|
||||||
|
"bevy_app/critical-section",
|
||||||
|
"bevy_ecs/critical-section",
|
||||||
|
"bevy_reflect?/critical-section",
|
||||||
|
]
|
||||||
|
|
||||||
## `portable-atomic` provides additional platform support for atomic types and
|
## `portable-atomic` provides additional platform support for atomic types and
|
||||||
## operations, even on targets without native support.
|
## operations, even on targets without native support.
|
||||||
portable-atomic = ["bevy_app/portable-atomic", "bevy_ecs/portable-atomic"]
|
portable-atomic = [
|
||||||
|
"bevy_app/portable-atomic",
|
||||||
|
"bevy_ecs/portable-atomic",
|
||||||
|
"bevy_reflect?/portable-atomic",
|
||||||
|
]
|
||||||
|
|
||||||
## Uses the `libm` maths library instead of the one provided in `std` and `core`.
|
## Uses the `libm` maths library instead of the one provided in `std` and `core`.
|
||||||
libm = ["bevy_math/libm"]
|
libm = ["bevy_math/libm"]
|
||||||
|
@ -278,6 +278,7 @@ bevy_log = { path = "../bevy_log", version = "0.16.0-dev" }
|
|||||||
bevy_math = { path = "../bevy_math", version = "0.16.0-dev", features = [
|
bevy_math = { path = "../bevy_math", version = "0.16.0-dev", features = [
|
||||||
"bevy_reflect",
|
"bevy_reflect",
|
||||||
] }
|
] }
|
||||||
|
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev" }
|
||||||
bevy_ptr = { path = "../bevy_ptr", version = "0.16.0-dev" }
|
bevy_ptr = { path = "../bevy_ptr", version = "0.16.0-dev" }
|
||||||
bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", features = [
|
bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", features = [
|
||||||
"bevy",
|
"bevy",
|
||||||
|
@ -46,6 +46,7 @@ pub use bevy_math as math;
|
|||||||
pub use bevy_pbr as pbr;
|
pub use bevy_pbr as pbr;
|
||||||
#[cfg(feature = "bevy_picking")]
|
#[cfg(feature = "bevy_picking")]
|
||||||
pub use bevy_picking as picking;
|
pub use bevy_picking as picking;
|
||||||
|
pub use bevy_platform_support as platform_support;
|
||||||
pub use bevy_ptr as ptr;
|
pub use bevy_ptr as ptr;
|
||||||
pub use bevy_reflect as reflect;
|
pub use bevy_reflect as reflect;
|
||||||
#[cfg(feature = "bevy_remote")]
|
#[cfg(feature = "bevy_remote")]
|
||||||
|
@ -26,6 +26,9 @@ bevy_time = { path = "../bevy_time", version = "0.16.0-dev" }
|
|||||||
bevy_transform = { path = "../bevy_transform", version = "0.16.0-dev" }
|
bevy_transform = { path = "../bevy_transform", version = "0.16.0-dev" }
|
||||||
bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev" }
|
bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev" }
|
||||||
bevy_window = { path = "../bevy_window", version = "0.16.0-dev" }
|
bevy_window = { path = "../bevy_window", version = "0.16.0-dev" }
|
||||||
|
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [
|
||||||
|
"std",
|
||||||
|
] }
|
||||||
|
|
||||||
# other
|
# other
|
||||||
crossbeam-channel = { version = "0.5", optional = true }
|
crossbeam-channel = { version = "0.5", optional = true }
|
||||||
|
@ -41,9 +41,10 @@ use core::{fmt::Debug, time::Duration};
|
|||||||
|
|
||||||
use bevy_ecs::{prelude::*, query::QueryData, system::SystemParam, traversal::Traversal};
|
use bevy_ecs::{prelude::*, query::QueryData, system::SystemParam, traversal::Traversal};
|
||||||
use bevy_math::Vec2;
|
use bevy_math::Vec2;
|
||||||
|
use bevy_platform_support::time::Instant;
|
||||||
use bevy_reflect::prelude::*;
|
use bevy_reflect::prelude::*;
|
||||||
use bevy_render::camera::NormalizedRenderTarget;
|
use bevy_render::camera::NormalizedRenderTarget;
|
||||||
use bevy_utils::{HashMap, Instant};
|
use bevy_utils::HashMap;
|
||||||
use bevy_window::Window;
|
use bevy_window::Window;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
|
52
crates/bevy_platform_support/Cargo.toml
Normal file
52
crates/bevy_platform_support/Cargo.toml
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
[package]
|
||||||
|
name = "bevy_platform_support"
|
||||||
|
version = "0.16.0-dev"
|
||||||
|
edition = "2021"
|
||||||
|
description = "Platform compatibility support for Bevy Engine"
|
||||||
|
homepage = "https://bevyengine.org"
|
||||||
|
repository = "https://github.com/bevyengine/bevy"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
keywords = ["bevy"]
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["std"]
|
||||||
|
|
||||||
|
# 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",
|
||||||
|
"critical-section?/std",
|
||||||
|
"portable-atomic?/std",
|
||||||
|
"portable-atomic-util?/std",
|
||||||
|
]
|
||||||
|
|
||||||
|
alloc = ["portable-atomic-util?/alloc"]
|
||||||
|
|
||||||
|
## `critical-section` provides the building blocks for synchronization primitives
|
||||||
|
## on all platforms, including `no_std`.
|
||||||
|
critical-section = ["dep:critical-section", "portable-atomic?/critical-section"]
|
||||||
|
|
||||||
|
## `portable-atomic` provides additional platform support for atomic types and
|
||||||
|
## operations, even on targets without native support.
|
||||||
|
portable-atomic = ["dep:portable-atomic", "dep:portable-atomic-util"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
critical-section = { version = "1.2.0", default-features = false, optional = true }
|
||||||
|
portable-atomic = { version = "1", default-features = false, features = [
|
||||||
|
"fallback",
|
||||||
|
], optional = true }
|
||||||
|
portable-atomic-util = { version = "0.2.4", default-features = false, optional = true }
|
||||||
|
|
||||||
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
|
web-time = { version = "1.1", default-features = false }
|
||||||
|
getrandom = { version = "0.2.0", default-features = false, features = ["js"] }
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
|
[package.metadata.docs.rs]
|
||||||
|
rustdoc-args = ["-Zunstable-options", "--generate-link-to-definition"]
|
||||||
|
all-features = true
|
56
crates/bevy_platform_support/README.md
Normal file
56
crates/bevy_platform_support/README.md
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# Bevy Platform Support
|
||||||
|
|
||||||
|
[](https://github.com/bevyengine/bevy#license)
|
||||||
|
[](https://crates.io/crates/bevy_platform_support)
|
||||||
|
[](https://crates.io/crates/bevy_platform_support)
|
||||||
|
[](https://docs.rs/bevy_platform_support/latest/bevy_platform_support/)
|
||||||
|
[](https://discord.gg/bevy)
|
||||||
|
|
||||||
|
Rust is a fantastic multi-platform language with extensive support for modern targets through its [standard library](https://doc.rust-lang.org/stable/std/).
|
||||||
|
However, some items within the standard library have alternatives that are better suited for [Bevy](https://crates.io/crates/bevy) and game engines in general.
|
||||||
|
Additionally, to support embedded and other esoteric platforms, it's often necessary to shed reliance on `std`, making your crate [`no_std`](https://docs.rust-embedded.org/book/intro/no-std.html).
|
||||||
|
|
||||||
|
These needs are handled by this crate, `bevy_platform_support`.
|
||||||
|
The goal of this crate is to provide alternatives and extensions to the Rust standard library which minimize friction when developing with and for Bevy across multiple platforms.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
Like any dependency from [crates.io](https://crates.io/), use `cargo` to add it to your `Cargo.toml` file:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo add bevy_platform_support
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, instead of importing from `std` you can use `bevy_platform_support` for items it has alternative for.
|
||||||
|
See the documentation for what items are available, and explanations for _why_ you may want to use them.
|
||||||
|
|
||||||
|
## `no_std` Support
|
||||||
|
|
||||||
|
By default, `bevy_platform_support` will activate the `std` feature, requiring access to the `std` crate for whichever platforms you're targeting.
|
||||||
|
To use this crate on `no_std` platforms, disable default features:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
bevy_platform_support = { version = "x.y.z", default-features = false }
|
||||||
|
```
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
### `std` (_default_)
|
||||||
|
|
||||||
|
Enables usage of the standard library. Note that where this crate has alternatives to the standard library that it considers _better_ than what's provided, it will provide the alternative even when `std` is enabled.
|
||||||
|
This is explicitly incompatible with `no_std` targets.
|
||||||
|
|
||||||
|
### `alloc` (_default_)
|
||||||
|
|
||||||
|
Enables usage of the [`alloc`](https://doc.rust-lang.org/stable/alloc/) crate. Note that this feature is automatically enabled when enabling `std`.
|
||||||
|
This is compatible with most `no_std` targets, but not all.
|
||||||
|
|
||||||
|
### `portable-atomic`
|
||||||
|
|
||||||
|
Switches to using [`portable-atomic`](https://docs.rs/portable-atomic/latest/portable_atomic/) as a backend for atomic types, such as `Arc`, `AtomicU8`, etc.
|
||||||
|
You may need to enable this feature on platforms without full support for atomic types or certain operations, such as [atomic CAS](https://en.wikipedia.org/wiki/Compare-and-swap).
|
||||||
|
|
||||||
|
### `critical-section`
|
||||||
|
|
||||||
|
Switches to using [`critical-section`](https://docs.rs/critical-section/latest/critical_section/) as a backend for synchronization.
|
||||||
|
You may need to enable this feature on platforms with little to no support for atomic operations, and is often paired with the `portable-atomic` feature.
|
19
crates/bevy_platform_support/src/lib.rs
Normal file
19
crates/bevy_platform_support/src/lib.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||||
|
#![doc(
|
||||||
|
html_logo_url = "https://bevyengine.org/assets/icon.png",
|
||||||
|
html_favicon_url = "https://bevyengine.org/assets/icon.png"
|
||||||
|
)]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
//! Platform compatibility support for first-party [Bevy] engine crates.
|
||||||
|
//!
|
||||||
|
//! [Bevy]: https://bevyengine.org/
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
extern crate std;
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
pub mod sync;
|
||||||
|
pub mod time;
|
30
crates/bevy_platform_support/src/sync.rs
Normal file
30
crates/bevy_platform_support/src/sync.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
//! Provides various synchronization alternatives to language primitives.
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
pub use arc::{Arc, Weak};
|
||||||
|
|
||||||
|
pub mod atomic {
|
||||||
|
//! Provides various atomic alternatives to language primitives.
|
||||||
|
//!
|
||||||
|
//! Certain platforms lack complete atomic support, requiring the use of a fallback
|
||||||
|
//! such as `portable-atomic`.
|
||||||
|
//! Using these types will ensure the correct atomic provider is used without the need for
|
||||||
|
//! feature gates in your own code.
|
||||||
|
|
||||||
|
pub use atomic::{
|
||||||
|
AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16,
|
||||||
|
AtomicU32, AtomicU64, AtomicU8, AtomicUsize, Ordering,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "portable-atomic"))]
|
||||||
|
use core::sync::atomic;
|
||||||
|
|
||||||
|
#[cfg(feature = "portable-atomic")]
|
||||||
|
use portable_atomic as atomic;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "alloc", feature = "portable-atomic"))]
|
||||||
|
use portable_atomic_util as arc;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "alloc", not(feature = "portable-atomic")))]
|
||||||
|
use alloc::sync as arc;
|
194
crates/bevy_platform_support/src/time.rs
Normal file
194
crates/bevy_platform_support/src/time.rs
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
//! Provides `Instant` for all platforms.
|
||||||
|
|
||||||
|
pub use time::Instant;
|
||||||
|
|
||||||
|
// TODO: Create a `web` feature to enable WASI compatibility.
|
||||||
|
// See https://github.com/bevyengine/bevy/issues/4906
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
use web_time as time;
|
||||||
|
|
||||||
|
#[cfg(all(not(target_arch = "wasm32"), feature = "std"))]
|
||||||
|
use std::time;
|
||||||
|
|
||||||
|
#[cfg(all(not(target_arch = "wasm32"), not(feature = "std")))]
|
||||||
|
use fallback as time;
|
||||||
|
|
||||||
|
#[cfg(all(not(target_arch = "wasm32"), not(feature = "std")))]
|
||||||
|
mod fallback {
|
||||||
|
//! Provides a fallback implementation of `Instant` from the standard library.
|
||||||
|
|
||||||
|
#![expect(
|
||||||
|
unsafe_code,
|
||||||
|
reason = "Instant fallback requires unsafe to allow users to update the internal value"
|
||||||
|
)]
|
||||||
|
|
||||||
|
use crate::sync::atomic::{AtomicPtr, Ordering};
|
||||||
|
|
||||||
|
use core::{
|
||||||
|
fmt,
|
||||||
|
ops::{Add, AddAssign, Sub, SubAssign},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
static ELAPSED_GETTER: AtomicPtr<fn() -> Duration> = AtomicPtr::new(unset_getter as *mut _);
|
||||||
|
|
||||||
|
/// Fallback implementation of `Instant` suitable for a `no_std` environment.
|
||||||
|
///
|
||||||
|
/// If you are on any of the following target architectures, this is a drop-in replacement:
|
||||||
|
///
|
||||||
|
/// - `x86`
|
||||||
|
/// - `x86_64`
|
||||||
|
/// - `aarch64`
|
||||||
|
///
|
||||||
|
/// On any other architecture, you must call [`Instant::set_elapsed`], providing a method
|
||||||
|
/// which when called supplies a monotonically increasing count of elapsed nanoseconds relative
|
||||||
|
/// to some arbitrary point in time.
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct Instant(Duration);
|
||||||
|
|
||||||
|
impl Instant {
|
||||||
|
/// Returns an instant corresponding to "now".
|
||||||
|
#[must_use]
|
||||||
|
pub fn now() -> Instant {
|
||||||
|
let getter = ELAPSED_GETTER.load(Ordering::Acquire);
|
||||||
|
|
||||||
|
// SAFETY: Function pointer is always valid
|
||||||
|
let getter = unsafe { *getter };
|
||||||
|
|
||||||
|
Self((getter)())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Provides a function returning the amount of time that has elapsed since execution began.
|
||||||
|
/// The getter provided to this method will be used by [`now`](Instant::now).
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// - The function provided must accurately represent the elapsed time.
|
||||||
|
/// - The function must preserve all invariants of the [`Instant`] type.
|
||||||
|
/// - The pointer to the function must be valid whenever [`Instant::now`] is called.
|
||||||
|
pub unsafe fn set_elapsed(getter: *mut fn() -> Duration) {
|
||||||
|
ELAPSED_GETTER.store(getter, Ordering::Release);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the amount of time elapsed from another instant to this one,
|
||||||
|
/// or zero duration if that instant is later than this one.
|
||||||
|
#[must_use]
|
||||||
|
pub fn duration_since(&self, earlier: Instant) -> Duration {
|
||||||
|
self.saturating_duration_since(earlier)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the amount of time elapsed from another instant to this one,
|
||||||
|
/// or None if that instant is later than this one.
|
||||||
|
///
|
||||||
|
/// Due to monotonicity bugs, even under correct logical ordering of the passed `Instant`s,
|
||||||
|
/// this method can return `None`.
|
||||||
|
#[must_use]
|
||||||
|
pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
|
||||||
|
self.0.checked_sub(earlier.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the amount of time elapsed from another instant to this one,
|
||||||
|
/// or zero duration if that instant is later than this one.
|
||||||
|
#[must_use]
|
||||||
|
pub fn saturating_duration_since(&self, earlier: Instant) -> Duration {
|
||||||
|
self.0.saturating_sub(earlier.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the amount of time elapsed since this instant.
|
||||||
|
#[must_use]
|
||||||
|
pub fn elapsed(&self) -> Duration {
|
||||||
|
self.saturating_duration_since(Instant::now())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as
|
||||||
|
/// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
|
||||||
|
/// otherwise.
|
||||||
|
pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
|
||||||
|
self.0.checked_add(duration).map(Instant)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as
|
||||||
|
/// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
|
||||||
|
/// otherwise.
|
||||||
|
pub fn checked_sub(&self, duration: Duration) -> Option<Instant> {
|
||||||
|
self.0.checked_sub(duration).map(Instant)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add<Duration> for Instant {
|
||||||
|
type Output = Instant;
|
||||||
|
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// This function may panic if the resulting point in time cannot be represented by the
|
||||||
|
/// underlying data structure. See [`Instant::checked_add`] for a version without panic.
|
||||||
|
fn add(self, other: Duration) -> Instant {
|
||||||
|
self.checked_add(other)
|
||||||
|
.expect("overflow when adding duration to instant")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddAssign<Duration> for Instant {
|
||||||
|
fn add_assign(&mut self, other: Duration) {
|
||||||
|
*self = *self + other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sub<Duration> for Instant {
|
||||||
|
type Output = Instant;
|
||||||
|
|
||||||
|
fn sub(self, other: Duration) -> Instant {
|
||||||
|
self.checked_sub(other)
|
||||||
|
.expect("overflow when subtracting duration from instant")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SubAssign<Duration> for Instant {
|
||||||
|
fn sub_assign(&mut self, other: Duration) {
|
||||||
|
*self = *self - other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sub<Instant> for Instant {
|
||||||
|
type Output = Duration;
|
||||||
|
|
||||||
|
/// Returns the amount of time elapsed from another instant to this one,
|
||||||
|
/// or zero duration if that instant is later than this one.
|
||||||
|
fn sub(self, other: Instant) -> Duration {
|
||||||
|
self.duration_since(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Instant {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
self.0.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unset_getter() -> Duration {
|
||||||
|
let _nanos: u64;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86")]
|
||||||
|
unsafe {
|
||||||
|
_nanos = core::arch::x86::_rdtsc();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
unsafe {
|
||||||
|
_nanos = core::arch::x86_64::_rdtsc();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
unsafe {
|
||||||
|
let mut ticks: u64;
|
||||||
|
core::arch::asm!("mrs {}, cntvct_el0", out(reg) ticks);
|
||||||
|
_nanos = ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")))]
|
||||||
|
panic!("An elapsed time getter has not been provided to `Instant`. Please use `Instant::set_elapsed(...)` before calling `Instant::now()`");
|
||||||
|
|
||||||
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64"))]
|
||||||
|
return Duration::from_nanos(_nanos);
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,48 @@ rust-version = "1.81.0"
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std", "smallvec", "debug"]
|
default = ["std", "smallvec", "debug"]
|
||||||
|
|
||||||
|
# Features
|
||||||
|
|
||||||
|
## When enabled, allows documentation comments to be accessed via reflection
|
||||||
|
documentation = ["bevy_reflect_derive/documentation"]
|
||||||
|
|
||||||
|
## Enables function reflection
|
||||||
|
functions = ["bevy_reflect_derive/functions"]
|
||||||
|
|
||||||
|
# When enabled, provides Bevy-related reflection implementations
|
||||||
|
bevy = ["smallvec", "smol_str"]
|
||||||
|
|
||||||
|
# Debugging Features
|
||||||
|
|
||||||
|
## Enables features useful for debugging reflection
|
||||||
|
debug = ["debug_stack"]
|
||||||
|
|
||||||
|
## When enabled, keeps track of the current serialization/deserialization context for better error messages
|
||||||
|
debug_stack = []
|
||||||
|
|
||||||
|
# Integrations
|
||||||
|
|
||||||
|
## Adds reflection support to `glam` types.
|
||||||
|
glam = ["dep:glam"]
|
||||||
|
|
||||||
|
## Adds reflection support to `petgraph` types.
|
||||||
|
petgraph = ["dep:petgraph", "std"]
|
||||||
|
|
||||||
|
## Adds reflection support to `smallvec` types.
|
||||||
|
smallvec = ["dep:smallvec"]
|
||||||
|
|
||||||
|
## Adds reflection support to `uuid` types.
|
||||||
|
uuid = ["dep:uuid"]
|
||||||
|
|
||||||
|
## Adds reflection support to `wgpu-types` types.
|
||||||
|
wgpu-types = ["dep:wgpu-types", "std"]
|
||||||
|
|
||||||
|
# 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 = [
|
std = [
|
||||||
"bevy_utils/std",
|
"bevy_utils/std",
|
||||||
"erased-serde/std",
|
"erased-serde/std",
|
||||||
@ -20,22 +62,23 @@ std = [
|
|||||||
"glam?/std",
|
"glam?/std",
|
||||||
"smol_str?/std",
|
"smol_str?/std",
|
||||||
"uuid?/std",
|
"uuid?/std",
|
||||||
|
"bevy_platform_support/std",
|
||||||
|
]
|
||||||
|
|
||||||
|
## `critical-section` provides the building blocks for synchronization primitives
|
||||||
|
## on all platforms, including `no_std`.
|
||||||
|
critical-section = [
|
||||||
|
"bevy_platform_support/critical-section",
|
||||||
|
"bevy_utils/critical-section",
|
||||||
|
]
|
||||||
|
|
||||||
|
## `portable-atomic` provides additional platform support for atomic types and
|
||||||
|
## operations, even on targets without native support.
|
||||||
|
portable-atomic = [
|
||||||
|
"bevy_platform_support/portable-atomic",
|
||||||
|
"spin/portable_atomic",
|
||||||
|
"bevy_utils/portable-atomic",
|
||||||
]
|
]
|
||||||
# When enabled, provides Bevy-related reflection implementations
|
|
||||||
bevy = ["smallvec", "smol_str"]
|
|
||||||
glam = ["dep:glam"]
|
|
||||||
petgraph = ["dep:petgraph", "std"]
|
|
||||||
smallvec = ["dep:smallvec"]
|
|
||||||
uuid = ["dep:uuid"]
|
|
||||||
wgpu-types = ["dep:wgpu-types", "std"]
|
|
||||||
# Enables features useful for debugging reflection
|
|
||||||
debug = ["debug_stack"]
|
|
||||||
# When enabled, keeps track of the current serialization/deserialization context for better error messages
|
|
||||||
debug_stack = []
|
|
||||||
# When enabled, allows documentation comments to be accessed via reflection
|
|
||||||
documentation = ["bevy_reflect_derive/documentation"]
|
|
||||||
# Enables function reflection
|
|
||||||
functions = ["bevy_reflect_derive/functions"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# bevy
|
# bevy
|
||||||
@ -44,6 +87,9 @@ bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev", default-features
|
|||||||
"alloc",
|
"alloc",
|
||||||
] }
|
] }
|
||||||
bevy_ptr = { path = "../bevy_ptr", version = "0.16.0-dev" }
|
bevy_ptr = { path = "../bevy_ptr", version = "0.16.0-dev" }
|
||||||
|
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [
|
||||||
|
"alloc",
|
||||||
|
] }
|
||||||
|
|
||||||
# used by bevy-utils, but it also needs reflect impls
|
# used by bevy-utils, but it also needs reflect impls
|
||||||
foldhash = { version = "0.1.3", default-features = false }
|
foldhash = { version = "0.1.3", default-features = false }
|
||||||
@ -62,7 +108,6 @@ spin = { version = "0.9.8", default-features = false, features = [
|
|||||||
"rwlock",
|
"rwlock",
|
||||||
] }
|
] }
|
||||||
assert_type_match = "0.1.1"
|
assert_type_match = "0.1.1"
|
||||||
|
|
||||||
smallvec = { version = "1.11", default-features = false, optional = true }
|
smallvec = { version = "1.11", default-features = false, optional = true }
|
||||||
glam = { version = "0.29", default-features = false, features = [
|
glam = { version = "0.29", default-features = false, features = [
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -4,7 +4,8 @@ use crate::{
|
|||||||
type_info::impl_type_methods,
|
type_info::impl_type_methods,
|
||||||
DynamicEnum, Generics, PartialReflect, Type, TypePath, VariantInfo, VariantType,
|
DynamicEnum, Generics, PartialReflect, Type, TypePath, VariantInfo, VariantType,
|
||||||
};
|
};
|
||||||
use alloc::{boxed::Box, format, string::String, sync::Arc};
|
use alloc::{boxed::Box, format, string::String};
|
||||||
|
use bevy_platform_support::sync::Arc;
|
||||||
use bevy_utils::HashMap;
|
use bevy_utils::HashMap;
|
||||||
use core::slice::Iter;
|
use core::slice::Iter;
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ use crate::{
|
|||||||
NamedField, UnnamedField,
|
NamedField, UnnamedField,
|
||||||
};
|
};
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::sync::Arc;
|
use bevy_platform_support::sync::Arc;
|
||||||
use bevy_utils::HashMap;
|
use bevy_utils::HashMap;
|
||||||
use core::slice::Iter;
|
use core::slice::Iter;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
@ -3,7 +3,7 @@ use crate::{
|
|||||||
type_info::impl_type_methods,
|
type_info::impl_type_methods,
|
||||||
MaybeTyped, PartialReflect, Type, TypeInfo, TypePath,
|
MaybeTyped, PartialReflect, Type, TypeInfo, TypePath,
|
||||||
};
|
};
|
||||||
use alloc::sync::Arc;
|
use bevy_platform_support::sync::Arc;
|
||||||
|
|
||||||
/// The named field of a reflected struct.
|
/// The named field of a reflected struct.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -11,7 +11,8 @@ use crate::{
|
|||||||
ApplyError, MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned,
|
ApplyError, MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned,
|
||||||
ReflectRef, TypeInfo, TypePath,
|
ReflectRef, TypeInfo, TypePath,
|
||||||
};
|
};
|
||||||
use alloc::{borrow::Cow, boxed::Box, sync::Arc};
|
use alloc::{borrow::Cow, boxed::Box};
|
||||||
|
use bevy_platform_support::sync::Arc;
|
||||||
use bevy_reflect_derive::impl_type_path;
|
use bevy_reflect_derive::impl_type_path;
|
||||||
use core::fmt::{Debug, Formatter};
|
use core::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
@ -92,8 +93,21 @@ impl<'env> DynamicFunction<'env> {
|
|||||||
func: F,
|
func: F,
|
||||||
info: impl TryInto<FunctionInfo, Error: Debug>,
|
info: impl TryInto<FunctionInfo, Error: Debug>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let arc = Arc::new(func);
|
||||||
|
|
||||||
|
#[cfg(feature = "portable-atomic")]
|
||||||
|
#[expect(
|
||||||
|
unsafe_code,
|
||||||
|
reason = "unsized coercion is an unstable feature for non-std types"
|
||||||
|
)]
|
||||||
|
// SAFETY:
|
||||||
|
// - Coercion from `T` to `dyn for<'a> Fn(ArgList<'a>) -> FunctionResult<'a> + Send + Sync + 'env`
|
||||||
|
// is valid as `T: for<'a> Fn(ArgList<'a>) -> FunctionResult<'a> + Send + Sync + 'env`
|
||||||
|
// - `Arc::from_raw` receives a valid pointer from a previous call to `Arc::into_raw`
|
||||||
|
let arc = unsafe { ArcFn::<'env>::from_raw(Arc::into_raw(arc) as *const _) };
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
internal: DynamicFunctionInternal::new(Arc::new(func), info.try_into().unwrap()),
|
internal: DynamicFunctionInternal::new(arc, info.try_into().unwrap()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use alloc::{borrow::Cow, boxed::Box, sync::Arc};
|
use alloc::{borrow::Cow, boxed::Box};
|
||||||
|
use bevy_platform_support::sync::Arc;
|
||||||
use core::fmt::{Debug, Formatter};
|
use core::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
use crate::func::{
|
use crate::func::{
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use alloc::{borrow::Cow, sync::Arc};
|
use alloc::borrow::Cow;
|
||||||
|
use bevy_platform_support::sync::Arc;
|
||||||
|
use bevy_utils::HashMap;
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use std::sync::{PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
use std::sync::{PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||||
|
|
||||||
use bevy_utils::HashMap;
|
|
||||||
|
|
||||||
use crate::func::{
|
use crate::func::{
|
||||||
ArgList, DynamicFunction, FunctionRegistrationError, FunctionResult, IntoFunction,
|
ArgList, DynamicFunction, FunctionRegistrationError, FunctionResult, IntoFunction,
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use crate::type_info::impl_type_methods;
|
use crate::type_info::impl_type_methods;
|
||||||
use crate::{Reflect, Type, TypePath};
|
use crate::{Reflect, Type, TypePath};
|
||||||
use alloc::{borrow::Cow, boxed::Box, sync::Arc};
|
use alloc::{borrow::Cow, boxed::Box};
|
||||||
|
use bevy_platform_support::sync::Arc;
|
||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
use derive_more::derive::From;
|
use derive_more::derive::From;
|
||||||
|
|
||||||
@ -180,7 +181,19 @@ impl ConstParamInfo {
|
|||||||
|
|
||||||
/// Sets the default value for the parameter.
|
/// Sets the default value for the parameter.
|
||||||
pub fn with_default<T: Reflect + 'static>(mut self, default: T) -> Self {
|
pub fn with_default<T: Reflect + 'static>(mut self, default: T) -> Self {
|
||||||
self.default = Some(Arc::new(default));
|
let arc = Arc::new(default);
|
||||||
|
|
||||||
|
#[cfg(feature = "portable-atomic")]
|
||||||
|
#[expect(
|
||||||
|
unsafe_code,
|
||||||
|
reason = "unsized coercion is an unstable feature for non-std types"
|
||||||
|
)]
|
||||||
|
// SAFETY:
|
||||||
|
// - Coercion from `T` to `dyn Reflect` is valid as `T: Reflect + 'static`
|
||||||
|
// - `Arc::from_raw` receives a valid pointer from a previous call to `Arc::into_raw`
|
||||||
|
let arc = unsafe { Arc::from_raw(Arc::into_raw(arc) as *const dyn Reflect) };
|
||||||
|
|
||||||
|
self.default = Some(arc);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +127,9 @@ impl_reflect_opaque!(::core::time::Duration(
|
|||||||
Default
|
Default
|
||||||
));
|
));
|
||||||
#[cfg(any(target_arch = "wasm32", feature = "std"))]
|
#[cfg(any(target_arch = "wasm32", feature = "std"))]
|
||||||
impl_reflect_opaque!(::bevy_utils::Instant(Debug, Hash, PartialEq));
|
impl_reflect_opaque!(::bevy_platform_support::time::Instant(
|
||||||
|
Debug, Hash, PartialEq
|
||||||
|
));
|
||||||
impl_reflect_opaque!(::core::num::NonZeroI128(
|
impl_reflect_opaque!(::core::num::NonZeroI128(
|
||||||
Debug,
|
Debug,
|
||||||
Hash,
|
Hash,
|
||||||
@ -214,6 +216,11 @@ impl_reflect_opaque!(::core::num::NonZeroI8(
|
|||||||
));
|
));
|
||||||
impl_reflect_opaque!(::core::num::Wrapping<T: Clone + Send + Sync>());
|
impl_reflect_opaque!(::core::num::Wrapping<T: Clone + Send + Sync>());
|
||||||
impl_reflect_opaque!(::core::num::Saturating<T: Clone + Send + Sync>());
|
impl_reflect_opaque!(::core::num::Saturating<T: Clone + Send + Sync>());
|
||||||
|
impl_reflect_opaque!(::bevy_platform_support::sync::Arc<T: Send + Sync + ?Sized>);
|
||||||
|
|
||||||
|
// We check despite `portable-atomic` being enabled, if the standard library `Arc` is
|
||||||
|
// also available, and implement Reflect for it.
|
||||||
|
#[cfg(all(feature = "portable-atomic", target_has_atomic = "ptr"))]
|
||||||
impl_reflect_opaque!(::alloc::sync::Arc<T: Send + Sync + ?Sized>);
|
impl_reflect_opaque!(::alloc::sync::Arc<T: Send + Sync + ?Sized>);
|
||||||
|
|
||||||
// `Serialize` and `Deserialize` only for platforms supported by serde:
|
// `Serialize` and `Deserialize` only for platforms supported by serde:
|
||||||
@ -2432,7 +2439,8 @@ mod tests {
|
|||||||
TypeInfo, TypeRegistry, Typed, VariantInfo, VariantType,
|
TypeInfo, TypeRegistry, Typed, VariantInfo, VariantType,
|
||||||
};
|
};
|
||||||
use alloc::{collections::BTreeMap, string::String, vec};
|
use alloc::{collections::BTreeMap, string::String, vec};
|
||||||
use bevy_utils::{HashMap, Instant};
|
use bevy_platform_support::time::Instant;
|
||||||
|
use bevy_utils::HashMap;
|
||||||
use core::{
|
use core::{
|
||||||
f32::consts::{PI, TAU},
|
f32::consts::{PI, TAU},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
|
@ -189,7 +189,8 @@ mod tests {
|
|||||||
use crate::serde::{DeserializeWithRegistry, ReflectDeserializeWithRegistry};
|
use crate::serde::{DeserializeWithRegistry, ReflectDeserializeWithRegistry};
|
||||||
use crate::serde::{ReflectSerializeWithRegistry, SerializeWithRegistry};
|
use crate::serde::{ReflectSerializeWithRegistry, SerializeWithRegistry};
|
||||||
use crate::{ReflectFromReflect, TypePath};
|
use crate::{ReflectFromReflect, TypePath};
|
||||||
use alloc::{format, string::String, sync::Arc, vec, vec::Vec};
|
use alloc::{format, string::String, vec, vec::Vec};
|
||||||
|
use bevy_platform_support::sync::Arc;
|
||||||
use bevy_reflect_derive::reflect_trait;
|
use bevy_reflect_derive::reflect_trait;
|
||||||
use core::any::TypeId;
|
use core::any::TypeId;
|
||||||
use core::fmt::{Debug, Formatter};
|
use core::fmt::{Debug, Formatter};
|
||||||
@ -336,6 +337,22 @@ mod tests {
|
|||||||
registry
|
registry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_arc_dyn_enemy<T: Enemy>(enemy: T) -> Arc<dyn Enemy> {
|
||||||
|
let arc = Arc::new(enemy);
|
||||||
|
|
||||||
|
#[cfg(feature = "portable-atomic")]
|
||||||
|
#[expect(
|
||||||
|
unsafe_code,
|
||||||
|
reason = "unsized coercion is an unstable feature for non-std types"
|
||||||
|
)]
|
||||||
|
// SAFETY:
|
||||||
|
// - Coercion from `T` to `dyn Enemy` is valid as `T: Enemy + 'static`
|
||||||
|
// - `Arc::from_raw` receives a valid pointer from a previous call to `Arc::into_raw`
|
||||||
|
let arc = unsafe { Arc::from_raw(Arc::into_raw(arc) as *const dyn Enemy) };
|
||||||
|
|
||||||
|
arc
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_serialize_with_serialize_with_registry() {
|
fn should_serialize_with_serialize_with_registry() {
|
||||||
let registry = create_registry();
|
let registry = create_registry();
|
||||||
@ -343,8 +360,8 @@ mod tests {
|
|||||||
let level = Level {
|
let level = Level {
|
||||||
name: String::from("Level 1"),
|
name: String::from("Level 1"),
|
||||||
enemies: EnemyList(vec![
|
enemies: EnemyList(vec![
|
||||||
Arc::new(Skeleton(10)),
|
create_arc_dyn_enemy(Skeleton(10)),
|
||||||
Arc::new(Zombie {
|
create_arc_dyn_enemy(Zombie {
|
||||||
health: 20,
|
health: 20,
|
||||||
walk_speed: 0.5,
|
walk_speed: 0.5,
|
||||||
}),
|
}),
|
||||||
@ -374,8 +391,8 @@ mod tests {
|
|||||||
let expected = Level {
|
let expected = Level {
|
||||||
name: String::from("Level 1"),
|
name: String::from("Level 1"),
|
||||||
enemies: EnemyList(vec![
|
enemies: EnemyList(vec![
|
||||||
Arc::new(Skeleton(10)),
|
create_arc_dyn_enemy(Skeleton(10)),
|
||||||
Arc::new(Zombie {
|
create_arc_dyn_enemy(Zombie {
|
||||||
health: 20,
|
health: 20,
|
||||||
walk_speed: 0.5,
|
walk_speed: 0.5,
|
||||||
}),
|
}),
|
||||||
@ -388,8 +405,8 @@ mod tests {
|
|||||||
let unexpected = Level {
|
let unexpected = Level {
|
||||||
name: String::from("Level 1"),
|
name: String::from("Level 1"),
|
||||||
enemies: EnemyList(vec![
|
enemies: EnemyList(vec![
|
||||||
Arc::new(Skeleton(20)),
|
create_arc_dyn_enemy(Skeleton(20)),
|
||||||
Arc::new(Zombie {
|
create_arc_dyn_enemy(Zombie {
|
||||||
health: 20,
|
health: 20,
|
||||||
walk_speed: 5.0,
|
walk_speed: 5.0,
|
||||||
}),
|
}),
|
||||||
|
@ -6,7 +6,8 @@ use crate::{
|
|||||||
ApplyError, Generics, NamedField, PartialReflect, Reflect, ReflectKind, ReflectMut,
|
ApplyError, Generics, NamedField, PartialReflect, Reflect, ReflectKind, ReflectMut,
|
||||||
ReflectOwned, ReflectRef, Type, TypeInfo, TypePath,
|
ReflectOwned, ReflectRef, Type, TypeInfo, TypePath,
|
||||||
};
|
};
|
||||||
use alloc::{borrow::Cow, boxed::Box, sync::Arc, vec::Vec};
|
use alloc::{borrow::Cow, boxed::Box, vec::Vec};
|
||||||
|
use bevy_platform_support::sync::Arc;
|
||||||
use bevy_reflect_derive::impl_type_path;
|
use bevy_reflect_derive::impl_type_path;
|
||||||
use bevy_utils::HashMap;
|
use bevy_utils::HashMap;
|
||||||
use core::{
|
use core::{
|
||||||
|
@ -8,7 +8,8 @@ use crate::{
|
|||||||
ApplyError, DynamicTuple, Generics, PartialReflect, Reflect, ReflectKind, ReflectMut,
|
ApplyError, DynamicTuple, Generics, PartialReflect, Reflect, ReflectKind, ReflectMut,
|
||||||
ReflectOwned, ReflectRef, Tuple, Type, TypeInfo, TypePath, UnnamedField,
|
ReflectOwned, ReflectRef, Tuple, Type, TypeInfo, TypePath, UnnamedField,
|
||||||
};
|
};
|
||||||
use alloc::{boxed::Box, sync::Arc, vec::Vec};
|
use alloc::{boxed::Box, vec::Vec};
|
||||||
|
use bevy_platform_support::sync::Arc;
|
||||||
use core::{
|
use core::{
|
||||||
fmt::{Debug, Formatter},
|
fmt::{Debug, Formatter},
|
||||||
slice::Iter,
|
slice::Iter,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{serde::Serializable, FromReflect, Reflect, TypeInfo, TypePath, Typed};
|
use crate::{serde::Serializable, FromReflect, Reflect, TypeInfo, TypePath, Typed};
|
||||||
use alloc::sync::Arc;
|
|
||||||
use alloc::{boxed::Box, string::String};
|
use alloc::{boxed::Box, string::String};
|
||||||
|
use bevy_platform_support::sync::Arc;
|
||||||
use bevy_ptr::{Ptr, PtrMut};
|
use bevy_ptr::{Ptr, PtrMut};
|
||||||
use bevy_utils::{HashMap, HashSet, TypeIdMap};
|
use bevy_utils::{HashMap, HashSet, TypeIdMap};
|
||||||
use core::{
|
use core::{
|
||||||
|
@ -56,6 +56,9 @@ bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev" }
|
|||||||
bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev" }
|
bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev" }
|
||||||
bevy_image = { path = "../bevy_image", version = "0.16.0-dev" }
|
bevy_image = { path = "../bevy_image", version = "0.16.0-dev" }
|
||||||
bevy_mesh = { path = "../bevy_mesh", version = "0.16.0-dev" }
|
bevy_mesh = { path = "../bevy_mesh", version = "0.16.0-dev" }
|
||||||
|
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [
|
||||||
|
"std",
|
||||||
|
] }
|
||||||
|
|
||||||
# rendering
|
# rendering
|
||||||
image = { version = "0.25.2", default-features = false }
|
image = { version = "0.25.2", default-features = false }
|
||||||
|
@ -7,7 +7,7 @@ use std::thread::{self, ThreadId};
|
|||||||
|
|
||||||
use bevy_diagnostic::{Diagnostic, DiagnosticMeasurement, DiagnosticPath, DiagnosticsStore};
|
use bevy_diagnostic::{Diagnostic, DiagnosticMeasurement, DiagnosticPath, DiagnosticsStore};
|
||||||
use bevy_ecs::system::{Res, ResMut, Resource};
|
use bevy_ecs::system::{Res, ResMut, Resource};
|
||||||
use bevy_utils::Instant;
|
use bevy_platform_support::time::Instant;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use wgpu::{
|
use wgpu::{
|
||||||
Buffer, BufferDescriptor, BufferUsages, CommandEncoder, ComputePass, Features, MapMode,
|
Buffer, BufferDescriptor, BufferUsages, CommandEncoder, ComputePass, Features, MapMode,
|
||||||
|
@ -18,8 +18,8 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use bevy_ecs::{prelude::*, system::SystemState};
|
use bevy_ecs::{prelude::*, system::SystemState};
|
||||||
|
use bevy_platform_support::time::Instant;
|
||||||
use bevy_time::TimeSender;
|
use bevy_time::TimeSender;
|
||||||
use bevy_utils::Instant;
|
|
||||||
use wgpu::{
|
use wgpu::{
|
||||||
Adapter, AdapterInfo, CommandBuffer, CommandEncoder, DeviceType, Instance, Queue,
|
Adapter, AdapterInfo, CommandBuffer, CommandEncoder, DeviceType, Instance, Queue,
|
||||||
RequestAdapterOptions,
|
RequestAdapterOptions,
|
||||||
|
@ -36,6 +36,7 @@ critical-section = [
|
|||||||
"bevy_ecs/critical-section",
|
"bevy_ecs/critical-section",
|
||||||
"bevy_utils/critical-section",
|
"bevy_utils/critical-section",
|
||||||
"bevy_app?/critical-section",
|
"bevy_app?/critical-section",
|
||||||
|
"bevy_reflect?/critical-section",
|
||||||
]
|
]
|
||||||
|
|
||||||
## `portable-atomic` provides additional platform support for atomic types and
|
## `portable-atomic` provides additional platform support for atomic types and
|
||||||
@ -44,6 +45,7 @@ portable-atomic = [
|
|||||||
"bevy_ecs/portable-atomic",
|
"bevy_ecs/portable-atomic",
|
||||||
"bevy_utils/portable-atomic",
|
"bevy_utils/portable-atomic",
|
||||||
"bevy_app?/portable-atomic",
|
"bevy_app?/portable-atomic",
|
||||||
|
"bevy_reflect?/portable-atomic",
|
||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -15,25 +15,27 @@ std = [
|
|||||||
"async-task/std",
|
"async-task/std",
|
||||||
"spin/std",
|
"spin/std",
|
||||||
"edge-executor?/std",
|
"edge-executor?/std",
|
||||||
"portable-atomic-util?/std",
|
"bevy_platform_support/std",
|
||||||
]
|
]
|
||||||
multi_threaded = ["std", "dep:async-channel", "dep:concurrent-queue"]
|
multi_threaded = ["std", "dep:async-channel", "dep:concurrent-queue"]
|
||||||
async_executor = ["std", "dep:async-executor"]
|
async_executor = ["std", "dep:async-executor"]
|
||||||
edge_executor = ["dep:edge-executor"]
|
edge_executor = ["dep:edge-executor"]
|
||||||
critical-section = [
|
critical-section = [
|
||||||
"dep:critical-section",
|
"bevy_platform_support/critical-section",
|
||||||
"edge-executor?/critical-section",
|
"edge-executor?/critical-section",
|
||||||
"portable-atomic?/critical-section",
|
|
||||||
]
|
]
|
||||||
portable-atomic = [
|
portable-atomic = [
|
||||||
"dep:portable-atomic",
|
"bevy_platform_support/portable-atomic",
|
||||||
"dep:portable-atomic-util",
|
|
||||||
"edge-executor?/portable-atomic",
|
"edge-executor?/portable-atomic",
|
||||||
"async-task/portable-atomic",
|
"async-task/portable-atomic",
|
||||||
"spin/portable_atomic",
|
"spin/portable_atomic",
|
||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [
|
||||||
|
"alloc",
|
||||||
|
] }
|
||||||
|
|
||||||
futures-lite = { version = "2.0.1", default-features = false, features = [
|
futures-lite = { version = "2.0.1", default-features = false, features = [
|
||||||
"alloc",
|
"alloc",
|
||||||
] }
|
] }
|
||||||
@ -53,13 +55,6 @@ edge-executor = { version = "0.4.1", default-features = false, optional = true }
|
|||||||
async-channel = { version = "2.3.0", optional = true }
|
async-channel = { version = "2.3.0", optional = true }
|
||||||
async-io = { version = "2.0.0", optional = true }
|
async-io = { version = "2.0.0", optional = true }
|
||||||
concurrent-queue = { version = "2.0.0", optional = true }
|
concurrent-queue = { version = "2.0.0", optional = true }
|
||||||
critical-section = { version = "1.2.0", optional = true }
|
|
||||||
portable-atomic = { version = "1", default-features = false, features = [
|
|
||||||
"fallback",
|
|
||||||
], optional = true }
|
|
||||||
portable-atomic-util = { version = "0.2.4", features = [
|
|
||||||
"alloc",
|
|
||||||
], optional = true }
|
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
wasm-bindgen-futures = "0.4"
|
wasm-bindgen-futures = "0.4"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use alloc::{string::String, vec::Vec};
|
use alloc::{string::String, vec::Vec};
|
||||||
|
use bevy_platform_support::sync::Arc;
|
||||||
use core::{cell::RefCell, future::Future, marker::PhantomData, mem};
|
use core::{cell::RefCell, future::Future, marker::PhantomData, mem};
|
||||||
|
|
||||||
use crate::Task;
|
use crate::Task;
|
||||||
@ -6,12 +7,6 @@ use crate::Task;
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::thread_local;
|
use std::thread_local;
|
||||||
|
|
||||||
#[cfg(feature = "portable-atomic")]
|
|
||||||
use portable_atomic_util::Arc;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "portable-atomic"))]
|
|
||||||
use alloc::sync::Arc;
|
|
||||||
|
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
feature = "std",
|
feature = "std",
|
||||||
any(feature = "async_executor", feature = "edge_executor")
|
any(feature = "async_executor", feature = "edge_executor")
|
||||||
|
@ -6,15 +6,10 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::executor::FallibleTask;
|
use crate::executor::FallibleTask;
|
||||||
|
use bevy_platform_support::sync::Arc;
|
||||||
use concurrent_queue::ConcurrentQueue;
|
use concurrent_queue::ConcurrentQueue;
|
||||||
use futures_lite::FutureExt;
|
use futures_lite::FutureExt;
|
||||||
|
|
||||||
#[cfg(feature = "portable-atomic")]
|
|
||||||
use portable_atomic_util::Arc;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "portable-atomic"))]
|
|
||||||
use alloc::sync::Arc;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
block_on,
|
block_on,
|
||||||
thread_executor::{ThreadExecutor, ThreadExecutorTicker},
|
thread_executor::{ThreadExecutor, ThreadExecutorTicker},
|
||||||
|
@ -21,7 +21,9 @@ bevy_ecs = { path = "../bevy_ecs", version = "0.16.0-dev", features = [
|
|||||||
bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", features = [
|
bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", features = [
|
||||||
"bevy",
|
"bevy",
|
||||||
], optional = true }
|
], optional = true }
|
||||||
bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev" }
|
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [
|
||||||
|
"std",
|
||||||
|
] }
|
||||||
|
|
||||||
# other
|
# other
|
||||||
crossbeam-channel = "0.5.0"
|
crossbeam-channel = "0.5.0"
|
||||||
|
@ -35,7 +35,7 @@ use bevy_ecs::{
|
|||||||
event::{event_update_system, signal_event_update_system, EventRegistry, ShouldUpdateEvents},
|
event::{event_update_system, signal_event_update_system, EventRegistry, ShouldUpdateEvents},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
use bevy_utils::Instant;
|
use bevy_platform_support::time::Instant;
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
pub use crossbeam_channel::TrySendError;
|
pub use crossbeam_channel::TrySendError;
|
||||||
use crossbeam_channel::{Receiver, Sender};
|
use crossbeam_channel::{Receiver, Sender};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
use bevy_platform_support::time::Instant;
|
||||||
#[cfg(feature = "bevy_reflect")]
|
#[cfg(feature = "bevy_reflect")]
|
||||||
use bevy_reflect::Reflect;
|
use bevy_reflect::Reflect;
|
||||||
use bevy_utils::Instant;
|
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
|
|
||||||
use crate::time::Time;
|
use crate::time::Time;
|
||||||
|
@ -160,7 +160,7 @@ use {
|
|||||||
/// ```
|
/// ```
|
||||||
/// # use bevy_ecs::prelude::*;
|
/// # use bevy_ecs::prelude::*;
|
||||||
/// # use bevy_time::prelude::*;
|
/// # use bevy_time::prelude::*;
|
||||||
/// # use bevy_utils::Instant;
|
/// # use bevy_platform_support::time::Instant;
|
||||||
/// #
|
/// #
|
||||||
/// #[derive(Debug)]
|
/// #[derive(Debug)]
|
||||||
/// struct Custom {
|
/// struct Custom {
|
||||||
|
@ -21,37 +21,32 @@ serde = ["hashbrown/serde"]
|
|||||||
## Allows access to the `std` crate. Enabling this feature will prevent compilation
|
## Allows access to the `std` crate. Enabling this feature will prevent compilation
|
||||||
## on `no_std` targets, but provides access to certain additional features on
|
## on `no_std` targets, but provides access to certain additional features on
|
||||||
## supported platforms.
|
## supported platforms.
|
||||||
std = ["alloc", "foldhash/std", "dep:thread_local"]
|
std = ["alloc", "bevy_platform_support/std", "foldhash/std", "dep:thread_local"]
|
||||||
|
|
||||||
## Allows access to the `alloc` crate.
|
## Allows access to the `alloc` crate.
|
||||||
alloc = ["hashbrown"]
|
alloc = ["bevy_platform_support/alloc", "hashbrown"]
|
||||||
|
|
||||||
## `critical-section` provides the building blocks for synchronization primitives
|
## `critical-section` provides the building blocks for synchronization primitives
|
||||||
## on all platforms, including `no_std`.
|
## on all platforms, including `no_std`.
|
||||||
critical-section = ["portable-atomic?/critical-section"]
|
critical-section = ["bevy_platform_support/critical-section"]
|
||||||
|
|
||||||
## `portable-atomic` provides additional platform support for atomic types and
|
## `portable-atomic` provides additional platform support for atomic types and
|
||||||
## operations, even on targets without native support.
|
## operations, even on targets without native support.
|
||||||
portable-atomic = ["dep:portable-atomic"]
|
portable-atomic = ["bevy_platform_support/portable-atomic"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false }
|
||||||
|
|
||||||
foldhash = { version = "0.1.3", default-features = false }
|
foldhash = { version = "0.1.3", default-features = false }
|
||||||
hashbrown = { version = "0.15.1", features = [
|
hashbrown = { version = "0.15.1", features = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"raw-entry",
|
"raw-entry",
|
||||||
], optional = true, default-features = false }
|
], optional = true, default-features = false }
|
||||||
thread_local = { version = "1.0", optional = true }
|
thread_local = { version = "1.0", optional = true }
|
||||||
portable-atomic = { version = "1", default-features = false, features = [
|
|
||||||
"fallback",
|
|
||||||
], optional = true }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
static_assertions = "1.1.0"
|
static_assertions = "1.1.0"
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
|
||||||
getrandom = { version = "0.2.0", features = ["js"] }
|
|
||||||
web-time = { version = "1.1" }
|
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@ mod default;
|
|||||||
mod once;
|
mod once;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
mod parallel_queue;
|
mod parallel_queue;
|
||||||
mod time;
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use once::OnceFlag;
|
pub use once::OnceFlag;
|
||||||
@ -59,8 +58,6 @@ pub use foldhash::fast::{FixedState, FoldHasher as DefaultHasher, RandomState};
|
|||||||
pub use hashbrown;
|
pub use hashbrown;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use parallel_queue::*;
|
pub use parallel_queue::*;
|
||||||
#[cfg(any(feature = "std", target_arch = "wasm32"))]
|
|
||||||
pub use time::*;
|
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
use core::any::TypeId;
|
use core::any::TypeId;
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
#[cfg(feature = "portable-atomic")]
|
use bevy_platform_support::sync::atomic::{AtomicBool, Ordering};
|
||||||
use portable_atomic::{AtomicBool, Ordering};
|
|
||||||
|
|
||||||
#[cfg(not(feature = "portable-atomic"))]
|
|
||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
|
||||||
|
|
||||||
/// Wrapper around an [`AtomicBool`], abstracting the backing implementation and
|
/// Wrapper around an [`AtomicBool`], abstracting the backing implementation and
|
||||||
/// ordering considerations.
|
/// ordering considerations.
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
#[cfg(target_arch = "wasm32")]
|
|
||||||
pub use web_time::Instant;
|
|
||||||
|
|
||||||
#[cfg(all(not(target_arch = "wasm32"), feature = "std"))]
|
|
||||||
pub use std::time::Instant;
|
|
@ -34,6 +34,9 @@ bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev" }
|
|||||||
bevy_window = { path = "../bevy_window", version = "0.16.0-dev" }
|
bevy_window = { path = "../bevy_window", version = "0.16.0-dev" }
|
||||||
bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev" }
|
bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev" }
|
||||||
bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev" }
|
bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev" }
|
||||||
|
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [
|
||||||
|
"std",
|
||||||
|
] }
|
||||||
|
|
||||||
# bevy optional
|
# bevy optional
|
||||||
bevy_asset = { path = "../bevy_asset", version = "0.16.0-dev", optional = true }
|
bevy_asset = { path = "../bevy_asset", version = "0.16.0-dev", optional = true }
|
||||||
|
@ -20,11 +20,11 @@ use bevy_log::{error, trace, warn};
|
|||||||
#[cfg(feature = "custom_cursor")]
|
#[cfg(feature = "custom_cursor")]
|
||||||
use bevy_math::URect;
|
use bevy_math::URect;
|
||||||
use bevy_math::{ivec2, DVec2, Vec2};
|
use bevy_math::{ivec2, DVec2, Vec2};
|
||||||
|
use bevy_platform_support::time::Instant;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use bevy_tasks::tick_global_task_pools_on_main_thread;
|
use bevy_tasks::tick_global_task_pools_on_main_thread;
|
||||||
#[cfg(feature = "custom_cursor")]
|
#[cfg(feature = "custom_cursor")]
|
||||||
use bevy_utils::HashMap;
|
use bevy_utils::HashMap;
|
||||||
use bevy_utils::Instant;
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use winit::platform::web::EventLoopExtWebSys;
|
use winit::platform::web::EventLoopExtWebSys;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# if crate A depends on crate B, B must come before A in this list
|
# if crate A depends on crate B, B must come before A in this list
|
||||||
crates=(
|
crates=(
|
||||||
|
bevy_platform_support
|
||||||
bevy_utils
|
bevy_utils
|
||||||
bevy_ptr
|
bevy_ptr
|
||||||
bevy_macro_utils
|
bevy_macro_utils
|
||||||
|
Loading…
Reference in New Issue
Block a user