bevy_render/
extract_param.rs1use crate::MainWorld;
2use bevy_ecs::{
3 component::Tick,
4 prelude::*,
5 system::{
6 ReadOnlySystemParam, SystemMeta, SystemParam, SystemParamItem, SystemParamValidationError,
7 SystemState,
8 },
9 world::unsafe_world_cell::UnsafeWorldCell,
10};
11use core::ops::{Deref, DerefMut};
12
13pub struct Extract<'w, 's, P>
50where
51 P: ReadOnlySystemParam + 'static,
52{
53 item: SystemParamItem<'w, 's, P>,
54}
55
56#[doc(hidden)]
57pub struct ExtractState<P: SystemParam + 'static> {
58 state: SystemState<P>,
59 main_world_state: <Res<'static, MainWorld> as SystemParam>::State,
60}
61
62unsafe impl<P> ReadOnlySystemParam for Extract<'_, '_, P> where P: ReadOnlySystemParam {}
64
65unsafe impl<P> SystemParam for Extract<'_, '_, P>
68where
69 P: ReadOnlySystemParam,
70{
71 type State = ExtractState<P>;
72 type Item<'w, 's> = Extract<'w, 's, P>;
73
74 fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
75 let mut main_world = world.resource_mut::<MainWorld>();
76 ExtractState {
77 state: SystemState::new(&mut main_world),
78 main_world_state: Res::<MainWorld>::init_state(world, system_meta),
79 }
80 }
81
82 #[inline]
83 unsafe fn validate_param(
84 state: &Self::State,
85 _system_meta: &SystemMeta,
86 world: UnsafeWorldCell,
87 ) -> Result<(), SystemParamValidationError> {
88 let result = unsafe { world.get_resource_by_id(state.main_world_state) };
90 let Some(main_world) = result else {
91 return Err(SystemParamValidationError::invalid::<Self>(
92 "`MainWorld` resource does not exist",
93 ));
94 };
95 let main_world: &World = unsafe { main_world.deref() };
97 unsafe {
99 SystemState::<P>::validate_param(
100 &state.state,
101 main_world.as_unsafe_world_cell_readonly(),
102 )
103 }
104 }
105
106 #[inline]
107 unsafe fn get_param<'w, 's>(
108 state: &'s mut Self::State,
109 system_meta: &SystemMeta,
110 world: UnsafeWorldCell<'w>,
111 change_tick: Tick,
112 ) -> Self::Item<'w, 's> {
113 let main_world = unsafe {
117 Res::<MainWorld>::get_param(
118 &mut state.main_world_state,
119 system_meta,
120 world,
121 change_tick,
122 )
123 };
124 let item = state.state.get(main_world.into_inner());
125 Extract { item }
126 }
127}
128
129impl<'w, 's, P> Deref for Extract<'w, 's, P>
130where
131 P: ReadOnlySystemParam,
132{
133 type Target = SystemParamItem<'w, 's, P>;
134
135 #[inline]
136 fn deref(&self) -> &Self::Target {
137 &self.item
138 }
139}
140
141impl<'w, 's, P> DerefMut for Extract<'w, 's, P>
142where
143 P: ReadOnlySystemParam,
144{
145 #[inline]
146 fn deref_mut(&mut self) -> &mut Self::Target {
147 &mut self.item
148 }
149}
150
151impl<'a, 'w, 's, P> IntoIterator for &'a Extract<'w, 's, P>
152where
153 P: ReadOnlySystemParam,
154 &'a SystemParamItem<'w, 's, P>: IntoIterator,
155{
156 type Item = <&'a SystemParamItem<'w, 's, P> as IntoIterator>::Item;
157 type IntoIter = <&'a SystemParamItem<'w, 's, P> as IntoIterator>::IntoIter;
158
159 fn into_iter(self) -> Self::IntoIter {
160 (&self.item).into_iter()
161 }
162}