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,24 @@ 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
+ assert_eq ! ( Vector3i :: new( 10 , 5 , -5 ) . max_axis( ) , Some ( Vector3Axis :: X ) ) ;
206
+ assert_eq ! ( Vector3i :: new( 5 , 10 , -5 ) . max_axis( ) , Some ( Vector3Axis :: Y ) ) ;
207
+ assert_eq ! ( Vector3i :: new( 5 , -5 , 10 ) . max_axis( ) , Some ( Vector3Axis :: Z ) ) ;
208
+
209
+ assert_eq ! ( Vector3i :: new( -5 , 5 , 10 ) . min_axis( ) , Some ( Vector3Axis :: X ) ) ;
210
+ assert_eq ! ( Vector3i :: new( 5 , -5 , 10 ) . min_axis( ) , Some ( Vector3Axis :: Y ) ) ;
211
+ assert_eq ! ( Vector3i :: new( 5 , 10 , -5 ) . min_axis( ) , Some ( Vector3Axis :: Z ) ) ;
212
+
213
+ assert_eq ! ( Vector3i :: new( 15 , 15 , 5 ) . max_axis( ) , None ) ;
214
+ assert_eq ! ( Vector3i :: new( 15 , 15 , 15 ) . max_axis( ) , None ) ;
215
+ assert_eq ! ( Vector3i :: new( 15 , 15 , 25 ) . min_axis( ) , None ) ;
216
+ assert_eq ! ( Vector3i :: new( 15 , 15 , 15 ) . min_axis( ) , None ) ;
217
+
218
+ // Checks for non-max / non-min equality "traps"
219
+ assert_eq ! ( Vector3i :: new( 15 , 15 , 25 ) . max_axis( ) , Some ( Vector3Axis :: Z ) ) ;
220
+ assert_eq ! ( Vector3i :: new( 15 , 5 , 15 ) . min_axis( ) , Some ( Vector3Axis :: Y ) ) ;
221
+ }
150
222
}
0 commit comments