use sorted_vec::SortedSet;
use crate::object;
use crate::collision::{InternalId, ObjectPair};
use super::Contact;
#[cfg(feature = "derive_serdes")]
use serde::{Deserialize, Serialize};
pub(crate) type KeyType = object::KeyType;
#[cfg_attr(feature = "derive_serdes", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Default, PartialEq)]
pub(crate) struct Group {
pub contacts : Vec <(ObjectPair, Contact)>
}
impl Group {
pub(crate) fn partition (&self) -> Vec <Group> {
let mut components : Vec <Vec <InternalId>> = vec![];
let find_component = |components : &Vec <Vec <InternalId>>, object_id| {
let mut found_component = None;
for (i, component) in components.iter().enumerate() {
if component.contains (&object_id) {
found_component = Some (i);
break
}
}
found_component
};
for (ObjectPair (object_id_a, object_id_b), _) in self.contacts.iter() {
let component_index_a = if object_id_a.kind() == object::Kind::Dynamic {
find_component (&components, *object_id_a)
} else {
None
};
let component_index_b = find_component (&components, *object_id_b);
match (component_index_a, component_index_b) {
(None, None) => {
let mut component = vec![*object_id_b];
if object_id_a.kind() == object::Kind::Dynamic {
component.push (*object_id_a);
}
components.push (component);
}
(None, Some (component_index_b)) =>
if object_id_a.kind() == object::Kind::Dynamic {
components[component_index_b].push (*object_id_a);
}
(Some (component_index_a), None) =>
components[component_index_a].push (*object_id_b),
(Some (mut component_index_a), Some (component_index_b)) =>
if component_index_a != component_index_b {
let component_b = components.remove (component_index_b);
if component_index_a > component_index_b {
component_index_a -= 1;
}
components[component_index_a].extend (component_b);
}
}
}
debug_assert!(!components.is_empty());
if components.len() == 1 {
debug_assert_eq!(components[0].len(), self.dynamic_ids().len());
vec![]
} else {
let mut out = vec![Group::default(); components.len()];
for contact@(ObjectPair (_, object_id_b), _) in self.contacts.iter() {
for (i, component) in components.iter().enumerate() {
if component.contains (object_id_b) {
out[i].contacts.push (contact.clone());
break
}
}
}
debug_assert!(out.len() >= 2);
out
}
}
pub(crate) fn dynamic_ids (&self) -> SortedSet <InternalId> {
let mut out = SortedSet::new();
for (ObjectPair (object_id_a, object_id_b), _) in self.contacts.iter() {
if object_id_a.kind() == object::Kind::Dynamic {
out.push (*object_id_a);
}
out.push (*object_id_b);
}
out
}
#[expect(dead_code)]
pub(super) fn contains (&self, object_pair : ObjectPair) -> bool {
let (object_id_a, object_id_b) = object_pair.into();
for (pair, _) in self.contacts.iter() {
let (id_a, id_b) = (*pair).into();
if id_a == object_id_a && id_b == object_id_b {
return true
}
}
false
}
pub(super) fn remove_object (&mut self, object_id : InternalId) -> Vec <InternalId> {
let mut out = vec![];
self.contacts.retain (|(object_pair, _)|{
let (id_a, id_b) = (*object_pair).into();
if id_a == object_id {
out.push (id_b);
false
} else if id_b == object_id {
out.push (id_a);
false
} else {
true
}
});
out
}
}