use bevy_ecs::prelude::*;
use bevy_log::error_once;
use bevy_math::{DQuat, DVec3};
use bevy_transform::prelude::*;
#[derive(Resource)]
pub struct TransformAdapter {
read_fn: Box<dyn Fn(&EntityRef) -> Option<(DVec3, DQuat)> + Send + Sync>,
apply_delta_fn: Box<dyn Fn(&mut EntityMut, DVec3, DQuat) + Send + Sync>,
}
impl TransformAdapter {
pub fn new(
read: impl Fn(&EntityRef) -> Option<(DVec3, DQuat)> + Send + Sync + 'static,
apply_delta: impl Fn(&mut EntityMut, DVec3, DQuat) + Send + Sync + 'static,
) -> Self {
Self {
read_fn: Box::new(read),
apply_delta_fn: Box::new(apply_delta),
}
}
pub fn read(&self, entity: &EntityRef) -> Option<(DVec3, DQuat)> {
(self.read_fn)(entity)
}
pub fn apply_delta(
&self,
entity: &mut EntityMut,
delta_translation: DVec3,
delta_rotation: DQuat,
) {
(self.apply_delta_fn)(entity, delta_translation, delta_rotation)
}
}
pub fn transform_delta(
(original_translation, original_rotation): (DVec3, DQuat),
(new_translation, new_rotation): (DVec3, DQuat),
) -> (DVec3, DQuat) {
let inverse = original_rotation.inverse();
(
inverse * (new_translation - original_translation),
inverse * new_rotation,
)
}
impl Default for TransformAdapter {
fn default() -> Self {
Self::new(
|entity| {
let Some(cam_transform) = entity.get::<Transform>() else {
error_once!("Unable to retrieve Transform from EditorCam entity.");
return None;
};
Some((
cam_transform.translation.as_dvec3(),
cam_transform.rotation.as_dquat(),
))
},
|entity, delta_translation, delta_rotation| {
let Some(mut cam_transform) = entity.get_mut::<Transform>() else {
error_once!("Unable to retrieve Transform from EditorCam entity.");
return;
};
let rotation = cam_transform.rotation.as_dquat();
let translation = cam_transform.translation.as_dvec3();
cam_transform.translation = (translation + rotation * delta_translation).as_vec3();
cam_transform.rotation = (rotation * delta_rotation).normalize().as_quat();
},
)
}
}