Skip to content
Snippets Groups Projects
utilities.rs 2.68 KiB
Newer Older
Louis's avatar
Louis committed
use std::ops::{Deref, DerefMut};

use bevy::prelude::UVec2;
use num_traits::AsPrimitive;
Louis's avatar
Louis committed

Louis's avatar
Louis committed
#[inline]
pub fn f32_max(a: f32, b: f32) -> f32 {
	if a > b {
		a
	} else {
		b
	}
}
#[inline]
pub fn f32_max_mag(a: f32, b: f32) -> f32 {
	if a.abs() > b.abs() {
		a.abs()
	} else {
		b.abs()
	}
}
#[inline]
pub fn f32_min(a: f32, b: f32) -> f32 {
	if a < b {
		a
	} else {
		b
	}
}
#[inline]
pub fn f32_min_mag(a: f32, b: f32) -> f32 {
	if a.abs() < b.abs() {
		a.abs()
	} else {
		b.abs()
	}
}
Louis's avatar
Louis committed

#[derive(Debug, Copy, Clone)]
pub struct Indexer {
	width: usize,
	height: usize,
}

impl Indexer {
	pub fn new(width: impl AsPrimitive<usize>, height: impl AsPrimitive<usize>) -> Self {
		Indexer {
			width: width.as_(),
			height: height.as_(),
		}
Louis's avatar
Louis committed
	}
	pub fn index(&self, x: impl AsPrimitive<usize>, y: impl AsPrimitive<usize>) -> usize {
		(y.as_() * self.width) + x.as_()
Louis's avatar
Louis committed
	}
	pub fn checked_index(
		&self,
		x: impl AsPrimitive<usize>,
		y: impl AsPrimitive<usize>,
	) -> Option<usize> {
Louis's avatar
Louis committed
		if self.is_coordinate_valid(x, y) {
			Some(self.index(x, y))
		} else {
			None
		}
	}
	pub fn reverse(&self, index: impl AsPrimitive<usize>) -> (usize, usize) {
		(index.as_() % self.width, index.as_() / self.width)
Louis's avatar
Louis committed
	}
	pub fn checked_reverse(&self, idx: impl AsPrimitive<usize>) -> Option<(usize, usize)> {
Louis's avatar
Louis committed
		if self.is_index_valid(idx) {
			Some(self.reverse(idx))
		} else {
			None
		}
	}
	pub fn index_within(&self, idx: impl AsPrimitive<usize>) -> bool {
Louis's avatar
Louis committed
		let (x, y) = self.reverse(idx);
		x >= 0 && x < self.width && y >= 0 && y < self.height
	}
	pub fn is_uvec2_valid(&self, point: UVec2) -> bool {
		self.is_coordinate_valid(point.x, point.y)
	}
	pub fn square_adjacent(
		&self,
		x: impl AsPrimitive<u32>,
		y: impl AsPrimitive<u32>,
	) -> Vec<UVec2> {
		let x = x.as_();
		let y = y.as_();

		let initial_point = UVec2::new(x, y);

		let left = UVec2::new(x.saturating_sub(1), y);
		let right = UVec2::new(x.saturating_add(1), y);
		let top = UVec2::new(x, y.saturating_add(1));
		let bottom = UVec2::new(x, y.saturating_sub(1));

		let mut output = Vec::with_capacity(4);
		if left != initial_point {
			output.push(left);
		}
		if right != initial_point && right.x < self.width as u32 {
			output.push(right);
		}
		if bottom != initial_point {
			output.push(bottom)
		}
		if top != initial_point && top.y < self.height as u32 {
			output.push(top)
		}

		output
Louis's avatar
Louis committed
	}
	pub fn is_coordinate_valid(
		&self,
		x: impl AsPrimitive<usize>,
		y: impl AsPrimitive<usize>,
	) -> bool {
		x.as_() < self.width && y.as_() < self.height
Louis's avatar
Louis committed
	}
	pub fn is_index_valid(&self, idx: impl AsPrimitive<usize>) -> bool {
		idx.as_() < self.width * self.height
Louis's avatar
Louis committed
	}
	pub fn width(&self) -> usize {
		self.width
	}
	pub fn height(&self) -> usize {
		self.height
	}
}