Skip to main content

bevy_math/rects/
rect.rs

1use crate::{IRect, URect, Vec2};
2
3#[cfg(feature = "bevy_reflect")]
4use bevy_reflect::{std_traits::ReflectDefault, Reflect};
5#[cfg(all(feature = "serialize", feature = "bevy_reflect"))]
6use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
7
8/// A rectangle defined by two opposite corners.
9///
10/// The rectangle is axis aligned, and defined by its minimum and maximum coordinates,
11/// stored in `Rect::min` and `Rect::max`, respectively. The minimum/maximum invariant
12/// must be upheld by the user when directly assigning the fields, otherwise some methods
13/// produce invalid results. It is generally recommended to use one of the constructor
14/// methods instead, which will ensure this invariant is met, unless you already have
15/// the minimum and maximum corners.
16#[repr(C)]
17#[derive(#[automatically_derived]
impl ::core::default::Default for Rect {
    #[inline]
    fn default() -> Rect {
        Rect {
            min: ::core::default::Default::default(),
            max: ::core::default::Default::default(),
        }
    }
}Default, #[automatically_derived]
impl ::core::clone::Clone for Rect {
    #[inline]
    fn clone(&self) -> Rect {
        let _: ::core::clone::AssertParamIsClone<Vec2>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Rect { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for Rect {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "Rect", "min",
            &self.min, "max", &&self.max)
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for Rect {
    #[inline]
    fn eq(&self, other: &Rect) -> bool {
        self.min == other.min && self.max == other.max
    }
}PartialEq)]
18#[cfg_attr(feature = "serialize", derive(#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl _serde::Serialize for Rect {
            fn serialize<__S>(&self, __serializer: __S)
                -> _serde::__private228::Result<__S::Ok, __S::Error> where
                __S: _serde::Serializer {
                let mut __serde_state =
                    _serde::Serializer::serialize_struct(__serializer, "Rect",
                            false as usize + 1 + 1)?;
                _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
                        "min", &self.min)?;
                _serde::ser::SerializeStruct::serialize_field(&mut __serde_state,
                        "max", &self.max)?;
                _serde::ser::SerializeStruct::end(__serde_state)
            }
        }
    };serde::Serialize, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
    {
        #[allow(unused_extern_crates, clippy :: useless_attribute)]
        extern crate serde as _serde;
        ;
        #[automatically_derived]
        impl<'de> _serde::Deserialize<'de> for Rect {
            fn deserialize<__D>(__deserializer: __D)
                -> _serde::__private228::Result<Self, __D::Error> where
                __D: _serde::Deserializer<'de> {
                #[allow(non_camel_case_types)]
                #[doc(hidden)]
                enum __Field { __field0, __field1, __ignore, }
                #[doc(hidden)]
                struct __FieldVisitor;
                #[automatically_derived]
                impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
                    type Value = __Field;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private228::Formatter)
                        -> _serde::__private228::fmt::Result {
                        _serde::__private228::Formatter::write_str(__formatter,
                            "field identifier")
                    }
                    fn visit_u64<__E>(self, __value: u64)
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            0u64 => _serde::__private228::Ok(__Field::__field0),
                            1u64 => _serde::__private228::Ok(__Field::__field1),
                            _ => _serde::__private228::Ok(__Field::__ignore),
                        }
                    }
                    fn visit_str<__E>(self, __value: &str)
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            "min" => _serde::__private228::Ok(__Field::__field0),
                            "max" => _serde::__private228::Ok(__Field::__field1),
                            _ => { _serde::__private228::Ok(__Field::__ignore) }
                        }
                    }
                    fn visit_bytes<__E>(self, __value: &[u8])
                        -> _serde::__private228::Result<Self::Value, __E> where
                        __E: _serde::de::Error {
                        match __value {
                            b"min" => _serde::__private228::Ok(__Field::__field0),
                            b"max" => _serde::__private228::Ok(__Field::__field1),
                            _ => { _serde::__private228::Ok(__Field::__ignore) }
                        }
                    }
                }
                #[automatically_derived]
                impl<'de> _serde::Deserialize<'de> for __Field {
                    #[inline]
                    fn deserialize<__D>(__deserializer: __D)
                        -> _serde::__private228::Result<Self, __D::Error> where
                        __D: _serde::Deserializer<'de> {
                        _serde::Deserializer::deserialize_identifier(__deserializer,
                            __FieldVisitor)
                    }
                }
                #[doc(hidden)]
                struct __Visitor<'de> {
                    marker: _serde::__private228::PhantomData<Rect>,
                    lifetime: _serde::__private228::PhantomData<&'de ()>,
                }
                #[automatically_derived]
                impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
                    type Value = Rect;
                    fn expecting(&self,
                        __formatter: &mut _serde::__private228::Formatter)
                        -> _serde::__private228::fmt::Result {
                        _serde::__private228::Formatter::write_str(__formatter,
                            "struct Rect")
                    }
                    #[inline]
                    fn visit_seq<__A>(self, mut __seq: __A)
                        -> _serde::__private228::Result<Self::Value, __A::Error>
                        where __A: _serde::de::SeqAccess<'de> {
                        let __field0 =
                            match _serde::de::SeqAccess::next_element::<Vec2>(&mut __seq)?
                                {
                                _serde::__private228::Some(__value) => __value,
                                _serde::__private228::None =>
                                    return _serde::__private228::Err(_serde::de::Error::invalid_length(0usize,
                                                &"struct Rect with 2 elements")),
                            };
                        let __field1 =
                            match _serde::de::SeqAccess::next_element::<Vec2>(&mut __seq)?
                                {
                                _serde::__private228::Some(__value) => __value,
                                _serde::__private228::None =>
                                    return _serde::__private228::Err(_serde::de::Error::invalid_length(1usize,
                                                &"struct Rect with 2 elements")),
                            };
                        _serde::__private228::Ok(Rect {
                                min: __field0,
                                max: __field1,
                            })
                    }
                    #[inline]
                    fn visit_map<__A>(self, mut __map: __A)
                        -> _serde::__private228::Result<Self::Value, __A::Error>
                        where __A: _serde::de::MapAccess<'de> {
                        let mut __field0: _serde::__private228::Option<Vec2> =
                            _serde::__private228::None;
                        let mut __field1: _serde::__private228::Option<Vec2> =
                            _serde::__private228::None;
                        while let _serde::__private228::Some(__key) =
                                _serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
                            match __key {
                                __Field::__field0 => {
                                    if _serde::__private228::Option::is_some(&__field0) {
                                        return _serde::__private228::Err(<__A::Error as
                                                        _serde::de::Error>::duplicate_field("min"));
                                    }
                                    __field0 =
                                        _serde::__private228::Some(_serde::de::MapAccess::next_value::<Vec2>(&mut __map)?);
                                }
                                __Field::__field1 => {
                                    if _serde::__private228::Option::is_some(&__field1) {
                                        return _serde::__private228::Err(<__A::Error as
                                                        _serde::de::Error>::duplicate_field("max"));
                                    }
                                    __field1 =
                                        _serde::__private228::Some(_serde::de::MapAccess::next_value::<Vec2>(&mut __map)?);
                                }
                                _ => {
                                    let _ =
                                        _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
                                }
                            }
                        }
                        let __field0 =
                            match __field0 {
                                _serde::__private228::Some(__field0) => __field0,
                                _serde::__private228::None =>
                                    _serde::__private228::de::missing_field("min")?,
                            };
                        let __field1 =
                            match __field1 {
                                _serde::__private228::Some(__field1) => __field1,
                                _serde::__private228::None =>
                                    _serde::__private228::de::missing_field("max")?,
                            };
                        _serde::__private228::Ok(Rect {
                                min: __field0,
                                max: __field1,
                            })
                    }
                }
                #[doc(hidden)]
                const FIELDS: &'static [&'static str] = &["min", "max"];
                _serde::Deserializer::deserialize_struct(__deserializer,
                    "Rect", FIELDS,
                    __Visitor {
                        marker: _serde::__private228::PhantomData::<Rect>,
                        lifetime: _serde::__private228::PhantomData,
                    })
            }
        }
    };serde::Deserialize))]
