4
4
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
5
*/
6
6
7
+ use std:: cmp:: Ordering ;
7
8
use std:: fmt;
8
9
9
10
use godot_ffi as sys;
10
11
use sys:: { ffi_methods, GodotFfi } ;
11
12
12
- use crate :: builtin:: math:: { GlamConv , GlamType , IVec3 } ;
13
- use crate :: builtin:: Vector3 ;
13
+ use crate :: builtin:: math:: { FloatExt , GlamConv , GlamType } ;
14
+ use crate :: builtin:: { real , RVec3 , Vector3 , Vector3Axis } ;
14
15
15
16
/// Vector used for 3D math using integer coordinates.
16
17
///
@@ -65,6 +66,50 @@ impl Vector3i {
65
66
Self { x, y, z }
66
67
}
67
68
69
+ /// Axis of the vector's highest value. [`None`] if at least two components are equal.
70
+ pub fn max_axis ( self ) -> Option < Vector3Axis > {
71
+ use Vector3Axis :: * ;
72
+
73
+ match self . x . cmp ( & self . y ) {
74
+ Ordering :: Less => match self . y . cmp ( & self . z ) {
75
+ Ordering :: Less => Some ( Z ) ,
76
+ Ordering :: Equal => None ,
77
+ Ordering :: Greater => Some ( Y ) ,
78
+ } ,
79
+ Ordering :: Equal => match self . x . cmp ( & self . z ) {
80
+ Ordering :: Less => Some ( Z ) ,
81
+ _ => None ,
82
+ } ,
83
+ Ordering :: Greater => match self . x . cmp ( & self . z ) {
84
+ Ordering :: Less => Some ( Z ) ,
85
+ Ordering :: Equal => None ,
86
+ Ordering :: Greater => Some ( X ) ,
87
+ } ,
88
+ }
89
+ }
90
+
91
+ /// Axis of the vector's highest value. [`None`] if at least two components are equal.
92
+ pub fn min_axis ( self ) -> Option < Vector3Axis > {
93
+ use Vector3Axis :: * ;
94
+
95
+ match self . x . cmp ( & self . y ) {
96
+ Ordering :: Less => match self . x . cmp ( & self . z ) {
97
+ Ordering :: Less => Some ( X ) ,
98
+ Ordering :: Equal => None ,
99
+ Ordering :: Greater => Some ( Z ) ,
100
+ } ,
101
+ Ordering :: Equal => match self . x . cmp ( & self . z ) {
102
+ Ordering :: Greater => Some ( Z ) ,
103
+ _ => None ,
104
+ } ,
105
+ Ordering :: Greater => match self . y . cmp ( & self . z ) {
106
+ Ordering :: Less => Some ( Y ) ,
107
+ Ordering :: Equal => None ,
108
+ Ordering :: Greater => Some ( Z ) ,
109
+ } ,
110
+ }
111
+ }
112
+
68
113
/// Constructs a new `Vector3i` with all components set to `v`.
69
114
pub const fn splat ( v : i32 ) -> Self {
70
115
Self :: new ( v, v, v)
@@ -80,13 +125,18 @@ impl Vector3i {
80
125
}
81
126
82
127
/// Converts the corresponding `glam` type to `Self`.
83
- fn from_glam ( v : IVec3 ) -> Self {
128
+ fn from_glam ( v : glam :: IVec3 ) -> Self {
84
129
Self :: new ( v. x , v. y , v. z )
85
130
}
86
131
87
132
/// Converts `self` to the corresponding `glam` type.
88
- fn to_glam ( self ) -> IVec3 {
89
- IVec3 :: new ( self . x , self . y , self . z )
133
+ fn to_glam ( self ) -> glam:: IVec3 {
134
+ glam:: IVec3 :: new ( self . x , self . y , self . z )
135
+ }
136
+
137
+ /// Converts `self` to the corresponding [`real`] `glam` type.
138
+ fn to_glam_real ( self ) -> RVec3 {
139
+ RVec3 :: new ( self . x as real , self . y as real , self . z as real )
90
140
}
91
141
92
142
pub fn coords ( & self ) -> ( i32 , i32 , i32 ) {
@@ -102,6 +152,8 @@ impl fmt::Display for Vector3i {
102
152
}
103
153
104
154
impl_common_vector_fns ! ( Vector3i , i32 ) ;
155
+ impl_integer_vector_glam_fns ! ( Vector3i , real) ;
156
+ impl_integer_vector_component_fns ! ( Vector3i , real, ( x, y, z) ) ;
105
157
impl_vector_operators ! ( Vector3i , i32 , ( x, y, z) ) ;
106
158
impl_from_tuple_for_vector3x ! ( Vector3i , i32 ) ;
107
159
@@ -111,20 +163,20 @@ unsafe impl GodotFfi for Vector3i {
111
163
ffi_methods ! { type sys:: GDExtensionTypePtr = * mut Self ; .. }
112
164
}
113
165
114
- impl GlamType for IVec3 {
166
+ impl GlamType for glam :: IVec3 {
115
167
type Mapped = Vector3i ;
116
168
117
169
fn to_front ( & self ) -> Self :: Mapped {
118
170
Vector3i :: new ( self . x , self . y , self . z )
119
171
}
120
172
121
173
fn from_front ( mapped : & Self :: Mapped ) -> Self {
122
- IVec3 :: new ( mapped. x , mapped. y , mapped. z )
174
+ glam :: IVec3 :: new ( mapped. x , mapped. y , mapped. z )
123
175
}
124
176
}
125
177
126
178
impl GlamConv for Vector3i {
127
- type Glam = IVec3 ;
179
+ type Glam = glam :: IVec3 ;
128
180
}
129
181
130
182
#[ cfg( test) ]
@@ -147,4 +199,39 @@ mod test {
147
199
148
200
crate :: builtin:: test_utils:: roundtrip ( & vector, expected_json) ;
149
201
}
202
+
203
+ #[ test]
204
+ fn axis_min_max ( ) {
205
+ let x_max = Vector3i :: new ( 10 , 5 , -5 ) ;
206
+ let y_max = Vector3i :: new ( 5 , 10 , -5 ) ;
207
+ let z_max = Vector3i :: new ( 5 , -5 , 10 ) ;
208
+
209
+ let x_min = Vector3i :: new ( -5 , 5 , 10 ) ;
210
+ let y_min = Vector3i :: new ( 5 , -5 , 10 ) ;
211
+ let z_min = Vector3i :: new ( 5 , 10 , -5 ) ;
212
+
213
+ let max_eq_2 = Vector3i :: new ( 15 , 15 , 5 ) ;
214
+ let max_eq_3 = Vector3i :: new ( 15 , 15 , 15 ) ;
215
+ let min_eq_2 = Vector3i :: new ( 15 , 15 , 25 ) ;
216
+ let min_eq_3 = Vector3i :: new ( 15 , 15 , 15 ) ;
217
+
218
+ let max_eq_trap = Vector3i :: new ( 15 , 15 , 25 ) ;
219
+ let min_eq_trap = Vector3i :: new ( 15 , 5 , 15 ) ;
220
+
221
+ assert_eq ! ( x_max. max_axis( ) , Some ( Vector3Axis :: X ) ) ;
222
+ assert_eq ! ( y_max. max_axis( ) , Some ( Vector3Axis :: Y ) ) ;
223
+ assert_eq ! ( z_max. max_axis( ) , Some ( Vector3Axis :: Z ) ) ;
224
+
225
+ assert_eq ! ( x_min. min_axis( ) , Some ( Vector3Axis :: X ) ) ;
226
+ assert_eq ! ( y_min. min_axis( ) , Some ( Vector3Axis :: Y ) ) ;
227
+ assert_eq ! ( z_min. min_axis( ) , Some ( Vector3Axis :: Z ) ) ;
228
+
229
+ assert_eq ! ( max_eq_2. max_axis( ) , None ) ;
230
+ assert_eq ! ( max_eq_3. max_axis( ) , None ) ;
231
+ assert_eq ! ( min_eq_2. min_axis( ) , None ) ;
232
+ assert_eq ! ( min_eq_3. min_axis( ) , None ) ;
233
+
234
+ assert_eq ! ( max_eq_trap. max_axis( ) , Some ( Vector3Axis :: Z ) ) ;
235
+ assert_eq ! ( min_eq_trap. min_axis( ) , Some ( Vector3Axis :: Y ) ) ;
236
+ }
150
237
}
0 commit comments