boxdd 0.4.0

Safe, ergonomic Rust bindings for Box2D v3
Documentation
use super::runtime_handle::JointRuntimeHandle;
use super::*;
use crate::error::ApiResult;
use crate::types::{BodyId, JointId, Vec2};
use std::marker::PhantomData;
use std::os::raw::c_void;
use std::sync::Arc;

impl OwnedJoint {
    pub(crate) fn new(core: Arc<WorldCore>, id: JointId) -> Self {
        core.owned_joints
            .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
        Self {
            id,
            core,
            destroy_on_drop: true,
            wake_bodies_on_drop: true,
            _not_send: PhantomData,
        }
    }

    pub fn id(&self) -> JointId {
        self.id
    }

    pub fn is_valid(&self) -> bool {
        JointRuntimeHandle::is_valid(self)
    }

    pub fn try_is_valid(&self) -> ApiResult<bool> {
        JointRuntimeHandle::try_is_valid(self)
    }

    /// Borrow the raw id for ID-style APIs.
    pub fn as_id(&self) -> JointId {
        self.id
    }

    pub fn joint_type(&self) -> JointType {
        JointRuntimeHandle::joint_type(self)
    }

    pub fn try_joint_type(&self) -> ApiResult<JointType> {
        JointRuntimeHandle::try_joint_type(self)
    }

    pub fn joint_type_raw(&self) -> ffi::b2JointType {
        JointRuntimeHandle::joint_type_raw(self)
    }

    pub fn try_joint_type_raw(&self) -> ApiResult<ffi::b2JointType> {
        JointRuntimeHandle::try_joint_type_raw(self)
    }

    pub fn body_a_id(&self) -> BodyId {
        JointRuntimeHandle::body_a_id(self)
    }

    pub fn try_body_a_id(&self) -> ApiResult<BodyId> {
        JointRuntimeHandle::try_body_a_id(self)
    }

    pub fn body_b_id(&self) -> BodyId {
        JointRuntimeHandle::body_b_id(self)
    }

    pub fn try_body_b_id(&self) -> ApiResult<BodyId> {
        JointRuntimeHandle::try_body_b_id(self)
    }

    pub fn collide_connected(&self) -> bool {
        JointRuntimeHandle::collide_connected(self)
    }

    pub fn try_collide_connected(&self) -> ApiResult<bool> {
        JointRuntimeHandle::try_collide_connected(self)
    }

    pub fn set_collide_connected(&mut self, flag: bool) {
        JointRuntimeHandle::set_collide_connected(self, flag)
    }

    pub fn try_set_collide_connected(&mut self, flag: bool) -> ApiResult<()> {
        JointRuntimeHandle::try_set_collide_connected(self, flag)
    }

    pub fn constraint_tuning(&self) -> ConstraintTuning {
        JointRuntimeHandle::constraint_tuning(self)
    }

    pub fn try_constraint_tuning(&self) -> ApiResult<ConstraintTuning> {
        JointRuntimeHandle::try_constraint_tuning(self)
    }

    pub fn set_constraint_tuning(&mut self, tuning: ConstraintTuning) {
        JointRuntimeHandle::set_constraint_tuning(self, tuning)
    }

    pub fn try_set_constraint_tuning(&mut self, tuning: ConstraintTuning) -> ApiResult<()> {
        JointRuntimeHandle::try_set_constraint_tuning(self, tuning)
    }

    pub fn local_frame_a(&self) -> crate::Transform {
        JointRuntimeHandle::local_frame_a(self)
    }

    pub fn try_local_frame_a(&self) -> ApiResult<crate::Transform> {
        JointRuntimeHandle::try_local_frame_a(self)
    }

    pub fn local_frame_b(&self) -> crate::Transform {
        JointRuntimeHandle::local_frame_b(self)
    }

    pub fn try_local_frame_b(&self) -> ApiResult<crate::Transform> {
        JointRuntimeHandle::try_local_frame_b(self)
    }

    pub fn wake_bodies(&mut self) {
        JointRuntimeHandle::wake_bodies(self)
    }

    pub fn try_wake_bodies(&mut self) -> ApiResult<()> {
        JointRuntimeHandle::try_wake_bodies(self)
    }

    pub fn linear_separation(&self) -> f32 {
        JointRuntimeHandle::linear_separation(self)
    }

    pub fn try_linear_separation(&self) -> ApiResult<f32> {
        JointRuntimeHandle::try_linear_separation(self)
    }

    pub fn angular_separation(&self) -> f32 {
        JointRuntimeHandle::angular_separation(self)
    }

    pub fn try_angular_separation(&self) -> ApiResult<f32> {
        JointRuntimeHandle::try_angular_separation(self)
    }

    pub fn constraint_force(&self) -> Vec2 {
        JointRuntimeHandle::constraint_force(self)
    }

    pub fn try_constraint_force(&self) -> ApiResult<Vec2> {
        JointRuntimeHandle::try_constraint_force(self)
    }

    pub fn constraint_torque(&self) -> f32 {
        JointRuntimeHandle::constraint_torque(self)
    }

    pub fn try_constraint_torque(&self) -> ApiResult<f32> {
        JointRuntimeHandle::try_constraint_torque(self)
    }

    pub fn force_threshold(&self) -> f32 {
        JointRuntimeHandle::force_threshold(self)
    }

    pub fn try_force_threshold(&self) -> ApiResult<f32> {
        JointRuntimeHandle::try_force_threshold(self)
    }

    pub fn set_force_threshold(&mut self, threshold: f32) {
        JointRuntimeHandle::set_force_threshold(self, threshold)
    }

    pub fn try_set_force_threshold(&mut self, threshold: f32) -> ApiResult<()> {
        JointRuntimeHandle::try_set_force_threshold(self, threshold)
    }

