use crate::prelude::*;
use bevy_ecs::prelude::*;
use bevy_math::{DVec3, IVec3};
use bevy_platform::time::Instant;
use bevy_reflect::prelude::*;
use bevy_transform::prelude::*;
#[derive(Component, Default, Debug, PartialEq, Eq, Clone, Copy, Hash, Reflect)]
#[reflect(Component, Default, PartialEq)]
#[require(Transform, GlobalTransform)]
pub struct CellCoord {
pub x: GridPrecision,
pub y: GridPrecision,
pub z: GridPrecision,
}
impl CellCoord {
pub fn new(x: GridPrecision, y: GridPrecision, z: GridPrecision) -> Self {
Self { x, y, z }
}
pub const ZERO: Self = CellCoord { x: 0, y: 0, z: 0 };
pub const ONE: Self = CellCoord { x: 1, y: 1, z: 1 };
pub fn as_dvec3(&self, grid: &Grid) -> DVec3 {
DVec3 {
x: self.x as f64 * grid.cell_edge_length() as f64,
y: self.y as f64 * grid.cell_edge_length() as f64,
z: self.z as f64 * grid.cell_edge_length() as f64,
}
}
pub fn min(&self, rhs: Self) -> Self {
Self {
x: self.x.min(rhs.x),
y: self.y.min(rhs.y),
z: self.z.min(rhs.z),
}
}
pub fn max(&self, rhs: Self) -> Self {
Self {
x: self.x.max(rhs.x),
y: self.y.max(rhs.y),
z: self.z.max(rhs.z),
}
}
pub fn recenter_large_transforms(
mut stats: Option<ResMut<crate::timing::PropagationStats>>,
grids: Query<&Grid>,
mut changed_transform: Query<(&mut Self, &mut Transform, &ChildOf), Changed<Transform>>,
) {
let start = Instant::now();
changed_transform
.par_iter_mut()
.for_each(|(mut grid_pos, mut transform, parent)| {
let Ok(grid) = grids.get(parent.parent()) else {
return;
};
if transform
.bypass_change_detection()
.translation
.abs()
.max_element()
> grid.maximum_distance_from_origin()
{
let (grid_cell_delta, translation) = grid.imprecise_translation_to_grid(
transform.bypass_change_detection().translation,
);
*grid_pos += grid_cell_delta;
transform.translation = translation;
}
});
if let Some(stats) = stats.as_mut() {
stats.grid_recentering += start.elapsed();
}
}
}
impl core::ops::Add for CellCoord {
type Output = CellCoord;
fn add(self, rhs: Self) -> Self::Output {
CellCoord {
x: self.x.wrapping_add(rhs.x),
y: self.y.wrapping_add(rhs.y),
z: self.z.wrapping_add(rhs.z),
}
}
}
impl core::ops::Add<IVec3> for CellCoord {
type Output = CellCoord;
fn add(self, rhs: IVec3) -> Self::Output {
CellCoord {
x: self.x.wrapping_add(rhs.x as GridPrecision),
y: self.y.wrapping_add(rhs.y as GridPrecision),
z: self.z.wrapping_add(rhs.z as GridPrecision),
}
}
}
impl core::ops::Sub for CellCoord {
type Output = CellCoord;
fn sub(self, rhs: Self) -> Self::Output {
CellCoord {
x: self.x.wrapping_sub(rhs.x),
y: self.y.wrapping_sub(rhs.y),
z: self.z.wrapping_sub(rhs.z),
}
}
}
impl core::ops::Sub<IVec3> for CellCoord {
type Output = CellCoord;
fn sub(self, rhs: IVec3) -> Self::Output {
CellCoord {
x: self.x.wrapping_add(-rhs.x as GridPrecision),
y: self.y.wrapping_add(-rhs.y as GridPrecision),
z: self.z.wrapping_add(-rhs.z as GridPrecision),
}
}
}
impl core::ops::Add for &CellCoord {
type Output = CellCoord;
fn add(self, rhs: Self) -> Self::Output {
(*self).add(*rhs)
}
}
impl core::ops::Add<IVec3> for &CellCoord {
type Output = CellCoord;
fn add(self, rhs: IVec3) -> Self::Output {
(*self).add(rhs)
}
}
impl core::ops::Sub for &CellCoord {
type Output = CellCoord;
fn sub(self, rhs: Self) -> Self::Output {
(*self).sub(*rhs)
}
}
impl core::ops::Sub<IVec3> for &CellCoord {
type Output = CellCoord;
fn sub(self, rhs: IVec3) -> Self::Output {
(*self).sub(rhs)
}
}
impl core::ops::AddAssign for CellCoord {
fn add_assign(&mut self, rhs: Self) {
use core::ops::Add;
*self = self.add(rhs);
}
}
impl core::ops::AddAssign<IVec3> for CellCoord {
fn add_assign(&mut self, rhs: IVec3) {
use core::ops::Add;
*self = self.add(rhs);
}
}
impl core::ops::SubAssign for CellCoord {
fn sub_assign(&mut self, rhs: Self) {
use core::ops::Sub;
*self = self.sub(rhs);
}
}
impl core::ops::SubAssign<IVec3> for CellCoord {
fn sub_assign(&mut self, rhs: IVec3) {
use core::ops::Sub;
*self = self.sub(rhs);
}
}
impl core::ops::Mul<GridPrecision> for CellCoord {
type Output = CellCoord;
fn mul(self, rhs: GridPrecision) -> Self::Output {
CellCoord {
x: self.x * rhs,
y: self.y * rhs,
z: self.z * rhs,
}
}
}
impl core::ops::Mul<GridPrecision> for &CellCoord {
type Output = CellCoord;
fn mul(self, rhs: GridPrecision) -> Self::Output {
(*self).mul(rhs)
}
}
impl core::ops::Div<GridPrecision> for CellCoord {
type Output = CellCoord;
fn div(self, rhs: GridPrecision) -> Self::Output {
CellCoord {
x: self.x / rhs,
y: self.y / rhs,
z: self.z / rhs,
}
}
}
impl core::ops::Div<GridPrecision> for &CellCoord {
type Output = CellCoord;
fn div(self, rhs: GridPrecision) -> Self::Output {
(*self).div(rhs)
}
}