use core::hint::unreachable_unchecked;
use bevy::{ecs::component::Component, reflect::Reflect};
use crate::prelude::RigidBody;
#[derive(Component, Clone, Copy, Debug, PartialEq, Eq, Hash, Reflect)]
pub struct ColliderTreeProxyKey(u32);
impl ColliderTreeProxyKey {
pub const PLACEHOLDER: Self = ColliderTreeProxyKey(u32::MAX);
#[inline]
pub const fn new(id: ProxyId, tree_type: ColliderTreeType) -> Self {
ColliderTreeProxyKey((id.id() << 2) | (tree_type as u32))
}
#[inline]
pub const fn id(&self) -> ProxyId {
ProxyId::new(self.0 >> 2)
}
#[inline]
pub const fn tree_type(&self) -> ColliderTreeType {
match self.0 & 0b11 {
0 => ColliderTreeType::Dynamic,
1 => ColliderTreeType::Kinematic,
2 => ColliderTreeType::Static,
3 => ColliderTreeType::Standalone,
_ => unsafe { unreachable_unchecked() },
}
}
#[inline]
pub const fn body(&self) -> Option<RigidBody> {
match self.0 & 0b11 {
0 => Some(RigidBody::Dynamic),
1 => Some(RigidBody::Kinematic),
2 => Some(RigidBody::Static),
3 => None,
_ => unsafe { unreachable_unchecked() },
}
}
#[inline]
pub const fn is_dynamic(&self) -> bool {
if let Some(body) = self.body() {
body as u32 == RigidBody::Dynamic as u32
} else {
false
}
}
#[inline]
pub const fn is_kinematic(&self) -> bool {
if let Some(body) = self.body() {
body as u32 == RigidBody::Kinematic as u32
} else {
false
}
}
#[inline]
pub const fn is_static(&self) -> bool {
if let Some(body) = self.body() {
body as u32 == RigidBody::Static as u32
} else {
false
}
}
#[inline]
pub const fn is_standalone(&self) -> bool {
self.body().is_none()
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Reflect)]
pub struct ProxyId(u32);
impl ProxyId {
pub const PLACEHOLDER: Self = ProxyId(u32::MAX >> 2);
#[inline]
pub const fn new(id: u32) -> Self {
debug_assert!(id < (1 << 30), "ProxyId can only use lower 30 bits");
ProxyId(id)
}
#[inline]
pub const fn id(&self) -> u32 {
self.0
}
#[inline]
pub const fn index(&self) -> usize {
self.0 as usize
}
}
impl From<u32> for ProxyId {
#[inline]
fn from(id: u32) -> Self {
ProxyId::new(id)
}
}
impl From<ProxyId> for u32 {
#[inline]
fn from(proxy_id: ProxyId) -> Self {
proxy_id.id()
}
}
impl PartialOrd for ProxyId {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for ProxyId {
#[inline]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.0.cmp(&other.0)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Reflect)]
pub enum ColliderTreeType {
Dynamic = 0,
Kinematic = 1,
Static = 2,
Standalone = 3,
}
impl ColliderTreeType {
pub const ALL: [ColliderTreeType; 4] = [
ColliderTreeType::Dynamic,
ColliderTreeType::Kinematic,
ColliderTreeType::Static,
ColliderTreeType::Standalone,
];
#[inline]
pub const fn from_body(body: Option<RigidBody>) -> Self {
match body {
Some(RigidBody::Dynamic) => ColliderTreeType::Dynamic,
Some(RigidBody::Kinematic) => ColliderTreeType::Kinematic,
Some(RigidBody::Static) => ColliderTreeType::Static,
None => ColliderTreeType::Standalone,
}
}
#[inline]
pub const fn is_dynamic(&self) -> bool {
matches!(self, ColliderTreeType::Dynamic)
}
#[inline]
pub const fn is_kinematic(&self) -> bool {
matches!(self, ColliderTreeType::Kinematic)
}
#[inline]
pub const fn is_static(&self) -> bool {
matches!(self, ColliderTreeType::Static)
}
#[inline]
pub const fn is_standalone(&self) -> bool {
matches!(self, ColliderTreeType::Standalone)
}
}
impl From<Option<RigidBody>> for ColliderTreeType {
#[inline]
fn from(body: Option<RigidBody>) -> Self {
match body {
Some(RigidBody::Dynamic) => ColliderTreeType::Dynamic,
Some(RigidBody::Kinematic) => ColliderTreeType::Kinematic,
Some(RigidBody::Static) => ColliderTreeType::Static,
None => ColliderTreeType::Standalone,
}
}
}
impl From<ColliderTreeType> for Option<RigidBody> {
#[inline]
fn from(tree_type: ColliderTreeType) -> Self {
match tree_type {
ColliderTreeType::Dynamic => Some(RigidBody::Dynamic),
ColliderTreeType::Kinematic => Some(RigidBody::Kinematic),
ColliderTreeType::Static => Some(RigidBody::Static),
ColliderTreeType::Standalone => None,
}
}
}
impl From<RigidBody> for ColliderTreeType {
#[inline]
fn from(body: RigidBody) -> Self {
match body {
RigidBody::Dynamic => ColliderTreeType::Dynamic,
RigidBody::Kinematic => ColliderTreeType::Kinematic,
RigidBody::Static => ColliderTreeType::Static,
}
}
}