feo_oop_engine/scripting/executor.rs
1//! \[backend\] Manages the async scripts.
2use {
3 super::{
4 swap::Swap,
5 globals::EngineGlobals,
6 },
7 crate::{
8 scene::{
9 Scene,
10 game_object::GameObject,
11 },
12 registration::{
13 relation::{
14 Parent,
15 ParentWrapper
16 },
17 id::ID,
18 }
19 },
20 std::{
21 future::Future,
22 sync::mpsc::{
23 Receiver,
24 SyncSender
25 },
26 collections::HashMap,
27 sync::{
28 Arc,
29 Mutex,
30 RwLock
31 },
32 task::{
33 Context,
34 Poll
35 }
36 },
37 futures::{
38 future::{
39 BoxFuture,
40 FutureExt
41 },
42 task::{
43 waker_ref,
44 ArcWake
45 },
46 },
47 rayon::slice::ParallelSliceMut,
48};
49
50pub struct Executor {
51 pub ready: Vec<Arc<RwLock<Box<dyn GameObject>>>>,
52 pub queue: Receiver<Arc<Task>>,
53}
54
55#[derive(Clone)]
56pub struct Spawner {
57 pub engine_globals: EngineGlobals, // distributed to all frames
58 pub task_sender: SyncSender<Arc<Task>>,
59}
60
61pub struct Task{
62 future: Mutex<Option<BoxFuture<'static, Swap>>>,
63 task_sender: SyncSender<Arc<Task>>,
64}
65
66impl Spawner {
67 pub fn spawn(&self, future: impl Future<Output = Swap> + 'static + Send) {
68 let future = future.boxed();
69 let task = Arc::new(Task {
70 future: Mutex::new(Some(future)),
71 task_sender: self.task_sender.clone(),
72 });
73 self.task_sender.send(task).expect("too many tasks queued");
74 }
75}
76
77impl ArcWake for Task {
78 fn wake_by_ref(arc_self: &Arc<Self>) {
79 let cloned = arc_self.clone();
80 arc_self
81 .task_sender
82 .send(cloned)
83 .expect("too many tasks queued");
84 }
85}
86
87impl Executor {
88 pub fn run(&self, scene: Arc<RwLock<Scene>>) {
89 let mut swaps = Vec::new();
90
91 while let Ok(task) = self.queue.recv() {
92 let mut future_slot = task.future.lock().unwrap();
93 if let Some(mut future) = future_slot.take() {
94 let waker = waker_ref(&task);
95 let context = &mut Context::from_waker(&*waker);
96 match future.as_mut().poll(context) {
97 Poll::Pending => { *future_slot = Some(future); },
98 Poll::Ready(swap_status) => {
99 match swap_status {
100 Swap::None => {},
101 _ => { swaps.push(swap_status); }
102 }
103 },
104 }
105 }
106 }
107
108 if !swaps.is_empty() {
109 Self::sort(&mut swaps, scene.clone());
110
111 swaps.into_iter().for_each( |swap| {
112 match swap {
113 // By swapping out the physical pointers rather than the interior it makes it possible to store a pointer to swap back in later
114 Swap::SwapParent(id, replacement) => { //
115 let mut found = false;
116 let mut queue = scene.read().unwrap().get_children().clone();
117
118 while let (Some(old), false) = (queue.pop(), found) {
119 let read = old.read().unwrap(); // will not actually be changing the target object
120 queue.append(&mut read.get_children());
121 if read.get_id() == id {
122 let children = read.get_children();
123 let parent = read.get_parent();
124
125 // direct children to the replacement
126 children.into_iter().for_each(|child| {
127 // set child object's parent object to be the new object
128 unsafe { child.write().unwrap().set_parent(ParentWrapper::GameObject(replacement.clone()))};
129
130 // set replacement's child objects to be the new object
131 replacement.write().unwrap().add_child(child);
132 });
133
134 // direct parent to the replacement
135 match parent.clone() { // shadowing
136 ParentWrapper::GameObject(parent) => unsafe {
137 parent.write().unwrap().replace_child(old.clone(), replacement.clone()).unwrap();
138 },
139 ParentWrapper::Scene(p) => unsafe {
140 p.write().unwrap().replace_child(old.clone(), replacement.clone()).unwrap();
141 }
142 }
143 unsafe { replacement.write().unwrap().set_parent(parent); }
144
145 found = true;
146 }
147 }
148
149 // Check Camera
150 let mut scene_rw = scene.write().unwrap();
151 if let Some(old_camera) = scene_rw.main_camera.clone() {
152 let old_camera_read = old_camera.read().unwrap();
153 if id == old_camera_read.get_id() {
154
155 // Note that swapping a main camera parent does not make sense unless the main camera is part of the game_object tree since those objects would not be drawn.
156 // If your intent is to toggle this group the objects and toggle their visibility attribute instead.
157 assert!(found);
158 // // direct children to the replacement
159 // let children = old_camera_read.get_children();
160 // let parent = old_camera_read.get_parent();
161 // let as_gameobject = old_camera_read.cast_gameobject_arc_rwlock(old_camera.clone());
162 // children.into_iter().for_each(|child| {
163 // // set child object's parent object to be the new object
164 // unsafe { child.write().unwrap().set_parent(ParentWrapper::GameObject(replacement.clone())) };
165 // // set replacement's child objects to be the new object
166 // replacement.write().unwrap().add_child(child);
167 // });
168
169 // // direct parent to the replacement
170 // match parent.clone() {
171 // ParentWrapper::GameObject(p) => unsafe {
172 // p.write().unwrap().replace_child(as_gameobject.clone(), replacement.clone()).unwrap();
173 // },
174 // ParentWrapper::Scene(_) => unsafe {
175 // scene_rw.replace_child(as_gameobject, replacement.clone()).unwrap();
176 // },
177 // }
178 // unsafe { replacement.write().unwrap().set_parent(parent); }
179
180 // replace the old camera with the replacement in the main_camera slot
181 scene_rw.main_camera = Some(replacement.clone().read().unwrap().cast_camera_arc_rwlock(replacement.clone()).unwrap());
182
183 found = true;
184 }
185 }
186
187 if !found {
188 panic!("could not find the ID.");
189 }
190 },
191 // cutting is fine here
192 Swap::SwapFull(id, replacement) => {
193 let mut found = false;
194 let mut queue = scene.read().unwrap().get_children().clone();
195
196 while let (Some(old), false) = (queue.pop(), found) {
197 let read = old.read().unwrap(); // will not actually be changing the target object
198 queue.append(&mut read.get_children());
199 if read.get_id() == id {
200 let parent = read.get_parent();
201
202 // direct parent to the replacement
203 match parent.clone() { // shadowing
204 ParentWrapper::GameObject(parent) => unsafe {
205 parent.write().unwrap().replace_child(old.clone(), replacement.clone()).unwrap();
206 },
207 ParentWrapper::Scene(p) => unsafe {
208 p.write().unwrap().replace_child(old.clone(), replacement.clone()).unwrap();
209 }
210 }
211 unsafe { replacement.write().unwrap().set_parent(parent); }
212
213 found = true;
214 }
215 }
216
217 // Check Camera
218 let mut scene_rw = scene.write().unwrap();
219 if let Some(old_camera) = scene_rw.main_camera.clone() {
220 let old_camera_read = old_camera.read().unwrap();
221 if id == old_camera_read.get_id() {
222 let parent = old_camera_read.get_parent();
223 // Not needed because It is done in above loop based on children of parents
224 // let as_gameobject = old_camera_read.cast_gameobject_arc_rwlock(old_camera.clone());
225 // match parent.clone() {
226 // ParentWrapper::GameObject(p) => unsafe {
227 // p.write().unwrap().replace_child(as_gameobject.clone(), replacement.clone()).unwrap();
228 // },
229 // ParentWrapper::Scene(_) => unsafe {
230 // scene_rw.replace_child(as_gameobject.clone(), replacement.clone()).unwrap();
231 // },
232 // }
233
234 // needed in the case that someone does not wish to have scripts on a main camera with scene parent and thus does not
235 // tell parent that camera is its child.
236 unsafe { replacement.write().unwrap().set_parent(parent); }
237
238 scene_rw.main_camera = Some(replacement.clone().read().unwrap().cast_camera_arc_rwlock(replacement.clone()).unwrap());
239
240 found = true;
241 }
242 }
243
244 if !found {
245 panic!("could not find the ID.");
246 }
247 },
248
249 Swap::Delete(id) => {
250 let mut found = false;
251 let mut queue = scene.read().unwrap().get_children().clone();
252 while let Some(old) = queue.pop() {
253 let read = old.read().unwrap(); // will not actually be changing the target object
254 queue.append(&mut read.get_children());
255 if read.get_id() == id {
256 let parent = read.get_parent();
257
258 // direct parent to the replacement
259 match parent.clone() { // shadowing
260 ParentWrapper::GameObject(p) => unsafe {
261 p.write().unwrap().remove_child(old.clone()).unwrap();
262 },
263 ParentWrapper::Scene(p) => unsafe {
264 p.write().unwrap().remove_child(old.clone()).unwrap();
265 }
266 }
267
268 found = true;
269 }
270 }
271
272 // Check Camera
273 if let Some(camera) = scene.read().unwrap().main_camera.clone() {
274 if id == camera.read().expect("camera in use").get_id() {
275 panic!("You can not delete the main camera. It can only be replaced.");
276 }
277 }
278
279 if !found {
280 panic!("could not find the ID.");
281 }
282 },
283 _ => { panic!("not possible"); }
284 }
285 });
286 }
287 }
288
289 #[inline(always)]
290 fn order_id(game_object: Arc<RwLock<dyn GameObject>>, n: &mut usize) -> Vec<(ID, usize)>{
291 let read_lock = game_object.read().unwrap();
292 let mut result: Vec<(ID, usize)> = vec![(read_lock.get_id(), *n)];
293 read_lock.get_children().into_iter().for_each(|child| {
294 *n -= 1;
295 result.append(&mut Self::order_id(child, n));
296 });
297 result
298 }
299
300 fn sort(swaps: &mut Vec<Swap>, scene: Arc<RwLock<Scene>>) {
301 let read_lock = scene.read().unwrap();
302
303 // sort by parent, children... , parent2, children2...
304 let mut order: Vec<(ID, usize)> = Vec::new();
305
306 // reverse to get ...children2, parent2, ...children, parent
307 let mut n = usize::MAX;
308 read_lock.get_children().into_iter().for_each(|child| {
309 order.append(&mut Self::order_id(child, &mut n));
310 });
311
312 let hash_map: HashMap<ID, usize> = order.into_iter().collect();
313
314 swaps.par_sort_unstable_by_key(|swap| hash_map.get(swap.get_id().unwrap()));
315 }
316}