use super::*;
impl World {
pub fn create_body(&mut self, def: BodyDef) -> Result<BodyId> {
callback_state::check_not_in_callback()?;
let prepared = def.prepare()?;
let pending = self.state.ledger.reserve_body()?;
let _guard = box3d_lock::lock();
self.check_world_valid_locked()?;
let raw_def = prepared.lower_locked();
let raw = unsafe { ffi::b3CreateBody(self.raw, &raw_def) };
if unsafe { ffi::b3Body_IsValid(raw) } {
Ok(self.state.ledger.publish_body(raw, pending))
} else {
Err(Error::NativeFailure)
}
}
pub fn create_sphere_shape(
&mut self,
body_id: BodyId,
def: &ShapeDef,
sphere: &Sphere,
) -> Result<ShapeId> {
callback_state::check_not_in_callback()?;
let mut prepared = def.prepare(ShapeMaterialUsage::BaseOnly)?;
sphere.validate()?;
let pending = self.state.ledger.reserve_shape(body_id, None)?;
let _guard = self.lock_body_checked(body_id)?;
let raw_def = prepared.lower_locked();
let raw = unsafe { ffi::b3CreateSphereShape(body_id.into_raw(), &raw_def, sphere.raw()) };
if unsafe { ffi::b3Shape_IsValid(raw) } {
Ok(self.state.ledger.publish_shape(raw, pending))
} else {
Err(Error::NativeFailure)
}
}
pub fn create_hull_shape(
&mut self,
body_id: BodyId,
def: &ShapeDef,
hull: &BoxHull,
) -> Result<ShapeId> {
callback_state::check_not_in_callback()?;
let mut prepared = def.prepare(ShapeMaterialUsage::BaseOnly)?;
let pending = self.state.ledger.reserve_shape(body_id, None)?;
let _guard = self.lock_body_checked(body_id)?;
let raw_def = prepared.lower_locked();
let raw = unsafe { ffi::b3CreateHullShape(body_id.into_raw(), &raw_def, hull.hull_data()) };
if unsafe { ffi::b3Shape_IsValid(raw) } {
Ok(self.state.ledger.publish_shape(raw, pending))
} else {
Err(Error::NativeFailure)
}
}
pub fn create_capsule_shape(
&mut self,
body_id: BodyId,
def: &ShapeDef,
capsule: &Capsule,
) -> Result<ShapeId> {
callback_state::check_not_in_callback()?;
let mut prepared = def.prepare(ShapeMaterialUsage::BaseOnly)?;
capsule.validate()?;
let pending = self.state.ledger.reserve_shape(body_id, None)?;
let _guard = self.lock_body_checked(body_id)?;
let raw_def = prepared.lower_locked();
let raw = unsafe { ffi::b3CreateCapsuleShape(body_id.into_raw(), &raw_def, capsule.raw()) };
if unsafe { ffi::b3Shape_IsValid(raw) } {
Ok(self.state.ledger.publish_shape(raw, pending))
} else {
Err(Error::NativeFailure)
}
}
pub fn create_created_hull_shape(
&mut self,
body_id: BodyId,
def: &ShapeDef,
hull: &Hull,
) -> Result<ShapeId> {
callback_state::check_not_in_callback()?;
let mut prepared = def.prepare(ShapeMaterialUsage::BaseOnly)?;
let pending = self.state.ledger.reserve_shape(body_id, None)?;
let _guard = self.lock_body_checked(body_id)?;
let raw_def = prepared.lower_locked();
let raw = unsafe { ffi::b3CreateHullShape(body_id.into_raw(), &raw_def, hull.as_ptr()) };
if unsafe { ffi::b3Shape_IsValid(raw) } {
Ok(self.state.ledger.publish_shape(raw, pending))
} else {
Err(Error::NativeFailure)
}
}
pub fn create_transformed_hull_shape(
&mut self,
body_id: BodyId,
def: &ShapeDef,
hull: &Hull,
transform: impl Into<crate::types::Transform>,
scale: impl Into<Vec3>,
) -> Result<ShapeId> {
callback_state::check_not_in_callback()?;
let mut prepared = def.prepare(ShapeMaterialUsage::BaseOnly)?;
let transform = transform.into();
transform.validate()?;
let scale = scale.into().validate()?;
let pending = self.state.ledger.reserve_shape(body_id, None)?;
let _guard = self.lock_body_checked(body_id)?;
let raw_def = prepared.lower_locked();
let raw = unsafe {
ffi::b3CreateTransformedHullShape(
body_id.into_raw(),
&raw_def,
hull.as_ptr(),
transform.into_raw(),
scale.into_raw(),
)
};
if unsafe { ffi::b3Shape_IsValid(raw) } {
Ok(self.state.ledger.publish_shape(raw, pending))
} else {
Err(Error::NativeFailure)
}
}
pub fn create_mesh_shape(
&mut self,
body_id: BodyId,
def: &ShapeDef,
mesh: MeshData,
scale: impl Into<Vec3>,
) -> Result<ShapeId> {
callback_state::check_not_in_callback()?;
let mut prepared = def.prepare(ShapeMaterialUsage::PerTriangle)?;
let scale = validate_mesh_scale(scale.into())?;
if self.body_type(body_id)? != BodyType::Static {
return Err(validation::invalid(
"mesh_shape.body_type",
crate::error::InvalidValueReason::InvalidCombination,
));
}
let mesh_ptr = mesh.as_ptr();
let pending = self
.state
.ledger
.reserve_shape(body_id, Some(ShapeResource::Mesh { _data: mesh }))?;
let _guard = self.lock_body_checked(body_id)?;
let raw_def = prepared.lower_locked();
let raw = unsafe {
ffi::b3CreateMeshShape(body_id.into_raw(), &raw_def, mesh_ptr, scale.into_raw())
};
if !unsafe { ffi::b3Shape_IsValid(raw) } {
return Err(Error::NativeFailure);
}
Ok(self.state.ledger.publish_shape(raw, pending))
}
pub fn create_height_field_shape(
&mut self,
body_id: BodyId,
def: &ShapeDef,
height_field: HeightField,
) -> Result<ShapeId> {
callback_state::check_not_in_callback()?;
let mut prepared = def.prepare(ShapeMaterialUsage::PerTriangle)?;
if self.body_type(body_id)? != BodyType::Static {
return Err(validation::invalid(
"height_field_shape.body_type",
crate::error::InvalidValueReason::InvalidCombination,
));
}
let height_field_ptr = height_field.as_ptr();
let pending = self.state.ledger.reserve_shape(
body_id,
Some(ShapeResource::HeightField {
_data: height_field,
}),
)?;
let _guard = self.lock_body_checked(body_id)?;
let raw_def = prepared.lower_locked();
let raw = unsafe {
ffi::b3CreateHeightFieldShape(body_id.into_raw(), &raw_def, height_field_ptr)
};
if !unsafe { ffi::b3Shape_IsValid(raw) } {
return Err(Error::NativeFailure);
}
Ok(self.state.ledger.publish_shape(raw, pending))
}
pub fn create_compound_shape(
&mut self,
body_id: BodyId,
def: &ShapeDef,
compound: Compound,
) -> Result<ShapeId> {
callback_state::check_not_in_callback()?;
let mut prepared = def.prepare(ShapeMaterialUsage::BaseOnly)?;
if def.sensor {
return Err(validation::invalid(
"compound_shape.sensor",
crate::error::InvalidValueReason::InvalidCombination,
));
}
if self.body_type(body_id)? != BodyType::Static {
return Err(validation::invalid(
"compound_shape.body_type",
crate::error::InvalidValueReason::InvalidCombination,
));
}
let compound_ptr = compound.as_ptr();
let pending = self
.state
.ledger
.reserve_shape(body_id, Some(ShapeResource::Compound { _data: compound }))?;
let _guard = self.lock_body_checked(body_id)?;
let mut raw_def = prepared.lower_locked();
let raw = unsafe {
ffi::b3CreateBakedCompoundShape(body_id.into_raw(), &mut raw_def, compound_ptr)
};
if !unsafe { ffi::b3Shape_IsValid(raw) } {
return Err(Error::NativeFailure);
}
Ok(self.state.ledger.publish_shape(raw, pending))
}
}