Fix adding a subtree of required components to an existing tree replacing shallower required component constructors (#16441)
# Objective - Fixes #16406 even more. The previous implementation did not take into account the depth of the requiree when setting the depth relative to the required_by component. ## Solution - Add the depth of the requiree! ## Testing - Added a test. --------- Co-authored-by: Carter Anderson <mcanders1@gmail.com>
This commit is contained in:
parent
8a3a8b5cfb
commit
6741e01dfa
@ -1029,8 +1029,8 @@ impl Components {
|
|||||||
/// registration will be used.
|
/// registration will be used.
|
||||||
pub(crate) unsafe fn register_required_components<R: Component>(
|
pub(crate) unsafe fn register_required_components<R: Component>(
|
||||||
&mut self,
|
&mut self,
|
||||||
required: ComponentId,
|
|
||||||
requiree: ComponentId,
|
requiree: ComponentId,
|
||||||
|
required: ComponentId,
|
||||||
constructor: fn() -> R,
|
constructor: fn() -> R,
|
||||||
) -> Result<(), RequiredComponentsError> {
|
) -> Result<(), RequiredComponentsError> {
|
||||||
// SAFETY: The caller ensures that the `requiree` is valid.
|
// SAFETY: The caller ensures that the `requiree` is valid.
|
||||||
@ -1083,14 +1083,17 @@ impl Components {
|
|||||||
|
|
||||||
for (component_id, component) in inherited_requirements.iter() {
|
for (component_id, component) in inherited_requirements.iter() {
|
||||||
// Register the required component.
|
// Register the required component.
|
||||||
// The inheritance depth is increased by `1` since this is a component required by the original 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.
|
// SAFETY: Component ID and constructor match the ones on the original requiree.
|
||||||
// The original requiree is responsible for making sure the registration is safe.
|
// The original requiree is responsible for making sure the registration is safe.
|
||||||
unsafe {
|
unsafe {
|
||||||
required_components.register_dynamic(
|
required_components.register_dynamic(
|
||||||
*component_id,
|
*component_id,
|
||||||
component.constructor.clone(),
|
component.constructor.clone(),
|
||||||
component.inheritance_depth + 1,
|
component.inheritance_depth + depth + 1,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2399,6 +2399,40 @@ mod tests {
|
|||||||
assert_eq!(world.entity(id).get::<Counter>().unwrap().0, 1);
|
assert_eq!(world.entity(id).get::<Counter>().unwrap().0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn runtime_required_components_deep_require_does_not_override_shallow_require_deep_subtree_after_shallow(
|
||||||
|
) {
|
||||||
|
#[derive(Component)]
|
||||||
|
struct A;
|
||||||
|
#[derive(Component, Default)]
|
||||||
|
struct B;
|
||||||
|
#[derive(Component, Default)]
|
||||||
|
struct C;
|
||||||
|
#[derive(Component, Default)]
|
||||||
|
struct D;
|
||||||
|
#[derive(Component, Default)]
|
||||||
|
struct E;
|
||||||
|
#[derive(Component)]
|
||||||
|
struct Counter(i32);
|
||||||
|
#[derive(Component, Default)]
|
||||||
|
struct F;
|
||||||
|
|
||||||
|
let mut world = World::new();
|
||||||
|
|
||||||
|
world.register_required_components::<A, B>();
|
||||||
|
world.register_required_components::<B, C>();
|
||||||
|
world.register_required_components::<C, D>();
|
||||||
|
world.register_required_components::<D, E>();
|
||||||
|
world.register_required_components_with::<E, Counter>(|| Counter(1));
|
||||||
|
world.register_required_components_with::<F, Counter>(|| Counter(2));
|
||||||
|
world.register_required_components::<E, F>();
|
||||||
|
|
||||||
|
let id = world.spawn(A).id();
|
||||||
|
|
||||||
|
// The "shallower" of the two components is used.
|
||||||
|
assert_eq!(world.entity(id).get::<Counter>().unwrap().0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn runtime_required_components_existing_archetype() {
|
fn runtime_required_components_existing_archetype() {
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
|
|||||||
@ -515,7 +515,7 @@ impl World {
|
|||||||
// SAFETY: We just created the `required` and `requiree` components.
|
// SAFETY: We just created the `required` and `requiree` components.
|
||||||
unsafe {
|
unsafe {
|
||||||
self.components
|
self.components
|
||||||
.register_required_components::<R>(required, requiree, constructor)
|
.register_required_components::<R>(requiree, required, constructor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user