makepad_platform/
pass.rs

1use crate::{
2    makepad_live_compiler::{
3        LiveType,
4        LiveNode,
5        LiveId,
6        LiveModuleId,
7        LiveTypeInfo,
8        LiveNodeSliceApi
9    },
10    live_traits::{LiveNew, LiveApply, ApplyFrom},
11    makepad_live_tokenizer::{LiveErrorOrigin, live_error_origin},
12    makepad_live_id::*,
13    makepad_math::*,
14    id_pool::*,
15    area::Area,
16    window::WindowId,
17    os::CxOsPass,
18    cx::Cx,
19    draw_list::DrawListId,
20    live_traits::*,
21    texture::{
22        Texture,
23        TextureId
24    }
25};
26
27#[derive(Debug)]
28pub struct Pass(PoolId);
29
30#[derive(Clone, Copy, Debug, PartialEq)]
31pub struct PassId(pub (crate) usize);
32
33impl Pass {
34}
35
36#[derive(Default)]
37pub struct CxPassPool(pub (crate) IdPool<CxPass>);
38impl CxPassPool {
39    fn alloc(&mut self) -> Pass {
40        Pass(self.0.alloc())
41    }
42    
43    pub fn id_iter(&self) -> PassIterator {
44        PassIterator {
45            cur: 0,
46            len: self.0.pool.len()
47        }
48    }
49}
50
51pub struct PassIterator {
52    cur: usize,
53    len: usize
54}
55
56impl Iterator for PassIterator {
57    type Item = PassId;
58    fn next(&mut self) -> Option<Self::Item> {
59        if self.cur >= self.len {
60            return None;
61        }
62        let cur = self.cur;
63        self.cur += 1;
64        Some(PassId(cur))
65    }
66}
67
68impl std::ops::Index<PassId> for CxPassPool {
69    type Output = CxPass;
70    fn index(&self, index: PassId) -> &Self::Output {
71        &self.0.pool[index.0].item
72    }
73}
74
75impl std::ops::IndexMut<PassId> for CxPassPool {
76    fn index_mut(&mut self, index: PassId) -> &mut Self::Output {
77        &mut self.0.pool[index.0].item
78    }
79}
80
81impl LiveHook for Pass {}
82impl LiveNew for Pass {
83    fn live_design_with(_cx:&mut Cx){}
84    fn new(cx: &mut Cx) -> Self {
85        let pass = cx.passes.alloc();
86        pass
87    }
88    
89    fn live_type_info(_cx: &mut Cx) -> LiveTypeInfo {
90        LiveTypeInfo {
91            module_id: LiveModuleId::from_str(&module_path!()).unwrap(),
92            live_type: LiveType::of::<Self>(),
93            fields: Vec::new(),
94            live_ignore: true,
95            //kind: LiveTypeKind::Object,
96            type_name: id_lut!(Pass)
97        }
98    }
99}
100
101impl LiveApply for Pass {
102    
103    fn apply(&mut self, cx: &mut Cx, from: ApplyFrom, start_index: usize, nodes: &[LiveNode]) -> usize {
104        
105        if !nodes[start_index].value.is_structy_type() {
106            cx.apply_error_wrong_type_for_struct(live_error_origin!(), start_index, nodes, live_id!(View));
107            return nodes.skip_node(start_index);
108        }
109        
110        let mut index = start_index + 1;
111        loop {
112            if nodes[index].value.is_close() {
113                index += 1;
114                break;
115            }
116            match nodes[index].id {
117                live_id!(clear_color) => cx.passes[self.pass_id()].clear_color = LiveNew::new_apply_mut_index(cx, from, &mut index, nodes),
118                live_id!(dont_clear) => cx.passes[self.pass_id()].dont_clear = LiveNew::new_apply_mut_index(cx, from, &mut index, nodes),
119                _ => {
120                    cx.apply_error_no_matching_field(live_error_origin!(), index, nodes);
121                    index = nodes.skip_node(index);
122                }
123            }
124        }
125        return index;
126    }
127}
128
129impl Pass {
130    pub fn id_equals(&self, id:usize)->bool{
131        self.0.id == id
132    }
133    
134    pub fn new_with_name(cx: &mut Cx, name:&str) -> Self {
135        let pass = cx.passes.alloc();
136        pass.set_pass_name(cx, name);
137        pass
138    }
139    
140    pub fn pass_id(&self) -> PassId {PassId(self.0.id)}
141    
142    pub fn set_pass_parent(&self, cx: &mut Cx, pass: &Pass) {
143        let cxpass = &mut cx.passes[self.pass_id()];
144        cxpass.parent = CxPassParent::Pass(pass.pass_id());
145    }
146    
147    pub fn set_pass_name(&self, cx: &mut Cx, name: &str) {
148        let cxpass = &mut cx.passes[self.pass_id()];
149        cxpass.debug_name = name.to_string();
150    }
151    
152    pub fn pass_name<'a>(&self, cx: &'a mut Cx)->&'a str{
153        let cxpass = &mut cx.passes[self.pass_id()];
154        &cxpass.debug_name
155    }
156    
157    pub fn set_size(&self, cx: &mut Cx, pass_size: DVec2) {
158        let mut pass_size = pass_size;
159        if pass_size.x < 1.0 {pass_size.x = 1.0};
160        if pass_size.y < 1.0 {pass_size.y = 1.0};
161        let cxpass = &mut cx.passes[self.pass_id()];
162        cxpass.pass_rect = Some(CxPassRect::Size(pass_size));
163    }
164    
165    pub fn set_window_clear_color(&self, cx: &mut Cx, clear_color: Vec4) {
166        let cxpass = &mut cx.passes[self.pass_id()];
167        cxpass.clear_color = clear_color;
168    }
169    
170    pub fn clear_color_textures(&self, cx: &mut Cx) {
171        let cxpass = &mut cx.passes[self.pass_id()];
172        cxpass.color_textures.truncate(0);
173    }
174    
175    pub fn add_color_texture(&self, cx: &mut Cx, texture: &Texture, clear_color: PassClearColor) {
176        let cxpass = &mut cx.passes[self.pass_id()];
177        cxpass.color_textures.push(CxPassColorTexture {
178            texture_id: texture.texture_id(),
179            clear_color: clear_color
180        })
181    }
182    
183    pub fn set_depth_texture(&self, cx: &mut Cx, texture: &Texture, clear_depth: PassClearDepth) {
184        let cxpass = &mut cx.passes[self.pass_id()];
185        cxpass.depth_texture = Some(texture.texture_id());
186        cxpass.clear_depth = clear_depth;
187    }
188    
189    pub fn set_matrix_mode(&self, cx: &mut Cx, pmm: PassMatrixMode) {
190        let cxpass = &mut cx.passes[self.pass_id()];
191        cxpass.paint_dirty = true;
192        cxpass.matrix_mode = pmm;
193    }
194    
195    pub fn set_debug(&mut self, cx: &mut Cx, debug: bool) {
196        let cxpass = &mut cx.passes[self.pass_id()];
197        cxpass.debug = debug;
198    }
199    
200}
201
202#[derive(Clone)]
203pub enum PassClearColor {
204    InitWith(Vec4),
205    ClearWith(Vec4)
206}
207
208impl Default for PassClearColor {
209    fn default() -> Self {
210        Self::ClearWith(Vec4::default())
211    }
212}
213
214#[derive(Clone)]
215pub enum PassClearDepth {
216    InitWith(f32),
217    ClearWith(f32)
218}
219
220#[derive(Clone)]
221pub struct CxPassColorTexture {
222    pub clear_color: PassClearColor,
223    pub texture_id: TextureId
224}
225
226#[derive(Default, Clone)]
227#[repr(C)]
228pub struct PassUniforms {
229    camera_projection: Mat4,
230    camera_view: Mat4,
231    camera_inv: Mat4,
232    dpi_factor: f32,
233    dpi_dilate: f32,
234    time: f32,
235    pad2: f32
236}
237
238impl PassUniforms {
239    pub fn as_slice(&self) -> &[f32; std::mem::size_of::<PassUniforms>() >> 2] {
240        unsafe {std::mem::transmute(self)}
241    }
242}
243
244#[derive(Clone, Debug)]
245pub enum PassMatrixMode {
246    Ortho,
247    Projection {fov_y: f32, near: f32, far: f32, cam: Mat4}
248}
249
250#[derive(Clone)]
251pub enum CxPassRect {
252    Area(Area),
253    ScaledArea(Area,f64),
254    Size(DVec2)
255}
256
257#[derive(Clone)]
258pub struct CxPass {
259    pub debug: bool,
260    pub debug_name: String,
261    pub matrix_mode: PassMatrixMode,
262    pub color_textures: Vec<CxPassColorTexture>,
263    pub depth_texture: Option<TextureId>,
264    pub clear_depth: PassClearDepth,
265    pub dont_clear: bool,
266    pub depth_init: f64,
267    pub clear_color: Vec4,
268    pub dpi_factor: Option<f64>,
269    pub main_draw_list_id: Option<DrawListId>,
270    pub parent: CxPassParent,
271    pub paint_dirty: bool,
272    pub pass_rect: Option<CxPassRect>,
273    pub pass_uniforms: PassUniforms,
274    pub zbias_step: f32,
275    pub os: CxOsPass,
276}
277
278impl Default for CxPass {
279    fn default() -> Self {
280        CxPass {
281            debug: false,
282            dont_clear: false,
283            debug_name: String::new(),
284            matrix_mode: PassMatrixMode::Ortho,
285            zbias_step: 0.001,
286            pass_uniforms: PassUniforms::default(),
287            color_textures: Vec::new(),
288            depth_texture: None,
289            dpi_factor: None,
290            clear_depth: PassClearDepth::ClearWith(1.0),
291            clear_color: Vec4::default(),
292            depth_init: 1.0,
293            main_draw_list_id: None,
294            parent: CxPassParent::None,
295            paint_dirty: false,
296            pass_rect: None,
297            os: CxOsPass::default()
298        }
299    }
300}
301
302#[derive(Clone, Debug)]
303pub enum CxPassParent {
304    Window(WindowId),
305    Pass(PassId),
306    None
307}
308
309impl CxPass {
310    pub fn set_time(&mut self, time: f32) {
311        self.pass_uniforms.time = time;
312    }
313    
314    pub fn set_dpi_factor(&mut self, dpi_factor: f64) {
315        let dpi_dilate = (2. - dpi_factor).max(0.).min(1.);
316        self.pass_uniforms.dpi_factor = dpi_factor as f32;
317        self.pass_uniforms.dpi_dilate = dpi_dilate as f32;
318    }
319    
320    pub fn set_matrix(&mut self, offset: DVec2, size: DVec2) {
321        match self.matrix_mode {
322            PassMatrixMode::Ortho => {
323                let ortho = Mat4::ortho(
324                    offset.x as f32,
325                    (offset.x + size.x) as f32,
326                    offset.y as f32,
327                    (offset.y + size.y) as f32,
328                    100.,
329                    -100.,
330                    1.0,
331                    1.0
332                );
333                self.pass_uniforms.camera_projection = ortho;
334                self.pass_uniforms.camera_view = Mat4::identity();
335            }
336            PassMatrixMode::Projection {fov_y, near, far, cam} => {
337                let proj = Mat4::perspective(fov_y, (size.x / size.y) as f32, near, far);
338                self.pass_uniforms.camera_projection = proj;
339                self.pass_uniforms.camera_view = cam;
340            }
341        };
342    }
343}