summaryrefslogtreecommitdiff
path: root/engine-ecs/src/sole.rs
blob: 9409bcb0580833c2baa07c63b835aacefce4a024 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use std::any::{type_name, Any};
use std::fmt::Debug;
use std::ops::{Deref, DerefMut};

use crate::uid::Uid;
use crate::component::HandleMut as ComponentHandleMut;
use crate::component::IntoParts as IntoComponentParts;
use crate::system::{Metadata as SystemMetadata, Param as SystemParam};
use crate::World;

/// A type which has a single instance and is shared globally.
pub trait Sole: Any + IntoComponentParts
{
    fn id() -> Uid
    where
        Self: Sized;

    fn type_reflection() -> Option<&'static crate::reflection::Type>
    where
        Self: Sized;

    /// Returns the name of this component.
    fn name(&self) -> &'static str;
}

impl dyn Sole
{
    pub fn downcast_mut<Real: 'static>(&mut self) -> Option<&mut Real>
    {
        (self as &mut dyn Any).downcast_mut()
    }

    pub fn downcast_ref<Real: 'static>(&self) -> Option<&Real>
    {
        (self as &dyn Any).downcast_ref()
    }

    pub fn is<Other: 'static>(&self) -> bool
    {
        (self as &dyn Any).is::<Other>()
    }
}

impl Debug for dyn Sole
{
    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
    {
        formatter.debug_struct("Sole").finish_non_exhaustive()
    }
}

/// Holds a reference to a globally shared singleton value.
#[derive(Debug)]
pub struct Single<'world, SoleT: Sole>
{
    sole: ComponentHandleMut<'world, SoleT>,
}


impl<'world, SoleT> Single<'world, SoleT>
where
    SoleT: Sole,
{
    pub(crate) fn new(sole: ComponentHandleMut<'world, SoleT>) -> Self
    {
        Self { sole }
    }
}

impl<'world, SoleT> SystemParam<'world> for Single<'world, SoleT>
where
    SoleT: Sole,
{
    type Input = ();

    fn new(world: &'world World, _system_metadata: &SystemMetadata) -> Self
    {
        let sole = world
            .get_entity(SoleT::id())
            .and_then(|ent| ent.get_with_id_mut::<SoleT>(SoleT::id()))
            .unwrap_or_else(|| {
                panic!("Sole component {} was not found in world", type_name::<SoleT>())
            });

        Self::new(sole)
    }
}

impl<SoleT> Deref for Single<'_, SoleT>
where
    SoleT: Sole,
{
    type Target = SoleT;

    fn deref(&self) -> &Self::Target
    {
        &*self.sole
    }
}

impl<SoleT> DerefMut for Single<'_, SoleT>
where
    SoleT: Sole,
{
    fn deref_mut(&mut self) -> &mut Self::Target
    {
        &mut *self.sole
    }
}