diff --git a/src/shape/capsule.rs b/src/shape/capsule.rs index 54b595e4..d4dad62d 100644 --- a/src/shape/capsule.rs +++ b/src/shape/capsule.rs @@ -8,7 +8,7 @@ use either::Either; #[cfg(feature = "rkyv")] use rkyv::{bytecheck, CheckBytes}; -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))] #[cfg_attr( diff --git a/src/shape/compound.rs b/src/shape/compound.rs index 024fded9..e0d1279f 100644 --- a/src/shape/compound.rs +++ b/src/shape/compound.rs @@ -26,6 +26,12 @@ pub struct Compound { aabb: Aabb, } +impl PartialEq for Compound { + fn eq(&self, other: &Self) -> bool { + self.shapes() == other.shapes() + } +} + impl Compound { /// Builds a new compound shape. /// diff --git a/src/shape/convex_polygon.rs b/src/shape/convex_polygon.rs index 7ef31b94..fc2b3ca5 100644 --- a/src/shape/convex_polygon.rs +++ b/src/shape/convex_polygon.rs @@ -10,7 +10,7 @@ use na::{self, ComplexField, RealField, Unit}; derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize), archive(check_bytes) )] -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct ConvexPolygon { points: Vec>, normals: Vec>>, diff --git a/src/shape/polyline.rs b/src/shape/polyline.rs index 8d47b35d..eb04bdc5 100644 --- a/src/shape/polyline.rs +++ b/src/shape/polyline.rs @@ -23,6 +23,12 @@ pub struct Polyline { indices: Vec<[u32; 2]>, } +impl PartialEq for Polyline { + fn eq(&self, other: &Self) -> bool { + self.indices() == other.indices() && self.vertices() == other.vertices() + } +} + impl Polyline { /// Creates a new polyline from a vertex buffer and an index buffer. pub fn new(vertices: Vec>, indices: Option>) -> Self { diff --git a/src/shape/round_shape.rs b/src/shape/round_shape.rs index 96c05130..5ebd26d7 100644 --- a/src/shape/round_shape.rs +++ b/src/shape/round_shape.rs @@ -9,7 +9,7 @@ use na::Unit; archive(check_bytes) )] #[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))] -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq)] #[repr(C)] /// A shape with rounded borders. pub struct RoundShape { diff --git a/src/shape/shared_shape.rs b/src/shape/shared_shape.rs index 5935029f..b1d33b6a 100644 --- a/src/shape/shared_shape.rs +++ b/src/shape/shared_shape.rs @@ -14,6 +14,8 @@ use na::Unit; use std::ops::Deref; use std::sync::Arc; +use super::TypedShape; + /// The shape of a collider. #[derive(Clone)] pub struct SharedShape(pub Arc); @@ -384,3 +386,47 @@ impl<'de> serde::Deserialize<'de> for SharedShape { .ok_or(D::Error::custom("Cannot deserialize custom shape.")) } } + +impl PartialEq for SharedShape { + fn eq(&self, other: &Self) -> bool { + // shapes with different types can't be equal. + if self.shape_type() != other.shape_type() { + return false; + } + match self.as_typed_shape() { + TypedShape::Ball(shape) => shape == other.as_ball().unwrap(), + TypedShape::Cuboid(shape) => shape == other.as_cuboid().unwrap(), + TypedShape::RoundCuboid(shape) => shape == other.as_round_cuboid().unwrap(), + TypedShape::Capsule(shape) => shape == other.as_capsule().unwrap(), + TypedShape::Segment(shape) => shape == other.as_segment().unwrap(), + TypedShape::Triangle(shape) => shape == other.as_triangle().unwrap(), + TypedShape::RoundTriangle(shape) => shape == other.as_round_triangle().unwrap(), + TypedShape::TriMesh(shape) => shape == other.as_trimesh().unwrap(), + TypedShape::Polyline(shape) => shape == other.as_polyline().unwrap(), + TypedShape::HalfSpace(shape) => shape == other.as_halfspace().unwrap(), + TypedShape::HeightField(_) => false, + TypedShape::Compound(shape) => shape == other.as_compound().unwrap(), + TypedShape::Custom(_) => false, + #[cfg(feature = "dim3")] + TypedShape::ConvexPolyhedron(shape) => shape == other.as_convex_polyhedron().unwrap(), + #[cfg(feature = "dim3")] + TypedShape::Cylinder(shape) => shape == other.as_cylinder().unwrap(), + #[cfg(feature = "dim3")] + TypedShape::Cone(shape) => shape == other.as_cone().unwrap(), + #[cfg(feature = "dim3")] + TypedShape::RoundCylinder(shape) => shape == other.as_round_cylinder().unwrap(), + #[cfg(feature = "dim3")] + TypedShape::RoundCone(shape) => shape == other.as_round_cone().unwrap(), + #[cfg(feature = "dim3")] + TypedShape::RoundConvexPolyhedron(shape) => { + shape == other.as_round_convex_polyhedron().unwrap() + } + #[cfg(feature = "dim2")] + TypedShape::ConvexPolygon(shape) => shape == other.as_convex_polygon().unwrap(), + #[cfg(feature = "dim2")] + TypedShape::RoundConvexPolygon(shape) => { + shape == other.as_round_convex_polygon().unwrap() + } + } + } +} diff --git a/src/shape/trimesh.rs b/src/shape/trimesh.rs index 8686207c..012d5747 100644 --- a/src/shape/trimesh.rs +++ b/src/shape/trimesh.rs @@ -358,6 +358,22 @@ pub struct GenericTriMesh { flags: TriMeshFlags, } +impl PartialEq for TriMesh { + fn eq(&self, other: &Self) -> bool { + let triangles = self.triangles(); + let other_triangles = other.triangles(); + if triangles.len() != other_triangles.len() { + return false; + } + for (t1, t2) in triangles.zip(other_triangles) { + if t1 != t2 { + return false; + } + } + true + } +} + /// A triangle-mesh. pub type TriMesh = GenericTriMesh; #[cfg(feature = "cuda")]