#[derive(Copy, Clone, PartialEq, Eq, Debug, Default, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Pad {
pub x: i32,
pub y: i32,
}
impl Pad {
pub fn up(self, steps: i32) -> Self {
Self {
x: self.x,
y: self.y - steps,
}
}
pub fn down(self, steps: i32) -> Self {
Self {
x: self.x,
y: self.y + steps,
}
}
pub fn left(self, steps: i32) -> Self {
Self {
x: self.x - steps,
y: self.y,
}
}
pub fn right(self, steps: i32) -> Self {
Self {
x: self.x + steps,
y: self.y,
}
}
pub fn neighbors_4(self) -> [Self; 4] {
[self.up(1), self.right(1), self.down(1), self.left(1)]
}
pub fn neighbors_5(self) -> [Self; 5] {
[self, self.up(1), self.right(1), self.down(1), self.left(1)]
}
pub fn neighbors_8(self) -> [Self; 8] {
[
self.up(1),
self.up(1).right(1),
self.right(1),
self.right(1).down(1),
self.down(1),
self.down(1).left(1),
self.left(1),
self.left(1).up(1),
]
}
pub fn neighbors_9(self) -> [Self; 9] {
[
self,
self.up(1),
self.up(1).right(1),
self.right(1),
self.right(1).down(1),
self.down(1),
self.down(1).left(1),
self.left(1),
self.left(1).up(1),
]
}
pub fn to_u32(self) -> Option<(u32, u32)> {
if self.x >= 0 && self.y >= 0 {
Some((self.x as u32, self.y as u32))
} else {
None
}
}
pub fn wrap_edges(self, width: u32, height: u32) -> Pad {
Pad {
x: self.x.rem_euclid(width as i32),
y: self.y.rem_euclid(height as i32),
}
}
}
impl std::ops::Add<(i32, i32)> for Pad {
type Output = Self;
fn add(self, offset: (i32, i32)) -> Self {
let (x_offset, y_offset) = offset;
Self {
x: self.x + x_offset,
y: self.y + y_offset,
}
}
}
impl std::ops::AddAssign<(i32, i32)> for Pad {
fn add_assign(&mut self, offset: (i32, i32)) {
let (x_offset, y_offset) = offset;
self.x += x_offset;
self.y += y_offset;
}
}
impl std::ops::Sub<Pad> for Pad {
type Output = (i32, i32);
fn sub(self, other: Pad) -> (i32, i32) {
(self.x - other.x, self.y - other.y)
}
}
impl std::ops::Sub<(i32, i32)> for Pad {
type Output = Self;
fn sub(self, offset: (i32, i32)) -> Self {
let (x_offset, y_offset) = offset;
Self {
x: self.x - x_offset,
y: self.y - y_offset,
}
}
}
impl std::ops::SubAssign<(i32, i32)> for Pad {
fn sub_assign(&mut self, offset: (i32, i32)) {
let (x_offset, y_offset) = offset;
self.x -= x_offset;
self.y -= y_offset;
}
}
impl From<(i32, i32)> for Pad {
fn from((x, y): (i32, i32)) -> Self {
Self { x, y }
}
}
impl From<(u32, u32)> for Pad {
fn from((x, y): (u32, u32)) -> Self {
Self {
x: x as i32,
y: y as i32,
}
}
}