makepad_draw/shader/
draw_quad.rs

1use {
2    crate::{
3        makepad_platform::*,
4        draw_list_2d::ManyInstances,
5        geometry::GeometryQuad2D,
6        cx_2d::Cx2d,
7        turtle::{Walk, Layout}
8    },
9};
10
11live_design!{
12    use link::shaders::*;
13    pub DrawQuad = {{DrawQuad}} {
14        varying pos: vec2
15        varying world: vec4,
16        fn clip_and_transform_vertex(self, rect_pos:vec2, rect_size:vec2) -> vec4 {
17            let clipped: vec2 = clamp(
18                clamp(
19                    self.geom_pos * rect_size + rect_pos,
20                    self.draw_clip.xy,
21                    self.draw_clip.zw
22                )
23                + self.view_shift,
24                self.view_clip.xy,
25                self.view_clip.zw
26            );
27            //clipped = self.geom_pos * rect_size + rect_pos;
28            self.pos = (clipped - rect_pos) / rect_size
29            self.world = self.view_transform * vec4(
30                clipped.x,
31                clipped.y,
32                self.draw_depth + self.draw_zbias,
33                1.
34            );
35            // only pass the clipped position forward
36            return self.camera_projection * (self.camera_view * (self.world))
37        }
38        
39        fn transform_vertex(self, rect_pos:vec2, rect_size:vec2) -> vec4 {
40            let clipped: vec2 = self.geom_pos * rect_size + rect_pos;
41            
42            self.pos = (clipped - rect_pos) / rect_size
43            // only pass the clipped position forward
44            self.world = self.view_transform * vec4(
45                clipped.x,
46                clipped.y,
47                self.draw_depth + self.draw_zbias,
48                1.
49            );
50            return self.camera_projection * (self.camera_view * (self.world ))
51        }
52        
53        fn vertex(self) -> vec4 {
54            return self.clip_and_transform_vertex(self.rect_pos, self.rect_size)
55        }
56        
57        fn pixel(self)->vec4{
58            return #f00
59        }
60        
61        fn fragment(self) -> vec4 {
62            return depth_clip(self.world, self.pixel(), self.depth_clip);
63        }
64    }
65}
66
67#[derive(Live, LiveRegister)]
68#[repr(C)]
69pub struct DrawQuad {
70    #[rust] pub many_instances: Option<ManyInstances>,
71    #[live] pub geometry: GeometryQuad2D,
72    #[deref] pub draw_vars: DrawVars,
73    #[calc] pub rect_pos: Vec2,
74    #[calc] pub rect_size: Vec2,
75    #[calc] pub draw_clip: Vec4,
76    #[live(1.0)] pub depth_clip: f32,
77    #[live(1.0)] pub draw_depth: f32,
78}
79
80impl LiveHook for DrawQuad{
81    fn before_apply(&mut self, cx: &mut Cx, apply: &mut Apply, index: usize, nodes: &[LiveNode]){
82        self.draw_vars.before_apply_init_shader(cx, apply, index, nodes, &self.geometry);
83    }
84    fn after_apply(&mut self, cx: &mut Cx, apply: &mut Apply, index: usize, nodes: &[LiveNode]) {
85        self.draw_vars.after_apply_update_self(cx, apply, index, nodes, &self.geometry);
86    }
87}
88
89impl DrawQuad {
90    pub fn begin(&mut self, cx: &mut Cx2d, walk: Walk, layout: Layout) {
91        cx.begin_turtle(walk, layout);
92        if self.draw_vars.draw_shader.is_some() {
93            let new_area = cx.add_aligned_instance(&self.draw_vars);
94            self.draw_vars.area = cx.update_area_refs(self.draw_vars.area, new_area);
95        }
96    }
97    
98    pub fn end(&mut self, cx: &mut Cx2d) {
99        let rect = cx.end_turtle();
100        self.draw_vars.area.set_rect(cx, &rect);
101    }
102    
103    pub fn draw_walk(&mut self, cx: &mut Cx2d, walk: Walk) -> Rect {
104        let rect = cx.walk_turtle(walk);
105        self.rect_pos = rect.pos.into();
106        self.rect_size = rect.size.into();
107        self.draw(cx);
108        rect
109    }
110    
111    pub fn draw(&mut self, cx: &mut Cx2d) {
112        if let Some(mi) = &mut self.many_instances {
113            mi.instances.extend_from_slice(self.draw_vars.as_slice());
114        }
115        else if self.draw_vars.can_instance() {
116            let new_area = cx.add_aligned_instance(&self.draw_vars);
117            self.draw_vars.area = cx.update_area_refs(self.draw_vars.area, new_area);
118        }
119    }
120    
121    pub fn update_abs(&mut self, cx: &mut Cx, rect: Rect) {
122        self.rect_pos = rect.pos.into();
123        self.rect_size = rect.size.into();
124        self.draw_vars.update_rect(cx, rect);
125    }
126    
127    pub fn draw_abs(&mut self, cx: &mut Cx2d, rect: Rect) {
128        self.rect_pos = rect.pos.into();
129        self.rect_size = rect.size.into();
130        self.draw(cx);
131    }
132    
133    pub fn draw_rel(&mut self, cx: &mut Cx2d, rect: Rect) {
134        let rect = rect.translate(cx.turtle().origin());
135        self.rect_pos = rect.pos.into();
136        self.rect_size = rect.size.into();
137        self.draw(cx);
138    }
139    
140    pub fn new_draw_call(&self, cx: &mut Cx2d) {
141        cx.new_draw_call(&self.draw_vars);
142    }
143    
144    pub fn append_to_draw_call(&self, cx: &mut Cx2d) {
145        cx.append_to_draw_call(&self.draw_vars);
146    }
147    
148    pub fn begin_many_instances(&mut self, cx: &mut Cx2d) {
149        let mi = cx.begin_many_aligned_instances(&self.draw_vars);
150        self.many_instances = mi;
151    }
152    
153    pub fn end_many_instances(&mut self, cx: &mut Cx2d) {
154        if let Some(mi) = self.many_instances.take() {
155            let new_area = cx.end_many_instances(mi);
156            self.draw_vars.area = cx.update_area_refs(self.draw_vars.area, new_area);
157        }
158    }
159}