format comments (#1612)

Uses the new unstable comment formatting features added to rustfmt.toml.
This commit is contained in:
Carter Anderson 2021-03-11 00:27:30 +00:00
parent be1c317d4e
commit b17f8a4bce
125 changed files with 894 additions and 599 deletions

View file

@ -9,24 +9,25 @@ use bevy_utils::tracing::info_span;
#[allow(clippy::needless_doctest_main)]
/// Containers of app logic and data
///
/// App store the ECS World, Resources, Schedule, and Executor. They also store the "run" function of the App, which
/// by default executes the App schedule once. Apps are constructed using the builder pattern.
/// App store the ECS World, Resources, Schedule, and Executor. They also store the "run" function
/// of the App, which by default executes the App schedule once. Apps are constructed using the
/// builder pattern.
///
/// ## Example
/// Here is a simple "Hello World" Bevy app:
/// ```
///# use bevy_app::prelude::*;
///# use bevy_ecs::prelude::*;
/// # use bevy_app::prelude::*;
/// # use bevy_ecs::prelude::*;
///
///fn main() {
/// fn main() {
/// App::build()
/// .add_system(hello_world_system.system())
/// .run();
///}
/// }
///
///fn hello_world_system() {
/// fn hello_world_system() {
/// println!("hello world");
///}
/// }
/// ```
pub struct App {
pub world: World,

View file

@ -234,7 +234,8 @@ impl AppBuilder {
.add_system_to_stage(CoreStage::First, Events::<T>::update_system.system())
}
/// Inserts a resource to the current [App] and overwrites any resource previously added of the same type.
/// Inserts a resource to the current [App] and overwrites any resource previously added of the
/// same type.
pub fn insert_resource<T>(&mut self, resource: T) -> &mut Self
where
T: Component,
@ -255,9 +256,9 @@ impl AppBuilder {
where
R: FromWorld + Send + Sync + 'static,
{
// PERF: We could avoid double hashing here, since the `from_resources` call is guaranteed not to
// modify the map. However, we would need to be borrowing resources both mutably and immutably,
// so we would need to be extremely certain this is correct
// PERF: We could avoid double hashing here, since the `from_resources` call is guaranteed
// not to modify the map. However, we would need to be borrowing resources both
// mutably and immutably, so we would need to be extremely certain this is correct
if !self.world_mut().contains_resource::<R>() {
let resource = R::from_world(self.world_mut());
self.insert_resource(resource);

View file

@ -55,10 +55,12 @@ enum State {
B,
}
/// An event collection that represents the events that occurred within the last two [Events::update] calls. Events can be cheaply read using
/// an [EventReader]. This collection is meant to be paired with a system that calls [Events::update] exactly once per update/frame. [Events::update_system]
/// is a system that does this. [EventReader]s are expected to read events from this collection at least once per update/frame. If events are not handled
/// within one frame/update, they will be dropped.
/// An event collection that represents the events that occurred within the last two
/// [Events::update] calls. Events can be cheaply read using an [EventReader]. This collection is
/// meant to be paired with a system that calls [Events::update] exactly once per update/frame.
/// [Events::update_system] is a system that does this. [EventReader]s are expected to read events
/// from this collection at least once per update/frame. If events are not handled within one
/// frame/update, they will be dropped.
///
/// # Example
/// ```
@ -89,14 +91,16 @@ enum State {
///
/// # Details
///
/// [Events] is implemented using a double buffer. Each call to [Events::update] swaps buffers and clears out the oldest buffer.
/// [EventReader]s that read at least once per update will never drop events. [EventReader]s that read once within two updates might
/// still receive some events. [EventReader]s that read after two updates are guaranteed to drop all events that occurred before those updates.
/// [Events] is implemented using a double buffer. Each call to [Events::update] swaps buffers and
/// clears out the oldest buffer. [EventReader]s that read at least once per update will never drop
/// events. [EventReader]s that read once within two updates might still receive some events.
/// [EventReader]s that read after two updates are guaranteed to drop all events that occurred
/// before those updates.
///
/// The buffers in [Events] will grow indefinitely if [Events::update] is never called.
///
/// An alternative call pattern would be to call [Events::update] manually across frames to control when events are cleared. However
/// this complicates consumption
/// An alternative call pattern would be to call [Events::update] manually across frames to control
/// when events are cleared. However this complicates consumption
#[derive(Debug)]
pub struct Events<T> {
events_a: Vec<EventInstance<T>>,
@ -180,7 +184,8 @@ impl<T> ManualEventReader<T> {
}
}
/// Like [`iter_with_id`](EventReader::iter_with_id) except not emitting any traces for read messages.
/// Like [`iter_with_id`](EventReader::iter_with_id) except not emitting any traces for read
/// messages.
fn internal_event_reader<'a, T>(
last_event_count: &mut usize,
events: &'a Events<T>,
@ -232,7 +237,8 @@ fn internal_event_reader<'a, T>(
impl<'a, T: Component> EventReader<'a, T> {
/// Iterates over the events this EventReader has not seen yet. This updates the EventReader's
/// event counter, which means subsequent event reads will not include events that happened before now.
/// event counter, which means subsequent event reads will not include events that happened
/// before now.
pub fn iter(&mut self) -> impl DoubleEndedIterator<Item = &T> {
self.iter_with_id().map(|(event, _id)| event)
}
@ -247,7 +253,8 @@ impl<'a, T: Component> EventReader<'a, T> {
}
impl<T: Component> Events<T> {
/// "Sends" an `event` by writing it to the current event buffer. [EventReader]s can then read the event.
/// "Sends" an `event` by writing it to the current event buffer. [EventReader]s can then read
/// the event.
pub fn send(&mut self, event: T) {
let event_id = EventId {
id: self.event_count,
@ -273,7 +280,8 @@ impl<T: Component> Events<T> {
}
}
/// Gets a new [ManualEventReader]. This will ignore all events already in the event buffers. It will read all future events.
/// Gets a new [ManualEventReader]. This will ignore all events already in the event buffers. It
/// will read all future events.
pub fn get_reader_current(&self) -> ManualEventReader<T> {
ManualEventReader {
last_event_count: self.event_count,
@ -281,7 +289,8 @@ impl<T: Component> Events<T> {
}
}
/// Swaps the event buffers and clears the oldest event buffer. In general, this should be called once per frame/update.
/// Swaps the event buffers and clears the oldest event buffer. In general, this should be
/// called once per frame/update.
pub fn update(&mut self) {
match self.state {
State::A => {
@ -335,10 +344,11 @@ impl<T: Component> Events<T> {
}
/// Iterates over events that happened since the last "update" call.
/// WARNING: You probably don't want to use this call. In most cases you should use an `EventReader`. You should only use
/// this if you know you only need to consume events between the last `update()` call and your call to `iter_current_update_events`.
/// If events happen outside that window, they will not be handled. For example, any events that happen after this call and before
/// the next `update()` call will be dropped.
/// WARNING: You probably don't want to use this call. In most cases you should use an
/// `EventReader`. You should only use this if you know you only need to consume events
/// between the last `update()` call and your call to `iter_current_update_events`.
/// If events happen outside that window, they will not be handled. For example, any events that
/// happen after this call and before the next `update()` call will be dropped.
pub fn iter_current_update_events(&self) -> impl DoubleEndedIterator<Item = &T> {
match self.state {
State::A => self.events_a.iter().map(map_instance_event),
@ -363,7 +373,8 @@ mod tests {
let event_1 = TestEvent { i: 1 };
let event_2 = TestEvent { i: 2 };
// this reader will miss event_0 and event_1 because it wont read them over the course of two updates
// this reader will miss event_0 and event_1 because it wont read them over the course of
// two updates
let mut reader_missed = events.get_reader();
let mut reader_a = events.get_reader();

View file

@ -33,7 +33,8 @@ pub enum CoreStage {
First,
/// Name of app stage responsible for performing setup before an update. Runs before UPDATE.
PreUpdate,
/// Name of app stage responsible for doing most app logic. Systems should be registered here by default.
/// Name of app stage responsible for doing most app logic. Systems should be registered here
/// by default.
Update,
/// Name of app stage responsible for processing the results of UPDATE. Runs after UPDATE.
PostUpdate,

View file

@ -3,7 +3,8 @@ use std::any::Any;
/// A collection of Bevy App logic and configuration
///
/// Plugins use [AppBuilder] to configure an [App](crate::App). When an [App](crate::App) registers a plugin, the plugin's [Plugin::build] function is run.
/// Plugins use [AppBuilder] to configure an [App](crate::App). When an [App](crate::App) registers
/// a plugin, the plugin's [Plugin::build] function is run.
pub trait Plugin: Any + Send + Sync {
fn build(&self, app: &mut AppBuilder);
fn name(&self) -> &str {

View file

@ -41,7 +41,8 @@ impl ScheduleRunnerSettings {
}
}
/// Configures an App to run its [Schedule](bevy_ecs::schedule::Schedule) according to a given [RunMode]
/// Configures an App to run its [Schedule](bevy_ecs::schedule::Schedule) according to a given
/// [RunMode]
#[derive(Default)]
pub struct ScheduleRunnerPlugin {}

View file

@ -226,7 +226,8 @@ impl AssetServer {
let asset_loader = self.get_path_asset_loader(asset_path.path())?;
let asset_path_id: AssetPathId = asset_path.get_id();
// load metadata and update source info. this is done in a scope to ensure we release the locks before loading
// load metadata and update source info. this is done in a scope to ensure we release the
// locks before loading
let version = {
let mut asset_sources = self.server.asset_sources.write();
let source_info = match asset_sources.entry(asset_path_id.source_path_id()) {
@ -282,7 +283,8 @@ impl AssetServer {
.await
.map_err(AssetServerError::AssetLoaderError)?;
// if version has changed since we loaded and grabbed a lock, return. theres is a newer version being loaded
// if version has changed since we loaded and grabbed a lock, return. theres is a newer
// version being loaded
let mut asset_sources = self.server.asset_sources.write();
let source_info = asset_sources
.get_mut(&asset_path_id.source_path_id())

View file

@ -2,7 +2,8 @@ use crossbeam_channel::Receiver;
use notify::{Event, RecommendedWatcher, RecursiveMode, Result, Watcher};
use std::path::Path;
/// Watches for changes to assets on the filesystem. This is used by the `AssetServer` to reload them
/// Watches for changes to assets on the filesystem. This is used by the `AssetServer` to reload
/// them
pub struct FilesystemWatcher {
pub watcher: RecommendedWatcher,
pub receiver: Receiver<Result<Event>>,

View file

@ -56,7 +56,8 @@ impl HandleId {
/// A handle into a specific Asset of type `T`
///
/// Handles contain a unique id that corresponds to a specific asset in the [Assets](crate::Assets) collection.
/// Handles contain a unique id that corresponds to a specific asset in the [Assets](crate::Assets)
/// collection.
#[derive(Reflect)]
#[reflect(Component)]
pub struct Handle<T>
@ -147,7 +148,8 @@ impl<T: Asset> Drop for Handle<T> {
fn drop(&mut self) {
match self.handle_type {
HandleType::Strong(ref sender) => {
// ignore send errors because this means the channel is shut down / the game has stopped
// ignore send errors because this means the channel is shut down / the game has
// stopped
let _ = sender.send(RefChange::Decrement(self.id));
}
HandleType::Weak => {}
@ -233,7 +235,8 @@ unsafe impl<T: Asset> Sync for Handle<T> {}
/// A non-generic version of [Handle]
///
/// This allows handles to be mingled in a cross asset context. For example, storing `Handle<A>` and `Handle<B>` in the same `HashSet<HandleUntyped>`.
/// This allows handles to be mingled in a cross asset context. For example, storing `Handle<A>` and
/// `Handle<B>` in the same `HashSet<HandleUntyped>`.
#[derive(Debug)]
pub struct HandleUntyped {
pub id: HandleId,
@ -299,7 +302,8 @@ impl Drop for HandleUntyped {
fn drop(&mut self) {
match self.handle_type {
HandleType::Strong(ref sender) => {
// ignore send errors because this means the channel is shut down / the game has stopped
// ignore send errors because this means the channel is shut down / the game has
// stopped
let _ = sender.send(RefChange::Decrement(self.id));
}
HandleType::Weak => {}

View file

@ -39,8 +39,8 @@ pub enum AssetStage {
AssetEvents,
}
/// Adds support for Assets to an App. Assets are typed collections with change tracking, which are added as App Resources.
/// Examples of assets: textures, sounds, 3d models, maps, scenes
/// Adds support for Assets to an App. Assets are typed collections with change tracking, which are
/// added as App Resources. Examples of assets: textures, sounds, 3d models, maps, scenes
#[derive(Default)]
pub struct AssetPlugin;

View file

@ -101,8 +101,8 @@ unsafe impl Byteable for isize {}
unsafe impl Byteable for f32 {}
unsafe impl Byteable for f64 {}
unsafe impl Byteable for Vec2 {}
// NOTE: Vec3 actually takes up the size of 4 floats / 16 bytes due to SIMD. This is actually convenient because GLSL
// uniform buffer objects pad Vec3s to be 16 bytes.
// NOTE: Vec3 actually takes up the size of 4 floats / 16 bytes due to SIMD. This is actually
// convenient because GLSL uniform buffer objects pad Vec3s to be 16 bytes.
unsafe impl Byteable for Vec3 {}
unsafe impl Byteable for Vec4 {}

View file

@ -5,9 +5,9 @@ use std::{
ops::Neg,
};
/// A wrapper type that enables ordering floats. This is a work around for the famous "rust float ordering" problem.
/// By using it, you acknowledge that sorting NaN is undefined according to spec. This implementation treats NaN as the
/// "smallest" float.
/// A wrapper type that enables ordering floats. This is a work around for the famous "rust float
/// ordering" problem. By using it, you acknowledge that sorting NaN is undefined according to spec.
/// This implementation treats NaN as the "smallest" float.
#[derive(Debug, Copy, Clone, PartialOrd)]
pub struct FloatOrd(pub f32);

View file

@ -61,7 +61,8 @@ impl Labels {
}
}
/// Maintains a mapping from [Entity](bevy_ecs::prelude::Entity) ids to entity labels and entity labels to [Entities](bevy_ecs::prelude::Entity).
/// Maintains a mapping from [Entity](bevy_ecs::prelude::Entity) ids to entity labels and entity
/// labels to [Entities](bevy_ecs::prelude::Entity).
#[derive(Debug, Default)]
pub struct EntityLabels {
label_entities: HashMap<Cow<'static, str>, Vec<Entity>>,

View file

@ -31,7 +31,8 @@ pub struct CorePlugin;
#[derive(Debug, PartialEq, Eq, Clone, Hash, SystemLabel)]
pub enum CoreSystem {
/// Updates the elapsed time. Any system that interacts with [Time] component should run after this.
/// Updates the elapsed time. Any system that interacts with [Time] component should run after
/// this.
Time,
}
@ -54,7 +55,8 @@ impl Plugin for CorePlugin {
.register_type::<Labels>()
.register_type::<Range<f32>>()
.register_type::<Timer>()
// time system is added as an "exclusive system" to ensure it runs before other systems in CoreStage::First
// time system is added as an "exclusive system" to ensure it runs before other systems
// in CoreStage::First
.add_system_to_stage(
CoreStage::First,
time_system.exclusive_system().label(CoreSystem::Time),

View file

@ -36,9 +36,11 @@ impl TaskPoolThreadAssignmentPolicy {
/// this helper will do nothing.
#[derive(Clone)]
pub struct DefaultTaskPoolOptions {
/// If the number of physical cores is less than min_total_threads, force using min_total_threads
/// If the number of physical cores is less than min_total_threads, force using
/// min_total_threads
pub min_total_threads: usize,
/// If the number of physical cores is grater than max_total_threads, force using max_total_threads
/// If the number of physical cores is grater than max_total_threads, force using
/// max_total_threads
pub max_total_threads: usize,
/// Used to determine number of IO threads to allocate

View file

@ -169,8 +169,8 @@ impl System for FixedTimestep {
}
unsafe fn run_unsafe(&mut self, _input: Self::In, world: &World) -> Self::Out {
// SAFE: this system inherits the internal system's component access and archetype component access,
// which means the caller has ensured running the internal system is safe
// SAFE: this system inherits the internal system's component access and archetype component
// access, which means the caller has ensured running the internal system is safe
self.internal_system.run_unsafe((), world)
}

View file

@ -6,7 +6,8 @@ use bevy_utils::Duration;
/// Tracks elapsed time. Enters the finished state once `duration` is reached.
///
/// Non repeating timers will stop tracking and stay in the finished state until reset.
/// Repeating timers will only be in the finished state on each tick `duration` is reached or exceeded, and can still be reset at any given point.
/// Repeating timers will only be in the finished state on each tick `duration` is reached or
/// exceeded, and can still be reset at any given point.
///
/// Paused timers will not have elapsed time increased.
#[derive(Clone, Debug, Default, Reflect)]

View file

@ -11,8 +11,8 @@ mod shader_defs;
use proc_macro::TokenStream;
/// Derives the FromResources trait. Each field must also implement the FromResources trait or this will fail. FromResources is
/// automatically implemented for types that implement Default.
/// Derives the FromResources trait. Each field must also implement the FromResources trait or this
/// will fail. FromResources is automatically implemented for types that implement Default.
#[proc_macro_derive(FromResources, attributes(as_crate))]
pub fn derive_from_resources(input: TokenStream) -> TokenStream {
resource::derive_from_resources(input)

View file

@ -264,7 +264,8 @@ impl Archetype {
self.table_info.entity_rows.reserve(additional);
}
/// Removes the entity at `index` by swapping it out. Returns the table row the entity is stored in.
/// Removes the entity at `index` by swapping it out. Returns the table row the entity is stored
/// in.
pub(crate) fn swap_remove(&mut self, index: usize) -> ArchetypeSwapRemoveResult {
let is_last = index == self.entities.len() - 1;
self.entities.swap_remove(index);
@ -374,8 +375,8 @@ impl Default for Archetypes {
};
archetypes.get_id_or_insert(TableId::empty(), Vec::new(), Vec::new());
// adds the resource archetype. it is "special" in that it is inaccessible via a "hash", which prevents entities from
// being added to it
// adds the resource archetype. it is "special" in that it is inaccessible via a "hash",
// which prevents entities from being added to it
archetypes.archetypes.push(Archetype::new(
ArchetypeId::resource(),
TableId::empty(),
@ -470,6 +471,7 @@ impl Archetypes {
/// Gets the archetype id matching the given inputs or inserts a new one if it doesn't exist.
/// `table_components` and `sparse_set_components` must be sorted
///
/// # Safety
/// TableId must exist in tables
pub(crate) fn get_id_or_insert(

View file

@ -8,14 +8,15 @@ use crate::{
use bevy_ecs_macros::all_tuples;
use std::{any::TypeId, collections::HashMap};
/// An ordered collection of components, commonly used for spawning entities, and adding and removing components in bulk.
/// An ordered collection of components, commonly used for spawning entities, and adding and
/// removing components in bulk.
///
/// You cannot query for a bundle, only individual components within it.
///
/// Typically, you will simply use `#[derive(Bundle)]` when creating your own `Bundle`.
/// The `Bundle` trait is automatically implemented for tuples of components:
/// `(ComponentA, ComponentB)` is a very convenient shorthand when working with one-off collections of components.
/// Note that both `()` and `(ComponentA, )` are valid tuples.
/// `(ComponentA, ComponentB)` is a very convenient shorthand when working with one-off collections
/// of components. Note that both `()` and `(ComponentA, )` are valid tuples.
///
/// You can nest bundles like so:
/// ```
@ -34,23 +35,29 @@ use std::{any::TypeId, collections::HashMap};
/// z: String,
/// }
/// ```
///
/// # Safety
/// [Bundle::type_info] must return the TypeInfo for each component type in the bundle, in the _exact_
/// order that [Bundle::get_components] is called.
/// [Bundle::from_components] must call `func` exactly once for each [TypeInfo] returned by [Bundle::type_info]
/// [Bundle::type_info] must return the TypeInfo for each component type in the bundle, in the
/// _exact_ order that [Bundle::get_components] is called.
/// [Bundle::from_components] must call `func` exactly once for each [TypeInfo] returned by
/// [Bundle::type_info]
pub unsafe trait Bundle: Send + Sync + 'static {
/// Gets this [Bundle]'s components type info, in the order of this bundle's Components
fn type_info() -> Vec<TypeInfo>;
/// Calls `func`, which should return data for each component in the bundle, in the order of this bundle's Components
/// Calls `func`, which should return data for each component in the bundle, in the order of
/// this bundle's Components
///
/// # Safety
/// Caller must return data for each component in the bundle, in the order of this bundle's Components
/// Caller must return data for each component in the bundle, in the order of this bundle's
/// Components
unsafe fn from_components(func: impl FnMut() -> *mut u8) -> Self
where
Self: Sized;
/// Calls `func` on each value, in the order of this bundle's Components. This will "mem::forget" the bundle
/// fields, so callers are responsible for dropping the fields if that is desirable.
/// Calls `func` on each value, in the order of this bundle's Components. This will
/// "mem::forget" the bundle fields, so callers are responsible for dropping the fields if
/// that is desirable.
fn get_components(self, func: impl FnMut(*mut u8));
}
@ -126,7 +133,8 @@ impl BundleInfo {
bundle_flags: &[ComponentFlags],
bundle: T,
) {
// NOTE: get_components calls this closure on each component in "bundle order". bundle_info.component_ids are also in "bundle order"
// NOTE: get_components calls this closure on each component in "bundle order".
// bundle_info.component_ids are also in "bundle order"
let mut bundle_component = 0;
bundle.get_components(|component_ptr| {
// SAFE: component_id was initialized by get_dynamic_bundle_info

View file

@ -31,7 +31,8 @@ pub struct ComponentInfo {
name: String,
id: ComponentId,
type_id: Option<TypeId>,
// SAFETY: This must remain private. It must only be set to "true" if this component is actually Send + Sync
// SAFETY: This must remain private. It must only be set to "true" if this component is
// actually Send + Sync
is_send_and_sync: bool,
layout: Layout,
drop: unsafe fn(*mut u8),
@ -116,7 +117,8 @@ impl SparseSetIndex for ComponentId {
pub struct ComponentDescriptor {
name: String,
storage_type: StorageType,
// SAFETY: This must remain private. It must only be set to "true" if this component is actually Send + Sync
// SAFETY: This must remain private. It must only be set to "true" if this component is
// actually Send + Sync
is_send_and_sync: bool,
type_id: Option<TypeId>,
layout: Layout,

View file

@ -56,9 +56,9 @@ impl Entity {
self.id
}
/// Returns the generation of this Entity's id. The generation is incremented each time an entity with
/// a given id is despawned. This serves as a "count" of the number of times a given id has been reused
/// (id, generation) pairs uniquely identify a given Entity.
/// Returns the generation of this Entity's id. The generation is incremented each time an
/// entity with a given id is despawned. This serves as a "count" of the number of times a
/// given id has been reused (id, generation) pairs uniquely identify a given Entity.
#[inline]
pub fn generation(self) -> u32 {
self.generation
@ -121,16 +121,16 @@ pub struct Entities {
/// The `pending` and `free_cursor` fields describe three sets of Entity IDs
/// that have been freed or are in the process of being allocated:
///
/// - The `freelist` IDs, previously freed by `free()`. These IDs are available to any
/// of `alloc()`, `reserve_entity()` or `reserve_entities()`. Allocation will
/// always prefer these over brand new IDs.
/// - The `freelist` IDs, previously freed by `free()`. These IDs are available to any of
/// `alloc()`, `reserve_entity()` or `reserve_entities()`. Allocation will always prefer
/// these over brand new IDs.
///
/// - The `reserved` list of IDs that were once in the freelist, but got
/// reserved by `reserve_entities` or `reserve_entity()`. They are now waiting
/// for `flush()` to make them fully allocated.
/// - The `reserved` list of IDs that were once in the freelist, but got reserved by
/// `reserve_entities` or `reserve_entity()`. They are now waiting for `flush()` to make them
/// fully allocated.
///
/// - The count of new IDs that do not yet exist in `self.meta()`, but which
/// we have handed out and reserved. `flush()` will allocate room for them in `self.meta()`.
/// - The count of new IDs that do not yet exist in `self.meta()`, but which we have handed out
/// and reserved. `flush()` will allocate room for them in `self.meta()`.
///
/// The contents of `pending` look like this:
///
@ -257,7 +257,8 @@ impl Entities {
/// Allocate a specific entity ID, overwriting its generation
///
/// Returns the location of the entity currently using the given ID, if any. Location should be written immediately.
/// Returns the location of the entity currently using the given ID, if any. Location should be
/// written immediately.
pub fn alloc_at(&mut self, entity: Entity) -> Option<EntityLocation> {
self.verify_flushed();

View file

@ -171,7 +171,8 @@ impl<T: SparseSetIndex> FilteredAccessSet<T> {
}
pub fn get_conflicts(&self, filtered_access: &FilteredAccess<T>) -> Vec<T> {
// if combined unfiltered access is incompatible, check each filtered access for compatibility
// if combined unfiltered access is incompatible, check each filtered access for
// compatibility
if !filtered_access.access.is_compatible(&self.combined_access) {
for current_filtered_access in self.filtered_accesses.iter() {
if !current_filtered_access.is_compatible(&filtered_access) {

View file

@ -22,44 +22,60 @@ pub trait Fetch<'w>: Sized {
type State: FetchState;
/// Creates a new instance of this fetch.
///
/// # Safety
/// `state` must have been initialized (via [FetchState::init]) using the same `world` passed in to this function.
/// `state` must have been initialized (via [FetchState::init]) using the same `world` passed in
/// to this function.
unsafe fn init(world: &World, state: &Self::State) -> Self;
/// Returns true if (and only if) every table of every archetype matched by this Fetch contains all of the matched components.
/// This is used to select a more efficient "table iterator" for "dense" queries.
/// If this returns true, [Fetch::set_table] and [Fetch::table_fetch] will be called for iterators
/// If this returns false, [Fetch::set_archetype] and [Fetch::archetype_fetch] will be called for iterators
/// Returns true if (and only if) every table of every archetype matched by this Fetch contains
/// all of the matched components. This is used to select a more efficient "table iterator"
/// for "dense" queries. If this returns true, [Fetch::set_table] and [Fetch::table_fetch]
/// will be called for iterators If this returns false, [Fetch::set_archetype] and
/// [Fetch::archetype_fetch] will be called for iterators
fn is_dense(&self) -> bool;
/// Adjusts internal state to account for the next [Archetype]. This will always be called on archetypes that match this [Fetch]
/// Adjusts internal state to account for the next [Archetype]. This will always be called on
/// archetypes that match this [Fetch]
///
/// # Safety
/// `archetype` and `tables` must be from the [World] [Fetch::init] was called on. `state` must be the [Self::State] this was initialized with.
/// `archetype` and `tables` must be from the [World] [Fetch::init] was called on. `state` must
/// be the [Self::State] this was initialized with.
unsafe fn set_archetype(&mut self, state: &Self::State, archetype: &Archetype, tables: &Tables);
/// Adjusts internal state to account for the next [Table]. This will always be called on tables that match this [Fetch]
/// Adjusts internal state to account for the next [Table]. This will always be called on tables
/// that match this [Fetch]
///
/// # Safety
/// `table` must be from the [World] [Fetch::init] was called on. `state` must be the [Self::State] this was initialized with.
/// `table` must be from the [World] [Fetch::init] was called on. `state` must be the
/// [Self::State] this was initialized with.
unsafe fn set_table(&mut self, state: &Self::State, table: &Table);
/// Fetch [Self::Item] for the given `archetype_index` in the current [Archetype]. This must always be called after [Fetch::set_archetype] with an `archetype_index`
/// in the range of the current [Archetype]
/// Fetch [Self::Item] for the given `archetype_index` in the current [Archetype]. This must
/// always be called after [Fetch::set_archetype] with an `archetype_index` in the range of
/// the current [Archetype]
///
/// # Safety
/// Must always be called _after_ [Fetch::set_archetype]. `archetype_index` must be in the range of the current archetype
/// Must always be called _after_ [Fetch::set_archetype]. `archetype_index` must be in the range
/// of the current archetype
unsafe fn archetype_fetch(&mut self, archetype_index: usize) -> Self::Item;
/// Fetch [Self::Item] for the given `table_row` in the current [Table]. This must always be called after [Fetch::set_table] with a `table_row`
/// in the range of the current [Table]
/// Fetch [Self::Item] for the given `table_row` in the current [Table]. This must always be
/// called after [Fetch::set_table] with a `table_row` in the range of the current [Table]
///
/// # Safety
/// Must always be called _after_ [Fetch::set_table]. `table_row` must be in the range of the current table
/// Must always be called _after_ [Fetch::set_table]. `table_row` must be in the range of the
/// current table
unsafe fn table_fetch(&mut self, table_row: usize) -> Self::Item;
}
/// State used to construct a Fetch. This will be cached inside QueryState, so it is best to move as much data /
/// computation here as possible to reduce the cost of constructing Fetch.
/// State used to construct a Fetch. This will be cached inside QueryState, so it is best to move as
/// much data / computation here as possible to reduce the cost of constructing Fetch.
/// SAFETY:
/// Implementor must ensure that [FetchState::update_component_access] and [FetchState::update_archetype_component_access] exactly
/// reflects the results of [FetchState::matches_archetype], [FetchState::matches_table], [Fetch::archetype_fetch], and [Fetch::table_fetch]
/// Implementor must ensure that [FetchState::update_component_access] and
/// [FetchState::update_archetype_component_access] exactly reflects the results of
/// [FetchState::matches_archetype], [FetchState::matches_table], [Fetch::archetype_fetch], and
/// [Fetch::table_fetch]
pub unsafe trait FetchState: Send + Sync + Sized {
fn init(world: &mut World) -> Self;
fn update_component_access(&self, access: &mut FilteredAccess<ComponentId>);
@ -167,7 +183,8 @@ pub struct ReadState<T> {
marker: PhantomData<T>,
}
// SAFE: component access and archetype component access are properly updated to reflect that T is read
// SAFE: component access and archetype component access are properly updated to reflect that T is
// read
unsafe impl<T: Component> FetchState for ReadState<T> {
fn init(world: &mut World) -> Self {
let component_info = world.components.get_or_insert_info::<T>();
@ -312,7 +329,8 @@ pub struct WriteState<T> {
marker: PhantomData<T>,
}
// SAFE: component access and archetype component access are properly updated to reflect that T is written
// SAFE: component access and archetype component access are properly updated to reflect that T is
// written
unsafe impl<T: Component> FetchState for WriteState<T> {
fn init(world: &mut World) -> Self {
let component_info = world.components.get_or_insert_info::<T>();
@ -457,7 +475,8 @@ pub struct OptionState<T: FetchState> {
state: T,
}
// SAFE: component access and archetype component access are properly updated according to the internal Fetch
// SAFE: component access and archetype component access are properly updated according to the
// internal Fetch
unsafe impl<T: FetchState> FetchState for OptionState<T> {
fn init(world: &mut World) -> Self {
Self {
@ -589,7 +608,8 @@ pub struct FlagsState<T> {
marker: PhantomData<T>,
}
// SAFE: component access and archetype component access are properly updated to reflect that T is read
// SAFE: component access and archetype component access are properly updated to reflect that T is
// read
unsafe impl<T: Component> FetchState for FlagsState<T> {
fn init(world: &mut World) -> Self {
let component_info = world.components.get_or_insert_info::<T>();

View file

@ -10,8 +10,8 @@ use crate::{
use bevy_ecs_macros::all_tuples;
use std::{marker::PhantomData, ptr};
// TODO: uncomment this and use as shorthand (remove where F::Fetch: FilterFetch everywhere) when this bug is fixed in Rust 1.51:
// https://github.com/rust-lang/rust/pull/81671
// TODO: uncomment this and use as shorthand (remove where F::Fetch: FilterFetch everywhere) when
// this bug is fixed in Rust 1.51: https://github.com/rust-lang/rust/pull/81671
// pub trait QueryFilter: WorldQuery
// where
// Self::Fetch: FilterFetch,
@ -21,14 +21,17 @@ use std::{marker::PhantomData, ptr};
// impl<T: WorldQuery> QueryFilter for T where T::Fetch: FilterFetch {
// }
/// Fetch methods used by query filters. This trait exists to allow "short circuit" behaviors for relevant query filter fetches.
/// Fetch methods used by query filters. This trait exists to allow "short circuit" behaviors for
/// relevant query filter fetches.
pub trait FilterFetch: for<'a> Fetch<'a> {
/// # Safety
/// Must always be called _after_ [Fetch::set_archetype]. `archetype_index` must be in the range of the current archetype
/// Must always be called _after_ [Fetch::set_archetype]. `archetype_index` must be in the range
/// of the current archetype
unsafe fn archetype_filter_fetch(&mut self, archetype_index: usize) -> bool;
/// # Safety
/// Must always be called _after_ [Fetch::set_table]. `table_row` must be in the range of the current table
/// Must always be called _after_ [Fetch::set_table]. `table_row` must be in the range of the
/// current table
unsafe fn table_filter_fetch(&mut self, table_row: usize) -> bool;
}
@ -47,7 +50,8 @@ where
}
}
/// Filter that retrieves components of type `T` that have either been mutated or added since the start of the frame.
/// Filter that retrieves components of type `T` that have either been mutated or added since the
/// start of the frame.
pub struct With<T>(PhantomData<T>);
impl<T: Component> WorldQuery for With<T> {
@ -137,7 +141,8 @@ impl<'a, T: Component> Fetch<'a> for WithFetch<T> {
}
}
/// Filter that retrieves components of type `T` that have either been mutated or added since the start of the frame.
/// Filter that retrieves components of type `T` that have either been mutated or added since the
/// start of the frame.
pub struct Without<T>(PhantomData<T>);
impl<T: Component> WorldQuery for Without<T> {
@ -573,13 +578,15 @@ macro_rules! impl_flag_filter {
}
impl_flag_filter!(
/// Filter that retrieves components of type `T` that have been added since the start of the frame
/// Filter that retrieves components of type `T` that have been added since the start of the
/// frame
///
/// This filter is useful as a performance optimization as it means that the query contains fewer items
/// for a system to iterate over.
/// This filter is useful as a performance optimization as it means that the query contains
/// fewer items for a system to iterate over.
///
/// Because the ordering of systems can change and this filter is only effective on changes before the query executes
/// you need to use explicit dependency ordering or ordered stages for these query filters to be useful.
/// Because the ordering of systems can change and this filter is only effective on changes
/// before the query executes you need to use explicit dependency ordering or ordered
/// stages for these query filters to be useful.
///
///
/// Example:
@ -604,14 +611,15 @@ impl_flag_filter!(
);
impl_flag_filter!(
/// Filter that retrieves components of type `T` that have been mutated since the start of the frame.
/// Added components do not count as mutated.
/// Filter that retrieves components of type `T` that have been mutated since the start of the
/// frame. Added components do not count as mutated.
///
/// This filter is useful as a performance optimization as it means that the query contains fewer items
/// for a system to iterate over.
/// This filter is useful as a performance optimization as it means that the query contains
/// fewer items for a system to iterate over.
///
/// Because the ordering of systems can change and this filter is only effective on changes before the query executes
/// you need to use explicit dependency ordering or ordered stages for these query filters to be useful.
/// Because the ordering of systems can change and this filter is only effective on changes
/// before the query executes you need to use explicit dependency ordering or ordered
/// stages for these query filters to be useful.
///
/// Example:
/// ```
@ -635,15 +643,18 @@ impl_flag_filter!(
);
impl_flag_filter!(
/// Filter that retrieves components of type `T` that have been added or mutated since the start of the frame
/// Filter that retrieves components of type `T` that have been added or mutated since the
/// start of the frame
///
/// This filter is useful as a performance optimization as it means that the query contains fewer items
/// for a system to iterate over.
/// This filter is useful as a performance optimization as it means that the query contains
/// fewer items for a system to iterate over.
///
/// Because the ordering of systems can change and this filter is only effective on changes before the query executes
/// you need to use explicit dependency ordering or ordered stages for these query filters to be useful.
/// Because the ordering of systems can change and this filter is only effective on changes
/// before the query executes you need to use explicit dependency ordering or ordered
/// stages for these query filters to be useful.
///
/// Also see the documentation for [`Mutated<T>`] and [`Added`] as this filter is a logical OR of them.
/// Also see the documentation for [`Mutated<T>`] and [`Added`] as this filter is a logical OR
/// of them.
Changed,
ChangedState,
ChangedFetch,

View file

@ -199,8 +199,8 @@ where
/// # Safety
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
/// have unique access to the components they query.
/// This does not validate that `world.id()` matches `self.world_id`. Calling this on a `world` with
/// a mismatched WorldId is unsafe.
/// This does not validate that `world.id()` matches `self.world_id`. Calling this on a `world`
/// with a mismatched WorldId is unsafe.
#[inline]
pub(crate) unsafe fn iter_unchecked_manual<'w, 's>(
&'s self,
@ -296,8 +296,8 @@ where
/// # Safety
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
/// have unique access to the components they query.
/// This does not validate that `world.id()` matches `self.world_id`. Calling this on a `world` with
/// a mismatched WorldId is unsafe.
/// This does not validate that `world.id()` matches `self.world_id`. Calling this on a `world`
/// with a mismatched WorldId is unsafe.
pub(crate) unsafe fn for_each_unchecked_manual<'w, 's>(
&'s self,
world: &'w World,
@ -341,8 +341,8 @@ where
/// # Safety
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
/// have unique access to the components they query.
/// This does not validate that `world.id()` matches `self.world_id`. Calling this on a `world` with
/// a mismatched WorldId is unsafe.
/// This does not validate that `world.id()` matches `self.world_id`. Calling this on a `world`
/// with a mismatched WorldId is unsafe.
pub unsafe fn par_for_each_unchecked_manual<'w, 's>(
&'s self,
world: &'w World,

View file

@ -43,8 +43,10 @@ impl ReflectComponent {
}
/// # Safety
/// This method does not prevent you from having two mutable pointers to the same data, violating Rust's aliasing rules. To avoid this:
/// * Only call this method in an exclusive system to avoid sharing across threads (or use a scheduler that enforces safe memory access).
/// This method does not prevent you from having two mutable pointers to the same data,
/// violating Rust's aliasing rules. To avoid this:
/// * Only call this method in an exclusive system to avoid sharing across threads (or use a
/// scheduler that enforces safe memory access).
/// * Don't call this method more than once in the same scope for a given component.
pub unsafe fn reflect_component_unchecked_mut<'a>(
&self,

View file

@ -38,8 +38,8 @@ impl ParallelSystemExecutor for SingleThreadedExecutor {
}
impl SingleThreadedExecutor {
/// Calls system.new_archetype() for each archetype added since the last call to [update_archetypes] and
/// updates cached archetype_component_access.
/// Calls system.new_archetype() for each archetype added since the last call to
/// [update_archetypes] and updates cached archetype_component_access.
fn update_archetypes(&mut self, systems: &mut [ParallelSystemContainer], world: &World) {
let archetypes = world.archetypes();
let old_generation = self.archetype_generation;

View file

@ -148,8 +148,8 @@ impl ParallelSystemExecutor for ParallelExecutor {
}
impl ParallelExecutor {
/// Calls system.new_archetype() for each archetype added since the last call to [update_archetypes] and
/// updates cached archetype_component_access.
/// Calls system.new_archetype() for each archetype added since the last call to
/// [update_archetypes] and updates cached archetype_component_access.
fn update_archetypes(&mut self, systems: &mut [ParallelSystemContainer], world: &World) {
let archetypes = world.archetypes();
let old_generation = self.archetype_generation;

View file

@ -35,13 +35,14 @@ impl_downcast!(Stage);
/// This occurs because, in the absence of explicit constraints, systems are executed in
/// an unstable, arbitrary order within each stage that may vary between runs and frames.
///
/// Some ambiguities reported by the ambiguity checker may be warranted (to allow two systems to run without blocking each other)
/// or spurious, as the exact combination of archetypes used may prevent them from ever conflicting during actual gameplay.
/// You can resolve the warnings produced by the ambiguity checker by adding `.before` or `.after` to one of the conflicting systems
/// Some ambiguities reported by the ambiguity checker may be warranted (to allow two systems to run
/// without blocking each other) or spurious, as the exact combination of archetypes used may
/// prevent them from ever conflicting during actual gameplay. You can resolve the warnings produced
/// by the ambiguity checker by adding `.before` or `.after` to one of the conflicting systems
/// referencing the other system to force a specific ordering.
///
/// The checker may report a system more times than the amount of constraints it would actually need to have
/// unambiguous order with regards to a group of already-constrained systems.
/// The checker may report a system more times than the amount of constraints it would actually need
/// to have unambiguous order with regards to a group of already-constrained systems.
pub struct ReportExecutionOrderAmbiguities;
struct VirtualSystemSet {
@ -523,7 +524,7 @@ fn find_ambiguities(systems: &[impl SystemContainer]) -> Vec<(usize, usize, Vec<
for (index_a, relations) in all_relations.drain(..).enumerate() {
// TODO: prove that `.take(index_a)` would be correct here, and uncomment it if so.
for index_b in full_bitset.difference(&relations)
/*.take(index_a)*/
// .take(index_a)
{
if !processed.contains(index_b)
&& all_ambiguity_sets[index_a].is_disjoint(&all_ambiguity_sets[index_b])

View file

@ -217,7 +217,8 @@ impl<T: Clone> State<T> {
self.next.as_ref()
}
/// Queue a state change. This will fail if there is already a state in the queue, or if the given `state` matches the current state
/// Queue a state change. This will fail if there is already a state in the queue, or if the
/// given `state` matches the current state
pub fn set_next(&mut self, state: T) -> Result<(), StateError> {
if std::mem::discriminant(&self.current) == std::mem::discriminant(&state) {
return Err(StateError::AlreadyInState);
@ -231,7 +232,8 @@ impl<T: Clone> State<T> {
Ok(())
}
/// Same as [Self::set_next], but if there is already a next state, it will be overwritten instead of failing
/// Same as [Self::set_next], but if there is already a next state, it will be overwritten
/// instead of failing
pub fn overwrite_next(&mut self, state: T) -> Result<(), StateError> {
if std::mem::discriminant(&self.current) == std::mem::discriminant(&state) {
return Err(StateError::AlreadyInState);

View file

@ -98,7 +98,9 @@ impl BlobVec {
std::ptr::copy_nonoverlapping(value, ptr, self.item_layout.size());
}
/// increases the length by one (and grows the vec if needed) with uninitialized memory and returns the index
/// increases the length by one (and grows the vec if needed) with uninitialized memory and
/// returns the index
///
/// # Safety
/// the newly allocated space must be immediately populated with a valid value
#[inline]
@ -110,17 +112,19 @@ impl BlobVec {
}
/// # Safety
/// len must be <= capacity. if length is decreased, "out of bounds" items must be dropped. Newly added items must be
/// immediately populated with valid values and length must be increased. For better unwind safety, call [BlobVec::set_len]
/// _after_ populating a new value.
/// len must be <= capacity. if length is decreased, "out of bounds" items must be dropped.
/// Newly added items must be immediately populated with valid values and length must be
/// increased. For better unwind safety, call [BlobVec::set_len] _after_ populating a new
/// value.
pub unsafe fn set_len(&mut self, len: usize) {
debug_assert!(len <= self.capacity());
self.len = len;
}
/// Performs a "swap remove" at the given `index`, which removes the item at `index` and moves the last item
/// in the [BlobVec] to `index` (if `index` is not the last item). It is the caller's responsibility to
/// drop the returned pointer, if that is desirable.
/// Performs a "swap remove" at the given `index`, which removes the item at `index` and moves
/// the last item in the [BlobVec] to `index` (if `index` is not the last item). It is the
/// caller's responsibility to drop the returned pointer, if that is desirable.
///
/// # Safety
/// It is the caller's responsibility to ensure that `index` is < self.len()
/// Callers should _only_ access the returned pointer immediately after calling this function.
@ -161,6 +165,7 @@ impl BlobVec {
}
/// Gets a pointer to the start of the vec
///
/// # Safety
/// must ensure rust mutability rules are not violated
#[inline]
@ -170,13 +175,13 @@ impl BlobVec {
pub fn clear(&mut self) {
let len = self.len;
// We set len to 0 _before_ dropping elements for unwind safety. This ensures we don't accidentally
// drop elements twice in the event of a drop impl panicking.
// We set len to 0 _before_ dropping elements for unwind safety. This ensures we don't
// accidentally drop elements twice in the event of a drop impl panicking.
self.len = 0;
for i in 0..len {
unsafe {
// NOTE: this doesn't use self.get_unchecked(i) because the debug_assert on index will
// panic here due to self.len being set to 0
// NOTE: this doesn't use self.get_unchecked(i) because the debug_assert on index
// will panic here due to self.len being set to 0
let ptr = self.get_ptr().as_ptr().add(i * self.item_layout.size());
(self.drop)(ptr);
}
@ -260,7 +265,8 @@ mod tests {
use crate::component::TypeInfo;
use std::{alloc::Layout, cell::RefCell, rc::Rc};
/// # Safety:
/// # Safety
///
/// `blob_vec` must have a layout that matches Layout::new::<T>()
unsafe fn push<T>(blob_vec: &mut BlobVec, mut value: T) {
let index = blob_vec.push_uninit();
@ -268,7 +274,8 @@ mod tests {
std::mem::forget(value);
}
/// # Safety:
/// # Safety
///
/// `blob_vec` must have a layout that matches Layout::new::<T>()
unsafe fn swap_remove<T>(blob_vec: &mut BlobVec, index: usize) -> T {
assert!(index < blob_vec.len());
@ -276,9 +283,10 @@ mod tests {
value.cast::<T>().read()
}
/// # Safety:
/// `blob_vec` must have a layout that matches Layout::new::<T>(), it most store a valid T value at
/// the given `index`
/// # Safety
///
/// `blob_vec` must have a layout that matches Layout::new::<T>(), it most store a valid T value
/// at the given `index`
unsafe fn get_mut<T>(blob_vec: &mut BlobVec, index: usize) -> &mut T {
assert!(index < blob_vec.len());
&mut *blob_vec.get_unchecked(index).cast::<T>()

View file

@ -113,10 +113,12 @@ impl ComponentSparseSet {
}
/// Inserts the `entity` key and component `value` pair into this sparse set.
/// The caller is responsible for ensuring the value is not dropped. This collection will drop the value when needed.
/// The caller is responsible for ensuring the value is not dropped. This collection will drop
/// the value when needed.
///
/// # Safety
/// The `value` pointer must point to a valid address that matches the `Layout` inside the `ComponentInfo` given
/// when constructing this sparse set.
/// The `value` pointer must point to a valid address that matches the `Layout` inside the
/// `ComponentInfo` given when constructing this sparse set.
pub unsafe fn insert(&mut self, entity: Entity, value: *mut u8, flags: ComponentFlags) {
let dense = &mut self.dense;
let entities = &mut self.entities;
@ -175,8 +177,9 @@ impl ComponentSparseSet {
})
}
/// Removes the `entity` from this sparse set and returns a pointer to the associated value (if it exists).
/// It is the caller's responsibility to drop the returned ptr (if Some is returned).
/// Removes the `entity` from this sparse set and returns a pointer to the associated value (if
/// it exists). It is the caller's responsibility to drop the returned ptr (if Some is
/// returned).
pub fn remove_and_forget(&mut self, entity: Entity) -> Option<*mut u8> {
self.sparse.remove(entity).map(|dense_index| {
// SAFE: unique access to flags
@ -268,8 +271,8 @@ impl<I: SparseSetIndex, V> SparseSet<I, V> {
self.dense.push(value);
}
// PERF: switch to this. it's faster but it has an invalid memory access on table_add_remove_many
// let dense = &mut self.dense;
// PERF: switch to this. it's faster but it has an invalid memory access on
// table_add_remove_many let dense = &mut self.dense;
// let indices = &mut self.indices;
// let dense_index = *self.sparse.get_or_insert_with(index.clone(), move || {
// if dense.len() == dense.capacity() {

View file

@ -49,7 +49,8 @@ impl Column {
/// # Safety
/// Assumes data has already been allocated for the given row/column.
/// Allows aliased mutable accesses to the data at the given `row`. Caller must ensure that this does not happen.
/// Allows aliased mutable accesses to the data at the given `row`. Caller must ensure that this
/// does not happen.
#[inline]
pub unsafe fn set_unchecked(&self, row: usize, data: *mut u8) {
self.data.set_unchecked(row, data);
@ -67,7 +68,8 @@ impl Column {
/// # Safety
/// Assumes data has already been allocated for the given row/column.
/// Allows aliased mutable accesses to the row's ComponentFlags. Caller must ensure that this does not happen.
/// Allows aliased mutable accesses to the row's ComponentFlags. Caller must ensure that this
/// does not happen.
#[inline]
#[allow(clippy::mut_from_ref)]
pub unsafe fn get_flags_unchecked_mut(&self, row: usize) -> &mut ComponentFlags {
@ -193,7 +195,9 @@ impl Table {
)
}
/// Removes the entity at the given row and returns the entity swapped in to replace it (if an entity was swapped in)
/// Removes the entity at the given row and returns the entity swapped in to replace it (if an
/// entity was swapped in)
///
/// # Safety
/// `row` must be in-bounds
pub unsafe fn swap_remove_unchecked(&mut self, row: usize) -> Option<Entity> {
@ -209,9 +213,11 @@ impl Table {
}
}
/// Moves the `row` column values to `new_table`, for the columns shared between both tables. Returns the index of the
/// new row in `new_table` and the entity in this table swapped in to replace it (if an entity was swapped in).
/// missing columns will be "forgotten". It is the caller's responsibility to drop them
/// Moves the `row` column values to `new_table`, for the columns shared between both tables.
/// Returns the index of the new row in `new_table` and the entity in this table swapped in
/// to replace it (if an entity was swapped in). missing columns will be "forgotten". It is
/// the caller's responsibility to drop them
///
/// # Safety
/// Row must be in-bounds
pub unsafe fn move_to_and_forget_missing_unchecked(
@ -239,8 +245,10 @@ impl Table {
}
}
/// Moves the `row` column values to `new_table`, for the columns shared between both tables. Returns the index of the
/// new row in `new_table` and the entity in this table swapped in to replace it (if an entity was swapped in).
/// Moves the `row` column values to `new_table`, for the columns shared between both tables.
/// Returns the index of the new row in `new_table` and the entity in this table swapped in
/// to replace it (if an entity was swapped in).
///
/// # Safety
/// row must be in-bounds
pub unsafe fn move_to_and_drop_missing_unchecked(
@ -270,8 +278,10 @@ impl Table {
}
}
/// Moves the `row` column values to `new_table`, for the columns shared between both tables. Returns the index of the
/// new row in `new_table` and the entity in this table swapped in to replace it (if an entity was swapped in).
/// Moves the `row` column values to `new_table`, for the columns shared between both tables.
/// Returns the index of the new row in `new_table` and the entity in this table swapped in
/// to replace it (if an entity was swapped in).
///
/// # Safety
/// `row` must be in-bounds. `new_table` must contain every component this table has
pub unsafe fn move_to_superset_unchecked(
@ -326,6 +336,7 @@ impl Table {
}
/// Allocates space for a new entity
///
/// # Safety
/// the allocated row must be written to immediately with valid values in each column
pub unsafe fn allocate(&mut self, entity: Entity) -> usize {

View file

@ -49,7 +49,10 @@ impl<'a> Commands<'a> {
/// Creates a new entity with the components contained in `bundle`.
///
/// Note that `bundle` is a [Bundle], which is a collection of components. [Bundle] is automatically implemented for tuples of components. You can also create your own bundle types by deriving [`derive@Bundle`]. If you would like to spawn an entity with a single component, consider wrapping the component in a tuple (which [Bundle] is implemented for).
/// Note that `bundle` is a [Bundle], which is a collection of components. [Bundle] is
/// automatically implemented for tuples of components. You can also create your own bundle
/// types by deriving [`derive@Bundle`]. If you would like to spawn an entity with a single
/// component, consider wrapping the component in a tuple (which [Bundle] is implemented for).
///
/// See [`Self::set_current_entity`], [`Self::insert`].
///
@ -88,7 +91,8 @@ impl<'a> Commands<'a> {
self
}
/// Equivalent to iterating `bundles_iter` and calling [`Self::spawn`] on each bundle, but slightly more performant.
/// Equivalent to iterating `bundles_iter` and calling [`Self::spawn`] on each bundle, but
/// slightly more performant.
pub fn spawn_batch<I>(&mut self, bundles_iter: I) -> &mut Self
where
I: IntoIterator + Send + Sync + 'static,
@ -167,7 +171,10 @@ impl<'a> Commands<'a> {
///
/// # Warning
///
/// It's possible to call this with a bundle, but this is likely not intended and [`Self::with_bundle`] should be used instead. If `with` is called with a bundle, the bundle itself will be added as a component instead of the bundles' inner components each being added.
/// It's possible to call this with a bundle, but this is likely not intended and
/// [`Self::with_bundle`] should be used instead. If `with` is called with a bundle, the bundle
/// itself will be added as a component instead of the bundles' inner components each being
/// added.
///
/// # Example
///
@ -207,7 +214,8 @@ impl<'a> Commands<'a> {
self
}
/// Adds a command directly to the command list. Prefer this to [`Self::add_command_boxed`] if the type of `command` is statically known.
/// Adds a command directly to the command list. Prefer this to [`Self::add_command_boxed`] if
/// the type of `command` is statically known.
pub fn add_command<C: Command>(&mut self, command: C) -> &mut Self {
self.queue.push(Box::new(command));
self
@ -344,7 +352,8 @@ where
{
fn write(self: Box<Self>, world: &mut World) {
if let Some(mut entity_mut) = world.get_entity_mut(self.entity) {
// remove intersection to gracefully handle components that were removed before running this command
// remove intersection to gracefully handle components that were removed before running
// this command
entity_mut.remove_bundle_intersection::<T>();
}
}

View file

@ -13,7 +13,8 @@ pub struct SystemState {
pub(crate) name: Cow<'static, str>,
pub(crate) component_access_set: FilteredAccessSet<ComponentId>,
pub(crate) archetype_component_access: Access<ArchetypeComponentId>,
// NOTE: this must be kept private. making a SystemState non-send is irreversible to prevent SystemParams from overriding each other
// NOTE: this must be kept private. making a SystemState non-send is irreversible to prevent
// SystemParams from overriding each other
is_send: bool,
}

View file

@ -24,8 +24,8 @@ where
F::Fetch: FilterFetch,
{
/// # Safety
/// This will create a Query that could violate memory safety rules. Make sure that this is only called in
/// ways that ensure the Queries have unique mutable access.
/// This will create a Query that could violate memory safety rules. Make sure that this is only
/// called in ways that ensure the Queries have unique mutable access.
#[inline]
pub(crate) unsafe fn new(world: &'w World, state: &'w QueryState<Q, F>) -> Self {
Self { world, state }
@ -37,41 +37,49 @@ where
where
Q::Fetch: ReadOnlyFetch,
{
// SAFE: system runs without conflicts with other systems. same-system queries have runtime borrow checks when they conflict
// SAFE: system runs without conflicts with other systems. same-system queries have runtime
// borrow checks when they conflict
unsafe { self.state.iter_unchecked_manual(self.world) }
}
/// Iterates over the query results
#[inline]
pub fn iter_mut(&mut self) -> QueryIter<'_, '_, Q, F> {
// SAFE: system runs without conflicts with other systems. same-system queries have runtime borrow checks when they conflict
// SAFE: system runs without conflicts with other systems. same-system queries have runtime
// borrow checks when they conflict
unsafe { self.state.iter_unchecked_manual(self.world) }
}
/// Iterates over the query results
///
/// # Safety
/// This allows aliased mutability. You must make sure this call does not result in multiple mutable references to the same component
/// This allows aliased mutability. You must make sure this call does not result in multiple
/// mutable references to the same component
#[inline]
pub unsafe fn iter_unsafe(&self) -> QueryIter<'_, '_, Q, F> {
// SEMI-SAFE: system runs without conflicts with other systems. same-system queries have runtime borrow checks when they conflict
// SEMI-SAFE: system runs without conflicts with other systems. same-system queries have
// runtime borrow checks when they conflict
self.state.iter_unchecked_manual(self.world)
}
/// Runs `f` on each query result. This is faster than the equivalent iter() method, but cannot be chained like a normal iterator.
/// This can only be called for read-only queries
/// Runs `f` on each query result. This is faster than the equivalent iter() method, but cannot
/// be chained like a normal iterator. This can only be called for read-only queries
#[inline]
pub fn for_each(&self, f: impl FnMut(<Q::Fetch as Fetch<'w>>::Item))
where
Q::Fetch: ReadOnlyFetch,
{
// SAFE: system runs without conflicts with other systems. same-system queries have runtime borrow checks when they conflict
// SAFE: system runs without conflicts with other systems. same-system queries have runtime
// borrow checks when they conflict
unsafe { self.state.for_each_unchecked_manual(self.world, f) };
}
/// Runs `f` on each query result. This is faster than the equivalent iter() method, but cannot be chained like a normal iterator.
/// Runs `f` on each query result. This is faster than the equivalent iter() method, but cannot
/// be chained like a normal iterator.
#[inline]
pub fn for_each_mut(&self, f: impl FnMut(<Q::Fetch as Fetch<'w>>::Item)) {
// SAFE: system runs without conflicts with other systems. same-system queries have runtime borrow checks when they conflict
// SAFE: system runs without conflicts with other systems. same-system queries have runtime
// borrow checks when they conflict
unsafe { self.state.for_each_unchecked_manual(self.world, f) };
}
@ -85,7 +93,8 @@ where
) where
Q::Fetch: ReadOnlyFetch,
{
// SAFE: system runs without conflicts with other systems. same-system queries have runtime borrow checks when they conflict
// SAFE: system runs without conflicts with other systems. same-system queries have runtime
// borrow checks when they conflict
unsafe {
self.state
.par_for_each_unchecked_manual(self.world, task_pool, batch_size, f)
@ -100,7 +109,8 @@ where
batch_size: usize,
f: impl Fn(<Q::Fetch as Fetch<'w>>::Item) + Send + Sync + Clone,
) {
// SAFE: system runs without conflicts with other systems. same-system queries have runtime borrow checks when they conflict
// SAFE: system runs without conflicts with other systems. same-system queries have runtime
// borrow checks when they conflict
unsafe {
self.state
.par_for_each_unchecked_manual(self.world, task_pool, batch_size, f)
@ -113,7 +123,8 @@ where
where
Q::Fetch: ReadOnlyFetch,
{
// SAFE: system runs without conflicts with other systems. same-system queries have runtime borrow checks when they conflict
// SAFE: system runs without conflicts with other systems. same-system queries have runtime
// borrow checks when they conflict
unsafe { self.state.get_unchecked_manual(self.world, entity) }
}
@ -123,24 +134,29 @@ where
&mut self,
entity: Entity,
) -> Result<<Q::Fetch as Fetch>::Item, QueryEntityError> {
// // SAFE: system runs without conflicts with other systems. same-system queries have runtime borrow checks when they conflict
// // SAFE: system runs without conflicts with other systems. same-system queries have
// runtime borrow checks when they conflict
unsafe { self.state.get_unchecked_manual(self.world, entity) }
}
/// Gets the query result for the given `entity`
///
/// # Safety
/// This allows aliased mutability. You must make sure this call does not result in multiple mutable references to the same component
/// This allows aliased mutability. You must make sure this call does not result in multiple
/// mutable references to the same component
#[inline]
pub unsafe fn get_unchecked(
&self,
entity: Entity,
) -> Result<<Q::Fetch as Fetch>::Item, QueryEntityError> {
// SEMI-SAFE: system runs without conflicts with other systems. same-system queries have runtime borrow checks when they conflict
// SEMI-SAFE: system runs without conflicts with other systems. same-system queries have
// runtime borrow checks when they conflict
self.state.get_unchecked_manual(self.world, entity)
}
/// Gets a reference to the entity's component of the given type. This will fail if the entity does not have
/// the given component type or if the given component type does not match this query.
/// Gets a reference to the entity's component of the given type. This will fail if the entity
/// does not have the given component type or if the given component type does not match
/// this query.
#[inline]
pub fn get_component<T: Component>(&self, entity: Entity) -> Result<&T, QueryComponentError> {
let world = self.world;
@ -168,8 +184,9 @@ where
}
}
/// Gets a mutable reference to the entity's component of the given type. This will fail if the entity does not have
/// the given component type or if the given component type does not match this query.
/// Gets a mutable reference to the entity's component of the given type. This will fail if the
/// entity does not have the given component type or if the given component type does not
/// match this query.
#[inline]
pub fn get_component_mut<T: Component>(
&mut self,
@ -179,10 +196,12 @@ where
unsafe { self.get_component_unchecked_mut(entity) }
}
/// Gets a mutable reference to the entity's component of the given type. This will fail if the entity does not have
/// the given component type or the component does not match the query.
/// Gets a mutable reference to the entity's component of the given type. This will fail if the
/// entity does not have the given component type or the component does not match the query.
///
/// # Safety
/// This allows aliased mutability. You must make sure this call does not result in multiple mutable references to the same component
/// This allows aliased mutability. You must make sure this call does not result in multiple
/// mutable references to the same component
#[inline]
pub unsafe fn get_component_unchecked_mut<T: Component>(
&self,

View file

@ -27,9 +27,10 @@ pub trait System: Send + Sync + 'static {
fn archetype_component_access(&self) -> &Access<ArchetypeComponentId>;
fn is_send(&self) -> bool;
/// # Safety
/// This might access World and Resources in an unsafe manner. This should only be called in one of the following contexts:
/// 1. This system is the only system running on the given World across all threads
/// 2. This system only runs in parallel with other systems that do not conflict with the `archetype_component_access()`
/// This might access World and Resources in an unsafe manner. This should only be called in one
/// of the following contexts: 1. This system is the only system running on the given World
/// across all threads 2. This system only runs in parallel with other systems that do not
/// conflict with the `archetype_component_access()`
unsafe fn run_unsafe(&mut self, input: Self::In, world: &World) -> Self::Out;
fn run(&mut self, input: Self::In, world: &mut World) -> Self::Out {
// SAFE: world and resources are exclusively borrowed

View file

@ -38,8 +38,9 @@ pub trait SystemParam: Sized {
/// # Safety
/// it is the implementors responsibility to ensure `system_state` is populated with the _exact_
/// [World] access used by the SystemParamState (and associated FetchSystemParam). Additionally, it is the
/// implementor's responsibility to ensure there is no conflicting access across all SystemParams.
/// [World] access used by the SystemParamState (and associated FetchSystemParam). Additionally, it
/// is the implementor's responsibility to ensure there is no conflicting access across all
/// SystemParams.
pub unsafe trait SystemParamState: Send + Sync + 'static {
type Config: Default + Send + Sync;
fn init(world: &mut World, system_state: &mut SystemState, config: Self::Config) -> Self;
@ -52,8 +53,8 @@ pub unsafe trait SystemParamState: Send + Sync + 'static {
pub trait SystemParamFetch<'a>: SystemParamState {
type Item;
/// # Safety
/// This call might access any of the input parameters in an unsafe way. Make sure the data access is safe in
/// the context of the system scheduler
/// This call might access any of the input parameters in an unsafe way. Make sure the data
/// access is safe in the context of the system scheduler
unsafe fn get_param(
state: &'a mut Self,
system_state: &'a SystemState,
@ -70,8 +71,8 @@ where
type Fetch = QueryState<Q, F>;
}
// SAFE: Relevant query ComponentId and ArchetypeComponentId access is applied to SystemState. If this QueryState conflicts
// with any prior access, a panic will occur.
// SAFE: Relevant query ComponentId and ArchetypeComponentId access is applied to SystemState. If
// this QueryState conflicts with any prior access, a panic will occur.
unsafe impl<Q: WorldQuery + 'static, F: WorldQuery + 'static> SystemParamState for QueryState<Q, F>
where
F::Fetch: FilterFetch,
@ -168,7 +169,8 @@ impl<'w, T: Component> Res<'w, T> {
self.flags.contains(ComponentFlags::MUTATED)
}
/// Returns true if (and only if) this resource been either mutated or added since the start of the frame.
/// Returns true if (and only if) this resource been either mutated or added since the start of
/// the frame.
pub fn changed(&self) -> bool {
self.flags
.intersects(ComponentFlags::ADDED | ComponentFlags::MUTATED)
@ -192,8 +194,8 @@ impl<'a, T: Component> SystemParam for Res<'a, T> {
type Fetch = ResState<T>;
}
// SAFE: Res ComponentId and ArchetypeComponentId access is applied to SystemState. If this Res conflicts
// with any prior access, a panic will occur.
// SAFE: Res ComponentId and ArchetypeComponentId access is applied to SystemState. If this Res
// conflicts with any prior access, a panic will occur.
unsafe impl<T: Component> SystemParamState for ResState<T> {
type Config = ();
@ -293,7 +295,8 @@ impl<'w, T: Component> ResMut<'w, T> {
self.flags.contains(ComponentFlags::MUTATED)
}
/// Returns true if (and only if) this resource been either mutated or added since the start of the frame.
/// Returns true if (and only if) this resource been either mutated or added since the start of
/// the frame.
pub fn changed(&self) -> bool {
self.flags
.intersects(ComponentFlags::ADDED | ComponentFlags::MUTATED)
@ -324,8 +327,8 @@ impl<'a, T: Component> SystemParam for ResMut<'a, T> {
type Fetch = ResMutState<T>;
}
// SAFE: Res ComponentId and ArchetypeComponentId access is applied to SystemState. If this Res conflicts
// with any prior access, a panic will occur.
// SAFE: Res ComponentId and ArchetypeComponentId access is applied to SystemState. If this Res
// conflicts with any prior access, a panic will occur.
unsafe impl<T: Component> SystemParamState for ResMutState<T> {
type Config = ();
@ -505,8 +508,8 @@ impl<'a, T: Component> SystemParam for RemovedComponents<'a, T> {
type Fetch = RemovedComponentsState<T>;
}
// SAFE: no component access. removed component entity collections can be read in parallel and are never mutably borrowed
// during system execution
// SAFE: no component access. removed component entity collections can be read in parallel and are
// never mutably borrowed during system execution
unsafe impl<T: Component> SystemParamState for RemovedComponentsState<T> {
type Config = ();
@ -557,8 +560,8 @@ impl<'a, T: 'static> SystemParam for NonSend<'a, T> {
type Fetch = NonSendState<T>;
}
// SAFE: NonSendComponentId and ArchetypeComponentId access is applied to SystemState. If this NonSend conflicts
// with any prior access, a panic will occur.
// SAFE: NonSendComponentId and ArchetypeComponentId access is applied to SystemState. If this
// NonSend conflicts with any prior access, a panic will occur.
unsafe impl<T: 'static> SystemParamState for NonSendState<T> {
type Config = ();
@ -643,8 +646,8 @@ impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> {
type Fetch = NonSendMutState<T>;
}
// SAFE: NonSendMut ComponentId and ArchetypeComponentId access is applied to SystemState. If this NonSendMut conflicts
// with any prior access, a panic will occur.
// SAFE: NonSendMut ComponentId and ArchetypeComponentId access is applied to SystemState. If this
// NonSendMut conflicts with any prior access, a panic will occur.
unsafe impl<T: 'static> SystemParamState for NonSendMutState<T> {
type Config = ();
@ -858,6 +861,6 @@ macro_rules! impl_system_param_tuple {
};
}
// TODO: consider creating a Config trait with a default() function, then implementing that for tuples.
// that would allow us to go past tuples of len 12
// TODO: consider creating a Config trait with a default() function, then implementing that for
// tuples. that would allow us to go past tuples of len 12
all_tuples!(impl_system_param_tuple, 0, 12, P);

View file

@ -36,7 +36,8 @@ impl<'w> EntityRef<'w> {
#[inline]
pub fn archetype(&self) -> &Archetype {
// SAFE: EntityRefs always point to valid entities. Valid entities always have valid archetypes
// SAFE: EntityRefs always point to valid entities. Valid entities always have valid
// archetypes
unsafe {
self.world
.archetypes
@ -76,7 +77,8 @@ impl<'w> EntityRef<'w> {
}
/// # Safety
/// This allows aliased mutability. You must make sure this call does not result in multiple mutable references to the same component
/// This allows aliased mutability. You must make sure this call does not result in multiple
/// mutable references to the same component
#[inline]
pub unsafe fn get_unchecked_mut<T: Component>(&self) -> Option<Mut<'w, T>> {
get_component_and_flags_with_type(self.world, TypeId::of::<T>(), self.entity, self.location)
@ -121,7 +123,8 @@ impl<'w> EntityMut<'w> {
#[inline]
pub fn archetype(&self) -> &Archetype {
// SAFE: EntityRefs always point to valid entities. Valid entities always have valid archetypes
// SAFE: EntityRefs always point to valid entities. Valid entities always have valid
// archetypes
unsafe {
self.world
.archetypes
@ -157,7 +160,8 @@ impl<'w> EntityMut<'w> {
#[inline]
pub fn get_mut<T: Component>(&mut self) -> Option<Mut<'w, T>> {
// SAFE: world access is unique, entity location is valid, and returned component is of type T
// SAFE: world access is unique, entity location is valid, and returned component is of type
// T
unsafe {
get_component_and_flags_with_type(
self.world,
@ -173,7 +177,8 @@ impl<'w> EntityMut<'w> {
}
/// # Safety
/// This allows aliased mutability. You must make sure this call does not result in multiple mutable references to the same component
/// This allows aliased mutability. You must make sure this call does not result in multiple
/// mutable references to the same component
#[inline]
pub unsafe fn get_unchecked_mut<T: Component>(&self) -> Option<Mut<'w, T>> {
get_component_and_flags_with_type(self.world, TypeId::of::<T>(), self.entity, self.location)
@ -227,7 +232,8 @@ impl<'w> EntityMut<'w> {
let (old_table, new_table) = storages
.tables
.get_2_mut(old_table_id, new_archetype.table_id());
// PERF: store "non bundle" components in edge, then just move those to avoid redundant copies
// PERF: store "non bundle" components in edge, then just move those to avoid
// redundant copies
let move_result =
old_table.move_to_superset_unchecked(old_table_row, new_table);
@ -235,7 +241,8 @@ impl<'w> EntityMut<'w> {
// if an entity was moved into this entity's table spot, update its table row
if let Some(swapped_entity) = move_result.swapped_entity {
let swapped_location = entities.get(swapped_entity).unwrap();
// SAFE: entity is live and is therefore contained in an archetype that exists
// SAFE: entity is live and is therefore contained in an archetype that
// exists
archetypes
.get_unchecked_mut(swapped_location.archetype_id)
.set_entity_table_row(swapped_location.index, old_table_row);
@ -297,7 +304,8 @@ impl<'w> EntityMut<'w> {
let old_archetype = unsafe { archetypes.get_unchecked_mut(old_location.archetype_id) };
let mut bundle_components = bundle_info.component_ids.iter().cloned();
let entity = self.entity;
// SAFE: bundle components are iterated in order, which guarantees that the component type matches
// SAFE: bundle components are iterated in order, which guarantees that the component type
// matches
let result = unsafe {
T::from_components(|| {
let component_id = bundle_components.next().unwrap();
@ -330,7 +338,8 @@ impl<'w> EntityMut<'w> {
.tables
.get_2_mut(old_table_id, new_archetype.table_id());
// SAFE: table_row exists. All "missing" components have been extracted into the bundle above and the caller takes ownership
// SAFE: table_row exists. All "missing" components have been extracted into the bundle
// above and the caller takes ownership
let move_result =
unsafe { old_table.move_to_and_forget_missing_unchecked(old_table_row, new_table) };
@ -505,22 +514,24 @@ impl<'w> EntityMut<'w> {
/// # Safety
/// Caller must not modify the world in a way that changes the current entity's location
/// If the caller _does_ do something that could change the location, self.update_location() must be
/// called before using any other methods in EntityMut
/// If the caller _does_ do something that could change the location, self.update_location()
/// must be called before using any other methods in EntityMut
#[inline]
pub unsafe fn world_mut(&mut self) -> &mut World {
self.world
}
/// Updates the internal entity location to match the current location in the internal [World].
/// This is only needed if the user called [EntityMut::world], which enables the location to change.
/// This is only needed if the user called [EntityMut::world], which enables the location to
/// change.
pub fn update_location(&mut self) {
self.location = self.world.entities().get(self.entity).unwrap();
}
}
/// # Safety
/// `entity_location` must be within bounds of the given archetype and `entity` must exist inside the archetype
/// `entity_location` must be within bounds of the given archetype and `entity` must exist inside
/// the archetype
#[inline]
unsafe fn get_component(
world: &World,
@ -580,7 +591,8 @@ unsafe fn get_component_and_flags(
}
/// # Safety
// `entity_location` must be within bounds of the given archetype and `entity` must exist inside the archetype
// `entity_location` must be within bounds of the given archetype and `entity` must exist inside the
// archetype
/// The relevant table row must be removed separately
/// `component_id` must be valid
#[inline]
@ -666,9 +678,10 @@ unsafe fn contains_component_with_id(
.contains(component_id)
}
/// Adds a bundle to the given archetype and returns the resulting archetype. This could be the same [ArchetypeId],
/// in the event that adding the given bundle does not result in an Archetype change. Results are cached in the
/// Archetype Graph to avoid redundant work.
/// Adds a bundle to the given archetype and returns the resulting archetype. This could be the same
/// [ArchetypeId], in the event that adding the given bundle does not result in an Archetype change.
/// Results are cached in the Archetype Graph to avoid redundant work.
///
/// # Safety
/// `archetype_id` must exist and components in `bundle_info` must exist
pub(crate) unsafe fn add_bundle_to_archetype(
@ -760,11 +773,13 @@ pub(crate) unsafe fn add_bundle_to_archetype(
}
}
/// Removes a bundle from the given archetype and returns the resulting archetype (or None if the removal was invalid).
/// in the event that adding the given bundle does not result in an Archetype change. Results are cached in the
/// Archetype Graph to avoid redundant work.
/// if `intersection` is false, attempting to remove a bundle with components _not_ contained in the current archetype will fail,
/// returning None. if `intersection` is true, components in the bundle but not in the current archetype will be ignored
/// Removes a bundle from the given archetype and returns the resulting archetype (or None if the
/// removal was invalid). in the event that adding the given bundle does not result in an Archetype
/// change. Results are cached in the Archetype Graph to avoid redundant work.
/// if `intersection` is false, attempting to remove a bundle with components _not_ contained in the
/// current archetype will fail, returning None. if `intersection` is true, components in the bundle
/// but not in the current archetype will be ignored
///
/// # Safety
/// `archetype_id` must exist and components in `bundle_info` must exist
unsafe fn remove_bundle_from_archetype(
@ -775,7 +790,8 @@ unsafe fn remove_bundle_from_archetype(
bundle_info: &BundleInfo,
intersection: bool,
) -> Option<ArchetypeId> {
// check the archetype graph to see if the Bundle has been removed from this archetype in the past
// check the archetype graph to see if the Bundle has been removed from this archetype in the
// past
let remove_bundle_result = {
// SAFE: entity location is valid and therefore the archetype exists
let current_archetype = archetypes.get_unchecked_mut(archetype_id);
@ -808,8 +824,9 @@ unsafe fn remove_bundle_from_archetype(
StorageType::SparseSet => removed_sparse_set_components.push(component_id),
}
} else if !intersection {
// a component in the bundle was not present in the entity's archetype, so this removal is invalid
// cache the result in the archetype graph
// a component in the bundle was not present in the entity's archetype, so this
// removal is invalid cache the result in the archetype
// graph
current_archetype
.edges_mut()
.set_remove_bundle(bundle_info.id, None);
@ -817,7 +834,8 @@ unsafe fn remove_bundle_from_archetype(
}
}
// sort removed components so we can do an efficient "sorted remove". archetype components are already sorted
// sort removed components so we can do an efficient "sorted remove". archetype
// components are already sorted
removed_table_components.sort();
removed_sparse_set_components.sort();
next_table_components = current_archetype.table_components().to_vec();

View file

@ -30,9 +30,10 @@ impl Default for WorldId {
}
}
/// [World] stores and exposes operations on [entities](Entity), [components](Component), and their associated metadata.
/// Each [Entity] has a set of components. Each component can have up to one instance of each component type.
/// Entity components can be created, updated, removed, and queried using a given [World].
/// [World] stores and exposes operations on [entities](Entity), [components](Component), and their
/// associated metadata. Each [Entity] has a set of components. Each component can have up to one
/// instance of each component type. Entity components can be created, updated, removed, and queried
/// using a given [World].
#[derive(Default)]
pub struct World {
id: WorldId,
@ -96,16 +97,17 @@ impl World {
&self.bundles
}
/// Retrieves a [WorldCell], which safely enables multiple mutable World accesses at the same time,
/// provided those accesses do not conflict with each other.
/// Retrieves a [WorldCell], which safely enables multiple mutable World accesses at the same
/// time, provided those accesses do not conflict with each other.
#[inline]
pub fn cell(&mut self) -> WorldCell<'_> {
WorldCell::new(self)
}
/// Registers a new component using the given [ComponentDescriptor]. Components do not need to be manually
/// registered. This just provides a way to override default configuration. Attempting to register a component
/// with a type that has already been used by [World] will result in an error.
/// Registers a new component using the given [ComponentDescriptor]. Components do not need to
/// be manually registered. This just provides a way to override default configuration.
/// Attempting to register a component with a type that has already been used by [World]
/// will result in an error.
///
/// The default component storage type can be overridden like this:
///
@ -269,7 +271,8 @@ impl World {
// PERF: consider avoiding allocating entities in the empty archetype unless needed
// SAFE: archetype tables always exist
let table = self.storages.tables.get_unchecked_mut(archetype.table_id());
// SAFE: no components are allocated by archetype.allocate() because the archetype is empty
// SAFE: no components are allocated by archetype.allocate() because the archetype is
// empty
let location = archetype.allocate(entity, table.allocate(entity));
// SAFE: entity index was just allocated
self.entities
@ -347,9 +350,9 @@ impl World {
self.get_entity_mut(entity)?.get_mut()
}
/// Despawns the given `entity`, if it exists. This will also remove all of the entity's [Component]s.
/// Returns `true` if the `entity` is successfully despawned and `false` if the `entity` does not exist.
/// ```
/// Despawns the given `entity`, if it exists. This will also remove all of the entity's
/// [Component]s. Returns `true` if the `entity` is successfully despawned and `false` if
/// the `entity` does not exist. ```
/// use bevy_ecs::world::World;
///
/// struct Position {
@ -391,7 +394,6 @@ impl World {
/// Returns [QueryState] for the given [WorldQuery], which is used to efficiently
/// run queries on the [World].
/// ```
///
/// use bevy_ecs::{entity::Entity, world::World};
///
/// #[derive(Debug, PartialEq)]
@ -450,7 +452,8 @@ impl World {
QueryState::new(self)
}
/// Returns an iterator of entities that had components of type `T` removed since the last call to [World::clear_trackers].
/// Returns an iterator of entities that had components of type `T` removed since the last call
/// to [World::clear_trackers].
pub fn removed<T: Component>(&self) -> std::iter::Cloned<std::slice::Iter<'_, Entity>> {
if let Some(component_id) = self.components.get_id(TypeId::of::<T>()) {
self.removed_with_id(component_id)
@ -459,7 +462,8 @@ impl World {
}
}
/// Returns an iterator of entities that had components with the given `component_id` removed since the last call to [World::clear_trackers].
/// Returns an iterator of entities that had components with the given `component_id` removed
/// since the last call to [World::clear_trackers].
pub fn removed_with_id(
&self,
component_id: ComponentId,
@ -501,8 +505,8 @@ impl World {
if column.is_empty() {
return None;
}
// SAFE: if a resource column exists, row 0 exists as well. caller takes ownership of the ptr value / drop is called when
// T is dropped
// SAFE: if a resource column exists, row 0 exists as well. caller takes ownership of the
// ptr value / drop is called when T is dropped
let (ptr, _) = unsafe { column.swap_remove_and_forget_unchecked(0) };
// SAFE: column is of type T
Some(unsafe { ptr.cast::<T>().read() })
@ -528,8 +532,8 @@ impl World {
unsafe { self.get_resource_with_id(component_id) }
}
/// Gets a mutable reference to the resource of the given type, if it exists. Otherwise returns [None]
/// Resources are "unique" data of a given type.
/// Gets a mutable reference to the resource of the given type, if it exists. Otherwise returns
/// [None] Resources are "unique" data of a given type.
#[inline]
pub fn get_resource_mut<T: Component>(&mut self) -> Option<Mut<'_, T>> {
// SAFE: unique world access
@ -537,7 +541,8 @@ impl World {
}
// PERF: optimize this to avoid redundant lookups
/// Gets a resource of type `T` if it exists, otherwise inserts the resource using the result of calling `func`.
/// Gets a resource of type `T` if it exists, otherwise inserts the resource using the result of
/// calling `func`.
#[inline]
pub fn get_resource_or_insert_with<T: Component>(
&mut self,
@ -549,19 +554,20 @@ impl World {
self.get_resource_mut().unwrap()
}
/// Gets a mutable reference to the resource of the given type, if it exists. Otherwise returns [None]
/// Resources are "unique" data of a given type.
/// Gets a mutable reference to the resource of the given type, if it exists. Otherwise returns
/// [None] Resources are "unique" data of a given type.
///
/// # Safety
/// This will allow aliased mutable access to the given resource type. The caller must ensure that only
/// one mutable access exists at a time.
/// This will allow aliased mutable access to the given resource type. The caller must ensure
/// that only one mutable access exists at a time.
#[inline]
pub unsafe fn get_resource_unchecked_mut<T: Component>(&self) -> Option<Mut<'_, T>> {
let component_id = self.components.get_resource_id(TypeId::of::<T>())?;
self.get_resource_unchecked_mut_with_id(component_id)
}
/// Gets a reference to the non-send resource of the given type, if it exists. Otherwise returns [None]
/// Resources are "unique" data of a given type.
/// Gets a reference to the non-send resource of the given type, if it exists. Otherwise returns
/// [None] Resources are "unique" data of a given type.
#[inline]
pub fn get_non_send_resource<T: 'static>(&self) -> Option<&T> {
let component_id = self.components.get_resource_id(TypeId::of::<T>())?;
@ -569,28 +575,29 @@ impl World {
unsafe { self.get_non_send_with_id(component_id) }
}
/// Gets a mutable reference to the non-send resource of the given type, if it exists. Otherwise returns [None]
/// Resources are "unique" data of a given type.
/// Gets a mutable reference to the non-send resource of the given type, if it exists. Otherwise
/// returns [None] Resources are "unique" data of a given type.
#[inline]
pub fn get_non_send_resource_mut<T: 'static>(&mut self) -> Option<Mut<'_, T>> {
// SAFE: unique world access
unsafe { self.get_non_send_resource_unchecked_mut() }
}
/// Gets a mutable reference to the non-send resource of the given type, if it exists. Otherwise returns [None]
/// Resources are "unique" data of a given type.
/// Gets a mutable reference to the non-send resource of the given type, if it exists. Otherwise
/// returns [None] Resources are "unique" data of a given type.
///
/// # Safety
/// This will allow aliased mutable access to the given non-send resource type. The caller must ensure that only
/// one mutable access exists at a time.
/// This will allow aliased mutable access to the given non-send resource type. The caller must
/// ensure that only one mutable access exists at a time.
#[inline]
pub unsafe fn get_non_send_resource_unchecked_mut<T: 'static>(&self) -> Option<Mut<'_, T>> {
let component_id = self.components.get_resource_id(TypeId::of::<T>())?;
self.get_non_send_unchecked_mut_with_id(component_id)
}
/// Temporarily removes the requested resource from this [World], then re-adds it before returning.
/// This enables safe mutable access to a resource while still providing mutable world access
/// ```
/// Temporarily removes the requested resource from this [World], then re-adds it before
/// returning. This enables safe mutable access to a resource while still providing mutable
/// world access ```
/// use bevy_ecs::world::{World, Mut};
/// struct A(u32);
/// struct B(u32);
@ -621,8 +628,8 @@ impl World {
if column.is_empty() {
panic!("resource does not exist");
}
// SAFE: if a resource column exists, row 0 exists as well. caller takes ownership of the ptr value / drop is called when
// T is dropped
// SAFE: if a resource column exists, row 0 exists as well. caller takes ownership of
// the ptr value / drop is called when T is dropped
unsafe { column.swap_remove_and_forget_unchecked(0) }
};
// SAFE: pointer is of type T
@ -801,7 +808,8 @@ impl World {
.get_unchecked_mut(empty_archetype.table_id());
// PERF: consider pre-allocating space for flushed entities
self.entities.flush(|entity, location| {
// SAFE: no components are allocated by archetype.allocate() because the archetype is empty
// SAFE: no components are allocated by archetype.allocate() because the archetype
// is empty
*location = empty_archetype.allocate(entity, table.allocate(entity));
});
}

View file

@ -41,7 +41,8 @@ impl<'w, T> Mut<'w, T> {
self.flags.contains(ComponentFlags::MUTATED)
}
/// Returns true if (and only if) this component been either mutated or added since the start of the frame.
/// Returns true if (and only if) this component been either mutated or added since the start of
/// the frame.
pub fn changed(&self) -> bool {
self.flags
.intersects(ComponentFlags::ADDED | ComponentFlags::MUTATED)

View file

@ -88,7 +88,8 @@ where
fn next(&mut self) -> Option<Entity> {
let bundle = self.inner.next()?;
let entity = self.entities.alloc();
// SAFE: component values are immediately written to relevant storages (which have been allocated)
// SAFE: component values are immediately written to relevant storages (which have been
// allocated)
unsafe {
let table_row = self.table.allocate(entity);
let location = self.archetype.allocate(entity, table_row);

View file

@ -11,8 +11,8 @@ use std::{
rc::Rc,
};
/// Exposes safe mutable access to multiple resources at a time in a World. Attempting to access World in a way that violates
/// Rust's mutability rules will panic thanks to runtime checks.
/// Exposes safe mutable access to multiple resources at a time in a World. Attempting to access
/// World in a way that violates Rust's mutability rules will panic thanks to runtime checks.
pub struct WorldCell<'w> {
pub(crate) world: &'w mut World,
pub(crate) access: Rc<RefCell<ArchetypeComponentAccess>>,

View file

@ -33,7 +33,8 @@ pub enum MouseScrollUnit {
Pixel,
}
/// A mouse scroll wheel event, where x represents horizontal scroll and y represents vertical scroll.
/// A mouse scroll wheel event, where x represents horizontal scroll and y represents vertical
/// scroll.
#[derive(Debug, Clone)]
pub struct MouseWheel {
pub unit: MouseScrollUnit,

View file

@ -79,7 +79,8 @@ pub fn lights_node_system(
mut state: Local<LightsNodeSystemState>,
render_resource_context: Res<Box<dyn RenderResourceContext>>,
ambient_light_resource: Res<AmbientLight>,
// TODO: this write on RenderResourceBindings will prevent this system from running in parallel with other systems that do the same
// TODO: this write on RenderResourceBindings will prevent this system from running in parallel
// with other systems that do the same
mut render_resource_bindings: ResMut<RenderResourceBindings>,
query: Query<(&Light, &GlobalTransform)>,
) {

View file

@ -4,8 +4,8 @@ use bevy_utils::HashMap;
use crate::{serde::Serializable, Reflect, ReflectMut, ReflectRef};
/// An ordered ReflectValue->ReflectValue mapping. ReflectValue Keys are assumed to return a non-None hash.
/// Ideally the ordering is stable across runs, but this is not required.
/// An ordered ReflectValue->ReflectValue mapping. ReflectValue Keys are assumed to return a
/// non-None hash. Ideally the ordering is stable across runs, but this is not required.
/// This corresponds to types like [std::collections::HashMap].
pub trait Map: Reflect {
fn get(&self, key: &dyn Reflect) -> Option<&dyn Reflect>;

View file

@ -31,11 +31,14 @@ pub trait Reflect: Any + Send + Sync {
fn reflect_ref(&self) -> ReflectRef;
fn reflect_mut(&mut self) -> ReflectMut;
fn clone_value(&self) -> Box<dyn Reflect>;
/// Returns a hash of the value (which includes the type) if hashing is supported. Otherwise `None` will be returned.
/// Returns a hash of the value (which includes the type) if hashing is supported. Otherwise
/// `None` will be returned.
fn reflect_hash(&self) -> Option<u64>;
/// Returns a "partial equal" comparison result if comparison is supported. Otherwise `None` will be returned.
/// Returns a "partial equal" comparison result if comparison is supported. Otherwise `None`
/// will be returned.
fn reflect_partial_eq(&self, _value: &dyn Reflect) -> Option<bool>;
/// Returns a serializable value, if serialization is supported. Otherwise `None` will be returned.
/// Returns a serializable value, if serialization is supported. Otherwise `None` will be
/// returned.
fn serializable(&self) -> Option<Serializable>;
}
@ -47,7 +50,8 @@ impl Debug for dyn Reflect {
impl dyn Reflect {
pub fn downcast<T: Reflect>(self: Box<dyn Reflect>) -> Result<Box<T>, Box<dyn Reflect>> {
// SAFE?: Same approach used by std::any::Box::downcast. ReflectValue is always Any and type has been checked.
// SAFE?: Same approach used by std::any::Box::downcast. ReflectValue is always Any and type
// has been checked.
if self.is::<T>() {
unsafe {
let raw: *mut dyn Reflect = Box::into_raw(self);

View file

@ -13,7 +13,8 @@ pub struct TypeRegistry {
ambiguous_names: HashSet<String>,
}
// TODO: remove this wrapper once we migrate to Atelier Assets and the Scene AssetLoader doesn't need a TypeRegistry ref
// TODO: remove this wrapper once we migrate to Atelier Assets and the Scene AssetLoader doesn't
// need a TypeRegistry ref
#[derive(Clone, Default)]
pub struct TypeRegistryArc {
pub internal: Arc<RwLock<TypeRegistry>>,

View file

@ -73,7 +73,8 @@ pub fn camera_system<T: CameraProjection + Component>(
)>,
) {
let mut changed_window_ids = Vec::new();
// handle resize events. latest events are handled first because we only want to resize each window once
// handle resize events. latest events are handled first because we only want to resize each
// window once
for event in window_resized_events.iter().rev() {
if changed_window_ids.contains(&event.id) {
continue;
@ -82,7 +83,8 @@ pub fn camera_system<T: CameraProjection + Component>(
changed_window_ids.push(event.id);
}
// handle resize events. latest events are handled first because we only want to resize each window once
// handle resize events. latest events are handled first because we only want to resize each
// window once
for event in window_created_events.iter().rev() {
if changed_window_ids.contains(&event.id) {
continue;

View file

@ -34,8 +34,8 @@ pub type Layer = u8;
/// Cameras with this component will only render entities with intersecting
/// layers.
///
/// There are 32 layers numbered `0` - [`TOTAL_LAYERS`](RenderLayers::TOTAL_LAYERS). Entities may belong to one or more
/// layers, or no layer at all.
/// There are 32 layers numbered `0` - [`TOTAL_LAYERS`](RenderLayers::TOTAL_LAYERS). Entities may
/// belong to one or more layers, or no layer at all.
///
/// The [`Default`] instance of `RenderLayers` contains layer `0`, the first layer.
///
@ -228,7 +228,8 @@ pub fn visible_entities_system(
let order = if let Ok(global_transform) = visible_transform_query.get(entity) {
let position = global_transform.translation;
// smaller distances are sorted to lower indices by using the distance from the camera
// smaller distances are sorted to lower indices by using the distance from the
// camera
FloatOrd(match camera.depth_calculation {
DepthCalculation::ZDifference => camera_position.z - position.z,
DepthCalculation::Distance => (camera_position - position).length_squared(),
@ -253,6 +254,7 @@ pub fn visible_entities_system(
transparent_entities.sort_by_key(|e| -e.order);
visible_entities.value.extend(transparent_entities);
// TODO: check for big changes in visible entities len() vs capacity() (ex: 2x) and resize to prevent holding unneeded memory
// TODO: check for big changes in visible entities len() vs capacity() (ex: 2x) and resize
// to prevent holding unneeded memory
}
}

View file

@ -13,7 +13,8 @@ use std::ops::{Add, AddAssign, Mul, MulAssign};
// TODO: Separate types for non-linear sRGB and linear sRGB, with conversions between
// see comment on bevy issue #688 https://github.com/bevyengine/bevy/pull/688#issuecomment-711414011
/// RGBA color in the Linear sRGB colorspace (often colloquially referred to as "linear", "RGB", or "linear RGB").
/// RGBA color in the Linear sRGB colorspace (often colloquially referred to as "linear", "RGB", or
/// "linear RGB").
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)]
#[reflect(PartialEq, Serialize, Deserialize)]

View file

@ -3,7 +3,7 @@ pub trait SrgbColorSpace {
fn nonlinear_to_linear_srgb(self) -> Self;
}
//source: https://entropymine.com/imageworsener/srgbformula/
// source: https://entropymine.com/imageworsener/srgbformula/
impl SrgbColorSpace for f32 {
fn linear_to_nonlinear_srgb(self) -> f32 {
if self <= 0.0 {
@ -13,7 +13,7 @@ impl SrgbColorSpace for f32 {
if self <= 0.0031308 {
self * 12.92 // linear falloff in dark values
} else {
(1.055 * self.powf(1.0 / 2.4)) - 0.055 //gamma curve in other area
(1.055 * self.powf(1.0 / 2.4)) - 0.055 // gamma curve in other area
}
}
@ -24,7 +24,7 @@ impl SrgbColorSpace for f32 {
if self <= 0.04045 {
self / 12.92 // linear falloff in dark values
} else {
((self + 0.055) / 1.055).powf(2.4) //gamma curve in other area
((self + 0.055) / 1.055).powf(2.4) // gamma curve in other area
}
}
}

View file

@ -277,7 +277,8 @@ impl<'a> DrawContext<'a> {
}
}
// if none of the given RenderResourceBindings have the current bind group, try their assets
// if none of the given RenderResourceBindings have the current bind group, try their
// assets
let asset_render_resource_bindings =
if let Some(value) = asset_render_resource_bindings.as_mut() {
value

View file

@ -68,7 +68,8 @@ pub enum RenderSystem {
pub enum RenderStage {
/// Stage where render resources are set up
RenderResource,
/// Stage where Render Graph systems are run. In general you shouldn't add systems to this stage manually.
/// Stage where Render Graph systems are run. In general you shouldn't add systems to this
/// stage manually.
RenderGraphSystems,
// Stage where draw systems are executed. This is generally where Draw components are setup
Draw,
@ -78,7 +79,8 @@ pub enum RenderStage {
/// Adds core render types and systems to an App
pub struct RenderPlugin {
/// configures the "base render graph". If this is not `None`, the "base render graph" will be added
/// configures the "base render graph". If this is not `None`, the "base render graph" will be
/// added
pub base_render_graph_config: Option<BaseRenderGraphConfig>,
}

View file

@ -208,7 +208,8 @@ impl From<&Indices> for IndexFormat {
#[uuid = "8ecbac0f-f545-4473-ad43-e1f4243af51e"]
pub struct Mesh {
primitive_topology: PrimitiveTopology,
/// `bevy_utils::HashMap` with all defined vertex attributes (Positions, Normals, ...) for this mesh. Attribute name maps to attribute values.
/// `bevy_utils::HashMap` with all defined vertex attributes (Positions, Normals, ...) for this
/// mesh. Attribute name maps to attribute values.
attributes: HashMap<Cow<'static, str>, VertexAttributeValues>,
indices: Option<Indices>,
}
@ -233,7 +234,8 @@ pub struct Mesh {
impl Mesh {
/// Per vertex coloring. Use in conjunction with [`Mesh::set_attribute`]
pub const ATTRIBUTE_COLOR: &'static str = "Vertex_Color";
/// The direction the vertex normal is facing in. Use in conjunction with [`Mesh::set_attribute`]
/// The direction the vertex normal is facing in. Use in conjunction with
/// [`Mesh::set_attribute`]
pub const ATTRIBUTE_NORMAL: &'static str = "Vertex_Normal";
/// Where the vertex is located in space. Use in conjunction with [`Mesh::set_attribute`]
pub const ATTRIBUTE_POSITION: &'static str = "Vertex_Position";
@ -279,7 +281,8 @@ impl Mesh {
}
/// Indices describe how triangles are constructed out of the vertex attributes.
/// They are only useful for the [`crate::pipeline::PrimitiveTopology`] variants that use triangles
/// They are only useful for the [`crate::pipeline::PrimitiveTopology`] variants that use
/// triangles
pub fn set_indices(&mut self, indices: Option<Indices>) {
self.indices = indices;
}

View file

@ -39,7 +39,8 @@ pub enum CapsuleUvProfile {
Aspect,
/// Hemispheres get UV space according to the ratio of latitudes to rings.
Uniform,
/// Upper third of the texture goes to the northern hemisphere, middle third to the cylinder and lower third to the southern one.
/// Upper third of the texture goes to the northern hemisphere, middle third to the cylinder
/// and lower third to the southern one.
Fixed,
}

View file

@ -30,8 +30,8 @@ pub enum BindType {
readonly: bool,
},
Sampler {
/// The sampling result is produced based on more than a single color sample from a texture,
/// e.g. when bilinear interpolation is enabled.
/// The sampling result is produced based on more than a single color sample from a
/// texture, e.g. when bilinear interpolation is enabled.
///
/// A filtering sampler can only be used with a filterable texture.
filtering: bool,

View file

@ -197,7 +197,8 @@ impl PipelineCompiler {
}
specialized_descriptor.layout = Some(layout);
// create a vertex layout that provides all attributes from either the specialized vertex buffers or a zero buffer
// create a vertex layout that provides all attributes from either the specialized vertex
// buffers or a zero buffer
let mut pipeline_layout = specialized_descriptor.layout.as_mut().unwrap();
// the vertex buffer descriptor of the mesh
let mesh_vertex_buffer_layout = &pipeline_specialization.vertex_buffer_layout;
@ -235,7 +236,7 @@ impl PipelineCompiler {
}
}
//TODO: add other buffers (like instancing) here
// TODO: add other buffers (like instancing) here
let mut vertex_buffer_descriptors = Vec::<VertexBufferLayout>::default();
if !pipeline_layout.vertex_buffer_descriptors.is_empty() {
vertex_buffer_descriptors.push(compiled_vertex_buffer_descriptor);

View file

@ -58,8 +58,8 @@ impl PipelineLayout {
.map(|(_, value)| value)
.collect::<Vec<BindGroupDescriptor>>();
// NOTE: for some reason bind groups need to be sorted by index. this is likely an issue with bevy and not with wgpu
// TODO: try removing this
// NOTE: for some reason bind groups need to be sorted by index. this is likely an issue
// with bevy and not with wgpu TODO: try removing this
bind_groups_result.sort_by(|a, b| a.index.partial_cmp(&b.index).unwrap());
PipelineLayout {

View file

@ -17,7 +17,8 @@ use bevy_utils::HashSet;
pub struct RenderPipeline {
pub pipeline: Handle<PipelineDescriptor>,
pub specialization: PipelineSpecialization,
/// used to track if PipelineSpecialization::dynamic_bindings is in sync with RenderResourceBindings
/// used to track if PipelineSpecialization::dynamic_bindings is in sync with
/// RenderResourceBindings
pub dynamic_bindings_generation: usize,
}

View file

@ -92,9 +92,9 @@ impl Default for BaseRenderGraphConfig {
}
}
/// The "base render graph" provides a core set of render graph nodes which can be used to build any graph.
/// By itself this graph doesn't do much, but it allows Render plugins to interop with each other by having a common
/// set of nodes. It can be customized using `BaseRenderGraphConfig`.
/// The "base render graph" provides a core set of render graph nodes which can be used to build any
/// graph. By itself this graph doesn't do much, but it allows Render plugins to interop with each
/// other by having a common set of nodes. It can be customized using `BaseRenderGraphConfig`.
pub(crate) fn add_base_graph(config: &BaseRenderGraphConfig, world: &mut World) {
let world = world.cell();
let mut graph = world.get_resource_mut::<RenderGraph>().unwrap();
@ -124,7 +124,8 @@ pub(crate) fn add_base_graph(config: &BaseRenderGraphConfig, world: &mut World)
mip_level_count: 1,
sample_count: msaa.samples,
dimension: TextureDimension::D2,
format: TextureFormat::Depth32Float, // PERF: vulkan docs recommend using 24 bit depth for better performance
format: TextureFormat::Depth32Float, /* PERF: vulkan docs recommend using 24
* bit depth for better performance */
usage: TextureUsage::OUTPUT_ATTACHMENT,
},
),

View file

@ -47,7 +47,8 @@ pub enum Command {
#[derive(Debug, Default, Clone)]
pub struct CommandQueue {
// TODO: this shouldn't really need a mutex. it just needs to be shared on whatever thread it's scheduled on
// TODO: this shouldn't really need a mutex. it just needs to be shared on whatever thread it's
// scheduled on
queue: Arc<Mutex<Vec<Command>>>,
}

View file

@ -28,10 +28,12 @@ pub trait Node: Downcast + Send + Sync + 'static {
&[]
}
/// Prepare the graph node with unique world access. This runs once per graph run before [Node::update] is called.
/// Prepare the graph node with unique world access. This runs once per graph run before
/// [Node::update] is called.
fn prepare(&mut self, _world: &mut World) {}
/// Run the graph node logic. This runs once per graph run after [Node::prepare] has been called on all nodes.
/// Run the graph node logic. This runs once per graph run after [Node::prepare] has been called
/// on all nodes.
fn update(
&mut self,
world: &World,

View file

@ -70,8 +70,8 @@ pub fn camera_node_system(
mut state: Local<CameraNodeState>,
active_cameras: Res<ActiveCameras>,
render_resource_context: Res<Box<dyn RenderResourceContext>>,
// PERF: this write on RenderResourceAssignments will prevent this system from running in parallel
// with other systems that do the same
// PERF: this write on RenderResourceAssignments will prevent this system from running in
// parallel with other systems that do the same
mut render_resource_bindings: ResMut<RenderResourceBindings>,
query: Query<(&Camera, &GlobalTransform)>,
) {

View file

@ -182,7 +182,8 @@ where
self.current_staging_buffer_offset = 0;
}
/// Find a spot for the given RenderResources in each uniform's BufferArray and prepare space in the staging buffer
/// Find a spot for the given RenderResources in each uniform's BufferArray and prepare space in
/// the staging buffer
fn prepare_uniform_buffers(&mut self, id: I, render_resources: &T) {
for (i, render_resource) in render_resources.iter().enumerate() {
if let Some(RenderResourceType::Buffer) = render_resource.resource_type() {
@ -497,7 +498,8 @@ fn render_resources_node_system<T: RenderResources>(
staging_buffer,
0..state.uniform_buffer_arrays.staging_buffer_size as u64,
&mut |mut staging_buffer, _render_resource_context| {
// if the buffer array was resized, write all entities to the new buffer, otherwise only write changes
// if the buffer array was resized, write all entities to the new buffer, otherwise
// only write changes
if resized {
for (entity, uniforms, visible, mut render_pipelines) in
queries.q1_mut().iter_mut()

View file

@ -67,7 +67,8 @@ impl Stages {
}
pub fn borrow<'a>(&self, render_graph: &'a mut RenderGraph) -> Vec<StageBorrow<'a>> {
// unfortunately borrowing render graph nodes in a specific order takes a little bit of gymnastics
// unfortunately borrowing render graph nodes in a specific order takes a little bit of
// gymnastics
let mut stage_borrows = Vec::with_capacity(self.stages.len());
let mut node_borrows = Vec::new();
@ -101,13 +102,15 @@ impl Stages {
}
}
/// Produces a collection of `Stages`, which are sets of OrderedJobs that must be run before moving on to the next stage
/// Produces a collection of `Stages`, which are sets of OrderedJobs that must be run before moving
/// on to the next stage
pub trait RenderGraphStager {
fn get_stages(&mut self, render_graph: &RenderGraph) -> Result<Stages, RenderGraphError>;
}
// TODO: remove this
/// This scheduler ignores dependencies and puts everything in one stage. It shouldn't be used for anything :)
/// This scheduler ignores dependencies and puts everything in one stage. It shouldn't be used for
/// anything :)
#[derive(Debug, Default)]
pub struct LinearStager;
@ -229,8 +232,9 @@ fn stage_node(
})
.count();
// if the current node has more than one parent on the highest stage (aka requires synchronization), then move it to the next
// stage and start a new job on that stage
// if the current node has more than one parent on the highest stage (aka requires
// synchronization), then move it to the next stage and start a new job on that
// stage
if max_stage_parent_count > 1 {
stage_index = max_parent_stage + 1;
} else {
@ -492,7 +496,8 @@ mod tests {
assert_eq!(job.nodes.len(), 7, "expect exactly 7 nodes in the job");
// its hard to test the exact order of this job's nodes because of hashing, so instead we'll test the constraints that must hold true
// its hard to test the exact order of this job's nodes because of hashing, so instead we'll
// test the constraints that must hold true
let index =
|node_id: NodeId| -> usize { job.nodes.iter().position(|id| *id == node_id).unwrap() };

View file

@ -61,13 +61,15 @@ pub enum BindGroupStatus {
NoMatch,
}
// PERF: if the bindings are scoped to a specific pipeline layout, then names could be replaced with indices here for a perf boost
// PERF: if the bindings are scoped to a specific pipeline layout, then names could be replaced with
// indices here for a perf boost
#[derive(Eq, PartialEq, Debug, Default, Clone)]
pub struct RenderResourceBindings {
pub bindings: HashMap<String, RenderResourceBinding>,
/// A Buffer that contains all attributes a mesh has defined
pub vertex_attribute_buffer: Option<BufferId>,
/// A Buffer that is filled with zeros that will be used for attributes required by the shader, but undefined by the mesh.
/// A Buffer that is filled with zeros that will be used for attributes required by the shader,
/// but undefined by the mesh.
pub vertex_fallback_buffer: Option<BufferId>,
pub index_buffer: Option<(BufferId, IndexFormat)>,
assets: HashSet<(HandleUntyped, TypeId)>,
@ -87,7 +89,8 @@ impl RenderResourceBindings {
self.bindings.insert(name.to_string(), binding);
}
/// The current "generation" of dynamic bindings. This number increments every time a dynamic binding changes
/// The current "generation" of dynamic bindings. This number increments every time a dynamic
/// binding changes
pub fn dynamic_bindings_generation(&self) -> usize {
self.dynamic_bindings_generation
}
@ -182,8 +185,9 @@ impl RenderResourceBindings {
Some(bind_group)
}
BindGroupStatus::Unchanged(id) => {
// PERF: this is only required because RenderResourceContext::remove_stale_bind_groups doesn't inform RenderResourceBindings
// when a stale bind group has been removed
// PERF: this is only required because
// RenderResourceContext::remove_stale_bind_groups doesn't inform
// RenderResourceBindings when a stale bind group has been removed
let bind_group = self
.get_bind_group(id)
.expect("`RenderResourceSet` was just changed, so it should exist.");

View file

@ -77,13 +77,16 @@ pub trait RenderResourceContext: Downcast + Send + Sync + 'static {
fn remove_stale_bind_groups(&self);
/// Reflects the pipeline layout from its shaders.
///
/// If `bevy_conventions` is true, it will be assumed that the shader follows "bevy shader conventions". These allow
/// richer reflection, such as inferred Vertex Buffer names and inferred instancing.
/// If `bevy_conventions` is true, it will be assumed that the shader follows "bevy shader
/// conventions". These allow richer reflection, such as inferred Vertex Buffer names and
/// inferred instancing.
///
/// If `dynamic_bindings` has values, shader uniforms will be set to "dynamic" if there is a matching binding in the list
/// If `dynamic_bindings` has values, shader uniforms will be set to "dynamic" if there is a
/// matching binding in the list
///
/// If `vertex_buffer_descriptors` is set, the pipeline's vertex buffers
/// will inherit their layouts from global descriptors, otherwise the layout will be assumed to be complete / local.
/// will inherit their layouts from global descriptors, otherwise the layout will be assumed to
/// be complete / local.
fn reflect_pipeline_layout(
&self,
shaders: &Assets<Shader>,

View file

@ -4,7 +4,8 @@ use crate::{pipeline::RenderPipelines, Texture};
pub use bevy_derive::ShaderDefs;
use bevy_ecs::system::{Query, Res};
/// Something that can either be "defined" or "not defined". This is used to determine if a "shader def" should be considered "defined"
/// Something that can either be "defined" or "not defined". This is used to determine if a "shader
/// def" should be considered "defined"
pub trait ShaderDef {
fn is_defined(&self) -> bool;
}

View file

@ -101,7 +101,8 @@ impl Texture {
.resize(size.volume() * self.format.pixel_size(), 0);
}
/// Changes the `size`, asserting that the total number of data elements (pixels) remains the same.
/// Changes the `size`, asserting that the total number of data elements (pixels) remains the
/// same.
pub fn reinterpret_size(&mut self, new_size: Extent3d) {
assert!(
new_size.volume() == self.size.volume(),
@ -113,9 +114,9 @@ impl Texture {
self.size = new_size;
}
/// Takes a 2D texture containing vertically stacked images of the same size, and reinterprets it as a 2D array texture,
/// where each of the stacked images becomes one layer of the array. This is primarily for use with the `texture2DArray`
/// shader uniform type.
/// Takes a 2D texture containing vertically stacked images of the same size, and reinterprets
/// it as a 2D array texture, where each of the stacked images becomes one layer of the
/// array. This is primarily for use with the `texture2DArray` shader uniform type.
pub fn reinterpret_stacked_2d_as_array(&mut self, layers: u32) {
// Must be a stacked image, and the height must be divisible by layers.
assert!(self.dimension == TextureDimension::D2);
@ -171,8 +172,9 @@ impl Texture {
}
AssetEvent::Removed { handle } => {
Self::remove_current_texture_resources(render_resource_context, handle);
// if texture was modified and removed in the same update, ignore the modification
// events are ordered so future modification events are ok
// if texture was modified and removed in the same update, ignore the
// modification events are ordered so future modification
// events are ok
changed_textures.remove(handle);
}
}
@ -217,7 +219,8 @@ impl Texture {
}
}
/// Load a bytes buffer in a [`Texture`], according to type `image_type`, using the `image` crate`
/// Load a bytes buffer in a [`Texture`], according to type `image_type`, using the `image`
/// crate`
pub fn from_buffer(buffer: &[u8], image_type: ImageType) -> Result<Texture, TextureError> {
let format = match image_type {
ImageType::MimeType(mime_type) => match mime_type {

View file

@ -95,7 +95,8 @@ pub struct PixelInfo {
/// Underlying texture data format.
///
/// If there is a conversion in the format (such as srgb -> linear), The conversion listed is for
/// loading from texture in a shader. When writing to the texture, the opposite conversion takes place.
/// loading from texture in a shader. When writing to the texture, the opposite conversion takes
/// place.
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub enum TextureFormat {
// Normal 8 bit formats

View file

@ -81,7 +81,8 @@ impl SceneSpawner {
for instance_id in instance_ids {
if let Some(instance) = self.spawned_instances.get(&instance_id) {
for entity in instance.entity_map.values() {
let _ = world.despawn(entity); // Ignore the result, despawn only cares if it exists.
let _ = world.despawn(entity); // Ignore the result, despawn only cares if
// it exists.
}
}
}

View file

@ -51,8 +51,8 @@ impl DynamicTextureAtlasBuilder {
// let change_list = self.atlas_allocator.resize_and_rearrange(new_size2);
// for change in change_list.changes {
// if let Some(changed_texture_handle) = self.allocation_textures.remove(&change.old.id) {
// let changed_texture = textures.get(&changed_texture_handle).unwrap();
// if let Some(changed_texture_handle) = self.allocation_textures.remove(&change.old.id)
// { let changed_texture = textures.get(&changed_texture_handle).unwrap();
// self.place_texture(change.new, changed_texture_handle, changed_texture);
// }
// }

View file

@ -68,7 +68,8 @@ impl Plugin for SpritePlugin {
color_materials.set_untracked(Handle::<ColorMaterial>::default(), ColorMaterial::default());
meshes.set_untracked(
QUAD_HANDLE,
// Use a flipped quad because the camera is facing "forward" but quads should face backward
// Use a flipped quad because the camera is facing "forward" but quads should face
// backward
Mesh::from(shape::Quad::new(Vec2::new(1.0, 1.0))),
)
}

View file

@ -1,7 +1,8 @@
use bevy_core::Byteable;
use bevy_math::Vec2;
/// A rectangle defined by two points. There is no defined origin, so 0,0 could be anywhere (top-left, bottom-left, etc)
/// A rectangle defined by two points. There is no defined origin, so 0,0 could be anywhere
/// (top-left, bottom-left, etc)
#[repr(C)]
#[derive(Default, Clone, Copy, Debug)]
pub struct Rect {

View file

@ -86,7 +86,8 @@ pub fn sprite_system(
if let Some(ref texture_handle) = material.texture {
if let Some(texture) = textures.get(texture_handle) {
let texture_size = texture.size.as_vec3().truncate();
// only set sprite size if it has changed (this check prevents change detection from triggering)
// only set sprite size if it has changed (this check prevents change
// detection from triggering)
if sprite.size != texture_size {
sprite.size = texture_size;
}

View file

@ -114,7 +114,8 @@ pub fn event_resets_if_listeners_are_cleared() {
event.notify(std::usize::MAX);
futures_lite::future::block_on(listener1);
// If all listeners are notified, the structure should now be cleared. We're free to listen again
// If all listeners are notified, the structure should now be cleared. We're free to listen
// again
let listener2 = event.listen();
let listener3 = event.listen();

View file

@ -381,7 +381,8 @@ where
.max_by_key(f)
}
/// Returns the item that gives the maximum value with respect to the specified comparison function.
/// Returns the item that gives the maximum value with respect to the specified comparison
/// function.
///
/// See [`Iterator::max_by()`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.max_by)
fn max_by<F>(mut self, pool: &TaskPool, f: F) -> Option<Self::Item>
@ -420,7 +421,8 @@ where
.min_by_key(f)
}
/// Returns the item that gives the minimum value with respect to the specified comparison function.
/// Returns the item that gives the minimum value with respect to the specified comparison
/// function.
///
/// See [`Iterator::min_by()`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.min_by)
fn min_by<F>(mut self, pool: &TaskPool, f: F) -> Option<Self::Item>

View file

@ -22,7 +22,8 @@ impl<T> Task<T> {
Self(task)
}
/// Detaches the task to let it keep running in the background. See `async_executor::Task::detach`
/// Detaches the task to let it keep running in the background. See
/// `async_executor::Task::detach`
pub fn detach(self) {
self.0.detach();
}

View file

@ -86,8 +86,8 @@ pub struct TaskPool {
/// The executor for the pool
///
/// This has to be separate from TaskPoolInner because we have to create an Arc<Executor> to
/// pass into the worker threads, and we must create the worker threads before we can create the
/// Vec<Task<T>> contained within TaskPoolInner
/// pass into the worker threads, and we must create the worker threads before we can create
/// the Vec<Task<T>> contained within TaskPoolInner
executor: Arc<async_executor::Executor<'static>>,
/// Inner state of the pool
@ -200,17 +200,18 @@ impl TaskPool {
// Pin the futures on the stack.
pin!(fut);
// SAFETY: This function blocks until all futures complete, so we do not read/write the
// data from futures outside of the 'scope lifetime. However, rust has no way of knowing
// this so we must convert to 'static here to appease the compiler as it is unable to
// validate safety.
// SAFETY: This function blocks until all futures complete, so we do not read/write
// the data from futures outside of the 'scope lifetime. However,
// rust has no way of knowing this so we must convert to 'static
// here to appease the compiler as it is unable to validate safety.
let fut: Pin<&mut (dyn Future<Output = Vec<T>>)> = fut;
let fut: Pin<&'static mut (dyn Future<Output = Vec<T>> + 'static)> =
unsafe { mem::transmute(fut) };
// The thread that calls scope() will participate in driving tasks in the pool forward
// until the tasks that are spawned by this scope() call complete. (If the caller of scope()
// happens to be a thread in this thread pool, and we only have one thread in the pool, then
// The thread that calls scope() will participate in driving tasks in the pool
// forward until the tasks that are spawned by this scope() call
// complete. (If the caller of scope() happens to be a thread in
// this thread pool, and we only have one thread in the pool, then
// simply calling future::block_on(spawned) would deadlock.)
let mut spawned = local_executor.spawn(fut);
loop {
@ -376,7 +377,8 @@ mod tests {
scope.spawn_local(async move {
inner_count_clone.fetch_add(1, Ordering::Release);
if std::thread::current().id() != spawner {
// NOTE: This check is using an atomic rather than simply panicing the thread to avoid deadlocking the barrier on failure
// NOTE: This check is using an atomic rather than simply panicing the
// thread to avoid deadlocking the barrier on failure
inner_thread_check_failed.store(true, Ordering::Release);
}
});

View file

@ -171,7 +171,8 @@ pub fn text2d_system(
&mut *textures,
) {
Err(TextError::NoSuchFont) => {
// There was an error processing the text layout, let's add this entity to the queue for further processing
// There was an error processing the text layout, let's add this entity to the
// queue for further processing
new_queue.push(entity);
}
Err(e @ TextError::FailedToAddGlyph(_)) => {

View file

@ -63,7 +63,8 @@ impl GlobalTransform {
}
}
/// Returns transform with the same translation and scale, but rotation so that transform.forward() points at target
/// Returns transform with the same translation and scale, but rotation so that
/// transform.forward() points at target
#[inline]
pub fn looking_at(mut self, target: Vec3, up: Vec3) -> Self {
self.look_at(target, up);

View file

@ -12,8 +12,8 @@ pub struct Parent(pub Entity);
// TODO: We need to impl either FromWorld or Default so Parent can be registered as Properties.
// This is because Properties deserialize by creating an instance and apply a patch on top.
// However Parent should only ever be set with a real user-defined entity. Its worth looking into better
// ways to handle cases like this.
// However Parent should only ever be set with a real user-defined entity. Its worth looking into
// better ways to handle cases like this.
impl FromWorld for Parent {
fn from_world(_world: &mut World) -> Self {
Parent(Entity::new(u32::MAX))

View file

@ -63,7 +63,8 @@ impl Transform {
}
}
/// Returns transform with the same translation and scale, but rotation so that transform.forward() points at target
/// Returns transform with the same translation and scale, but rotation so that
/// transform.forward() points at target
#[inline]
pub fn looking_at(mut self, target: Vec3, up: Vec3) -> Self {
self.look_at(target, up);

View file

@ -29,7 +29,8 @@ impl Command for InsertChildren {
added = true;
}
// NOTE: ideally this is just an else statement, but currently that _incorrectly_ fails borrow-checking
// NOTE: ideally this is just an else statement, but currently that _incorrectly_ fails
// borrow-checking
if !added {
world
.entity_mut(self.parent)
@ -64,7 +65,8 @@ impl Command for PushChildren {
added = true;
}
// NOTE: ideally this is just an else statement, but currently that _incorrectly_ fails borrow-checking
// NOTE: ideally this is just an else statement, but currently that _incorrectly_ fails
// borrow-checking
if !added {
world
.entity_mut(self.parent)
@ -270,8 +272,8 @@ impl<'w> BuildWorldChildren for EntityMut<'w> {
let mut builder = WorldChildBuilder {
current_entity: None,
parent_entities: vec![entity],
// SAFE: self.update_location() is called below. It is impossible to make EntityMut function calls on `self`
// within the scope defined here
// SAFE: self.update_location() is called below. It is impossible to make EntityMut
// function calls on `self` within the scope defined here
world: unsafe { self.world_mut() },
};

View file

@ -106,7 +106,8 @@ mod tests {
{
let mut commands = Commands::new(&mut queue, &world);
commands.despawn_recursive(parent_entity);
commands.despawn_recursive(parent_entity); // despawning the same entity twice should not panic
commands.despawn_recursive(parent_entity); // despawning the same entity twice should
// not panic
}
queue.apply(&mut world);

View file

@ -10,8 +10,8 @@ use smallvec::SmallVec;
pub fn parent_update_system(
mut commands: Commands,
removed_parent_query: Query<(Entity, &PreviousParent), Without<Parent>>,
// The next query could be run with a Changed<Parent> filter. However, this would mean that modifications later in the frame are lost.
// See issue 891: https://github.com/bevyengine/bevy/issues/891
// The next query could be run with a Changed<Parent> filter. However, this would mean that
// modifications later in the frame are lost. See issue 891: https://github.com/bevyengine/bevy/issues/891
mut parent_query: Query<(Entity, &Parent, Option<&mut PreviousParent>)>,
mut children_query: Query<&mut Children>,
) {

View file

@ -93,7 +93,8 @@ pub fn ui_focus_system(
let extents = node.size / 2.0;
let min = ui_position - extents;
let max = ui_position + extents;
// if the current cursor position is within the bounds of the node, consider it for clicking
// if the current cursor position is within the bounds of the node, consider it for
// clicking
if (min.x..max.x).contains(&cursor_position.x)
&& (min.y..max.y).contains(&cursor_position.y)
{
@ -120,7 +121,8 @@ pub fn ui_focus_system(
// only consider nodes with Interaction "clickable"
if *interaction != Interaction::Clicked {
*interaction = Interaction::Clicked;
// if the mouse was simultaneously released, reset this Interaction in the next frame
// if the mouse was simultaneously released, reset this Interaction in the next
// frame
if mouse_released {
state.entities_to_reset.push(entity);
}

View file

@ -105,7 +105,8 @@ pub fn text_system(
&mut *textures,
) {
Err(TextError::NoSuchFont) => {
// There was an error processing the text layout, let's add this entity to the queue for further processing
// There was an error processing the text layout, let's add this entity to the
// queue for further processing
new_queue.push(entity);
}
Err(e @ TextError::FailedToAddGlyph(_)) => {

View file

@ -66,8 +66,9 @@ impl WgpuRenderContext {
}
}
/// Consume this context, finalize the current CommandEncoder (if it exists), and take the current WgpuResources.
/// This is intended to be called from a worker thread right before synchronizing with the main thread.
/// Consume this context, finalize the current CommandEncoder (if it exists), and take the
/// current WgpuResources. This is intended to be called from a worker thread right before
/// synchronizing with the main thread.
pub fn finish(&mut self) -> Option<wgpu::CommandBuffer> {
self.command_encoder.take().map(|encoder| encoder.finish())
}

View file

@ -17,27 +17,32 @@ pub struct WgpuBindGroupInfo {
}
/// Grabs a read lock on all wgpu resources. When paired with WgpuResourceRefs, this allows
/// you to pass in wgpu resources to wgpu::RenderPass<'a> with the appropriate lifetime. This is accomplished by
/// grabbing a WgpuResourcesReadLock _before_ creating a wgpu::RenderPass, getting a WgpuResourcesRefs, and storing that
/// in the pass.
/// you to pass in wgpu resources to wgpu::RenderPass<'a> with the appropriate lifetime. This is
/// accomplished by grabbing a WgpuResourcesReadLock _before_ creating a wgpu::RenderPass, getting a
/// WgpuResourcesRefs, and storing that in the pass.
///
/// This is only a problem because RwLockReadGuard.read() erases the guard's lifetime and creates a new anonymous lifetime. If
/// you call RwLockReadGuard.read() during a pass, the reference will have an anonymous lifetime that lives for less than the
/// pass, which violates the lifetime constraints in place.
/// This is only a problem because RwLockReadGuard.read() erases the guard's lifetime and creates a
/// new anonymous lifetime. If you call RwLockReadGuard.read() during a pass, the reference will
/// have an anonymous lifetime that lives for less than the pass, which violates the lifetime
/// constraints in place.
///
/// The biggest implication of this design (other than the additional boilerplate here) is that beginning a render pass
/// blocks writes to these resources. This means that if the pass attempts to write any resource, a deadlock will occur. WgpuResourceRefs
/// only has immutable references, so the only way to make a deadlock happen is to access WgpuResources directly in the pass. It also means
/// that other threads attempting to write resources will need to wait for pass encoding to finish. Almost all writes should occur before
/// passes start, so this hopefully won't be a problem.
/// The biggest implication of this design (other than the additional boilerplate here) is that
/// beginning a render pass blocks writes to these resources. This means that if the pass attempts
/// to write any resource, a deadlock will occur. WgpuResourceRefs only has immutable references, so
/// the only way to make a deadlock happen is to access WgpuResources directly in the pass. It also
/// means that other threads attempting to write resources will need to wait for pass encoding to
/// finish. Almost all writes should occur before passes start, so this hopefully won't be a
/// problem.
///
/// It is worth comparing the performance of this to transactional / copy-based approaches. This lock based design guarantees
/// consistency, doesn't perform redundant allocations, and only blocks when a write is occurring. A copy based approach would
/// never block, but would require more allocations / state-synchronization, which I expect will be more expensive. It would also be
/// It is worth comparing the performance of this to transactional / copy-based approaches. This
/// lock based design guarantees consistency, doesn't perform redundant allocations, and only blocks
/// when a write is occurring. A copy based approach would never block, but would require more
/// allocations / state-synchronization, which I expect will be more expensive. It would also be
/// "eventually consistent" instead of "strongly consistent".
///
/// Single threaded implementations don't need to worry about these lifetimes constraints at all. RenderPasses can use a RenderContext's
/// WgpuResources directly. RenderContext already has a lifetime greater than the RenderPass.
/// Single threaded implementations don't need to worry about these lifetimes constraints at all.
/// RenderPasses can use a RenderContext's WgpuResources directly. RenderContext already has a
/// lifetime greater than the RenderPass.
#[derive(Debug)]
pub struct WgpuResourcesReadLock<'a> {
pub buffers: RwLockReadGuard<'a, HashMap<BufferId, Arc<wgpu::Buffer>>>,
@ -62,7 +67,8 @@ impl<'a> WgpuResourcesReadLock<'a> {
}
}
/// Stores read only references to WgpuResource collections. See WgpuResourcesReadLock docs for context on why this exists
/// Stores read only references to WgpuResource collections. See WgpuResourcesReadLock docs for
/// context on why this exists
#[derive(Debug)]
pub struct WgpuResourceRefs<'a> {
pub buffers: &'a HashMap<BufferId, Arc<wgpu::Buffer>>,

View file

@ -30,8 +30,8 @@ pub struct WindowCreated {
pub id: WindowId,
}
/// An event that is sent whenever a close was requested for a window. For example: when the "close" button
/// is pressed on a window.
/// An event that is sent whenever a close was requested for a window. For example: when the "close"
/// button is pressed on a window.
#[derive(Debug, Clone)]
pub struct WindowCloseRequested {
pub id: WindowId,

View file

@ -304,13 +304,15 @@ impl Window {
/// Modifies the position of the window in physical pixels.
///
/// Note that the top-left hand corner of the desktop is not necessarily the same as the screen. If the user uses a desktop with multiple monitors,
/// the top-left hand corner of the desktop is the top-left hand corner of the monitor at the top-left of the desktop. This automatically un-maximizes
/// the window if it's maximized.
/// Note that the top-left hand corner of the desktop is not necessarily the same as the screen.
/// If the user uses a desktop with multiple monitors, the top-left hand corner of the
/// desktop is the top-left hand corner of the monitor at the top-left of the desktop. This
/// automatically un-maximizes the window if it's maximized.
///
/// # Platform-specific
///
/// - iOS: Can only be called on the main thread. Sets the top left coordinates of the window in the screen space coordinate system.
/// - iOS: Can only be called on the main thread. Sets the top left coordinates of the window in
/// the screen space coordinate system.
/// - Web: Sets the top-left coordinates relative to the viewport.
/// - Android / Wayland: Unsupported.
#[inline]

View file

@ -365,7 +365,8 @@ pub fn winit_runner_with(mut app: App, mut event_loop: EventLoop<()>) {
let winit_window = winit_windows.get_window(window_id).unwrap();
let mut location = touch.location.to_logical(winit_window.scale_factor());
// On a mobile window, the start is from the top while on PC/Linux/OSX from bottom
// On a mobile window, the start is from the top while on PC/Linux/OSX from
// bottom
if cfg!(target_os = "android") || cfg!(target_os = "ios") {
let window_height = windows.get_primary().unwrap().height();
location.y = window_height - location.y;

View file

@ -1,6 +1,7 @@
use bevy::{asset::LoadState, prelude::*, sprite::TextureAtlasBuilder};
/// In this example we generate a new texture atlas (sprite sheet) from a folder containing individual sprites
/// In this example we generate a new texture atlas (sprite sheet) from a folder containing
/// individual sprites
fn main() {
App::build()
.init_resource::<RpgSpriteHandles>()

View file

@ -1,8 +1,9 @@
use bevy::prelude::*;
/// This example shows how to configure Multi-Sample Anti-Aliasing. Setting the sample count higher will result in smoother edges,
/// but it will also increase the cost to render those edges. The range should generally be somewhere between 1 (no multi sampling,
/// but cheap) to 8 (crisp but expensive)
/// This example shows how to configure Multi-Sample Anti-Aliasing. Setting the sample count higher
/// will result in smoother edges, but it will also increase the cost to render those edges. The
/// range should generally be somewhere between 1 (no multi sampling, but cheap) to 8 (crisp but
/// expensive)
fn main() {
App::build()
.insert_resource(Msaa { samples: 4 })

View file

@ -1,7 +1,7 @@
use bevy::prelude::*;
/// This example illustrates how to create parent->child relationships between entities how parent transforms
/// are propagated to their descendants
/// This example illustrates how to create parent->child relationships between entities how parent
/// transforms are propagated to their descendants
fn main() {
App::build()
.insert_resource(Msaa { samples: 4 })

View file

@ -5,9 +5,10 @@ use bevy::{
use rand::{rngs::StdRng, Rng, SeedableRng};
/// This example spawns a large number of cubes, each with its own changing position and material
/// This is intended to be a stress test of bevy's ability to render many objects with different properties
/// For the best results, run it in release mode: ```cargo run --example spawner --release
/// NOTE: Bevy still has a number of optimizations to do in this area. Expect the performance here to go way up in the future
/// This is intended to be a stress test of bevy's ability to render many objects with different
/// properties For the best results, run it in release mode: ```cargo run --example spawner
/// --release NOTE: Bevy still has a number of optimizations to do in this area. Expect the
/// performance here to go way up in the future
fn main() {
App::build()
.add_plugins(DefaultPlugins)

View file

@ -6,7 +6,8 @@ use bevy::{
},
};
/// This example visualizes camera z-ordering by setting the material of rotating cubes to their distance from the camera
/// This example visualizes camera z-ordering by setting the material of rotating cubes to their
/// distance from the camera
fn main() {
App::build()
.add_plugins(DefaultPlugins)

Some files were not shown because too many files have changed in this diff Show more