1mod sleeping;
46
47#[expect(deprecated)]
48pub use sleeping::{
49 IslandSleepingPlugin, SleepBody, SleepIslands, WakeBody, WakeIslands, WakeUpBody,
50};
51
52use bevy::{
53 ecs::{entity_disabling::Disabled, lifecycle::HookContext, world::DeferredWorld},
54 prelude::*,
55};
56use slab::Slab;
57
58use crate::{
59 collision::contact_types::{ContactGraphInternal, ContactId},
60 dynamics::solver::{
61 joint_graph::{JointGraph, JointId},
62 solver_body::SolverBody,
63 },
64 prelude::{
65 ContactGraph, PhysicsSchedule, RigidBody, RigidBodyColliders, RigidBodyDisabled,
66 SolverSystems,
67 },
68};
69
70pub struct IslandPlugin;
74
75impl Plugin for IslandPlugin {
76 fn build(&self, app: &mut App) {
77 app.init_resource::<PhysicsIslands>();
78
79 app.register_required_components::<SolverBody, BodyIslandNode>();
81
82 app.add_observer(
85 |trigger: On<Replace, RigidBodyDisabled>,
86 rb_query: Query<&RigidBody>,
87 mut commands: Commands| {
88 let Ok(rb) = rb_query.get(trigger.entity) else {
89 return;
90 };
91 if rb.is_dynamic() || rb.is_kinematic() {
92 commands
93 .entity(trigger.entity)
94 .try_insert(BodyIslandNode::default());
95 }
96 },
97 );
98 app.add_observer(
99 |trigger: On<Replace, Disabled>,
100 rb_query: Query<
101 &RigidBody,
102 (
103 With<Disabled>,
106 Without<RigidBodyDisabled>,
107 ),
108 >,
109 mut commands: Commands| {
110 let Ok(rb) = rb_query.get(trigger.entity) else {
111 return;
112 };
113 if rb.is_dynamic() || rb.is_kinematic() {
114 commands
115 .entity(trigger.entity)
116 .try_insert(BodyIslandNode::default());
117 }
118 },
119 );
120
121 app.add_observer(|trigger: On<Remove, RigidBody>, mut commands: Commands| {
127 commands
128 .entity(trigger.entity)
129 .try_remove::<BodyIslandNode>();
130 });
131 app.add_observer(
132 |trigger: On<Insert, (Disabled, RigidBodyDisabled)>,
133 query: Query<&RigidBody, Or<(With<Disabled>, Without<Disabled>)>>,
134 mut commands: Commands| {
135 if query.contains(trigger.entity) {
136 commands
137 .entity(trigger.entity)
138 .try_remove::<BodyIslandNode>();
139 }
140 },
141 );
142 app.add_observer(
143 |trigger: On<Insert, RigidBody>, query: Query<&RigidBody>, mut commands: Commands| {
144 if let Ok(rb) = query.get(trigger.entity)
145 && rb.is_static()
146 {
147 commands
148 .entity(trigger.entity)
149 .try_remove::<BodyIslandNode>();
150 }
151 },
152 );
153
154 app.add_systems(
155 PhysicsSchedule,
156 split_island.in_set(SolverSystems::Finalize),
157 );
158 }
159}
160
161fn split_island(
162 mut islands: ResMut<PhysicsIslands>,
163 mut body_islands: Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
164 body_colliders: Query<&RigidBodyColliders>,
165 mut contact_graph: ResMut<ContactGraph>,
166 mut joint_graph: ResMut<JointGraph>,
167) {
168 if let Some(island_id) = islands.split_candidate {
170 islands.split_island(
171 island_id,
172 &mut body_islands,
173 &body_colliders,
174 &mut contact_graph,
175 &mut joint_graph,
176 );
177 }
178}
179
180#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Reflect)]
182#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
183#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
184#[reflect(Debug, PartialEq)]
185pub struct IslandId(pub u32);
186
187impl IslandId {
188 pub const PLACEHOLDER: Self = Self(u32::MAX);
190}
191
192impl core::fmt::Display for IslandId {
193 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
194 write!(f, "IslandId({})", self.0)
195 }
196}
197
198#[derive(Clone, Debug, PartialEq)]
213pub struct PhysicsIsland {
214 pub(crate) id: IslandId,
215
216 pub(crate) head_body: Option<Entity>,
217 pub(crate) tail_body: Option<Entity>,
218 pub(crate) body_count: u32,
219
220 pub(crate) head_contact: Option<ContactId>,
221 pub(crate) tail_contact: Option<ContactId>,
222 pub(crate) contact_count: u32,
223
224 pub(crate) head_joint: Option<JointId>,
225 pub(crate) tail_joint: Option<JointId>,
226 pub(crate) joint_count: u32,
227
228 pub(crate) sleep_timer: f32,
229 pub(crate) is_sleeping: bool,
230
231 pub(crate) constraints_removed: u32,
232}
233
234impl PhysicsIsland {
235 #[inline]
237 pub const fn new(id: IslandId) -> Self {
238 Self {
239 id,
240 head_body: None,
241 tail_body: None,
242 body_count: 0,
243 head_contact: None,
244 tail_contact: None,
245 contact_count: 0,
246 head_joint: None,
247 tail_joint: None,
248 joint_count: 0,
249 sleep_timer: 0.0,
250 is_sleeping: false,
251 constraints_removed: 0,
252 }
253 }
254
255 #[inline]
257 pub const fn id(&self) -> IslandId {
258 self.id
259 }
260
261 #[inline]
263 pub const fn body_count(&self) -> u32 {
264 self.body_count
265 }
266
267 #[inline]
269 pub const fn contact_count(&self) -> u32 {
270 self.contact_count
271 }
272
273 #[inline]
275 pub const fn joint_count(&self) -> u32 {
276 self.joint_count
277 }
278
279 #[inline]
281 pub const fn is_sleeping(&self) -> bool {
282 self.is_sleeping
283 }
284
285 #[inline]
287 pub const fn constraints_removed(&self) -> u32 {
288 self.constraints_removed
289 }
290
291 #[inline]
294 pub fn validate(
295 &self,
296 body_islands: &Query<&BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
297 contact_graph: &ContactGraphInternal,
298 joint_graph: &JointGraph,
299 ) {
300 self.validate_bodies(body_islands);
301 self.validate_contacts(contact_graph);
302 self.validate_joints(joint_graph);
303 }
304
305 pub fn validate_bodies(
307 &self,
308 body_islands: &Query<&BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
309 ) {
310 if self.head_body.is_none() {
311 assert!(self.tail_body.is_none());
312 assert_eq!(self.body_count, 0);
313 return;
314 }
315
316 assert!(self.tail_body.is_some());
317 assert!(self.body_count > 0);
318
319 if self.body_count > 1 {
320 assert_ne!(self.head_body, self.tail_body);
321 }
322
323 let mut count = 0;
324 let mut body_id = self.head_body;
325
326 while let Some(entity) = body_id {
327 let body = body_islands.get(entity).unwrap();
328 assert_eq!(body.island_id, self.id);
329
330 count += 1;
331
332 if count == self.body_count {
333 assert_eq!(body_id, self.tail_body);
334 }
335
336 body_id = body.next;
337 }
338
339 assert_eq!(count, self.body_count);
340 }
341
342 pub fn validate_contacts(&self, contact_graph: &ContactGraphInternal) {
344 if self.head_contact.is_none() {
345 assert!(self.tail_contact.is_none());
346 assert_eq!(self.contact_count, 0);
347 return;
348 }
349
350 assert!(self.tail_contact.is_some());
351 assert!(self.contact_count > 0);
352
353 if self.contact_count > 1 {
354 assert_ne!(self.head_contact, self.tail_contact);
355 }
356
357 let mut count = 0;
358 let mut contact_id = self.head_contact;
359
360 while let Some(id) = contact_id {
361 let contact = contact_graph.edge_weight(id.into()).unwrap();
362 let contact_island = contact
363 .island
364 .as_ref()
365 .unwrap_or_else(|| panic!("Contact {id:?} has no island"));
366 assert_eq!(contact_island.island_id, self.id);
367
368 count += 1;
369
370 if count == self.contact_count {
371 assert_eq!(contact_id, self.tail_contact);
372 }
373
374 contact_id = contact_island.next;
375 }
376
377 assert_eq!(count, self.contact_count);
378 }
379
380 pub fn validate_joints(&self, joint_graph: &JointGraph) {
382 if self.head_joint.is_none() {
383 assert!(self.tail_joint.is_none());
384 assert_eq!(self.joint_count, 0);
385 return;
386 }
387
388 assert!(self.tail_joint.is_some());
389 assert!(self.joint_count > 0);
390
391 if self.joint_count > 1 {
392 assert_ne!(self.head_joint, self.tail_joint);
393 }
394
395 let mut count = 0;
396 let mut joint_id = self.head_joint;
397
398 while let Some(id) = joint_id {
399 let joint = joint_graph.get_by_id(id).unwrap();
400 let joint_island = &joint.island;
401 assert_eq!(joint_island.island_id, self.id);
402
403 count += 1;
404
405 if count == self.joint_count {
406 assert_eq!(joint_id, self.tail_joint);
407 }
408
409 joint_id = joint_island.next;
410 }
411
412 assert_eq!(count, self.joint_count);
413 }
414}
415
416#[derive(Resource, Debug, Default, Clone)]
418pub struct PhysicsIslands {
419 islands: Slab<PhysicsIsland>,
421 pub split_candidate: Option<IslandId>,
426 pub split_candidate_sleep_timer: f32,
430}
431
432impl PhysicsIslands {
433 #[inline]
435 pub fn create_island_with<F>(&mut self, init: F) -> IslandId
436 where
437 F: FnOnce(&mut PhysicsIsland),
438 {
439 let island_id = self.next_id();
441 let mut island = PhysicsIsland::new(island_id);
442
443 init(&mut island);
445
446 IslandId(self.islands.insert(island) as u32)
448 }
449
450 #[inline]
456 pub fn remove_island(&mut self, island_id: IslandId) -> PhysicsIsland {
457 if self.split_candidate == Some(island_id) {
458 self.split_candidate = None;
459 }
460
461 self.islands.remove(island_id.0 as usize)
463 }
464
465 #[inline]
467 pub fn next_id(&self) -> IslandId {
468 IslandId(self.islands.vacant_key() as u32)
469 }
470
471 #[inline]
473 pub fn get(&self, island_id: IslandId) -> Option<&PhysicsIsland> {
474 self.islands.get(island_id.0 as usize)
475 }
476
477 #[inline]
479 pub fn get_mut(&mut self, island_id: IslandId) -> Option<&mut PhysicsIsland> {
480 self.islands.get_mut(island_id.0 as usize)
481 }
482
483 #[inline]
485 pub fn iter(&self) -> impl Iterator<Item = &PhysicsIsland> {
486 self.islands.iter().map(|(_, island)| island)
487 }
488
489 #[inline]
491 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut PhysicsIsland> {
492 self.islands.iter_mut().map(|(_, island)| island)
493 }
494
495 #[inline]
497 pub fn len(&self) -> usize {
498 self.islands.len()
499 }
500
501 #[inline]
503 pub fn is_empty(&self) -> bool {
504 self.islands.is_empty()
505 }
506
507 pub fn add_contact(
514 &mut self,
515 contact_id: ContactId,
516 body_islands: &mut Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
517 contact_graph: &mut ContactGraph,
518 joint_graph: &mut JointGraph,
519 ) -> Option<&PhysicsIsland> {
520 let contact = contact_graph.get_edge_mut_by_id(contact_id).unwrap();
521
522 debug_assert!(contact.island.is_none());
523 debug_assert!(contact.is_touching());
524
525 let (Some(body1), Some(body2)) = (contact.body1, contact.body2) else {
526 return None;
527 };
528
529 let island_id = self.merge_islands(body1, body2, body_islands, contact_graph, joint_graph);
531
532 let island = self
534 .islands
535 .get_mut(island_id.0 as usize)
536 .unwrap_or_else(|| {
537 panic!("Island {island_id} does not exist");
538 });
539
540 let mut contact_island = IslandNode {
541 island_id: island.id,
542 prev: None,
543 next: None,
544 is_visited: false,
545 };
546
547 if let Some(head_contact_id) = island.head_contact {
548 contact_island.next = Some(head_contact_id);
550
551 let head_contact = contact_graph.get_edge_mut_by_id(head_contact_id).unwrap();
552 let head_contact_island = head_contact
553 .island
554 .as_mut()
555 .unwrap_or_else(|| panic!("Head contact {head_contact_id:?} has no island"));
556 head_contact_island.prev = Some(contact_id);
557 }
558
559 island.head_contact = Some(contact_id);
560
561 if island.tail_contact.is_none() {
562 island.tail_contact = island.head_contact;
563 }
564
565 let contact = contact_graph.get_edge_mut_by_id(contact_id).unwrap();
567 contact.island = Some(contact_island);
568
569 island.contact_count += 1;
570
571 #[cfg(feature = "validate")]
572 {
573 island.validate(
575 &body_islands.as_readonly(),
576 &contact_graph.edges,
577 joint_graph,
578 );
579 }
580
581 Some(island)
582 }
583
584 #[expect(
591 unused_variables,
592 reason = "additional parameters are needed with the `validate` feature"
593 )]
594 pub fn remove_contact(
595 &mut self,
596 contact_id: ContactId,
597 body_islands: &mut Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
598 contact_graph: &mut ContactGraphInternal,
599 joint_graph: &JointGraph,
600 ) -> &PhysicsIsland {
601 let contact = contact_graph.edge_weight_mut(contact_id.into()).unwrap();
602
603 debug_assert!(contact.island.is_some());
604
605 let contact_island = contact.island.take().unwrap();
607
608 if let Some(prev_contact_id) = contact_island.prev {
610 let prev_contact = contact_graph
611 .edge_weight_mut(prev_contact_id.into())
612 .unwrap();
613 let prev_contact_island = prev_contact
614 .island
615 .as_mut()
616 .expect("Previous contact has no island");
617 debug_assert!(prev_contact_island.next == Some(contact_id));
618 prev_contact_island.next = contact_island.next;
619 }
620
621 if let Some(next_contact_id) = contact_island.next {
622 let next_contact = contact_graph
623 .edge_weight_mut(next_contact_id.into())
624 .unwrap();
625 let next_contact_island = next_contact
626 .island
627 .as_mut()
628 .expect("Next contact has no island");
629 debug_assert!(next_contact_island.prev == Some(contact_id));
630 next_contact_island.prev = contact_island.prev;
631 }
632
633 let island = self
634 .islands
635 .get_mut(contact_island.island_id.0 as usize)
636 .unwrap_or_else(|| {
637 panic!("Island {} does not exist", contact_island.island_id);
638 });
639
640 if island.head_contact == Some(contact_id) {
641 island.head_contact = contact_island.next;
643 }
644
645 if island.tail_contact == Some(contact_id) {
646 island.tail_contact = contact_island.prev;
648 }
649
650 debug_assert!(island.contact_count > 0);
651 island.contact_count -= 1;
652 island.constraints_removed += 1;
653
654 #[cfg(feature = "validate")]
655 {
656 island.validate(&body_islands.as_readonly(), contact_graph, joint_graph);
658 }
659
660 island
661 }
662
663 pub fn add_joint(
670 &mut self,
671 joint_id: JointId,
672 body_islands: &mut Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
673 contact_graph: &mut ContactGraph,
674 joint_graph: &mut JointGraph,
675 ) -> Option<&PhysicsIsland> {
676 let joint = joint_graph.get_mut_by_id(joint_id).unwrap();
677
678 let island_id = self.merge_islands(
680 joint.body1,
681 joint.body2,
682 body_islands,
683 contact_graph,
684 joint_graph,
685 );
686
687 let island = self
689 .islands
690 .get_mut(island_id.0 as usize)
691 .unwrap_or_else(|| {
692 panic!("Island {island_id} does not exist");
693 });
694
695 let mut joint_island = IslandNode {
696 island_id: island.id,
697 prev: None,
698 next: None,
699 is_visited: false,
700 };
701
702 if let Some(head_joint_id) = island.head_joint {
703 joint_island.next = Some(head_joint_id);
705
706 let head_joint = joint_graph.get_mut_by_id(head_joint_id).unwrap();
707 let head_island = &mut head_joint.island;
708 head_island.prev = Some(joint_id);
709 }
710
711 island.head_joint = Some(joint_id);
712
713 if island.tail_joint.is_none() {
714 island.tail_joint = island.head_joint;
715 }
716
717 let joint = joint_graph.get_mut_by_id(joint_id).unwrap();
719 joint.island = joint_island;
720
721 island.joint_count += 1;
722
723 #[cfg(feature = "validate")]
724 {
725 island.validate(
727 &body_islands.as_readonly(),
728 &contact_graph.edges,
729 joint_graph,
730 );
731 }
732
733 Some(island)
734 }
735
736 #[expect(
746 unused_variables,
747 reason = "additional parameters are needed with the `validate` feature"
748 )]
749 pub fn remove_joint(
750 &mut self,
751 joint_id: JointId,
752 body_islands: &mut Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
753 contact_graph: &ContactGraph,
754 joint_graph: &mut JointGraph,
755 ) -> Option<&PhysicsIsland> {
756 let joint = joint_graph.get_mut_by_id(joint_id).unwrap();
757
758 debug_assert!(joint.island.island_id != IslandId::PLACEHOLDER);
759
760 let joint_island = joint.island;
762
763 if let Some(prev_joint_id) = joint_island.prev {
765 let prev_joint = joint_graph.get_mut_by_id(prev_joint_id).unwrap();
766 let prev_island = &mut prev_joint.island;
767 debug_assert!(prev_island.next == Some(joint_id));
768 prev_island.next = joint_island.next;
769 }
770
771 if let Some(next_joint_id) = joint_island.next {
772 let next_joint = joint_graph.get_mut_by_id(next_joint_id).unwrap();
773 let next_island = &mut next_joint.island;
774 debug_assert!(next_island.prev == Some(joint_id));
775 next_island.prev = joint_island.prev;
776 }
777
778 let island = self.islands.get_mut(joint_island.island_id.0 as usize)?;
779
780 if island.head_joint == Some(joint_id) {
781 island.head_joint = joint_island.next;
783 }
784
785 if island.tail_joint == Some(joint_id) {
786 island.tail_joint = joint_island.prev;
788 }
789
790 debug_assert!(island.joint_count > 0);
791 island.joint_count -= 1;
792 island.constraints_removed += 1;
793
794 #[cfg(feature = "validate")]
795 {
796 island.validate(
798 &body_islands.as_readonly(),
799 &contact_graph.edges,
800 joint_graph,
801 );
802 }
803
804 Some(island)
805 }
806
807 pub fn merge_islands(
815 &mut self,
816 body1: Entity,
817 body2: Entity,
818 body_islands: &mut Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
819 contact_graph: &mut ContactGraph,
820 joint_graph: &mut JointGraph,
821 ) -> IslandId {
822 let Ok(island_id1) = body_islands.get(body1).map(|island| island.island_id) else {
823 let island2 = body_islands.get(body2).unwrap_or_else(|_| {
824 panic!("Neither body {body1:?} nor {body2:?} is in an island");
825 });
826 return island2.island_id;
827 };
828
829 let Ok(island_id2) = body_islands.get(body2).map(|island| island.island_id) else {
830 let island1 = body_islands.get(body1).unwrap_or_else(|_| {
831 panic!("Neither body {body1:?} nor {body2:?} is in an island");
832 });
833 return island1.island_id;
834 };
835
836 if island_id1 == island_id2 {
837 return island_id1;
839 }
840
841 let [mut big, mut small] = self
844 .islands
845 .get_disjoint_mut([island_id1.0 as usize, island_id2.0 as usize])
846 .unwrap();
847 if big.body_count < small.body_count {
848 core::mem::swap(&mut big, &mut small);
849 }
850
851 let mut body_entity = small.head_body;
855 while let Some(entity) = body_entity {
856 let mut body_island = body_islands.get_mut(entity).unwrap();
857 body_island.island_id = big.id;
858 body_entity = body_island.next;
859 }
860
861 let mut contact_id = small.head_contact;
863 while let Some(id) = contact_id {
864 let contact = contact_graph.get_edge_mut_by_id(id).unwrap();
865 let contact_island = contact.island.as_mut().expect("Contact has no island");
866 contact_island.island_id = big.id;
867 contact_id = contact_island.next;
868 }
869
870 let mut joint_id = small.head_joint;
872 while let Some(id) = joint_id {
873 let joint = joint_graph.get_mut_by_id(id).unwrap();
874 joint.island.island_id = big.id;
875 joint_id = joint.island.next;
876 }
877
878 let tail_body_id = big.tail_body.expect("Island {island_id1} has no tail body");
882 let head_body_id = small
883 .head_body
884 .expect("Island {island_id2} has no head body");
885 let [mut tail_body, mut head_body] = body_islands
886 .get_many_mut([tail_body_id, head_body_id])
887 .unwrap();
888 tail_body.next = small.head_body;
889 head_body.prev = big.tail_body;
890
891 big.tail_body = small.tail_body;
892 big.body_count += small.body_count;
893
894 if big.head_contact.is_none() {
896 debug_assert!(big.tail_contact.is_none() && big.contact_count == 0);
898
899 big.head_contact = small.head_contact;
900 big.tail_contact = small.tail_contact;
901 big.contact_count = small.contact_count;
902 } else if small.head_contact.is_some() {
903 debug_assert!(big.contact_count > 0);
905 debug_assert!(small.contact_count > 0);
906
907 let tail_contact_id = big.tail_contact.expect("Root island has no tail contact");
908 let head_contact_id = small.head_contact.expect("Island has no head contact");
909
910 let tail_contact = contact_graph.get_edge_mut_by_id(tail_contact_id).unwrap();
912 let tail_contact_island = tail_contact
913 .island
914 .as_mut()
915 .expect("Tail contact has no island");
916 debug_assert!(tail_contact_island.next.is_none());
917 tail_contact_island.next = small.head_contact;
918
919 let head_contact = contact_graph.get_edge_mut_by_id(head_contact_id).unwrap();
921 let head_contact_island = head_contact
922 .island
923 .as_mut()
924 .expect("Head contact has no island");
925 debug_assert!(head_contact_island.prev.is_none());
926 head_contact_island.prev = big.tail_contact;
927
928 big.tail_contact = small.tail_contact;
929 big.contact_count += small.contact_count;
930 }
931
932 if big.head_joint.is_none() {
934 debug_assert!(big.tail_joint.is_none() && big.joint_count == 0);
936
937 big.head_joint = small.head_joint;
938 big.tail_joint = small.tail_joint;
939 big.joint_count = small.joint_count;
940 } else if small.head_joint.is_some() {
941 debug_assert!(big.joint_count > 0);
943 debug_assert!(small.joint_count > 0);
944
945 let tail_joint_id = big.tail_joint.expect("Root island has no tail joint");
946 let head_joint_id = small.head_joint.expect("Island has no head joint");
947
948 let tail_joint = joint_graph.get_mut_by_id(tail_joint_id).unwrap();
950 let tail_island = &mut tail_joint.island;
951 debug_assert!(tail_island.next.is_none());
952 tail_island.next = small.head_joint;
953
954 let head_joint = joint_graph.get_mut_by_id(head_joint_id).unwrap();
956 let head_island = &mut head_joint.island;
957 debug_assert!(head_island.prev.is_none());
958 head_island.prev = big.tail_joint;
959
960 big.tail_joint = small.tail_joint;
961 big.joint_count += small.joint_count;
962 }
963
964 big.constraints_removed += small.constraints_removed;
966
967 if small.is_sleeping {
969 big.is_sleeping = true;
971 big.sleep_timer = small.sleep_timer.max(big.sleep_timer);
972 }
973
974 #[cfg(feature = "validate")]
975 {
976 big.validate(
978 &body_islands.as_readonly(),
979 &contact_graph.edges,
980 joint_graph,
981 );
982 }
983
984 let big_id = big.id;
986 let small_id = small.id;
987 self.remove_island(small_id);
988
989 big_id
990 }
991
992 pub fn split_island(
996 &mut self,
997 island_id: IslandId,
998 body_islands: &mut Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
999 body_colliders: &Query<&RigidBodyColliders>,
1000 contact_graph: &mut ContactGraph,
1001 joint_graph: &mut JointGraph,
1002 ) {
1003 let island = self.islands.get_mut(island_id.0 as usize).unwrap();
1004
1005 if island.is_sleeping {
1006 return;
1008 }
1009
1010 if island.constraints_removed == 0 {
1011 return;
1013 }
1014
1015 #[cfg(feature = "validate")]
1016 {
1017 island.validate(
1019 &body_islands.as_readonly(),
1020 &contact_graph.edges,
1021 joint_graph,
1022 );
1023 }
1024
1025 let body_count = island.body_count;
1026
1027 let mut body_ids = Vec::with_capacity(body_count as usize);
1032 let mut next_body = island.head_body;
1033
1034 while let Some(body_id) = next_body {
1035 body_ids.push(body_id);
1036
1037 let mut body_island = body_islands.get_mut(body_id).unwrap();
1038
1039 body_island.is_visited = false;
1041
1042 next_body = body_island.next;
1043 }
1044
1045 debug_assert_eq!(body_ids.len(), body_count as usize);
1046
1047 let mut next_contact = island.head_contact;
1049 while let Some(contact_id) = next_contact {
1050 let contact = contact_graph.get_edge_mut_by_id(contact_id).unwrap();
1051 let contact_island = contact
1052 .island
1053 .as_mut()
1054 .unwrap_or_else(|| panic!("Contact {contact_id:?} has no island"));
1055
1056 contact_island.is_visited = false;
1058
1059 next_contact = contact_island.next;
1060 }
1061
1062 let mut next_joint = island.head_joint;
1064 while let Some(joint_id) = next_joint {
1065 let joint = joint_graph.get_mut_by_id(joint_id).unwrap();
1066 let joint_island = &mut joint.island;
1067
1068 joint_island.is_visited = false;
1070
1071 next_joint = joint_island.next;
1072 }
1073
1074 self.remove_island(island_id);
1076
1077 let mut stack = Vec::with_capacity(body_ids.len());
1079 for seed_id in body_ids.into_iter() {
1080 let mut seed = body_islands.get_mut(seed_id).unwrap();
1081
1082 if seed.is_visited {
1083 continue;
1085 }
1086
1087 seed.is_visited = true;
1088
1089 let island_id = self.next_id();
1091 let mut island = PhysicsIsland::new(island_id);
1092
1093 stack.push(seed_id);
1095
1096 while let Some(body) = stack.pop() {
1098 let mut body_island = unsafe { body_islands.get_unchecked(body).unwrap() };
1099
1100 debug_assert!(body_island.is_visited);
1101
1102 body_island.island_id = island_id;
1104
1105 if let Some(tail_body_id) = island.tail_body {
1106 debug_assert_ne!(tail_body_id, body);
1107 unsafe {
1108 body_islands.get_unchecked(tail_body_id).unwrap().next = Some(body);
1109 }
1110 }
1111
1112 body_island.prev = island.tail_body;
1113 body_island.next = None;
1114 island.tail_body = Some(body);
1115
1116 if island.head_body.is_none() {
1117 island.head_body = Some(body);
1118 }
1119
1120 island.body_count += 1;
1121
1122 let contact_edges: Vec<(ContactId, Entity)> = body_colliders
1125 .get(body)
1126 .iter()
1127 .flat_map(|colliders| {
1128 colliders.into_iter().flat_map(|collider| {
1129 contact_graph
1130 .contact_edges_with(collider)
1131 .filter_map(|contact_edge| {
1132 if contact_edge.island.is_some_and(|island| island.is_visited) {
1133 return None;
1135 }
1136
1137 if contact_edge.constraint_handles.is_empty() {
1138 return None;
1140 }
1141
1142 let (Some(body1), Some(body2)) =
1144 (contact_edge.body1, contact_edge.body2)
1145 else {
1146 return None;
1148 };
1149
1150 Some((
1151 contact_edge.id,
1152 if body1 == body { body2 } else { body1 },
1153 ))
1154 })
1155 })
1156 })
1157 .collect();
1158
1159 for (contact_id, other_body) in contact_edges {
1160 if let Ok(mut other_body_island) = body_islands.get_mut(other_body)
1162 && !other_body_island.is_visited
1163 {
1164 stack.push(other_body);
1165 other_body_island.is_visited = true;
1166 }
1167
1168 if let Some(tail_contact_id) = island.tail_contact {
1170 let tail_contact =
1171 contact_graph.get_edge_mut_by_id(tail_contact_id).unwrap();
1172 let tail_contact_island =
1173 tail_contact.island.as_mut().unwrap_or_else(|| {
1174 panic!("Tail contact {tail_contact_id:?} has no island")
1175 });
1176 tail_contact_island.next = Some(contact_id);
1177 }
1178
1179 let contact_edge = contact_graph.get_edge_mut_by_id(contact_id).unwrap();
1180 let contact_island = contact_edge
1181 .island
1182 .as_mut()
1183 .unwrap_or_else(|| panic!("Contact {contact_id:?} has no island"));
1184
1185 contact_island.is_visited = true;
1186 contact_island.island_id = island_id;
1187 contact_island.prev = island.tail_contact;
1188 contact_island.next = None;
1189
1190 island.tail_contact = Some(contact_id);
1191
1192 if island.head_contact.is_none() {
1193 island.head_contact = Some(contact_id);
1194 }
1195
1196 island.contact_count += 1;
1197 }
1198
1199 let joint_edges: Vec<(JointId, Entity)> = joint_graph
1201 .joints_of(body)
1202 .filter_map(|joint_edge| {
1203 if joint_edge.island.is_visited {
1204 return None;
1206 }
1207
1208 Some((
1209 joint_edge.id,
1210 if joint_edge.body1 == body {
1211 joint_edge.body2
1212 } else {
1213 joint_edge.body1
1214 },
1215 ))
1216 })
1217 .collect();
1218
1219 for (joint_id, other_body) in joint_edges {
1220 if let Ok(mut other_body_island) = body_islands.get_mut(other_body)
1222 && !other_body_island.is_visited
1223 {
1224 stack.push(other_body);
1225 other_body_island.is_visited = true;
1226 }
1227
1228 if let Some(tail_joint_id) = island.tail_joint {
1230 let tail_joint = joint_graph.get_mut_by_id(tail_joint_id).unwrap();
1231 let tail_island = &mut tail_joint.island;
1232 tail_island.next = Some(joint_id);
1233 }
1234
1235 let joint = joint_graph.get_mut_by_id(joint_id).unwrap();
1236 let joint_island = &mut joint.island;
1237
1238 joint_island.is_visited = true;
1239 joint_island.island_id = island_id;
1240 joint_island.prev = island.tail_joint;
1241 joint_island.next = None;
1242
1243 island.tail_joint = Some(joint_id);
1244
1245 if island.head_joint.is_none() {
1246 island.head_joint = Some(joint_id);
1247 }
1248
1249 island.joint_count += 1;
1250 }
1251 }
1252
1253 #[cfg(feature = "validate")]
1254 {
1255 island.validate(
1257 &body_islands.as_readonly(),
1258 &contact_graph.edges,
1259 joint_graph,
1260 );
1261 }
1262
1263 self.islands.insert(island);
1265 }
1266 }
1267}
1268
1269#[derive(Clone, Debug, PartialEq, Eq, Reflect)]
1271#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
1272pub struct IslandNode<Id> {
1273 pub(crate) island_id: IslandId,
1275 pub(crate) prev: Option<Id>,
1277 pub(crate) next: Option<Id>,
1279 pub(crate) is_visited: bool,
1281}
1282
1283impl<Id> IslandNode<Id> {
1284 pub const PLACEHOLDER: Self = Self::new(IslandId::PLACEHOLDER);
1286
1287 #[inline]
1289 pub const fn new(island_id: IslandId) -> Self {
1290 Self {
1291 island_id,
1292 prev: None,
1293 next: None,
1294 is_visited: false,
1295 }
1296 }
1297
1298 #[inline]
1300 pub const fn island_id(&self) -> IslandId {
1301 self.island_id
1302 }
1303}
1304
1305impl<Id> Default for IslandNode<Id> {
1306 fn default() -> Self {
1307 Self::PLACEHOLDER
1308 }
1309}
1310
1311impl<Id: Copy> Copy for IslandNode<Id> {}
1312
1313#[derive(Component, Clone, Debug, Default, Deref, DerefMut, PartialEq, Eq, Reflect)]
1315#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
1316#[component(on_add = BodyIslandNode::on_add, on_remove = BodyIslandNode::on_remove)]
1317pub struct BodyIslandNode(IslandNode<Entity>);
1318
1319impl BodyIslandNode {
1320 #[inline]
1322 pub const fn new(island_id: IslandId) -> Self {
1323 Self(IslandNode::new(island_id))
1324 }
1325
1326 fn on_add(mut world: DeferredWorld, ctx: HookContext) {
1328 let mut islands = world.resource_mut::<PhysicsIslands>();
1330 let island_id = islands.create_island_with(|island| {
1331 island.head_body = Some(ctx.entity);
1332 island.tail_body = Some(ctx.entity);
1333 island.body_count = 1;
1334 });
1335
1336 let mut body_island = world.get_mut::<BodyIslandNode>(ctx.entity).unwrap();
1338 body_island.island_id = island_id;
1339 }
1340
1341 fn on_remove(mut world: DeferredWorld, ctx: HookContext) {
1343 let body_island = world.get::<BodyIslandNode>(ctx.entity).unwrap();
1344 let island_id = body_island.island_id;
1345 let prev_body_entity = body_island.prev;
1346 let next_body_entity = body_island.next;
1347
1348 if let Some(entity) = prev_body_entity {
1350 let mut prev_body_island = world.get_mut::<BodyIslandNode>(entity).unwrap();
1351 prev_body_island.next = next_body_entity;
1352 }
1353 if let Some(entity) = next_body_entity {
1354 let mut next_body_island = world.get_mut::<BodyIslandNode>(entity).unwrap();
1355 next_body_island.prev = prev_body_entity;
1356 }
1357
1358 let mut islands = world.resource_mut::<PhysicsIslands>();
1359 let island = islands
1360 .get_mut(island_id)
1361 .unwrap_or_else(|| panic!("Island {island_id} does not exist"));
1362
1363 debug_assert!(island.body_count > 0);
1364 island.body_count -= 1;
1365
1366 #[cfg(feature = "validate")]
1367 let mut island_removed = false;
1368
1369 if island.head_body == Some(ctx.entity) {
1370 island.head_body = next_body_entity;
1371
1372 if island.head_body.is_none() {
1373 debug_assert!(island.tail_body == Some(ctx.entity));
1375 debug_assert!(island.body_count == 0);
1376 debug_assert!(island.contact_count == 0);
1377
1378 world
1379 .resource_mut::<PhysicsIslands>()
1380 .remove_island(island_id);
1381
1382 #[cfg(feature = "validate")]
1383 {
1384 island_removed = true;
1385 }
1386 }
1387 } else if island.tail_body == Some(ctx.entity) {
1388 island.tail_body = prev_body_entity;
1389 }
1390
1391 #[cfg(feature = "validate")]
1392 if !island_removed {
1393 world.commands().queue(move |world: &mut World| {
1395 use bevy::ecs::system::RunSystemOnce;
1396 let _ = world.run_system_once(
1398 move |bodies: Query<
1399 &BodyIslandNode,
1400 Or<(With<Disabled>, Without<Disabled>)>,
1401 >,
1402 islands: Res<PhysicsIslands>,
1403 contact_graph: Res<ContactGraph>,
1404 joint_graph: Res<JointGraph>| {
1405 let island = islands
1406 .get(island_id)
1407 .unwrap_or_else(|| panic!("Island {island_id} does not exist"));
1408 island.validate(&bodies, &contact_graph.edges, &joint_graph);
1409 },
1410 );
1411 });
1412 }
1413 }
1414}