use bevy::prelude::*;
use physx::prelude::*;
use crate::prelude::{Scene, *};
#[derive(Component, Debug, Default, PartialEq, Clone, Copy, Reflect)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[reflect(Component, Default)]
pub struct Kinematic {
pub target: Transform,
}
impl Kinematic {
pub fn new(target: Transform) -> Self {
Self { target }
}
}
pub struct KinematicPlugin;
impl Plugin for KinematicPlugin {
fn build(&self, app: &mut App) {
app.register_type::<Kinematic>();
app.add_systems(PhysicsSchedule, (
kinematic_enable,
kinematic_disable,
kinematic_apply,
).chain().in_set(PhysicsSet::Sync));
}
}
pub fn kinematic_enable(
mut scene: ResMut<Scene>,
mut added: Query<
(&mut RigidDynamicHandle, &Kinematic),
Or<(
Added<RigidDynamicHandle>,
Added<Kinematic>,
)>,
>,
) {
for (mut actor, kinematic) in added.iter_mut() {
let mut rigid_body = actor.get_mut(&mut scene);
rigid_body.set_global_pose(&kinematic.target.to_physx(), false);
rigid_body.set_rigid_body_flag(RigidBodyFlag::Kinematic, true);
}
}
pub fn kinematic_disable(
mut scene: ResMut<Scene>,
mut removed: RemovedComponents<Kinematic>,
mut handles: Query<&mut RigidDynamicHandle>,
) {
for entity in removed.read() {
if let Ok(mut actor) = handles.get_mut(entity) {
let mut rigid_body = actor.get_mut(&mut scene);
rigid_body.set_rigid_body_flag(RigidBodyFlag::Kinematic, false);
rigid_body.wake_up();
};
}
}
pub fn kinematic_apply(
mut scene: ResMut<Scene>,
mut actors: Query<
(Option<&mut RigidDynamicHandle>, Ref<Kinematic>),
Or<(Added<RigidDynamicHandle>, Changed<Kinematic>)>,
>,
) {
for (actor, kinematic) in actors.iter_mut() {
if let Some(mut actor) = actor {
let mut rigid_body = actor.get_mut(&mut scene);
rigid_body.set_kinematic_target(&kinematic.target.to_physx());
} else if !kinematic.is_added() {
bevy::log::warn!("Kinematic component exists, but it's not a rigid dynamic");
};
}
}