Skip to main content

rapier3d/dynamics/soft_body/soft_body_set/
soft_body_set.rs

1//! The `SoftBodySet` struct, its island event, its accessors and its `Index` impls.
2use crate::alloc_prelude::*;
3use crate::data::arena::Arena;
4use crate::dynamics::RigidBodyHandle;
5#[allow(unused_imports)]
6use crate::dynamics::RigidBodySet;
7use crate::dynamics::soft_body::{SoftBody, SoftBodyHandle};
8#[allow(unused_imports)]
9use crate::geometry::ColliderSet;
10use parry::utils::hashmap::HashMap;
11
12/// Deferred island-connectivity event emitted by [`SoftBodySet`] on insertion, removal and
13/// attachment changes, drained at the start of the next step.
14#[derive(Copy, Clone, Debug)]
15pub(crate) struct SoftBodyIslandEvent {
16    /// The soft body whose attachment links must be updated (relinked if it still exists,
17    /// unlinked otherwise).
18    pub handle: SoftBodyHandle,
19}
20
21/// A set of soft bodies that can be handled by a physics pipeline. Inserting a soft body creates
22/// its hidden root rigid body in the [`RigidBodySet`] (see [`SoftBody`]) and its colliders in the
23/// [`ColliderSet`]; removing it removes them, so never remove those yourself.
24#[derive(Clone, Default)]
25#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
26pub struct SoftBodySet {
27    pub(crate) bodies: Arena<SoftBody>,
28    /// Island-connectivity events (soft body inserted/removed, attachments changed), drained at
29    /// the start of the next timestep.
30    #[cfg_attr(feature = "serde-serialize", serde(skip))]
31    pub(crate) island_events: Vec<SoftBodyIslandEvent>,
32    /// The soft bodies attached to each rigid body, with the attachment's index (rebuilt when
33    /// attachments change; the island manager's adjacency).
34    #[cfg_attr(feature = "serde-serialize", serde(skip))]
35    pub(crate) attached_to: HashMap<RigidBodyHandle, Vec<(SoftBodyHandle, u32)>>,
36    /// Whether `attached_to` must be rebuilt (a body with attachments was removed, or the set
37    /// was deserialized).
38    #[cfg_attr(feature = "serde-serialize", serde(skip, default = "default_true"))]
39    pub(super) attached_to_stale: bool,
40}
41
42#[cfg(feature = "serde-serialize")]
43fn default_true() -> bool {
44    true
45}
46
47impl SoftBodySet {
48    /// Creates an empty set.
49    pub fn new() -> Self {
50        Self::default()
51    }
52
53    /// The number of soft bodies in this set.
54    pub fn len(&self) -> usize {
55        self.bodies.len()
56    }
57
58    /// Whether this set is empty.
59    pub fn is_empty(&self) -> bool {
60        self.bodies.is_empty()
61    }
62
63    /// Whether the given handle identifies a soft body of this set.
64    pub fn contains(&self, handle: SoftBodyHandle) -> bool {
65        self.bodies.contains(handle.0)
66    }
67
68    /// The soft body with the given handle.
69    pub fn get(&self, handle: SoftBodyHandle) -> Option<&SoftBody> {
70        self.bodies.get(handle.0)
71    }
72
73    /// The soft body with the given handle.
74    pub fn get_mut(&mut self, handle: SoftBodyHandle) -> Option<&mut SoftBody> {
75        self.bodies.get_mut(handle.0)
76    }
77
78    /// Iterates over the soft bodies of this set.
79    pub fn iter(&self) -> impl ExactSizeIterator<Item = (SoftBodyHandle, &SoftBody)> {
80        self.bodies.iter().map(|(h, b)| (SoftBodyHandle(h), b))
81    }
82
83    /// Iterates mutably over the soft bodies of this set.
84    pub fn iter_mut(&mut self) -> impl ExactSizeIterator<Item = (SoftBodyHandle, &mut SoftBody)> {
85        self.bodies.iter_mut().map(|(h, b)| (SoftBodyHandle(h), b))
86    }
87
88    /// The soft bodies with a particle attached to the given rigid body, with the attachment's
89    /// index in their attachment list (as of the start of the current step).
90    pub(crate) fn attached_to(&self, body: RigidBodyHandle) -> &[(SoftBodyHandle, u32)] {
91        self.attached_to.get(&body).map_or(&[], |v| v.as_slice())
92    }
93}
94
95impl core::ops::Index<SoftBodyHandle> for SoftBodySet {
96    type Output = SoftBody;
97
98    fn index(&self, index: SoftBodyHandle) -> &SoftBody {
99        &self.bodies[index.0]
100    }
101}
102
103impl core::ops::IndexMut<SoftBodyHandle> for SoftBodySet {
104    fn index_mut(&mut self, index: SoftBodyHandle) -> &mut SoftBody {
105        &mut self.bodies[index.0]
106    }
107}