Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runtime required components #15458

Merged
merged 23 commits into from
Sep 30, 2024
Merged
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Refactor inherited requirements into separate method
Jondolf committed Sep 28, 2024
commit bd2ecab55d65cb6ba6400ffee26ea98a23a18e64
65 changes: 33 additions & 32 deletions crates/bevy_ecs/src/component.rs
Original file line number Diff line number Diff line change
@@ -1059,32 +1059,9 @@ impl Components {
let required_by = unsafe { self.get_required_by_mut(required).debug_checked_unwrap() };
required_by.insert(requiree);

// 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.
// SAFETY: The caller ensures that the `requiree` is valid.
// The inherited required components are valid, since they were just found.
unsafe {
self.register_required_components_internal(requiree, &inherited_requirements);
}
// SAFETY: The caller ensures that the `requiree` and `required` components are valid.
let inherited_requirements =
unsafe { self.register_inherited_required_components(requiree, required) };

// 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).cloned() {
@@ -1118,17 +1095,39 @@ impl Components {
Ok(())
}

/// Registers the given components as required components for the given `requiree`.
/// Registers the components inherited from `required` for the given `requiree`,
/// returning the requirements in a list.
///
/// # Safety
///
/// The given `requiree` and the components in the `required` list must be valid component IDs.
unsafe fn register_required_components_internal(
/// The given component IDs `requiree` and `required` must be valid.
unsafe fn register_inherited_required_components(
&mut self,
requiree: ComponentId,
required: &[(ComponentId, RequiredComponent)],
) {
for (component_id, component) in required.iter().cloned() {
required: ComponentId,
) -> 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().cloned() {
// SAFETY: The caller ensures that the `requiree` is valid.
let required_components = unsafe {
self.get_required_components_mut(requiree)
@@ -1153,6 +1152,8 @@ impl Components {
};
required_by.insert(requiree);
}

inherited_requirements
}

// NOTE: This should maybe be private, but it is currently public so that `bevy_ecs_macros` can use it.