|
1 | 1 | use crate::{
|
2 | 2 | archetype::{Archetype, Archetypes},
|
| 3 | + bundle::Bundle, |
3 | 4 | change_detection::{MaybeThinSlicePtrLocation, Ticks, TicksMut},
|
4 | 5 | component::{Component, ComponentId, Components, StorageType, Tick},
|
5 | 6 | entity::{Entities, Entity, EntityLocation},
|
6 | 7 | query::{Access, DebugCheckedUnwrap, FilteredAccess, WorldQuery},
|
7 | 8 | storage::{ComponentSparseSet, Table, TableRow},
|
8 | 9 | world::{
|
9 |
| - unsafe_world_cell::UnsafeWorldCell, EntityMut, EntityRef, FilteredEntityMut, |
10 |
| - FilteredEntityRef, Mut, Ref, World, |
| 10 | + unsafe_world_cell::UnsafeWorldCell, EntityMut, EntityMutExcept, EntityRef, EntityRefExcept, |
| 11 | + FilteredEntityMut, FilteredEntityRef, Mut, Ref, World, |
11 | 12 | },
|
12 | 13 | };
|
13 | 14 | use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref};
|
14 | 15 | use bevy_utils::all_tuples;
|
| 16 | +use smallvec::SmallVec; |
15 | 17 | use std::{cell::UnsafeCell, marker::PhantomData};
|
16 | 18 |
|
17 | 19 | /// Types that can be fetched from a [`World`] using a [`Query`].
|
@@ -626,27 +628,15 @@ unsafe impl<'a> WorldQuery for FilteredEntityRef<'a> {
|
626 | 628 | unsafe fn set_archetype<'w>(
|
627 | 629 | fetch: &mut Self::Fetch<'w>,
|
628 | 630 | state: &Self::State,
|
629 |
| - archetype: &'w Archetype, |
| 631 | + _: &'w Archetype, |
630 | 632 | _table: &Table,
|
631 | 633 | ) {
|
632 |
| - let mut access = Access::default(); |
633 |
| - state.access.component_reads().for_each(|id| { |
634 |
| - if archetype.contains(id) { |
635 |
| - access.add_component_read(id); |
636 |
| - } |
637 |
| - }); |
638 |
| - fetch.1 = access; |
| 634 | + fetch.1.clone_from(&state.access); |
639 | 635 | }
|
640 | 636 |
|
641 | 637 | #[inline]
|
642 |
| - unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table) { |
643 |
| - let mut access = Access::default(); |
644 |
| - state.access.component_reads().for_each(|id| { |
645 |
| - if table.has_column(id) { |
646 |
| - access.add_component_read(id); |
647 |
| - } |
648 |
| - }); |
649 |
| - fetch.1 = access; |
| 638 | + unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, _: &'w Table) { |
| 639 | + fetch.1.clone_from(&state.access); |
650 | 640 | }
|
651 | 641 |
|
652 | 642 | #[inline]
|
@@ -733,37 +723,15 @@ unsafe impl<'a> WorldQuery for FilteredEntityMut<'a> {
|
733 | 723 | unsafe fn set_archetype<'w>(
|
734 | 724 | fetch: &mut Self::Fetch<'w>,
|
735 | 725 | state: &Self::State,
|
736 |
| - archetype: &'w Archetype, |
| 726 | + _: &'w Archetype, |
737 | 727 | _table: &Table,
|
738 | 728 | ) {
|
739 |
| - let mut access = Access::default(); |
740 |
| - state.access.component_reads().for_each(|id| { |
741 |
| - if archetype.contains(id) { |
742 |
| - access.add_component_read(id); |
743 |
| - } |
744 |
| - }); |
745 |
| - state.access.component_writes().for_each(|id| { |
746 |
| - if archetype.contains(id) { |
747 |
| - access.add_component_write(id); |
748 |
| - } |
749 |
| - }); |
750 |
| - fetch.1 = access; |
| 729 | + fetch.1.clone_from(&state.access); |
751 | 730 | }
|
752 | 731 |
|
753 | 732 | #[inline]
|
754 |
| - unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table) { |
755 |
| - let mut access = Access::default(); |
756 |
| - state.access.component_reads().for_each(|id| { |
757 |
| - if table.has_column(id) { |
758 |
| - access.add_component_read(id); |
759 |
| - } |
760 |
| - }); |
761 |
| - state.access.component_writes().for_each(|id| { |
762 |
| - if table.has_column(id) { |
763 |
| - access.add_component_write(id); |
764 |
| - } |
765 |
| - }); |
766 |
| - fetch.1 = access; |
| 733 | + unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, _: &'w Table) { |
| 734 | + fetch.1.clone_from(&state.access); |
767 | 735 | }
|
768 | 736 |
|
769 | 737 | #[inline]
|
@@ -815,6 +783,201 @@ unsafe impl<'a> QueryData for FilteredEntityMut<'a> {
|
815 | 783 | type ReadOnly = FilteredEntityRef<'a>;
|
816 | 784 | }
|
817 | 785 |
|
| 786 | +/// SAFETY: `EntityRefExcept` guards access to all components in the bundle `B` |
| 787 | +/// and populates `Access` values so that queries that conflict with this access |
| 788 | +/// are rejected. |
| 789 | +unsafe impl<'a, B> WorldQuery for EntityRefExcept<'a, B> |
| 790 | +where |
| 791 | + B: Bundle, |
| 792 | +{ |
| 793 | + type Fetch<'w> = UnsafeWorldCell<'w>; |
| 794 | + type Item<'w> = EntityRefExcept<'w, B>; |
| 795 | + type State = SmallVec<[ComponentId; 4]>; |
| 796 | + |
| 797 | + fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { |
| 798 | + item |
| 799 | + } |
| 800 | + |
| 801 | + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { |
| 802 | + fetch |
| 803 | + } |
| 804 | + |
| 805 | + unsafe fn init_fetch<'w>( |
| 806 | + world: UnsafeWorldCell<'w>, |
| 807 | + _: &Self::State, |
| 808 | + _: Tick, |
| 809 | + _: Tick, |
| 810 | + ) -> Self::Fetch<'w> { |
| 811 | + world |
| 812 | + } |
| 813 | + |
| 814 | + const IS_DENSE: bool = true; |
| 815 | + |
| 816 | + unsafe fn set_archetype<'w>( |
| 817 | + _: &mut Self::Fetch<'w>, |
| 818 | + _: &Self::State, |
| 819 | + _: &'w Archetype, |
| 820 | + _: &'w Table, |
| 821 | + ) { |
| 822 | + } |
| 823 | + |
| 824 | + unsafe fn set_table<'w>(_: &mut Self::Fetch<'w>, _: &Self::State, _: &'w Table) {} |
| 825 | + |
| 826 | + unsafe fn fetch<'w>( |
| 827 | + world: &mut Self::Fetch<'w>, |
| 828 | + entity: Entity, |
| 829 | + _: TableRow, |
| 830 | + ) -> Self::Item<'w> { |
| 831 | + let cell = world.get_entity(entity).unwrap(); |
| 832 | + EntityRefExcept::new(cell) |
| 833 | + } |
| 834 | + |
| 835 | + fn update_component_access( |
| 836 | + state: &Self::State, |
| 837 | + filtered_access: &mut FilteredAccess<ComponentId>, |
| 838 | + ) { |
| 839 | + let mut my_access = Access::new(); |
| 840 | + my_access.read_all_components(); |
| 841 | + for id in state { |
| 842 | + my_access.remove_component_read(*id); |
| 843 | + } |
| 844 | + |
| 845 | + let access = filtered_access.access_mut(); |
| 846 | + assert!( |
| 847 | + access.is_compatible(&my_access), |
| 848 | + "`EntityRefExcept<{}>` conflicts with a previous access in this query.", |
| 849 | + std::any::type_name::<B>(), |
| 850 | + ); |
| 851 | + access.extend(&my_access); |
| 852 | + } |
| 853 | + |
| 854 | + fn init_state(world: &mut World) -> Self::State { |
| 855 | + Self::get_state(world.components()).unwrap() |
| 856 | + } |
| 857 | + |
| 858 | + fn get_state(components: &Components) -> Option<Self::State> { |
| 859 | + let mut ids = SmallVec::new(); |
| 860 | + B::get_component_ids(components, &mut |maybe_id| { |
| 861 | + if let Some(id) = maybe_id { |
| 862 | + ids.push(id); |
| 863 | + } |
| 864 | + }); |
| 865 | + Some(ids) |
| 866 | + } |
| 867 | + |
| 868 | + fn matches_component_set(_: &Self::State, _: &impl Fn(ComponentId) -> bool) -> bool { |
| 869 | + true |
| 870 | + } |
| 871 | +} |
| 872 | + |
| 873 | +/// SAFETY: `Self` is the same as `Self::ReadOnly`. |
| 874 | +unsafe impl<'a, B> QueryData for EntityRefExcept<'a, B> |
| 875 | +where |
| 876 | + B: Bundle, |
| 877 | +{ |
| 878 | + type ReadOnly = Self; |
| 879 | +} |
| 880 | + |
| 881 | +/// SAFETY: `EntityRefExcept` enforces read-only access to its contained |
| 882 | +/// components. |
| 883 | +unsafe impl<'a, B> ReadOnlyQueryData for EntityRefExcept<'a, B> where B: Bundle {} |
| 884 | + |
| 885 | +/// SAFETY: `EntityMutExcept` guards access to all components in the bundle `B` |
| 886 | +/// and populates `Access` values so that queries that conflict with this access |
| 887 | +/// are rejected. |
| 888 | +unsafe impl<'a, B> WorldQuery for EntityMutExcept<'a, B> |
| 889 | +where |
| 890 | + B: Bundle, |
| 891 | +{ |
| 892 | + type Fetch<'w> = UnsafeWorldCell<'w>; |
| 893 | + type Item<'w> = EntityMutExcept<'w, B>; |
| 894 | + type State = SmallVec<[ComponentId; 4]>; |
| 895 | + |
| 896 | + fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { |
| 897 | + item |
| 898 | + } |
| 899 | + |
| 900 | + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { |
| 901 | + fetch |
| 902 | + } |
| 903 | + |
| 904 | + unsafe fn init_fetch<'w>( |
| 905 | + world: UnsafeWorldCell<'w>, |
| 906 | + _: &Self::State, |
| 907 | + _: Tick, |
| 908 | + _: Tick, |
| 909 | + ) -> Self::Fetch<'w> { |
| 910 | + world |
| 911 | + } |
| 912 | + |
| 913 | + const IS_DENSE: bool = true; |
| 914 | + |
| 915 | + unsafe fn set_archetype<'w>( |
| 916 | + _: &mut Self::Fetch<'w>, |
| 917 | + _: &Self::State, |
| 918 | + _: &'w Archetype, |
| 919 | + _: &'w Table, |
| 920 | + ) { |
| 921 | + } |
| 922 | + |
| 923 | + unsafe fn set_table<'w>(_: &mut Self::Fetch<'w>, _: &Self::State, _: &'w Table) {} |
| 924 | + |
| 925 | + unsafe fn fetch<'w>( |
| 926 | + world: &mut Self::Fetch<'w>, |
| 927 | + entity: Entity, |
| 928 | + _: TableRow, |
| 929 | + ) -> Self::Item<'w> { |
| 930 | + let cell = world.get_entity(entity).unwrap(); |
| 931 | + EntityMutExcept::new(cell) |
| 932 | + } |
| 933 | + |
| 934 | + fn update_component_access( |
| 935 | + state: &Self::State, |
| 936 | + filtered_access: &mut FilteredAccess<ComponentId>, |
| 937 | + ) { |
| 938 | + let mut my_access = Access::new(); |
| 939 | + my_access.write_all_components(); |
| 940 | + for id in state { |
| 941 | + my_access.remove_component_read(*id); |
| 942 | + } |
| 943 | + |
| 944 | + let access = filtered_access.access_mut(); |
| 945 | + assert!( |
| 946 | + access.is_compatible(&my_access), |
| 947 | + "`EntityMutExcept<{}>` conflicts with a previous access in this query.", |
| 948 | + std::any::type_name::<B>() |
| 949 | + ); |
| 950 | + access.extend(&my_access); |
| 951 | + } |
| 952 | + |
| 953 | + fn init_state(world: &mut World) -> Self::State { |
| 954 | + Self::get_state(world.components()).unwrap() |
| 955 | + } |
| 956 | + |
| 957 | + fn get_state(components: &Components) -> Option<Self::State> { |
| 958 | + let mut ids = SmallVec::new(); |
| 959 | + B::get_component_ids(components, &mut |maybe_id| { |
| 960 | + if let Some(id) = maybe_id { |
| 961 | + ids.push(id); |
| 962 | + } |
| 963 | + }); |
| 964 | + Some(ids) |
| 965 | + } |
| 966 | + |
| 967 | + fn matches_component_set(_: &Self::State, _: &impl Fn(ComponentId) -> bool) -> bool { |
| 968 | + true |
| 969 | + } |
| 970 | +} |
| 971 | + |
| 972 | +/// SAFETY: All accesses that `EntityRefExcept` provides are also accesses that |
| 973 | +/// `EntityMutExcept` provides. |
| 974 | +unsafe impl<'a, B> QueryData for EntityMutExcept<'a, B> |
| 975 | +where |
| 976 | + B: Bundle, |
| 977 | +{ |
| 978 | + type ReadOnly = EntityRefExcept<'a, B>; |
| 979 | +} |
| 980 | + |
818 | 981 | /// SAFETY:
|
819 | 982 | /// `update_component_access` and `update_archetype_component_access` do nothing.
|
820 | 983 | /// This is sound because `fetch` does not access components.
|
|
0 commit comments