19#[cfg_attr(
20    feature = "bevy_reflect",
21    derive(const _: () =
    {
        impl bevy_reflect::GetTypeRegistration for Rect where  {
            fn get_type_registration() -> bevy_reflect::TypeRegistration {
                let mut registration =
                    bevy_reflect::TypeRegistration::of::<Self>();
                registration.insert::<bevy_reflect::ReflectFromPtr>(bevy_reflect::FromType::<Self>::from_type());
                registration.insert::<bevy_reflect::ReflectFromReflect>(bevy_reflect::FromType::<Self>::from_type());
                registration.register_type_data::<ReflectDefault, Self>();
                registration.register_type_data::<ReflectSerialize, Self>();
                registration.register_type_data::<ReflectDeserialize, Self>();
                registration
            }
            #[inline(never)]
            fn register_type_dependencies(registry:
                    &mut bevy_reflect::TypeRegistry) {
                <Vec2 as
                        bevy_reflect::__macro_exports::RegisterForReflection>::__register(registry);
            }
        }
        impl bevy_reflect::Typed for Rect where  {
            #[inline]
            fn type_info() -> &'static bevy_reflect::TypeInfo {
                static CELL: bevy_reflect::utility::NonGenericTypeInfoCell =
                    bevy_reflect::utility::NonGenericTypeInfoCell::new();
                CELL.get_or_set(||
                        {
                            bevy_reflect::TypeInfo::Struct(bevy_reflect::structs::StructInfo::new::<Self>(&[bevy_reflect::NamedField::new::<Vec2>("min"),
                                                bevy_reflect::NamedField::new::<Vec2>("max")]))
                        })
            }
        }
        #[allow(deprecated, reason =
        "derives on a deprecated type shouldn't be considered a usage")]
        impl bevy_reflect::TypePath for Rect where  {
            fn type_path() -> &'static str { "bevy_math::rects::rect::Rect" }
            fn short_type_path() -> &'static str { "Rect" }
            fn type_ident() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("Rect")
            }
            fn crate_name() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_math::rects::rect".split(':').next().unwrap())
            }
            fn module_path() -> ::core::option::Option<&'static str> {
                ::core::option::Option::Some("bevy_math::rects::rect")
            }
        }
        impl bevy_reflect::Reflect for Rect where  {
            #[inline]
            fn into_any(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn ::core::any::Any> {
                self
            }
            #[inline]
            fn as_any(&self) -> &dyn ::core::any::Any { self }
            #[inline]
            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any { self }
            #[inline]
            fn into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect> {
                self
            }
            #[inline]
            fn as_reflect(&self) -> &dyn bevy_reflect::Reflect { self }
            #[inline]
            fn as_reflect_mut(&mut self) -> &mut dyn bevy_reflect::Reflect {
                self
            }
            #[inline]
            fn set(&mut self,
                value:
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>)
                ->
                    ::core::result::Result<(),
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>> {
                *self = <dyn bevy_reflect::Reflect>::take(value)?;
                ::core::result::Result::Ok(())
            }
        }
        impl bevy_reflect::structs::Struct for Rect where  {
            fn field(&self, name: &str)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match name {
                    "min" => ::core::option::Option::Some(&self.min),
                    "max" => ::core::option::Option::Some(&self.max),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_mut(&mut self, name: &str)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match name {
                    "min" => ::core::option::Option::Some(&mut self.min),
                    "max" => ::core::option::Option::Some(&mut self.max),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at(&self, index: usize)
                -> ::core::option::Option<&dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&self.min),
                    1usize => ::core::option::Option::Some(&self.max),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_at_mut(&mut self, index: usize)
                ->
                    ::core::option::Option<&mut dyn bevy_reflect::PartialReflect> {
                match index {
                    0usize => ::core::option::Option::Some(&mut self.min),
                    1usize => ::core::option::Option::Some(&mut self.max),
                    _ => ::core::option::Option::None,
                }
            }
            fn name_at(&self, index: usize) -> ::core::option::Option<&str> {
                match index {
                    0usize => ::core::option::Option::Some("min"),
                    1usize => ::core::option::Option::Some("max"),
                    _ => ::core::option::Option::None,
                }
            }
            fn index_of_name(&self, name: &str)
                -> ::core::option::Option<usize> {
                match name {
                    "min" => ::core::option::Option::Some(0usize),
                    "max" => ::core::option::Option::Some(1usize),
                    _ => ::core::option::Option::None,
                }
            }
            fn field_len(&self) -> usize { 2usize }
            fn iter_fields(&self) -> bevy_reflect::structs::FieldIter {
                bevy_reflect::structs::FieldIter::new(self)
            }
            fn to_dynamic_struct(&self)
                -> bevy_reflect::structs::DynamicStruct {
                let mut dynamic: bevy_reflect::structs::DynamicStruct =
                    ::core::default::Default::default();
                dynamic.set_represented_type(bevy_reflect::PartialReflect::get_represented_type_info(self));
                dynamic.insert_boxed("min",
                    bevy_reflect::PartialReflect::to_dynamic(&self.min));
                dynamic.insert_boxed("max",
                    bevy_reflect::PartialReflect::to_dynamic(&self.max));
                dynamic
            }
        }
        impl bevy_reflect::PartialReflect for Rect where  {
            #[inline]
            fn get_represented_type_info(&self)
                -> ::core::option::Option<&'static bevy_reflect::TypeInfo> {
                ::core::option::Option::Some(<Self as
                            bevy_reflect::Typed>::type_info())
            }
            #[inline]
            fn try_apply(&mut self, value: &dyn bevy_reflect::PartialReflect)
                -> ::core::result::Result<(), bevy_reflect::ApplyError> {
                if let bevy_reflect::ReflectRef::Struct(struct_value) =
                        bevy_reflect::PartialReflect::reflect_ref(value) {
                    for (name, value) in
                        bevy_reflect::structs::Struct::iter_fields(struct_value) {
                        if let ::core::option::Option::Some(v) =
                                bevy_reflect::structs::Struct::field_mut(self, name) {
                            bevy_reflect::PartialReflect::try_apply(v, value)?;
                        }
                    }
                } else {
                    return ::core::result::Result::Err(bevy_reflect::ApplyError::MismatchedKinds {
                                from_kind: bevy_reflect::PartialReflect::reflect_kind(value),
                                to_kind: bevy_reflect::ReflectKind::Struct,
                            });
                }
                ::core::result::Result::Ok(())
            }
            #[inline]
            fn reflect_kind(&self) -> bevy_reflect::ReflectKind {
                bevy_reflect::ReflectKind::Struct
            }
            #[inline]
            fn reflect_ref(&self) -> bevy_reflect::ReflectRef {
                bevy_reflect::ReflectRef::Struct(self)
            }
            #[inline]
            fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut {
                bevy_reflect::ReflectMut::Struct(self)
            }
            #[inline]
            fn reflect_owned(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                -> bevy_reflect::ReflectOwned {
                bevy_reflect::ReflectOwned::Struct(self)
            }
            #[inline]
            fn try_into_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect>> {
                ::core::result::Result::Ok(self)
            }
            #[inline]
            fn try_as_reflect(&self)
                -> ::core::option::Option<&dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn try_as_reflect_mut(&mut self)
                -> ::core::option::Option<&mut dyn bevy_reflect::Reflect> {
                ::core::option::Option::Some(self)
            }
            #[inline]
            fn into_partial_reflect(self:
                    bevy_reflect::__macro_exports::alloc_utils::Box<Self>)
                ->
                    bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::PartialReflect> {
                self
            }
            #[inline]
            fn as_partial_reflect(&self)
                -> &dyn bevy_reflect::PartialReflect {
                self
            }
            #[inline]
            fn as_partial_reflect_mut(&mut self)
                -> &mut dyn bevy_reflect::PartialReflect {
                self
            }
            fn reflect_partial_eq(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<bool> {
                let value =
                    <dyn bevy_reflect::PartialReflect>::try_downcast_ref::<Self>(value);
                if let ::core::option::Option::Some(value) = value {
                    ::core::option::Option::Some(::core::cmp::PartialEq::eq(self,
                            value))
                } else { ::core::option::Option::Some(false) }
            }
            fn reflect_partial_cmp(&self,
                value: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<::core::cmp::Ordering> {
                (bevy_reflect::structs::struct_partial_cmp)(self, value)
            }
            fn debug(&self, f: &mut ::core::fmt::Formatter<'_>)
                -> ::core::fmt::Result {
                ::core::fmt::Debug::fmt(self, f)
            }
            #[inline]
            fn reflect_clone(&self)
                ->
                    ::core::result::Result<bevy_reflect::__macro_exports::alloc_utils::Box<dyn bevy_reflect::Reflect>,
                    bevy_reflect::ReflectCloneError> {
                ::core::result::Result::Ok(bevy_reflect::__macro_exports::alloc_utils::Box::new(::core::clone::Clone::clone(self)))
            }
        }
        impl bevy_reflect::FromReflect for Rect where  {
            fn from_reflect(reflect: &dyn bevy_reflect::PartialReflect)
                -> ::core::option::Option<Self> {
                if let bevy_reflect::ReflectRef::Struct(__ref_struct) =
                        bevy_reflect::PartialReflect::reflect_ref(reflect) {
                    let mut __this =
                        <Self as ::core::default::Default>::default();
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <Vec2 as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "min")?))() {
                        __this.min = __field;
                    }
                    if let ::core::option::Option::Some(__field) =
                            (||
                                        <Vec2 as
                                                bevy_reflect::FromReflect>::from_reflect(bevy_reflect::structs::Struct::field(__ref_struct,
                                                    "max")?))() {
                        __this.max = __field;
                    }
                    ::core::option::Option::Some(__this)
                } else { ::core::option::Option::None }
            }
        }
    };Reflect),
