Просмотр исходного кода

wallet: editbox clip the rendered text properly

darkfi 2 лет назад
Родитель
Сommit
04ede06c9c
4 измененных файлов с 66 добавлено и 27 удалено
  1. 14 10
      bin/darkwallet/src/app.rs
  2. 7 0
      bin/darkwallet/src/gfx2.rs
  3. 31 10
      bin/darkwallet/src/mesh.rs
  4. 14 7
      bin/darkwallet/src/ui/editbox.rs

+ 14 - 10
bin/darkwallet/src/app.rs

@@ -324,19 +324,22 @@ impl App {
         node.set_property_bool("is_active", true).unwrap();
         let prop = node.get_property("rect").unwrap();
         prop.set_f32(0, 150.).unwrap();
-        let code = vec![Op::Sub((
-            Box::new(Op::LoadVar("h".to_string())),
-            Box::new(Op::ConstFloat32(60.)),
-        ))];
-        prop.set_expr(1, code).unwrap();
-        let code = vec![Op::Sub((
-            Box::new(Op::LoadVar("w".to_string())),
-            Box::new(Op::ConstFloat32(120.)),
-        ))];
-        prop.set_expr(2, code).unwrap();
+        prop.set_f32(1, 150.).unwrap();
+        prop.set_f32(2, 380.).unwrap();
+        //let code = vec![Op::Sub((
+        //    Box::new(Op::LoadVar("h".to_string())),
+        //    Box::new(Op::ConstFloat32(60.)),
+        //))];
+        //prop.set_expr(1, code).unwrap();
+        //let code = vec![Op::Sub((
+        //    Box::new(Op::LoadVar("w".to_string())),
+        //    Box::new(Op::ConstFloat32(120.)),
+        //))];
+        //prop.set_expr(2, code).unwrap();
         prop.set_f32(3, 60.).unwrap();
         node.set_property_f32("baseline", 40.).unwrap();
         node.set_property_f32("font_size", 20.).unwrap();
+        node.set_property_f32("font_size", 40.).unwrap();
         node.set_property_str("text", "hello king!😁🍆jelly 🍆1234").unwrap();
         let prop = node.get_property("text_color").unwrap();
         prop.set_f32(0, 1.).unwrap();
@@ -357,6 +360,7 @@ impl App {
         prop.set_null(0).unwrap();
         prop.set_null(1).unwrap();
         node.set_property_u32("z_index", 1).unwrap();
+        node.set_property_bool("debug", true).unwrap();
 
         drop(sg);
         let pimpl = EditBox::new(

+ 7 - 0
bin/darkwallet/src/gfx2.rs

@@ -139,6 +139,13 @@ impl Rectangle {
             point.y <= self.y + self.h
     }
 
+    pub fn rhs(&self) -> f32 {
+        self.x + self.w
+    }
+    pub fn bhs(&self) -> f32 {
+        self.y + self.h
+    }
+
     pub fn top_left(&self) -> Point {
         Point { x: self.x, y: self.y }
     }

+ 31 - 10
bin/darkwallet/src/mesh.rs

@@ -34,26 +34,47 @@ impl MeshBuilder {
     }
 
     pub fn append(&mut self, mut verts: Vec<Vertex>, indices: Vec<u16>) {
-        if let Some(clipper) = &self.clipper {
-            for vert in &mut verts {
-                let mut vpos = vert.pos();
-                clipper.clip_point(&mut vpos);
-                vert.set_pos(&vpos);
-            }
-        }
-
         let mut indices = indices.into_iter().map(|i| i + self.verts.len() as u16).collect();
         self.verts.append(&mut verts);
         self.indices.append(&mut indices);
     }
 
     pub fn draw_box(&mut self, obj: &Rectangle, color: Color, uv: &Rectangle) {
-        let (x1, y1) = obj.top_left().unpack();
-        let (x2, y2) = obj.bottom_right().unpack();
+        let clipped = match &self.clipper {
+            Some(clipper) => {
+                let Some(clipped) = clipper.clip(&obj) else {
+                    return;
+                };
+                clipped
+            }
+            None => obj.clone(),
+        };
+
+        let (x1, y1) = clipped.top_left().unpack();
+        let (x2, y2) = clipped.bottom_right().unpack();
 
         let (u1, v1) = uv.top_left().unpack();
         let (u2, v2) = uv.bottom_right().unpack();
 
+        // Interpolate UV coords
+        assert!(obj.w >= clipped.w);
+        assert!(obj.h >= clipped.h);
+
+        let i = (clipped.x - obj.x) / obj.w;
+        let clip_u1 = u1 + i*(u2 - u1);
+
+        let i = (clipped.rhs() - obj.x) / obj.w;
+        let clip_u2 = u1 + i*(u2 - u1);
+
+        let i = (clipped.y - obj.y) / obj.h;
+        let clip_v1 = v1 + i*(v2 - v1);
+
+        let i = (clipped.bhs() - obj.y) / obj.h;
+        let clip_v2 = v1 + i*(v2 - v1);
+
+        let (u1, u2) = (clip_u1, clip_u2);
+        let (v1, v2) = (clip_v1, clip_v2);
+
         let verts = vec![
             // top left
             Vertex { pos: [x1, y1], color, uv: [u1, v1] },

+ 14 - 7
bin/darkwallet/src/ui/editbox.rs

@@ -246,18 +246,21 @@ impl EditBox {
 
     /// Called whenever the text or any text property changes.
     /// Not related to cursor, text highlighting or bounding (clip) rects.
-    async fn regen_mesh(&self, clip: &Rectangle) -> TextRenderInfo {
+    async fn regen_mesh(&self, mut clip: Rectangle) -> TextRenderInfo {
+        clip.x = 0.;
+        clip.y = 0.;
+
         let text = self.text.get();
         let font_size = self.font_size.get();
         let text_color = self.text_color.get();
         let baseline = self.baseline.get();
         let debug = self.debug.get();
-        debug!(target: "ui::editbox", "Rendering text '{}'", text);
+        debug!(target: "ui::editbox", "Rendering text '{}' clip={:?}", text, clip);
 
         let glyphs = self.glyphs.lock().unwrap().clone();
         let atlas = text2::make_texture_atlas(&self.render_api, font_size, &glyphs).await.unwrap();
 
-        let mut mesh = MeshBuilder::new();
+        let mut mesh = MeshBuilder::with_clip(clip.clone());
         let mut glyph_pos_iter = GlyphPositionIter::new(font_size, &glyphs, baseline);
         for ((uv_rect, glyph_rect), glyph) in
             atlas.uv_rects.into_iter().zip(glyph_pos_iter).zip(glyphs.iter())
@@ -270,6 +273,10 @@ impl EditBox {
             mesh.draw_box(&glyph_rect, color, &uv_rect);
         }
 
+        if debug {
+            mesh.draw_outline(&clip, COLOR_BLUE, 1.);
+        }
+
         let mesh = mesh.alloc(&self.render_api).await.unwrap();
 
         TextRenderInfo { mesh, texture_id: atlas.texture_id }
@@ -438,11 +445,14 @@ impl EditBox {
             panic!("Node {:?} bad rect property", node);
         };
 
+        rect.x += parent_rect.x;
+        rect.y += parent_rect.y;
+
         let render_info = self.render_info.lock().unwrap().clone();
         let render_info = match render_info {
             Some(render_info) => render_info,
             None => {
-                let render_info = self.regen_mesh(&rect).await;
+                let render_info = self.regen_mesh(rect.clone()).await;
                 *self.render_info.lock().unwrap() = Some(render_info.clone());
                 render_info
             }
@@ -455,9 +465,6 @@ impl EditBox {
             num_elements: render_info.mesh.num_elements,
         };
 
-        rect.x += parent_rect.x;
-        rect.y += parent_rect.x;
-
         let off_x = rect.x / parent_rect.w;
         let off_y = rect.y / parent_rect.h;
         let scale_x = 1. / parent_rect.w;