use std::fmt::Debug;
use cgmath::{BaseFloat, EuclideanSpace, Point2, Point3, Rotation, Transform, Zero};
use collision::{Bound, Contains, Primitive, SurfaceArea, Union};
use collision::dbvt::{DynamicBoundingVolumeTree, TreeValue};
use shrev::EventChannel;
use specs::{Component, Entity, World};
use core::{BodyPose, Collider, CollisionShape, ContactEvent, ForceAccumulator, GetId, Mass,
NextFrame, RigidBody, Velocity};
use physics::DeltaTime;
pub trait WithRhusics {
fn register_collision<P, B, T, D, Y>(&mut self)
where
P: Primitive + Send + Sync + 'static,
P::Point: Send + Sync + 'static,
<P::Point as EuclideanSpace>::Diff: Debug + Send + Sync + 'static,
<P::Point as EuclideanSpace>::Scalar: BaseFloat + Debug + Send + Sync + 'static,
B: Bound<Point = P::Point>
+ Clone
+ Union<B, Output = B>
+ Contains<B>
+ SurfaceArea<Scalar = <P::Point as EuclideanSpace>::Scalar>
+ Send
+ Sync
+ 'static,
T: Transform<P::Point> + Component + Send + Sync + 'static,
D: TreeValue<Bound = B> + GetId<Entity> + Send + Sync + 'static,
Y: Collider + Send + Sync + 'static;
fn register_physics<P, B, R, D, Y, L, A, I>(&mut self)
where
P: Primitive + Send + Sync + 'static,
P::Point: EuclideanSpace + Send + Sync + 'static,
<P::Point as EuclideanSpace>::Diff: Debug + Send + Sync + 'static,
<P::Point as EuclideanSpace>::Scalar: BaseFloat + Debug + Send + Sync + 'static,
B: Bound<Point = P::Point>
+ Clone
+ Union<B, Output = B>
+ Contains<B>
+ SurfaceArea<Scalar = <P::Point as EuclideanSpace>::Scalar>
+ Send
+ Sync
+ 'static,
R: Rotation<P::Point> + Send + Sync + 'static,
D: TreeValue<Bound = B> + GetId<Entity> + Send + Sync + 'static,
Y: Collider + Send + Sync + 'static,
L: Clone + Send + Sync + 'static,
A: Clone + Send + Sync + 'static,
I: Send + Sync + 'static;
fn register_physics_2d<S, P, B, D, Y>(&mut self)
where
P: Primitive<Point = Point2<S>> + Send + Sync + 'static,
S: BaseFloat + Send + Sync + 'static,
B: Bound<Point = P::Point>
+ Clone
+ Union<B, Output = B>
+ Contains<B>
+ SurfaceArea<Scalar = S>
+ Send
+ Sync
+ 'static,
D: TreeValue<Bound = B> + GetId<Entity> + Send + Sync + 'static,
Y: Collider + Send + Sync + 'static;
fn register_physics_3d<S, P, B, D, Y>(&mut self)
where
P: Primitive<Point = Point3<S>> + Send + Sync + 'static,
S: BaseFloat + Send + Sync + 'static,
B: Bound<Point = P::Point>
+ Clone
+ Union<B, Output = B>
+ Contains<B>
+ SurfaceArea<Scalar = S>
+ Send
+ Sync
+ 'static,
D: TreeValue<Bound = B> + GetId<Entity> + Send + Sync + 'static,
Y: Collider + Send + Sync + 'static;
}
impl WithRhusics for World {
fn register_collision<P, B, T, D, Y>(&mut self)
where
P: Primitive + Send + Sync + 'static,
P::Point: Send + Sync + 'static,
<P::Point as EuclideanSpace>::Diff: Debug + Send + Sync + 'static,
<P::Point as EuclideanSpace>::Scalar: BaseFloat + Debug + Send + Sync + 'static,
B: Bound<Point = P::Point>
+ Clone
+ Union<B, Output = B>
+ Contains<B>
+ SurfaceArea<Scalar = <P::Point as EuclideanSpace>::Scalar>
+ Send
+ Sync
+ 'static,
T: Transform<P::Point> + Component + Send + Sync + 'static,
D: TreeValue<Bound = B> + GetId<Entity> + Send + Sync + 'static,
Y: Collider + Send + Sync + 'static,
{
self.register::<T>();
self.register::<NextFrame<T>>();
self.register::<CollisionShape<P, T, B, Y>>();
self.add_resource(EventChannel::<ContactEvent<Entity, P::Point>>::new());
self.add_resource(DynamicBoundingVolumeTree::<D>::new());
}
fn register_physics<P, B, R, D, Y, L, A, I>(&mut self)
where
P: Primitive + Send + Sync + 'static,
P::Point: EuclideanSpace + Send + Sync + 'static,
<P::Point as EuclideanSpace>::Diff: Debug + Send + Sync + 'static,
<P::Point as EuclideanSpace>::Scalar: BaseFloat + Debug + Send + Sync + 'static,
B: Bound<Point = P::Point>
+ Clone
+ Union<B, Output = B>
+ Contains<B>
+ SurfaceArea<Scalar = <P::Point as EuclideanSpace>::Scalar>
+ Send
+ Sync
+ 'static,
R: Rotation<P::Point> + Send + Sync + 'static,
D: TreeValue<Bound = B> + GetId<Entity> + Send + Sync + 'static,
Y: Collider + Send + Sync + 'static,
L: Clone + Send + Sync + 'static,
A: Clone + Send + Sync + 'static,
I: Send + Sync + 'static,
{
self.add_resource(DeltaTime {
delta_seconds: <P::Point as EuclideanSpace>::Scalar::zero(),
});
self.register::<Mass<<P::Point as EuclideanSpace>::Scalar, I>>();
self.register::<Velocity<L, A>>();
self.register::<NextFrame<Velocity<L, A>>>();
self.register::<RigidBody<<P::Point as EuclideanSpace>::Scalar>>();
self.register::<ForceAccumulator<L, A>>();
self.register_collision::<P, B, BodyPose<P::Point, R>, D, Y>();
}
fn register_physics_2d<S, P, B, D, Y>(&mut self)
where
P: Primitive<Point = Point2<S>> + Send + Sync + 'static,
S: BaseFloat + Send + Sync + 'static,
B: Bound<Point = P::Point>
+ Clone
+ Union<B, Output = B>
+ Contains<B>
+ SurfaceArea<Scalar = S>
+ Send
+ Sync
+ 'static,
D: TreeValue<Bound = B> + GetId<Entity> + Send + Sync + 'static,
Y: Collider + Send + Sync + 'static,
{
use cgmath::{Basis2, Vector2};
self.register_physics::<P, B, Basis2<S>, D, Y, Vector2<S>, S, S>()
}
fn register_physics_3d<S, P, B, D, Y>(&mut self)
where
P: Primitive<Point = Point3<S>> + Send + Sync + 'static,
S: BaseFloat + Send + Sync + 'static,
B: Bound<Point = P::Point>
+ Clone
+ Union<B, Output = B>
+ Contains<B>
+ SurfaceArea<Scalar = S>
+ Send
+ Sync
+ 'static,
D: TreeValue<Bound = B> + GetId<Entity> + Send + Sync + 'static,
Y: Collider + Send + Sync + 'static,
{
use cgmath::{Matrix3, Quaternion, Vector3};
self.register_physics::<P, B, Quaternion<S>, D, Y, Vector3<S>, Vector3<S>, Matrix3<S>>()
}
}