Skip to content

Commit

Permalink
Implement IntoIterator for ECS wrapper types. (#5096)
Browse files Browse the repository at this point in the history
# 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 <justthecooldude@gmail.com>
  • Loading branch information
tim-blackbird and tim-blackbird committed Oct 24, 2022
1 parent 6aa2dce commit b291223
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 2 deletions.
50 changes: 50 additions & 0 deletions crates/bevy_ecs/src/change_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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>,);
Expand Down
36 changes: 36 additions & 0 deletions crates/bevy_ecs/src/system/system_param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,18 @@ impl<'w, T: Resource> From<ResMut<'w, T>> 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<T>`].
#[doc(hidden)]
pub struct ResState<T> {
Expand Down Expand Up @@ -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<T>`].
#[doc(hidden)]
pub struct LocalState<T: Send + 'static>(pub(crate) SyncCell<T>);
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_pbr/src/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -1126,7 +1126,7 @@ pub(crate) fn assign_lights_to_clusters(
}

let mut update_from_light_intersections = |visible_lights: &mut Vec<Entity>| {
for light in lights.iter() {
for light in &lights {
let light_sphere = light.sphere();

// Check if the light is within the view frustum
Expand Down

0 comments on commit b291223

Please sign in to comment.