Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ColliderParent component #397

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions bevy_rapier3d/examples/ray_casting3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,16 @@ fn cast_ray(
) {
let window = windows.single();

let Some(cursor_position) = window.cursor_position() else { return; };
let Some(cursor_position) = window.cursor_position() else {
return;
};

// We will color in read the colliders hovered by the mouse.
for (camera, camera_transform) in &cameras {
// First, compute a ray from the mouse position.
let Some(ray) = camera.viewport_to_world(camera_transform, cursor_position) else { return; };
let Some(ray) = camera.viewport_to_world(camera_transform, cursor_position) else {
return;
};

// Then cast the ray.
let hit = rapier_context.cast_ray(
Expand Down
48 changes: 46 additions & 2 deletions src/geometry/collider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@ use std::fmt;
#[cfg(all(feature = "dim3", feature = "async-collider"))]
use {crate::geometry::VHACDParameters, bevy::utils::HashMap};

use bevy::prelude::*;
use bevy::{
ecs::{
entity::{EntityMapper, MapEntities},
reflect::ReflectMapEntities,
},
prelude::*,
utils::HashSet,
};

use bevy::utils::HashSet;
use rapier::geometry::Shape;
use rapier::prelude::{ColliderHandle, InteractionGroups, SharedShape};

Expand Down Expand Up @@ -503,6 +509,44 @@ impl CollidingEntities {
#[reflect(Component, PartialEq)]
pub struct ColliderDisabled;

/// Rigid body parent of the collider.
///
/// This is not meant to be set directly, this is controlled by bevy's hierarchy.
///
/// To change a colliders parent, set the [`Parent`] of the entity to a
/// different rigid body or remove the parent to leave the collider unattached.
#[derive(Component, Debug, Eq, PartialEq, Reflect)]
#[reflect(Component, MapEntities, PartialEq)]
pub struct ColliderParent(pub(crate) Entity);

impl ColliderParent {
/// Gets the [`Entity`] ID of the rigid-body parent this collider is attached to.
///
/// This may be the same entity as the collider.
pub fn get(&self) -> Entity {
self.0
}
}

impl FromWorld for ColliderParent {
fn from_world(_world: &mut World) -> Self {
Self(Entity::PLACEHOLDER)
}
}

impl MapEntities for ColliderParent {
fn map_entities(&mut self, entity_mapper: &mut EntityMapper) {
self.0 = entity_mapper.get_or_reserve(self.0);
}
}

impl std::ops::Deref for ColliderParent {
type Target = Entity;
fn deref(&self) -> &Self::Target {
&self.0
}
}

/// We restrict the scaling increment to 1.0e-4, to avoid numerical jitter
/// due to the extraction of scaling factor from the GlobalTransform matrix.
pub fn get_snapped_scale(scale: Vect) -> Vect {
Expand Down
4 changes: 3 additions & 1 deletion src/geometry/collider_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,9 @@ impl Collider {
/// Returns `None` if the index buffer or vertex buffer of the mesh are in an incompatible format.
#[cfg(all(feature = "dim3", feature = "async-collider"))]
pub fn from_bevy_mesh(mesh: &Mesh, collider_shape: &ComputedColliderShape) -> Option<Self> {
let Some((vtx, idx)) = extract_mesh_vertices_indices(mesh) else { return None; };
let Some((vtx, idx)) = extract_mesh_vertices_indices(mesh) else {
return None;
};
match collider_shape {
ComputedColliderShape::TriMesh => Some(
SharedShape::trimesh_with_flags(vtx, idx, TriMeshFlags::MERGE_DUPLICATE_VERTICES)
Expand Down
26 changes: 23 additions & 3 deletions src/plugin/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ where
/// See [`PhysicsSet`] for a description of these systems.
pub fn get_systems(set: PhysicsSet) -> SystemConfigs {
match set {
PhysicsSet::EveryFrame => (
systems::collect_collider_hierarchy_changes,
apply_deferred,
systems::sync_removals,
)
.chain()
.into_configs(),
PhysicsSet::SyncBackend => (
// Run the character controller before the manual transform propagation.
systems::update_character_controls,
Expand All @@ -94,9 +101,10 @@ where
systems::init_rigid_bodies,
systems::init_colliders,
systems::init_joints,
systems::sync_removals,
// Run this here so the folowwing systems do not have a 1 frame delay.
systems::collect_collider_hierarchy_changes,
// Run this here so the following systems do not have a 1 frame delay.
apply_deferred,
systems::sync_removals,
systems::apply_scale,
systems::apply_collider_user_changes,
systems::apply_rigid_body_user_changes,
Expand Down Expand Up @@ -159,6 +167,9 @@ pub enum PhysicsSet {
/// components and the [`GlobalTransform`] component.
/// These systems typically run immediately after [`PhysicsSet::StepSimulation`].
Writeback,
/// The systems responsible for responding to state like `Events` that get
/// cleared every 2 main schedule runs.
EveryFrame,
}

impl<PhysicsHooks> Plugin for RapierPhysicsPlugin<PhysicsHooks>
Expand All @@ -172,6 +183,10 @@ where
.register_type::<Velocity>()
.register_type::<AdditionalMassProperties>()
.register_type::<MassProperties>()
.register_type::<ReadMassProperties>()
.register_type::<ColliderMassProperties>()
.register_type::<ColliderDisabled>()
.register_type::<RigidBodyDisabled>()
.register_type::<LockedAxes>()
.register_type::<ExternalForce>()
.register_type::<ExternalImpulse>()
Expand All @@ -185,6 +200,7 @@ where
.register_type::<Friction>()
.register_type::<Restitution>()
.register_type::<CollisionGroups>()
.register_type::<ColliderParent>()
.register_type::<SolverGroups>()
.register_type::<ContactForceEventThreshold>()
.register_type::<Group>();
Expand All @@ -204,6 +220,7 @@ where

// Add each set as necessary
if self.default_system_setup {
app.configure_sets(PostUpdate, (PhysicsSet::EveryFrame,));
app.configure_sets(
self.schedule.clone(),
(
Expand All @@ -216,7 +233,10 @@ where
);

// These *must* be in the main schedule currently so that they do not miss events.
app.add_systems(PostUpdate, (systems::sync_removals,));
app.add_systems(
PostUpdate,
Self::get_systems(PhysicsSet::EveryFrame).in_set(PhysicsSet::EveryFrame),
);

app.add_systems(
self.schedule.clone(),
Expand Down
Loading