Skip to content

Commit

Permalink
Implements std::ops operator traits for Mut.
Browse files Browse the repository at this point in the history
    # Objective

    No one likes how tuple structs and Mut force you to write things like: health.0 += 10;

    # Solution

    Implement AddAssign on Mut.

    impl <'a, T, U> AddAssign<U> for Mut<'a, T> where T: AddAssign<U> {
        fn add_assign(&mut self, rhs: U) {
            *self.value += rhs;
        }
    }

    then in our game

    impl AddAssign<u32> for Health {
        fn add_assign(&mut self, rhs: u32) {
            self.0 += rhs.0;
        }
    }

    pub fn health_system(
        mut query: Query<&mut Health>
    ) {
        query.for_each_mut(|mut health| {
            health += 10;
        });
    }
  • Loading branch information
ickshonpe committed Feb 6, 2022
1 parent fa15a91 commit d87f997
Showing 1 changed file with 240 additions and 1 deletion.
241 changes: 240 additions & 1 deletion crates/bevy_ecs/src/change_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
use crate::{component::ComponentTicks, system::Resource};
#[cfg(feature = "bevy_reflect")]
use bevy_reflect::Reflect;
use std::ops::{Deref, DerefMut};
use std::ops::{
Add, AddAssign, BitAnd, BitOr, BitOrAssign, BitXor, Deref, DerefMut, Div, DivAssign, Index,
IndexMut, Mul, MulAssign, Neg, Not, RangeBounds, Rem, RemAssign, Shl, ShlAssign, Shr,
ShrAssign, Sub, SubAssign,
};

/// Types that implement reliable change detection.
///
Expand Down Expand Up @@ -184,6 +188,241 @@ pub struct Mut<'a, T> {
pub(crate) ticks: Ticks<'a>,
}

impl<'a, T, U, V> Add<U> for Mut<'a, T>
where
T: Add<U, Output = V> + Copy,
{
type Output = V;

fn add(self, rhs: U) -> Self::Output {
*self.value + rhs
}
}

impl<'a, T, U> AddAssign<U> for Mut<'a, T>
where
T: AddAssign<U>,
{
fn add_assign(&mut self, rhs: U) {
*self.value += rhs;
}
}

impl<'a, T, U, V> BitAnd<U> for Mut<'a, T>
where
T: BitAnd<U, Output = V> + Copy,
{
type Output = V;

fn bitand(self, rhs: U) -> Self::Output {
*self & rhs
}
}

impl<'a, T, U, V> BitOr<U> for Mut<'a, T>
where
T: BitOr<U, Output = V> + Copy,
{
type Output = V;

fn bitor(self, rhs: U) -> Self::Output {
*self | rhs
}
}

impl<'a, T, U> BitOrAssign<U> for Mut<'a, T>
where
T: BitOrAssign<U>,
{
fn bitor_assign(&mut self, rhs: U) {
*self.value |= rhs;
}
}

impl<'a, T, U, V> BitXor<U> for Mut<'a, T>
where
T: BitXor<U, Output = V> + Copy,
{
type Output = V;

fn bitxor(self, rhs: U) -> Self::Output {
*self ^ rhs
}
}

impl<'a, T, U> Div<U> for Mut<'a, T>
where
T: Div<U, Output = T> + Copy,
{
type Output = T;

fn div(self, rhs: U) -> Self::Output {
*self.value / rhs
}
}

impl<'a, T, U> DivAssign<U> for Mut<'a, T>
where
T: DivAssign<U>,
{
fn div_assign(&mut self, rhs: U) {
*self.value /= rhs;
}
}

impl<'a, T, U> Mul<U> for Mut<'a, T>
where
T: Mul<U, Output = T> + Copy,
{
type Output = T;

fn mul(self, rhs: U) -> Self::Output {
*self.value * rhs
}
}

impl<'a, T, U> MulAssign<U> for Mut<'a, T>
where
T: MulAssign<U>,
{
fn mul_assign(&mut self, rhs: U) {
*self.value *= rhs;
}
}

impl<'a, T> RangeBounds<T> for Mut<'a, T>
where
T: RangeBounds<T>,
{
fn start_bound(&self) -> std::ops::Bound<&T> {
self.as_ref().start_bound()
}

fn end_bound(&self) -> std::ops::Bound<&T> {
self.as_ref().end_bound()
}
}

impl<'a, T, U> Rem<T> for Mut<'a, T>
where
T: Rem<T, Output = U> + Copy,
{
type Output = U;
fn rem(self, rhs: T) -> Self::Output {
*self % rhs
}
}

impl<'a, T, U> RemAssign<U> for Mut<'a, T>
where
T: RemAssign<U>,
{
fn rem_assign(&mut self, rhs: U) {
*self.value %= rhs;
}
}

impl<'a, T, U> Shl<T> for Mut<'a, T>
where
T: Shl<T, Output = U> + Copy,
{
type Output = U;
fn shl(self, rhs: T) -> Self::Output {
*self << rhs
}
}

impl<'a, T, U> ShlAssign<U> for Mut<'a, T>
where
T: ShlAssign<U>,
{
fn shl_assign(&mut self, rhs: U) {
*self.value <<= rhs;
}
}

impl<'a, T, U> Shr<T> for Mut<'a, T>
where
T: Shr<T, Output = U> + Copy,
{
type Output = U;
fn shr(self, rhs: T) -> Self::Output {
*self >> rhs
}
}

impl<'a, T, U> ShrAssign<U> for Mut<'a, T>
where
T: ShrAssign<U>,
{
fn shr_assign(&mut self, rhs: U) {
*self.value >>= rhs;
}
}

impl<'a, T, U> SubAssign<U> for Mut<'a, T>
where
T: SubAssign<U>,
{
fn sub_assign(&mut self, rhs: U) {
*self.value -= rhs;
}
}

impl<'a, T, U> Sub<U> for Mut<'a, T>
where
T: Sub<U, Output = T>,
T: Copy,
{
type Output = T;

fn sub(self, rhs: U) -> Self::Output {
*self.value - rhs
}
}

impl<'a, T, U, V> Index<U> for Mut<'a, T>
where
T: Index<U, Output = V>,
{
type Output = V;

fn index(&self, index: U) -> &Self::Output {
&self.as_ref()[index]
}
}

impl<'a, T, U, V> IndexMut<U> for Mut<'a, T>
where
T: IndexMut<U, Output = V>,
{
fn index_mut(&mut self, index: U) -> &mut Self::Output {
&mut self.as_mut()[index]
}
}

impl<'a, T, U> Neg for Mut<'a, T>
where
T: Neg<Output = U> + Copy,
{
type Output = U;

fn neg(self) -> Self::Output {
-*self
}
}

impl<'a, T, U> Not for Mut<'a, T>
where
T: Not<Output = U> + Copy,
{
type Output = U;

fn not(self) -> Self::Output {
!*self
}
}

change_detection_impl!(Mut<'a, T>, T,);
impl_into_inner!(Mut<'a, T>, T,);
impl_debug!(Mut<'a, T>,);
Expand Down

0 comments on commit d87f997

Please sign in to comment.