intuicio_framework_ecs/
multiverse.rs

1use crate::{
2    archetype::{
3        ArchetypeColumnInfo, ArchetypeDynamicEntityColumnAccess, ArchetypeEntityColumnAccess,
4    },
5    entity::Entity,
6    query::{
7        DynamicQueryFilter, DynamicQueryItem, DynamicQueryIter, TypedQueryFetch, TypedQueryIter,
8    },
9    world::{World, WorldError},
10    Component,
11};
12use intuicio_data::type_hash::TypeHash;
13use serde::{Deserialize, Serialize};
14use std::{
15    collections::VecDeque,
16    ops::{Deref, DerefMut},
17};
18
19#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
20pub enum Multity {
21    One([Entity; 1]),
22    Two([Entity; 2]),
23    More(Vec<Entity>),
24}
25
26impl Multity {
27    pub fn new(entity: Entity) -> Self {
28        Self::One([entity])
29    }
30
31    pub fn with(mut self, entity: Entity) -> Self {
32        self.push(entity);
33        self
34    }
35
36    #[allow(clippy::len_without_is_empty)]
37    pub fn len(&self) -> usize {
38        match self {
39            Self::One(_) => 1,
40            Self::Two(_) => 2,
41            Self::More(items) => items.len(),
42        }
43    }
44
45    pub fn root(&self) -> Entity {
46        match self {
47            Self::One([entity]) => *entity,
48            Self::Two([entity, _]) => *entity,
49            Self::More(items) => *items.first().unwrap(),
50        }
51    }
52
53    pub fn entity(&self) -> Entity {
54        match self {
55            Self::One([entity]) => *entity,
56            Self::Two([_, entity]) => *entity,
57            Self::More(items) => *items.last().unwrap(),
58        }
59    }
60
61    pub fn parent(&self) -> Option<Self> {
62        let mut result = self.clone();
63        if result.pop().is_some() {
64            Some(result)
65        } else {
66            None
67        }
68    }
69
70    pub fn push(&mut self, entity: Entity) {
71        *self = match std::mem::replace(self, Self::new(Default::default())) {
72            Self::One([a]) => Self::Two([a, entity]),
73            Self::Two([a, b]) => Self::More(vec![a, b, entity]),
74            Self::More(mut items) => {
75                items.push(entity);
76                Self::More(items)
77            }
78        }
79    }
80
81    pub fn pop(&mut self) -> Option<Entity> {
82        match std::mem::replace(self, Self::new(Default::default())) {
83            Self::One([a]) => {
84                *self = Self::One([a]);
85                None
86            }
87            Self::Two([a, b]) => {
88                *self = Self::One([a]);
89                Some(b)
90            }
91            Self::More(mut items) => {
92                let result = items.pop()?;
93                match items.len() {
94                    2 => {
95                        *self = Self::Two([items[0], items[1]]);
96                    }
97                    1 => {
98                        *self = Self::One([items[0]]);
99                    }
100                    _ => {
101                        *self = Self::More(items);
102                    }
103                }
104                Some(result)
105            }
106        }
107    }
108
109    pub fn prepend(&mut self, other: impl IntoIterator<Item = Entity>) {
110        *self = Self::from_iter(other.into_iter().chain(self.iter()));
111    }
112
113    pub fn append(&mut self, other: impl IntoIterator<Item = Entity>) {
114        for entity in other.into_iter() {
115            self.push(entity);
116        }
117    }
118
119    pub fn iter(&self) -> impl Iterator<Item = Entity> + '_ {
120        match self {
121            Self::One(items) => items.as_slice().iter().copied(),
122            Self::Two(items) => items.as_slice().iter().copied(),
123            Self::More(items) => items.as_slice().iter().copied(),
124        }
125    }
126
127    pub fn into_inner(self) -> Vec<Entity> {
128        self.iter().collect()
129    }
130}
131
132impl FromIterator<Entity> for Multity {
133    fn from_iter<T: IntoIterator<Item = Entity>>(iter: T) -> Self {
134        let mut iter = iter.into_iter();
135        let entity = iter.next().unwrap();
136        let mut result = Self::new(entity);
137        for entity in iter {
138            result.push(entity);
139        }
140        result
141    }
142}
143
144pub struct ArchetypeMultityColumnAccess<'a, const LOCKING: bool, T: Component> {
145    _worlds: Vec<ArchetypeEntityColumnAccess<'a, LOCKING, World>>,
146    entity: ArchetypeEntityColumnAccess<'a, LOCKING, T>,
147}
148
149impl<const LOCKING: bool, T: Component> ArchetypeMultityColumnAccess<'_, LOCKING, T> {
150    #[inline]
151    pub fn info(&self) -> &ArchetypeColumnInfo {
152        self.entity.info()
153    }
154
155    #[inline]
156    pub fn is_unique(&self) -> bool {
157        self.entity.is_unique()
158    }
159
160    /// # Safety
161    #[inline]
162    pub unsafe fn data(&self) -> *mut u8 {
163        self.entity.data()
164    }
165
166    pub fn read(&self) -> Option<&T> {
167        self.entity.read()
168    }
169
170    pub fn write(&mut self) -> Option<&mut T> {
171        self.entity.write()
172    }
173}
174
175pub struct ArchetypeDynamicMultityColumnAccess<'a, const LOCKING: bool> {
176    _worlds: Vec<ArchetypeEntityColumnAccess<'a, LOCKING, World>>,
177    entity: ArchetypeDynamicEntityColumnAccess<'a, LOCKING>,
178}
179
180impl<const LOCKING: bool> ArchetypeDynamicMultityColumnAccess<'_, LOCKING> {
181    #[inline]
182    pub fn info(&self) -> &ArchetypeColumnInfo {
183        self.entity.info()
184    }
185
186    #[inline]
187    pub fn is_unique(&self) -> bool {
188        self.entity.is_unique()
189    }
190
191    /// # Safety
192    #[inline]
193    pub unsafe fn data(&self) -> *mut u8 {
194        self.entity.data()
195    }
196
197    pub fn read<T: Component>(&self) -> Option<&T> {
198        self.entity.read::<T>()
199    }
200
201    pub fn write<T: Component>(&mut self) -> Option<&mut T> {
202        self.entity.write::<T>()
203    }
204}
205
206pub struct HyperComponentRef<'a, const LOCKING: bool, T: Send + Sync + 'static> {
207    inner: ArchetypeMultityColumnAccess<'a, LOCKING, T>,
208}
209
210impl<const LOCKING: bool, T: Send + Sync + 'static> Deref for HyperComponentRef<'_, LOCKING, T> {
211    type Target = T;
212
213    fn deref(&self) -> &Self::Target {
214        self.inner.read().unwrap()
215    }
216}
217
218pub struct HyperComponentRefMut<'a, const LOCKING: bool, T: Send + Sync + 'static> {
219    inner: ArchetypeMultityColumnAccess<'a, LOCKING, T>,
220}
221
222impl<const LOCKING: bool, T: Send + Sync + 'static> Deref for HyperComponentRefMut<'_, LOCKING, T> {
223    type Target = T;
224
225    fn deref(&self) -> &Self::Target {
226        self.inner.read().unwrap()
227    }
228}
229
230impl<const LOCKING: bool, T: Send + Sync + 'static> DerefMut
231    for HyperComponentRefMut<'_, LOCKING, T>
232{
233    fn deref_mut(&mut self) -> &mut Self::Target {
234        self.inner.write().unwrap()
235    }
236}
237
238pub struct MultiverseTypedQueryIter<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>> {
239    queries: VecDeque<TypedQueryIter<'a, LOCKING, Fetch>>,
240}
241
242impl<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>> Default
243    for MultiverseTypedQueryIter<'a, LOCKING, Fetch>
244{
245    fn default() -> Self {
246        Self {
247            queries: Default::default(),
248        }
249    }
250}
251
252impl<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>>
253    MultiverseTypedQueryIter<'a, LOCKING, Fetch>
254{
255    pub fn new(world: &'a World) -> Self {
256        let mut result = Self::default();
257        result.include(world);
258        result
259    }
260
261    pub fn include(&mut self, world: &'a World) {
262        self.queries.push_back(world.query::<'a, LOCKING, Fetch>());
263        for world in world.query::<'a, LOCKING, &World>() {
264            self.include(world);
265        }
266    }
267}
268
269impl<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>> Iterator
270    for MultiverseTypedQueryIter<'a, LOCKING, Fetch>
271{
272    type Item = Fetch::Value;
273
274    fn next(&mut self) -> Option<Self::Item> {
275        loop {
276            if let Some(query) = self.queries.back_mut() {
277                if let Some(result) = query.next() {
278                    return Some(result);
279                }
280                self.queries.pop_back();
281                continue;
282            }
283            break;
284        }
285        None
286    }
287}
288
289pub struct MultiverseDynamicQueryIter<'a, const LOCKING: bool> {
290    queries: VecDeque<DynamicQueryIter<'a, LOCKING>>,
291}
292
293impl<const LOCKING: bool> Default for MultiverseDynamicQueryIter<'_, LOCKING> {
294    fn default() -> Self {
295        Self {
296            queries: Default::default(),
297        }
298    }
299}
300
301impl<'a, const LOCKING: bool> MultiverseDynamicQueryIter<'a, LOCKING> {
302    pub fn new(filter: &DynamicQueryFilter, world: &'a World) -> Self {
303        let mut result = Self::default();
304        result.include(filter, world);
305        result
306    }
307
308    pub fn include(&mut self, filter: &DynamicQueryFilter, world: &'a World) {
309        self.queries
310            .push_back(world.dynamic_query::<LOCKING>(filter));
311        for world in world.query::<'a, LOCKING, &World>() {
312            self.include(filter, world);
313        }
314    }
315}
316
317impl<'a, const LOCKING: bool> Iterator for MultiverseDynamicQueryIter<'a, LOCKING> {
318    type Item = DynamicQueryItem<'a>;
319
320    fn next(&mut self) -> Option<Self::Item> {
321        loop {
322            if let Some(query) = self.queries.back_mut() {
323                if let Some(result) = query.next() {
324                    return Some(result);
325                }
326                self.queries.pop_back();
327                continue;
328            }
329            break;
330        }
331        None
332    }
333}
334
335pub struct MultiverseMultityTypedQueryIter<
336    'a,
337    const LOCKING: bool,
338    Fetch: TypedQueryFetch<'a, LOCKING>,
339> {
340    /// [(parent world?, query)]
341    #[allow(clippy::type_complexity)]
342    queries: VecDeque<(
343        Option<Multity>,
344        TypedQueryIter<'a, LOCKING, (Entity, Fetch)>,
345    )>,
346}
347
348impl<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>> Default
349    for MultiverseMultityTypedQueryIter<'a, LOCKING, Fetch>
350{
351    fn default() -> Self {
352        Self {
353            queries: Default::default(),
354        }
355    }
356}
357
358impl<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>>
359    MultiverseMultityTypedQueryIter<'a, LOCKING, Fetch>
360{
361    pub fn new(world: &'a World) -> Self {
362        let mut result = Self::default();
363        result.include(world, None);
364        result
365    }
366
367    fn include(&mut self, world: &'a World, parent: Option<Multity>) {
368        self.queries.push_back((
369            parent.clone(),
370            world.query::<'a, LOCKING, (Entity, Fetch)>(),
371        ));
372        for (entity, world) in world.query::<'a, LOCKING, (Entity, &World)>() {
373            let parent = if let Some(parent) = parent.as_ref() {
374                parent.clone().with(entity)
375            } else {
376                Multity::new(entity)
377            };
378            self.include(world, Some(parent));
379        }
380    }
381}
382
383impl<'a, const LOCKING: bool, Fetch: TypedQueryFetch<'a, LOCKING>> Iterator
384    for MultiverseMultityTypedQueryIter<'a, LOCKING, Fetch>
385{
386    type Item = (Multity, Fetch::Value);
387
388    fn next(&mut self) -> Option<Self::Item> {
389        loop {
390            if let Some((parent, query)) = self.queries.back_mut() {
391                if let Some((entity, result)) = query.next() {
392                    let multity = if let Some(parent) = parent.as_ref() {
393                        parent.clone().with(entity)
394                    } else {
395                        Multity::new(entity)
396                    };
397                    return Some((multity, result));
398                }
399                self.queries.pop_back();
400                continue;
401            }
402            break;
403        }
404        None
405    }
406}
407
408pub struct MultiverseMultityDynamicQueryIter<'a, const LOCKING: bool> {
409    /// [(parent world?, query)]
410    queries: VecDeque<(Option<Multity>, DynamicQueryIter<'a, LOCKING>)>,
411}
412
413impl<const LOCKING: bool> Default for MultiverseMultityDynamicQueryIter<'_, LOCKING> {
414    fn default() -> Self {
415        Self {
416            queries: Default::default(),
417        }
418    }
419}
420
421impl<'a, const LOCKING: bool> MultiverseMultityDynamicQueryIter<'a, LOCKING> {
422    pub fn new(filter: &DynamicQueryFilter, world: &'a World) -> Self {
423        let mut result = Self::default();
424        result.include(filter, world, None);
425        result
426    }
427
428    fn include(&mut self, filter: &DynamicQueryFilter, world: &'a World, parent: Option<Multity>) {
429        self.queries
430            .push_back((parent.clone(), world.dynamic_query::<LOCKING>(filter)));
431        for (entity, world) in world.query::<'a, LOCKING, (Entity, &World)>() {
432            let parent = if let Some(parent) = parent.as_ref() {
433                parent.clone().with(entity)
434            } else {
435                Multity::new(entity)
436            };
437            self.include(filter, world, Some(parent));
438        }
439    }
440}
441
442impl<'a, const LOCKING: bool> Iterator for MultiverseMultityDynamicQueryIter<'a, LOCKING> {
443    type Item = (Multity, DynamicQueryItem<'a>);
444
445    fn next(&mut self) -> Option<Self::Item> {
446        loop {
447            if let Some((parent, query)) = self.queries.back_mut() {
448                if let Some(result) = query.next() {
449                    let multity = if let Some(parent) = parent.as_ref() {
450                        parent.clone().with(result.entity())
451                    } else {
452                        Multity::new(result.entity())
453                    };
454                    return Some((multity, result));
455                }
456                self.queries.pop_back();
457                continue;
458            }
459            break;
460        }
461        None
462    }
463}
464
465pub struct Multiverse<'a> {
466    pub world: &'a World,
467}
468
469impl<'a> Multiverse<'a> {
470    pub fn new(world: &'a World) -> Self {
471        Self { world }
472    }
473
474    pub fn component<const LOCKING: bool, T: Component>(
475        &self,
476        multity: Multity,
477    ) -> Result<HyperComponentRef<LOCKING, T>, WorldError> {
478        Ok(HyperComponentRef {
479            inner: self.get::<LOCKING, T>(multity, false)?,
480        })
481    }
482
483    pub fn component_mut<const LOCKING: bool, T: Component>(
484        &self,
485        multity: Multity,
486    ) -> Result<HyperComponentRefMut<LOCKING, T>, WorldError> {
487        Ok(HyperComponentRefMut {
488            inner: self.get::<LOCKING, T>(multity, true)?,
489        })
490    }
491
492    pub fn get<const LOCKING: bool, T: Component>(
493        &self,
494        multity: Multity,
495        unique: bool,
496    ) -> Result<ArchetypeMultityColumnAccess<'a, LOCKING, T>, WorldError> {
497        let mut worlds =
498            Vec::<ArchetypeEntityColumnAccess<LOCKING, World>>::with_capacity(multity.len());
499        let mut iter = multity.iter().peekable();
500        while let Some(entity) = iter.next() {
501            if iter.peek().is_none() {
502                let entity = if let Some(access) = worlds.last() {
503                    let world =
504                        unsafe { std::mem::transmute::<&World, &'a World>(access.read().unwrap()) };
505                    world.get::<LOCKING, T>(entity, unique)?
506                } else {
507                    self.world.get::<LOCKING, T>(entity, unique)?
508                };
509                return Ok(ArchetypeMultityColumnAccess {
510                    _worlds: worlds,
511                    entity,
512                });
513            }
514            let world = if let Some(access) = worlds.last() {
515                let world =
516                    unsafe { std::mem::transmute::<&World, &'a World>(access.read().unwrap()) };
517                world.get::<LOCKING, World>(entity, unique)?
518            } else {
519                self.world.get::<LOCKING, World>(entity, unique)?
520            };
521            worlds.push(world);
522        }
523        unreachable!()
524    }
525
526    pub fn dynamic_get<const LOCKING: bool>(
527        &self,
528        type_hash: TypeHash,
529        multity: Multity,
530        unique: bool,
531    ) -> Result<ArchetypeDynamicMultityColumnAccess<LOCKING>, WorldError> {
532        let mut worlds =
533            Vec::<ArchetypeEntityColumnAccess<LOCKING, World>>::with_capacity(multity.len());
534        let mut iter = multity.iter().peekable();
535        while let Some(entity) = iter.next() {
536            if iter.peek().is_none() {
537                let entity = if let Some(access) = worlds.last() {
538                    let world =
539                        unsafe { std::mem::transmute::<&World, &'a World>(access.read().unwrap()) };
540                    world.dynamic_get::<LOCKING>(type_hash, entity, unique)?
541                } else {
542                    self.world
543                        .dynamic_get::<LOCKING>(type_hash, entity, unique)?
544                };
545                return Ok(ArchetypeDynamicMultityColumnAccess {
546                    _worlds: worlds,
547                    entity,
548                });
549            }
550            let world = if let Some(access) = worlds.last() {
551                let world =
552                    unsafe { std::mem::transmute::<&World, &'a World>(access.read().unwrap()) };
553                world.get::<LOCKING, World>(entity, unique)?
554            } else {
555                self.world.get::<LOCKING, World>(entity, unique)?
556            };
557            worlds.push(world);
558        }
559        unreachable!()
560    }
561
562    pub fn query<'b, const LOCKING: bool, Fetch: TypedQueryFetch<'b, LOCKING>>(
563        &'b self,
564    ) -> MultiverseTypedQueryIter<'b, LOCKING, Fetch> {
565        MultiverseTypedQueryIter::new(self.world)
566    }
567
568    pub fn multity_query<'b, const LOCKING: bool, Fetch: TypedQueryFetch<'b, LOCKING>>(
569        &'b self,
570    ) -> MultiverseMultityTypedQueryIter<'b, LOCKING, Fetch> {
571        MultiverseMultityTypedQueryIter::new(self.world)
572    }
573
574    pub fn dynamic_query<'b, const LOCKING: bool>(
575        &'b self,
576        filter: &DynamicQueryFilter,
577    ) -> MultiverseDynamicQueryIter<'a, LOCKING> {
578        MultiverseDynamicQueryIter::new(filter, self.world)
579    }
580
581    pub fn dynamic_multity_query<'b, const LOCKING: bool>(
582        &'b self,
583        filter: &DynamicQueryFilter,
584    ) -> MultiverseMultityDynamicQueryIter<'a, LOCKING> {
585        MultiverseMultityDynamicQueryIter::new(filter, self.world)
586    }
587}
588
589#[cfg(test)]
590mod tests {
591    use super::*;
592    use crate::{query::Include, world::World};
593
594    #[test]
595    fn test_multiverse() {
596        let mut world1 = World::default();
597        let a = world1.spawn((1usize,)).unwrap();
598        let b = world1.spawn((2usize,)).unwrap();
599        let c = world1.spawn((3usize,)).unwrap();
600
601        let mut world2 = World::default();
602        let d = world2.spawn((4usize,)).unwrap();
603        let e = world2.spawn((5usize,)).unwrap();
604        let f = world2.spawn((world1,)).unwrap();
605
606        let mut world3 = World::default();
607        let g = world3.spawn((6usize,)).unwrap();
608        let h = world3.spawn((world2,)).unwrap();
609
610        let mut world = World::default();
611        let i = world.spawn((world3,)).unwrap();
612
613        assert_eq!(
614            Multiverse::new(&world)
615                .query::<true, &usize>()
616                .copied()
617                .collect::<Vec<_>>(),
618            vec![1, 2, 3, 4, 5, 6]
619        );
620
621        assert_eq!(
622            Multiverse::new(&world)
623                .dynamic_query::<true>(&DynamicQueryFilter::default().read::<usize>())
624                .map(|item| *item.read::<usize>().unwrap().read::<usize>().unwrap())
625                .collect::<Vec<_>>(),
626            vec![1, 2, 3, 4, 5, 6]
627        );
628
629        let multity = Multity::from_iter([i, h, f, b]);
630        *Multiverse::new(&world)
631            .component_mut::<true, usize>(multity.clone())
632            .unwrap() = 10;
633        assert_eq!(
634            *Multiverse::new(&world)
635                .component::<true, usize>(multity.clone())
636                .unwrap(),
637            10
638        );
639
640        assert_eq!(
641            Multiverse::new(&world)
642                .query::<true, &usize>()
643                .copied()
644                .collect::<Vec<_>>(),
645            vec![1, 10, 3, 4, 5, 6]
646        );
647
648        assert_eq!(
649            Multiverse::new(&world)
650                .multity_query::<true, Include<usize>>()
651                .map(|(multity, _)| multity)
652                .collect::<Vec<_>>(),
653            vec![
654                Multity::from_iter([i, h, f, a]),
655                Multity::from_iter([i, h, f, b]),
656                Multity::from_iter([i, h, f, c]),
657                Multity::from_iter([i, h, d]),
658                Multity::from_iter([i, h, e]),
659                Multity::from_iter([i, g]),
660            ]
661        );
662
663        assert_eq!(
664            Multiverse::new(&world)
665                .dynamic_multity_query::<true>(&DynamicQueryFilter::default().include::<usize>())
666                .map(|(multity, _)| multity)
667                .collect::<Vec<_>>(),
668            vec![
669                Multity::from_iter([i, h, f, a]),
670                Multity::from_iter([i, h, f, b]),
671                Multity::from_iter([i, h, f, c]),
672                Multity::from_iter([i, h, d]),
673                Multity::from_iter([i, h, e]),
674                Multity::from_iter([i, g]),
675            ]
676        );
677    }
678}