1use crate::cx::*;
2
3#[derive(Clone)]
4pub struct Blit {
5 pub shader: Shader,
6 pub min_x: f32,
7 pub min_y: f32,
8 pub max_x: f32,
9 pub max_y: f32,
10 pub alpha: f32,
11 pub do_scroll: bool
12}
13
14impl Blit {
15 pub fn style(cx: &mut Cx) -> Self {
16 Self {
17 alpha: 1.0,
18 min_x:0.0,
19 min_y:0.0,
20 max_x:1.0,
21 max_y:1.0,
22 shader: cx.add_shader(Self::def_blit_shader(), "Blit"),
23 do_scroll:false,
24 }
25 }
26
27 pub fn instance_x()->InstanceFloat{uid!()}
28 pub fn instance_y()->InstanceFloat{uid!()}
29 pub fn instance_w()->InstanceFloat{uid!()}
30 pub fn instance_h()->InstanceFloat{uid!()}
31 pub fn instance_min_x()->InstanceFloat{uid!()}
32 pub fn instance_min_y()->InstanceFloat{uid!()}
33 pub fn instance_max_x()->InstanceFloat{uid!()}
34 pub fn instance_max_y()->InstanceFloat{uid!()}
35 pub fn instance_z()->InstanceFloat{uid!()}
36 pub fn instance_color()->InstanceColor{uid!()}
37 pub fn uniform_alpha()->UniformFloat{uid!()}
38
39 pub fn def_blit_shader() -> ShaderGen {
40 let mut sb = ShaderGen::new();
42
43 sb.geometry_vertices = vec![0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0];
44 sb.geometry_indices = vec![0, 1, 2, 2, 3, 0];
45
46 sb.compose(shader_ast!({
47
48 let geom: vec2<Geometry>;
49 let x: Self::instance_x();
50 let y: Self::instance_y();
51 let w: Self::instance_w();
52 let h: Self::instance_h();
53 let min_x: Self::instance_min_x();
54 let min_y: Self::instance_min_y();
55 let max_x: Self::instance_max_x();
56 let max_y: Self::instance_max_y();
57 let tc: vec2<Varying>;
58 let alpha: Self::uniform_alpha();
59 let texturez:texture2d<Texture>;
60 let v_pixel: vec2<Varying>;
61 fn vertex() -> vec4 {
64 let shift: vec2 = -draw_scroll.xy;
66 let clipped: vec2 = clamp(
67 geom * vec2(w, h) + vec2(x, y) + shift,
68 draw_clip.xy,
69 draw_clip.zw
70 );
71 let pos = (clipped - shift - vec2(x, y)) / vec2(w, h);
72 tc = mix(vec2(min_x,min_y), vec2(max_x,max_y), pos);
73 v_pixel = clipped;
74 return camera_projection * vec4(clipped.x, clipped.y, 0., 1.);
76 }
77
78 fn pixel() -> vec4 {
79 return vec4(sample2d(texturez, tc.xy).rgb, alpha);
80 }
81
82 }))
83 }
84
85
86 pub fn begin_blit(&mut self, cx: &mut Cx, texture:&Texture, layout: Layout) -> InstanceArea {
87 let inst = self.draw_blit(cx, texture, Rect::default());
88 let area = inst.clone().into();
89 cx.begin_turtle(layout, area);
90 inst
91 }
92
93 pub fn end_blit(&mut self, cx: &mut Cx, inst: &InstanceArea) -> Area {
94 let area = inst.clone().into();
95 let rect = cx.end_turtle(area);
96 area.set_rect(cx, &rect);
97 area
98 }
99
100 pub fn draw_blit_walk(&mut self, cx: &mut Cx, texture:&Texture, walk:Walk) -> InstanceArea {
101 let geom = cx.walk_turtle(walk);
102 let inst = self.draw_blit_abs(cx, texture, geom);
103 cx.align_instance(inst);
104 inst
105 }
106
107 pub fn draw_blit(&mut self, cx: &mut Cx, texture:&Texture, rect: Rect) -> InstanceArea {
108 let pos = cx.get_turtle_origin();
109 let inst = self.draw_blit_abs(cx, texture, Rect {x: rect.x + pos.x, y: rect.y + pos.y, w: rect.w, h: rect.h});
110 cx.align_instance(inst);
111 inst
112 }
113
114 pub fn draw_blit_abs(&mut self, cx: &mut Cx, texture:&Texture, rect: Rect) -> InstanceArea {
115 let inst = cx.new_instance_draw_call(&self.shader, 1);
116 if inst.need_uniforms_now(cx) {
117 inst.push_uniform_float(cx, if self.do_scroll {1.0}else {0.0});
118 inst.push_uniform_float(cx, self.alpha);
119 inst.push_uniform_texture_2d(cx, texture);
120 }
121 let data = [
123 rect.x,
124 rect.y,
125 rect.w,
126 rect.h,
127 self.min_x,
128 self.min_y,
129 self.max_x,
130 self.max_y
131 ];
132 inst.push_slice(cx, &data);
133 inst
134 }
135}