use bevy::{
ecs::{
entity::{Entity, EntityNotSpawnedError},
system::{Query, SystemParam, lifetimeless::Write},
world::Mut,
},
transform::{
components::GlobalTransform,
helper::{ComputeGlobalTransformError, TransformHelper},
},
};
use thiserror::Error;
use crate::{
math::AdjustPrecision,
prelude::{Position, Rotation},
};
#[derive(SystemParam)]
pub struct PhysicsTransformHelper<'w, 's> {
pub transform_helper: TransformHelper<'w, 's>,
pub query: Query<'w, 's, (Write<Position>, Write<Rotation>)>,
}
impl PhysicsTransformHelper<'_, '_> {
pub fn compute_global_transform(
&self,
entity: Entity,
) -> Result<GlobalTransform, ComputeGlobalTransformError> {
self.transform_helper.compute_global_transform(entity)
}
pub fn update_physics_transform(
&mut self,
entity: Entity,
) -> Result<(Mut<'_, Position>, Mut<'_, Rotation>), UpdatePhysicsTransformError> {
use ComputeGlobalTransformError::*;
let global_transform = self
.transform_helper
.compute_global_transform(entity)
.map_err(|err| match err {
MissingTransform(e) => UpdatePhysicsTransformError::MissingTransform(e),
NoSuchEntity(e) => UpdatePhysicsTransformError::NoSuchEntity(e),
MalformedHierarchy(e) => UpdatePhysicsTransformError::MalformedHierarchy(e),
})?;
let Ok((mut position, mut rotation)) = self.query.get_mut(entity) else {
return Err(UpdatePhysicsTransformError::MissingTransform(entity));
};
#[cfg(feature = "2d")]
{
position.0 = global_transform.translation().truncate().adjust_precision();
*rotation = Rotation::from(global_transform.rotation().adjust_precision());
}
#[cfg(feature = "3d")]
{
position.0 = global_transform.translation().adjust_precision();
rotation.0 = global_transform.rotation().adjust_precision();
}
Ok((position, rotation))
}
}
#[derive(Debug, Error)]
pub enum UpdatePhysicsTransformError {
#[error(
"The entity {0:?} or one of its ancestors is missing either the `Transform`, `Position`, or `Rotation` component"
)]
MissingTransform(Entity),
#[error("{0}")]
NoSuchEntity(EntityNotSpawnedError),
#[error("{0}")]
MalformedHierarchy(EntityNotSpawnedError),
}