@@ -1110,6 +1110,146 @@ unsafe impl<T: WorldQuery> WorldQuery for Option<T> {
1110
1110
/// SAFETY: [`OptionFetch`] is read only because `T` is read only
1111
1111
unsafe impl < T : ReadOnlyWorldQuery > ReadOnlyWorldQuery for Option < T > { }
1112
1112
1113
+ /// Returns a bool that describes if an entity has the component `T`.
1114
+ ///
1115
+ /// This can be used in a [`Query`](crate::system::Query) if you want to know whether or not entities
1116
+ /// have the component `T` but don't actually care about the component's value.
1117
+ ///
1118
+ /// # Examples
1119
+ ///
1120
+ /// ```
1121
+ /// # use bevy_ecs::component::Component;
1122
+ /// # use bevy_ecs::query::Has;
1123
+ /// # use bevy_ecs::system::IntoSystem;
1124
+ /// # use bevy_ecs::system::Query;
1125
+ /// #
1126
+ /// # #[derive(Component)]
1127
+ /// # struct IsHungry;
1128
+ /// # #[derive(Component)]
1129
+ /// # struct Name { name: &'static str };
1130
+ /// #
1131
+ /// fn food_entity_system(query: Query<(&Name, Has<IsHungry>) >) {
1132
+ /// for (name, is_hungry) in &query {
1133
+ /// if is_hungry{
1134
+ /// println!("{} would like some food.", name.name);
1135
+ /// } else {
1136
+ /// println!("{} has had sufficient.", name.name);
1137
+ /// }
1138
+ /// }
1139
+ /// }
1140
+ /// # bevy_ecs::system::assert_is_system(food_entity_system);
1141
+ /// ```
1142
+ ///
1143
+ /// ```
1144
+ /// # use bevy_ecs::component::Component;
1145
+ /// # use bevy_ecs::query::Has;
1146
+ /// # use bevy_ecs::system::IntoSystem;
1147
+ /// # use bevy_ecs::system::Query;
1148
+ /// #
1149
+ /// # #[derive(Component)]
1150
+ /// # struct Alpha{has_beta: bool};
1151
+ /// # #[derive(Component)]
1152
+ /// # struct Beta { has_alpha: bool };
1153
+ /// #
1154
+ /// // Unlike `Option<&T>`, `Has<T>` is compatible with `&mut T`
1155
+ /// // as it does not actually access any data.
1156
+ /// fn alphabet_entity_system(mut alphas: Query<(&mut Alpha, Has<Beta>)>, mut betas: Query<(&mut Beta, Has<Alpha>)>) {
1157
+ /// for (mut alpha, has_beta) in alphas.iter_mut() {
1158
+ /// alpha.has_beta = has_beta;
1159
+ /// }
1160
+ /// for (mut beta, has_alpha) in betas.iter_mut() {
1161
+ /// beta.has_alpha = has_alpha;
1162
+ /// }
1163
+ /// }
1164
+ /// # bevy_ecs::system::assert_is_system(alphabet_entity_system);
1165
+ /// ```
1166
+ pub struct Has < T > ( PhantomData < T > ) ;
1167
+
1168
+ // SAFETY: `Self::ReadOnly` is the same as `Self`
1169
+ unsafe impl < T : Component > WorldQuery for Has < T > {
1170
+ type Fetch < ' w > = bool ;
1171
+ type Item < ' w > = bool ;
1172
+ type ReadOnly = Self ;
1173
+ type State = ComponentId ;
1174
+
1175
+ fn shrink < ' wlong : ' wshort , ' wshort > ( item : Self :: Item < ' wlong > ) -> Self :: Item < ' wshort > {
1176
+ item
1177
+ }
1178
+
1179
+ const IS_DENSE : bool = {
1180
+ match T :: Storage :: STORAGE_TYPE {
1181
+ StorageType :: Table => true ,
1182
+ StorageType :: SparseSet => false ,
1183
+ }
1184
+ } ;
1185
+
1186
+ const IS_ARCHETYPAL : bool = true ;
1187
+
1188
+ #[ inline]
1189
+ unsafe fn init_fetch < ' w > (
1190
+ _world : UnsafeWorldCell < ' w > ,
1191
+ _state : & Self :: State ,
1192
+ _last_run : Tick ,
1193
+ _this_run : Tick ,
1194
+ ) -> Self :: Fetch < ' w > {
1195
+ false
1196
+ }
1197
+
1198
+ unsafe fn clone_fetch < ' w > ( fetch : & Self :: Fetch < ' w > ) -> Self :: Fetch < ' w > {
1199
+ * fetch
1200
+ }
1201
+
1202
+ #[ inline]
1203
+ unsafe fn set_archetype < ' w > (
1204
+ fetch : & mut Self :: Fetch < ' w > ,
1205
+ state : & Self :: State ,
1206
+ archetype : & ' w Archetype ,
1207
+ _table : & Table ,
1208
+ ) {
1209
+ * fetch = archetype. contains ( * state) ;
1210
+ }
1211
+
1212
+ #[ inline]
1213
+ unsafe fn set_table < ' w > ( fetch : & mut Self :: Fetch < ' w > , state : & Self :: State , table : & ' w Table ) {
1214
+ * fetch = table. has_column ( * state) ;
1215
+ }
1216
+
1217
+ #[ inline( always) ]
1218
+ unsafe fn fetch < ' w > (
1219
+ fetch : & mut Self :: Fetch < ' w > ,
1220
+ _entity : Entity ,
1221
+ _table_row : TableRow ,
1222
+ ) -> Self :: Item < ' w > {
1223
+ * fetch
1224
+ }
1225
+
1226
+ fn update_component_access ( _state : & Self :: State , _access : & mut FilteredAccess < ComponentId > ) {
1227
+ // Do nothing as presence of `Has<T>` never affects whether two queries are disjoint
1228
+ }
1229
+
1230
+ fn update_archetype_component_access (
1231
+ _state : & Self :: State ,
1232
+ _archetype : & Archetype ,
1233
+ _access : & mut Access < ArchetypeComponentId > ,
1234
+ ) {
1235
+ }
1236
+
1237
+ fn init_state ( world : & mut World ) -> ComponentId {
1238
+ world. init_component :: < T > ( )
1239
+ }
1240
+
1241
+ fn matches_component_set (
1242
+ _state : & Self :: State ,
1243
+ _set_contains_id : & impl Fn ( ComponentId ) -> bool ,
1244
+ ) -> bool {
1245
+ // `Has<T>` always matches
1246
+ true
1247
+ }
1248
+ }
1249
+
1250
+ /// SAFETY: [`Has`] is read only
1251
+ unsafe impl < T : Component > ReadOnlyWorldQuery for Has < T > { }
1252
+
1113
1253
macro_rules! impl_tuple_fetch {
1114
1254
( $( ( $name: ident, $state: ident) ) ,* ) => {
1115
1255
#[ allow( non_snake_case) ]
0 commit comments