ready_paint/
scene.rs

1use crate::gfx::Gfx;
2use std::{
3    any::{Any, TypeId},
4    collections::HashMap,
5};
6pub type HashTypeId2Data = HashMap<TypeId, Box<dyn Any>>;
7/// Render -> Scene
8///        -> Scene is impl Queue (mean its process in sequence)
9///        -> Queue just inroduce your Scene
10/// Ready And Paint in Scene
11///        -> [[add_ready, add_ready, ..],
12pub trait Ready {
13    fn ready(&mut self, data: &mut HashTypeId2Data, gfx: &Gfx);
14}
15/// Paint can handle lots of code
16/// you can use Update or Pass to reduce code in Paint
17/// fn paint will be called at frame render
18pub trait Paint {
19    fn paint(data: &mut HashTypeId2Data, gfx: &Gfx);
20}
21/// running in Paint function {
22///    [update, update, ..]
23///       (may also have)
24///    [{pass}, {pass}, ..]
25/// }
26pub trait Update {
27    fn update(data: &mut HashTypeId2Data, gfx: &Gfx);
28}
29/// running in Paint function {
30///    [update, update, ..]
31///       (may also have)
32///    [{pass}, {pass}, ..]
33/// }
34pub trait Pass<'a> {
35    fn pass(data: &mut HashTypeId2Data, render_pass: wgpu::RenderPass<'a>) -> wgpu::RenderPass<'a>;
36}
37
38/// Render -> Scene
39///        -> Scene is impl Queue (mean its process in sequence)
40///        -> Queue just inroduce your Scene
41pub trait Queue {
42    fn introduce(scene: &mut Scene);
43}
44
45/// get res from hashmap by type into box data
46pub fn get_res<T: Any + 'static>(data: &HashTypeId2Data) -> &T {
47    data.get(&TypeId::of::<T>())
48        .and_then(|data| data.downcast_ref::<T>())
49        .expect(&format!(
50            "Failed to get resource of type: {}",
51            std::any::type_name::<T>()
52        ))
53}
54/// get ref mut from hashmap by type into box data
55pub fn get_res_mut<T: Any + 'static>(data: &mut HashTypeId2Data) -> &mut T {
56    data.get_mut(&TypeId::of::<T>())
57        .and_then(|data| data.downcast_mut::<T>())
58        .expect(&format!(
59            "Failed to get mutable resource of type: {}",
60            std::any::type_name::<T>()
61        ))
62}
63
64/// get ref and mut from hashmap by type into box data
65pub fn get_ref_and_mut<Ref: Any + 'static, Mut: Any + 'static>(
66    data: &mut HashTypeId2Data,
67) -> (&Ref, &mut Mut) {
68    assert_ne!(
69        TypeId::of::<Ref>(),
70        TypeId::of::<Mut>(),
71        "Ref and Mut should not be the same type"
72    );
73    unsafe {
74        let data_ptr = data as *mut HashTypeId2Data;
75        let t1 = (&*data_ptr)
76            .get(&TypeId::of::<Ref>())
77            .and_then(|r| r.downcast_ref::<Ref>())
78            .expect(&format!(
79                "Failed to get resource of type: {}",
80                std::any::type_name::<Ref>()
81            ));
82        let t2 = (&mut *data_ptr)
83            .get_mut(&TypeId::of::<Mut>())
84            .and_then(|d| d.downcast_mut::<Mut>())
85            .expect(&format!(
86                "Failed to get mutable resource of type: {}",
87                std::any::type_name::<Mut>()
88            ));
89        (t1, t2)
90    }
91}
92
93/// create a new box data of type in hashmap (directly cover)
94pub fn return_res<T: Any + 'static>(data: &mut HashMap<TypeId, Box<dyn Any>>, new_data: T) {
95    data.insert(TypeId::of::<T>(), Box::new(new_data));
96}
97
98pub struct Scene {
99    name: String,
100    res: HashMap<TypeId, Box<dyn Any>>,
101    readys: Vec<TypeId>,
102    paints: Vec<TypeId>,
103    readys_hashmap: HashMap<TypeId, Box<dyn FnMut(&mut HashMap<TypeId, Box<dyn Any>>, &Gfx)>>,
104    paints_hashmap: HashMap<TypeId, Box<dyn Fn(&mut HashMap<TypeId, Box<dyn Any>>, &Gfx)>>,
105}
106
107impl Scene {
108    pub fn new(name: String) -> Self {
109        Scene {
110            name,
111            res: HashMap::new(),
112            readys: Vec::new(),
113            paints: Vec::new(),
114            readys_hashmap: HashMap::new(),
115            paints_hashmap: HashMap::new(),
116        }
117    }
118
119    pub fn get_name(&self) -> &str {
120        &self.name
121    }
122
123    pub fn add_ready<T: Ready + Default + 'static>(&mut self, mut ready_res: T) -> &mut Self {
124        let type_id = TypeId::of::<T>();
125        self.readys.push(type_id);
126        self.res.insert(type_id, Box::new(T::default()));
127        self.readys_hashmap.insert(
128            type_id,
129            Box::new(move |data, gfx| {
130                ready_res.ready(data, gfx);
131            }),
132        );
133
134        self
135    }
136
137    pub fn add_paint<T: Paint + 'static>(&mut self) {
138        let type_id = TypeId::of::<T>();
139        self.paints.push(type_id);
140        self.paints_hashmap.insert(type_id, Box::new(T::paint));
141    }
142
143    pub fn ready(&mut self, gfx: &Gfx) {
144        println!("<Scene>::ready");
145        for ready_type_id in self.readys.iter() {
146            if let Some(ready_fn) = self.readys_hashmap.get_mut(ready_type_id) {
147                ready_fn(&mut self.res, gfx);
148            }
149        }
150    }
151
152    pub fn paint(&mut self, gfx: &Gfx) {
153        for paint_type_id in self.paints.iter() {
154            if let Some(paint_fn) = self.paints_hashmap.get_mut(paint_type_id) {
155                paint_fn(&mut self.res, gfx);
156            }
157        }
158    }
159}