Skip to main content

raylib_sys/
math.rs

1#[cfg(feature = "serde")]
2use serde::{Deserialize, Serialize};
3
4/// A unit quaternion used for 3D rotations.
5///
6/// C aliases `Quaternion` to `Vector4` (`typedef Vector4 Quaternion`); raylib-rs
7/// uses a **distinct** `#[repr(C)]` struct so the two types have their own method
8/// namespaces. The layout is identical (`x`, `y`, `z`, `w` as `f32`), and
9/// zero-cost conversions are provided:
10/// - `Quaternion::from(v: Vector4)` — convert from a raw four-component vector.
11/// - `Vector4::from(q: Quaternion)` — convert back.
12///
13/// Build a `Quaternion` with one of the constructor functions:
14/// [`from_axis_angle`](Quaternion::from_axis_angle),
15/// [`from_euler`](Quaternion::from_euler),
16/// [`from_matrix`](Quaternion::from_matrix),
17/// or [`identity`](Quaternion::identity).
18#[repr(C)]
19#[derive(Default, Debug, Copy, Clone, PartialEq)]
20#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
21pub struct Quaternion {
22    pub x: f32,
23    pub y: f32,
24    pub z: f32,
25    pub w: f32,
26}
27
28impl Quaternion {
29    #[inline]
30    pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
31        Self { x, y, z, w }
32    }
33}
34
35// Zero-cost interchange with the FFI Vector4 that raymath's Quaternion* fns actually take/return.
36impl From<crate::Vector4> for Quaternion {
37    #[inline]
38    fn from(v: crate::Vector4) -> Self {
39        Self {
40            x: v.x,
41            y: v.y,
42            z: v.z,
43            w: v.w,
44        }
45    }
46}
47impl From<Quaternion> for crate::Vector4 {
48    #[inline]
49    fn from(q: Quaternion) -> Self {
50        crate::Vector4 {
51            x: q.x,
52            y: q.y,
53            z: q.z,
54            w: q.w,
55        }
56    }
57}
58
59/// An axis-aligned rectangle defined by its top-left corner and dimensions.
60///
61/// `Rectangle` is a `#[repr(C)]` struct with four `f32` fields: `x` and `y` for the top-left
62/// corner position, and `width` / `height` for the extents. It maps directly to raylib's
63/// `Rectangle` type in C.
64///
65/// Collision and containment helpers are available as methods:
66/// [`check_collision_recs`](Rectangle::check_collision_recs),
67/// [`check_collision_point_rec`](Rectangle::check_collision_point_rec),
68/// [`get_collision_rec`](Rectangle::get_collision_rec),
69/// [`check_collision_circle_rec`](Rectangle::check_collision_circle_rec).
70///
71/// # Examples
72///
73/// ```rust
74/// use raylib_sys::Rectangle;
75///
76/// let r1 = Rectangle::new(0.0, 0.0, 10.0, 10.0);
77/// let r2 = Rectangle::new(5.0, 5.0, 10.0, 10.0);
78/// let r3 = Rectangle::new(20.0, 20.0, 10.0, 10.0);
79///
80/// assert!(r1.check_collision_recs(r2));   // overlapping
81/// assert!(!r1.check_collision_recs(r3));  // non-overlapping
82/// ```
83#[repr(C)]
84#[derive(Default, Debug, Copy, Clone, PartialEq)]
85#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
86pub struct Rectangle {
87    pub x: f32,
88    pub y: f32,
89    pub width: f32,
90    pub height: f32,
91}
92
93impl Rectangle {
94    #[must_use]
95    pub fn new(x: f32, y: f32, width: f32, height: f32) -> Self {
96        Self {
97            x,
98            y,
99            width,
100            height,
101        }
102    }
103
104    /// Check collision between two rectangles
105    #[inline]
106    #[must_use]
107    pub fn check_collision_recs(&self, other: Rectangle) -> bool {
108        // SAFETY: CheckCollisionRecs is a pure value-in/out raylib fn; both args are
109        // #[repr(C)] Copy structs with no pointer aliasing or preconditions.
110        unsafe { crate::CheckCollisionRecs(*self, other) }
111    }
112
113    /// Checks collision between circle and rectangle.
114    #[inline]
115    #[must_use]
116    pub fn check_collision_circle_rec(
117        &self,
118        center: impl Into<crate::Vector2>,
119        radius: f32,
120    ) -> bool {
121        // SAFETY: CheckCollisionCircleRec is a pure value-in/out raylib fn; all args are
122        // #[repr(C)] Copy values (Vector2, f32, Rectangle) with no pointer aliasing or preconditions.
123        unsafe { crate::CheckCollisionCircleRec(center.into(), radius, *self) }
124    }
125
126    /// Gets the overlap between two colliding rectangles.
127    /// ```rust
128    /// use raylib_sys::Rectangle;
129    ///
130    /// let r1 = Rectangle::new(0.0, 0.0, 10.0, 10.0);
131    /// let r2 = Rectangle::new(20.0, 20.0, 10.0, 10.0);
132    /// assert_eq!(None, r1.get_collision_rec(r2));
133    /// assert_eq!(Some(r1), r1.get_collision_rec(r1));
134    /// ```
135    #[inline]
136    #[must_use]
137    pub fn get_collision_rec(&self, other: Rectangle) -> Option<Rectangle> {
138        self.check_collision_recs(other).then(|| {
139            // SAFETY: GetCollisionRec is a pure value-in/out raylib fn; both args are
140            // #[repr(C)] Copy structs with no pointer aliasing or preconditions.
141            unsafe { crate::GetCollisionRec(*self, other) }
142        })
143    }
144
145    /// Checks if point is inside rectangle.
146    #[inline]
147    #[must_use]
148    pub fn check_collision_point_rec(&self, point: impl Into<crate::Vector2>) -> bool {
149        // SAFETY: CheckCollisionPointRec is a pure value-in/out raylib fn; both args are
150        // #[repr(C)] Copy values (Vector2, Rectangle) with no pointer aliasing or preconditions.
151        unsafe { crate::CheckCollisionPointRec(point.into(), *self) }
152    }
153}