1use alloc::{vec, vec::Vec};
10use core::{marker::PhantomData, mem::ManuallyDrop};
11
12use crate::{
13 action::LocalActionEncoder,
14 component::{Component, ComponentBorrow},
15 entity::EntityId,
16};
17
18pub use edict_proc::Relation;
19
20pub use self::{
21 child_of::ChildOf,
22 query::{
23 FetchFilterRelatedBy, FetchRelated, FetchRelatesExclusiveRead, FetchRelatesExclusiveWrite,
24 FetchRelatesRead, FetchRelatesToRead, FetchRelatesToWrite, FetchRelatesWrite,
25 FilterFetchRelatesTo, FilterRelated, FilterRelatedBy, FilterRelates, FilterRelatesTo,
26 Related, Relates, RelatesExclusive, RelatesReadIter, RelatesTo, RelatesWriteIter,
27 },
28};
29
30mod child_of;
31mod query;
32
33pub trait Relation: Copy + 'static {
49 const EXCLUSIVE: bool = false;
57
58 const SYMMETRIC: bool = false;
61
62 const OWNED: bool = false;
65
66 #[inline(always)]
70 #[must_use]
71 fn name() -> &'static str {
72 core::any::type_name::<Self>()
73 }
74
75 #[inline(always)]
78 fn on_drop(&mut self, origin: EntityId, target: EntityId, encoder: LocalActionEncoder) {
79 let _ = origin;
80 let _ = target;
81 let _ = encoder;
82 }
83
84 #[inline(always)]
94 fn on_replace(
95 &mut self,
96 value: &Self,
97 origin: EntityId,
98 target: EntityId,
99 new_target: EntityId,
100 encoder: LocalActionEncoder,
101 ) -> bool {
102 let _ = value;
103 let _ = origin;
104 let _ = target;
105 let _ = new_target;
106 let _ = encoder;
107
108 true
109 }
110
111 #[inline(always)]
115 fn on_target_drop(origin: EntityId, target: EntityId, encoder: LocalActionEncoder) {
116 let _ = origin;
117 let _ = target;
118 let _ = encoder;
119 }
120}
121
122pub trait ExclusiveRelation: Relation {
130 #[doc(hidden)]
131 const ASSERT_EXCLUSIVE: () = assert!(Self::EXCLUSIVE);
132}
133
134pub(crate) struct RelationTarget<R> {
135 pub target: EntityId,
136 pub relation: R,
137}
138
139pub(crate) union OriginComponent<R: Relation> {
140 exclusive: ManuallyDrop<RelationTarget<R>>,
141 non_exclusive: ManuallyDrop<Vec<RelationTarget<R>>>,
142}
143
144impl<R> Drop for OriginComponent<R>
145where
146 R: Relation,
147{
148 fn drop(&mut self) {
149 match R::EXCLUSIVE {
150 false => unsafe { ManuallyDrop::drop(&mut self.non_exclusive) },
151 true => unsafe { ManuallyDrop::drop(&mut self.exclusive) },
152 }
153 }
154}
155
156impl<R> OriginComponent<R>
157where
158 R: Relation,
159{
160 #[must_use]
162 pub fn new_relation(target: EntityId, relation: R) -> Self {
163 match R::EXCLUSIVE {
164 false => OriginComponent {
165 non_exclusive: ManuallyDrop::new(vec![RelationTarget { target, relation }]),
166 },
167 true => OriginComponent {
168 exclusive: ManuallyDrop::new(RelationTarget { target, relation }),
169 },
170 }
171 }
172
173 pub fn add_relation(
175 &mut self,
176 origin: EntityId,
177 target: EntityId,
178 relation: R,
179 encoder: LocalActionEncoder,
180 ) {
181 match R::EXCLUSIVE {
182 false => {
183 let relations = unsafe { &mut *self.non_exclusive };
184 for r in relations.iter_mut() {
185 if r.target == target {
186 Self::set_one(&mut r.relation, relation, origin, target, target, encoder);
187 return;
188 }
189 }
190 relations.push(RelationTarget { target, relation });
191 }
192 true => {
193 let r = unsafe { &mut *self.exclusive };
194 Self::set_one(&mut r.relation, relation, origin, r.target, target, encoder);
195 r.target = target;
196 }
197 }
198 }
199
200 pub fn remove_relation(
203 &mut self,
204 origin: EntityId,
205 target: EntityId,
206 mut encoder: LocalActionEncoder,
207 ) -> Option<R> {
208 match R::EXCLUSIVE {
209 false => {
210 let relations = unsafe { &mut *self.non_exclusive };
211 for idx in 0..relations.len() {
212 if relations[idx].target == target {
213 let r = relations.swap_remove(idx);
214 if relations.is_empty() {
215 encoder.drop::<Self>(origin);
216 }
217 return Some(r.relation);
218 }
219 }
220 None
221 }
222 true => {
223 let r = unsafe { &mut *self.exclusive };
224 if r.target == target {
225 encoder.drop::<Self>(origin);
226 return Some(r.relation);
227 }
228 None
229 }
230 }
231 }
232
233 fn on_target_drop(origin: EntityId, target: EntityId, mut encoder: LocalActionEncoder) {
235 if R::EXCLUSIVE {
236 if R::OWNED {
237 encoder.despawn(origin);
238 } else {
239 encoder.drop::<Self>(origin);
240 }
241 } else {
242 encoder.closure(move |world| {
243 let Ok(mut origin) = world.entity(origin) else {
244 return;
245 };
246
247 let Some(comp) = origin.get_mut::<&mut Self>() else {
248 return;
249 };
250
251 let origins = unsafe { &mut *comp.non_exclusive };
252
253 for idx in 0..origins.len() {
254 if origins[idx].target == target {
255 origins.swap_remove(idx);
256 break;
257 }
258 }
259
260 if origins.is_empty() {
261 if R::OWNED {
262 origin.despawn();
263 } else {
264 origin.drop::<Self>();
265 }
266 }
267 });
268 }
269 }
270
271 #[must_use]
272 pub fn relations(&self) -> &[RelationTarget<R>] {
273 match R::EXCLUSIVE {
274 false => unsafe { &*self.non_exclusive },
275 true => core::slice::from_ref(unsafe { &*self.exclusive }),
276 }
277 }
278
279 #[must_use]
280 pub fn relations_mut(&mut self) -> &mut [RelationTarget<R>] {
281 match R::EXCLUSIVE {
282 false => unsafe { &mut *self.non_exclusive },
283 true => core::slice::from_mut(unsafe { &mut *self.exclusive }),
284 }
285 }
286
287 fn drop_one(
288 relation: &mut R,
289 origin: EntityId,
290 target: EntityId,
291 mut encoder: LocalActionEncoder,
292 ) {
293 relation.on_drop(origin, target, encoder.reborrow());
294 if R::SYMMETRIC {
295 if target != origin {
296 Self::on_target_drop(target, origin, encoder);
297 }
298 } else {
299 TargetComponent::<R>::on_origin_drop(origin, target, encoder)
300 }
301 }
302
303 fn set_one(
304 relation: &mut R,
305 new_relation: R,
306 origin: EntityId,
307 target: EntityId,
308 new_target: EntityId,
309 mut encoder: LocalActionEncoder,
310 ) {
311 let on_replace = relation.on_replace(
312 &new_relation,
313 origin,
314 target,
315 new_target,
316 encoder.reborrow(),
317 );
318 if on_replace {
319 relation.on_drop(origin, target, encoder.reborrow());
320 }
321 if new_target != target {
322 if R::SYMMETRIC {
323 if target != origin {
324 Self::on_target_drop(target, origin, encoder);
325 }
326 } else {
327 TargetComponent::<R>::on_origin_drop(origin, target, encoder)
328 }
329 }
330 *relation = new_relation;
331 }
332}
333
334impl<R> Component for OriginComponent<R>
335where
336 R: Relation,
337{
338 #[inline(always)]
339 fn on_drop(&mut self, origin: EntityId, mut encoder: LocalActionEncoder) {
340 for r in self.relations_mut() {
341 Self::drop_one(&mut r.relation, origin, r.target, encoder.reborrow());
342 }
343 }
344
345 #[inline(always)]
346 fn on_replace(
347 &mut self,
348 _value: &Self,
349 _origin: EntityId,
350 _encoder: LocalActionEncoder,
351 ) -> bool {
352 unimplemented!("This method is not intended to be called");
353 }
354
355 #[inline(always)]
356 #[must_use]
357 fn borrows() -> Vec<ComponentBorrow> {
358 Vec::new()
359 }
360}
361
362pub(crate) struct TargetComponent<R> {
364 origins: Vec<EntityId>,
365 relation: PhantomData<fn() -> R>,
366}
367
368impl<R> TargetComponent<R>
369where
370 R: Relation,
371{
372 #[must_use]
373 pub(crate) fn new(origin: EntityId) -> Self {
374 debug_assert!(!R::SYMMETRIC);
375
376 TargetComponent {
377 origins: vec![origin],
378 relation: PhantomData,
379 }
380 }
381
382 pub(crate) fn add(&mut self, origin: EntityId) {
383 debug_assert!(!self.origins.contains(&origin));
384 self.origins.push(origin);
385 }
386
387 pub fn remove_relation(
390 &mut self,
391 origin: EntityId,
392 target: EntityId,
393 mut encoder: LocalActionEncoder,
394 ) {
395 for idx in 0..self.origins.len() {
396 if self.origins[idx] == origin {
397 self.origins.swap_remove(idx);
398 if self.origins.is_empty() {
399 encoder.drop::<Self>(target);
400 }
401 }
402 }
403 }
404
405 fn on_origin_drop(origin: EntityId, target: EntityId, mut encoder: LocalActionEncoder) {
408 encoder.closure(move |world| {
409 let Ok(mut target) = world.entity(target) else {
410 return;
411 };
412 let Some(comp) = target.get_mut::<&mut Self>() else {
413 return;
414 };
415
416 for idx in 0..comp.origins.len() {
417 if comp.origins[idx] == origin {
418 comp.origins.swap_remove(idx);
419 break;
420 }
421 }
422
423 if comp.origins.is_empty() {
424 target.drop::<Self>();
425 }
426 })
427 }
428}
429
430impl<R> Component for TargetComponent<R>
431where
432 R: Relation,
433{
434 #[inline(always)]
435 fn on_drop(&mut self, target: EntityId, mut encoder: LocalActionEncoder) {
436 for &origin in &self.origins {
437 R::on_target_drop(origin, target, encoder.reborrow());
438 OriginComponent::<R>::on_target_drop(origin, target, encoder.reborrow());
439 }
440 }
441
442 #[inline(always)]
443 fn on_replace(
444 &mut self,
445 _value: &Self,
446 _entity: EntityId,
447 _encoder: LocalActionEncoder,
448 ) -> bool {
449 unimplemented!("This method is not intended to be called");
450 }
451
452 #[inline(always)]
453 #[must_use]
454 fn borrows() -> Vec<ComponentBorrow> {
455 Vec::new()
456 }
457}