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.
|
||||
pub(crate) unsafe fn register_required_components<R: Component>(
|
||||
&mut self,
|
||||
required: ComponentId,
|
||||
requiree: ComponentId,
|
||||
required: ComponentId,
|
||||
constructor: fn() -> R,
|
||||
) -> Result<(), RequiredComponentsError> {
|
||||
// SAFETY: The caller ensures that the `requiree` is valid.
|
||||
@ -1083,14 +1083,17 @@ impl Components {
|
||||
|
||||
for (component_id, component) in inherited_requirements.iter() {
|
||||
// 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.
|
||||
// The original requiree is responsible for making sure the registration is safe.
|
||||
unsafe {
|
||||
required_components.register_dynamic(
|
||||
*component_id,
|
||||
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);
|
||||
}
|
||||
|
||||
#[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]
|
||||
fn runtime_required_components_existing_archetype() {
|
||||
#[derive(Component)]
|
||||
|
||||
@ -515,7 +515,7 @@ impl World {
|
||||
// SAFETY: We just created the `required` and `requiree` components.
|
||||
unsafe {
|
||||
self.components
|
||||
.register_required_components::<R>(required, requiree, constructor)
|
||||
.register_required_components::<R>(requiree, required, constructor)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user