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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
use std::any::{type_name, Any, TypeId};
use std::fmt::Debug;
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use crate::lock::WriteGuard;
use crate::system::{NoInitParamFlag, Param as SystemParam, System};
use crate::tuple::FilterExclude as TupleFilterExclude;
use crate::type_name::TypeName;
use crate::WorldData;
/// A type which has a single instance and is shared globally.
pub trait Sole: Any + TypeName
{
fn as_any_mut(&mut self) -> &mut dyn Any;
fn as_any(&self) -> &dyn Any;
}
impl dyn Sole
{
pub fn downcast_mut<Real: 'static>(&mut self) -> Option<&mut Real>
{
self.as_any_mut().downcast_mut()
}
pub fn downcast_ref<Real: 'static>(&self) -> Option<&Real>
{
self.as_any().downcast_ref()
}
}
impl Debug for dyn Sole
{
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
{
formatter.debug_struct("Sole").finish_non_exhaustive()
}
}
impl TypeName for Box<dyn Sole>
{
fn type_name(&self) -> &'static str
{
self.as_ref().type_name()
}
}
/// Holds a reference to a globally shared singleton value.
#[derive(Debug)]
pub struct Single<'world, SoleT: Sole>
{
sole: WriteGuard<'world, Box<dyn Sole>>,
_ph: PhantomData<SoleT>,
}
unsafe impl<'world, SoleT> SystemParam<'world> for Single<'world, SoleT>
where
SoleT: Sole,
{
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 sole = world_data
.sole_storage
.get::<SoleT>()
.expect("Sole was not found in world")
.write_nonblock()
.unwrap_or_else(|_| {
panic!(
"Failed to aquire read-write lock to single component {}",
type_name::<SoleT>()
)
});
Self { sole, _ph: PhantomData }
}
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::<SoleT>() != comparable.sole_type_id
}
fn get_comparable() -> Box<dyn Any>
{
Box::new(Comparable { sole_type_id: TypeId::of::<SoleT>() })
}
}
impl<'world, SoleT> Deref for Single<'world, SoleT>
where
SoleT: Sole,
{
type Target = SoleT;
fn deref(&self) -> &Self::Target
{
self.sole.downcast_ref().unwrap()
}
}
impl<'world, SoleT> DerefMut for Single<'world, SoleT>
where
SoleT: Sole,
{
fn deref_mut(&mut self) -> &mut Self::Target
{
self.sole.downcast_mut().unwrap()
}
}
struct Comparable
{
sole_type_id: TypeId,
}
|