makepad_draw/shader/
draw_trapezoid.rs

1pub use {
2    std::{
3        rc::Rc,
4        cell::RefCell,
5        io::prelude::*,
6        fs::File,
7        collections::HashMap,
8    },
9    crate::{
10        makepad_platform::*,
11        cx_2d::Cx2d,
12        turtle::{Walk, Layout},
13        draw_list_2d::{ManyInstances, DrawList2d, RedrawingApi},
14        geometry::GeometryQuad2D,
15        makepad_vector::font::Glyph,
16        makepad_vector::trapezoidator::Trapezoidator,
17        makepad_vector::geometry::{AffineTransformation, Transform, Vector},
18        makepad_vector::internal_iter::*,
19        makepad_vector::path::PathIterator,
20    }
21};
22
23live_design!{
24    DrawTrapezoidVector= {{DrawTrapezoidVector}} {
25        
26        varying v_p0: vec2;
27        varying v_p1: vec2;
28        varying v_p2: vec2;
29        varying v_p3: vec2;
30        varying v_pixel: vec2;
31        
32        fn intersect_line_segment_with_vertical_line(p0: vec2, p1: vec2, x: float) -> vec2 {
33            return vec2(
34                x,
35                mix(p0.y, p1.y, (x - p0.x) / (p1.x - p0.x))
36            );
37        }
38        
39        fn intersect_line_segment_with_horizontal_line(p0: vec2, p1: vec2, y: float) -> vec2 {
40            return vec2(
41                mix(p0.x, p1.x, (y - p0.y) / (p1.y - p0.y)),
42                y
43            );
44        }
45        
46        fn compute_clamped_right_trapezoid_area(p0: vec2, p1: vec2, p_min: vec2, p_max: vec2) -> float {
47            let x0 = clamp(p0.x, p_min.x, p_max.x);
48            let x1 = clamp(p1.x, p_min.x, p_max.x);
49            if (p0.x < p_min.x && p_min.x < p1.x) {
50                p0 = intersect_line_segment_with_vertical_line(p0, p1, p_min.x);
51            }
52            if (p0.x < p_max.x && p_max.x < p1.x) {
53                p1 = intersect_line_segment_with_vertical_line(p0, p1, p_max.x);
54            }
55            if (p0.y < p_min.y && p_min.y < p1.y) {
56                p0 = intersect_line_segment_with_horizontal_line(p0, p1, p_min.y);
57            }
58            if (p1.y < p_min.y && p_min.y < p0.y) {
59                p1 = intersect_line_segment_with_horizontal_line(p1, p0, p_min.y);
60            }
61            if (p0.y < p_max.y && p_max.y < p1.y) {
62                p1 = intersect_line_segment_with_horizontal_line(p0, p1, p_max.y);
63            }
64            if (p1.y < p_max.y && p_max.y < p0.y) {
65                p0 = intersect_line_segment_with_horizontal_line(p1, p0, p_max.y);
66            }
67            p0 = clamp(p0, p_min, p_max);
68            p1 = clamp(p1, p_min, p_max);
69            let h0 = p_max.y - p0.y;
70            let h1 = p_max.y - p1.y;
71            let a0 = (p0.x - x0) * h0;
72            let a1 = (p1.x - p0.x) * (h0 + h1) * 0.5;
73            let a2 = (x1 - p1.x) * h1;
74            return a0 + a1 + a2;
75        }
76        
77        fn compute_clamped_trapezoid_area(self, p_min: vec2, p_max: vec2) -> float {
78            let a0 = compute_clamped_right_trapezoid_area(self.v_p0, self.v_p1, p_min, p_max);
79            let a1 = compute_clamped_right_trapezoid_area(self.v_p2, self.v_p3, p_min, p_max);
80            return a0 - a1;
81        }
82        
83        fn pixel(self) -> vec4 {
84            let p_min = self.v_pixel.xy - 0.5;
85            let p_max = self.v_pixel.xy + 0.5;
86            let t_area = self.compute_clamped_trapezoid_area(p_min, p_max);
87            if self.chan < 0.5 {
88                return vec4(t_area, 0., 0., 0.);
89            }
90            if self.chan < 1.5 {
91                return vec4(0., t_area, 0., 0.);
92            }
93            if self.chan < 2.5 {
94                return vec4(0., 0., t_area, 0.);
95            }
96            return vec4(t_area, t_area, t_area, 0.);
97        }
98        
99        fn vertex(self) -> vec4 {
100            let pos_min = vec2(self.a_xs.x, min(self.a_ys.x, self.a_ys.y));
101            let pos_max = vec2(self.a_xs.y, max(self.a_ys.z, self.a_ys.w));
102            let pos = mix(pos_min - 1.0, pos_max + 1.0, self.geom_pos);
103            
104            // set the varyings
105            self.v_p0 = vec2(self.a_xs.x, self.a_ys.x);
106            self.v_p1 = vec2(self.a_xs.y, self.a_ys.y);
107            self.v_p2 = vec2(self.a_xs.x, self.a_ys.z);
108            self.v_p3 = vec2(self.a_xs.y, self.a_ys.w);
109            self.v_pixel = pos;
110            return self.camera_projection * vec4(pos, 0.0, 1.0);
111        }
112    }
113}
114
115
116#[derive(Live)]
117#[repr(C)]
118pub struct DrawTrapezoidVector {
119    #[rust] pub trapezoidator: Trapezoidator,
120    #[live] pub geometry: GeometryQuad2D,
121    #[deref] pub draw_vars: DrawVars,
122    #[calc] pub a_xs: Vec2,
123    #[calc] pub a_ys: Vec4,
124    #[calc] pub chan: f32,
125}
126
127impl LiveHook for DrawTrapezoidVector{
128    fn before_apply(&mut self, cx: &mut Cx, apply_from: ApplyFrom, index: usize, nodes: &[LiveNode]){
129        self.draw_vars.before_apply_init_shader(cx, apply_from, index, nodes, &self.geometry);
130    }
131    fn after_apply(&mut self, cx: &mut Cx, apply_from: ApplyFrom, index: usize, nodes: &[LiveNode]) {
132        self.draw_vars.after_apply_update_self(cx, apply_from, index, nodes, &self.geometry);
133    }
134}
135