use std::ops::{Deref, DerefMut}; use bevy::prelude::UVec2; use num_traits::AsPrimitive; #[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() } } #[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_(), } } pub fn index(&self, x: impl AsPrimitive<usize>, y: impl AsPrimitive<usize>) -> usize { (y.as_() * self.width) + x.as_() } pub fn checked_index( &self, x: impl AsPrimitive<usize>, y: impl AsPrimitive<usize>, ) -> Option<usize> { 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) } pub fn checked_reverse(&self, idx: impl AsPrimitive<usize>) -> Option<(usize, usize)> { if self.is_index_valid(idx) { Some(self.reverse(idx)) } else { None } } pub fn index_within(&self, idx: impl AsPrimitive<usize>) -> bool { 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 } pub fn is_coordinate_valid( &self, x: impl AsPrimitive<usize>, y: impl AsPrimitive<usize>, ) -> bool { x.as_() < self.width && y.as_() < self.height } pub fn is_index_valid(&self, idx: impl AsPrimitive<usize>) -> bool { idx.as_() < self.width * self.height } pub fn width(&self) -> usize { self.width } pub fn height(&self) -> usize { self.height } }