use std::cmp::Ordering;
use std::fmt;
use godot_ffi as sys;
use sys::{ExtVariantType, GodotFfi, ffi_methods};
use crate::builtin::math::{GlamConv, GlamType};
use crate::builtin::{RVec2, Vector2, Vector2Axis, inner, real};
#[doc = shared_vector_docs!()]
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(C)]
pub struct Vector2i {
pub x: i32,
pub y: i32,
}
impl Vector2i {
impl_vector_consts!(i32);
impl_integer_vector_consts!();
impl_vector2x_consts!(i32);
}
impl Vector2i {
inline_impl_integer_vector_fns!(Vector2, x, y);
#[doc(hidden)]
#[inline]
pub fn to_glam_real(self) -> RVec2 {
RVec2::new(self.x as real, self.y as real)
}
#[doc(hidden)]
#[inline]
pub fn as_inner(&self) -> inner::InnerVector2i<'_> {
inner::InnerVector2i::from_outer(self)
}
}
impl_vector_fns!(Vector2i, glam::IVec2, i32, (x, y));
impl_vector2x_fns!(Vector2i, Vector3i, i32);
impl_vector_operators!(Vector2i, i32, (x, y));
impl fmt::Display for Vector2i {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
unsafe impl GodotFfi for Vector2i {
const VARIANT_TYPE: ExtVariantType = ExtVariantType::Concrete(sys::VariantType::VECTOR2I);
ffi_methods! { type sys::GDExtensionTypePtr = *mut Self; .. }
}
crate::meta::impl_godot_as_self!(Vector2i: ByValue);
impl GlamType for glam::IVec2 {
type Mapped = Vector2i;
fn to_front(&self) -> Self::Mapped {
Vector2i::new(self.x, self.y)
}
fn from_front(mapped: &Self::Mapped) -> Self {
glam::IVec2::new(mapped.x, mapped.y)
}
}
impl GlamConv for Vector2i {
type Glam = glam::IVec2;
}
#[cfg(test)] #[cfg_attr(published_docs, doc(cfg(test)))]
mod test {
use super::*;
use crate::assert_eq_approx;
#[test]
fn coord_min_max() {
let a = Vector2i::new(1, 3);
let b = Vector2i::new(0, 5);
assert_eq!(a.coord_min(b), Vector2i::new(0, 3));
assert_eq!(a.coord_max(b), Vector2i::new(1, 5));
}
#[cfg(feature = "serde")] #[cfg_attr(published_docs, doc(cfg(feature = "serde")))]
#[test]
fn serde_roundtrip() {
let vector = Vector2i::default();
let expected_json = "{\"x\":0,\"y\":0}";
crate::builtin::test_utils::roundtrip(&vector, expected_json);
}
#[test]
fn sign() {
let vector = Vector2i::new(2, -5);
assert_eq!(vector.sign(), Vector2i::new(1, -1));
let vector = Vector2i::new(1, 0);
assert_eq!(vector.sign(), Vector2i::new(1, 0));
}
#[test]
fn axis_min_max() {
assert_eq!(Vector2i::new(10, 5).max_axis(), Some(Vector2Axis::X));
assert_eq!(Vector2i::new(5, 10).max_axis(), Some(Vector2Axis::Y));
assert_eq!(Vector2i::new(-5, 5).min_axis(), Some(Vector2Axis::X));
assert_eq!(Vector2i::new(5, -5).min_axis(), Some(Vector2Axis::Y));
assert_eq!(Vector2i::new(15, 15).max_axis(), None);
assert_eq!(Vector2i::new(15, 15).min_axis(), None);
}
#[test]
fn distance() {
let a = Vector2i::new(1, 2);
let b = Vector2i::new(4, 6);
assert_eq!(a.distance_squared_to(b), 25);
assert_eq_approx!(a.distance_to(b), 5.0);
}
#[test]
fn mini_maxi_clampi() {
let v = Vector2i::new(10, -5);
assert_eq!(v.mini(3), Vector2i::new(3, -5));
assert_eq!(v.maxi(-2), Vector2i::new(10, -2));
assert_eq!(v.clampi(-3, 7), Vector2i::new(7, -3));
}
#[test]
fn snappedi() {
let v = Vector2i::new(13, -8);
assert_eq!(v.snappedi(5), Vector2i::new(15, -10));
}
}