Skip to main content

macroquad_ply/experimental/
scene.rs

1use 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        // "used" is now moved to RefMut and will be invalidated by RefMut's drop
220        // no need for RefMutAny's drop than
221        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        // https://medium.com/@tglaiel/how-to-make-your-game-run-at-60fps-24c61210fe75x
496        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
612/// Get node and panic if the node is borrowed or deleted
613pub 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}