From 385601b6411a6264a906a744e014838d5f7332a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Crozet?= Date: Sat, 23 Mar 2024 13:11:37 +0100 Subject: [PATCH] =?UTF-8?q?feat:=E2=80=AFadd=20RigidBody::copy=5Ffrom=20an?= =?UTF-8?q?d=20Collider::copy=5Ffrom?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #595 --- CHANGELOG.md | 2 ++ src/dynamics/rigid_body.rs | 55 ++++++++++++++++++++++++++++++++++++++ src/geometry/collider.rs | 47 ++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf37c0693..b99f8d4e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ - Add `RigidBody::predict_position_using_velocity` to predict the next position of the rigid-body based only on its current velocity. +- Add `Collider::copy_from` to copy most collider attributes to an existing collider. +- Add `RigidBody::copy_from` to copy most rigid-body attributes to an existing rigid-body. ## v0.18.0 (24 Jan. 2024) diff --git a/src/dynamics/rigid_body.rs b/src/dynamics/rigid_body.rs index 2b07f379e..5af4131f6 100644 --- a/src/dynamics/rigid_body.rs +++ b/src/dynamics/rigid_body.rs @@ -74,6 +74,61 @@ impl RigidBody { self.ids = Default::default(); } + /// Copy all the characteristics from `other` to `self`. + /// + /// If you have a mutable reference to a rigid-body `rigid_body: &mut RigidBody`, attempting to + /// assign it a whole new rigid-body instance, e.g., `*rigid_body = RigidBodyBuilder::dynamic().build()`, + /// will crash due to some internal indices being overwritten. Instead, use + /// `rigid_body.copy_from(&RigidBodyBuilder::dynamic().build())`. + /// + /// This method will allow you to set most characteristics of this rigid-body from another + /// rigid-body instance without causing any breakage. + /// + /// This method **cannot** be used for editing the list of colliders attached to this rigid-body. + /// Therefore, the list of colliders attached to `self` won’t be replaced by the one attached + /// to `other`. + /// + /// The pose of `other` will only copied into `self` if `self` doesn’t have a parent (if it has + /// a parent, its position is directly controlled by the parent rigid-body). + pub fn copy_from(&mut self, other: &RigidBody) { + // NOTE: we deconstruct the rigid-body struct to be sure we don’t forget to + // add some copies here if we add more field to RigidBody in the future. + let RigidBody { + pos, + mprops, + integrated_vels, + vels, + damping, + forces, + ccd, + ids: _ids, // Internal ids must not be overwritten. + colliders: _colliders, // This function cannot be used to edit collider sets. + activation, + changes: _changes, // Will be set to ALL. + body_type, + dominance, + enabled, + additional_solver_iterations, + user_data, + } = other; + + self.pos = *pos; + self.mprops = mprops.clone(); + self.integrated_vels = *integrated_vels; + self.vels = *vels; + self.damping = *damping; + self.forces = *forces; + self.ccd = *ccd; + self.activation = *activation; + self.body_type = *body_type; + self.dominance = *dominance; + self.enabled = *enabled; + self.additional_solver_iterations = *additional_solver_iterations; + self.user_data = *user_data; + + self.changes = RigidBodyChanges::all(); + } + /// Set the additional number of solver iterations run for this rigid-body and /// everything interacting with it. /// diff --git a/src/geometry/collider.rs b/src/geometry/collider.rs index 2a31afa91..4e7fbc74d 100644 --- a/src/geometry/collider.rs +++ b/src/geometry/collider.rs @@ -60,6 +60,53 @@ impl Collider { self.coll_type.is_sensor() } + /// Copy all the characteristics from `other` to `self`. + /// + /// If you have a mutable reference to a collider `collider: &mut Collider`, attempting to + /// assign it a whole new collider instance, e.g., `*collider = ColliderBuilder::ball(0.5).build()`, + /// will crash due to some internal indices being overwritten. Instead, use + /// `collider.copy_from(&ColliderBuilder::ball(0.5).build())`. + /// + /// This method will allow you to set most characteristics of this collider from another + /// collider instance without causing any breakage. + /// + /// This method **cannot** be used for reparenting a collider. Therefore, the parent of the + /// `other` (if any), as well as its relative position to that parent will not be copied into + /// `self`. + /// + /// The pose of `other` will only copied into `self` if `self` doesn’t have a parent (if it has + /// a parent, its position is directly controlled by the parent rigid-body). + pub fn copy_from(&mut self, other: &Collider) { + // NOTE: we deconstruct the collider struct to be sure we don’t forget to + // add some copies here if we add more field to Collider in the future. + let Collider { + coll_type, + shape, + mprops, + changes: _changes, // Will be set to ALL. + parent: _parent, // This function cannot be used to reparent the collider. + pos, + material, + flags, + bf_data: _bf_data, // Internal ids must not be overwritten. + contact_force_event_threshold, + user_data, + } = other; + + if self.parent.is_none() { + self.pos = *pos; + } + + self.coll_type = *coll_type; + self.shape = shape.clone(); + self.mprops = mprops.clone(); + self.material = *material; + self.contact_force_event_threshold = *contact_force_event_threshold; + self.user_data = *user_data; + self.flags = *flags; + self.changes = ColliderChanges::all(); + } + /// The physics hooks enabled for this collider. pub fn active_hooks(&self) -> ActiveHooks { self.flags.active_hooks