use crate::prelude::*;
use bevy::prelude::*;
use bevy_rapier2d::{
prelude::*,
rapier::prelude::{Pose, SharedShape, Vector},
};
#[derive(Default, Reflect, Copy, Clone, Debug)]
#[reflect(Default, Debug)]
pub enum TiledPhysicsRapierBackend {
#[default]
Polyline,
Triangulation,
LineStrip,
}
impl TiledPhysicsBackend for TiledPhysicsRapierBackend {
fn spawn_colliders(
&self,
commands: &mut Commands,
_source: TiledColliderSource,
origin: Entity,
multi_polygons_list: Vec<geo::MultiPolygon<f32>>,
) -> Option<Entity> {
let mut out = None;
for multi_polygon in multi_polygons_list {
match self {
TiledPhysicsRapierBackend::Triangulation => {
let shared_shapes = multi_polygon_as_triangles(&multi_polygon)
.iter()
.map(|([a, b, c], centroid)| {
(Pose::new(*centroid, 0.), SharedShape::triangle(*a, *b, *c))
})
.collect::<Vec<_>>();
if !shared_shapes.is_empty() {
let collider: Collider = SharedShape::compound(shared_shapes).into();
let collider_entity = match out {
Some(parent) => commands
.spawn((ChildOf(parent), Name::from("Rapier[Triangulation]")))
.id(),
None => {
out = Some(origin);
origin
}
};
commands.entity(collider_entity).insert(collider);
}
}
TiledPhysicsRapierBackend::LineStrip => {
multi_polygon_as_line_strings(&multi_polygon)
.iter()
.enumerate()
.for_each(|(i, ls)| {
let collider: Collider = SharedShape::polyline(
ls.points().map(|v| Vector::new(v.x(), v.y())).collect(),
None,
)
.into();
let collider_entity = match out {
Some(parent) => commands
.spawn((
ChildOf(parent),
Name::from(format!("Rapier[LineStrip {i}]")),
))
.id(),
None => {
out = Some(origin);
origin
}
};
commands.entity(collider_entity).insert(collider);
});
}
TiledPhysicsRapierBackend::Polyline => {
let mut vertices = vec![];
let mut indices = vec![];
multi_polygon_as_line_strings(&multi_polygon)
.iter()
.for_each(|ls| {
ls.lines().for_each(|l| {
let points = l.points();
let len = vertices.len();
vertices.push(Vector::new(points.0.x(), points.0.y()));
vertices.push(Vector::new(points.1.x(), points.1.y()));
indices.push([len as u32, (len + 1) as u32]);
});
});
if !vertices.is_empty() {
let collider: Collider =
SharedShape::polyline(vertices, Some(indices)).into();
let collider_entity = match out {
Some(parent) => commands
.spawn((ChildOf(parent), Name::from("Rapier[Polyline]")))
.id(),
None => {
out = Some(origin);
origin
}
};
commands.entity(collider_entity).insert(collider);
}
}
}
}
out
}
}