use astrodyn::{Position, RootInertial, Velocity};
use bevy::prelude::*;
use crate::components::*;
use crate::frame_param::FrameOrigin;
pub(crate) fn body_integ_origin_in_root(
body_frame: Option<&FrameEntityC>,
parents: &Query<&ChildOf>,
root_frame_entity: Entity,
frame_origin: &FrameOrigin,
) -> (Position<RootInertial>, Velocity<RootInertial>) {
let integ_frame_entity =
body_frame.and_then(|fe| parents.get(fe.0).ok().map(|child_of| child_of.parent()));
match integ_frame_entity {
Some(integ_e) if integ_e != root_frame_entity => {
frame_origin.origin_in_root(root_frame_entity, integ_e)
}
_ => (
Position::<RootInertial>::zero(),
Velocity::<RootInertial>::zero(),
),
}
}
pub(crate) fn body_integ_origin_in_root_lazy(
body_frame: Option<&FrameEntityC>,
parents: &Query<&ChildOf>,
root_frame_entity: Option<Entity>,
frame_origin: &FrameOrigin,
) -> (Position<RootInertial>, Velocity<RootInertial>) {
let Some(fe) = body_frame else {
return (
Position::<RootInertial>::zero(),
Velocity::<RootInertial>::zero(),
);
};
let integ_e = parents
.get(fe.0)
.map(|child_of| child_of.parent())
.unwrap_or_else(|err| {
panic!(
"malformed frame tree: body's FrameEntityC ({:?}) has no ChildOf parent \
({err:?}). Every body frame entity must be parented under either the root \
frame entity (root-integrated) or a planet's inertial frame entity \
(planet-integrated). Detached or freshly reparented bodies must restore \
the ChildOf edge before the next staging/step; treating this as \
root-integrated would feed planet-relative coordinates into a \
root-inertial kernel and silently corrupt the merged composite by the \
missing integ-frame's full root-inertial state. Likely cause: an attach \
or detach handler dropped the frame-tree reparent step.",
fe.0,
)
});
let root = root_frame_entity.unwrap_or_else(|| {
panic!(
"RootFrameEntityR resource not present, but a body carries FrameEntityC \
({:?}) whose integ-frame parent is {integ_e:?} — the integ-origin shift \
cannot be computed without the root frame entity. AstrodynPlugin must be \
loaded for systems that lift integration-frame coordinates to \
root-inertial (staging_system, step_detached_system). If your test \
intentionally omits AstrodynPlugin, also omit FrameEntityC from the body \
(root-integrated bodies skip this path entirely).",
fe.0,
)
});
if integ_e == root {
(
Position::<RootInertial>::zero(),
Velocity::<RootInertial>::zero(),
)
} else {
frame_origin.origin_in_root(root, integ_e)
}
}