avian3d/collider_tree/
proxy_key.rs1use core::hint::unreachable_unchecked;
2
3use bevy::{
4 ecs::{
5 component::Component,
6 entity::{ComponentCloneCtx, SourceComponent},
7 },
8 reflect::Reflect,
9};
10
11use crate::prelude::RigidBody;
12
13#[derive(Component, Clone, Copy, Debug, PartialEq, Eq, Hash, Reflect)]
21#[component(clone_behavior = Custom(clone_placeholder_proxy_key))]
22pub struct ColliderTreeProxyKey(u32);
23
24fn clone_placeholder_proxy_key(_source: &SourceComponent, ctx: &mut ComponentCloneCtx) {
26 ctx.write_target_component(ColliderTreeProxyKey::PLACEHOLDER);
27}
28
29impl ColliderTreeProxyKey {
30 pub const PLACEHOLDER: Self = ColliderTreeProxyKey(u32::MAX);
32
33 #[inline]
35 pub const fn new(id: ProxyId, tree_type: ColliderTreeType) -> Self {
36 ColliderTreeProxyKey((id.id() << 2) | (tree_type as u32))
38 }
39
40 #[inline]
42 pub const fn id(&self) -> ProxyId {
43 ProxyId::new(self.0 >> 2)
44 }
45
46 #[inline]
48 pub const fn tree_type(&self) -> ColliderTreeType {
49 match self.0 & 0b11 {
50 0 => ColliderTreeType::Dynamic,
51 1 => ColliderTreeType::Kinematic,
52 2 => ColliderTreeType::Static,
53 3 => ColliderTreeType::Standalone,
54 _ => unsafe { unreachable_unchecked() },
56 }
57 }
58
59 #[inline]
63 pub const fn body(&self) -> Option<RigidBody> {
64 match self.0 & 0b11 {
65 0 => Some(RigidBody::Dynamic),
66 1 => Some(RigidBody::Kinematic),
67 2 => Some(RigidBody::Static),
68 3 => None,
69 _ => unsafe { unreachable_unchecked() },
71 }
72 }
73
74 #[inline]
76 pub const fn is_dynamic(&self) -> bool {
77 if let Some(body) = self.body() {
78 body as u32 == RigidBody::Dynamic as u32
79 } else {
80 false
81 }
82 }
83
84 #[inline]
86 pub const fn is_kinematic(&self) -> bool {
87 if let Some(body) = self.body() {
88 body as u32 == RigidBody::Kinematic as u32
89 } else {
90 false
91 }
92 }
93
94 #[inline]
96 pub const fn is_static(&self) -> bool {
97 if let Some(body) = self.body() {
98 body as u32 == RigidBody::Static as u32
99 } else {
100 false
101 }
102 }
103
104 #[inline]
106 pub const fn is_standalone(&self) -> bool {
107 self.body().is_none()
108 }
109}
110
111#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Reflect)]
115pub struct ProxyId(u32);
116
117impl ProxyId {
118 pub const PLACEHOLDER: Self = ProxyId(u32::MAX >> 2);
120
121 #[inline]
129 pub const fn new(id: u32) -> Self {
130 debug_assert!(id < (1 << 30), "ProxyId can only use lower 30 bits");
131 ProxyId(id)
132 }
133
134 #[inline]
136 pub const fn id(&self) -> u32 {
137 self.0
138 }
139
140 #[inline]
142 pub const fn index(&self) -> usize {
143 self.0 as usize
144 }
145}
146
147impl From<u32> for ProxyId {
148 #[inline]
149 fn from(id: u32) -> Self {
150 ProxyId::new(id)
151 }
152}
153
154impl From<ProxyId> for u32 {
155 #[inline]
156 fn from(proxy_id: ProxyId) -> Self {
157 proxy_id.id()
158 }
159}
160
161impl PartialOrd for ProxyId {
162 #[inline]
163 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
164 Some(self.cmp(other))
165 }
166}
167
168impl Ord for ProxyId {
169 #[inline]
170 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
171 self.0.cmp(&other.0)
172 }
173}
174
175#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Reflect)]
177pub enum ColliderTreeType {
178 Dynamic = 0,
180 Kinematic = 1,
182 Static = 2,
184 Standalone = 3,
186}
187
188impl ColliderTreeType {
189 pub const ALL: [ColliderTreeType; 4] = [
191 ColliderTreeType::Dynamic,
192 ColliderTreeType::Kinematic,
193 ColliderTreeType::Static,
194 ColliderTreeType::Standalone,
195 ];
196
197 #[inline]
201 pub const fn from_body(body: Option<RigidBody>) -> Self {
202 match body {
203 Some(RigidBody::Dynamic) => ColliderTreeType::Dynamic,
204 Some(RigidBody::Kinematic) => ColliderTreeType::Kinematic,
205 Some(RigidBody::Static) => ColliderTreeType::Static,
206 None => ColliderTreeType::Standalone,
207 }
208 }
209
210 #[inline]
212 pub const fn is_dynamic(&self) -> bool {
213 matches!(self, ColliderTreeType::Dynamic)
214 }
215
216 #[inline]
218 pub const fn is_kinematic(&self) -> bool {
219 matches!(self, ColliderTreeType::Kinematic)
220 }
221
222 #[inline]
224 pub const fn is_static(&self) -> bool {
225 matches!(self, ColliderTreeType::Static)
226 }
227
228 #[inline]
230 pub const fn is_standalone(&self) -> bool {
231 matches!(self, ColliderTreeType::Standalone)
232 }
233}
234
235impl From<Option<RigidBody>> for ColliderTreeType {
236 #[inline]
237 fn from(body: Option<RigidBody>) -> Self {
238 match body {
239 Some(RigidBody::Dynamic) => ColliderTreeType::Dynamic,
240 Some(RigidBody::Kinematic) => ColliderTreeType::Kinematic,
241 Some(RigidBody::Static) => ColliderTreeType::Static,
242 None => ColliderTreeType::Standalone,
243 }
244 }
245}
246
247impl From<ColliderTreeType> for Option<RigidBody> {
248 #[inline]
249 fn from(tree_type: ColliderTreeType) -> Self {
250 match tree_type {
251 ColliderTreeType::Dynamic => Some(RigidBody::Dynamic),
252 ColliderTreeType::Kinematic => Some(RigidBody::Kinematic),
253 ColliderTreeType::Static => Some(RigidBody::Static),
254 ColliderTreeType::Standalone => None,
255 }
256 }
257}
258
259impl From<RigidBody> for ColliderTreeType {
260 #[inline]
261 fn from(body: RigidBody) -> Self {
262 match body {
263 RigidBody::Dynamic => ColliderTreeType::Dynamic,
264 RigidBody::Kinematic => ColliderTreeType::Kinematic,
265 RigidBody::Static => ColliderTreeType::Static,
266 }
267 }
268}