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}