From f91e5afde0fcee904edc60f759025a048d437fbd Mon Sep 17 00:00:00 2001 From: ira Date: Mon, 24 Oct 2022 21:01:08 +0000 Subject: [PATCH] Implement IntoIterator for ECS wrapper types. (#5096) # Objective Improve ergonomics by passing on the `IntoIterator` impl of the underlying type to wrapper types. ## Solution Implement `IntoIterator` for ECS wrapper types (Mut, Local, Res, etc.). Co-authored-by: devil-ira --- crates/bevy_ecs/src/change_detection.rs | 50 ++++++++++++++++++++++ crates/bevy_ecs/src/system/system_param.rs | 36 ++++++++++++++++ crates/bevy_pbr/src/light.rs | 4 +- 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/change_detection.rs b/crates/bevy_ecs/src/change_detection.rs index f808106a0be00..b8d1f7c196d35 100644 --- a/crates/bevy_ecs/src/change_detection.rs +++ b/crates/bevy_ecs/src/change_detection.rs @@ -245,6 +245,31 @@ pub struct ResMut<'a, T: ?Sized + Resource> { pub(crate) ticks: Ticks<'a>, } +impl<'w, 'a, T: Resource> IntoIterator for &'a ResMut<'w, T> +where + &'a T: IntoIterator, +{ + type Item = <&'a T as IntoIterator>::Item; + type IntoIter = <&'a T as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.value.into_iter() + } +} + +impl<'w, 'a, T: Resource> IntoIterator for &'a mut ResMut<'w, T> +where + &'a mut T: IntoIterator, +{ + type Item = <&'a mut T as IntoIterator>::Item; + type IntoIter = <&'a mut T as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.set_changed(); + self.value.into_iter() + } +} + change_detection_impl!(ResMut<'a, T>, T, Resource); impl_methods!(ResMut<'a, T>, T, Resource); impl_debug!(ResMut<'a, T>, Resource); @@ -298,6 +323,31 @@ pub struct Mut<'a, T: ?Sized> { pub(crate) ticks: Ticks<'a>, } +impl<'w, 'a, T> IntoIterator for &'a Mut<'w, T> +where + &'a T: IntoIterator, +{ + type Item = <&'a T as IntoIterator>::Item; + type IntoIter = <&'a T as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.value.into_iter() + } +} + +impl<'w, 'a, T> IntoIterator for &'a mut Mut<'w, T> +where + &'a mut T: IntoIterator, +{ + type Item = <&'a mut T as IntoIterator>::Item; + type IntoIter = <&'a mut T as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.set_changed(); + self.value.into_iter() + } +} + change_detection_impl!(Mut<'a, T>, T,); impl_methods!(Mut<'a, T>, T,); impl_debug!(Mut<'a, T>,); diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index d064198c61aee..3e19653278375 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -344,6 +344,18 @@ impl<'w, T: Resource> From> for Res<'w, T> { } } +impl<'w, 'a, T: Resource> IntoIterator for &'a Res<'w, T> +where + &'a T: IntoIterator, +{ + type Item = <&'a T as IntoIterator>::Item; + type IntoIter = <&'a T as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.value.into_iter() + } +} + /// The [`SystemParamState`] of [`Res`]. #[doc(hidden)] pub struct ResState { @@ -719,6 +731,30 @@ impl<'a, T: FromWorld + Send + Sync + 'static> DerefMut for Local<'a, T> { } } +impl<'w, 'a, T: FromWorld + Send + 'static> IntoIterator for &'a Local<'w, T> +where + &'a T: IntoIterator, +{ + type Item = <&'a T as IntoIterator>::Item; + type IntoIter = <&'a T as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +impl<'w, 'a, T: FromWorld + Send + 'static> IntoIterator for &'a mut Local<'w, T> +where + &'a mut T: IntoIterator, +{ + type Item = <&'a mut T as IntoIterator>::Item; + type IntoIter = <&'a mut T as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + /// The [`SystemParamState`] of [`Local`]. #[doc(hidden)] pub struct LocalState(pub(crate) SyncCell); diff --git a/crates/bevy_pbr/src/light.rs b/crates/bevy_pbr/src/light.rs index 4d2fc0dca26db..344fff88cb358 100644 --- a/crates/bevy_pbr/src/light.rs +++ b/crates/bevy_pbr/src/light.rs @@ -971,7 +971,7 @@ pub(crate) fn assign_lights_to_clusters( if config.dynamic_resizing() { let mut cluster_index_estimate = 0.0; - for light in lights.iter() { + for light in &lights { let light_sphere = light.sphere(); // Check if the light is within the view frustum @@ -1126,7 +1126,7 @@ pub(crate) fn assign_lights_to_clusters( } let mut update_from_light_intersections = |visible_lights: &mut Vec| { - for light in lights.iter() { + for light in &lights { let light_sphere = light.sphere(); // Check if the light is within the view frustum