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}