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(
36        data: &mut HashTypeId2Data,
37        render_pass: &'a mut wgpu::RenderPass<'a>,
38    ) -> &'a mut wgpu::RenderPass<'a>;
39}
40
41/// Render -> Scene
42///        -> Scene is impl Queue (mean its process in sequence)
43///        -> Queue just inroduce your Scene
44pub trait Queue {
45    fn introduce(scene: &mut Scene);
46}
47
48/// get res from hashmap by type into box data
49pub fn get_res<T: Any + 'static>(data: &HashTypeId2Data) -> &T {
50    data.get(&TypeId::of::<T>())
51        .and_then(|data| data.downcast_ref::<T>())
52        .expect(&format!(
53            "Failed to get resource of type: {}",
54            std::any::type_name::<T>()
55        ))
56}
57/// get ref mut from hashmap by type into box data
58pub fn get_res_mut<T: Any + 'static>(data: &mut HashTypeId2Data) -> &mut T {
59    data.get_mut(&TypeId::of::<T>())
60        .and_then(|data| data.downcast_mut::<T>())
61        .expect(&format!(
62            "Failed to get mutable resource of type: {}",
63            std::any::type_name::<T>()
64        ))
65}
66
67/// get ref and mut from hashmap by type into box data
68pub fn get_ref_and_mut<Ref: Any + 'static, Mut: Any + 'static>(
69    data: &mut HashTypeId2Data,
70) -> (&Ref, &mut Mut) {
71    assert_ne!(
72        TypeId::of::<Ref>(),
73        TypeId::of::<Mut>(),
74        "Ref and Mut should not be the same type"
75    );
76    unsafe {
77        let data_ptr = data as *mut HashTypeId2Data;
78        let t1 = (&*data_ptr)
79            .get(&TypeId::of::<Ref>())
80            .and_then(|r| r.downcast_ref::<Ref>())
81            .expect(&format!(
82                "Failed to get resource of type: {}",
83                std::any::type_name::<Ref>()
84            ));
85        let t2 = (&mut *data_ptr)
86            .get_mut(&TypeId::of::<Mut>())
87            .and_then(|d| d.downcast_mut::<Mut>())
88            .expect(&format!(
89                "Failed to get mutable resource of type: {}",
90                std::any::type_name::<Mut>()
91            ));
92        (t1, t2)
93    }
94}
95
96/// create a new box data of type in hashmap (directly cover)
97pub fn return_res<T: Any + 'static>(data: &mut HashMap<TypeId, Box<dyn Any>>, new_data: T) {
98    data.insert(TypeId::of::<T>(), Box::new(new_data));
99}
100
101pub struct Scene {
102    readys: Vec<TypeId>,
103    paints: Vec<TypeId>,
104    readys_hashmap: HashMap<TypeId, Box<dyn FnMut(&mut HashMap<TypeId, Box<dyn Any>>, &Gfx)>>,
105    paints_hashmap: HashMap<TypeId, Box<dyn FnMut(&mut HashMap<TypeId, Box<dyn Any>>, &Gfx)>>,
106    res: HashMap<TypeId, Box<dyn Any>>,
107    name: String,
108}
109impl Scene {
110    pub fn get_name(&self) -> &str {
111        &self.name
112    }
113    pub fn new(name: impl Into<String>) -> Self {
114        Scene {
115            res: HashMap::new(),
116            paints_hashmap: HashMap::new(),
117            readys: Vec::new(),
118            name: name.into(),
119            paints: Vec::new(),
120            readys_hashmap: HashMap::new(),
121        }
122    }
123
124    pub fn add_ready<T: Ready + Default + 'static>(&mut self, mut ready_res: T) -> &mut Self {
125        let type_id = TypeId::of::<T>();
126        self.readys.push(type_id);
127        self.res.insert(type_id, Box::new(T::default()));
128        self.readys_hashmap.insert(
129            type_id,
130            Box::new(move |data, gfx| {
131                ready_res.ready(data, gfx);
132            }),
133        );
134
135        self
136    }
137
138    pub fn add_paint<T: Paint + 'static>(&mut self) {
139        let type_id = TypeId::of::<T>();
140        self.paints.push(type_id);
141        self.paints_hashmap.insert(type_id, Box::new(T::paint));
142    }
143
144    pub fn ready(&mut self, gfx: &Gfx) {
145        println!("<Scene>::ready");
146        for ready_type_id in self.readys.iter() {
147            if let Some(ready_fn) = self.readys_hashmap.get_mut(ready_type_id) {
148                ready_fn(&mut self.res, gfx);
149            }
150        }
151    }
152
153    pub fn paint(&mut self, gfx: &Gfx) {
154        for paint_type_id in self.paints.iter() {
155            if let Some(paint_fn) = self.paints_hashmap.get_mut(paint_type_id) {
156                paint_fn(&mut self.res, gfx);
157            }
158        }
159    }
160}