1use crate::body::{BodyArena, BodyId, RigidBody};
2use crate::integrator::PhysicsSpace;
3
4#[derive(Default)]
5pub(crate) struct DirtyBodies {
6 ids: Vec<BodyId>,
7 marked: Vec<bool>,
8}
9
10impl DirtyBodies {
11 pub(crate) fn mark(&mut self, id: BodyId) {
12 let slot = id.slot() as usize;
13 if slot >= self.marked.len() {
14 self.marked.resize(slot + 1, false);
15 }
16 if self.marked[slot] {
17 return;
18 }
19 self.marked[slot] = true;
20 self.ids.push(id);
21 }
22
23 pub(crate) fn forget(&mut self, id: BodyId) {
24 if let Some(flag) = self.marked.get_mut(id.slot() as usize) {
25 *flag = false;
26 }
27 }
28
29 pub(crate) fn mark_every<S: PhysicsSpace>(&mut self, bodies: &BodyArena<S>) {
30 self.ids.clear();
31 for flag in &mut self.marked {
32 *flag = false;
33 }
34 for dense in 0..bodies.len() {
35 self.mark(bodies.id_at(dense));
36 }
37 }
38
39 pub(crate) fn drain<'a, S: PhysicsSpace>(
40 &'a mut self,
41 bodies: &'a BodyArena<S>,
42 ) -> DirtyDrain<'a, S> {
43 let Self { ids, marked } = self;
44 DirtyDrain {
45 bodies,
46 marked,
47 ids: ids.drain(..),
48 }
49 }
50}
51
52pub struct DirtyDrain<'a, S: PhysicsSpace> {
53 bodies: &'a BodyArena<S>,
54 marked: &'a mut [bool],
55 ids: std::vec::Drain<'a, BodyId>,
56}
57
58impl<'a, S: PhysicsSpace> Iterator for DirtyDrain<'a, S> {
59 type Item = (BodyId, &'a RigidBody<S>);
60
61 fn next(&mut self) -> Option<Self::Item> {
62 let bodies = self.bodies;
63 for id in self.ids.by_ref() {
64 if let Some(flag) = self.marked.get_mut(id.slot() as usize) {
65 *flag = false;
66 }
67 if let Some(body) = bodies.get(id) {
68 return Some((id, body));
69 }
70 }
71 None
72 }
73}
74
75impl<S: PhysicsSpace> Drop for DirtyDrain<'_, S> {
76 fn drop(&mut self) {
77 for id in self.ids.by_ref() {
78 if let Some(flag) = self.marked.get_mut(id.slot() as usize) {
79 *flag = false;
80 }
81 }
82 }
83}