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#[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 pub min: Vec2,
31 pub max: Vec2,
33}
34
35impl Rect {
36 pub const EMPTY: Self = Self {
42 max: Vec2::NEG_INFINITY,
43 min: Vec2::INFINITY,
44 };
45 #[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 #[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 #[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 #[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 #[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 #[inline]
154 pub const fn width(&self) -> f32 {
155 self.max.x - self.min.x
156 }
157
158 #[inline]
168 pub const fn height(&self) -> f32 {
169 self.max.y - self.min.y
170 }
171
172 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 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 #[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 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 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 #[inline]
417 pub const fn area(&self) -> f32 {
418 self.width() * self.height()
419 }
420
421 #[inline]
423 pub fn as_irect(&self) -> IRect {
424 IRect::from_corners(self.min.as_ivec2(), self.max.as_ivec2())
425 }
426
427 #[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); 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 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 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 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); 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 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); 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 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 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 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); 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}