Add mutated state when inserting an already existing component (#404)
Add mutated state when inserting an already existing component
This commit is contained in:
		
							parent
							
								
									0db9e9494d
								
							
						
					
					
						commit
						5bd6deb974
					
				@ -406,11 +406,15 @@ impl Archetype {
 | 
			
		||||
        size: usize,
 | 
			
		||||
        index: usize,
 | 
			
		||||
        added: bool,
 | 
			
		||||
        mutated: bool,
 | 
			
		||||
    ) {
 | 
			
		||||
        let state = self.state.get_mut(&ty).unwrap();
 | 
			
		||||
        if added {
 | 
			
		||||
            state.added_entities[index] = true;
 | 
			
		||||
        }
 | 
			
		||||
        if mutated {
 | 
			
		||||
            state.mutated_entities[index] = true;
 | 
			
		||||
        }
 | 
			
		||||
        let ptr = (*self.data.get())
 | 
			
		||||
            .as_ptr()
 | 
			
		||||
            .add(state.offset + size * index)
 | 
			
		||||
 | 
			
		||||
@ -900,24 +900,24 @@ mod tests {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn get_changed_a(world: &mut World) -> Vec<Entity> {
 | 
			
		||||
        fn get_mutated_a(world: &mut World) -> Vec<Entity> {
 | 
			
		||||
            world
 | 
			
		||||
                .query_mut::<(Mutated<A>, Entity)>()
 | 
			
		||||
                .map(|(_a, e)| e)
 | 
			
		||||
                .collect::<Vec<Entity>>()
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        assert_eq!(get_changed_a(&mut world), vec![e1, e3]);
 | 
			
		||||
        assert_eq!(get_mutated_a(&mut world), vec![e1, e3]);
 | 
			
		||||
 | 
			
		||||
        // ensure changing an entity's archetypes also moves its mutated state
 | 
			
		||||
        world.insert(e1, (C,)).unwrap();
 | 
			
		||||
 | 
			
		||||
        assert_eq!(get_changed_a(&mut world), vec![e3, e1], "changed entities list should not change (although the order will due to archetype moves)");
 | 
			
		||||
        assert_eq!(get_mutated_a(&mut world), vec![e3, e1], "changed entities list should not change (although the order will due to archetype moves)");
 | 
			
		||||
 | 
			
		||||
        // spawning a new A entity should not change existing mutated state
 | 
			
		||||
        world.insert(e1, (A(0), B)).unwrap();
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            get_changed_a(&mut world),
 | 
			
		||||
            get_mutated_a(&mut world),
 | 
			
		||||
            vec![e3, e1],
 | 
			
		||||
            "changed entities list should not change"
 | 
			
		||||
        );
 | 
			
		||||
@ -925,7 +925,7 @@ mod tests {
 | 
			
		||||
        // removing an unchanged entity should not change mutated state
 | 
			
		||||
        world.despawn(e2).unwrap();
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            get_changed_a(&mut world),
 | 
			
		||||
            get_mutated_a(&mut world),
 | 
			
		||||
            vec![e3, e1],
 | 
			
		||||
            "changed entities list should not change"
 | 
			
		||||
        );
 | 
			
		||||
@ -933,7 +933,7 @@ mod tests {
 | 
			
		||||
        // removing a changed entity should remove it from enumeration
 | 
			
		||||
        world.despawn(e1).unwrap();
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            get_changed_a(&mut world),
 | 
			
		||||
            get_mutated_a(&mut world),
 | 
			
		||||
            vec![e3],
 | 
			
		||||
            "e1 should no longer be returned"
 | 
			
		||||
        );
 | 
			
		||||
@ -943,8 +943,46 @@ mod tests {
 | 
			
		||||
        assert!(world
 | 
			
		||||
            .query_mut::<(Mutated<A>, Entity)>()
 | 
			
		||||
            .map(|(_a, e)| e)
 | 
			
		||||
            .collect::<Vec<Entity>>()
 | 
			
		||||
            .is_empty());
 | 
			
		||||
            .next()
 | 
			
		||||
            .is_none());
 | 
			
		||||
 | 
			
		||||
        let e4 = world.spawn(());
 | 
			
		||||
 | 
			
		||||
        world.insert_one(e4, A(0)).unwrap();
 | 
			
		||||
        assert!(get_mutated_a(&mut world).is_empty());
 | 
			
		||||
 | 
			
		||||
        world.insert_one(e4, A(1)).unwrap();
 | 
			
		||||
        assert_eq!(get_mutated_a(&mut world), vec![e4]);
 | 
			
		||||
 | 
			
		||||
        world.clear_trackers();
 | 
			
		||||
 | 
			
		||||
        // ensure inserting multiple components set mutated state for
 | 
			
		||||
        // already existing components and set added state for
 | 
			
		||||
        // non existing components even when changing archetype.
 | 
			
		||||
        world.insert(e4, (A(0), B(0))).unwrap();
 | 
			
		||||
 | 
			
		||||
        let added_a = world
 | 
			
		||||
            .query::<(Added<A>, Entity)>()
 | 
			
		||||
            .iter()
 | 
			
		||||
            .map(|(_, e)| e)
 | 
			
		||||
            .next();
 | 
			
		||||
        assert!(added_a.is_none());
 | 
			
		||||
 | 
			
		||||
        assert_eq!(get_mutated_a(&mut world), vec![e4]);
 | 
			
		||||
 | 
			
		||||
        let added_b = world
 | 
			
		||||
            .query::<(Added<B>, Entity)>()
 | 
			
		||||
            .iter()
 | 
			
		||||
            .map(|(_, e)| e)
 | 
			
		||||
            .next();
 | 
			
		||||
        assert!(added_b.is_some());
 | 
			
		||||
 | 
			
		||||
        let mutated_b = world
 | 
			
		||||
            .query_mut::<(Mutated<B>, Entity)>()
 | 
			
		||||
            .iter()
 | 
			
		||||
            .map(|(_, e)| e)
 | 
			
		||||
            .next();
 | 
			
		||||
        assert!(mutated_b.is_none());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
@ -962,11 +1000,11 @@ mod tests {
 | 
			
		||||
            b.0 += 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let a_b_changed = world
 | 
			
		||||
        let a_b_mutated = world
 | 
			
		||||
            .query_mut::<(Mutated<A>, Mutated<B>, Entity)>()
 | 
			
		||||
            .map(|(_a, _b, e)| e)
 | 
			
		||||
            .collect::<Vec<Entity>>();
 | 
			
		||||
        assert_eq!(a_b_changed, vec![e2]);
 | 
			
		||||
        assert_eq!(a_b_mutated, vec![e2]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
@ -986,12 +1024,12 @@ mod tests {
 | 
			
		||||
            b.0 += 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let a_b_changed = world
 | 
			
		||||
        let a_b_mutated = world
 | 
			
		||||
            .query_mut::<(Or<(Mutated<A>, Mutated<B>)>, Entity)>()
 | 
			
		||||
            .map(|((_a, _b), e)| e)
 | 
			
		||||
            .collect::<Vec<Entity>>();
 | 
			
		||||
        // e1 has mutated A, e3 has mutated B, e2 has mutated A and B, _e4 has no mutated component
 | 
			
		||||
        assert_eq!(a_b_changed, vec![e1, e2, e3]);
 | 
			
		||||
        assert_eq!(a_b_mutated, vec![e1, e2, e3]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
 | 
			
		||||
@ -102,7 +102,7 @@ impl World {
 | 
			
		||||
        unsafe {
 | 
			
		||||
            let index = archetype.allocate(entity);
 | 
			
		||||
            components.put(|ptr, ty, size| {
 | 
			
		||||
                archetype.put_dynamic(ptr, ty, size, index, true);
 | 
			
		||||
                archetype.put_dynamic(ptr, ty, size, index, true, false);
 | 
			
		||||
                true
 | 
			
		||||
            });
 | 
			
		||||
            self.entities.meta[entity.id as usize].location = Location {
 | 
			
		||||
@ -530,7 +530,7 @@ impl World {
 | 
			
		||||
                // Update components in the current archetype
 | 
			
		||||
                let arch = &mut self.archetypes[loc.archetype as usize];
 | 
			
		||||
                components.put(|ptr, ty, size| {
 | 
			
		||||
                    arch.put_dynamic(ptr, ty, size, loc.index, false);
 | 
			
		||||
                    arch.put_dynamic(ptr, ty, size, loc.index, false, true);
 | 
			
		||||
                    true
 | 
			
		||||
                });
 | 
			
		||||
                return Ok(());
 | 
			
		||||
@ -547,7 +547,7 @@ impl World {
 | 
			
		||||
            let old_index = mem::replace(&mut loc.index, target_index);
 | 
			
		||||
            if let Some(moved) =
 | 
			
		||||
                source_arch.move_to(old_index, |ptr, ty, size, is_added, is_mutated| {
 | 
			
		||||
                    target_arch.put_dynamic(ptr, ty, size, target_index, false);
 | 
			
		||||
                    target_arch.put_dynamic(ptr, ty, size, target_index, false, false);
 | 
			
		||||
                    let type_state = target_arch.get_type_state_mut(ty).unwrap();
 | 
			
		||||
                    *type_state.added().as_ptr().add(target_index) = is_added;
 | 
			
		||||
                    *type_state.mutated().as_ptr().add(target_index) = is_mutated;
 | 
			
		||||
@ -557,7 +557,8 @@ impl World {
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            components.put(|ptr, ty, size| {
 | 
			
		||||
                target_arch.put_dynamic(ptr, ty, size, target_index, true);
 | 
			
		||||
                let had_component = source_arch.has_dynamic(ty);
 | 
			
		||||
                target_arch.put_dynamic(ptr, ty, size, target_index, !had_component, had_component);
 | 
			
		||||
                true
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
@ -1003,7 +1004,8 @@ where
 | 
			
		||||
        unsafe {
 | 
			
		||||
            let index = self.archetype.allocate(entity);
 | 
			
		||||
            components.put(|ptr, ty, size| {
 | 
			
		||||
                self.archetype.put_dynamic(ptr, ty, size, index, true);
 | 
			
		||||
                self.archetype
 | 
			
		||||
                    .put_dynamic(ptr, ty, size, index, true, false);
 | 
			
		||||
                true
 | 
			
		||||
            });
 | 
			
		||||
            self.entities.meta[entity.id as usize].location = Location {
 | 
			
		||||
 | 
			
		||||
@ -231,6 +231,7 @@ impl Resources {
 | 
			
		||||
                core::mem::size_of::<T>(),
 | 
			
		||||
                index,
 | 
			
		||||
                added,
 | 
			
		||||
                !added,
 | 
			
		||||
            );
 | 
			
		||||
            std::mem::forget(resource);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user