22    reflect(Debug, PartialEq, Default, Clone)
23)]
24#[cfg_attr(
25    all(feature = "serialize", feature = "bevy_reflect"),
26    reflect(Serialize, Deserialize)
27)]
28pub struct Rect {
29    /// The minimum corner point of the rect.
30    pub min: Vec2,
31    /// The maximum corner point of the rect.
32    pub max: Vec2,
33}
34
35impl Rect {
36    /// An empty `Rect`, represented by maximum and minimum corner points
37    /// at `Vec2::NEG_INFINITY` and `Vec2::INFINITY`, respectively.
38    /// This is so the `Rect` has a infinitely negative size.
39    /// This is useful, because when taking a union B of a non-empty `Rect` A and
40    /// this empty `Rect`, B will simply equal A.
41    pub const EMPTY: Self = Self {
42        max: Vec2::NEG_INFINITY,
43        min: Vec2::INFINITY,
44    };
45    /// Create a new rectangle from two corner points.
46    ///
47    /// The two points do not need to be the minimum and/or maximum corners.
48    /// They only need to be two opposite corners.
49    ///
50    /// # Examples
51    ///
52    /// ```
53    /// # use bevy_math::Rect;
54    /// let r = Rect::new(0., 4., 10., 6.); // w=10 h=2
55    /// let r = Rect::new(2., 3., 5., -1.); // w=3 h=4
56    /// ```
57    #[inline]
58    pub const fn new(x0: f32, y0: f32, x1: f32, y1: f32) -> Self {
59        Self::from_corners(Vec2::new(x0, y0), Vec2::new(x1, y1))
60    }
61
62    /// Create a new rectangle from two corner points.
63    ///
64    /// The two points do not need to be the minimum and/or maximum corners.
65    /// They only need to be two opposite corners.
66    ///
67    /// # Examples
68    ///
69    /// ```
70    /// # use bevy_math::{Rect, Vec2};
71    /// // Unit rect from [0,0] to [1,1]
72    /// let r = Rect::from_corners(Vec2::ZERO, Vec2::ONE); // w=1 h=1
73    /// // Same; the points do not need to be ordered
74    /// let r = Rect::from_corners(Vec2::ONE, Vec2::ZERO); // w=1 h=1
75    /// ```
76    #[inline]
77    pub const fn from_corners(p0: Vec2, p1: Vec2) -> Self {
78        Self {
79            min: Vec2::new(p0.x.min(p1.x), p0.y.min(p1.y)),
80            max: Vec2::new(p0.x.max(p1.x), p0.y.max(p1.y)),
81        }
82    }
83
84    /// Create a new rectangle from its center and size.
85    ///
86    /// # Panics
87    ///
88    /// This method panics if any of the components of the size is negative.
89    ///
90    /// # Examples
91    ///
92    /// ```
93    /// # use bevy_math::{Rect, Vec2};
94    /// let r = Rect::from_center_size(Vec2::ZERO, Vec2::ONE); // w=1 h=1
95    /// assert!(r.min.abs_diff_eq(Vec2::splat(-0.5), 1e-5));
96    /// assert!(r.max.abs_diff_eq(Vec2::splat(0.5), 1e-5));
97    /// ```
98    #[inline]
99    pub const fn from_center_size(origin: Vec2, size: Vec2) -> Self {
100        if !(0. <= size.x && 0. <= size.y) {
    {
        ::core::panicking::panic_fmt(format_args!("Rect size must be positive"));
    }
};assert!(0. <= size.x && 0. <= size.y, "Rect size must be positive");
101        Self::from_center_half_size(origin, Vec2::new(0.5 * size.x, 0.5 * size.y))
102    }
103
104    /// Create a new rectangle from its center and half-size.
105    ///
106    /// # Panics
107    ///
108    /// This method panics if any of the components of the half-size is negative.
109    ///
110    /// # Examples
111    ///
112    /// ```
113    /// # use bevy_math::{Rect, Vec2};
114    /// let r = Rect::from_center_half_size(Vec2::ZERO, Vec2::ONE); // w=2 h=2
115    /// assert!(r.min.abs_diff_eq(Vec2::splat(-1.), 1e-5));
116    /// assert!(r.max.abs_diff_eq(Vec2::splat(1.), 1e-5));
117    /// ```
118    #[inline]
119    pub const fn from_center_half_size(origin: Vec2, half_size: Vec2) -> Self {
120        if !(0. <= half_size.x && 0. <= half_size.y) {
    {
        ::core::panicking::panic_fmt(format_args!("Rect half_size must be positive"));
    }
};assert!(
121            0. <= half_size.x && 0. <= half_size.y,
122            "Rect half_size must be positive"
123        );
124        Self {
125            min: Vec2::new(origin.x - half_size.x, origin.y - half_size.y),
126            max: Vec2::new(origin.x + half_size.x, origin.y + half_size.y),
127        }
128    }
129
130    /// Check if the rectangle is empty.
131    ///
132    /// # Examples
133    ///
134    /// ```
135    /// # use bevy_math::{Rect, Vec2};
136    /// let r = Rect::from_corners(Vec2::ZERO, Vec2::new(0., 1.)); // w=0 h=1
137    /// assert!(r.is_empty());
138    /// ```
139    #[inline]
140    pub const fn is_empty(&self) -> bool {
141        self.min.x >= self.max.x || self.min.y >= self.max.y
142    }
143
144    /// Rectangle width (max.x - min.x).
145    ///
146    /// # Examples
147    ///
148    /// ```
149    /// # use bevy_math::Rect;
150    /// let r = Rect::new(0., 0., 5., 1.); // w=5 h=1
151    /// assert!((r.width() - 5.).abs() <= 1e-5);
152    /// ```
153    #[inline]
154    pub const fn width(&self) -> f32 {
155        self.max.x - self.min.x
156    }
157
158    /// Rectangle height (max.y - min.y).
159    ///
160    /// # Examples
161    ///
162    /// ```
163    /// # use bevy_math::Rect;
164    /// let r = Rect::new(0., 0., 5., 1.); // w=5 h=1
165    /// assert!((r.height() - 1.).abs() <= 1e-5);
166    /// ```
167    #[inline]
168    pub const fn height(&self) -> f32 {
169        self.max.y - self.min.y
170    }
171
172    /// Rectangle size.
173    ///
174    /// # Examples
175    ///
176    /// ```
177    /// # use bevy_math::{Rect, Vec2};
178    /// let r = Rect::new(0., 0., 5., 1.); // w=5 h=1
179    /// assert!(r.size().abs_diff_eq(Vec2::new(5., 1.), 1e-5));
180    /// ```
181    #[inline]
182    pub const fn size(&self) -> Vec2 {
183        Vec2::new(self.max.x - self.min.x, self.max.y - self.min.y)
184    }
185
186    /// Rectangle half-size.
187    ///
188    /// # Examples
189    ///
190    /// ```
191    /// # use bevy_math::{Rect, Vec2};
192    /// let r = Rect::new(0., 0., 5., 1.); // w=5 h=1
193    /// assert!(r.half_size().abs_diff_eq(Vec2::new(2.5, 0.5), 1e-5));
194    /// ```
195    #[inline]
196    pub const fn half_size(&self) -> Vec2 {
197        let size = self.size();
198        Vec2::new(0.5 * size.x, 0.5 * size.y)
199    }
200
201    /// The center point of the rectangle.
202    ///
203    /// # Examples
204    ///
205    /// ```
206    /// # use bevy_math::{Rect, Vec2};
207    /// let r = Rect::new(0., 0., 5., 1.); // w=5 h=1
208    /// assert!(r.center().abs_diff_eq(Vec2::new(2.5, 0.5), 1e-5));
209    /// ```
210    #[inline]
211    pub const fn center(&self) -> Vec2 {
212        Vec2::new(
213            0.5 * (self.min.x + self.max.x),
214            0.5 * (self.min.y + self.max.y),
215        )
216    }
217
218    /// Returns the rectangle translated by the given offset.
219    ///
220    /// # Examples
221    ///
222    /// ```
223    /// # use bevy_math::{Rect, Vec2};
224    /// let r = Rect::new(0., 0., 5., 1.); // w=5 h=1
225    /// let r2 = r.translate(Vec2::new(2., -3.));
226    /// assert!(r2.min.abs_diff_eq(Vec2::new(2., -3.), 1e-5));
227    /// assert!(r2.max.abs_diff_eq(Vec2::new(7., -2.), 1e-5));
228    /// ```
229    #[inline]
230    pub const fn translate(&self, offset: Vec2) -> Self {
231        Self {
232            min: Vec2::new(self.min.x + offset.x, self.min.y + offset.y),
233            max: Vec2::new(self.max.x + offset.x, self.max.y + offset.y),
234        }
235    }
236
237    /// Check if a point lies within this rectangle, inclusive of its edges.
238    ///
239    /// # Examples
240    ///
241    /// ```
242    /// # use bevy_math::Rect;
243    /// let r = Rect::new(0., 0., 5., 1.); // w=5 h=1
244    /// assert!(r.contains(r.center()));
245    /// assert!(r.contains(r.min));
246    /// assert!(r.contains(r.max));
247    /// ```
248    #[inline]
249    pub const fn contains(&self, point: Vec2) -> bool {
250        self.min.x <= point.x
251            && point.x <= self.max.x
252            && self.min.y <= point.y
253            && point.y <= self.max.y
254    }
255
256    /// Build a new rectangle formed of the union of this rectangle and another rectangle.
257    ///
258    /// The union is the smallest rectangle enclosing both rectangles.
259    ///
260    /// # Examples
261    ///
262    /// ```
263    /// # use bevy_math::{Rect, Vec2};
264    /// let r1 = Rect::new(0., 0., 5., 1.); // w=5 h=1
265    /// let r2 = Rect::new(1., -1., 3., 3.); // w=2 h=4
266    /// let r = r1.union(r2);
267    /// assert!(r.min.abs_diff_eq(Vec2::new(0., -1.), 1e-5));
268    /// assert!(r.max.abs_diff_eq(Vec2::new(5., 3.), 1e-5));
269    /// ```
270    #[inline]
271    pub const fn union(&self, other: Self) -> Self {
272        let min_x = self.min.x.min(other.min.x);
273        let min_y = self.min.y.min(other.min.y);
274        let max_x = self.max.x.max(other.max.x);
275        let max_y = self.max.y.max(other.max.y);
276
277        Self {
278            min: Vec2::new(min_x, min_y),
279            max: Vec2::new(max_x, max_y),
280        }
281    }
282
283    /// Build a new rectangle formed of the union of this rectangle and a point.
284    ///
285    /// The union is the smallest rectangle enclosing both the rectangle and the point. If the
286    /// point is already inside the rectangle, this method returns a copy of the rectangle.
287    ///
288    /// # Examples
289    ///
290    /// ```
291    /// # use bevy_math::{Rect, Vec2};
292    /// let r = Rect::new(0., 0., 5., 1.); // w=5 h=1
293    /// let u = r.union_point(Vec2::new(3., 6.));
294    /// assert!(u.min.abs_diff_eq(Vec2::ZERO, 1e-5));
295    /// assert!(u.max.abs_diff_eq(Vec2::new(5., 6.), 1e-5));
296    /// ```
297    #[inline]
298    pub const fn union_point(&self, other: Vec2) -> Self {
299        let min_x = self.min.x.min(other.x);
300        let min_y = self.min.y.min(other.y);
301        let max_x = self.max.x.max(other.x);
302        let max_y = self.max.y.max(other.y);
303
304        Self {
305            min: Vec2::new(min_x, min_y),
306            max: Vec2::new(max_x, max_y),
307        }
308    }
309
310    /// Build a new rectangle formed of the intersection of this rectangle and another rectangle.
311    ///
312    /// The intersection is the largest rectangle enclosed in both rectangles. If the intersection
313    /// is empty, this method returns an empty rectangle ([`Rect::is_empty()`] returns `true`), but
314    /// the actual values of [`Rect::min`] and [`Rect::max`] are implementation-dependent.
315    ///
316    /// # Examples
317    ///
318    /// ```
319    /// # use bevy_math::{Rect, Vec2};
320    /// let r1 = Rect::new(0., 0., 5., 1.); // w=5 h=1
321    /// let r2 = Rect::new(1., -1., 3., 3.); // w=2 h=4
322    /// let r = r1.intersect(r2);
323    /// assert!(r.min.abs_diff_eq(Vec2::new(1., 0.), 1e-5));
324    /// assert!(r.max.abs_diff_eq(Vec2::new(3., 1.), 1e-5));
325    /// ```
326    #[inline]
327    pub fn intersect(&self, other: Self) -> Self {
328        let min_x = self.min.x.max(other.min.x);
329        let min_y = self.min.y.max(other.min.y);
330        let max_x = self.max.x.min(other.max.x);
331        let max_y = self.max.y.min(other.max.y);
332        // Collapse min over max to enforce invariants and ensure e.g. width() or
333        // height() never return a negative value.
334        let collapsed_min_x = min_x.min(max_x);
335        let collapsed_min_y = min_y.min(max_y);
336        Self {
337            min: Vec2::new(collapsed_min_x, collapsed_min_y),
338            max: Vec2::new(max_x, max_y),
339        }
340    }
341
342    /// Create a new rectangle by expanding it evenly on all sides.
343    ///
344    /// A positive expansion value produces a larger rectangle,
345    /// while a negative expansion value produces a smaller rectangle.
346    /// If this would result in zero or negative width or height, [`Rect::EMPTY`] is returned instead.
347    ///
348    /// # Examples
349    ///
350    /// ```
351    /// # use bevy_math::{Rect, Vec2};
352    /// let r = Rect::new(0., 0., 5., 1.); // w=5 h=1
353    /// let r2 = r.inflate(3.); // w=11 h=7
354    /// assert!(r2.min.abs_diff_eq(Vec2::splat(-3.), 1e-5));
355    /// assert!(r2.max.abs_diff_eq(Vec2::new(8., 4.), 1e-5));
356    ///
357    /// let r = Rect::new(0., -1., 6., 7.); // w=6 h=8
358    /// let r2 = r.inflate(-2.); // w=11 h=7
359    /// assert!(r2.min.abs_diff_eq(Vec2::new(2., 1.), 1e-5));
360    /// assert!(r2.max.abs_diff_eq(Vec2::new(4., 5.), 1e-5));
361    /// ```
362    #[inline]
363    pub const fn inflate(&self, expansion: f32) -> Self {
364        let min_x = self.min.x - expansion;
365        let min_y = self.min.y - expansion;
366        let max_x = self.max.x + expansion;
367        let max_y = self.max.y + expansion;
368        // Collapse min over max to enforce invariants and ensure e.g. width() or
369        // height() never return a negative value.
370        let collapsed_min_x = min_x.min(max_x);
371        let collapsed_min_y = min_y.min(max_y);
372        Self {
373            min: Vec2::new(collapsed_min_x, collapsed_min_y),
374            max: Vec2::new(max_x, max_y),
375        }
376    }
377
378    /// Build a new rectangle from this one with its coordinates expressed
379    /// relative to `other` in a normalized ([0..1] x [0..1]) coordinate system.
380    ///
381    /// # Examples
382    ///
383    /// ```
384    /// # use bevy_math::{Rect, Vec2};
385    /// let r = Rect::new(2., 3., 4., 6.);
386    /// let s = Rect::new(0., 0., 10., 10.);
387    /// let n = r.normalize(s);
388    ///
389    /// assert_eq!(n.min.x, 0.2);
390    /// assert_eq!(n.min.y, 0.3);
391    /// assert_eq!(n.max.x, 0.4);
392    /// assert_eq!(n.max.y, 0.6);
393    /// ```
394    pub const fn normalize(&self, other: Self) -> Self {
395        let outer_size = other.size();
396        let min_x = (self.min.x - other.min.x) / outer_size.x;
397        let min_y = (self.min.y - other.min.y) / outer_size.y;
398        let max_x = (self.max.x - other.min.x) / outer_size.x;
399        let max_y = (self.max.y - other.min.y) / outer_size.y;
400
401        Self {
402            min: Vec2::new(min_x, min_y),
403            max: Vec2::new(max_x, max_y),
404        }
405    }
406
407    /// Return the area of this rectangle.
408    ///
409    /// # Examples
410    ///
411    /// ```
412    /// # use bevy_math::Rect;
413    /// let r = Rect::new(0., 0., 10., 10.); // w=10 h=10
414    /// assert_eq!(r.area(), 100.0);
415    /// ```
416    #[inline]
417    pub const fn area(&self) -> f32 {
418        self.width() * self.height()
419    }
420
421    /// Returns self as [`IRect`] (i32)
422    #[inline]
423    pub fn as_irect(&self) -> IRect {
424        IRect::from_corners(self.min.as_ivec2(), self.max.as_ivec2())
425    }
426
427    /// Returns self as [`URect`] (u32)
428    #[inline]
429    pub fn as_urect(&self) -> URect {
430        URect::from_corners(self.min.as_uvec2(), self.max.as_uvec2())
431    }
432}
433
434#[cfg(test)]
435mod tests {
436    use crate::ops;
437
438    use super::*;
439
440    #[test]
441    fn well_formed() {
442        let r = Rect::from_center_size(Vec2::new(3., -5.), Vec2::new(8., 11.));
443
444        assert!(r.min.abs_diff_eq(Vec2::new(-1., -10.5), 1e-5));
445        assert!(r.max.abs_diff_eq(Vec2::new(7., 0.5), 1e-5));
446
447        assert!(r.center().abs_diff_eq(Vec2::new(3., -5.), 1e-5));
448
449        assert!(ops::abs(r.width() - 8.) <= 1e-5);
450        assert!(ops::abs(r.height() - 11.) <= 1e-5);
451        assert!(r.size().abs_diff_eq(Vec2::new(8., 11.), 1e-5));
452        assert!(r.half_size().abs_diff_eq(Vec2::new(4., 5.5), 1e-5));
453
454        assert!(r.contains(Vec2::new(3., -5.)));
455        assert!(r.contains(Vec2::new(-1., -10.5)));
456        assert!(r.contains(Vec2::new(-1., 0.5)));
457        assert!(r.contains(Vec2::new(7., -10.5)));
458        assert!(r.contains(Vec2::new(7., 0.5)));
459        assert!(!r.contains(Vec2::new(50., -5.)));
460    }
461
462    #[test]
463    fn rect_union() {
464        let r = Rect::from_center_size(Vec2::ZERO, Vec2::ONE); // [-0.5,-0.5] - [0.5,0.5]
465
466        // overlapping
467        let r2 = Rect {
468            min: Vec2::new(-0.8, 0.3),
469            max: Vec2::new(0.1, 0.7),
470        };
471        let u = r.union(r2);
472        assert!(u.min.abs_diff_eq(Vec2::new(-0.8, -0.5), 1e-5));
473        assert!(u.max.abs_diff_eq(Vec2::new(0.5, 0.7), 1e-5));
474
475        // disjoint
476        let r2 = Rect {
477            min: Vec2::new(-1.8, -0.5),
478            max: Vec2::new(-1.5, 0.3),
479        };
480        let u = r.union(r2);
481        assert!(u.min.abs_diff_eq(Vec2::new(-1.8, -0.5), 1e-5));
482        assert!(u.max.abs_diff_eq(Vec2::new(0.5, 0.5), 1e-5));
483
484        // included
485        let r2 = Rect::from_center_size(Vec2::ZERO, Vec2::splat(0.5));
486        let u = r.union(r2);
487        assert!(u.min.abs_diff_eq(r.min, 1e-5));
488        assert!(u.max.abs_diff_eq(r.max, 1e-5));
489
490        // including
491        let r2 = Rect::from_center_size(Vec2::ZERO, Vec2::splat(1.5));
492        let u = r.union(r2);
493        assert!(u.min.abs_diff_eq(r2.min, 1e-5));
494        assert!(u.max.abs_diff_eq(r2.max, 1e-5));
495    }
496
497    #[test]
498    fn rect_union_pt() {
499        let r = Rect::from_center_size(Vec2::ZERO, Vec2::ONE); // [-0.5,-0.5] - [0.5,0.5]
500
501        // inside
502        let v = Vec2::new(0.3, -0.2);
503        let u = r.union_point(v);
504        assert!(u.min.abs_diff_eq(r.min, 1e-5));
505        assert!(u.max.abs_diff_eq(r.max, 1e-5));
506
507        // outside
508        let v = Vec2::new(10., -3.);
509        let u = r.union_point(v);
510        assert!(u.min.abs_diff_eq(Vec2::new(-0.5, -3.), 1e-5));
511        assert!(u.max.abs_diff_eq(Vec2::new(10., 0.5), 1e-5));
512    }
513
514    #[test]
515    fn rect_intersect() {
516        let r = Rect::from_center_size(Vec2::ZERO, Vec2::ONE); // [-0.5,-0.5] - [0.5,0.5]
517
518        // overlapping
519        let r2 = Rect {
520            min: Vec2::new(-0.8, 0.3),
521            max: Vec2::new(0.1, 0.7),
522        };
523        let u = r.intersect(r2);
524        assert!(u.min.abs_diff_eq(Vec2::new(-0.5, 0.3), 1e-5));
525        assert!(u.max.abs_diff_eq(Vec2::new(0.1, 0.5), 1e-5));
526
527        // disjoint
528        let r2 = Rect {
529            min: Vec2::new(-1.8, -0.5),
530            max: Vec2::new(-1.5, 0.3),
531        };
532        let u = r.intersect(r2);
533        assert!(u.is_empty());
534        assert!(u.width() <= 1e-5);
535
536        // included
537        let r2 = Rect::from_center_size(Vec2::ZERO, Vec2::splat(0.5));
538        let u = r.intersect(r2);
539        assert!(u.min.abs_diff_eq(r2.min, 1e-5));
540        assert!(u.max.abs_diff_eq(r2.max, 1e-5));
541
542        // including
543        let r2 = Rect::from_center_size(Vec2::ZERO, Vec2::splat(1.5));
544        let u = r.intersect(r2);
545        assert!(u.min.abs_diff_eq(r.min, 1e-5));
546        assert!(u.max.abs_diff_eq(r.max, 1e-5));
547    }
548
549    #[test]
550    fn rect_inflate() {
551        let r = Rect::from_center_size(Vec2::ZERO, Vec2::ONE); // [-0.5,-0.5] - [0.5,0.5]
552
553        let r2 = r.inflate(0.3);
554        assert!(r2.min.abs_diff_eq(Vec2::new(-0.8, -0.8), 1e-5));
555        assert!(r2.max.abs_diff_eq(Vec2::new(0.8, 0.8), 1e-5));
556    }
557
558    #[test]
559    fn rect_translate() {
560        let r = Rect::new(0., 1., 4., 3.);
561        let r2 = r.translate(Vec2::new(2., -5.));
562
563        assert!(r2.min.abs_diff_eq(Vec2::new(2., -4.), 1e-5));
564        assert!(r2.max.abs_diff_eq(Vec2::new(6., -2.), 1e-5));
565        assert!(r2.size().abs_diff_eq(r.size(), 1e-5));
566    }
567}