gizmo_core/system/
params.rs1use super::*;
2use crate::world::World;
3use std::any::TypeId;
4
5use crate::world::{ResourceReadGuard, ResourceWriteGuard};
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12#[non_exhaustive]
13pub enum SystemParamFetchError {
14 Resource(crate::world::ResourceFetchError),
15 QueryError,
16}
17
18impl From<crate::world::ResourceFetchError> for SystemParamFetchError {
19 fn from(value: crate::world::ResourceFetchError) -> Self {
20 Self::Resource(value)
21 }
22}
23
24impl std::fmt::Display for SystemParamFetchError {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 match self {
27 SystemParamFetchError::Resource(e) => {
28 write!(f, "system parameter resource fetch failed: {e}")
29 }
30 SystemParamFetchError::QueryError => {
31 write!(f, "system parameter query construction failed")
32 }
33 }
34 }
35}
36
37impl std::error::Error for SystemParamFetchError {
38 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
39 match self {
40 SystemParamFetchError::Resource(e) => Some(e),
41 SystemParamFetchError::QueryError => None,
42 }
43 }
44}
45
46pub(crate) mod sealed {
54 pub trait Sealed {}
55}
56
57pub trait SystemParam: sealed::Sealed {
64 type Item<'w>;
65 fn fetch<'w>(world: &'w World, dt: f32) -> Result<Self::Item<'w>, SystemParamFetchError>;
66 fn get_access_info(info: &mut AccessInfo);
67}
68
69pub struct Res<'w, T: 'static> {
70 value: ResourceReadGuard<'w, T>,
71}
72
73impl<'w, T: 'static> std::ops::Deref for Res<'w, T> {
74 type Target = T;
75 fn deref(&self) -> &Self::Target {
76 &self.value
77 }
78}
79
80impl<T: 'static> sealed::Sealed for Res<'static, T> {}
81impl<T: 'static> SystemParam for Res<'static, T> {
82 type Item<'w> = Res<'w, T>;
83 fn fetch<'w>(world: &'w World, _dt: f32) -> Result<Self::Item<'w>, SystemParamFetchError> {
84 let value = world.try_get_resource::<T>()?;
85 Ok(Res::<T> { value })
86 }
87 fn get_access_info(info: &mut AccessInfo) {
88 info.resource_reads.push(TypeId::of::<T>());
89 }
90}
91
92pub struct ResMut<'w, T: 'static> {
93 value: ResourceWriteGuard<'w, T>,
94}
95
96impl<'w, T: 'static> std::ops::Deref for ResMut<'w, T> {
97 type Target = T;
98 fn deref(&self) -> &Self::Target {
99 &self.value
100 }
101}
102
103impl<'w, T: 'static> std::ops::DerefMut for ResMut<'w, T> {
104 fn deref_mut(&mut self) -> &mut Self::Target {
105 &mut self.value
106 }
107}
108
109impl<T: 'static> sealed::Sealed for ResMut<'static, T> {}
110impl<T: 'static> SystemParam for ResMut<'static, T> {
111 type Item<'w> = ResMut<'w, T>;
112 fn fetch<'w>(world: &'w World, _dt: f32) -> Result<Self::Item<'w>, SystemParamFetchError> {
113 let value = world.try_get_resource_mut::<T>()?;
114 Ok(ResMut::<T> { value })
115 }
116 fn get_access_info(info: &mut AccessInfo) {
117 info.resource_writes.push(TypeId::of::<T>());
118 }
119}
120
121impl sealed::Sealed for f32 {}
122impl SystemParam for f32 {
123 type Item<'w> = f32;
124 fn fetch<'w>(_world: &'w World, dt: f32) -> Result<Self::Item<'w>, SystemParamFetchError> {
125 Ok(dt)
126 }
127 fn get_access_info(_info: &mut AccessInfo) {}
128}
129
130impl<Q: crate::query::WorldQuery + 'static> sealed::Sealed for crate::query::Query<'static, Q> {}
131impl<Q: crate::query::WorldQuery + 'static> SystemParam for crate::query::Query<'static, Q> {
132 type Item<'w> = crate::query::Query<'w, Q>;
133 fn fetch<'w>(world: &'w World, _dt: f32) -> Result<Self::Item<'w>, SystemParamFetchError> {
134 if let Some(query) = unsafe { world.query_unchecked::<Q>() } {
141 Ok(query)
142 } else {
143 Err(SystemParamFetchError::QueryError)
144 }
145 }
146 fn get_access_info(info: &mut AccessInfo) {
147 let mut types = Vec::new();
148 Q::check_aliasing(&mut types);
149 for (tid, is_mut) in types {
150 if is_mut {
151 info.component_writes.push(tid);
152 } else {
153 info.component_reads.push(tid);
154 }
155 }
156 }
157}
158