use crate::Transform;
use crate::types::BodyId;
use crate::world::{World, WorldHandle};
use boxdd_sys::ffi;
#[derive(Clone, Debug)]
pub struct BodyMoveEvent {
pub body_id: BodyId,
pub transform: Transform,
pub fell_asleep: bool,
}
#[derive(Copy, Clone)]
pub struct BodyMove<'a>(&'a ffi::b2BodyMoveEvent);
impl<'a> BodyMove<'a> {
pub fn body_id(&self) -> BodyId {
BodyId::from_raw(self.0.bodyId)
}
pub fn transform(&self) -> Transform {
Transform::from_raw(self.0.transform)
}
pub fn fell_asleep(&self) -> bool {
self.0.fellAsleep
}
}
pub struct BodyMoveIter<'a>(core::slice::Iter<'a, ffi::b2BodyMoveEvent>);
impl<'a> Iterator for BodyMoveIter<'a> {
type Item = BodyMove<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(BodyMove)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
fn body_events_into_impl(world: ffi::b2WorldId, out: &mut Vec<BodyMoveEvent>) {
let raw = unsafe { ffi::b2World_GetBodyEvents(world) };
let slice = if raw.moveCount > 0 && !raw.moveEvents.is_null() {
unsafe { core::slice::from_raw_parts(raw.moveEvents, raw.moveCount as usize) }
} else {
&[][..]
};
super::map_snapshot_into(out, slice, |e| BodyMoveEvent {
body_id: BodyId::from_raw(e.bodyId),
transform: Transform::from_raw(e.transform),
fell_asleep: e.fellAsleep,
});
}
fn body_events_snapshot_impl(world: ffi::b2WorldId) -> Vec<BodyMoveEvent> {
let mut out = Vec::new();
body_events_into_impl(world, &mut out);
out
}
fn body_events_checked_impl(world: ffi::b2WorldId) -> Vec<BodyMoveEvent> {
crate::core::callback_state::assert_not_in_callback();
body_events_snapshot_impl(world)
}
fn body_events_into_checked_impl(world: ffi::b2WorldId, out: &mut Vec<BodyMoveEvent>) {
crate::core::callback_state::assert_not_in_callback();
body_events_into_impl(world, out);
}
fn try_body_events_impl(world: ffi::b2WorldId) -> crate::error::ApiResult<Vec<BodyMoveEvent>> {
crate::core::callback_state::check_not_in_callback()?;
Ok(body_events_snapshot_impl(world))
}
fn try_body_events_into_impl(
world: ffi::b2WorldId,
out: &mut Vec<BodyMoveEvent>,
) -> crate::error::ApiResult<()> {
crate::core::callback_state::check_not_in_callback()?;
body_events_into_impl(world, out);
Ok(())
}
impl World {
pub fn body_events(&self) -> Vec<BodyMoveEvent> {
body_events_checked_impl(self.raw())
}
pub fn body_events_into(&self, out: &mut Vec<BodyMoveEvent>) {
body_events_into_checked_impl(self.raw(), out);
}
pub fn try_body_events(&self) -> crate::error::ApiResult<Vec<BodyMoveEvent>> {
try_body_events_impl(self.raw())
}
pub fn try_body_events_into(
&self,
out: &mut Vec<BodyMoveEvent>,
) -> crate::error::ApiResult<()> {
try_body_events_into_impl(self.raw(), out)
}
}
impl WorldHandle {
pub fn body_events(&self) -> Vec<BodyMoveEvent> {
body_events_checked_impl(self.raw())
}
pub fn body_events_into(&self, out: &mut Vec<BodyMoveEvent>) {
body_events_into_checked_impl(self.raw(), out);
}
pub fn try_body_events(&self) -> crate::error::ApiResult<Vec<BodyMoveEvent>> {
try_body_events_impl(self.raw())
}
pub fn try_body_events_into(
&self,
out: &mut Vec<BodyMoveEvent>,
) -> crate::error::ApiResult<()> {
try_body_events_into_impl(self.raw(), out)
}
}
impl World {
pub unsafe fn with_body_events_raw<T>(
&self,
f: impl FnOnce(&[ffi::b2BodyMoveEvent]) -> T,
) -> T {
self.with_borrowed_event_buffers(|| {
let raw = unsafe { ffi::b2World_GetBodyEvents(self.raw()) };
let slice = if raw.moveCount > 0 && !raw.moveEvents.is_null() {
unsafe { core::slice::from_raw_parts(raw.moveEvents, raw.moveCount as usize) }
} else {
&[][..]
};
f(slice)
})
}
pub unsafe fn try_with_body_events_raw<T>(
&self,
f: impl FnOnce(&[ffi::b2BodyMoveEvent]) -> T,
) -> crate::error::ApiResult<T> {
self.try_with_borrowed_event_buffers(|| {
let raw = unsafe { ffi::b2World_GetBodyEvents(self.raw()) };
let slice = if raw.moveCount > 0 && !raw.moveEvents.is_null() {
unsafe { core::slice::from_raw_parts(raw.moveEvents, raw.moveCount as usize) }
} else {
&[][..]
};
f(slice)
})
}
pub fn with_body_events_view<T>(&self, f: impl FnOnce(BodyMoveIter<'_>) -> T) -> T {
self.with_borrowed_event_buffers(|| {
let raw = unsafe { ffi::b2World_GetBodyEvents(self.raw()) };
let slice = if raw.moveCount > 0 && !raw.moveEvents.is_null() {
unsafe { core::slice::from_raw_parts(raw.moveEvents, raw.moveCount as usize) }
} else {
&[][..]
};
f(BodyMoveIter(slice.iter()))
})
}
pub fn try_with_body_events_view<T>(
&self,
f: impl FnOnce(BodyMoveIter<'_>) -> T,
) -> crate::error::ApiResult<T> {
self.try_with_borrowed_event_buffers(|| {
let raw = unsafe { ffi::b2World_GetBodyEvents(self.raw()) };
let slice = if raw.moveCount > 0 && !raw.moveEvents.is_null() {
unsafe { core::slice::from_raw_parts(raw.moveEvents, raw.moveCount as usize) }
} else {
&[][..]
};
f(BodyMoveIter(slice.iter()))
})
}
}