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 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}