use std::any::{type_name, Any, TypeId}; use std::ops::{Deref, DerefMut}; use crate::component::Component; use crate::system::{ComponentRefMut, NoInitParamFlag, Param as SystemParam, System}; use crate::tuple::FilterExclude as TupleFilterExclude; use crate::WorldData; /// Holds a component which has a single instance and is shared globally. #[derive(Debug)] pub struct Single<'world, SingleComponent: Component> { single_component: ComponentRefMut<'world, SingleComponent>, } unsafe impl<'world, SingleComponent> SystemParam<'world> for Single<'world, SingleComponent> where SingleComponent: Component, { type Flags = NoInitParamFlag; type Input = TupleFilterExclude; fn initialize( _system: &mut impl System<'world, SystemImpl>, _input: Self::Input, ) { } fn new( _system: &'world impl System<'world, SystemImpl>, world_data: &'world WorldData, ) -> Self { let single_component = world_data .single_component_storage .get::() .expect("Single component was not found in world") .write_nonblock() .unwrap_or_else(|_| { panic!( "Failed to aquire read-write lock to single component {}", type_name::() ) }); Self { single_component: ComponentRefMut::new(single_component), } } fn is_compatible>() -> bool { let other_comparable = Other::get_comparable(); let Some(comparable) = other_comparable.downcast_ref::() else { // The other system param is not Single return true; }; TypeId::of::() != comparable.single_component_type_id } fn get_comparable() -> Box { Box::new(Comparable { single_component_type_id: TypeId::of::(), }) } } impl<'world, SingleComponent> Deref for Single<'world, SingleComponent> where SingleComponent: Component, { type Target = SingleComponent; fn deref(&self) -> &Self::Target { &self.single_component } } impl<'world, SingleComponent> DerefMut for Single<'world, SingleComponent> where SingleComponent: Component, { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.single_component } } struct Comparable { single_component_type_id: TypeId, }