Fix user changes handling (#803)

* add failing test from @Johannes0021

* apply fix on update_positions

* apply fix on ColliderSet::iter_mut

* fix clippy..

* more complete test

* feat: refactor modified sets into a wrapper to avoid future mistakes

* chore: fix typos

---------

Co-authored-by: Sébastien Crozet <sebcrozet@dimforge.com>
This commit is contained in:
Thierry Berger
2025-03-28 12:48:25 +01:00
committed by GitHub
parent d291041278
commit 176c3bae14
10 changed files with 272 additions and 78 deletions

View File

@@ -0,0 +1,65 @@
use std::marker::PhantomData;
use std::ops::Deref;
/// Contains handles of modified objects.
///
/// This is a wrapper over a `Vec` to ensure we dont forget to set the objects
/// MODIFIED flag when adding it to this set.
/// It is possible to bypass the wrapper with `.as_mut_internal`. But this should only
/// be done for internal engine usage (like the physics pipeline).
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[derive(Clone, Debug)]
pub(crate) struct ModifiedObjects<Handle, Object>(Vec<Handle>, PhantomData<Object>);
impl<Handle, Object> Default for ModifiedObjects<Handle, Object> {
fn default() -> Self {
Self(Vec::new(), PhantomData)
}
}
pub(crate) trait HasModifiedFlag {
fn has_modified_flag(&self) -> bool;
fn set_modified_flag(&mut self);
}
impl<Handle, Object> Deref for ModifiedObjects<Handle, Object> {
type Target = Vec<Handle>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<Handle, Object: HasModifiedFlag> ModifiedObjects<Handle, Object> {
pub fn with_capacity(capacity: usize) -> Self {
Self(Vec::with_capacity(capacity), PhantomData)
}
/// Remove every handle from this set.
///
/// Note that the corresponding object MODIFIED flags wont be reset automatically by this function.
pub fn clear(&mut self) {
self.0.clear()
}
/// Pushes a object handle to this set after checking that it doesnt have the MODIFIED
/// flag set.
///
/// This will also set the objects MODIFIED flag.
pub fn push_once(&mut self, handle: Handle, object: &mut Object) {
if !object.has_modified_flag() {
self.push_unchecked(handle, object);
}
}
/// Pushes an object handle to this set without checking if the object already has the MODIFIED
/// flags.
///
/// Only use in situation where you are certain (due to other contextual information) that
/// the object isnt already in the set.
///
/// This will also set the objects MODIFIED flag.
pub fn push_unchecked(&mut self, handle: Handle, object: &mut Object) {
object.set_modified_flag();
self.0.push(handle);
}
}