leudz / shipyard

Entity Component System focused on usability and flexibility.
Other
750 stars 45 forks source link

clear_all_modified function doesn't work in test code #166

Closed notinmybackyaard closed 1 year ago

notinmybackyaard commented 1 year ago

Hello! I wrote a test to understand how to tracking options work in workload, but I found something weird that looks like clear_all_modified function doesn't work in a code below.

    #[test]
    fn track_modification() {
        #[derive(Component, Debug)]
        #[track(Modification)]
        struct Hello(i32);

        fn insert(mut entities: EntitiesViewMut, mut hellos: ViewMut<Hello>) {
            entities.add_entity(&mut hellos, Hello(1));

            assert_eq!(hellos.modified().iter().count(), 0);
            hellos.clear_all_modified();
        }
        fn write_value(mut hellos: ViewMut<Hello>) {
            (&mut hellos)
                .get(EntityId::from_inner(1).unwrap())
                .unwrap()
                .0 = 1;

            assert_eq!(hellos.modified().iter().count(), 1);
            hellos.clear_all_modified();
        }
        fn read_value(mut hellos: ViewMut<Hello>) {
            let _ = (&mut hellos)
                .get(EntityId::from_inner(1).unwrap())
                .unwrap()
                .0;

            assert_eq!(hellos.modified().iter().count(), 0);
            hellos.clear_all_modified();
        }
        {
            let world = World::new();
            let which_is_modification = || (insert, write_value, read_value).into_workload();
            world.add_workload(which_is_modification);
            world.run_workload(which_is_modification).unwrap();
        }
}

I expected not to fail in whole cases, but it failed in read_value function. assert_eq!(hellos.modified().iter().count(), 0); I think previous system function write_value didn't clear the modified flag. Would you tell me whether this is intented or not?

leudz commented 1 year ago

Hey! Your test is failing because workloads keep a separate counter. clear_* will not reset their counter. The idea behind it is that all systems in workloads are not affected by other systems.

The doc is missing a pretty big piece of information: clear_* methods are only intended to be used outside workloads. The guide mentions it but not the doc...

0.6 reworked tracking, in previous version you had to call clear_* in workloads too. It caused problems, sometimes there was no good place to put the clear_* call. For example if you have a workload like this: (modify_sys, read1_sys, other_sys, read1_sys, read2_sys). If you put the clear_* call after the first read1_sys then read2_sys will be missing some tracking info. But if you put the call somewhere else then read1_sys will not be correct.

Here's a modified version of your test to demonstrate the workload auto-clear. I removed the clear_all_modified calls and added read_value a second time in the workload.

#[test]
fn track_modification() {
    #[derive(Component, Debug)]
    #[track(Modification)]
    struct Hello(i32);

    fn insert(mut entities: EntitiesViewMut, mut hellos: ViewMut<Hello>) {
        entities.add_entity(&mut hellos, Hello(1));

        assert_eq!(hellos.modified().iter().count(), 0);
    }
    fn write_value(mut hellos: ViewMut<Hello>) {
        (&mut hellos)
            .get(EntityId::from_inner(1).unwrap())
            .unwrap()
            .0 = 1;

        assert_eq!(hellos.modified().iter().count(), 1);
    }
    fn read_value(mut hellos: ViewMut<Hello>) {
        let _ = (&mut hellos)
            .get(EntityId::from_inner(1).unwrap())
            .unwrap()
            .0;

        assert_eq!(hellos.modified().iter().count(), 1);
    }
    {
        let world = World::new();
        let which_is_modification = || (insert, write_value, read_value, read_value).into_workload();
        world.add_workload(which_is_modification);
        world.run_workload(which_is_modification).unwrap();
    }
}
notinmybackyaard commented 1 year ago

Oh, It is designed not to be used inside the workload.. I got it. Thank you very much, it was a great help. I am always grateful to you! :>