use crate::size::Size;
use bytemuck::{Pod, Zeroable};
use std::ops::{AddAssign, SubAssign};
use winit::dpi::PhysicalPosition;
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default, Pod, Zeroable)]
pub struct Position {
pub x: f32,
pub y: f32,
}
impl Position {
pub fn new(x: f32, y: f32) -> Self {
Self { x, y }
}
pub fn translate(&mut self, x: f32, y: f32) {
self.x += x;
self.y += y;
}
pub fn set(&mut self, x: f32, y: f32) {
self.x = x;
self.y = y;
}
pub fn unit(value: f32) -> Self {
Self { x: value, y: value }
}
}
impl AddAssign<Position> for Position {
fn add_assign(&mut self, rhs: Position) {
self.x += rhs.x;
self.y += rhs.y;
}
}
impl SubAssign<Position> for Position {
fn sub_assign(&mut self, rhs: Position) {
self.x -= rhs.x;
self.y -= rhs.y;
}
}
impl<I> AddAssign<I> for Position
where
f32: AddAssign<I>,
I: Copy,
{
fn add_assign(&mut self, rhs: I) {
self.x += rhs;
self.y += rhs;
}
}
impl<I> SubAssign<I> for Position
where
f32: SubAssign<I>,
I: Copy,
{
fn sub_assign(&mut self, rhs: I) {
self.x -= rhs;
self.y -= rhs;
}
}
impl From<PhysicalPosition<f64>> for Position {
fn from(position: PhysicalPosition<f64>) -> Self {
Self {
x: position.x as f32,
y: position.y as f32,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
pub struct Bounds {
pub x: [f32; 2],
pub y: [f32; 2],
}
impl Bounds {
pub fn new(position: Position, size: Size) -> Self {
Self {
x: [position.x, position.x + size.width],
y: [position.y, position.y + size.height],
}
}
pub fn within(&self, position: &Position) -> bool {
if position.x > self.x[0]
&& position.x < self.x[1]
&& position.y > self.y[0]
&& position.y < self.y[1]
{
return true;
}
false
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn add_assign() {
let mut pos = Position::new(1.0, 2.0);
pos += 5.0;
assert_eq!(pos, Position::new(6.0, 7.0));
}
#[test]
fn sub_assign() {
let mut pos = Position::new(0.0, 15.0);
pos -= 15.0;
assert_eq!(pos, Position::new(-15.0, 0.0));
}
}