1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
#[macro_export] macro_rules! either_many { (@__first $first:tt $(, $($others:tt),+)?) => { $first }; (readonly $(#[$($m:meta),*])? $name:ident $(< $($lf:lifetime),* $(, )? >)?, $($varn:ident($($vart:tt)+)),+ $(, )?) => { $crate::either_many!($(#[$($m),*])? $name $(< $($lf),*>)?, $($varn($($vart)+)),+); $crate::exports::paste!{ unsafe impl $(< $($lf),*>)? ::bevy::ecs::query::ReadOnlyFetch for [<__ $name:lower>]::[<$name Fetch>] $(< $($lf),*>)? {} } }; ($(#[$($m:meta),*])? $name:ident $(< $($lf:lifetime),* >)?, $($varn:ident($($vart:tt)+)),+ $(, )?) => { $crate::exports::paste!{ $(#[$($m),*])? #[doc = "A [world query](::bevy::ecs::query::WorldQuery) allowing you to match one of " "multiple other [world queries](::bevy::ecs::query::WorldQuery).\n" "There is exactly one variant per [world query](::bevy::ecs::query::WorldQuery) " "that [`" $name "`] can fulfill.\n\nIn priority order, [`" $name "`] matches:" $("\n * [`" $name "::" $varn "(_)`](" $name "::" $varn ")")+ ] pub enum $name $(< $($lf),*>)? { $($varn(< <$($vart)+ as ::bevy::ecs::query::WorldQuery>::Fetch as ::bevy::ecs::query::Fetch<'static> >::Item)),+ } } $crate::exports::paste!{mod [<__ $name:lower>] { use super::*; use ::bevy::prelude::*; use ::bevy::ecs::{storage::*, component::*, archetype::*, query::*}; #[derive(Copy, Clone)] enum Matches { $($varn),+ } impl Matches { const FIRST: Self = { use Matches::*; $crate::either_many!(@__first $($varn),+) }; } #[allow(non_snake_case)] pub struct [<$name State>] $(< $($lf),*>)? { $($varn: <$($vart)+ as WorldQuery>::State),+ } unsafe impl $(< $($lf),*>)? FetchState for [<$name State>] $(< $($lf),*>)? { fn init(world: &mut World) -> Self { Self { $($varn: <$($vart)+ as WorldQuery>::State::init(world)),+ } } fn update_component_access(&self, access: &mut FilteredAccess<ComponentId>) { $(self.$varn.update_component_access(access);)+ } fn update_archetype_component_access( &self, archetype: &Archetype, access: &mut Access<ArchetypeComponentId>, ) { $(self.$varn.update_archetype_component_access(archetype, access);)+ } fn matches_archetype(&self, archetype: &Archetype) -> bool { $(self.$varn.matches_archetype(archetype))||+ } fn matches_table(&self, table: &Table) -> bool { $(self.$varn.matches_table(table))||+ } } #[allow(non_snake_case)] pub struct [<$name Fetch>] $(< $($lf),*>)? { matches: Matches, $($varn: <$($vart)+ as WorldQuery>::Fetch),+ } impl $(< $($lf),*>)? Fetch<'_> for [<$name Fetch>] $(< $($lf),*>)? { type Item = $name $(< $($lf),*>)?; type State = [<$name State>] $(< $($lf),*>)?; fn is_dense(&self) -> bool { $(self.$varn.is_dense())||+ } unsafe fn init( world: &World, state: &Self::State, last_change_tick: u32, change_tick: u32, ) -> Self { Self { matches: Matches::FIRST, $($varn: <$($vart)+ as WorldQuery>::Fetch::init( world, &state.$varn, last_change_tick, change_tick, ),)+ } } unsafe fn set_archetype( &mut self, state: &Self::State, archetype: &Archetype, tables: &Tables, ) { $(if state.$varn.matches_archetype(archetype) { self.$varn.set_archetype(&state.$varn, archetype, tables); self.matches = { use Matches::*; $varn }; })else+ else if cfg!(debug_assertions) { unreachable!("None of the variants were matched. At least one should be."); } } unsafe fn set_table(&mut self, state: &Self::State, table: &Table) { $(if state.$varn.matches_table(table) { self.$varn.set_table(&state.$varn, table); self.matches = { use Matches::*; $varn }; })else+ else if cfg!(debug_assertions) { unreachable!("None of the variants were matched. At least one should be."); } } unsafe fn archetype_fetch(&mut self, archetype_index: usize) -> Self::Item { use Matches::*; match self.matches { $($varn => $name::$varn(self.$varn.archetype_fetch(archetype_index)),)+ } } unsafe fn table_fetch(&mut self, table_row: usize) -> Self::Item { use Matches::*; match self.matches { $($varn => $name::$varn(self.$varn.table_fetch(table_row)),)+ } } } impl $(< $($lf),*>)? WorldQuery for $name $(< $($lf),*>)? { type Fetch = [<$name Fetch>] $(< $($lf),*>)?; type State = [<$name State>] $(< $($lf),*>)?; } }} }; }