    pub fn torque_threshold(&self) -> f32 {
        JointRuntimeHandle::torque_threshold(self)
    }

    pub fn try_torque_threshold(&self) -> ApiResult<f32> {
        JointRuntimeHandle::try_torque_threshold(self)
    }

    pub fn set_torque_threshold(&mut self, threshold: f32) {
        JointRuntimeHandle::set_torque_threshold(self, threshold)
    }

    pub fn try_set_torque_threshold(&mut self, threshold: f32) -> ApiResult<()> {
        JointRuntimeHandle::try_set_torque_threshold(self, threshold)
    }

    /// Set an opaque user data pointer on this joint.
    ///
    /// # Safety
    /// The caller must ensure that `p` is valid for as long as Box2D may read it.
    ///
    /// If typed user data was previously set via `set_user_data`, it will be cleared and dropped.
    pub unsafe fn set_user_data_ptr_raw(&mut self, p: *mut c_void) {
        unsafe { JointRuntimeHandle::set_user_data_ptr_raw(self, p) }
    }

    /// Set an opaque user data pointer on this joint.
    ///
    /// # Safety
    /// Same safety contract as `set_user_data_ptr_raw`.
    ///
    /// If typed user data was previously set via `set_user_data`, it will be cleared and dropped.
    pub unsafe fn try_set_user_data_ptr_raw(&mut self, p: *mut c_void) -> ApiResult<()> {
        unsafe { JointRuntimeHandle::try_set_user_data_ptr_raw(self, p) }
    }

    pub fn user_data_ptr_raw(&self) -> *mut c_void {
        JointRuntimeHandle::user_data_ptr_raw(self)
    }

    pub fn try_user_data_ptr_raw(&self) -> ApiResult<*mut c_void> {
        JointRuntimeHandle::try_user_data_ptr_raw(self)
    }

    /// Set typed user data on this joint.
    ///
    /// This stores a `Box<T>` internally and sets Box2D's user data pointer to it. The allocation
    /// is automatically freed when cleared or when the joint is destroyed.
    pub fn set_user_data<T: 'static>(&mut self, value: T) {
        JointRuntimeHandle::set_user_data(self, value);
    }

    pub fn try_set_user_data<T: 'static>(&mut self, value: T) -> ApiResult<()> {
        JointRuntimeHandle::try_set_user_data(self, value)
    }

    /// Clear typed user data on this joint. Returns whether any typed data was present.
    pub fn clear_user_data(&mut self) -> bool {
        JointRuntimeHandle::clear_user_data(self)
    }

    pub fn try_clear_user_data(&mut self) -> ApiResult<bool> {
        JointRuntimeHandle::try_clear_user_data(self)
    }

    pub fn with_user_data<T: 'static, R>(&self, f: impl FnOnce(&T) -> R) -> Option<R> {
        JointRuntimeHandle::with_user_data(self, f)
    }

    pub fn try_with_user_data<T: 'static, R>(
        &self,
        f: impl FnOnce(&T) -> R,
    ) -> ApiResult<Option<R>> {
        JointRuntimeHandle::try_with_user_data(self, f)
    }

    pub fn with_user_data_mut<T: 'static, R>(&mut self, f: impl FnOnce(&mut T) -> R) -> Option<R> {
        JointRuntimeHandle::with_user_data_mut(self, f)
    }

    pub fn try_with_user_data_mut<T: 'static, R>(
        &mut self,
        f: impl FnOnce(&mut T) -> R,
    ) -> ApiResult<Option<R>> {
        JointRuntimeHandle::try_with_user_data_mut(self, f)
    }

    pub fn take_user_data<T: 'static>(&mut self) -> Option<T> {
        JointRuntimeHandle::take_user_data(self)
    }

    pub fn try_take_user_data<T: 'static>(&mut self) -> ApiResult<Option<T>> {
        JointRuntimeHandle::try_take_user_data(self)
    }

    pub fn wake_bodies_on_drop(mut self, flag: bool) -> Self {
        self.wake_bodies_on_drop = flag;
        self
    }

    pub fn into_id(mut self) -> JointId {
        self.destroy_on_drop = false;
        self.id
    }

    pub fn destroy(mut self, wake_bodies: bool) {
        if self.destroy_on_drop && unsafe { ffi::b2Joint_IsValid(raw_joint_id(self.id)) } {
            if crate::core::callback_state::in_callback() || self.core.events_buffers_are_borrowed()
            {
                self.core
                    .defer_destroy(crate::core::world_core::DeferredDestroy::Joint {
                        id: self.id,
                        wake_bodies,
                    });
            } else {
                unsafe { ffi::b2DestroyJoint(raw_joint_id(self.id), wake_bodies) };
                let _ = self.core.clear_joint_user_data(self.id);
            }
        }
        self.destroy_on_drop = false;
    }
}

impl Drop for OwnedJoint {
    fn drop(&mut self) {
        let _ = self.core.id;
        let prev = self
            .core
            .owned_joints
            .fetch_sub(1, std::sync::atomic::Ordering::Relaxed);
        debug_assert!(prev > 0, "owned joint counter underflow");
        if self.destroy_on_drop && unsafe { ffi::b2Joint_IsValid(raw_joint_id(self.id)) } {
            if crate::core::callback_state::in_callback() || self.core.events_buffers_are_borrowed()
            {
                self.core
                    .defer_destroy(crate::core::world_core::DeferredDestroy::Joint {
                        id: self.id,
                        wake_bodies: self.wake_bodies_on_drop,
                    });
            } else {
                unsafe { ffi::b2DestroyJoint(raw_joint_id(self.id), self.wake_bodies_on_drop) };
                let _ = self.core.clear_joint_user_data(self.id);
            }
        }
    }
}