diff options
Diffstat (limited to 'ecs/src/component')
| -rw-r--r-- | ecs/src/component/single.rs | 98 | 
1 files changed, 98 insertions, 0 deletions
diff --git a/ecs/src/component/single.rs b/ecs/src/component/single.rs new file mode 100644 index 0000000..a63dbe3 --- /dev/null +++ b/ecs/src/component/single.rs @@ -0,0 +1,98 @@ +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<SystemImpl>( +        _system: &mut impl System<'world, SystemImpl>, +        _input: Self::Input, +    ) +    { +    } + +    fn new<SystemImpl>( +        _system: &'world impl System<'world, SystemImpl>, +        world_data: &'world WorldData, +    ) -> Self +    { +        let single_component = world_data +            .single_component_storage +            .get::<SingleComponent>() +            .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::<SingleComponent>() +                ) +            }); + +        Self { +            single_component: ComponentRefMut::new(single_component), +        } +    } + +    fn is_compatible<Other: SystemParam<'world>>() -> bool +    { +        let other_comparable = Other::get_comparable(); + +        let Some(comparable) = other_comparable.downcast_ref::<Comparable>() else { +            // The other system param is not Single +            return true; +        }; + +        TypeId::of::<SingleComponent>() != comparable.single_component_type_id +    } + +    fn get_comparable() -> Box<dyn Any> +    { +        Box::new(Comparable { +            single_component_type_id: TypeId::of::<SingleComponent>(), +        }) +    } +} + +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, +}  | 
