use amethyst_core::{
ecs::{
storage::ComponentEvent, BitSet, Join, ReadExpect, ReadStorage, ReaderId, System,
SystemData, World, WriteStorage,
},
math::Isometry3,
transform::components::{Parent, Transform},
};
use crate::{conversors, objects::*, servers::*};
pub struct PhysicsSyncTransformToSystem<N: crate::PtReal> {
phantom_data: std::marker::PhantomData<N>,
transf_event_reader: Option<ReaderId<ComponentEvent>>,
rigid_bodies_event_reader: Option<ReaderId<ComponentEvent>>,
areas_event_reader: Option<ReaderId<ComponentEvent>>,
}
impl<N: crate::PtReal> PhysicsSyncTransformToSystem<N> {
pub fn new() -> PhysicsSyncTransformToSystem<N> {
PhysicsSyncTransformToSystem {
phantom_data: std::marker::PhantomData,
transf_event_reader: None,
rigid_bodies_event_reader: None,
areas_event_reader: None,
}
}
fn parent_transform(
parent: &Parent,
transforms: &ReadStorage<'_, Transform>,
parents: &ReadStorage<'_, Parent>,
) -> Isometry3<f32> {
let i = transforms
.get(parent.entity)
.map_or(Isometry3::identity(), |t| *t.isometry());
if let Some(parent_parent) = parents.get(parent.entity) {
Self::parent_transform(parent_parent, transforms, parents) * i
} else {
i
}
}
}
impl<'s, N: crate::PtReal> System<'s> for PhysicsSyncTransformToSystem<N> {
#[allow(clippy::type_complexity)]
type SystemData = (
ReadExpect<'s, PhysicsWorld<N>>,
ReadStorage<'s, Transform>,
ReadStorage<'s, PhysicsHandle<PhysicsRigidBodyTag>>,
ReadStorage<'s, PhysicsHandle<PhysicsAreaTag>>,
ReadStorage<'s, PhysicsAttachment<N>>,
ReadStorage<'s, Parent>,
);
fn run(
&mut self,
(physics_world, transforms, bodies, areas, attachments, parents): Self::SystemData,
) {
let edited_transforms = {
let trs_events = transforms
.channel()
.read(self.transf_event_reader.as_mut().unwrap());
let bodies_events = bodies
.channel()
.read(self.rigid_bodies_event_reader.as_mut().unwrap());
let area_events = areas
.channel()
.read(self.areas_event_reader.as_mut().unwrap());
let mut edited_transforms = BitSet::with_capacity(
(trs_events.len() + bodies_events.len() + area_events.len()) as u32,
);
for e in trs_events {
#[allow(clippy::single_match)] match e {
ComponentEvent::Inserted(index) => {
edited_transforms.add(*index);
}
_ => {}
}
}
for e in bodies_events {
if let ComponentEvent::Inserted(index) = e {
edited_transforms.add(*index);
}
}
for e in area_events {
if let ComponentEvent::Inserted(index) = e {
edited_transforms.add(*index);
}
}
edited_transforms
};
for (transform, rb_tag, _, _) in
(&transforms, &bodies, !&parents, &edited_transforms).join()
{
physics_world.rigid_body_server().set_transform(
rb_tag.get(),
&conversors::transf_conversor::to_physics(transform.isometry()),
);
}
for (transform, a_tag, _, _) in (&transforms, &areas, !&parents, &edited_transforms).join()
{
physics_world.area_server().set_transform(
a_tag.get(),
&conversors::transf_conversor::to_physics(transform.isometry()),
);
}
{
for (transform, rb_tag, parent, _, _) in (
&transforms,
&bodies,
&parents,
&edited_transforms,
!&attachments,
)
.join()
{
let computed_trs =
Self::parent_transform(parent, &transforms, &parents) * transform.isometry();
physics_world.rigid_body_server().set_transform(
rb_tag.get(),
&conversors::transf_conversor::to_physics(&computed_trs),
);
}
for (transform, a_tag, parent, _, _) in (
&transforms,
&areas,
&parents,
&edited_transforms,
!&attachments,
)
.join()
{
let computed_trs =
Self::parent_transform(parent, &transforms, &parents) * transform.isometry();
physics_world.area_server().set_transform(
a_tag.get(),
&conversors::transf_conversor::to_physics(&computed_trs),
);
}
}
}
fn setup(&mut self, world: &mut World) {
Self::SystemData::setup(world);
{
let mut storage: WriteStorage<'_, Transform> = SystemData::fetch(&world);
self.transf_event_reader = Some(storage.register_reader());
}
{
let mut storage: WriteStorage<'_, PhysicsHandle<PhysicsRigidBodyTag>> =
SystemData::fetch(&world);
self.rigid_bodies_event_reader = Some(storage.register_reader());
}
{
let mut storage: WriteStorage<'_, PhysicsHandle<PhysicsAreaTag>> =
SystemData::fetch(&world);
self.areas_event_reader = Some(storage.register_reader());
}
}
}