Rewrite required components
This commit is contained in:
parent
c182932618
commit
e335244112
@ -237,38 +237,17 @@ pub fn derive_component(input: TokenStream) -> TokenStream {
|
||||
|
||||
let requires = &attrs.requires;
|
||||
let mut register_required = Vec::with_capacity(attrs.requires.iter().len());
|
||||
let mut register_recursive_requires = Vec::with_capacity(attrs.requires.iter().len());
|
||||
if let Some(requires) = requires {
|
||||
for require in requires {
|
||||
let ident = &require.path;
|
||||
register_recursive_requires.push(quote! {
|
||||
<#ident as #bevy_ecs_path::component::Component>::register_required_components(
|
||||
requiree,
|
||||
components,
|
||||
required_components,
|
||||
inheritance_depth + 1
|
||||
);
|
||||
let constructor = match &require.func {
|
||||
Some(func) => quote! { || { let x: #ident = (#func)().into(); x } },
|
||||
None => quote! { <#ident as Default>::default },
|
||||
};
|
||||
register_required.push(quote! {
|
||||
// SAFETY: we registered all components with the same instance of components.
|
||||
unsafe { required_components.register::<#ident>(components, #constructor) };
|
||||
});
|
||||
match &require.func {
|
||||
Some(func) => {
|
||||
register_required.push(quote! {
|
||||
components.register_required_components_manual::<Self, #ident>(
|
||||
required_components,
|
||||
|| { let x: #ident = (#func)().into(); x },
|
||||
inheritance_depth
|
||||
);
|
||||
});
|
||||
}
|
||||
None => {
|
||||
register_required.push(quote! {
|
||||
components.register_required_components_manual::<Self, #ident>(
|
||||
required_components,
|
||||
<#ident as Default>::default,
|
||||
inheritance_depth
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let struct_name = &ast.ident;
|
||||
@ -308,14 +287,12 @@ pub fn derive_component(input: TokenStream) -> TokenStream {
|
||||
impl #impl_generics #bevy_ecs_path::component::Component for #struct_name #type_generics #where_clause {
|
||||
const STORAGE_TYPE: #bevy_ecs_path::component::StorageType = #storage;
|
||||
type Mutability = #mutable_type;
|
||||
fn register_required_components(
|
||||
unsafe fn register_required_components(
|
||||
_requiree: #bevy_ecs_path::component::ComponentId,
|
||||
components: &mut #bevy_ecs_path::component::ComponentsRegistrator,
|
||||
required_components: &mut #bevy_ecs_path::component::RequiredComponents,
|
||||
inheritance_depth: u16,
|
||||
) {
|
||||
#(#register_required)*
|
||||
#(#register_recursive_requires)*
|
||||
}
|
||||
|
||||
#on_add
|
||||
|
@ -3,14 +3,15 @@ use bevy_platform::collections::{HashMap, HashSet};
|
||||
use bevy_ptr::OwningPtr;
|
||||
use bevy_utils::TypeIdMap;
|
||||
use core::{any::TypeId, ptr::NonNull};
|
||||
use indexmap::{IndexMap, IndexSet};
|
||||
|
||||
use crate::{
|
||||
archetype::{Archetype, BundleComponentStatus, ComponentStatus},
|
||||
bundle::{Bundle, DynamicBundle},
|
||||
change_detection::MaybeLocation,
|
||||
component::{
|
||||
ComponentId, Components, ComponentsRegistrator, RequiredComponentConstructor,
|
||||
RequiredComponents, StorageType, Tick,
|
||||
ComponentId, Components, ComponentsRegistrator, RequiredComponentConstructor, StorageType,
|
||||
Tick,
|
||||
},
|
||||
entity::Entity,
|
||||
query::DebugCheckedUnwrap as _,
|
||||
@ -59,6 +60,7 @@ pub enum InsertMode {
|
||||
/// [`World`]: crate::world::World
|
||||
pub struct BundleInfo {
|
||||
pub(super) id: BundleId,
|
||||
|
||||
/// The list of all components contributed by the bundle (including Required Components). This is in
|
||||
/// the order `[EXPLICIT_COMPONENTS][REQUIRED_COMPONENTS]`
|
||||
///
|
||||
@ -67,9 +69,10 @@ pub struct BundleInfo {
|
||||
/// must have its storage initialized (i.e. columns created in tables, sparse set created),
|
||||
/// and the range (0..`explicit_components_len`) must be in the same order as the source bundle
|
||||
/// type writes its components in.
|
||||
pub(super) component_ids: Vec<ComponentId>,
|
||||
pub(super) required_components: Vec<RequiredComponentConstructor>,
|
||||
pub(super) explicit_components_len: usize,
|
||||
pub(super) contributed_components: Vec<ComponentId>,
|
||||
|
||||
/// The list of constructors for all required components indirectly contributed by this bundle.
|
||||
pub(super) required_component_constructors: Vec<RequiredComponentConstructor>,
|
||||
}
|
||||
|
||||
impl BundleInfo {
|
||||
@ -86,11 +89,10 @@ impl BundleInfo {
|
||||
mut component_ids: Vec<ComponentId>,
|
||||
id: BundleId,
|
||||
) -> BundleInfo {
|
||||
let explicit_component_ids = component_ids.iter().copied().collect::<IndexSet<_>>();
|
||||
|
||||
// check for duplicates
|
||||
let mut deduped = component_ids.clone();
|
||||
deduped.sort_unstable();
|
||||
deduped.dedup();
|
||||
if deduped.len() != component_ids.len() {
|
||||
if explicit_component_ids.len() != component_ids.len() {
|
||||
// TODO: Replace with `Vec::partition_dedup` once https://github.com/rust-lang/rust/issues/54279 is stabilized
|
||||
let mut seen = <HashSet<_>>::default();
|
||||
let mut dups = Vec::new();
|
||||
@ -111,31 +113,30 @@ impl BundleInfo {
|
||||
panic!("Bundle {bundle_type_name} has duplicate components: {names:?}");
|
||||
}
|
||||
|
||||
// handle explicit components
|
||||
let explicit_components_len = component_ids.len();
|
||||
let mut required_components = RequiredComponents::default();
|
||||
for component_id in component_ids.iter().copied() {
|
||||
let mut depth_first_components = IndexMap::new();
|
||||
for &component_id in &component_ids {
|
||||
// SAFETY: caller has verified that all ids are valid
|
||||
let info = unsafe { components.get_info_unchecked(component_id) };
|
||||
required_components.merge(info.required_components());
|
||||
|
||||
for (&required_id, required_component) in &info.required_components().all {
|
||||
depth_first_components
|
||||
.entry(required_id)
|
||||
.or_insert_with(|| required_component.clone());
|
||||
}
|
||||
|
||||
storages.prepare_component(info);
|
||||
}
|
||||
required_components.remove_explicit_components(&component_ids);
|
||||
|
||||
// handle required components
|
||||
let required_components = required_components
|
||||
.0
|
||||
.into_iter()
|
||||
.map(|(component_id, v)| {
|
||||
// Safety: These ids came out of the passed `components`, so they must be valid.
|
||||
let info = unsafe { components.get_info_unchecked(component_id) };
|
||||
storages.prepare_component(info);
|
||||
// This adds required components to the component_ids list _after_ using that list to remove explicitly provided
|
||||
// components. This ordering is important!
|
||||
component_ids.push(component_id);
|
||||
v.constructor
|
||||
let required_components = depth_first_components
|
||||
.iter()
|
||||
.filter(|&(required_id, _)| !explicit_component_ids.contains(required_id))
|
||||
.inspect(|&(&required_id, _)| {
|
||||
// SAFETY: These ids came out of the passed `components`, so they must be valid.
|
||||
storages.prepare_component(unsafe { components.get_info_unchecked(required_id) });
|
||||
component_ids.push(required_id);
|
||||
})
|
||||
.collect();
|
||||
.map(|(_, required_component)| required_component.constructor.clone())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// SAFETY: The caller ensures that component_ids:
|
||||
// - is valid for the associated world
|
||||
@ -143,9 +144,8 @@ impl BundleInfo {
|
||||
// - is in the same order as the source bundle type
|
||||
BundleInfo {
|
||||
id,
|
||||
component_ids,
|
||||
required_components,
|
||||
explicit_components_len,
|
||||
contributed_components: component_ids,
|
||||
required_component_constructors: required_components,
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,19 +155,24 @@ impl BundleInfo {
|
||||
self.id
|
||||
}
|
||||
|
||||
/// Returns the length of the explicit components part of the [contributed_components](Self::contributed_components) list.
|
||||
pub(super) fn explicit_components_len(&self) -> usize {
|
||||
self.contributed_components.len() - self.required_component_constructors.len()
|
||||
}
|
||||
|
||||
/// Returns the [ID](ComponentId) of each component explicitly defined in this bundle (ex: Required Components are excluded).
|
||||
///
|
||||
/// For all components contributed by this bundle (including Required Components), see [`BundleInfo::contributed_components`]
|
||||
#[inline]
|
||||
pub fn explicit_components(&self) -> &[ComponentId] {
|
||||
&self.component_ids[0..self.explicit_components_len]
|
||||
&self.contributed_components[0..self.explicit_components_len()]
|
||||
}
|
||||
|
||||
/// Returns the [ID](ComponentId) of each Required Component needed by this bundle. This _does not include_ Required Components that are
|
||||
/// explicitly provided by the bundle.
|
||||
#[inline]
|
||||
pub fn required_components(&self) -> &[ComponentId] {
|
||||
&self.component_ids[self.explicit_components_len..]
|
||||
&self.contributed_components[self.explicit_components_len()..]
|
||||
}
|
||||
|
||||
/// Returns the [ID](ComponentId) of each component contributed by this bundle. This includes Required Components.
|
||||
@ -175,7 +180,7 @@ impl BundleInfo {
|
||||
/// For only components explicitly defined in this bundle, see [`BundleInfo::explicit_components`]
|
||||
#[inline]
|
||||
pub fn contributed_components(&self) -> &[ComponentId] {
|
||||
&self.component_ids
|
||||
&self.contributed_components
|
||||
}
|
||||
|
||||
/// Returns an iterator over the [ID](ComponentId) of each component explicitly defined in this bundle (ex: this excludes Required Components).
|
||||
@ -190,7 +195,7 @@ impl BundleInfo {
|
||||
/// To iterate only components explicitly defined in this bundle, see [`BundleInfo::iter_explicit_components`]
|
||||
#[inline]
|
||||
pub fn iter_contributed_components(&self) -> impl Iterator<Item = ComponentId> + Clone + '_ {
|
||||
self.component_ids.iter().copied()
|
||||
self.contributed_components().iter().copied()
|
||||
}
|
||||
|
||||
/// Returns an iterator over the [ID](ComponentId) of each Required Component needed by this bundle. This _does not include_ Required Components that are
|
||||
@ -236,7 +241,7 @@ impl BundleInfo {
|
||||
// bundle_info.component_ids are also in "bundle order"
|
||||
let mut bundle_component = 0;
|
||||
let after_effect = bundle.get_components(&mut |storage_type, component_ptr| {
|
||||
let component_id = *self.component_ids.get_unchecked(bundle_component);
|
||||
let component_id = *self.contributed_components.get_unchecked(bundle_component);
|
||||
// SAFETY: bundle_component is a valid index for this bundle
|
||||
let status = unsafe { bundle_component_status.get_status(bundle_component) };
|
||||
match storage_type {
|
||||
|
@ -433,7 +433,7 @@ impl BundleInfo {
|
||||
}
|
||||
let mut new_table_components = Vec::new();
|
||||
let mut new_sparse_set_components = Vec::new();
|
||||
let mut bundle_status = Vec::with_capacity(self.explicit_components_len);
|
||||
let mut bundle_status = Vec::with_capacity(self.explicit_components_len());
|
||||
let mut added_required_components = Vec::new();
|
||||
let mut added = Vec::new();
|
||||
let mut existing = Vec::new();
|
||||
@ -457,7 +457,7 @@ impl BundleInfo {
|
||||
|
||||
for (index, component_id) in self.iter_required_components().enumerate() {
|
||||
if !current_archetype.contains(component_id) {
|
||||
added_required_components.push(self.required_components[index].clone());
|
||||
added_required_components.push(self.required_component_constructors[index].clone());
|
||||
added.push(component_id);
|
||||
// SAFETY: component_id exists
|
||||
let component_info = unsafe { components.get_info_unchecked(component_id) };
|
||||
|
@ -108,7 +108,7 @@ impl<'w> BundleSpawner<'w> {
|
||||
table,
|
||||
sparse_sets,
|
||||
&SpawnBundleStatus,
|
||||
bundle_info.required_components.iter(),
|
||||
bundle_info.required_component_constructors.iter(),
|
||||
entity,
|
||||
table_row,
|
||||
self.change_tick,
|
||||
|
@ -1,5 +1,5 @@
|
||||
use alloc::{borrow::Cow, vec::Vec};
|
||||
use bevy_platform::{collections::HashSet, sync::PoisonError};
|
||||
use bevy_platform::sync::PoisonError;
|
||||
use bevy_ptr::OwningPtr;
|
||||
#[cfg(feature = "bevy_reflect")]
|
||||
use bevy_reflect::Reflect;
|
||||
@ -10,6 +10,7 @@ use core::{
|
||||
fmt::Debug,
|
||||
mem::needs_drop,
|
||||
};
|
||||
use indexmap::IndexSet;
|
||||
|
||||
use crate::{
|
||||
archetype::ArchetypeFlags,
|
||||
@ -30,7 +31,10 @@ pub struct ComponentInfo {
|
||||
pub(super) descriptor: ComponentDescriptor,
|
||||
pub(super) hooks: ComponentHooks,
|
||||
pub(super) required_components: RequiredComponents,
|
||||
pub(super) required_by: HashSet<ComponentId>,
|
||||
/// The set of components that require this components.
|
||||
/// Invariant: this is stored in a depth-first order, that is components are stored after the components
|
||||
/// that they depend on.
|
||||
pub(super) required_by: IndexSet<ComponentId>,
|
||||
}
|
||||
|
||||
impl ComponentInfo {
|
||||
@ -505,6 +509,13 @@ impl Components {
|
||||
.and_then(|info| info.as_mut().map(|info| &mut info.hooks))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn get_required_components(&self, id: ComponentId) -> Option<&RequiredComponents> {
|
||||
self.components
|
||||
.get(id.0)
|
||||
.and_then(|info| info.as_ref().map(|info| &info.required_components))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn get_required_components_mut(
|
||||
&mut self,
|
||||
@ -516,7 +527,7 @@ impl Components {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn get_required_by(&self, id: ComponentId) -> Option<&HashSet<ComponentId>> {
|
||||
pub(crate) fn get_required_by(&self, id: ComponentId) -> Option<&IndexSet<ComponentId>> {
|
||||
self.components
|
||||
.get(id.0)
|
||||
.and_then(|info| info.as_ref().map(|info| &info.required_by))
|
||||
@ -526,7 +537,7 @@ impl Components {
|
||||
pub(crate) fn get_required_by_mut(
|
||||
&mut self,
|
||||
id: ComponentId,
|
||||
) -> Option<&mut HashSet<ComponentId>> {
|
||||
) -> Option<&mut IndexSet<ComponentId>> {
|
||||
self.components
|
||||
.get_mut(id.0)
|
||||
.and_then(|info| info.as_mut().map(|info| &mut info.required_by))
|
||||
|
@ -522,11 +522,14 @@ pub trait Component: Send + Sync + 'static {
|
||||
}
|
||||
|
||||
/// Registers required components.
|
||||
fn register_required_components(
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - `_required_components` must only contain components valid in `_components`.
|
||||
unsafe fn register_required_components(
|
||||
_component_id: ComponentId,
|
||||
_components: &mut ComponentsRegistrator,
|
||||
_required_components: &mut RequiredComponents,
|
||||
_inheritance_depth: u16,
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ use core::any::Any;
|
||||
use core::ops::DerefMut;
|
||||
use core::{any::TypeId, fmt::Debug, ops::Deref};
|
||||
|
||||
use crate::component::enforce_no_required_components_recursion;
|
||||
use crate::query::DebugCheckedUnwrap as _;
|
||||
use crate::{
|
||||
component::{
|
||||
@ -189,8 +190,9 @@ impl<'w> ComponentsRegistrator<'w> {
|
||||
#[inline]
|
||||
pub(super) fn register_component_checked<T: Component>(&mut self) -> ComponentId {
|
||||
let type_id = TypeId::of::<T>();
|
||||
if let Some(id) = self.indices.get(&type_id) {
|
||||
return *id;
|
||||
if let Some(&id) = self.indices.get(&type_id) {
|
||||
enforce_no_required_components_recursion(self, &self.recursion_check_stack, id);
|
||||
return id;
|
||||
}
|
||||
|
||||
if let Some(registrator) = self
|
||||
@ -229,8 +231,15 @@ impl<'w> ComponentsRegistrator<'w> {
|
||||
|
||||
self.recursion_check_stack.push(id);
|
||||
let mut required_components = RequiredComponents::default();
|
||||
T::register_required_components(id, self, &mut required_components, 0);
|
||||
// SAFETY: `required_components` is empty
|
||||
unsafe { T::register_required_components(id, self, &mut required_components) };
|
||||
// SAFETY:
|
||||
// - `id` was just registered in `self`
|
||||
// - `register_required_components` have been given `self` to register components in
|
||||
// (TODO: this is not really true... but the alternative would be making `Component` `unsafe`...)
|
||||
unsafe { self.register_required_by(id, &required_components) };
|
||||
self.recursion_check_stack.pop();
|
||||
|
||||
// SAFETY: we just inserted it in `register_component_inner`
|
||||
let info = unsafe {
|
||||
&mut self
|
||||
|
@ -1,8 +1,8 @@
|
||||
use alloc::{format, vec::Vec};
|
||||
use bevy_platform::{collections::HashMap, sync::Arc};
|
||||
use bevy_platform::sync::Arc;
|
||||
use bevy_ptr::OwningPtr;
|
||||
use core::fmt::Debug;
|
||||
use smallvec::SmallVec;
|
||||
use indexmap::{IndexMap, IndexSet};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::{
|
||||
@ -14,273 +14,80 @@ use crate::{
|
||||
storage::{SparseSets, Table, TableRow},
|
||||
};
|
||||
|
||||
impl Components {
|
||||
/// Registers the given component `R` and [required components] inherited from it as required by `T`.
|
||||
///
|
||||
/// When `T` is added to an entity, `R` will also be added if it was not already provided.
|
||||
/// The given `constructor` will be used for the creation of `R`.
|
||||
///
|
||||
/// [required components]: Component#required-components
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The given component IDs `required` and `requiree` must be valid.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns a [`RequiredComponentsError`] if the `required` component is already a directly required component for the `requiree`.
|
||||
///
|
||||
/// Indirect requirements through other components are allowed. In those cases, the more specific
|
||||
/// registration will be used.
|
||||
pub(crate) unsafe fn register_required_components<R: Component>(
|
||||
&mut self,
|
||||
requiree: ComponentId,
|
||||
required: ComponentId,
|
||||
constructor: fn() -> R,
|
||||
) -> Result<(), RequiredComponentsError> {
|
||||
// SAFETY: The caller ensures that the `requiree` is valid.
|
||||
let required_components = unsafe {
|
||||
self.get_required_components_mut(requiree)
|
||||
.debug_checked_unwrap()
|
||||
};
|
||||
|
||||
// Cannot directly require the same component twice.
|
||||
if required_components
|
||||
.0
|
||||
.get(&required)
|
||||
.is_some_and(|c| c.inheritance_depth == 0)
|
||||
{
|
||||
return Err(RequiredComponentsError::DuplicateRegistration(
|
||||
requiree, required,
|
||||
));
|
||||
}
|
||||
|
||||
// Register the required component for the requiree.
|
||||
// This is a direct requirement with a depth of `0`.
|
||||
required_components.register_by_id(required, constructor, 0);
|
||||
|
||||
// Add the requiree to the list of components that require the required component.
|
||||
// SAFETY: The component is in the list of required components, so it must exist already.
|
||||
let required_by = unsafe { self.get_required_by_mut(required).debug_checked_unwrap() };
|
||||
required_by.insert(requiree);
|
||||
|
||||
let mut required_components_tmp = RequiredComponents::default();
|
||||
// SAFETY: The caller ensures that the `requiree` and `required` components are valid.
|
||||
let inherited_requirements = unsafe {
|
||||
self.register_inherited_required_components(
|
||||
requiree,
|
||||
required,
|
||||
&mut required_components_tmp,
|
||||
)
|
||||
};
|
||||
|
||||
// SAFETY: The caller ensures that the `requiree` is valid.
|
||||
let required_components = unsafe {
|
||||
self.get_required_components_mut(requiree)
|
||||
.debug_checked_unwrap()
|
||||
};
|
||||
required_components.0.extend(required_components_tmp.0);
|
||||
|
||||
// Propagate the new required components up the chain to all components that require the requiree.
|
||||
if let Some(required_by) = self
|
||||
.get_required_by(requiree)
|
||||
.map(|set| set.iter().copied().collect::<SmallVec<[ComponentId; 8]>>())
|
||||
{
|
||||
// `required` is now required by anything that `requiree` was required by.
|
||||
self.get_required_by_mut(required)
|
||||
.unwrap()
|
||||
.extend(required_by.iter().copied());
|
||||
for &required_by_id in required_by.iter() {
|
||||
// SAFETY: The component is in the list of required components, so it must exist already.
|
||||
let required_components = unsafe {
|
||||
self.get_required_components_mut(required_by_id)
|
||||
.debug_checked_unwrap()
|
||||
};
|
||||
|
||||
// Register the original required component in the "parent" of the requiree.
|
||||
// The inheritance depth is 1 deeper than the `requiree` wrt `required_by_id`.
|
||||
let depth = required_components.0.get(&requiree).expect("requiree is required by required_by_id, so its required_components must include requiree").inheritance_depth;
|
||||
required_components.register_by_id(required, constructor, depth + 1);
|
||||
|
||||
for (component_id, component) in inherited_requirements.iter() {
|
||||
// Register the required component.
|
||||
// The inheritance depth of inherited components is whatever the requiree's
|
||||
// depth is relative to `required_by_id`, plus the inheritance depth of the
|
||||
// inherited component relative to the requiree, plus 1 to account for the
|
||||
// requiree in between.
|
||||
// SAFETY: Component ID and constructor match the ones on the original requiree.
|
||||
// The original requiree is responsible for making sure the registration is safe.
|
||||
unsafe {
|
||||
required_components.register_dynamic_with(
|
||||
*component_id,
|
||||
component.inheritance_depth + depth + 1,
|
||||
|| component.constructor.clone(),
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Registers the components inherited from `required` for the given `requiree`,
|
||||
/// returning the requirements in a list.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The given component IDs `requiree` and `required` must be valid.
|
||||
unsafe fn register_inherited_required_components(
|
||||
&mut self,
|
||||
requiree: ComponentId,
|
||||
required: ComponentId,
|
||||
required_components: &mut RequiredComponents,
|
||||
) -> Vec<(ComponentId, RequiredComponent)> {
|
||||
// Get required components inherited from the `required` component.
|
||||
// SAFETY: The caller ensures that the `required` component is valid.
|
||||
let required_component_info = unsafe { self.get_info(required).debug_checked_unwrap() };
|
||||
let inherited_requirements: Vec<(ComponentId, RequiredComponent)> = required_component_info
|
||||
.required_components()
|
||||
.0
|
||||
.iter()
|
||||
.map(|(component_id, required_component)| {
|
||||
(
|
||||
*component_id,
|
||||
RequiredComponent {
|
||||
constructor: required_component.constructor.clone(),
|
||||
// Add `1` to the inheritance depth since this will be registered
|
||||
// for the component that requires `required`.
|
||||
inheritance_depth: required_component.inheritance_depth + 1,
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Register the new required components.
|
||||
for (component_id, component) in inherited_requirements.iter() {
|
||||
// Register the required component for the requiree.
|
||||
// SAFETY: Component ID and constructor match the ones on the original requiree.
|
||||
unsafe {
|
||||
required_components.register_dynamic_with(
|
||||
*component_id,
|
||||
component.inheritance_depth,
|
||||
|| component.constructor.clone(),
|
||||
);
|
||||
};
|
||||
|
||||
// Add the requiree to the list of components that require the required component.
|
||||
// SAFETY: The caller ensures that the required components are valid.
|
||||
let required_by = unsafe {
|
||||
self.get_required_by_mut(*component_id)
|
||||
.debug_checked_unwrap()
|
||||
};
|
||||
required_by.insert(requiree);
|
||||
}
|
||||
|
||||
inherited_requirements
|
||||
}
|
||||
|
||||
/// Registers the given component `R` and [required components] inherited from it as required by `T`,
|
||||
/// and adds `T` to their lists of requirees.
|
||||
///
|
||||
/// The given `inheritance_depth` determines how many levels of inheritance deep the requirement is.
|
||||
/// A direct requirement has a depth of `0`, and each level of inheritance increases the depth by `1`.
|
||||
/// Lower depths are more specific requirements, and can override existing less specific registrations.
|
||||
///
|
||||
/// This method does *not* register any components as required by components that require `T`.
|
||||
///
|
||||
/// [required component]: Component#required-components
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The given component IDs `required` and `requiree` must be valid.
|
||||
pub(crate) unsafe fn register_required_components_manual_unchecked<R: Component>(
|
||||
&mut self,
|
||||
requiree: ComponentId,
|
||||
required: ComponentId,
|
||||
required_components: &mut RequiredComponents,
|
||||
constructor: fn() -> R,
|
||||
inheritance_depth: u16,
|
||||
) {
|
||||
// Components cannot require themselves.
|
||||
if required == requiree {
|
||||
return;
|
||||
}
|
||||
|
||||
// Register the required component `R` for the requiree.
|
||||
required_components.register_by_id(required, constructor, inheritance_depth);
|
||||
|
||||
// Add the requiree to the list of components that require `R`.
|
||||
// SAFETY: The caller ensures that the component ID is valid.
|
||||
// Assuming it is valid, the component is in the list of required components, so it must exist already.
|
||||
let required_by = unsafe { self.get_required_by_mut(required).debug_checked_unwrap() };
|
||||
required_by.insert(requiree);
|
||||
|
||||
self.register_inherited_required_components(requiree, required, required_components);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'w> ComponentsRegistrator<'w> {
|
||||
// NOTE: This should maybe be private, but it is currently public so that `bevy_ecs_macros` can use it.
|
||||
// We can't directly move this there either, because this uses `Components::get_required_by_mut`,
|
||||
// which is private, and could be equally risky to expose to users.
|
||||
/// Registers the given component `R` and [required components] inherited from it as required by `T`,
|
||||
/// and adds `T` to their lists of requirees.
|
||||
///
|
||||
/// The given `inheritance_depth` determines how many levels of inheritance deep the requirement is.
|
||||
/// A direct requirement has a depth of `0`, and each level of inheritance increases the depth by `1`.
|
||||
/// Lower depths are more specific requirements, and can override existing less specific registrations.
|
||||
///
|
||||
/// This method does *not* register any components as required by components that require `T`.
|
||||
///
|
||||
/// Only use this method if you know what you are doing. In most cases, you should instead use [`World::register_required_components`],
|
||||
/// or the equivalent method in `bevy_app::App`.
|
||||
///
|
||||
/// [required component]: Component#required-components
|
||||
#[doc(hidden)]
|
||||
pub fn register_required_components_manual<T: Component, R: Component>(
|
||||
&mut self,
|
||||
required_components: &mut RequiredComponents,
|
||||
constructor: fn() -> R,
|
||||
inheritance_depth: u16,
|
||||
) {
|
||||
let requiree = self.register_component_checked::<T>();
|
||||
let required = self.register_component_checked::<R>();
|
||||
|
||||
enforce_no_required_components_recursion(self, &self.recursion_check_stack, required);
|
||||
|
||||
// SAFETY: We just created the components.
|
||||
unsafe {
|
||||
self.register_required_components_manual_unchecked::<R>(
|
||||
requiree,
|
||||
required,
|
||||
required_components,
|
||||
constructor,
|
||||
inheritance_depth,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An error returned when the registration of a required component fails.
|
||||
#[derive(Error, Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum RequiredComponentsError {
|
||||
/// The component is already a directly required component for the requiree.
|
||||
#[error("Component {0:?} already directly requires component {1:?}")]
|
||||
DuplicateRegistration(ComponentId, ComponentId),
|
||||
/// An archetype with the component that requires other components already exists
|
||||
#[error("An archetype with the component {0:?} that requires other components already exists")]
|
||||
ArchetypeExists(ComponentId),
|
||||
/// Metadata associated with a required component. See [`Component`] for details.
|
||||
#[derive(Clone)]
|
||||
pub struct RequiredComponent {
|
||||
/// The constructor used for the required component.
|
||||
pub constructor: RequiredComponentConstructor,
|
||||
}
|
||||
|
||||
/// A Required Component constructor. See [`Component`] for details.
|
||||
#[derive(Clone)]
|
||||
pub struct RequiredComponentConstructor(
|
||||
pub Arc<dyn Fn(&mut Table, &mut SparseSets, Tick, TableRow, Entity, MaybeLocation)>,
|
||||
// Note: this function makes `unsafe` assumptions, so it cannot be public.
|
||||
Arc<dyn Fn(&mut Table, &mut SparseSets, Tick, TableRow, Entity, MaybeLocation)>,
|
||||
);
|
||||
|
||||
impl RequiredComponentConstructor {
|
||||
/// Creates a new instance of `RequiredComponentConstructor` for the given type
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - `component_id` must be a valid component for type `C`.
|
||||
pub unsafe fn new<C: Component>(component_id: ComponentId, constructor: fn() -> C) -> Self {
|
||||
RequiredComponentConstructor({
|
||||
// `portable-atomic-util` `Arc` is not able to coerce an unsized
|
||||
// type like `std::sync::Arc` can. Creating a `Box` first does the
|
||||
// coercion.
|
||||
//
|
||||
// This would be resolved by https://github.com/rust-lang/rust/issues/123430
|
||||
|
||||
#[cfg(not(target_has_atomic = "ptr"))]
|
||||
use alloc::boxed::Box;
|
||||
|
||||
type Constructor = dyn for<'a, 'b> Fn(
|
||||
&'a mut Table,
|
||||
&'b mut SparseSets,
|
||||
Tick,
|
||||
TableRow,
|
||||
Entity,
|
||||
MaybeLocation,
|
||||
);
|
||||
|
||||
#[cfg(not(target_has_atomic = "ptr"))]
|
||||
type Intermediate<T> = Box<T>;
|
||||
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
type Intermediate<T> = Arc<T>;
|
||||
|
||||
let boxed: Intermediate<Constructor> = Intermediate::new(
|
||||
move |table, sparse_sets, change_tick, table_row, entity, caller| {
|
||||
OwningPtr::make(constructor(), |ptr| {
|
||||
// SAFETY: This will only be called in the context of `BundleInfo::write_components`, which will
|
||||
// pass in a valid table_row and entity requiring a C constructor
|
||||
// C::STORAGE_TYPE is the storage type associated with `component_id` / `C`
|
||||
// `ptr` points to valid `C` data, which matches the type associated with `component_id`
|
||||
unsafe {
|
||||
BundleInfo::initialize_required_component(
|
||||
table,
|
||||
sparse_sets,
|
||||
change_tick,
|
||||
table_row,
|
||||
entity,
|
||||
component_id,
|
||||
C::STORAGE_TYPE,
|
||||
ptr,
|
||||
caller,
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
Arc::from(boxed)
|
||||
})
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// This is intended to only be called in the context of [`BundleInfo::write_components`] to initialized required components.
|
||||
/// Calling it _anywhere else_ should be considered unsafe.
|
||||
@ -303,203 +110,403 @@ impl RequiredComponentConstructor {
|
||||
}
|
||||
}
|
||||
|
||||
/// Metadata associated with a required component. See [`Component`] for details.
|
||||
#[derive(Clone)]
|
||||
pub struct RequiredComponent {
|
||||
/// The constructor used for the required component.
|
||||
pub constructor: RequiredComponentConstructor,
|
||||
|
||||
/// The depth of the component requirement in the requirement hierarchy for this component.
|
||||
/// This is used for determining which constructor is used in cases where there are duplicate requires.
|
||||
///
|
||||
/// For example, consider the inheritance tree `X -> Y -> Z`, where `->` indicates a requirement.
|
||||
/// `X -> Y` and `Y -> Z` are direct requirements with a depth of 0, while `Z` is only indirectly
|
||||
/// required for `X` with a depth of `1`.
|
||||
///
|
||||
/// In cases where there are multiple conflicting requirements with the same depth, a higher priority
|
||||
/// will be given to components listed earlier in the `require` attribute, or to the latest added requirement
|
||||
/// if registered at runtime.
|
||||
pub inheritance_depth: u16,
|
||||
}
|
||||
|
||||
/// The collection of metadata for components that are required for a given component.
|
||||
///
|
||||
/// For more information, see the "Required Components" section of [`Component`].
|
||||
#[derive(Default, Clone)]
|
||||
pub struct RequiredComponents(pub(crate) HashMap<ComponentId, RequiredComponent>);
|
||||
pub struct RequiredComponents {
|
||||
/// The components that are directly required (i.e. excluding inherited ones), in the order of their precedence.
|
||||
///
|
||||
/// # Safety
|
||||
/// The [`RequiredComponent`] instance associated to each ID must be valid for its component.
|
||||
pub(crate) direct: IndexMap<ComponentId, RequiredComponent>,
|
||||
/// All the components that are required (i.e. including inherited ones), in depth-first order. Most importantly,
|
||||
/// components in this list always appear after all the components that they require.
|
||||
///
|
||||
/// Note that the direct components are not necessarily at the end of this list, for example if A and C are directly
|
||||
/// requires, and A requires B requires C, then `all` will hold [C, B, A].
|
||||
///
|
||||
/// # Safety
|
||||
/// The [`RequiredComponent`] instance associated to each ID must be valid for its component.
|
||||
pub(crate) all: IndexMap<ComponentId, RequiredComponent>,
|
||||
}
|
||||
|
||||
impl Debug for RequiredComponents {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_tuple("RequiredComponents")
|
||||
.field(&self.0.keys())
|
||||
f.debug_struct("RequiredComponents")
|
||||
.field("direct", &self.direct.keys())
|
||||
.field("all", &self.all.keys())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl RequiredComponents {
|
||||
/// Registers a required component.
|
||||
/// Registers the [`Component`] `C` as an explicitly required component.
|
||||
///
|
||||
/// If the component is already registered, it will be overwritten if the given inheritance depth
|
||||
/// is smaller than the depth of the existing registration. Otherwise, the new registration will be ignored.
|
||||
/// If the component was not already registered as an explicit required component then it is added
|
||||
/// as one, potentially overriding the constructor of a inherited required component, and `true` is returned.
|
||||
/// Otherwise `false` is returned.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `component_id` must match the type initialized by `constructor`.
|
||||
/// `constructor` _must_ initialize a component for `component_id` in such a way that
|
||||
/// matches the storage type of the component. It must only use the given `table_row` or `Entity` to
|
||||
/// initialize the storage for `component_id` corresponding to the given entity.
|
||||
/// - all other components in this [`RequiredComponents`] instance must have been registrated in `components`.
|
||||
pub unsafe fn register<C: Component>(
|
||||
&mut self,
|
||||
components: &mut ComponentsRegistrator<'_>,
|
||||
constructor: fn() -> C,
|
||||
) -> bool {
|
||||
let id = components.register_component::<C>();
|
||||
// SAFETY:
|
||||
// - `id` was just registered in `components`;
|
||||
// - the caller guarantees all other components were registered in `components`.
|
||||
unsafe { self.register_by_id::<C>(id, components, constructor) }
|
||||
}
|
||||
|
||||
/// Registers the [`Component`] with the given `component_id` ID as an explicitly required component.
|
||||
///
|
||||
/// If the component was not already registered as an explicit required component then it is added
|
||||
/// as one, potentially overriding the constructor of a inherited required component, and `true` is returned.
|
||||
/// Otherwise `false` is returned.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - `component_id` must be a valid component in `components` for the type `C`;
|
||||
/// - all other components in this [`RequiredComponents`] instance must have been registrated in `components`.
|
||||
pub unsafe fn register_by_id<C: Component>(
|
||||
&mut self,
|
||||
component_id: ComponentId,
|
||||
components: &Components,
|
||||
constructor: fn() -> C,
|
||||
) -> bool {
|
||||
// SAFETY: the caller guarantees that `component_id` is valid for the type `C`.
|
||||
let constructor =
|
||||
|| unsafe { RequiredComponentConstructor::new(component_id, constructor) };
|
||||
|
||||
// SAFETY:
|
||||
// - the caller guarantees that `component_id` is valid in `components`
|
||||
// - the caller guarantees all other components were registered in `components`;
|
||||
// - constructor is guaranteed to create a valid constructor for the component with id `component_id`.
|
||||
unsafe { self.register_dynamic_with(component_id, components, constructor) }
|
||||
}
|
||||
|
||||
/// Registers the [`Component`] with the given `component_id` ID as an explicitly required component.
|
||||
///
|
||||
/// If the component was not already registered as an explicit required component then it is added
|
||||
/// as one, potentially overriding the constructor of a inherited required component, and `true` is returned.
|
||||
/// Otherwise `false` is returned.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - `component_id` must be a valid component in `components`;
|
||||
/// - all other components in this [`RequiredComponents`] instance must have been registrated in `components`;
|
||||
/// - `constructor` must return a [`RequiredComponentConstructor`] that constructs a valid instance for the
|
||||
/// component with ID `component_id`.
|
||||
pub unsafe fn register_dynamic_with(
|
||||
&mut self,
|
||||
component_id: ComponentId,
|
||||
inheritance_depth: u16,
|
||||
components: &Components,
|
||||
constructor: impl FnOnce() -> RequiredComponentConstructor,
|
||||
) {
|
||||
let entry = self.0.entry(component_id);
|
||||
match entry {
|
||||
bevy_platform::collections::hash_map::Entry::Occupied(mut occupied) => {
|
||||
let current = occupied.get_mut();
|
||||
if current.inheritance_depth > inheritance_depth {
|
||||
*current = RequiredComponent {
|
||||
constructor: constructor(),
|
||||
inheritance_depth,
|
||||
}
|
||||
}
|
||||
}
|
||||
bevy_platform::collections::hash_map::Entry::Vacant(vacant) => {
|
||||
vacant.insert(RequiredComponent {
|
||||
constructor: constructor(),
|
||||
inheritance_depth,
|
||||
});
|
||||
) -> bool {
|
||||
// If already registered as a direct required component then bail.
|
||||
let entry = match self.direct.entry(component_id) {
|
||||
indexmap::map::Entry::Vacant(entry) => entry,
|
||||
indexmap::map::Entry::Occupied(_) => return false,
|
||||
};
|
||||
|
||||
// Insert into `direct`.
|
||||
let constructor = constructor();
|
||||
let required_component = RequiredComponent { constructor };
|
||||
entry.insert(required_component.clone());
|
||||
|
||||
// Register inherited required components.
|
||||
unsafe {
|
||||
Self::register_inherited_required_components_unchecked(
|
||||
&mut self.all,
|
||||
component_id,
|
||||
required_component,
|
||||
components,
|
||||
)
|
||||
};
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
/// Rebuild the `all` list
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - all components in this [`RequiredComponents`] instance must have been registrated in `components`.
|
||||
unsafe fn rebuild_inherited_required_components(&mut self, components: &Components) {
|
||||
// Clear `all`, we are re-initializing it.
|
||||
self.all.clear();
|
||||
|
||||
// Register all inherited components as if we just registered all components in `direct` one-by-one.
|
||||
for (&required_id, required_component) in &self.direct {
|
||||
// SAFETY:
|
||||
// - the caller guarantees that all components in this instance have been registered in `components`,
|
||||
// meaning both `all` and `required_id` have been registered in `components`;
|
||||
// - `required_component` was associated to `required_id`, so it must hold a constructor valid for it.
|
||||
unsafe {
|
||||
Self::register_inherited_required_components_unchecked(
|
||||
&mut self.all,
|
||||
required_id,
|
||||
required_component.clone(),
|
||||
components,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Registers a required component.
|
||||
/// Registers all the inherited required components from `required_id`.
|
||||
///
|
||||
/// If the component is already registered, it will be overwritten if the given inheritance depth
|
||||
/// is smaller than the depth of the existing registration. Otherwise, the new registration will be ignored.
|
||||
pub fn register<C: Component>(
|
||||
&mut self,
|
||||
components: &mut ComponentsRegistrator,
|
||||
constructor: fn() -> C,
|
||||
inheritance_depth: u16,
|
||||
/// # Safety
|
||||
///
|
||||
/// - all components in `all` must have been registered in `components`;
|
||||
/// - `required_id` must have been registered in `components`;
|
||||
/// - `required_component` must hold a valid constructor for the component with id `required_id`.
|
||||
unsafe fn register_inherited_required_components_unchecked(
|
||||
all: &mut IndexMap<ComponentId, RequiredComponent>,
|
||||
required_id: ComponentId,
|
||||
required_component: RequiredComponent,
|
||||
components: &Components,
|
||||
) {
|
||||
let component_id = components.register_component::<C>();
|
||||
self.register_by_id(component_id, constructor, inheritance_depth);
|
||||
}
|
||||
// SAFETY: the caller guarantees that `required_id` is valid in `components`.
|
||||
let info = unsafe { components.get_info(required_id).debug_checked_unwrap() };
|
||||
|
||||
/// Registers the [`Component`] with the given ID as required if it exists.
|
||||
///
|
||||
/// If the component is already registered, it will be overwritten if the given inheritance depth
|
||||
/// is smaller than the depth of the existing registration. Otherwise, the new registration will be ignored.
|
||||
pub fn register_by_id<C: Component>(
|
||||
&mut self,
|
||||
component_id: ComponentId,
|
||||
constructor: fn() -> C,
|
||||
inheritance_depth: u16,
|
||||
) {
|
||||
let erased = || {
|
||||
RequiredComponentConstructor({
|
||||
// `portable-atomic-util` `Arc` is not able to coerce an unsized
|
||||
// type like `std::sync::Arc` can. Creating a `Box` first does the
|
||||
// coercion.
|
||||
// Now we need to "recursively" register the
|
||||
// Small optimization: if the current required component was already required recursively
|
||||
// by an earlier direct required component then all its inherited components have all already
|
||||
// been inserted, so let's not try to reinsert them.
|
||||
if !all.contains_key(&required_id) {
|
||||
for (&inherited_id, inherited_required) in &info.required_components().all {
|
||||
// This is an inherited required component: insert it only if not already present.
|
||||
// By the invariants of `RequiredComponents`, `info.required_components().all` holds the required
|
||||
// components in a depth-first order, and this makes us store teh components in `self.all` also
|
||||
// in depth-first order, as long as we don't overwrite existing ones.
|
||||
//
|
||||
// This would be resolved by https://github.com/rust-lang/rust/issues/123430
|
||||
// SAFETY:
|
||||
// `inherited_required` was associated to `inherited_id`, so it must have been valid for its component.
|
||||
all.entry(inherited_id)
|
||||
.or_insert_with(|| inherited_required.clone());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_has_atomic = "ptr"))]
|
||||
use alloc::boxed::Box;
|
||||
|
||||
type Constructor = dyn for<'a, 'b> Fn(
|
||||
&'a mut Table,
|
||||
&'b mut SparseSets,
|
||||
Tick,
|
||||
TableRow,
|
||||
Entity,
|
||||
MaybeLocation,
|
||||
);
|
||||
|
||||
#[cfg(not(target_has_atomic = "ptr"))]
|
||||
type Intermediate<T> = Box<T>;
|
||||
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
type Intermediate<T> = Arc<T>;
|
||||
|
||||
let boxed: Intermediate<Constructor> = Intermediate::new(
|
||||
move |table, sparse_sets, change_tick, table_row, entity, caller| {
|
||||
OwningPtr::make(constructor(), |ptr| {
|
||||
// SAFETY: This will only be called in the context of `BundleInfo::write_components`, which will
|
||||
// pass in a valid table_row and entity requiring a C constructor
|
||||
// C::STORAGE_TYPE is the storage type associated with `component_id` / `C`
|
||||
// `ptr` points to valid `C` data, which matches the type associated with `component_id`
|
||||
unsafe {
|
||||
BundleInfo::initialize_required_component(
|
||||
table,
|
||||
sparse_sets,
|
||||
change_tick,
|
||||
table_row,
|
||||
entity,
|
||||
component_id,
|
||||
C::STORAGE_TYPE,
|
||||
ptr,
|
||||
caller,
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
Arc::from(boxed)
|
||||
})
|
||||
};
|
||||
|
||||
// SAFETY:
|
||||
// `component_id` matches the type initialized by the `erased` constructor above.
|
||||
// `erased` initializes a component for `component_id` in such a way that
|
||||
// matches the storage type of the component. It only uses the given `table_row` or `Entity` to
|
||||
// initialize the storage corresponding to the given entity.
|
||||
unsafe { self.register_dynamic_with(component_id, inheritance_depth, erased) };
|
||||
// For direct required components:
|
||||
// - insert them after inherited components to follow the depth-first order;
|
||||
// - insert them unconditionally in order to make their constructor the one that's used.
|
||||
// Note that `insert` does not change the order of components, meaning `component_id` will still appear
|
||||
// before any other component that requires it.
|
||||
//
|
||||
// SAFETY: the caller guaranees that `required_component` is valid for the component with ID `required_id`.
|
||||
all.insert(required_id, required_component);
|
||||
}
|
||||
|
||||
/// Iterates the ids of all required components. This includes recursive required components.
|
||||
pub fn iter_ids(&self) -> impl Iterator<Item = ComponentId> + '_ {
|
||||
self.0.keys().copied()
|
||||
self.all.keys().copied()
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes components that are explicitly provided in a given [`Bundle`]. These components should
|
||||
/// be logically treated as normal components, not "required components".
|
||||
impl Components {
|
||||
/// Registers the components in `required_components` as required by `requiree`.
|
||||
///
|
||||
/// [`Bundle`]: crate::bundle::Bundle
|
||||
pub(crate) fn remove_explicit_components(&mut self, components: &[ComponentId]) {
|
||||
for component in components {
|
||||
self.0.remove(component);
|
||||
}
|
||||
}
|
||||
|
||||
/// Merges `required_components` into this collection. This only inserts a required component
|
||||
/// if it _did not already exist_ *or* if the required component is more specific than the existing one
|
||||
/// (in other words, if the inheritance depth is smaller).
|
||||
/// # Safety
|
||||
///
|
||||
/// See [`register_dynamic_with`](Self::register_dynamic_with) for details.
|
||||
pub(crate) fn merge(&mut self, required_components: &RequiredComponents) {
|
||||
for (
|
||||
component_id,
|
||||
RequiredComponent {
|
||||
constructor,
|
||||
inheritance_depth,
|
||||
},
|
||||
) in required_components.0.iter()
|
||||
{
|
||||
// SAFETY: This exact registration must have been done on `required_components`, so safety is ensured by that caller.
|
||||
unsafe {
|
||||
self.register_dynamic_with(*component_id, *inheritance_depth, || {
|
||||
constructor.clone()
|
||||
});
|
||||
}
|
||||
/// - `requiree` must have been registered in `self`
|
||||
/// - all components in `required_components` must have been registered in `self`.
|
||||
pub(crate) unsafe fn register_required_by(
|
||||
&mut self,
|
||||
requiree: ComponentId,
|
||||
required_components: &RequiredComponents,
|
||||
) {
|
||||
for &required in required_components.all.keys() {
|
||||
// SAFETY: the caller guarantees that all components in `required_components` have been registered in `self`.
|
||||
let required_by = unsafe { self.get_required_by_mut(required).debug_checked_unwrap() };
|
||||
required_by.insert(requiree);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn enforce_no_required_components_recursion(
|
||||
impl Components {
|
||||
/// Registers the given component `R` and [required components] inherited from it as required by `T`.
|
||||
///
|
||||
/// When `T` is added to an entity, `R` will also be added if it was not already provided.
|
||||
/// The given `constructor` will be used for the creation of `R`.
|
||||
///
|
||||
/// [required components]: Component#required-components
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - the given component IDs `required` and `requiree` must be valid in `self`;
|
||||
/// - the given component ID `required` must be valid for the component type `R`.
|
||||
///
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns a [`RequiredComponentsError`] if either of these are true:
|
||||
/// - the `required` component is already a *directly* required component for the `requiree`; indirect
|
||||
/// requirements through other components are allowed. In those cases, the more specific
|
||||
/// registration will be used.
|
||||
/// - the `requiree` component is already a (possibly indirect) required component for the `required` component.
|
||||
pub(crate) unsafe fn register_required_components<R: Component>(
|
||||
&mut self,
|
||||
requiree: ComponentId,
|
||||
required: ComponentId,
|
||||
constructor: fn() -> R,
|
||||
) -> Result<(), RequiredComponentsError> {
|
||||
// First step: validate inputs and return errors.
|
||||
|
||||
// SAFETY: The caller ensures that the `required` is valid.
|
||||
let required_required_components = unsafe {
|
||||
self.get_required_components(required)
|
||||
.debug_checked_unwrap()
|
||||
};
|
||||
|
||||
// Cannot create cyclic requirements.
|
||||
if required_required_components.all.contains_key(&requiree) {
|
||||
return Err(RequiredComponentsError::CyclicRequirement(
|
||||
requiree, required,
|
||||
));
|
||||
}
|
||||
|
||||
// SAFETY: The caller ensures that the `requiree` is valid.
|
||||
let required_components = unsafe {
|
||||
self.get_required_components_mut(requiree)
|
||||
.debug_checked_unwrap()
|
||||
};
|
||||
|
||||
// Cannot directly require the same component twice.
|
||||
if required_components.direct.contains_key(&required) {
|
||||
return Err(RequiredComponentsError::DuplicateRegistration(
|
||||
requiree, required,
|
||||
));
|
||||
}
|
||||
|
||||
// Second step: register the single requirement requiree->required
|
||||
|
||||
// Store the old count of (all) required components. This will help determine which ones are new.
|
||||
let old_required_count = required_components.all.len();
|
||||
|
||||
// SAFETY: the caller guarantees that `requiree` and `required` are valid in `self`, with `required` valid for R.
|
||||
unsafe { self.register_required_component_single(requiree, required, constructor) };
|
||||
|
||||
// Third step: update the required components and required_by of all the indirect requirements/requirees.
|
||||
|
||||
// Borrow again otherwise it conflicts with the `self.register_required_component_single` call.
|
||||
// SAFETY: The caller ensures that the `requiree` is valid.
|
||||
let required_components = unsafe {
|
||||
self.get_required_components_mut(requiree)
|
||||
.debug_checked_unwrap()
|
||||
};
|
||||
|
||||
// Optimization: get all the new required components, i.e. those that were appended.
|
||||
// Other components that might be inherited when requiring `required` can be safely ignored because
|
||||
// any component requiring `requiree` will already transitively require them.
|
||||
// Note: the only small exception is for `required` itself, for which we cannot ignore the value of the
|
||||
// constructor. But for simplicity we will rebuild any `RequiredComponents`
|
||||
let new_required_components = required_components.all[old_required_count..]
|
||||
.keys()
|
||||
.copied()
|
||||
.collect::<IndexSet<_>>();
|
||||
|
||||
// Get all the new requiree components, i.e. `requiree` and all the components that `requiree` is required by.
|
||||
// SAFETY: The caller ensures that the `requiree` is valid.
|
||||
let new_requiree_components =
|
||||
unsafe { self.get_required_by(requiree).debug_checked_unwrap() }.clone();
|
||||
|
||||
// We now need to update the required and required_by components of all the components
|
||||
// directly or indirectly involved.
|
||||
// Important: we need to be careful about the order we do these operations in.
|
||||
// Since computing the required components of some component depends on the required components of
|
||||
// other components, and while we do this operations not all required components are up-to-date, we need
|
||||
// to ensure we update components in such a way that we update a component after the components it depends on.
|
||||
// Luckily this is exactly the depth-first order, which is guaranteed to be the order of `new_requiree_components`.
|
||||
|
||||
// Update the inherited required components of all requiree components (directly or indirectly).
|
||||
for &indirect_requiree in &new_requiree_components {
|
||||
// Extract the required components to avoid conflicting borrows. Remember to put this back before continuing!
|
||||
// SAFETY: `indirect_requiree` comes from `self`, so it must be valid.
|
||||
let mut required_components = std::mem::take(unsafe {
|
||||
self.get_required_components_mut(indirect_requiree)
|
||||
.debug_checked_unwrap()
|
||||
});
|
||||
|
||||
// Rebuild the inherited required components.
|
||||
// SAFETY: `required_components` comes from `self`, so all its components must have be valid in `self`.
|
||||
unsafe { required_components.rebuild_inherited_required_components(self) };
|
||||
|
||||
// Let's not forget to put back `required_components`!
|
||||
// SAFETY: `indirect_requiree` comes from `self`, so it must be valid.
|
||||
*unsafe {
|
||||
self.get_required_components_mut(indirect_requiree)
|
||||
.debug_checked_unwrap()
|
||||
} = required_components;
|
||||
}
|
||||
|
||||
// Update the `required_by` of all the components that were newly required (directly or indirectly).
|
||||
for &indirect_required in &new_required_components {
|
||||
// SAFETY: `indirect_required` comes from `self`, so it must be valid.
|
||||
let required_by = unsafe {
|
||||
self.get_required_by_mut(indirect_required)
|
||||
.debug_checked_unwrap()
|
||||
};
|
||||
|
||||
for &requiree in [&requiree].into_iter().chain(&new_requiree_components) {
|
||||
required_by.insert_before(required_by.len(), requiree);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Register the `required` as a required component in the [`RequiredComponents`] for `requiree`.
|
||||
/// This function does not update any other metadata, such as required components of components requiring `requiree`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - `requiree` and `required` must be defined in `self`.
|
||||
/// - `required` must be a valid component ID for the type `R`.
|
||||
unsafe fn register_required_component_single<R: Component>(
|
||||
&mut self,
|
||||
requiree: ComponentId,
|
||||
required: ComponentId,
|
||||
constructor: fn() -> R,
|
||||
) {
|
||||
// Extract the required components to avoid conflicting borrows. Remember to put this back before returning!
|
||||
// SAFETY: The caller ensures that the `requiree` is valid.
|
||||
let mut required_components = std::mem::take(unsafe {
|
||||
self.get_required_components_mut(requiree)
|
||||
.debug_checked_unwrap()
|
||||
});
|
||||
|
||||
// Register the required component for the requiree.
|
||||
required_components.register_by_id(required, self, constructor);
|
||||
|
||||
// Let's not forget to put back `required_components`!
|
||||
// SAFETY: The caller ensures that the `requiree` is valid.
|
||||
*unsafe {
|
||||
self.get_required_components_mut(requiree)
|
||||
.debug_checked_unwrap()
|
||||
} = required_components;
|
||||
}
|
||||
}
|
||||
|
||||
/// An error returned when the registration of a required component fails.
|
||||
#[derive(Error, Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum RequiredComponentsError {
|
||||
/// The component is already a directly required component for the requiree.
|
||||
#[error("Component {0:?} already directly requires component {1:?}")]
|
||||
DuplicateRegistration(ComponentId, ComponentId),
|
||||
/// Adding the given requirement would create a cycle.
|
||||
#[error("Cyclic requirement found: the requiree component {0:?} is required by the required component {1:?}")]
|
||||
CyclicRequirement(ComponentId, ComponentId),
|
||||
/// An archetype with the component that requires other components already exists
|
||||
#[error("An archetype with the component {0:?} that requires other components already exists")]
|
||||
ArchetypeExists(ComponentId),
|
||||
}
|
||||
|
||||
pub(super) fn enforce_no_required_components_recursion(
|
||||
components: &Components,
|
||||
recursion_check_stack: &[ComponentId],
|
||||
required: ComponentId,
|
||||
|
Loading…
Reference in New Issue
Block a user