macroquad_ply/experimental/
scene.rs1use std::{any::Any, marker::PhantomData, ops::Drop};
2
3use crate::camera::Camera2D;
4
5pub use macroquad_macro::CapabilityTrait;
6
7mod arena;
8
9#[rustfmt::skip]
10pub trait Node {
11 fn ready(_node: RefMut<Self>) where Self: Sized {}
12 fn update(_node: RefMut<Self>) where Self: Sized {}
13 fn fixed_update(_node: RefMut<Self>) where Self: Sized {}
14 fn draw(_node: RefMut<Self>) where Self: Sized {}
15}
16
17trait NodeAny: Any + Node {
18 fn as_any(&self) -> &dyn Any;
19 fn as_any_mut(&mut self) -> &mut dyn Any;
20}
21
22impl<T: Node + 'static> NodeAny for T {
23 fn as_any(&self) -> &dyn Any {
24 self
25 }
26 fn as_any_mut(&mut self) -> &mut dyn Any {
27 self
28 }
29}
30
31#[derive(Clone, Copy, Debug, PartialEq)]
32struct Id {
33 id: usize,
34 generation: u64,
35}
36
37pub struct Handle<T: 'static> {
38 id: Option<Id>,
39 _marker: PhantomData<T>,
40}
41
42unsafe impl<T: 'static> Send for Handle<T> {}
43
44#[derive(Clone, Copy, Debug)]
45pub struct HandleUntyped(Id);
46
47impl<T: 'static> std::fmt::Debug for Handle<T> {
48 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
49 write!(f, "{:?}", self.id)?;
50
51 Ok(())
52 }
53}
54
55impl<T: 'static> Clone for Handle<T> {
56 fn clone(&self) -> Handle<T> {
57 Handle {
58 id: self.id,
59 _marker: PhantomData,
60 }
61 }
62}
63
64impl<T: 'static> Copy for Handle<T> {}
65
66impl<T> Handle<T> {
67 pub const fn null() -> Handle<T> {
68 Handle {
69 id: None,
70 _marker: PhantomData,
71 }
72 }
73
74 pub fn untyped(&self) -> HandleUntyped {
75 HandleUntyped(self.id.unwrap())
76 }
77
78 pub const fn as_trait<T1: ?Sized>(&self) {}
79}
80
81pub(crate) struct Lens<T> {
82 handle: HandleUntyped,
83 offset: isize,
84 _marker: PhantomData<T>,
85}
86
87impl<T> Lens<T> {
88 pub fn get(&mut self) -> Option<&mut T> {
89 let node = get_untyped_node(self.handle)?;
90
91 Some(unsafe { &mut *((node.data as *mut u8).offset(self.offset) as *mut T) })
92 }
93}
94
95impl<T> Handle<T> {
96 pub(crate) fn lens<F, T1>(&self, f: F) -> Lens<T1>
97 where
98 F: for<'r> FnOnce(&'r mut T) -> &'r mut T1,
99 {
100 assert!(self.id.is_some());
101
102 let offset = unsafe {
103 let mut base = std::mem::MaybeUninit::<T>::uninit();
104 let field = f(std::mem::transmute(base.as_mut_ptr())) as *mut _ as *mut u8;
105
106 (field as *mut u8).offset_from(base.as_mut_ptr() as *mut u8)
107 };
108
109 Lens {
110 handle: HandleUntyped(self.id.unwrap()),
111 offset,
112 _marker: PhantomData,
113 }
114 }
115}
116
117pub struct NodeWith<T> {
118 pub node: HandleUntyped,
119 pub capability: T,
120}
121
122pub struct RefMut<T: 'static> {
123 data: *mut T,
124 handle: Handle<T>,
125 capabilities: *mut Vec<Box<dyn Any>>,
126 used: *mut bool,
127}
128
129impl<T: 'static> RefMut<T> {
130 pub const fn handle(&self) -> Handle<T> {
131 Handle {
132 id: self.handle.id,
133 _marker: PhantomData,
134 }
135 }
136
137 pub fn persist(&self) {
138 unsafe { get_scene() }.nodes[self.handle.id.unwrap().id]
139 .as_mut()
140 .unwrap()
141 .permanent = true;
142 }
143
144 pub fn provides<S: std::any::Any + Copy>(&mut self, x: S) {
145 unsafe { (*self.capabilities).push(Box::new(x)) };
146 }
147
148 pub fn delete(self) {
149 assert!(self.handle.id.is_some());
150
151 unsafe {
152 *self.used = false;
153 }
154 unsafe { get_scene() }.delete(self.handle.id.unwrap());
155 std::mem::forget(self);
156 }
157}
158
159impl<T> std::ops::Deref for RefMut<T> {
160 type Target = T;
161
162 fn deref(&self) -> &T {
163 unsafe { &*self.data }
164 }
165}
166
167impl<T> std::ops::DerefMut for RefMut<T> {
168 fn deref_mut(&mut self) -> &mut T {
169 unsafe { &mut *self.data }
170 }
171}
172
173impl<T: 'static> Drop for RefMut<T> {
174 fn drop(&mut self) {
175 assert_eq!(unsafe { *self.used }, true);
176 unsafe {
177 *self.used = false;
178 }
179 }
180}
181
182pub struct RefMutAny<'a> {
183 data: *mut (),
184 used: *mut bool,
185 vtable: *mut (),
186 capabilities: *mut Vec<Box<dyn Any>>,
187 handle: HandleUntyped,
188
189 _marker: PhantomData<&'a ()>,
190}
191
192impl<'a> RefMutAny<'a> {
193 pub const fn handle<T>(&self) -> Handle<T> {
194 Handle {
195 id: Some(self.handle.0),
196 _marker: PhantomData,
197 }
198 }
199
200 pub fn delete(self) {
201 unsafe {
202 *self.used = false;
203 }
204 unsafe { get_scene() }.delete(self.handle.0);
205 std::mem::forget(self);
206 }
207
208 pub fn to_typed<T>(self) -> RefMut<T> {
209 let res = RefMut {
210 data: self.data as *mut T,
211 handle: Handle {
212 id: Some(self.handle.0),
213 _marker: PhantomData::<T>,
214 },
215 capabilities: self.capabilities,
216 used: self.used,
217 };
218
219 std::mem::forget(self);
222
223 res
224 }
225}
226
227impl<'a> std::ops::Deref for RefMutAny<'a> {
228 type Target = dyn Any;
229
230 fn deref(&self) -> &Self::Target {
231 let trait_obj: &dyn NodeAny = unsafe { std::mem::transmute((self.data, self.vtable)) };
232
233 trait_obj.as_any()
234 }
235}
236
237impl<'a> std::ops::DerefMut for RefMutAny<'a> {
238 fn deref_mut(&mut self) -> &mut dyn Any {
239 let trait_obj: &mut dyn NodeAny = unsafe { std::mem::transmute((self.data, self.vtable)) };
240
241 trait_obj.as_any_mut()
242 }
243}
244
245impl<'a> Drop for RefMutAny<'a> {
246 fn drop(&mut self) {
247 assert_eq!(unsafe { *self.used }, true);
248
249 unsafe {
250 *self.used = false;
251 }
252 }
253}
254
255struct Cell {
256 id: Id,
257 data: *mut (),
258 vtable: *mut (),
259 capabilities: Vec<Box<dyn Any>>,
260 ready: *const fn(RefMut<()>),
261 update: *const fn(RefMut<()>),
262 fixed_update: *const fn(RefMut<()>),
263 draw: *const fn(RefMut<()>),
264 virtual_drop: *const fn(*mut ()),
265 data_len: usize,
266 permanent: bool,
267 initialized: bool,
268 used: *mut bool,
269}
270
271unsafe impl Sync for Scene {}
272
273fn virtual_drop<T: Node + 'static>(data: *mut ()) {
274 unsafe {
275 std::ptr::drop_in_place(data as *mut T);
276 }
277}
278
279impl Cell {
280 fn new<T: Node + 'static>(id: Id, data: *mut (), vtable: *mut (), used: *mut bool) -> Self {
281 Cell {
282 id,
283 data,
284 vtable,
285 capabilities: vec![],
286 used,
287 permanent: false,
288 ready: (&(Node::ready as fn(RefMut<T>)) as *const fn(RefMut<T>)).cast(),
289 update: (&(Node::update as fn(RefMut<T>)) as *const fn(RefMut<T>)).cast(),
290 fixed_update: (&(Node::fixed_update as fn(RefMut<T>)) as *const fn(RefMut<T>)).cast(),
291 draw: (&(Node::draw as fn(RefMut<T>)) as *const fn(RefMut<T>)).cast(),
292 virtual_drop: &(virtual_drop::<T> as fn(*mut ())) as *const fn(*mut ()),
293 data_len: size_of::<T>(),
294 initialized: false,
295 }
296 }
297
298 fn update<T: Node + 'static>(&mut self, data: T) {
299 assert!(size_of::<T>() <= self.data_len);
300
301 let trait_obj = &data as &dyn NodeAny;
302 let (_, vtable) = unsafe { std::mem::transmute::<_, (*mut (), *mut ())>(trait_obj) };
303
304 self.vtable = vtable;
305 self.ready = (&(Node::ready as fn(RefMut<T>)) as *const fn(RefMut<T>)).cast();
306 self.update = (&(Node::update as fn(RefMut<T>)) as *const fn(RefMut<T>)).cast();
307 self.fixed_update = (&(Node::fixed_update as fn(RefMut<T>)) as *const fn(RefMut<T>)).cast();
308 self.draw = (&(Node::draw as fn(RefMut<T>)) as *const fn(RefMut<T>)).cast();
309 self.virtual_drop = &(virtual_drop::<T> as fn(*mut ())) as *const fn(*mut ());
310
311 unsafe {
312 std::ptr::copy_nonoverlapping::<T>(&data as *const _ as *mut _, self.data as *mut _, 1);
313 }
314 self.id.generation += 1;
315 self.initialized = false;
316 self.permanent = false;
317
318 self.capabilities.clear();
319
320 std::mem::forget(data);
321 }
322}
323
324struct Scene {
325 dense: Vec<Id>,
326 dense_ongoing: Vec<Result<Id, Id>>,
327 nodes: Vec<Option<Cell>>,
328 arena: arena::Arena,
329 camera: [Option<Camera2D>; 4],
330 camera_pos: crate::Vec2,
331
332 acc: f64,
333 current_time: f64,
334 in_fixed_update: bool,
335
336 any_map: std::collections::HashMap<std::any::TypeId, Vec<(HandleUntyped, *mut u8)>>,
337 free_nodes: Vec<Cell>,
338}
339
340impl Scene {
341 pub fn new() -> Self {
342 Scene {
343 dense: vec![],
344 dense_ongoing: vec![],
345 nodes: Vec::new(),
346 arena: arena::Arena::new(),
347 free_nodes: Vec::new(),
348 camera: [Some(Camera2D::default()), None, None, None],
349 camera_pos: crate::vec2(0., 0.),
350 acc: 0.0,
351 current_time: crate::time::get_time(),
352 in_fixed_update: false,
353 any_map: std::collections::HashMap::new(),
354 }
355 }
356
357 pub fn clear(&mut self) {
358 self.any_map.clear();
359
360 for cell in &mut self.nodes {
361 if let Some(Cell {
362 permanent: false, ..
363 }) = cell
364 {
365 if let Some(cell) = cell.take() {
366 assert!(unsafe { *cell.used == false });
367
368 unsafe {
369 (*cell.virtual_drop)(cell.data);
370 }
371 let ix = self.dense.iter().position(|i| *i == cell.id).unwrap();
372 self.dense.remove(ix);
373
374 self.free_nodes.push(cell);
375 }
376 }
377 }
378 }
379
380 pub fn get_any(&mut self, handle: HandleUntyped) -> Option<RefMutAny> {
381 let handle = handle.0;
382 let cell = self.nodes.get_mut(handle.id)?;
383
384 if cell.is_none() {
385 return None;
386 }
387 let cell = cell.as_mut().unwrap();
388
389 if cell.id.generation != handle.generation {
390 return None;
391 }
392
393 if unsafe { *cell.used } {
394 return None;
395 }
396
397 unsafe { *cell.used = true };
398
399 Some(RefMutAny {
400 data: cell.data,
401 vtable: cell.vtable,
402 capabilities: &mut cell.capabilities as _,
403 handle: HandleUntyped(cell.id),
404 used: cell.used,
405
406 _marker: PhantomData,
407 })
408 }
409
410 pub fn get<T>(&mut self, handle: Handle<T>) -> Option<RefMut<T>> {
411 let ref_mut_any = self.get_any(HandleUntyped(handle.id?))?;
412 Some(ref_mut_any.to_typed())
413 }
414
415 fn iter(&self) -> MagicVecIterator {
416 MagicVecIterator {
417 n: 0,
418 len: self.dense.len(),
419 }
420 }
421
422 fn add_node<T: Node + 'static>(&mut self, data: T) -> Handle<T> {
423 let id;
424
425 if let Some(i) = self
426 .free_nodes
427 .iter()
428 .position(|free_node| free_node.data_len >= size_of::<T>())
429 {
430 let mut free_node = self.free_nodes.remove(i);
431
432 free_node.update::<T>(data);
433
434 id = free_node.id;
435
436 self.nodes[id.id] = Some(free_node);
437 } else {
438 let trait_obj = &data as &dyn NodeAny;
439 let (_, vtable) = unsafe { std::mem::transmute::<_, (*mut (), *mut ())>(trait_obj) };
440
441 let ptr = self.arena.alloc(size_of::<T>()) as *mut _ as *mut T;
442 unsafe {
443 std::ptr::write(ptr, data);
444 }
445 let ptr = ptr as *mut ();
446 let used = self.arena.alloc(1) as *mut _ as *mut bool;
447 unsafe {
448 std::ptr::write(used, false);
449 }
450 let used = used as *mut _ as *mut bool;
451
452 id = Id {
453 id: self.nodes.len(),
454 generation: 0,
455 };
456 self.nodes.push(Some(Cell::new::<T>(id, ptr, vtable, used)));
457 }
458
459 self.dense.push(id);
460
461 Handle {
462 id: Some(id),
463 _marker: PhantomData,
464 }
465 }
466
467 pub fn delete(&mut self, id: Id) {
468 if let Some(node) = self.nodes[id.id].take() {
469 assert_eq!(node.id.generation, id.generation);
470
471 self.dense_ongoing.push(Err(id));
472
473 unsafe {
474 (*node.virtual_drop)(node.data);
475 }
476 self.free_nodes.push(node);
477 }
478 }
479
480 pub fn update(&mut self) {
481 for node in &mut self.iter() {
482 let cell = self.nodes[node.handle.0.id].as_mut().unwrap();
483 if cell.initialized == false {
484 cell.initialized = true;
485
486 let node: RefMut<()> = node.to_typed::<()>();
487 unsafe { (*cell.ready)(node) };
488 }
489 }
490
491 let new_time = crate::time::get_time();
492
493 let mut frame_time = new_time - self.current_time;
494
495 if (frame_time - 1.0 / 120.0).abs() < 0.0002 {
497 frame_time = 1.0 / 120.0;
498 } else if (frame_time - 1.0 / 60.0).abs() < 0.0002 {
499 frame_time = 1.0 / 60.0;
500 } else if (frame_time - 1.0 / 30.0).abs() < 0.0002 {
501 frame_time = 1.0 / 30.0;
502 }
503
504 self.current_time = new_time;
505 self.acc += frame_time;
506
507 for node in &mut self.iter() {
508 let cell = self.nodes[node.handle.0.id].as_mut().unwrap();
509 let node: RefMut<()> = node.to_typed::<()>();
510 unsafe { (*cell.update)(node) };
511 }
512
513 while self.acc > CONST_FPS {
514 self.acc -= CONST_FPS;
515 for node in &mut self.iter() {
516 let cell = self.nodes[node.handle.0.id].as_mut().unwrap();
517 let node: RefMut<()> = node.to_typed::<()>();
518
519 self.in_fixed_update = true;
520 unsafe { (*cell.fixed_update)(node) };
521 self.in_fixed_update = false;
522 }
523 }
524
525 for camera in self.camera.iter() {
526 if let Some(camera) = camera {
527 self.camera_pos = camera.target;
528 crate::prelude::push_camera_state();
529 crate::prelude::set_camera(&*camera);
530
531 for node in &mut self.iter() {
532 let cell = self.nodes[node.handle.0.id].as_mut().unwrap();
533 let node: RefMut<()> = node.to_typed::<()>();
534 unsafe { (*cell.draw)(node) };
535 }
536
537 crate::prelude::pop_camera_state();
538 }
539 }
540
541 for id in self.dense_ongoing.drain(0..) {
542 match id {
543 Ok(id) => {
544 self.dense.push(id);
545 }
546 Err(id) => {
547 let ix = self.dense.iter().position(|i| *i == id).unwrap();
548 self.dense.remove(ix);
549 }
550 }
551 }
552 }
553}
554
555pub struct MagicVecIterator {
556 n: usize,
557 len: usize,
558}
559
560impl Iterator for MagicVecIterator {
561 type Item = RefMutAny<'static>;
562
563 fn next(&mut self) -> Option<RefMutAny<'static>> {
564 let scene = unsafe { get_scene() };
565 let nodes = &mut scene.nodes;
566 let dense = &scene.dense;
567 if self.n >= self.len {
568 return None;
569 }
570 let ix = dense[self.n];
571 let cell = &mut nodes[ix.id];
572 self.n += 1;
573
574 if cell.is_none() {
575 return self.next();
576 }
577 let cell = cell.as_mut().unwrap();
578
579 if unsafe { *cell.used } {
580 return self.next();
581 }
582
583 unsafe { *cell.used = true };
584
585 Some(RefMutAny {
586 data: cell.data,
587 vtable: cell.vtable,
588 capabilities: &mut cell.capabilities as _,
589 handle: HandleUntyped(cell.id),
590 used: cell.used,
591 _marker: PhantomData,
592 })
593 }
594}
595
596static mut SCENE: Option<Scene> = None;
597
598unsafe fn get_scene() -> &'static mut Scene {
599 SCENE.get_or_insert_with(|| Scene::new())
600}
601
602pub(crate) fn allocated_memory() -> usize {
603 unsafe { get_scene().arena.offset() }
604}
605
606pub fn clear() {
607 crate::experimental::coroutines::stop_all_coroutines();
608
609 unsafe { get_scene() }.clear()
610}
611
612pub fn get_node<T: Node>(handle: Handle<T>) -> RefMut<T> {
614 unsafe { get_scene() }
615 .get(handle)
616 .expect(&format!("No such node: {:?}", handle.id))
617}
618
619pub fn try_get_node<T: Node>(handle: Handle<T>) -> Option<RefMut<T>> {
620 unsafe { get_scene() }.get(handle)
621}
622
623pub fn get_untyped_node(handle: HandleUntyped) -> Option<RefMutAny<'static>> {
624 unsafe { get_scene() }.get_any(handle)
625}
626
627pub fn camera_pos() -> crate::Vec2 {
628 unsafe { get_scene() }.camera_pos
629}
630
631pub fn set_camera(n: usize, camera: Option<Camera2D>) {
632 assert!(n <= 4);
633 unsafe { get_scene() }.camera[n] = camera;
634}
635
636pub fn add_node<T: Node>(node: T) -> Handle<T> {
637 unsafe { get_scene() }.add_node(node)
638}
639
640pub(crate) fn update() {
641 unsafe { get_scene() }.update()
642}
643
644pub fn all_nodes() -> MagicVecIterator {
645 unsafe { get_scene() }.iter()
646}
647
648pub fn find_node_by_type<T: Any>() -> Option<RefMut<T>> {
649 unsafe { get_scene() }
650 .iter()
651 .find(|node| node.is::<T>())
652 .map(|node| node.to_typed())
653}
654
655pub fn find_nodes_with<T: Any + Copy>() -> impl Iterator<Item = NodeWith<T>> {
656 unsafe {
657 get_scene().iter().filter_map(|node| {
658 (*node.capabilities)
659 .iter()
660 .find(|capability| capability.is::<T>())
661 .map(|capability| NodeWith {
662 node: node.handle,
663 capability: *capability.downcast_ref::<T>().unwrap(),
664 })
665 })
666 }
667}
668
669pub fn find_nodes_by_type<T: Any>() -> impl Iterator<Item = RefMut<T>> {
670 unsafe { get_scene() }
671 .iter()
672 .filter(|node| node.is::<T>())
673 .map(|node| node.to_typed())
674}
675
676const CONST_FPS: f64 = 1.0 / 60.;
677
678pub(crate) fn in_fixed_update() -> bool {
679 unsafe { get_scene() }.in_fixed_update
680}
681
682pub(crate) const fn fixed_frame_time() -> f32 {
683 CONST_FPS as _
684}