use std::convert::Infallible; use crate::component::storage::Storage as ComponentStorage; use crate::component::{IntoParts as IntoComponentParts, Parts as ComponentParts}; use crate::entity::{ Handle as EntityHandle, MatchingComponentIter as EntityMatchingComponentIter, }; use crate::lock::ReadGuard; use crate::query::{ TermWithField as QueryTermWithField, TermsBuilder as QueryTermsBuilder, TermsBuilderInterface, }; use crate::uid::{PairParams as UidPairParams, Uid, Wildcard, With as WithUid}; use crate::{Component, World}; #[derive(Debug)] pub struct Pair { relation: RelationElem, target: TargetElem, } impl Pair { pub fn new(target: Uid) -> Self { Self { relation: Relation::uid(), target } } pub fn id(&self) -> Uid { Uid::new_pair(UidPairParams { relation: self.relation, target: self.target, }) } } impl IntoComponentParts for Pair { fn into_parts(self) -> ComponentParts { ComponentParts::builder().name("Pair").build(self.id(), ()) } } impl QueryTermWithField for Pair where Relation: WithUid, Target: WithUid, { type Field<'a> = Handle<'a>; fn apply_to_terms_builder( terms_builder: &mut QueryTermsBuilder, ) { terms_builder.with_required([Self::uid()]); } fn get_field<'world>( entity_handle: &EntityHandle<'world>, world: &'world World, ) -> Self::Field<'world> { let first_matching_comp = entity_handle .get_matching_components(Self::uid()) .next() .expect("Not possible"); Handle { world, component_storage_lock: world.data.component_storage.read_nonblock().unwrap(), pair_uid: first_matching_comp.id(), } } } impl WithUid for Pair where Relation: WithUid, Target: WithUid, { fn uid() -> Uid { Uid::new_pair(UidPairParams { relation: Relation::uid(), target: Target::uid(), }) } } impl QueryTermWithField for &'static [Pair] where Relation: WithUid, { type Field<'a> = HandleIter<'a>; fn apply_to_terms_builder( terms_builder: &mut QueryTermsBuilder, ) { terms_builder.with_required([Pair::::uid()]); } fn get_field<'world>( entity_handle: &EntityHandle<'world>, world: &'world World, ) -> Self::Field<'world> { HandleIter { inner: entity_handle .get_matching_components(Pair::::uid()), world, } } } pub struct Handle<'world> { world: &'world World, component_storage_lock: ReadGuard<'world, ComponentStorage>, pair_uid: Uid, } impl Handle<'_> { pub fn get_target_entity(&self) -> Option> { let archetype = self .component_storage_lock .get_entity_archetype(self.pair_uid.target_entity())?; let archetype_entity = archetype .get_entity_by_id(self.pair_uid.target_entity()) .expect("Not possible"); Some(EntityHandle::new(self.world, archetype, archetype_entity)) } } pub struct HandleIter<'a> { inner: EntityMatchingComponentIter<'a>, world: &'a World, } impl<'a> Iterator for HandleIter<'a> { type Item = Handle<'a>; fn next(&mut self) -> Option { let matching_comp = self.inner.next()?; Some(Handle { world: self.world, component_storage_lock: self .world .data .component_storage .read_nonblock() .unwrap(), pair_uid: matching_comp.id(), }) } } pub trait Element: sealed::Sealed { type Value; } impl Element for Uid { type Value = Uid; } impl sealed::Sealed for Uid {} impl Element for WithUidT { type Value = Infallible; } impl sealed::Sealed for WithUidT {} /// Relation denoting a dependency to another entity #[derive(Debug, Default, Clone, Copy, Component)] pub struct DependsOn; /// Relation denoting being the child of another entity. #[derive(Debug, Default, Clone, Copy, Component)] pub struct ChildOf; mod sealed { pub trait Sealed {} }