Bladeren bron

wallet: remove old unused modules from proj

darkfi 2 jaren geleden
bovenliggende
commit
dc71754be6

+ 2 - 2
bin/darkwallet/src/app.rs

@@ -32,13 +32,13 @@ use crate::{
     darkirc::{DarkIrcBackendPtr, Privmsg},
     error::Error,
     expr::Op,
-    gfx2::{GraphicsEventPublisherPtr, RenderApiPtr, Vertex},
+    gfx::{GraphicsEventPublisherPtr, RenderApiPtr, Vertex},
     prop::{Property, PropertyBool, PropertyStr, PropertySubType, PropertyType, Role},
     scene::{
         CallArgType, MethodResponseFn, Pimpl, SceneGraph, SceneGraphPtr2, SceneNodeId,
         SceneNodeType, Slot,
     },
-    text2::TextShaperPtr,
+    text::TextShaperPtr,
     ui::{chatview, Button, ChatView, EditBox, Image, Mesh, RenderLayer, Stoppable, Text, Window},
     ExecutorPtr,
 };

+ 0 - 436
bin/darkwallet/src/chatapp.rs

@@ -1,436 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2024 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use darkfi_serial::Encodable;
-
-use crate::{
-    expr::Op,
-    gfx::Rectangle,
-    prop::{Property, PropertySubType, PropertyType},
-    scene::{
-        SceneGraph, SceneNodeId,
-        SceneNodeType,
-    },
-};
-
-struct Buffer {
-    verts: Vec<u8>,
-    faces: Vec<u8>,
-    verts_len: u32,
-}
-
-impl Buffer {
-    pub fn new() -> Self {
-        Self { verts: vec![], faces: vec![], verts_len: 0 }
-    }
-
-    fn vertex(&mut self, x: f32, y: f32, r: f32, g: f32, b: f32, a: f32, u: f32, v: f32) {
-        // xy
-        x.encode(&mut self.verts).unwrap();
-        y.encode(&mut self.verts).unwrap();
-        // rgba
-        r.encode(&mut self.verts).unwrap();
-        g.encode(&mut self.verts).unwrap();
-        b.encode(&mut self.verts).unwrap();
-        a.encode(&mut self.verts).unwrap();
-        // uv
-        u.encode(&mut self.verts).unwrap();
-        v.encode(&mut self.verts).unwrap();
-        self.verts_len += 1
-    }
-
-    fn face(&mut self, i1: u32, i2: u32, i3: u32) {
-        i1.encode(&mut self.faces).unwrap();
-        i2.encode(&mut self.faces).unwrap();
-        i3.encode(&mut self.faces).unwrap();
-    }
-
-    pub fn draw_box(&mut self, rect: Rectangle<f32>, color: [f32; 4]) {
-        let k = self.verts_len;
-        let x = rect.x;
-        let y = rect.y;
-        let w = rect.w;
-        let h = rect.h;
-        let r = color[0];
-        let g = color[1];
-        let b = color[2];
-        let a = color[3];
-
-        self.vertex(x, y, r, g, b, a, 0., 0.);
-        self.vertex(x + w, y, r, g, b, a, 1., 0.);
-        self.vertex(x, y + h, r, g, b, a, 0., 1.);
-        self.vertex(x + w, y + h, r, g, b, a, 1., 1.);
-
-        self.face(k, k + 2, k + 1);
-        self.face(k + 1, k + 2, k + 3);
-    }
-
-    pub fn draw_outline(
-        &mut self,
-        rect: Rectangle<f32>,
-        color: [f32; 4],
-        pad: f32,
-        layer_w: f32,
-        layer_h: f32,
-    ) {
-        let pad_x = pad / layer_w;
-        let pad_y = pad / layer_h;
-
-        let x = rect.x;
-        let y = rect.y;
-        let w = rect.w;
-        let h = rect.h;
-
-        // left
-        self.draw_box(Rectangle { x, y, w: pad_x, h }, color);
-        // top
-        self.draw_box(Rectangle { x, y, w, h: pad_y }, color);
-        // right
-        let rhs = x + w;
-        self.draw_box(Rectangle { x: rhs - pad_x, y, w: pad_x, h }, color);
-        // bottom
-        let bhs = y + h;
-        self.draw_box(Rectangle { x, y: bhs - pad_y, w, h: pad_y }, color);
-    }
-}
-
-pub fn create_layer(sg: &mut SceneGraph, name: &str) -> SceneNodeId {
-    let win_id = sg.lookup_node("/window").unwrap().id;
-
-    let node = sg.add_node(name, SceneNodeType::RenderLayer);
-    let mut prop = Property::new("is_visible", PropertyType::Bool, PropertySubType::Null);
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("rect", PropertyType::Float32, PropertySubType::Pixel);
-    prop.set_array_len(4);
-    prop.allow_exprs();
-    node.add_property(prop).unwrap();
-
-    node.id
-}
-
-pub fn create_mesh(sg: &mut SceneGraph, name: &str) -> SceneNodeId {
-    let node = sg.add_node(name, SceneNodeType::RenderMesh);
-
-    let mut prop = Property::new("rect", PropertyType::Float32, PropertySubType::Pixel);
-    prop.set_array_len(4);
-    prop.allow_exprs();
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("z_index", PropertyType::Uint32, PropertySubType::Null);
-    node.add_property(prop).unwrap();
-
-    node.id
-}
-
-fn create_text(sg: &mut SceneGraph, name: &str, layer_node_id: SceneNodeId) -> SceneNodeId {
-    let node = sg.add_node(name, SceneNodeType::RenderText);
-
-    let mut prop = Property::new("rect", PropertyType::Float32, PropertySubType::Pixel);
-    prop.set_array_len(4);
-    prop.allow_exprs();
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("baseline", PropertyType::Float32, PropertySubType::Pixel);
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("font_size", PropertyType::Float32, PropertySubType::Pixel);
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("text", PropertyType::Str, PropertySubType::Null);
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("color", PropertyType::Float32, PropertySubType::Color);
-    prop.set_array_len(4);
-    prop.set_range_f32(0., 1.);
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("z_index", PropertyType::Uint32, PropertySubType::Null);
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("debug", PropertyType::Bool, PropertySubType::Null);
-    node.add_property(prop).unwrap();
-
-    let node_id = node.id;
-    sg.link(node_id, layer_node_id).unwrap();
-    node_id
-}
-
-fn create_editbox(sg: &mut SceneGraph, name: &str, layer_node_id: SceneNodeId) -> SceneNodeId {
-    let node = sg.add_node(name, SceneNodeType::EditBox);
-
-    let mut prop = Property::new("is_active", PropertyType::Bool, PropertySubType::Null);
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("rect", PropertyType::Float32, PropertySubType::Pixel);
-    prop.set_array_len(4);
-    prop.allow_exprs();
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("baseline", PropertyType::Float32, PropertySubType::Pixel);
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("scroll", PropertyType::Float32, PropertySubType::Pixel);
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("cursor_pos", PropertyType::Uint32, PropertySubType::Pixel);
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("font_size", PropertyType::Float32, PropertySubType::Pixel);
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("text", PropertyType::Str, PropertySubType::Null);
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("text_color", PropertyType::Float32, PropertySubType::Color);
-    prop.set_array_len(4);
-    prop.set_range_f32(0., 1.);
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("cursor_color", PropertyType::Float32, PropertySubType::Color);
-    prop.set_array_len(4);
-    prop.set_range_f32(0., 1.);
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("hi_bg_color", PropertyType::Float32, PropertySubType::Color);
-    prop.set_array_len(4);
-    prop.set_range_f32(0., 1.);
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("selected", PropertyType::Uint32, PropertySubType::Color);
-    prop.set_array_len(2);
-    prop.allow_null_values();
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("z_index", PropertyType::Uint32, PropertySubType::Null);
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("debug", PropertyType::Bool, PropertySubType::Null);
-    node.add_property(prop).unwrap();
-
-    let node_id = node.id;
-    sg.link(node_id, layer_node_id).unwrap();
-    node_id
-}
-
-fn create_chatview(sg: &mut SceneGraph, name: &str, layer_node_id: SceneNodeId) -> SceneNodeId {
-    let node = sg.add_node(name, SceneNodeType::ChatView);
-
-    let mut prop = Property::new("rect", PropertyType::Float32, PropertySubType::Pixel);
-    prop.set_array_len(4);
-    prop.allow_exprs();
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("z_index", PropertyType::Uint32, PropertySubType::Null);
-    node.add_property(prop).unwrap();
-
-    let mut prop = Property::new("debug", PropertyType::Bool, PropertySubType::Null);
-    node.add_property(prop).unwrap();
-
-    let node_id = node.id;
-
-    let mut arg_data = vec![];
-    node_id.encode(&mut arg_data).unwrap();
-    //let (tx, rx) = mpsc::sync_channel::<Result<Vec<u8>>>(0);
-    let response_fn = Box::new(move |_result| {
-        //tx.send(result).unwrap();
-    });
-    let win_node = sg.lookup_node_mut("/window").unwrap();
-    win_node.call_method("create_chat_view", arg_data, response_fn).unwrap();
-    //let _result = rx.recv().unwrap();
-
-    sg.link(node_id, layer_node_id).unwrap();
-    node_id
-}
-
-pub fn setup(sg: &mut SceneGraph) {
-    let layer_node_id = create_layer(sg, "view");
-    let node = sg.get_node(layer_node_id).unwrap();
-    let prop = node.get_property("rect").unwrap();
-    prop.set_u32(0, 0).unwrap();
-    prop.set_u32(1, 0).unwrap();
-    let code = vec![Op::Float32ToUint32((Box::new(Op::LoadVar("sw".to_string()))))];
-    prop.set_expr(2, code).unwrap();
-    let code = vec![Op::Float32ToUint32((Box::new(Op::LoadVar("sh".to_string()))))];
-    prop.set_expr(3, code).unwrap();
-
-    // Make the black background
-    // Maybe we should use a RenderPass for this instead
-    let node_id = create_mesh(sg, "bg");
-    let node = sg.get_node(node_id).unwrap();
-
-    let prop = node.get_property("rect").unwrap();
-    prop.set_f32(0, 0.).unwrap();
-    prop.set_f32(1, 0.).unwrap();
-    let code = vec![Op::LoadVar("lw".to_string())];
-    prop.set_expr(2, code).unwrap();
-    let code = vec![Op::LoadVar("lh".to_string())];
-    prop.set_expr(3, code).unwrap();
-
-    let prop = node.get_property("data").unwrap();
-
-    let mut buff = Buffer::new();
-    buff.draw_box(Rectangle { x: 0., y: 0., w: 1., h: 1. }, [0.05, 0.05, 0.05, 1.]);
-    prop.set_buf(0, buff.verts).unwrap();
-    prop.set_buf(1, buff.faces).unwrap();
-
-    // Make the chatedit bg
-    let node_id = create_mesh(sg, "chateditbg");
-    let node = sg.get_node(node_id).unwrap();
-    let prop = node.get_property("rect").unwrap();
-
-    let prop = node.get_property("rect").unwrap();
-    prop.set_f32(0, 140.).unwrap();
-    let code =
-        vec![Op::Sub((Box::new(Op::LoadVar("lh".to_string())), Box::new(Op::ConstFloat32(60.))))];
-    prop.set_expr(1, code).unwrap();
-    let code =
-        vec![Op::Sub((Box::new(Op::LoadVar("lw".to_string())), Box::new(Op::ConstFloat32(140.))))];
-    prop.set_expr(2, code).unwrap();
-    prop.set_f32(3, 60.).unwrap();
-
-    let prop = node.get_property("data").unwrap();
-
-    let mut buff = Buffer::new();
-    buff.draw_box(Rectangle { x: 0., y: 0., w: 1., h: 1. }, [0., 0.13, 0.08, 1.]);
-    // FIXME: layer dim is passed here manually!
-    // we should just use separate objs
-    buff.draw_outline(
-        Rectangle { x: 0., y: 0., w: 1., h: 1. },
-        [0.22, 0.22, 0.22, 1.],
-        1.,
-        1000.,
-        50.,
-    );
-    prop.set_buf(0, buff.verts).unwrap();
-    prop.set_buf(1, buff.faces).unwrap();
-
-    // Make the nicktext border
-    let node_id = create_mesh(sg, "nickbg");
-    let node = sg.get_node(node_id).unwrap();
-    let prop = node.get_property("rect").unwrap();
-    prop.set_f32(0, 0.).unwrap();
-    let code =
-        vec![Op::Sub((Box::new(Op::LoadVar("lh".to_string())), Box::new(Op::ConstFloat32(60.))))];
-    prop.set_expr(1, code).unwrap();
-    prop.set_f32(2, 130.).unwrap();
-    prop.set_f32(3, 60.).unwrap();
-
-    let prop = node.get_property("data").unwrap();
-
-    let mut buff = Buffer::new();
-    // FIXME: layer dim is passed here manually!
-    // we should just use separate objs
-    buff.draw_outline(
-        Rectangle { x: 0., y: 0., w: 1., h: 1. },
-        [0., 0.13, 0.08, 1.],
-        1.,
-        1000.,
-        50.,
-    );
-    prop.set_buf(0, buff.verts).unwrap();
-    prop.set_buf(1, buff.faces).unwrap();
-
-    // Nickname
-    let node_id = create_text(sg, "nick", layer_node_id);
-    let node = sg.get_node(node_id).unwrap();
-    let prop = node.get_property("rect").unwrap();
-    prop.set_f32(0, 20.).unwrap();
-    let code =
-        vec![Op::Sub((Box::new(Op::LoadVar("lh".to_string())), Box::new(Op::ConstFloat32(60.))))];
-    prop.set_expr(1, code).unwrap();
-    prop.set_f32(2, 120.).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_str("text", "anon1").unwrap();
-    let prop = node.get_property("color").unwrap();
-    prop.set_f32(0, 0.).unwrap();
-    prop.set_f32(1, 1.).unwrap();
-    prop.set_f32(2, 0.).unwrap();
-    prop.set_f32(3, 1.).unwrap();
-    node.set_property_u32("z_index", 1).unwrap();
-
-    // Text edit
-    let node_id = create_editbox(sg, "editz", layer_node_id);
-    let node = sg.get_node(node_id).unwrap();
-    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("lh".to_string())), Box::new(Op::ConstFloat32(60.))))];
-    prop.set_expr(1, code).unwrap();
-    let code =
-        vec![Op::Sub((Box::new(Op::LoadVar("lw".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_str("text", "hello king!😁🍆jelly 🍆1234").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();
-    prop.set_f32(1, 1.).unwrap();
-    prop.set_f32(2, 1.).unwrap();
-    prop.set_f32(3, 1.).unwrap();
-    let prop = node.get_property("cursor_color").unwrap();
-    prop.set_f32(0, 1.).unwrap();
-    prop.set_f32(1, 0.5).unwrap();
-    prop.set_f32(2, 0.5).unwrap();
-    prop.set_f32(3, 1.).unwrap();
-    let prop = node.get_property("hi_bg_color").unwrap();
-    prop.set_f32(0, 1.).unwrap();
-    prop.set_f32(1, 1.).unwrap();
-    prop.set_f32(2, 1.).unwrap();
-    prop.set_f32(3, 0.5).unwrap();
-    let prop = node.get_property("selected").unwrap();
-    prop.set_null(0).unwrap();
-    prop.set_null(1).unwrap();
-    node.set_property_u32("z_index", 1).unwrap();
-
-    let node_id = node.id;
-    let mut arg_data = vec![];
-    node_id.encode(&mut arg_data).unwrap();
-    //let (tx, rx) = mpsc::sync_channel::<Result<Vec<u8>>>(0);
-    let response_fn = Box::new(move |result| {
-        //tx.send(result).unwrap();
-    });
-    let win_node = sg.lookup_node_mut("/window").unwrap();
-    win_node.call_method("create_edit_box", arg_data, response_fn).unwrap();
-    //let _result = rx.recv().unwrap();
-
-    // ChatView
-    let node_id = create_chatview(sg, "chatty", layer_node_id);
-    let node = sg.get_node(node_id).unwrap();
-    let prop = node.get_property("rect").unwrap();
-    prop.set_f32(0, 0.).unwrap();
-    prop.set_f32(1, 0.).unwrap();
-    let code = vec![Op::LoadVar("lw".to_string())];
-    prop.set_expr(2, code).unwrap();
-    let code =
-        vec![Op::Sub((Box::new(Op::LoadVar("lh".to_string())), Box::new(Op::ConstFloat32(50.))))];
-    prop.set_expr(3, code).unwrap();
-    node.set_property_u32("z_index", 1).unwrap();
-
-    // On android lets scale the UI up
-    let win_node = sg.lookup_node_mut("/window").unwrap();
-    win_node.set_property_f32("scale", 1.6).unwrap();
-
-    let layer_node = sg.get_node(layer_node_id).unwrap();
-    layer_node.set_property_bool("is_visible", true).unwrap();
-}

+ 0 - 339
bin/darkwallet/src/chatview.rs

@@ -1,339 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2024 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use atomic_float::AtomicF32;
-use miniquad::{TextureId, UniformType};
-use std::{
-    collections::HashMap,
-    io::{BufRead, BufReader},
-    path::Path,
-    sync::{
-        atomic::Ordering,
-        Arc, Mutex,
-    },
-};
-
-use crate::{
-    error::Result,
-    gfx::{
-        FreetypeFace, Point, Rectangle, RenderContext,
-        COLOR_RED, COLOR_WHITE,
-    },
-    prop::PropertyBool,
-    scene::{Pimpl, SceneGraph, SceneNodeId},
-    text::{Glyph, TextShaper},
-};
-
-fn read_lines<P>(filename: P) -> Vec<String>
-where
-    P: AsRef<Path>,
-{
-    //let file = File::open(filename).unwrap();
-    //BufReader::new(file).lines().map(|l| l.unwrap()).collect()
-    // Just so we can package for android easily
-    // Later this will be all replaced anyway
-    let file = include_bytes!("../chat.txt");
-    BufReader::new(&file[..]).lines().map(|l| l.unwrap()).collect()
-}
-
-pub type ChatViewPtr = Arc<ChatView>;
-
-pub struct ChatView {
-    node_name: String,
-    debug: PropertyBool,
-    // Used for mouse interaction
-    world_rect: Mutex<Rectangle<f32>>,
-    mouse_pos: Mutex<Point<f32>>,
-    text_shaper: TextShaper,
-    scroll: AtomicF32,
-    lines: Vec<String>,
-    glyph_lines: Mutex<Vec<Vec<Glyph>>>,
-    atlas: Mutex<HashMap<(u32, [u8; 4]), TextureId>>,
-}
-
-impl ChatView {
-    pub fn new(
-        scene_graph: &mut SceneGraph,
-        node_id: SceneNodeId,
-        font_faces: Vec<FreetypeFace>,
-    ) -> Result<Pimpl> {
-        let node = scene_graph.get_node(node_id).unwrap();
-        let node_name = node.name.clone();
-        let debug = PropertyBool::wrap(node, "debug", 0)?;
-
-        let text_shaper = TextShaper { font_faces };
-
-        let lines = read_lines("chat.txt");
-        let mut glyph_lines = vec![];
-        glyph_lines.resize(lines.len(), vec![]);
-
-        let self_ = Arc::new(Self {
-            node_name: node_name.clone(),
-            debug,
-            world_rect: Mutex::new(Rectangle { x: 0., y: 0., w: 0., h: 0. }),
-            mouse_pos: Mutex::new(Point { x: 0., y: 0. }),
-            text_shaper,
-            scroll: AtomicF32::new(0.),
-            lines,
-            glyph_lines: Mutex::new(glyph_lines),
-            atlas: Mutex::new(HashMap::new()),
-        });
-
-        /*
-        let weak_self = Arc::downgrade(&self_);
-        let slot_move = Slot {
-            name: format!("{}::mouse_move", node_name),
-            func: Box::new(move |data| {
-                let mut cur = Cursor::new(&data);
-                let x = f32::decode(&mut cur).unwrap();
-                let y = f32::decode(&mut cur).unwrap();
-
-                let self_ = weak_self.upgrade();
-                if let Some(self_) = self_ {
-                    let pos = &mut *self_.mouse_pos.lock().unwrap();
-                    pos.x = x;
-                    pos.y = y;
-                }
-            }),
-        };
-
-        let weak_self = Arc::downgrade(&self_);
-        let slot_wheel = Slot {
-            name: format!("{}::mouse_wheel", node_name),
-            func: Box::new(move |data| {
-                let mut cur = Cursor::new(&data);
-                let x = f32::decode(&mut cur).unwrap();
-                let y = f32::decode(&mut cur).unwrap();
-
-                let self_ = weak_self.upgrade();
-                if let Some(self_) = self_ {
-                    self_.mouse_scroll(x, y);
-                }
-            }),
-        };
-        */
-
-        let mouse_node =
-            scene_graph.lookup_node_mut("/window/input/mouse").expect("no mouse attached!");
-        //mouse_node.register("wheel", slot_wheel);
-        //mouse_node.register("move", slot_move);
-
-        // Save any properties we use
-        Ok(Pimpl::ChatView(self_))
-    }
-
-    pub fn render<'a>(
-        &self,
-        render: &mut RenderContext<'a>,
-        node_id: SceneNodeId,
-        layer_rect: &Rectangle<f32>,
-    ) -> Result<()> {
-        let debug = self.debug.get();
-
-        let node = render.scene_graph.get_node(node_id).unwrap();
-        let rect = RenderContext::get_dim(node, layer_rect)?;
-
-        // Used for detecting mouse clicks
-        let mut world_rect = rect.clone();
-        world_rect.x += layer_rect.x as f32;
-        world_rect.y += layer_rect.y as f32;
-        *self.world_rect.lock().unwrap() = world_rect;
-
-        let layer_w = layer_rect.w as f32;
-        let layer_h = layer_rect.h as f32;
-        let off_x = rect.x / layer_w;
-        let off_y = rect.y / layer_h;
-        // Use absolute pixel scale
-        let scale_x = 1. / layer_w;
-        let scale_y = 1. / layer_h;
-        let model = glam::Mat4::from_translation(glam::Vec3::new(off_x, off_y, 0.)) *
-            glam::Mat4::from_scale(glam::Vec3::new(scale_x, scale_y, 1.));
-
-        let mut uniforms_data = [0u8; 128];
-        let data: [u8; 64] = unsafe { std::mem::transmute_copy(&render.proj) };
-        uniforms_data[0..64].copy_from_slice(&data);
-        let data: [u8; 64] = unsafe { std::mem::transmute_copy(&model) };
-        uniforms_data[64..].copy_from_slice(&data);
-        assert_eq!(128, 2 * UniformType::Mat4.size());
-
-        render.ctx.apply_uniforms_from_bytes(uniforms_data.as_ptr(), uniforms_data.len());
-
-        // Used for scaling the font size
-        let window = render.scene_graph.lookup_node("/window").expect("no window attached!");
-        let window_scale = window.get_property_f32("scale")?;
-        let font_size = window_scale * 20.;
-
-        let bound = Rectangle { x: 0., y: 0., w: rect.w, h: rect.h };
-
-        let glyph_lines = &mut self.glyph_lines.lock().unwrap();
-        let atlas = &mut self.atlas.lock().unwrap();
-
-        let scroll = self.scroll.load(Ordering::Relaxed);
-        for (i, (line, glyph_line)) in self.lines.iter().zip(glyph_lines.iter_mut()).enumerate() {
-            let line = line.replace("\t", "    ");
-
-            // Split time and nick from the line
-            let mut iter = line.split_whitespace();
-            let Some(time) = iter.next() else {
-                error!("line missing time");
-                continue
-            };
-            let Some(nick) = iter.next() else {
-                error!("line missing nick");
-                continue
-            };
-            let Some(line) = iter.remainder() else {
-                error!("line missing remainder");
-                continue
-            };
-
-            let linespacing = window_scale * 30.;
-            let off_y = linespacing * i as f32 + scroll;
-            if off_y + linespacing < 0. || off_y - linespacing > rect.h {
-                continue;
-            }
-
-            if glyph_line.is_empty() {
-                *glyph_line = self.text_shaper.shape(line.to_string(), font_size, COLOR_WHITE);
-            }
-
-            let times_color = [0.4, 0.4, 0.4, 1.];
-            let times_color_u8 =
-                [(255. * 0.4) as u8, (255. * 0.4) as u8, (255. * 0.4) as u8, (255. * 1.) as u8];
-            let glyphs_time = self.text_shaper.shape(time.to_string(), font_size, times_color);
-            let mut rhs = 0.;
-            for glyph in glyphs_time {
-                let mut pos = glyph.pos.clone();
-                pos.y += off_y;
-                rhs = pos.x + pos.w;
-
-                assert_eq!(glyph.bmp.len() as u16, glyph.bmp_width * glyph.bmp_height * 4);
-                //debug!("gly {} {}", glyph.substr, glyph.bmp.len());
-                let texture = if atlas.contains_key(&(glyph.id, times_color_u8.clone())) {
-                    *atlas.get(&(glyph.id, times_color_u8.clone())).unwrap()
-                } else {
-                    let texture = render.ctx.new_texture_from_rgba8(
-                        glyph.bmp_width,
-                        glyph.bmp_height,
-                        &glyph.bmp,
-                    );
-                    atlas.insert((glyph.id, times_color_u8.clone()), texture);
-                    texture
-                };
-                render.render_clipped_box_with_texture2(&bound, &pos, COLOR_WHITE, texture);
-                //render.ctx.delete_texture(texture);
-            }
-
-            let nick_colors = [
-                [0.00, 0.94, 1.00, 1.],
-                [0.36, 1.00, 0.69, 1.],
-                [0.29, 1.00, 0.45, 1.],
-                [0.00, 0.73, 0.38, 1.],
-                [0.21, 0.67, 0.67, 1.],
-                [0.56, 0.61, 1.00, 1.],
-                [0.84, 0.48, 1.00, 1.],
-                [1.00, 0.61, 0.94, 1.],
-                [1.00, 0.36, 0.48, 1.],
-                [1.00, 0.30, 0.00, 1.],
-            ];
-            let nick_colors_u8 = [
-                [(255. * 0.00) as u8, (255. * 0.94) as u8, (255. * 1.00) as u8, (255. * 1.) as u8],
-                [(255. * 0.36) as u8, (255. * 1.00) as u8, (255. * 0.69) as u8, (255. * 1.) as u8],
-                [(255. * 0.29) as u8, (255. * 1.00) as u8, (255. * 0.45) as u8, (255. * 1.) as u8],
-                [(255. * 0.00) as u8, (255. * 0.73) as u8, (255. * 0.38) as u8, (255. * 1.) as u8],
-                [(255. * 0.21) as u8, (255. * 0.67) as u8, (255. * 0.67) as u8, (255. * 1.) as u8],
-                [(255. * 0.56) as u8, (255. * 0.61) as u8, (255. * 1.00) as u8, (255. * 1.) as u8],
-                [(255. * 0.84) as u8, (255. * 0.48) as u8, (255. * 1.00) as u8, (255. * 1.) as u8],
-                [(255. * 1.00) as u8, (255. * 0.61) as u8, (255. * 0.94) as u8, (255. * 1.) as u8],
-                [(255. * 1.00) as u8, (255. * 0.36) as u8, (255. * 0.48) as u8, (255. * 1.) as u8],
-                [(255. * 1.00) as u8, (255. * 0.30) as u8, (255. * 0.00) as u8, (255. * 1.) as u8],
-            ];
-
-            let nick_color = nick_colors[nick.len() % nick_colors.len()];
-            let nick_color_u8 = nick_colors_u8[nick.len() % nick_colors.len()];
-            let glyphs_nick = self.text_shaper.shape(nick.to_string(), font_size, nick_color);
-            let off_x = rhs + window_scale * 20.;
-            for glyph in glyphs_nick {
-                let mut pos = glyph.pos.clone();
-                pos.x += off_x;
-                pos.y += off_y;
-                rhs = pos.x + pos.w;
-
-                assert_eq!(glyph.bmp.len() as u16, glyph.bmp_width * glyph.bmp_height * 4);
-                //debug!("gly {} {}", glyph.substr, glyph.bmp.len());
-                //let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
-                let texture = if atlas.contains_key(&(glyph.id, nick_color_u8.clone())) {
-                    *atlas.get(&(glyph.id, nick_color_u8.clone())).unwrap()
-                } else {
-                    let texture = render.ctx.new_texture_from_rgba8(
-                        glyph.bmp_width,
-                        glyph.bmp_height,
-                        &glyph.bmp,
-                    );
-                    atlas.insert((glyph.id, nick_color_u8.clone()), texture);
-                    texture
-                };
-                render.render_clipped_box_with_texture2(&bound, &pos, COLOR_WHITE, texture);
-                //render.ctx.delete_texture(texture);
-            }
-
-            let off_x = rhs + window_scale * 20.;
-            for glyph in glyph_line {
-                let mut pos = glyph.pos.clone();
-                pos.x += off_x;
-                pos.y += off_y;
-
-                assert_eq!(glyph.bmp.len() as u16, glyph.bmp_width * glyph.bmp_height * 4);
-                //debug!("gly {} {}", glyph.substr, glyph.bmp.len());
-                //let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
-                let texture = if atlas.contains_key(&(glyph.id, [255, 255, 255, 255])) {
-                    *atlas.get(&(glyph.id, [255, 255, 255, 255])).unwrap()
-                } else {
-                    let texture = render.ctx.new_texture_from_rgba8(
-                        glyph.bmp_width,
-                        glyph.bmp_height,
-                        &glyph.bmp,
-                    );
-                    atlas.insert((glyph.id, [255, 255, 255, 255]), texture);
-                    texture
-                };
-                render.render_clipped_box_with_texture2(&bound, &pos, COLOR_WHITE, texture);
-                //render.ctx.delete_texture(texture);
-            }
-        }
-
-        if debug {
-            render.outline(0., 0., rect.w, rect.h, COLOR_RED, 1.);
-        }
-
-        Ok(())
-    }
-
-    fn mouse_scroll(self: Arc<Self>, _x: f32, y: f32) {
-        let mouse_pos = &*self.mouse_pos.lock().unwrap();
-        if !self.world_rect.lock().unwrap().contains(mouse_pos) {
-            return;
-        }
-        drop(mouse_pos);
-
-        self.scroll.fetch_add(y * 10., Ordering::Relaxed);
-        // y =  1 for scroll up
-        // y = -1 for scroll down
-        //println!("{}", y);
-    }
-}

+ 1 - 1
bin/darkwallet/src/darkirc.rs

@@ -39,7 +39,7 @@ use darkfi_serial::{
 use crate::{
     net::ZeroMQAdapter,
     scene::{SceneGraph, SceneGraphPtr2},
-    text2::TextShaper,
+    text::TextShaper,
     ExecutorPtr,
 };
 

+ 0 - 865
bin/darkwallet/src/editbox.rs

@@ -1,865 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2024 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use log::{debug, info};
-use miniquad::{window, KeyMods, MouseButton, TextureId, UniformType};
-use std::{
-    collections::HashMap,
-    sync::{
-        atomic::{AtomicBool, Ordering},
-        Arc, Mutex,
-    },
-    time::Instant,
-};
-
-use crate::{
-    error::{Error, Result},
-    gfx::{
-        FreetypeFace, Point, Rectangle, RenderContext, COLOR_DARKGREY, COLOR_GREEN, COLOR_WHITE,
-    },
-    prop::{Property, PropertyBool, PropertyColor, PropertyFloat32, PropertyStr, PropertyUint32},
-    scene::{Pimpl, SceneGraph, SceneNodeId},
-    text::{Glyph, TextShaper},
-};
-
-const CURSOR_WIDTH: f32 = 4.;
-
-struct PressedKeysSmoothRepeat {
-    /// When holding keys, we track from start and last sent time.
-    /// This is useful for initial delay and smooth scrolling.
-    pressed_keys: HashMap<String, RepeatingKeyTimer>,
-    /// Initial delay before allowing keys
-    start_delay: u32,
-    /// Minimum time between repeated keys
-    step_time: u32,
-}
-
-impl PressedKeysSmoothRepeat {
-    fn new(start_delay: u32, step_time: u32) -> Self {
-        Self { pressed_keys: HashMap::new(), start_delay, step_time }
-    }
-
-    fn key_down(&mut self, key: &str, repeat: bool) -> u32 {
-        if !repeat {
-            return 1;
-        }
-
-        // Insert key if not exists
-        if !self.pressed_keys.contains_key(key) {
-            self.pressed_keys.insert(key.to_string(), RepeatingKeyTimer::new());
-        }
-
-        let repeater = self.pressed_keys.get_mut(key).expect("repeat map");
-        repeater.update(self.start_delay, self.step_time)
-    }
-
-    fn key_up(&mut self, key: &str) {
-        self.pressed_keys.remove(key);
-    }
-}
-
-struct RepeatingKeyTimer {
-    start: Instant,
-    actions: u32,
-}
-
-impl RepeatingKeyTimer {
-    fn new() -> Self {
-        Self { start: Instant::now(), actions: 0 }
-    }
-
-    fn update(&mut self, start_delay: u32, step_time: u32) -> u32 {
-        let elapsed = self.start.elapsed().as_millis();
-        if elapsed < start_delay as u128 {
-            return 0
-        }
-        let total_actions = ((elapsed - start_delay as u128) / step_time as u128) as u32;
-        let remaining_actions = total_actions - self.actions;
-        self.actions = total_actions;
-        remaining_actions
-    }
-}
-
-pub type EditBoxPtr = Arc<EditBox>;
-
-pub struct EditBox {
-    node_name: String,
-    is_active: PropertyBool,
-    debug: PropertyBool,
-    baseline: PropertyFloat32,
-    scroll: PropertyFloat32,
-    cursor_pos: PropertyUint32,
-    selected: Arc<Property>,
-    text: PropertyStr,
-    font_size: PropertyFloat32,
-    text_color: PropertyColor,
-    cursor_color: PropertyColor,
-    hi_bg_color: PropertyColor,
-    // Used for mouse clicks
-    world_rect: Mutex<Rectangle<f32>>,
-    glyphs: Mutex<Vec<Glyph>>,
-    text_shaper: TextShaper,
-    key_repeat: Mutex<PressedKeysSmoothRepeat>,
-    mouse_btn_held: AtomicBool,
-    window_scale: f32,
-    screen_size: Arc<Property>,
-    atlas: Mutex<HashMap<u32, TextureId>>,
-}
-
-impl EditBox {
-    pub fn new(
-        scene_graph: &mut SceneGraph,
-        node_id: SceneNodeId,
-        font_faces: Vec<FreetypeFace>,
-    ) -> Result<Pimpl> {
-        let node = scene_graph.get_node(node_id).unwrap();
-        let node_name = node.name.clone();
-        let is_active = PropertyBool::wrap(node, "is_active", 0)?;
-        let debug = PropertyBool::wrap(node, "debug", 0)?;
-        let baseline = PropertyFloat32::wrap(node, "baseline", 0)?;
-        let scroll = PropertyFloat32::wrap(node, "scroll", 0)?;
-        let cursor_pos = PropertyUint32::wrap(node, "cursor_pos", 0)?;
-        let selected = node.get_property("selected").ok_or(Error::PropertyNotFound)?;
-        let text = PropertyStr::wrap(node, "text", 0)?;
-        let font_size = PropertyFloat32::wrap(node, "font_size", 0)?;
-        let text_color = PropertyColor::wrap(node, "text_color")?;
-        let cursor_color = PropertyColor::wrap(node, "cursor_color")?;
-        let hi_bg_color = PropertyColor::wrap(node, "hi_bg_color")?;
-
-        let text_shaper = TextShaper { font_faces };
-
-        // TODO: catch window resize event and regen glyphs
-        // Used for scaling the font size
-        let window_node = scene_graph.lookup_node("/window").expect("no window attached!");
-        let window_scale = window_node.get_property_f32("scale")?;
-        let screen_size = window_node.get_property("screen_size").ok_or(Error::PropertyNotFound)?;
-
-        let self_ = Arc::new(Self {
-            node_name: node_name.clone(),
-            is_active,
-            debug,
-            baseline,
-            scroll,
-            cursor_pos,
-            selected,
-            text,
-            font_size,
-            text_color,
-            cursor_color,
-            hi_bg_color,
-            world_rect: Mutex::new(Rectangle { x: 0., y: 0., w: 0., h: 0. }),
-            glyphs: Mutex::new(vec![]),
-            text_shaper,
-            key_repeat: Mutex::new(PressedKeysSmoothRepeat::new(400, 50)),
-            mouse_btn_held: AtomicBool::new(false),
-            window_scale,
-            screen_size,
-            atlas: Mutex::new(HashMap::new()),
-        });
-        self_.regen_glyphs().unwrap();
-
-        /*
-        let weak_self = Arc::downgrade(&self_);
-        let slot_key_down = Slot {
-            name: format!("{}::key_down", node_name),
-            func: Box::new(move |data| {
-                let mut cur = Cursor::new(&data);
-                let keymods = KeyMods {
-                    shift: Decodable::decode(&mut cur).unwrap(),
-                    ctrl: Decodable::decode(&mut cur).unwrap(),
-                    alt: Decodable::decode(&mut cur).unwrap(),
-                    logo: Decodable::decode(&mut cur).unwrap(),
-                };
-                let repeat = bool::decode(&mut cur).unwrap();
-                let key = String::decode(&mut cur).unwrap();
-
-                let self_ = weak_self.upgrade();
-                if let Some(self_) = self_ {
-                    self_.key_down(key, keymods, repeat);
-                }
-            }),
-        };
-        let weak_self = Arc::downgrade(&self_);
-        let slot_key_up = Slot {
-            name: format!("{}::key_up", node_name),
-            func: Box::new(move |data| {
-                let mut cur = Cursor::new(&data);
-                let keymods = KeyMods {
-                    shift: Decodable::decode(&mut cur).unwrap(),
-                    ctrl: Decodable::decode(&mut cur).unwrap(),
-                    alt: Decodable::decode(&mut cur).unwrap(),
-                    logo: Decodable::decode(&mut cur).unwrap(),
-                };
-                let key = String::decode(&mut cur).unwrap();
-
-                let self_ = weak_self.upgrade();
-                if let Some(self_) = self_ {
-                    self_.key_up(key, keymods);
-                }
-            }),
-        };
-
-        let keyb_node =
-            scene_graph
-            .lookup_node_mut("/window/input/keyboard")
-            .expect("no keyboard attached!");
-        keyb_node.register("key_down", slot_key_down).unwrap();
-        keyb_node.register("key_up", slot_key_up).unwrap();
-
-        let weak_self = Arc::downgrade(&self_);
-        let slot_btn_down = Slot {
-            name: format!("{}::mouse_button_down", node_name),
-            func: Box::new(move |data| {
-                let mut cur = Cursor::new(&data);
-                let button = MouseButton::from_u8(u8::decode(&mut cur).unwrap());
-                let x = f32::decode(&mut cur).unwrap();
-                let y = f32::decode(&mut cur).unwrap();
-
-                let self_ = weak_self.upgrade();
-                if let Some(self_) = self_ {
-                    self_.mouse_button_down(button, x, y);
-                }
-            }),
-        };
-
-        let weak_self = Arc::downgrade(&self_);
-        let slot_btn_up = Slot {
-            name: format!("{}::mouse_button_up", node_name),
-            func: Box::new(move |data| {
-                let mut cur = Cursor::new(&data);
-                let button = MouseButton::from_u8(u8::decode(&mut cur).unwrap());
-                let x = f32::decode(&mut cur).unwrap();
-                let y = f32::decode(&mut cur).unwrap();
-
-                let self_ = weak_self.upgrade();
-                if let Some(self_) = self_ {
-                    self_.mouse_button_up(button, x, y);
-                }
-            }),
-        };
-
-        let weak_self = Arc::downgrade(&self_);
-        let slot_move = Slot {
-            name: format!("{}::mouse_move", node_name),
-            func: Box::new(move |data| {
-                let mut cur = Cursor::new(&data);
-                let x = f32::decode(&mut cur).unwrap();
-                let y = f32::decode(&mut cur).unwrap();
-
-                let self_ = weak_self.upgrade();
-                if let Some(self_) = self_ {
-                    self_.mouse_move(x, y);
-                }
-            }),
-        };
-
-        let mouse_node =
-            scene_graph
-            .lookup_node_mut("/window/input/mouse")
-            .expect("no mouse attached!");
-        mouse_node.register("button_down", slot_btn_down).unwrap();
-        mouse_node.register("button_up", slot_btn_up).unwrap();
-        mouse_node.register("move", slot_move).unwrap();
-
-        let weak_self = Arc::downgrade(&self_);
-        let slot_resize = Slot {
-            name: format!("{}::window_resize", node_name),
-            func: Box::new(move |data| {
-                let mut cur = Cursor::new(&data);
-                let w = f32::decode(&mut cur).unwrap();
-                let h = f32::decode(&mut cur).unwrap();
-
-                let self_ = weak_self.upgrade();
-                if let Some(self_) = self_ {
-                    self_.window_resize(w, h);
-                }
-            }),
-        };
-        */
-
-        let window_node = scene_graph.lookup_node_mut("/window").expect("no window attached!");
-        //window_node.register("resize", slot_resize).unwrap();
-
-        // Save any properties we use
-        Ok(Pimpl::EditBox(self_))
-    }
-
-    pub fn render<'a>(
-        &self,
-        render: &mut RenderContext<'a>,
-        node_id: SceneNodeId,
-        layer_rect: &Rectangle<f32>,
-    ) -> Result<()> {
-        let node = render.scene_graph.get_node(node_id).unwrap();
-
-        let rect = RenderContext::get_dim(node, layer_rect)?;
-
-        // Used for detecting mouse clicks
-        let mut world_rect = rect.clone();
-        world_rect.x += layer_rect.x as f32;
-        world_rect.y += layer_rect.y as f32;
-        world_rect.x *= self.window_scale;
-        world_rect.y *= self.window_scale;
-        world_rect.w *= self.window_scale;
-        world_rect.h *= self.window_scale;
-        *self.world_rect.lock().unwrap() = world_rect;
-
-        let layer_w = layer_rect.w as f32;
-        let layer_h = layer_rect.h as f32;
-        let off_x = rect.x / layer_w;
-        let off_y = rect.y / layer_h;
-        // Use absolute pixel scale
-        let scale_x = 1. / layer_w;
-        let scale_y = 1. / layer_h;
-        //let model = glam::Mat4::IDENTITY;
-        let model = glam::Mat4::from_translation(glam::Vec3::new(off_x, off_y, 0.)) *
-            glam::Mat4::from_scale(glam::Vec3::new(scale_x, scale_y, 1.));
-
-        let mut uniforms_data = [0u8; 128];
-        let data: [u8; 64] = unsafe { std::mem::transmute_copy(&render.proj) };
-        uniforms_data[0..64].copy_from_slice(&data);
-        let data: [u8; 64] = unsafe { std::mem::transmute_copy(&model) };
-        uniforms_data[64..].copy_from_slice(&data);
-        assert_eq!(128, 2 * UniformType::Mat4.size());
-
-        render.ctx.apply_uniforms_from_bytes(uniforms_data.as_ptr(), uniforms_data.len());
-
-        self.apply_cursor_scrolling(&rect);
-
-        let node = render.scene_graph.get_node(node_id).unwrap();
-        let debug = self.debug.get();
-        let baseline = self.baseline.get();
-        let scroll = self.scroll.get();
-        let cursor_pos = self.cursor_pos.get() as usize;
-        let cursor_color = self.cursor_color.get();
-        let text_color = self.text_color.get();
-
-        let glyphs = &*self.glyphs.lock().unwrap();
-        let atlas = &mut self.atlas.lock().unwrap();
-
-        if !self.selected.is_null(0)? && !self.selected.is_null(1)? {
-            self.render_selected(render, &rect, glyphs)?;
-        }
-
-        let bound = Rectangle { x: 0., y: 0., w: rect.w, h: rect.h };
-
-        let mut rhs = 0.;
-        for (glyph_idx, glyph) in glyphs.iter().enumerate() {
-            let x1 = glyph.pos.x + scroll;
-            let y1 = glyph.pos.y + baseline;
-            let x2 = x1 + glyph.pos.w;
-            let y2 = y1 + glyph.pos.h;
-
-            let texture = if atlas.contains_key(&glyph.id) {
-                *atlas.get(&glyph.id).unwrap()
-            } else {
-                let texture = render.ctx.new_texture_from_rgba8(
-                    glyph.bmp_width,
-                    glyph.bmp_height,
-                    &glyph.bmp,
-                );
-                atlas.insert(glyph.id, texture);
-                texture
-            };
-            //let texture = render.ctx.new_texture_from_rgba8(glyph.bmp_width, glyph.bmp_height, &glyph.bmp);
-            render.render_clipped_box_with_texture(&bound, x1, y1, x2, y2, COLOR_WHITE, texture);
-            //render.render_box_with_texture(x1, y1, x2, y2, COLOR_WHITE, texture);
-            //render.ctx.delete_texture(texture);
-
-            // Glyph outlines
-            //if debug {
-            //    render.outline(x1, y1, x2, y2, COLOR_BLUE, 1.);
-            //}
-
-            if cursor_pos != 0 && cursor_pos == glyph_idx {
-                render.render_box(x1 - CURSOR_WIDTH, 0., x1, rect.h, cursor_color);
-            }
-
-            rhs = x2;
-        }
-
-        if cursor_pos == 0 {
-            render.render_box(0., 0., CURSOR_WIDTH, rect.h, cursor_color);
-        } else if cursor_pos == glyphs.len() {
-            render.render_box(rhs - CURSOR_WIDTH, 0., rhs, rect.h, cursor_color);
-        }
-
-        if debug {
-            let outline_color = if self.is_active.get() { COLOR_GREEN } else { COLOR_DARKGREY };
-            // Baseline
-            //render.hline(0., rhs, 0., COLOR_RED, 1.);
-            render.outline(0., 0., rect.w, rect.h, outline_color, 1.);
-        }
-
-        Ok(())
-    }
-
-    pub fn render_selected<'a>(
-        &self,
-        render: &mut RenderContext<'a>,
-        rect: &Rectangle<f32>,
-        glyphs: &Vec<Glyph>,
-    ) -> Result<()> {
-        let start = self.selected.get_u32(0)? as usize;
-        let end = self.selected.get_u32(1)? as usize;
-
-        let sel_start = std::cmp::min(start, end);
-        let sel_end = std::cmp::max(start, end);
-
-        let scroll = self.scroll.get();
-        let hi_bg_color = self.hi_bg_color.get();
-
-        let mut start_x = 0.;
-        let mut end_x = 0.;
-
-        for (glyph_idx, glyph) in glyphs.iter().enumerate() {
-            let x1 = glyph.pos.x + scroll;
-
-            if glyph_idx == sel_start {
-                start_x = x1;
-            }
-            if glyph_idx == sel_end {
-                end_x = x1;
-            }
-        }
-        if sel_start == 0 {
-            start_x = scroll;
-        }
-        if sel_end == glyphs.len() {
-            let glyph = &glyphs.last().unwrap();
-            let x2 = glyph.pos.x + scroll + glyph.pos.w;
-            end_x = x2;
-        }
-
-        // Apply clipping
-        if start_x < 0. {
-            start_x = 0.;
-        }
-        if end_x > rect.w {
-            end_x = rect.w;
-        }
-        render.render_box(start_x, 0., end_x, rect.h, hi_bg_color);
-        Ok(())
-    }
-
-    fn delete_highlighted(&self) {
-        assert!(!self.selected.is_null(0).unwrap());
-        assert!(!self.selected.is_null(1).unwrap());
-
-        let start = self.selected.get_u32(0).unwrap() as usize;
-        let end = self.selected.get_u32(1).unwrap() as usize;
-
-        let sel_start = std::cmp::min(start, end);
-        let sel_end = std::cmp::max(start, end);
-
-        let glyphs = &*self.glyphs.lock().unwrap();
-
-        // Regen text
-        let mut text = String::new();
-        for (i, glyph) in glyphs.iter().enumerate() {
-            let mut substr = glyph.substr.clone();
-            if sel_start <= i && i < sel_end {
-                continue
-            }
-            text.push_str(&substr);
-        }
-        debug!(
-            "EditBox(\"{}\")::delete_highlighted() text=\"{}\", cursor_pos={}",
-            self.node_name, text, sel_start
-        );
-        self.text.set(text);
-
-        self.selected.set_null(0).unwrap();
-        self.selected.set_null(1).unwrap();
-        self.cursor_pos.set(sel_start as u32);
-    }
-
-    fn apply_cursor_scrolling(&self, rect: &Rectangle<f32>) {
-        let cursor_pos = self.cursor_pos.get() as usize;
-        let mut scroll = self.scroll.get();
-
-        let cursor_x = {
-            let glyphs = &*self.glyphs.lock().unwrap();
-            if cursor_pos == 0 {
-                0.
-            } else if cursor_pos == glyphs.len() {
-                let glyph = &glyphs.last().unwrap();
-                glyph.pos.x + glyph.pos.w
-            } else {
-                assert!(cursor_pos < glyphs.len());
-                let glyph = &glyphs[cursor_pos];
-                glyph.pos.x
-            }
-        };
-
-        let cursor_lhs = cursor_x + scroll;
-        let cursor_rhs = cursor_lhs + CURSOR_WIDTH;
-
-        if cursor_rhs > rect.w {
-            scroll = rect.w - cursor_x;
-        } else if cursor_lhs < 0. {
-            scroll = -cursor_x + CURSOR_WIDTH;
-        }
-
-        self.scroll.set(scroll);
-    }
-
-    fn regen_glyphs(&self) -> Result<()> {
-        let font_size = self.window_scale * self.font_size.get();
-
-        debug!("shape start");
-        let glyphs = self.text_shaper.shape(self.text.get(), font_size, self.text_color.get());
-        debug!("shape end");
-        if self.cursor_pos.get() > glyphs.len() as u32 {
-            self.cursor_pos.set(glyphs.len() as u32);
-        }
-        *self.glyphs.lock().unwrap() = glyphs;
-        Ok(())
-    }
-
-    fn key_down(self: Arc<Self>, key: String, mods: KeyMods, repeat: bool) {
-        if !self.is_active.get() {
-            return
-        }
-        let actions = {
-            let mut repeater = self.key_repeat.lock().unwrap();
-            repeater.key_down(&key, repeat)
-        };
-        for _ in 0..actions {
-            self.do_key_down(&key, &mods)
-        }
-    }
-
-    fn do_key_down(&self, key: &str, mods: &KeyMods) {
-        match key {
-            "Left" => {
-                let mut cursor_pos = self.cursor_pos.get();
-
-                // Start selection if shift is held
-                if !mods.shift {
-                    self.selected.set_null(0).unwrap();
-                    self.selected.set_null(1).unwrap();
-                } else if self.selected.is_null(0).unwrap() {
-                    assert!(self.selected.is_null(1).unwrap());
-                    self.selected.set_u32(0, cursor_pos).unwrap();
-                }
-
-                if cursor_pos > 0 {
-                    cursor_pos -= 1;
-                    debug!(
-                        "EditBox(\"{}\")::key_down(Left) cursor_pos={}",
-                        self.node_name, cursor_pos
-                    );
-                    self.cursor_pos.set(cursor_pos);
-                }
-
-                // Update selection
-                if mods.shift {
-                    self.selected.set_u32(1, cursor_pos).unwrap();
-                }
-            }
-            "Right" => {
-                let mut cursor_pos = self.cursor_pos.get();
-
-                // Start selection if shift is held
-                if !mods.shift {
-                    self.selected.set_null(0).unwrap();
-                    self.selected.set_null(1).unwrap();
-                } else if self.selected.is_null(0).unwrap() {
-                    assert!(self.selected.is_null(1).unwrap());
-                    self.selected.set_u32(0, cursor_pos).unwrap();
-                }
-
-                let glyphs_len = self.glyphs.lock().unwrap().len() as u32;
-                if cursor_pos < glyphs_len {
-                    cursor_pos += 1;
-                    debug!(
-                        "EditBox(\"{}\")::key_down(Right) cursor_pos={}",
-                        self.node_name, cursor_pos
-                    );
-                    self.cursor_pos.set(cursor_pos);
-                }
-
-                // Update selection
-                if mods.shift {
-                    self.selected.set_u32(1, cursor_pos).unwrap();
-                }
-            }
-            "Delete" => {
-                let cursor_pos = self.cursor_pos.get();
-
-                let _text = if !self.selected.is_null(0).unwrap() {
-                    self.delete_highlighted();
-                } else {
-                    let glyphs = &*self.glyphs.lock().unwrap();
-
-                    if cursor_pos == glyphs.len() as u32 {
-                        return;
-                    }
-
-                    // Regen text
-                    let mut text = String::new();
-                    for (i, glyph) in glyphs.iter().enumerate() {
-                        let mut substr = glyph.substr.clone();
-                        if cursor_pos as usize == i {
-                            // Lmk if anyone knows a better way to do substr.pop_front()
-                            let mut chars = substr.chars();
-                            chars.next();
-                            substr = chars.as_str().to_string();
-                        }
-                        text.push_str(&substr);
-                    }
-                    self.text.set(text);
-                };
-                self.regen_glyphs().unwrap();
-            }
-            "Backspace" => {
-                let cursor_pos = self.cursor_pos.get();
-
-                let _text = if !self.selected.is_null(0).unwrap() {
-                    self.delete_highlighted();
-                } else {
-                    if cursor_pos == 0 {
-                        return;
-                    }
-
-                    let glyphs = &*self.glyphs.lock().unwrap();
-
-                    let mut text = String::new();
-                    for (i, glyph) in glyphs.iter().enumerate() {
-                        let mut substr = glyph.substr.clone();
-                        if cursor_pos as usize - 1 == i {
-                            substr.pop().unwrap();
-                        }
-                        text.push_str(&substr);
-                    }
-                    self.text.set(text);
-                    self.cursor_pos.set(cursor_pos - 1);
-                };
-                self.regen_glyphs().unwrap();
-            }
-            "C" => {
-                if mods.ctrl {
-                    self.copy_highlighted_text().unwrap();
-                } else {
-                    self.insert_char(key, mods);
-                }
-            }
-            "V" => {
-                if mods.ctrl {
-                    if let Some(text) = window::clipboard_get() {
-                        self.insert_text(text);
-                    }
-                } else {
-                    self.insert_char(key, mods);
-                }
-            }
-            _ => {
-                self.insert_char(key, mods);
-            }
-        }
-    }
-
-    fn insert_char(&self, key: &str, mods: &KeyMods) {
-        // First filter for only single digit keys
-        let allowed_keys = [
-            "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q",
-            "R", "S", "T", "U", "V", "W", "X", "Y", "Z", " ", ":", ";", "'", "-", ".", "/", "=",
-            "(", "\\", ")", "`", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
-        ];
-        if !allowed_keys.contains(&key) {
-            return
-        }
-
-        // If we want to only allow specific chars in a String here
-        //let ch = key.chars().next().unwrap();
-        // if !self.allowed_chars.chars().any(|c| c == ch) { return }
-
-        let key = if mods.shift { key.to_string() } else { key.to_lowercase() };
-
-        self.insert_text(key);
-    }
-
-    fn insert_text(&self, key: String) {
-        let mut text = String::new();
-
-        let cursor_pos = self.cursor_pos.get();
-
-        if cursor_pos == 0 {
-            text = key;
-        } else {
-            let glyphs = &*self.glyphs.lock().unwrap();
-            for (glyph_idx, glyph) in glyphs.iter().enumerate() {
-                text.push_str(&glyph.substr);
-                if cursor_pos == glyph_idx as u32 + 1 {
-                    text.push_str(&key);
-                }
-            }
-        }
-        self.text.set(text);
-        // Not always true lol
-        self.cursor_pos.set(cursor_pos + 1);
-        self.regen_glyphs().unwrap();
-    }
-
-    fn copy_highlighted_text(&self) -> Result<()> {
-        let start = self.selected.get_u32(0)? as usize;
-        let end = self.selected.get_u32(1)? as usize;
-
-        let sel_start = std::cmp::min(start, end);
-        let sel_end = std::cmp::max(start, end);
-
-        let mut text = String::new();
-
-        let glyphs = &*self.glyphs.lock().unwrap();
-        for (glyph_idx, glyph) in glyphs.iter().enumerate() {
-            if sel_start <= glyph_idx && glyph_idx < sel_end {
-                text.push_str(&glyph.substr);
-            }
-        }
-
-        info!("Copied '{}'", text);
-        window::clipboard_set(&text);
-        Ok(())
-    }
-
-    fn key_up(self: Arc<Self>, key: String, mods: KeyMods) {
-        let mut repeater = self.key_repeat.lock().unwrap();
-        repeater.key_up(&key);
-    }
-
-    fn mouse_button_down(self: Arc<Self>, button: MouseButton, x: f32, y: f32) {
-        let mouse_pos = Point { x, y };
-        let rect = self.world_rect.lock().unwrap().clone();
-        debug!("mouse down event {} {} {} {} {} {}", x, y, rect.x, rect.y, rect.w, rect.h);
-
-        // clicking inside box will:
-        // 1. make it active
-        // 2. begin selection
-        if rect.contains(&mouse_pos) {
-            debug!("showkeyb!");
-            window::show_keyboard(true);
-            if !self.is_active.get() {
-                self.is_active.set(true);
-                println!("inside!");
-                // Send signal
-            }
-
-            let cpos = match self.find_closest_glyph_idx(x) {
-                MouseClickGlyph::Pos(cpos) => cpos,
-                _ => panic!("shouldn't be possible to reach here!"),
-            };
-
-            // set cursor pos
-            self.cursor_pos.set(cpos);
-
-            // begin selection
-            self.selected.set_u32(0, cpos).unwrap();
-            self.selected.set_u32(1, cpos).unwrap();
-            self.mouse_btn_held.store(true, Ordering::Relaxed);
-        }
-        // click outside the box will:
-        // 1. make it inactive
-        else {
-            if self.is_active.get() {
-                self.is_active.set(false);
-                // Send signal
-            }
-        }
-    }
-    fn mouse_button_up(self: Arc<Self>, button: MouseButton, x: f32, y: f32) {
-        // releasing mouse button will:
-        // 1. end selection
-        self.mouse_btn_held.store(false, Ordering::Relaxed);
-    }
-    fn mouse_move(self: Arc<Self>, x: f32, y: f32) {
-        if !self.mouse_btn_held.load(Ordering::Relaxed) {
-            return;
-        }
-
-        // if active and selection_active, then use x to modify the selection.
-        // also implement scrolling when cursor is to the left or right
-        // just scroll to the end
-        // also set cursor_pos too
-
-        let cpos = match self.find_closest_glyph_idx(x) {
-            MouseClickGlyph::Lhs => 0,
-            MouseClickGlyph::Pos(cpos) => cpos,
-            MouseClickGlyph::Rhs(cpos) => cpos,
-        };
-
-        self.cursor_pos.set(cpos);
-        self.selected.set_u32(1, cpos).unwrap();
-    }
-
-    // Uses screen x pos
-    fn find_closest_glyph_idx(&self, x: f32) -> MouseClickGlyph {
-        let rect = self.world_rect.lock().unwrap().clone();
-        let glyphs = &*self.glyphs.lock().unwrap();
-
-        let mouse_x = x - rect.x;
-
-        if mouse_x > rect.w {
-            // Highlight to the end
-            let cpos = glyphs.len() as u32;
-            return MouseClickGlyph::Rhs(cpos);
-            // Scroll to the right handled in render
-        } else if mouse_x < 0. {
-            return MouseClickGlyph::Lhs;
-        }
-
-        let scroll = self.scroll.get();
-
-        let mouse_x = x - rect.x;
-        let mut cpos = 0;
-        let lhs = 0.;
-        let mut last_d = (lhs - mouse_x).abs();
-
-        for (i, glyph) in glyphs.iter().skip(1).enumerate() {
-            // Because we skip the first item
-            let glyph_idx = (i + 1) as u32;
-
-            let x1 = glyph.pos.x + scroll;
-            let curr_d = (x1 - mouse_x).abs();
-            if curr_d < last_d {
-                last_d = curr_d;
-                cpos = glyph_idx;
-            }
-        }
-        // also check the right hand side
-        let rhs = {
-            let glyph = &glyphs.last().unwrap();
-            glyph.pos.x + scroll + glyph.pos.w
-        };
-        let curr_d = (rhs - mouse_x).abs();
-        if curr_d < last_d {
-            //last_d = curr_d;
-            cpos = glyphs.len() as u32;
-        }
-
-        MouseClickGlyph::Pos(cpos)
-    }
-
-    fn window_resize(self: Arc<Self>, w: f32, h: f32) {}
-}
-
-enum MouseClickGlyph {
-    Lhs,
-    Pos(u32),
-    Rhs(u32),
-}

+ 0 - 1352
bin/darkwallet/src/gfx.rs

@@ -1,1352 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2024 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use darkfi_serial::{Decodable, Encodable, SerialDecodable, SerialEncodable};
-use freetype as ft;
-use miniquad::{
-    conf, window, Backend, Bindings, BlendFactor, BlendState, BlendValue, BufferId, BufferLayout,
-    BufferSource, BufferType, BufferUsage, Equation, EventHandler, KeyCode, KeyMods, MouseButton,
-    PassAction, Pipeline, PipelineParams, RenderingBackend, ShaderMeta, ShaderSource, TextureId,
-    UniformDesc, UniformType, VertexAttribute, VertexFormat,
-};
-use std::{
-    array::IntoIter,
-    collections::HashMap,
-    fmt,
-    io::Cursor,
-    sync::{mpsc, Mutex, MutexGuard},
-    time::{Duration, Instant},
-};
-
-use crate::{
-    chatview, editbox,
-    error::{Error, Result},
-    expr::{SExprMachine, SExprVal},
-    keysym::{KeyCodeAsStr, MouseButtonAsU8},
-    prop::{Property, PropertySubType, PropertyType},
-    res::{ResourceId, ResourceManager},
-    scene::{
-        MethodResponseFn, Pimpl, SceneGraph, SceneGraphPtr, SceneNode, SceneNodeId, SceneNodeInfo,
-        SceneNodeType,
-    },
-    shader,
-};
-
-type Color = [f32; 4];
-
-pub const COLOR_RED: Color = [1., 0., 0., 1.];
-pub const COLOR_DARKGREY: Color = [0.2, 0.2, 0.2, 1.];
-pub const COLOR_GREEN: Color = [0., 1., 0., 1.];
-pub const COLOR_BLUE: Color = [0., 0., 1., 1.];
-pub const COLOR_WHITE: Color = [1., 1., 1., 1.];
-
-#[derive(Debug, SerialEncodable, SerialDecodable)]
-#[repr(C)]
-struct Vertex {
-    pos: [f32; 2],
-    color: [f32; 4],
-    uv: [f32; 2],
-}
-
-#[derive(SerialEncodable, SerialDecodable)]
-#[repr(C)]
-struct Face {
-    idxs: [u32; 3],
-}
-
-impl fmt::Debug for Face {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{:?}", self.idxs)
-    }
-}
-
-struct Mesh {
-    pub verts: Vec<Vertex>,
-    pub faces: Vec<Face>,
-    pub vertex_buffer: BufferId,
-    pub index_buffer: BufferId,
-}
-
-pub struct Point<T> {
-    pub x: T,
-    pub y: T,
-}
-
-#[derive(Debug, Clone)]
-pub struct Rectangle<
-    T: Copy + std::ops::Add<Output = T> + std::ops::Sub<Output = T> + std::cmp::PartialOrd,
-> {
-    pub x: T,
-    pub y: T,
-    pub w: T,
-    pub h: T,
-}
-
-impl<
-        T: Copy
-            + std::ops::Add<Output = T>
-            + std::ops::Sub<Output = T>
-            + std::ops::AddAssign
-            + std::cmp::PartialOrd,
-    > Rectangle<T>
-{
-    pub fn from_array(arr: [T; 4]) -> Self {
-        let mut iter = IntoIter::new(arr);
-        Self {
-            x: iter.next().unwrap(),
-            y: iter.next().unwrap(),
-            w: iter.next().unwrap(),
-            h: iter.next().unwrap(),
-        }
-    }
-
-    pub fn clip(&self, other: &Self) -> Option<Self> {
-        if other.x + other.w < self.x ||
-            other.x > self.x + self.w ||
-            other.y + other.h < self.y ||
-            other.y > self.y + self.h
-        {
-            return None
-        }
-
-        let mut clipped = other.clone();
-        if clipped.x < self.x {
-            clipped.x = self.x;
-            clipped.w = other.x + other.w - clipped.x;
-        }
-        if clipped.y < self.y {
-            clipped.y = self.y;
-            clipped.h = other.y + other.h - clipped.y;
-        }
-        if clipped.x + clipped.w > self.x + self.w {
-            clipped.w = self.x + self.w - clipped.x;
-        }
-        if clipped.y + clipped.h > self.y + self.h {
-            clipped.h = self.y + self.h - clipped.y;
-        }
-        Some(clipped)
-    }
-
-    pub fn contains(&self, point: &Point<T>) -> bool {
-        self.x <= point.x &&
-            point.x <= self.x + self.w &&
-            self.y <= point.y &&
-            point.y <= self.y + self.h
-    }
-
-    pub fn top_left(&self) -> Point<T> {
-        Point { x: self.x, y: self.y }
-    }
-    pub fn bottom_right(&self) -> Point<T> {
-        Point { x: self.x + self.w, y: self.y + self.h }
-    }
-
-    pub fn includes(&self, child: &Self) -> bool {
-        self.contains(&child.top_left()) && self.contains(&child.bottom_right())
-    }
-}
-
-pub type FreetypeFace = ft::Face<&'static [u8]>;
-
-#[derive(Debug)]
-enum GraphicsMethodEvent {
-    LoadTexture,
-    DeleteTexture,
-    CreateChatView,
-    CreateEditBox,
-}
-
-struct Stage {
-    ctx: Box<dyn RenderingBackend>,
-    pipeline: Pipeline,
-
-    scene_graph: SceneGraphPtr,
-
-    textures: ResourceManager<TextureId>,
-    font_faces: Vec<FreetypeFace>,
-
-    method_recvr: mpsc::Receiver<(GraphicsMethodEvent, SceneNodeId, Vec<u8>, MethodResponseFn)>,
-    method_sender: mpsc::SyncSender<(GraphicsMethodEvent, SceneNodeId, Vec<u8>, MethodResponseFn)>,
-
-    last_draw_time: Option<Instant>,
-    atlas: Mutex<HashMap<(u32, [u8; 4]), TextureId>>,
-}
-
-impl Stage {
-    const WHITE_TEXTURE_ID: ResourceId = 0;
-
-    pub fn new(scene_graph: SceneGraphPtr) -> Self {
-        let mut ctx: Box<dyn RenderingBackend> = window::new_rendering_backend();
-
-        let white_texture = ctx.new_texture_from_rgba8(1, 1, &[255, 255, 255, 255]);
-        let mut textures = ResourceManager::new();
-        let white_texture_id = textures.alloc(white_texture);
-        assert_eq!(white_texture_id, Self::WHITE_TEXTURE_ID);
-
-        let mut shader_meta: ShaderMeta = shader::meta();
-        shader_meta.uniforms.uniforms.push(UniformDesc::new("Projection", UniformType::Mat4));
-        shader_meta.uniforms.uniforms.push(UniformDesc::new("Model", UniformType::Mat4));
-
-        let shader = ctx
-            .new_shader(
-                match ctx.info().backend {
-                    Backend::OpenGl => ShaderSource::Glsl {
-                        vertex: shader::GL_VERTEX,
-                        fragment: shader::GL_FRAGMENT,
-                    },
-                    Backend::Metal => ShaderSource::Msl { program: shader::METAL },
-                },
-                shader_meta,
-            )
-            .unwrap();
-
-        let params = PipelineParams {
-            color_blend: Some(BlendState::new(
-                Equation::Add,
-                BlendFactor::Value(BlendValue::SourceAlpha),
-                BlendFactor::OneMinusValue(BlendValue::SourceAlpha),
-            )),
-            ..Default::default()
-        };
-
-        let pipeline = ctx.new_pipeline(
-            &[BufferLayout::default()],
-            &[
-                VertexAttribute::new("in_pos", VertexFormat::Float2),
-                VertexAttribute::new("in_color", VertexFormat::Float4),
-                VertexAttribute::new("in_uv", VertexFormat::Float2),
-            ],
-            shader,
-            params,
-        );
-
-        let (method_sender, method_recvr) = mpsc::sync_channel(100);
-
-        let ftlib = ft::Library::init().unwrap();
-        let mut font_faces = vec![];
-
-        let font_data = include_bytes!("../ibm-plex-mono-light.otf") as &[u8];
-        let ft_face = ftlib.new_memory_face2(font_data, 0).unwrap();
-        font_faces.push(ft_face);
-
-        let font_data = include_bytes!("../NotoColorEmoji.ttf") as &[u8];
-        let ft_face = ftlib.new_memory_face2(font_data, 0).unwrap();
-        font_faces.push(ft_face);
-
-        let mut stage = Stage {
-            ctx,
-            pipeline,
-            scene_graph,
-            textures,
-            font_faces,
-            method_recvr,
-            method_sender,
-            last_draw_time: None,
-            atlas: Mutex::new(HashMap::new()),
-        };
-        stage.setup_scene_graph_window();
-
-        stage.setup_scene();
-
-        debug!("Finished loading GUI");
-        stage
-    }
-
-    fn setup_scene_graph_window(&mut self) {
-        let mut scene_graph = self.scene_graph.lock().unwrap();
-
-        let window = scene_graph.add_node("window", SceneNodeType::Window);
-        let (screen_width, screen_height) = window::screen_size();
-
-        let mut prop = Property::new("screen_size", PropertyType::Float32, PropertySubType::Pixel);
-        prop.set_array_len(2);
-        prop.set_f32(0, screen_width);
-        prop.set_f32(1, screen_height);
-        window.add_property(prop).unwrap();
-
-        let mut prop = Property::new("scale", PropertyType::Float32, PropertySubType::Pixel);
-        prop.set_defaults_f32(vec![1.]).unwrap();
-        window.add_property(prop).unwrap();
-
-        window
-            .add_signal(
-                "resize",
-                "Screen resize event",
-                vec![
-                    ("screen_width", "", PropertyType::Float32),
-                    ("screen_height", "", PropertyType::Float32),
-                ],
-            )
-            .unwrap();
-
-        let window_id = window.id;
-
-        let sender = self.method_sender.clone();
-        let method_fn = Box::new(move |arg_data, response_fn| {
-            sender.send((GraphicsMethodEvent::LoadTexture, window_id, arg_data, response_fn));
-        });
-        window
-            .add_method(
-                "load_texture",
-                vec![("node_name", "", PropertyType::Str), ("path", "", PropertyType::Str)],
-                vec![("node_id", "", PropertyType::SceneNodeId)],
-                method_fn,
-            )
-            .unwrap();
-
-        let sender = self.method_sender.clone();
-        let method_fn = Box::new(move |arg_data, response_fn| {
-            sender.send((GraphicsMethodEvent::CreateChatView, window_id, arg_data, response_fn));
-        });
-        window
-            .add_method(
-                "create_chat_view",
-                vec![("node_id", "", PropertyType::SceneNodeId)],
-                vec![],
-                method_fn,
-            )
-            .unwrap();
-
-        let sender = self.method_sender.clone();
-        let method_fn = Box::new(move |arg_data, response_fn| {
-            sender.send((GraphicsMethodEvent::CreateEditBox, window_id, arg_data, response_fn));
-        });
-        window
-            .add_method(
-                "create_edit_box",
-                vec![("node_id", "", PropertyType::SceneNodeId)],
-                vec![],
-                method_fn,
-            )
-            .unwrap();
-
-        scene_graph.link(window_id, SceneGraph::ROOT_ID).unwrap();
-
-        let input = scene_graph.add_node("input", SceneNodeType::WindowInput);
-        let input_id = input.id;
-        scene_graph.link(input_id, window_id).unwrap();
-
-        let keyb = scene_graph.add_node("keyboard", SceneNodeType::Keyboard);
-        keyb.add_signal(
-            "key_down",
-            "Key press down event",
-            vec![
-                ("shift", "", PropertyType::Bool),
-                ("ctrl", "", PropertyType::Bool),
-                ("alt", "", PropertyType::Bool),
-                ("logo", "", PropertyType::Bool),
-                ("repeat", "", PropertyType::Bool),
-                ("keycode", "", PropertyType::Enum),
-            ],
-        )
-        .unwrap();
-        keyb.add_signal(
-            "key_up",
-            "Key press up event",
-            vec![
-                ("shift", "", PropertyType::Bool),
-                ("ctrl", "", PropertyType::Bool),
-                ("alt", "", PropertyType::Bool),
-                ("logo", "", PropertyType::Bool),
-                ("repeat", "", PropertyType::Bool),
-                ("keycode", "", PropertyType::Enum),
-            ],
-        )
-        .unwrap();
-        let keyb_id = keyb.id;
-        scene_graph.link(keyb_id, input_id).unwrap();
-
-        let mouse = scene_graph.add_node("mouse", SceneNodeType::Mouse);
-        mouse
-            .add_signal(
-                "button_up",
-                "Mouse button up event",
-                vec![
-                    ("button", "", PropertyType::Enum),
-                    ("x", "", PropertyType::Float32),
-                    ("y", "", PropertyType::Float32),
-                ],
-            )
-            .unwrap();
-        mouse
-            .add_signal(
-                "button_down",
-                "Mouse button down event",
-                vec![
-                    ("button", "", PropertyType::Enum),
-                    ("x", "", PropertyType::Float32),
-                    ("y", "", PropertyType::Float32),
-                ],
-            )
-            .unwrap();
-        mouse
-            .add_signal(
-                "wheel",
-                "Mouse wheel scroll event",
-                vec![("x", "", PropertyType::Float32), ("y", "", PropertyType::Float32)],
-            )
-            .unwrap();
-        mouse
-            .add_signal(
-                "move",
-                "Mouse cursor move event",
-                vec![("x", "", PropertyType::Float32), ("y", "", PropertyType::Float32)],
-            )
-            .unwrap();
-        let mouse_id = mouse.id;
-        scene_graph.link(mouse_id, input_id).unwrap();
-    }
-
-    fn method_load_texture(&mut self, node_id: SceneNodeId, arg_data: Vec<u8>) -> Result<Vec<u8>> {
-        let mut cur = Cursor::new(&arg_data);
-        let node_name = String::decode(&mut cur).unwrap();
-        let filepath = String::decode(&mut cur).unwrap();
-
-        let Ok(img) = image::open(filepath) else { return Err(Error::FileNotFound) };
-
-        let img = img.to_rgba8();
-        let width = img.width();
-        let height = img.height();
-        let bmp = img.into_raw();
-
-        let texture = self.ctx.new_texture_from_rgba8(width as u16, height as u16, &bmp);
-        let id = self.textures.alloc(texture);
-
-        let mut scene_graph = self.scene_graph.lock().unwrap();
-        let img_node = scene_graph.add_node(node_name, SceneNodeType::RenderTexture);
-
-        let mut prop = Property::new("size", PropertyType::Uint32, PropertySubType::Pixel);
-        prop.set_array_len(2);
-        prop.set_u32(0, width).unwrap();
-        prop.set_u32(1, height).unwrap();
-        img_node.add_property(prop)?;
-
-        let mut prop =
-            Property::new("texture_rid", PropertyType::Uint32, PropertySubType::ResourceId);
-        prop.set_u32(0, id).unwrap();
-        img_node.add_property(prop)?;
-
-        let mut reply = vec![];
-        img_node.id.encode(&mut reply).unwrap();
-
-        Ok(reply)
-    }
-    fn method_delete_texture(
-        &mut self,
-        node_id: SceneNodeId,
-        arg_data: Vec<u8>,
-    ) -> Result<Vec<u8>> {
-        let mut cur = Cursor::new(&arg_data);
-        let texture_id = ResourceId::decode(&mut cur).unwrap();
-        let texture = self.textures.get(texture_id).ok_or(Error::ResourceNotFound)?;
-        self.ctx.delete_texture(*texture);
-        self.textures.free(texture_id);
-        Ok(vec![])
-    }
-
-    fn method_create_chatview(&mut self, _: SceneNodeId, arg_data: Vec<u8>) -> Result<Vec<u8>> {
-        debug!("gfx::create_chatview()");
-        let mut cur = Cursor::new(&arg_data);
-        let node_id = SceneNodeId::decode(&mut cur).unwrap();
-
-        let mut scene_graph = self.scene_graph.lock().unwrap();
-        let editbox = chatview::ChatView::new(&mut scene_graph, node_id, self.font_faces.clone())?;
-
-        let node = scene_graph.get_node_mut(node_id).ok_or(Error::NodeNotFound)?;
-        node.pimpl = editbox;
-
-        let mut reply = vec![];
-        Ok(reply)
-    }
-
-    fn method_create_editbox(&mut self, _: SceneNodeId, arg_data: Vec<u8>) -> Result<Vec<u8>> {
-        debug!("gfx::create_editbox()");
-        let mut cur = Cursor::new(&arg_data);
-        let node_id = SceneNodeId::decode(&mut cur).unwrap();
-
-        let mut scene_graph = self.scene_graph.lock().unwrap();
-        let editbox = editbox::EditBox::new(&mut scene_graph, node_id, self.font_faces.clone())?;
-
-        let node = scene_graph.get_node_mut(node_id).ok_or(Error::NodeNotFound)?;
-        node.pimpl = editbox;
-
-        let mut reply = vec![];
-        Ok(reply)
-    }
-
-    fn setup_scene(&mut self) {
-        let mut sg = self.scene_graph.lock().unwrap();
-        crate::chatapp::setup(&mut sg);
-    }
-}
-
-pub struct RenderContext<'a> {
-    pub scene_graph: MutexGuard<'a, SceneGraph>,
-    pub ctx: &'a mut Box<dyn RenderingBackend>,
-    pub pipeline: &'a Pipeline,
-    pub proj: glam::Mat4,
-    pub textures: &'a ResourceManager<TextureId>,
-    pub font_faces: &'a Vec<FreetypeFace>,
-    pub atlas: &'a mut HashMap<(u32, [u8; 4]), TextureId>,
-}
-
-impl<'a> RenderContext<'a> {
-    fn render_window(&mut self) {
-        for layer in self
-            .scene_graph
-            .lookup_node("/window")
-            .expect("no window attached!")
-            .get_children(&[SceneNodeType::RenderLayer])
-        {
-            if let Err(err) = self.render_layer(layer.id) {
-                error!("error rendering layer '{}': {}", layer.name, err)
-            }
-        }
-
-        self.ctx.commit_frame();
-    }
-
-    fn get_rect(layer: &SceneNode) -> Result<Rectangle<i32>> {
-        let prop = layer.get_property("rect").ok_or(Error::PropertyNotFound)?;
-        if prop.array_len != 4 {
-            return Err(Error::PropertyWrongLen)
-        }
-
-        let mut rect = [0; 4];
-        for i in 0..4 {
-            if prop.is_expr(i)? {
-                let (screen_width, screen_height) = window::screen_size();
-
-                let expr = prop.get_expr(i).unwrap();
-
-                let machine = SExprMachine {
-                    globals: vec![
-                        ("sw".to_string(), SExprVal::Float32(screen_width)),
-                        ("sh".to_string(), SExprVal::Float32(screen_height)),
-                    ],
-                    stmts: &expr,
-                };
-
-                rect[i] = machine.call()?.as_u32()? as i32;
-            } else {
-                rect[i] = prop.get_u32(i)? as i32;
-            }
-        }
-        Ok(Rectangle::from_array(rect))
-    }
-
-    fn render_layer(
-        &mut self,
-        layer_id: SceneNodeId,
-        // parent rect
-    ) -> Result<()> {
-        let layer = self.scene_graph.get_node(layer_id).unwrap();
-
-        if !layer.get_property_bool("is_visible")? {
-            return Ok(())
-        }
-
-        self.ctx.begin_default_pass(PassAction::Nothing);
-        self.ctx.apply_pipeline(&self.pipeline);
-
-        let (_, screen_height) = window::screen_size();
-
-        let rect = Self::get_rect(&layer)?;
-
-        let mut view = rect.clone();
-        view.y = screen_height as i32 - (rect.y + rect.h);
-        self.ctx.apply_viewport(view.x, view.y, view.w, view.h);
-        self.ctx.apply_scissor_rect(view.x, view.y, view.w, view.h);
-
-        let window = self.scene_graph.lookup_node("/window").expect("no window attached!");
-        let window_scale = window.get_property_f32("scale")?;
-
-        let rect = Rectangle {
-            x: (rect.x as f32) / window_scale,
-            y: (rect.y as f32) / window_scale,
-            w: (rect.w as f32) / window_scale,
-            h: (rect.h as f32) / window_scale,
-        };
-
-        let layer_children = layer.get_children(&[
-            SceneNodeType::RenderMesh,
-            SceneNodeType::RenderText,
-            SceneNodeType::EditBox,
-            SceneNodeType::ChatView,
-        ]);
-        let layer_children = self.order_by_z_index(layer_children);
-
-        // get the rectangle
-        // make sure it's inside the parent's rect
-        for child in layer_children {
-            // x, y, w, h as pixels
-
-            // note that (x, y) is offset by layer rect so it is the pos within layer
-            // layer coords are (0, 0) -> (1, 1)
-
-            // optionally evaluated using sexpr
-
-            // mesh data is (0, 0) to (1, 1)
-            // so scale by (w, h)
-
-            match child.typ {
-                SceneNodeType::RenderMesh => {
-                    if let Err(err) = self.render_mesh(child.id, &rect) {
-                        error!("error rendering mesh '{}': {}", child.name, err);
-                    }
-                }
-                SceneNodeType::RenderText => {
-                    if let Err(err) = self.render_text(child.id, &rect) {
-                        error!("error rendering text '{}': {}", child.name, err);
-                    }
-                }
-                SceneNodeType::ChatView => {
-                    let node = self.scene_graph.get_node(child.id).unwrap();
-                    let chatview = match &node.pimpl {
-                        Pimpl::Null => {
-                            // Maybe the chatview isn't initialized fully yet
-                            continue;
-                        }
-                        Pimpl::ChatView(e) => e.clone(),
-                        _ => panic!("wrong pimpl for editbox"),
-                    };
-                    if let Err(err) = chatview.render(self, child.id, &rect) {
-                        error!("error rendering chatview '{}': {}", child.name, err);
-                    }
-                }
-                SceneNodeType::EditBox => {
-                    let node = self.scene_graph.get_node(child.id).unwrap();
-                    let editbox = match &node.pimpl {
-                        Pimpl::Null => {
-                            // Maybe the editbox isn't initialized fully yet
-                            continue;
-                        }
-                        Pimpl::EditBox(e) => e.clone(),
-                        _ => panic!("wrong pimpl for editbox"),
-                    };
-                    if let Err(err) = editbox.render(self, child.id, &rect) {
-                        error!("error rendering editbox '{}': {}", child.name, err);
-                    }
-                }
-                _ => panic!("render_layer(): unknown type"),
-            }
-        }
-
-        Ok(())
-    }
-
-    fn order_by_z_index(&self, nodes: Vec<SceneNodeInfo>) -> Vec<SceneNodeInfo> {
-        let mut nodes: Vec<_> = nodes
-            .into_iter()
-            .filter_map(|node_inf| {
-                let node = self.scene_graph.get_node(node_inf.id).unwrap();
-                //if !node.get_property_bool("is_visible").ok()? {
-                //    return None
-                //}
-                let z_index = node.get_property_u32("z_index").ok()?;
-                Some((z_index, node_inf))
-            })
-            .collect();
-        nodes.sort_unstable_by_key(|(z_index, node_inf)| *z_index);
-        nodes.into_iter().map(|(z_index, node_inf)| node_inf).collect()
-    }
-
-    pub fn get_dim(mesh: &SceneNode, layer_rect: &Rectangle<f32>) -> Result<Rectangle<f32>> {
-        let prop = mesh.get_property("rect").ok_or(Error::PropertyNotFound)?;
-        if prop.array_len != 4 {
-            return Err(Error::PropertyWrongLen)
-        }
-
-        let mut rect = [0.; 4];
-        for i in 0..4 {
-            if prop.is_expr(i)? {
-                let expr = prop.get_expr(i).unwrap();
-
-                let machine = SExprMachine {
-                    globals: vec![
-                        ("lw".to_string(), SExprVal::Uint32(layer_rect.w as u32)),
-                        ("lh".to_string(), SExprVal::Uint32(layer_rect.h as u32)),
-                    ],
-                    stmts: &expr,
-                };
-
-                rect[i] = machine.call()?.coerce_f32()?;
-            } else {
-                rect[i] = prop.get_f32(i)?;
-            }
-        }
-        Ok(Rectangle::from_array(rect))
-    }
-
-    fn render_mesh(&mut self, node_id: SceneNodeId, layer_rect: &Rectangle<f32>) -> Result<()> {
-        let mesh = self.scene_graph.get_node(node_id).unwrap();
-
-        let z_index = mesh.get_property_u32("z_index")?;
-
-        let data = mesh.get_property("data").ok_or(Error::PropertyNotFound)?;
-        let verts = data.get_buf(0)?;
-        let faces = data.get_buf(1)?;
-
-        let vertex_buffer = self.ctx.new_buffer(
-            BufferType::VertexBuffer,
-            BufferUsage::Immutable,
-            BufferSource::slice(&verts),
-        );
-
-        let bufsrc = unsafe {
-            BufferSource::pointer(
-                faces.as_ptr() as _,
-                std::mem::size_of_val(&faces[..]),
-                std::mem::size_of::<u32>(),
-            )
-        };
-
-        let index_buffer =
-            self.ctx.new_buffer(BufferType::IndexBuffer, BufferUsage::Immutable, bufsrc);
-
-        // temp
-        let texture = self.textures.get(Stage::WHITE_TEXTURE_ID).unwrap();
-
-        let rect = Self::get_dim(mesh, layer_rect)?;
-        //debug!("mesh rect: {:?}", rect);
-
-        let layer_w = layer_rect.w as f32;
-        let layer_h = layer_rect.h as f32;
-        let off_x = rect.x / layer_w;
-        let off_y = rect.y / layer_h;
-        let scale_x = rect.w / layer_w;
-        let scale_y = rect.h / layer_h;
-        //let model = glam::Mat4::IDENTITY;
-        let model = glam::Mat4::from_translation(glam::Vec3::new(off_x, off_y, 0.)) *
-            glam::Mat4::from_scale(glam::Vec3::new(scale_x, scale_y, 1.));
-
-        let mut uniforms_data = [0u8; 128];
-        let data: [u8; 64] = unsafe { std::mem::transmute_copy(&self.proj) };
-        uniforms_data[0..64].copy_from_slice(&data);
-        let data: [u8; 64] = unsafe { std::mem::transmute_copy(&model) };
-        uniforms_data[64..].copy_from_slice(&data);
-        assert_eq!(128, 2 * UniformType::Mat4.size());
-
-        let bindings =
-            Bindings { vertex_buffers: vec![vertex_buffer], index_buffer, images: vec![*texture] };
-
-        self.ctx.apply_bindings(&bindings);
-
-        self.ctx.apply_uniforms_from_bytes(uniforms_data.as_ptr(), uniforms_data.len());
-
-        self.ctx.draw(0, 3 * faces.len() as i32, 1);
-
-        self.ctx.delete_buffer(index_buffer);
-        self.ctx.delete_buffer(vertex_buffer);
-
-        Ok(())
-    }
-
-    pub fn render_clipped_box_with_texture2(
-        &mut self,
-        bound: &Rectangle<f32>,
-        obj: &Rectangle<f32>,
-        color: Color,
-        texture: TextureId,
-    ) {
-        let Some(clipped) = bound.clip(&obj) else { return };
-
-        let x1 = clipped.x;
-        let y1 = clipped.y;
-        let x2 = clipped.x + clipped.w;
-        let y2 = clipped.y + clipped.h;
-
-        let u1 = (clipped.x - obj.x) / obj.w;
-        let u2 = (clipped.x + clipped.w - obj.x) / obj.w;
-        let v1 = (clipped.y - obj.y) / obj.h;
-        let v2 = (clipped.y + clipped.h - obj.y) / obj.h;
-
-        let vertices: [Vertex; 4] = [
-            // top left
-            Vertex { pos: [x1, y1], color, uv: [u1, v1] },
-            // top right
-            Vertex { pos: [x2, y1], color, uv: [u2, v1] },
-            // bottom left
-            Vertex { pos: [x1, y2], color, uv: [u1, v2] },
-            // bottom right
-            Vertex { pos: [x2, y2], color, uv: [u2, v2] },
-        ];
-
-        let vertex_buffer = self.ctx.new_buffer(
-            BufferType::VertexBuffer,
-            BufferUsage::Immutable,
-            BufferSource::slice(&vertices),
-        );
-
-        let indices: [u16; 6] = [0, 2, 1, 1, 2, 3];
-        let index_buffer = self.ctx.new_buffer(
-            BufferType::IndexBuffer,
-            BufferUsage::Immutable,
-            BufferSource::slice(&indices),
-        );
-
-        let bindings =
-            Bindings { vertex_buffers: vec![vertex_buffer], index_buffer, images: vec![texture] };
-
-        self.ctx.apply_bindings(&bindings);
-        self.ctx.draw(0, 6, 1);
-        self.ctx.delete_buffer(vertex_buffer);
-        self.ctx.delete_buffer(index_buffer);
-    }
-
-    pub fn render_clipped_box_with_texture(
-        &mut self,
-        bound_rect: &Rectangle<f32>,
-        x1: f32,
-        y1: f32,
-        x2: f32,
-        y2: f32,
-        color: Color,
-        texture: TextureId,
-    ) {
-        let obj = Rectangle { x: x1, y: y1, w: x2 - x1, h: y2 - y1 };
-        if obj.w == 0. || obj.h == 0. {
-            return
-        }
-        let Some(clipped) = bound_rect.clip(&obj) else { return };
-
-        let x1 = clipped.x;
-        let y1 = clipped.y;
-        let x2 = clipped.x + clipped.w;
-        let y2 = clipped.y + clipped.h;
-
-        let u1 = (clipped.x - obj.x) / obj.w;
-        let u2 = (clipped.x + clipped.w - obj.x) / obj.w;
-        let v1 = (clipped.y - obj.y) / obj.h;
-        let v2 = (clipped.y + clipped.h - obj.y) / obj.h;
-
-        let vertices: [Vertex; 4] = [
-            // top left
-            Vertex { pos: [x1, y1], color, uv: [u1, v1] },
-            // top right
-            Vertex { pos: [x2, y1], color, uv: [u2, v1] },
-            // bottom left
-            Vertex { pos: [x1, y2], color, uv: [u1, v2] },
-            // bottom right
-            Vertex { pos: [x2, y2], color, uv: [u2, v2] },
-        ];
-
-        let vertex_buffer = self.ctx.new_buffer(
-            BufferType::VertexBuffer,
-            BufferUsage::Immutable,
-            BufferSource::slice(&vertices),
-        );
-
-        let indices: [u16; 6] = [0, 2, 1, 1, 2, 3];
-        let index_buffer = self.ctx.new_buffer(
-            BufferType::IndexBuffer,
-            BufferUsage::Immutable,
-            BufferSource::slice(&indices),
-        );
-
-        let bindings =
-            Bindings { vertex_buffers: vec![vertex_buffer], index_buffer, images: vec![texture] };
-
-        self.ctx.apply_bindings(&bindings);
-        self.ctx.draw(0, 6, 1);
-        self.ctx.delete_buffer(vertex_buffer);
-        self.ctx.delete_buffer(index_buffer);
-    }
-
-    pub fn render_box_with_texture(
-        &mut self,
-        x1: f32,
-        y1: f32,
-        x2: f32,
-        y2: f32,
-        color: Color,
-        texture: TextureId,
-    ) {
-        let vertices: [Vertex; 4] = [
-            // top left
-            Vertex { pos: [x1, y1], color, uv: [0., 0.] },
-            // top right
-            Vertex { pos: [x2, y1], color, uv: [1., 0.] },
-            // bottom left
-            Vertex { pos: [x1, y2], color, uv: [0., 1.] },
-            // bottom right
-            Vertex { pos: [x2, y2], color, uv: [1., 1.] },
-        ];
-
-        let vertex_buffer = self.ctx.new_buffer(
-            BufferType::VertexBuffer,
-            BufferUsage::Immutable,
-            BufferSource::slice(&vertices),
-        );
-
-        let indices: [u16; 6] = [0, 2, 1, 1, 2, 3];
-        let index_buffer = self.ctx.new_buffer(
-            BufferType::IndexBuffer,
-            BufferUsage::Immutable,
-            BufferSource::slice(&indices),
-        );
-
-        let bindings =
-            Bindings { vertex_buffers: vec![vertex_buffer], index_buffer, images: vec![texture] };
-
-        self.ctx.apply_bindings(&bindings);
-        self.ctx.draw(0, 6, 1);
-        self.ctx.delete_buffer(vertex_buffer);
-        self.ctx.delete_buffer(index_buffer);
-    }
-
-    pub fn render_box(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, color: Color) {
-        let texture = self.textures.get(Stage::WHITE_TEXTURE_ID).unwrap();
-        self.render_box_with_texture(x1, y1, x2, y2, color, *texture)
-    }
-
-    pub fn hline(&mut self, min_x: f32, max_x: f32, y: f32, color: Color, w: f32) {
-        self.render_box(min_x, y - w / 2., max_x, y + w / 2., color)
-    }
-
-    pub fn vline(&mut self, x: f32, min_y: f32, max_y: f32, color: Color, w: f32) {
-        self.render_box(x - w / 2., min_y, x + w / 2., max_y, color)
-    }
-
-    pub fn outline(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, color: Color, w: f32) {
-        // top
-        self.render_box(x1, y1, x2, y1 + w, color);
-        // left
-        self.render_box(x1, y1, x1 + w, y2, color);
-        // right
-        self.render_box(x2 - w, y1, x2, y2, color);
-        // bottom
-        self.render_box(x1, y2 - w, x2, y2, color);
-    }
-
-    fn render_text(&mut self, node_id: SceneNodeId, layer_rect: &Rectangle<f32>) -> Result<()> {
-        let node = self.scene_graph.get_node(node_id).unwrap();
-
-        let text = node.get_property_str("text")?;
-        let font_size = node.get_property_f32("font_size")?;
-        let debug = node.get_property_bool("debug")?;
-        let rect = Self::get_dim(node, layer_rect)?;
-        let baseline = node.get_property_f32("baseline")?;
-
-        let color_prop = node.get_property("color").ok_or(Error::PropertyNotFound)?;
-        let color_r = color_prop.get_f32(0)?;
-        let color_g = color_prop.get_f32(1)?;
-        let color_b = color_prop.get_f32(2)?;
-        let color_a = color_prop.get_f32(3)?;
-
-        let layer_w = layer_rect.w as f32;
-        let layer_h = layer_rect.h as f32;
-        let off_x = rect.x / layer_w;
-        let off_y = rect.y / layer_h;
-        // Use absolute pixel scale
-        let scale_x = 1. / layer_w;
-        let scale_y = 1. / layer_h;
-        //let model = glam::Mat4::IDENTITY;
-        let model = glam::Mat4::from_translation(glam::Vec3::new(off_x, off_y, 0.)) *
-            glam::Mat4::from_scale(glam::Vec3::new(scale_x, scale_y, 1.));
-
-        let mut uniforms_data = [0u8; 128];
-        let data: [u8; 64] = unsafe { std::mem::transmute_copy(&self.proj) };
-        uniforms_data[0..64].copy_from_slice(&data);
-        let data: [u8; 64] = unsafe { std::mem::transmute_copy(&model) };
-        uniforms_data[64..].copy_from_slice(&data);
-        assert_eq!(128, 2 * UniformType::Mat4.size());
-
-        self.ctx.apply_uniforms_from_bytes(uniforms_data.as_ptr(), uniforms_data.len());
-
-        // Used for scaling the font size
-        let window = self.scene_graph.lookup_node("/window").expect("no window attached!");
-        let window_scale = window.get_property_f32("scale")?;
-        let font_size = window_scale * font_size;
-
-        //let mut strings = vec![];
-        //let mut current_str = String::new();
-        //let mut current_idx = 0;
-        //for chr in text.chars() {
-        //    let ft_face = self.font_faces[current_idx];
-        //    if ft_face.get_char_index(chr as usize).is_some() {
-        //    }
-        //}
-
-        let mut current_idx = 0;
-        let mut current_str = String::new();
-        let mut substrs = vec![];
-        'next_char: for chr in text.chars() {
-            let idx = 'get_idx: {
-                for i in 0..self.font_faces.len() {
-                    let ft_face = &self.font_faces[i];
-                    if ft_face.get_char_index(chr as usize).is_some() {
-                        break 'get_idx i
-                    }
-                }
-
-                warn!("no font fallback for char: {}", chr);
-                // Skip this char
-                continue 'next_char
-            };
-            if current_idx != idx {
-                if !current_str.is_empty() {
-                    // Push
-                    substrs.push((current_idx, current_str.clone()));
-                }
-
-                current_str.clear();
-                current_idx = idx;
-            }
-            current_str.push(chr);
-        }
-        if !current_str.is_empty() {
-            // Push
-            substrs.push((current_idx, current_str));
-        }
-
-        let mut current_x = 0.;
-        let mut current_y = baseline;
-
-        for (face_idx, text) in substrs {
-            let face = &self.font_faces[face_idx];
-            if face.has_fixed_sizes() {
-                // emojis required a fixed size
-                //face.set_char_size(109 * 64, 0, 72, 72).unwrap();
-                face.select_size(0).unwrap();
-            } else {
-                face.set_char_size(font_size as isize * 64, 0, 72, 72).unwrap();
-            }
-
-            let hb_font = harfbuzz_rs::Font::from_freetype_face(face.clone());
-            let buffer = harfbuzz_rs::UnicodeBuffer::new().add_str(&text);
-            let output = harfbuzz_rs::shape(&hb_font, buffer, &[]);
-
-            let positions = output.get_glyph_positions();
-            let infos = output.get_glyph_infos();
-
-            for (position, info) in positions.iter().zip(infos) {
-                let gid = info.codepoint;
-                // Index within this substr
-                // let cluster = info.cluster;
-
-                let mut flags = ft::face::LoadFlag::DEFAULT;
-                if face.has_color() {
-                    flags |= ft::face::LoadFlag::COLOR;
-                }
-                face.load_glyph(gid, flags).unwrap();
-
-                let glyph = face.glyph();
-                glyph.render_glyph(ft::RenderMode::Normal).unwrap();
-
-                // https://gist.github.com/jokertarot/7583938?permalink_comment_id=3327566#gistcomment-3327566
-
-                let bmp = glyph.bitmap();
-                let buffer = bmp.buffer();
-                let bmp_width = bmp.width() as usize;
-                let bmp_height = bmp.rows() as usize;
-                let bearing_x = glyph.bitmap_left() as f32;
-                let bearing_y = glyph.bitmap_top() as f32;
-
-                //assert_eq!(bmp.pixel_mode().unwrap(), ft::bitmap::PixelMode::Bgra);
-                //assert_eq!(bmp.pixel_mode().unwrap(), ft::bitmap::PixelMode::Lcd);
-                //assert_eq!(bmp.pixel_mode().unwrap(), ft::bitmap::PixelMode::Gray);
-
-                let pixel_mode = bmp.pixel_mode().unwrap();
-                let tdata = match pixel_mode {
-                    ft::bitmap::PixelMode::Bgra => {
-                        let mut tdata = vec![];
-                        tdata.resize(4 * bmp_width * bmp_height, 0);
-                        // Convert from BGRA to RGBA
-                        for i in 0..bmp_width * bmp_height as usize {
-                            let idx = i * 4;
-                            let b = buffer[idx];
-                            let g = buffer[idx + 1];
-                            let r = buffer[idx + 2];
-                            let a = buffer[idx + 3];
-                            tdata[idx] = r;
-                            tdata[idx + 1] = g;
-                            tdata[idx + 2] = b;
-                            tdata[idx + 3] = a;
-                        }
-                        tdata
-                    }
-                    ft::bitmap::PixelMode::Gray => {
-                        // Convert from greyscale to RGBA8
-                        let tdata: Vec<_> = buffer
-                            .iter()
-                            .flat_map(|coverage| {
-                                let r = (255. * color_r) as u8;
-                                let g = (255. * color_g) as u8;
-                                let b = (255. * color_b) as u8;
-                                let a = ((*coverage as f32) * color_a) as u8;
-                                vec![r, g, b, a]
-                            })
-                            .collect();
-                        tdata
-                    }
-                    _ => panic!("unsupport pixel mode: {:?}", pixel_mode),
-                };
-
-                let (x1, y1, x2, y2) = if face.has_fixed_sizes() {
-                    // Downscale by height
-                    let width = (bmp_width as f32 * font_size) / bmp_height as f32;
-                    let height = font_size;
-
-                    let x1 = current_x;
-                    let y1 = current_y - height;
-
-                    let x2 = current_x + width;
-                    let y2 = current_y;
-
-                    current_x += width;
-
-                    (x1, y1, x2, y2)
-                } else {
-                    let (width, height) = (bmp_width as f32, bmp_height as f32);
-
-                    let off_x = position.x_offset as f32 / 64.;
-                    let off_y = position.y_offset as f32 / 64.;
-
-                    let x1 = current_x + off_x + bearing_x;
-                    let y1 = current_y - off_y - bearing_y;
-                    let x2 = x1 + width as f32;
-                    let y2 = y1 + height as f32;
-
-                    let x_advance = position.x_advance as f32 / 64.;
-                    let y_advance = position.y_advance as f32 / 64.;
-                    current_x += x_advance;
-                    current_y += y_advance;
-
-                    (x1, y1, x2, y2)
-                };
-
-                let key = (
-                    gid,
-                    [
-                        (255. * color_r) as u8,
-                        (255. * color_g) as u8,
-                        (255. * color_b) as u8,
-                        (255. * color_a) as u8,
-                    ],
-                );
-                let texture = if self.atlas.contains_key(&key) {
-                    *self.atlas.get(&key).unwrap()
-                } else {
-                    let texture = self.ctx.new_texture_from_rgba8(
-                        bmp_width as u16,
-                        bmp_height as u16,
-                        &tdata,
-                    );
-                    self.atlas.insert(key, texture);
-                    texture
-                };
-
-                //let texture = self.ctx.new_texture_from_rgba8(bmp_width as u16, bmp_height as u16, &tdata);
-                self.render_box_with_texture(x1, y1, x2, y2, COLOR_WHITE, texture);
-                //self.ctx.delete_texture(texture);
-
-                if debug {
-                    self.outline(x1, y1, x2, y2, COLOR_BLUE, 1.);
-                }
-            }
-            if debug {
-                self.hline(0., current_x, 0., COLOR_RED, 1.);
-            }
-        }
-
-        Ok(())
-    }
-
-    fn render_glyph(&mut self, glyph_id: u32, font_size: f32, x: f32, y: f32) -> Result<()> {
-        Ok(())
-    }
-}
-
-impl EventHandler for Stage {
-    fn update(&mut self) {
-        if self.last_draw_time.is_none() {
-            return
-        }
-
-        // Only allow 20 ms, process as much as we can during that time
-        let elapsed_since_draw = self.last_draw_time.unwrap().elapsed();
-        // We're long overdue a redraw. Exit for now
-        if elapsed_since_draw > Duration::from_millis(20) {
-            return
-        }
-        // The next redraw must happen 20ms since its last one.
-        // Calculate how much time is remaining until then.
-        let allowed_time = Duration::from_millis(20) - elapsed_since_draw;
-        let deadline = Instant::now() + allowed_time;
-
-        loop {
-            let Ok((event, node_id, arg_data, response_fn)) =
-                self.method_recvr.recv_deadline(deadline)
-            else {
-                break
-            };
-            let res = match event {
-                GraphicsMethodEvent::LoadTexture => self.method_load_texture(node_id, arg_data),
-                GraphicsMethodEvent::DeleteTexture => self.method_delete_texture(node_id, arg_data),
-                GraphicsMethodEvent::CreateChatView => {
-                    self.method_create_chatview(node_id, arg_data)
-                }
-                GraphicsMethodEvent::CreateEditBox => self.method_create_editbox(node_id, arg_data),
-            };
-            response_fn(res);
-        }
-    }
-
-    // Only do drawing here. Apps might not call this when minimized.
-    fn draw(&mut self) {
-        self.last_draw_time = Some(Instant::now());
-
-        // This will make the top left (0, 0) and the bottom right (1, 1)
-        // Default is (-1, 1) -> (1, -1)
-        let proj = glam::Mat4::from_translation(glam::Vec3::new(-1., 1., 0.)) *
-            glam::Mat4::from_scale(glam::Vec3::new(2., -2., 1.));
-        //let proj = glam::Mat4::IDENTITY;
-
-        let scene_graph = self.scene_graph.lock().unwrap();
-        let atlas = &mut self.atlas.lock().unwrap();
-
-        // We need this because scene_graph must remain locked for the duration of the rendering
-        let mut render_context = RenderContext {
-            scene_graph,
-            ctx: &mut self.ctx,
-            pipeline: &self.pipeline,
-            proj,
-            textures: &self.textures,
-            font_faces: &self.font_faces,
-            atlas,
-        };
-
-        render_context.render_window();
-
-        drop(render_context);
-    }
-
-    fn key_down_event(&mut self, keycode: KeyCode, modifiers: KeyMods, repeat: bool) {
-        let mut scene_graph = self.scene_graph.lock().unwrap();
-        let win = scene_graph.lookup_node_mut("/window/input/keyboard").unwrap();
-
-        let key = keycode.to_str();
-
-        let mut data = vec![];
-        modifiers.shift.encode(&mut data).unwrap();
-        modifiers.ctrl.encode(&mut data).unwrap();
-        modifiers.alt.encode(&mut data).unwrap();
-        modifiers.logo.encode(&mut data).unwrap();
-        repeat.encode(&mut data).unwrap();
-        key.encode(&mut data).unwrap();
-        //win.trigger("key_down", data).unwrap();
-    }
-    fn key_up_event(&mut self, keycode: KeyCode, modifiers: KeyMods) {
-        let mut scene_graph = self.scene_graph.lock().unwrap();
-        let win = scene_graph.lookup_node_mut("/window/input/keyboard").unwrap();
-
-        let key = keycode.to_str();
-
-        let mut data = vec![];
-        modifiers.shift.encode(&mut data).unwrap();
-        modifiers.ctrl.encode(&mut data).unwrap();
-        modifiers.alt.encode(&mut data).unwrap();
-        modifiers.logo.encode(&mut data).unwrap();
-        key.encode(&mut data).unwrap();
-        //win.trigger("key_up", data).unwrap();
-    }
-    fn mouse_motion_event(&mut self, x: f32, y: f32) {
-        let mut scene_graph = self.scene_graph.lock().unwrap();
-        let mut data = vec![];
-        x.encode(&mut data).unwrap();
-        y.encode(&mut data).unwrap();
-        let mouse = scene_graph.lookup_node_mut("/window/input/mouse").unwrap();
-        //mouse.trigger("move", data).unwrap();
-    }
-    fn mouse_wheel_event(&mut self, x: f32, y: f32) {
-        let mut scene_graph = self.scene_graph.lock().unwrap();
-        let mut data = vec![];
-        x.encode(&mut data).unwrap();
-        y.encode(&mut data).unwrap();
-        let mouse = scene_graph.lookup_node_mut("/window/input/mouse").unwrap();
-        //mouse.trigger("wheel", data).unwrap();
-    }
-    fn mouse_button_down_event(&mut self, button: MouseButton, x: f32, y: f32) {
-        let mut scene_graph = self.scene_graph.lock().unwrap();
-        let mut data = vec![];
-        button.to_u8().encode(&mut data).unwrap();
-        x.encode(&mut data).unwrap();
-        y.encode(&mut data).unwrap();
-        let mouse = scene_graph.lookup_node_mut("/window/input/mouse").unwrap();
-        //mouse.trigger("button_down", data).unwrap();
-    }
-    fn mouse_button_up_event(&mut self, button: MouseButton, x: f32, y: f32) {
-        let mut scene_graph = self.scene_graph.lock().unwrap();
-        let mut data = vec![];
-        button.to_u8().encode(&mut data).unwrap();
-        x.encode(&mut data).unwrap();
-        y.encode(&mut data).unwrap();
-        let mouse = scene_graph.lookup_node_mut("/window/input/mouse").unwrap();
-        //mouse.trigger("button_up", data).unwrap();
-    }
-
-    fn resize_event(&mut self, width: f32, height: f32) {
-        let mut data = vec![];
-        width.encode(&mut data).unwrap();
-        height.encode(&mut data).unwrap();
-
-        let mut scene_graph = self.scene_graph.lock().unwrap();
-        let win = scene_graph.lookup_node_mut("/window").unwrap();
-        let prop = win.get_property("screen_size").unwrap();
-        prop.set_f32(0, width).unwrap();
-        prop.set_f32(1, height).unwrap();
-        //win.trigger("resize", data).unwrap();
-    }
-}
-
-pub fn run_gui(scene_graph: SceneGraphPtr) {
-    #[cfg(target_os = "android")]
-    {
-        android_logger::init_once(
-            android_logger::Config::default().with_max_level(LevelFilter::Debug).with_tag("darkfi"),
-        );
-    }
-
-    #[cfg(target_os = "linux")]
-    {
-        let term_logger = simplelog::TermLogger::new(
-            simplelog::LevelFilter::Debug,
-            simplelog::Config::default(),
-            simplelog::TerminalMode::Mixed,
-            simplelog::ColorChoice::Auto,
-        );
-        simplelog::CombinedLogger::init(vec![term_logger]).expect("logger");
-    }
-
-    let mut conf = miniquad::conf::Conf {
-        high_dpi: true,
-        window_resizable: true,
-        platform: miniquad::conf::Platform {
-            linux_backend: miniquad::conf::LinuxBackend::WaylandWithX11Fallback,
-            wayland_use_fallback_decorations: false,
-            ..Default::default()
-        },
-        ..Default::default()
-    };
-    let metal = std::env::args().nth(1).as_deref() == Some("metal");
-    conf.platform.apple_gfx_api =
-        if metal { conf::AppleGfxApi::Metal } else { conf::AppleGfxApi::OpenGl };
-
-    miniquad::start(conf, || Box::new(Stage::new(scene_graph)));
-}

+ 9 - 8
bin/darkwallet/src/gfx2.rs → bin/darkwallet/src/gfx/mod.rs

@@ -32,11 +32,12 @@ use std::{
     time::{Duration, Instant},
 };
 
+mod shader;
+
 use crate::{
     app::{AppPtr, AsyncRuntime},
     error::{Error, Result},
     pubsub::{Publisher, PublisherPtr, Subscription, SubscriptionId},
-    shader,
     util::ansi_texture,
 };
 
@@ -734,15 +735,15 @@ impl Stage {
         sendr: async_channel::Sender<TextureId>,
     ) {
         let texture = self.ctx.new_texture_from_rgba8(width, height, &data);
-        //debug!(target: "gfx2", "Invoked method: new_texture({}, {}, ...) -> {:?}",
+        //debug!(target: "gfx", "Invoked method: new_texture({}, {}, ...) -> {:?}",
         //       width, height, texture);
-        //debug!(target: "gfx2", "Invoked method: new_texture({}, {}, ...) -> {:?}\n{}",
+        //debug!(target: "gfx", "Invoked method: new_texture({}, {}, ...) -> {:?}\n{}",
         //       width, height, texture,
         //       ansi_texture(width as usize, height as usize, &data));
         sendr.try_send(texture).unwrap();
     }
     fn method_delete_texture(&mut self, texture: TextureId) {
-        //debug!(target: "gfx2", "Invoked method: delete_texture({:?})", texture);
+        //debug!(target: "gfx", "Invoked method: delete_texture({:?})", texture);
         self.ctx.delete_texture(texture);
     }
     fn method_new_vertex_buffer(
@@ -755,7 +756,7 @@ impl Stage {
             BufferUsage::Immutable,
             BufferSource::slice(&verts),
         );
-        //debug!(target: "gfx2", "Invoked method: new_vertex_buffer({:?}) -> {:?}", verts, buffer);
+        //debug!(target: "gfx", "Invoked method: new_vertex_buffer({:?}) -> {:?}", verts, buffer);
         sendr.try_send(buffer).unwrap();
     }
     fn method_new_index_buffer(
@@ -768,15 +769,15 @@ impl Stage {
             BufferUsage::Immutable,
             BufferSource::slice(&indices),
         );
-        //debug!(target: "gfx2", "Invoked method: new_index_buffer({:?}) -> {:?}", indices, buffer);
+        //debug!(target: "gfx", "Invoked method: new_index_buffer({:?}) -> {:?}", indices, buffer);
         sendr.try_send(buffer).unwrap();
     }
     fn method_delete_buffer(&mut self, buffer: BufferId) {
-        //debug!(target: "gfx2", "Invoked method: delete_buffer({:?})", buffer);
+        //debug!(target: "gfx", "Invoked method: delete_buffer({:?})", buffer);
         self.ctx.delete_buffer(buffer);
     }
     fn method_replace_draw_calls(&mut self, dcs: Vec<(u64, DrawCall)>) {
-        //debug!(target: "gfx2", "Invoked method: replace_draw_calls({:?})", dcs);
+        //debug!(target: "gfx", "Invoked method: replace_draw_calls({:?})", dcs);
         for (key, val) in dcs {
             self.draw_calls.insert(key, val);
         }

+ 0 - 0
bin/darkwallet/src/shader.rs → bin/darkwallet/src/gfx/shader.rs


+ 0 - 434
bin/darkwallet/src/keysym.rs

@@ -1,434 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2024 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use miniquad::{KeyCode, MouseButton};
-
-pub trait KeyCodeAsStr {
-    fn to_str(&self) -> &str;
-}
-
-impl KeyCodeAsStr for KeyCode {
-    fn to_str(&self) -> &str {
-        match self {
-            Self::Space => " ",
-            Self::Apostrophe => "'",
-            Self::Comma => ",",
-            Self::Minus => "-",
-            Self::Period => ".",
-            Self::Slash => "/",
-            Self::Key0 => "0",
-            Self::Key1 => "1",
-            Self::Key2 => "2",
-            Self::Key3 => "3",
-            Self::Key4 => "4",
-            Self::Key5 => "5",
-            Self::Key6 => "6",
-            Self::Key7 => "7",
-            Self::Key8 => "8",
-            Self::Key9 => "9",
-            Self::Semicolon => ";",
-            Self::Equal => "=",
-            Self::A => "A",
-            Self::B => "B",
-            Self::C => "C",
-            Self::D => "D",
-            Self::E => "E",
-            Self::F => "F",
-            Self::G => "G",
-            Self::H => "H",
-            Self::I => "I",
-            Self::J => "J",
-            Self::K => "K",
-            Self::L => "L",
-            Self::M => "M",
-            Self::N => "N",
-            Self::O => "O",
-            Self::P => "P",
-            Self::Q => "Q",
-            Self::R => "R",
-            Self::S => "S",
-            Self::T => "T",
-            Self::U => "U",
-            Self::V => "V",
-            Self::W => "W",
-            Self::X => "X",
-            Self::Y => "Y",
-            Self::Z => "Z",
-            Self::LeftBracket => "(",
-            Self::Backslash => "\\",
-            Self::RightBracket => ")",
-            Self::GraveAccent => "`",
-            Self::World1 => "World1",
-            Self::World2 => "World2",
-            Self::Escape => "Escape",
-            Self::Enter => "\n",
-            Self::Tab => "Tab",
-            Self::Backspace => "Backspace",
-            Self::Insert => "Insert",
-            Self::Delete => "Delete",
-            Self::Right => "Right",
-            Self::Left => "Left",
-            Self::Down => "Down",
-            Self::Up => "Up",
-            Self::PageUp => "PageUp",
-            Self::PageDown => "PageDown",
-            Self::Home => "Home",
-            Self::End => "End",
-            Self::CapsLock => "CapsLock",
-            Self::ScrollLock => "ScrollLock",
-            Self::NumLock => "NumLock",
-            Self::PrintScreen => "PrintScreen",
-            Self::Pause => "Pause",
-            Self::F1 => "F1",
-            Self::F2 => "F2",
-            Self::F3 => "F3",
-            Self::F4 => "F4",
-            Self::F5 => "F5",
-            Self::F6 => "F6",
-            Self::F7 => "F7",
-            Self::F8 => "F8",
-            Self::F9 => "F9",
-            Self::F10 => "F10",
-            Self::F11 => "F11",
-            Self::F12 => "F12",
-            Self::F13 => "F13",
-            Self::F14 => "F14",
-            Self::F15 => "F15",
-            Self::F16 => "F16",
-            Self::F17 => "F17",
-            Self::F18 => "F18",
-            Self::F19 => "F19",
-            Self::F20 => "F20",
-            Self::F21 => "F21",
-            Self::F22 => "F22",
-            Self::F23 => "F23",
-            Self::F24 => "F24",
-            Self::F25 => "F25",
-            Self::Kp0 => "Kp0",
-            Self::Kp1 => "Kp1",
-            Self::Kp2 => "Kp2",
-            Self::Kp3 => "Kp3",
-            Self::Kp4 => "Kp4",
-            Self::Kp5 => "Kp5",
-            Self::Kp6 => "Kp6",
-            Self::Kp7 => "Kp7",
-            Self::Kp8 => "Kp8",
-            Self::Kp9 => "Kp9",
-            Self::KpDecimal => "KpDecimal",
-            Self::KpDivide => "KpDivide",
-            Self::KpMultiply => "KpMultiply",
-            Self::KpSubtract => "KpSubtract",
-            Self::KpAdd => "KpAdd",
-            Self::KpEnter => "KpEnter",
-            Self::KpEqual => "KpEqual",
-            Self::LeftShift => "LeftShift",
-            Self::LeftControl => "LeftControl",
-            Self::LeftAlt => "LeftAlt",
-            Self::LeftSuper => "LeftSuper",
-            Self::RightShift => "RightShift",
-            Self::RightControl => "RightControl",
-            Self::RightAlt => "RightAlt",
-            Self::RightSuper => "RightSuper",
-            Self::Menu => "Menu",
-            Self::Unknown => "Unknown",
-        }
-    }
-}
-
-pub trait KeyCodeAsU16 {
-    fn to_u16(&self) -> u16;
-    fn from_u16(keysym: u16) -> Self;
-}
-
-impl KeyCodeAsU16 for KeyCode {
-    fn to_u16(&self) -> u16 {
-        match self {
-            Self::Space => 0x0020,
-            Self::Apostrophe => 0x0027,
-            Self::Comma => 0x002c,
-            Self::Minus => 0x002d,
-            Self::Period => 0x002e,
-            Self::Slash => 0x002f,
-            Self::Key0 => 0x0030,
-            Self::Key1 => 0x0031,
-            Self::Key2 => 0x0032,
-            Self::Key3 => 0x0033,
-            Self::Key4 => 0x0034,
-            Self::Key5 => 0x0035,
-            Self::Key6 => 0x0036,
-            Self::Key7 => 0x0037,
-            Self::Key8 => 0x0038,
-            Self::Key9 => 0x0039,
-            Self::Semicolon => 0x003b,
-            Self::Equal => 0x003d,
-            Self::A => 0x0041,
-            Self::B => 0x0042,
-            Self::C => 0x0043,
-            Self::D => 0x0044,
-            Self::E => 0x0045,
-            Self::F => 0x0046,
-            Self::G => 0x0047,
-            Self::H => 0x0048,
-            Self::I => 0x0049,
-            Self::J => 0x004a,
-            Self::K => 0x004b,
-            Self::L => 0x004c,
-            Self::M => 0x004d,
-            Self::N => 0x004e,
-            Self::O => 0x004f,
-            Self::P => 0x0050,
-            Self::Q => 0x0051,
-            Self::R => 0x0052,
-            Self::S => 0x0053,
-            Self::T => 0x0054,
-            Self::U => 0x0055,
-            Self::V => 0x0056,
-            Self::W => 0x0057,
-            Self::X => 0x0058,
-            Self::Y => 0x0059,
-            Self::Z => 0x005a,
-            Self::LeftBracket => 0x005b,
-            Self::Backslash => 0x005c,
-            Self::RightBracket => 0x005d,
-            Self::GraveAccent => 0x0060,
-            Self::World1 => 0x0100,
-            Self::World2 => 0x0101,
-            Self::Escape => 0xff1b,
-            Self::Enter => 0xff0d,
-            Self::Tab => 0xff09,
-            Self::Backspace => 0xff08,
-            Self::Insert => 0xff63,
-            Self::Delete => 0xffff,
-            Self::Right => 0xff53,
-            Self::Left => 0xff51,
-            Self::Down => 0xff54,
-            Self::Up => 0xff52,
-            Self::PageUp => 0xff55,
-            Self::PageDown => 0xff56,
-            Self::Home => 0xff50,
-            Self::End => 0xff57,
-            Self::CapsLock => 0xffe5,
-            Self::ScrollLock => 0xff14,
-            Self::NumLock => 0xff7f,
-            Self::PrintScreen => 0xfd1d,
-            Self::Pause => 0xff13,
-            Self::F1 => 0xffbe,
-            Self::F2 => 0xffbf,
-            Self::F3 => 0xffc0,
-            Self::F4 => 0xffc1,
-            Self::F5 => 0xffc2,
-            Self::F6 => 0xffc3,
-            Self::F7 => 0xffc4,
-            Self::F8 => 0xffc5,
-            Self::F9 => 0xffc6,
-            Self::F10 => 0xffc7,
-            Self::F11 => 0xffc8,
-            Self::F12 => 0xffc9,
-            Self::F13 => 0xffca,
-            Self::F14 => 0xffcb,
-            Self::F15 => 0xffcc,
-            Self::F16 => 0xffcd,
-            Self::F17 => 0xffce,
-            Self::F18 => 0xffcf,
-            Self::F19 => 0xffd0,
-            Self::F20 => 0xffd1,
-            Self::F21 => 0xffd2,
-            Self::F22 => 0xffd3,
-            Self::F23 => 0xffd4,
-            Self::F24 => 0xffd5,
-            Self::F25 => 0xffd6,
-            Self::Kp0 => 0xffb0,
-            Self::Kp1 => 0xffb1,
-            Self::Kp2 => 0xffb2,
-            Self::Kp3 => 0xffb3,
-            Self::Kp4 => 0xffb4,
-            Self::Kp5 => 0xffb5,
-            Self::Kp6 => 0xffb6,
-            Self::Kp7 => 0xffb7,
-            Self::Kp8 => 0xffb8,
-            Self::Kp9 => 0xffb9,
-            Self::KpDecimal => 0xffae,
-            Self::KpDivide => 0xffaf,
-            Self::KpMultiply => 0xffaa,
-            Self::KpSubtract => 0xffad,
-            Self::KpAdd => 0xffab,
-            Self::KpEnter => 0xff8d,
-            Self::KpEqual => 0xffbd,
-            Self::LeftShift => 0xffe1,
-            Self::LeftControl => 0xffe3,
-            Self::LeftAlt => 0xffe9,
-            Self::LeftSuper => 0xffeb,
-            Self::RightShift => 0xffe2,
-            Self::RightControl => 0xffe4,
-            Self::RightAlt => 0xffea,
-            Self::RightSuper => 0xffec,
-            Self::Menu => 0xff67,
-            Self::Unknown => 0x01ff,
-        }
-    }
-    fn from_u16(keysym: u16) -> Self {
-        match keysym {
-            0x0020 => Self::Space,
-            0x0027 => Self::Apostrophe,
-            0x002c => Self::Comma,
-            0x002d => Self::Minus,
-            0x002e => Self::Period,
-            0x002f => Self::Slash,
-            0x0030 => Self::Key0,
-            0x0031 => Self::Key1,
-            0x0032 => Self::Key2,
-            0x0033 => Self::Key3,
-            0x0034 => Self::Key4,
-            0x0035 => Self::Key5,
-            0x0036 => Self::Key6,
-            0x0037 => Self::Key7,
-            0x0038 => Self::Key8,
-            0x0039 => Self::Key9,
-            0x003b => Self::Semicolon,
-            0x003d => Self::Equal,
-            0x0041 => Self::A,
-            0x0042 => Self::B,
-            0x0043 => Self::C,
-            0x0044 => Self::D,
-            0x0045 => Self::E,
-            0x0046 => Self::F,
-            0x0047 => Self::G,
-            0x0048 => Self::H,
-            0x0049 => Self::I,
-            0x004a => Self::J,
-            0x004b => Self::K,
-            0x004c => Self::L,
-            0x004d => Self::M,
-            0x004e => Self::N,
-            0x004f => Self::O,
-            0x0050 => Self::P,
-            0x0051 => Self::Q,
-            0x0052 => Self::R,
-            0x0053 => Self::S,
-            0x0054 => Self::T,
-            0x0055 => Self::U,
-            0x0056 => Self::V,
-            0x0057 => Self::W,
-            0x0058 => Self::X,
-            0x0059 => Self::Y,
-            0x005a => Self::Z,
-            0x005b => Self::LeftBracket,
-            0x005c => Self::Backslash,
-            0x005d => Self::RightBracket,
-            0x0060 => Self::GraveAccent,
-            0x0100 => Self::World1,
-            0x0101 => Self::World2,
-            0xff1b => Self::Escape,
-            0xff0d => Self::Enter,
-            0xff09 => Self::Tab,
-            0xff08 => Self::Backspace,
-            0xff63 => Self::Insert,
-            0xffff => Self::Delete,
-            0xff53 => Self::Right,
-            0xff51 => Self::Left,
-            0xff54 => Self::Down,
-            0xff52 => Self::Up,
-            0xff55 => Self::PageUp,
-            0xff56 => Self::PageDown,
-            0xff50 => Self::Home,
-            0xff57 => Self::End,
-            0xffe5 => Self::CapsLock,
-            0xff14 => Self::ScrollLock,
-            0xff7f => Self::NumLock,
-            0xfd1d => Self::PrintScreen,
-            0xff13 => Self::Pause,
-            0xffbe => Self::F1,
-            0xffbf => Self::F2,
-            0xffc0 => Self::F3,
-            0xffc1 => Self::F4,
-            0xffc2 => Self::F5,
-            0xffc3 => Self::F6,
-            0xffc4 => Self::F7,
-            0xffc5 => Self::F8,
-            0xffc6 => Self::F9,
-            0xffc7 => Self::F10,
-            0xffc8 => Self::F11,
-            0xffc9 => Self::F12,
-            0xffca => Self::F13,
-            0xffcb => Self::F14,
-            0xffcc => Self::F15,
-            0xffcd => Self::F16,
-            0xffce => Self::F17,
-            0xffcf => Self::F18,
-            0xffd0 => Self::F19,
-            0xffd1 => Self::F20,
-            0xffd2 => Self::F21,
-            0xffd3 => Self::F22,
-            0xffd4 => Self::F23,
-            0xffd5 => Self::F24,
-            0xffd6 => Self::F25,
-            0xffb0 => Self::Kp0,
-            0xffb1 => Self::Kp1,
-            0xffb2 => Self::Kp2,
-            0xffb3 => Self::Kp3,
-            0xffb4 => Self::Kp4,
-            0xffb5 => Self::Kp5,
-            0xffb6 => Self::Kp6,
-            0xffb7 => Self::Kp7,
-            0xffb8 => Self::Kp8,
-            0xffb9 => Self::Kp9,
-            0xffae => Self::KpDecimal,
-            0xffaf => Self::KpDivide,
-            0xffaa => Self::KpMultiply,
-            0xffad => Self::KpSubtract,
-            0xffab => Self::KpAdd,
-            0xff8d => Self::KpEnter,
-            0xffbd => Self::KpEqual,
-            0xffe1 => Self::LeftShift,
-            0xffe3 => Self::LeftControl,
-            0xffe9 => Self::LeftAlt,
-            0xffeb => Self::LeftSuper,
-            0xffe2 => Self::RightShift,
-            0xffe4 => Self::RightControl,
-            0xffea => Self::RightAlt,
-            0xffec => Self::RightSuper,
-            0xff67 => Self::Menu,
-            _ => Self::Unknown,
-        }
-    }
-}
-
-pub trait MouseButtonAsU8 {
-    fn to_u8(&self) -> u8;
-    fn from_u8(btn: u8) -> Self;
-}
-
-impl MouseButtonAsU8 for MouseButton {
-    fn to_u8(&self) -> u8 {
-        match self {
-            Self::Left => 0,
-            Self::Middle => 1,
-            Self::Right => 2,
-            Self::Unknown => 3,
-        }
-    }
-
-    fn from_u8(btn: u8) -> Self {
-        match btn {
-            0 => Self::Left,
-            1 => Self::Middle,
-            2 => Self::Right,
-            _ => Self::Unknown,
-        }
-    }
-}

+ 8 - 15
bin/darkwallet/src/main.rs

@@ -51,32 +51,25 @@ use log::LevelFilter;
 
 mod app;
 mod darkirc;
-use darkirc::DarkIrcBackend;
-//mod chatapp;
-//mod chatview;
-//mod editbox;
 mod error;
 mod expr;
-//mod gfx;
-mod gfx2;
-mod keysym;
+mod gfx;
 mod mesh;
 mod net;
 //mod plugin;
 mod prop;
 mod pubsub;
 //mod py;
-//mod res;
 mod scene;
-mod shader;
-mod text2;
+mod text;
 mod ui;
 mod util;
 
 use crate::{
+    darkirc::DarkIrcBackend,
     net::ZeroMQAdapter,
     scene::{SceneGraph, SceneGraphPtr2},
-    text2::TextShaper,
+    text::TextShaper,
 };
 
 pub type ExecutorPtr = Arc<smol::Executor<'static>>;
@@ -134,8 +127,8 @@ fn main() {
     let (method_req, method_rep) = mpsc::channel();
     // The UI actually needs to be running for this to reply back.
     // Otherwise calls will just hang.
-    let render_api = gfx2::RenderApi::new(method_req);
-    let event_pub = gfx2::GraphicsEventPublisher::new();
+    let render_api = gfx::RenderApi::new(method_req);
+    let event_pub = gfx::GraphicsEventPublisher::new();
 
     let text_shaper = TextShaper::new();
 
@@ -202,8 +195,8 @@ fn main() {
     });
     async_runtime.push_task(ev_relay_task);
 
-    //let stage = gfx2::Stage::new(method_rep, event_pub);
-    gfx2::run_gui(app, async_runtime, method_rep, event_pub);
+    //let stage = gfx::Stage::new(method_rep, event_pub);
+    gfx::run_gui(app, async_runtime, method_rep, event_pub);
     debug!(target: "main", "Started GFX backend");
 }
 

+ 1 - 1
bin/darkwallet/src/mesh.rs

@@ -18,7 +18,7 @@
 
 use crate::{
     error::Result,
-    gfx2::{DrawMesh, Point, Rectangle, RenderApi, Vertex},
+    gfx::{DrawMesh, Point, Rectangle, RenderApi, Vertex},
 };
 use miniquad::{BufferId, TextureId};
 

+ 0 - 73
bin/darkwallet/src/res.rs

@@ -1,73 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2024 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use crate::error::{Error, Result};
-
-pub type ResourceId = u32;
-
-pub struct ResourceManager<T> {
-    resources: Vec<(ResourceId, Option<T>)>,
-    freed: Vec<usize>,
-    id_counter: ResourceId,
-}
-
-impl<T> ResourceManager<T> {
-    pub fn new() -> Self {
-        Self { resources: vec![], freed: vec![], id_counter: 0 }
-    }
-
-    pub fn alloc(&mut self, rsrc: T) -> ResourceId {
-        let id = self.id_counter;
-        self.id_counter += 1;
-
-        if self.freed.is_empty() {
-            let idx = self.resources.len();
-            self.resources.push((id, Some(rsrc)));
-        } else {
-            let idx = self.freed.pop().unwrap();
-            let _ = std::mem::replace(&mut self.resources[idx], (id, Some(rsrc)));
-        }
-        id
-    }
-
-    pub fn get(&self, id: ResourceId) -> Option<&T> {
-        for (idx, (rsrc_id, rsrc)) in self.resources.iter().enumerate() {
-            if self.freed.contains(&idx) {
-                continue
-            }
-            if *rsrc_id == id {
-                return rsrc.as_ref()
-            }
-        }
-        None
-    }
-
-    pub fn free(&mut self, id: ResourceId) -> Result<()> {
-        for (idx, (rsrc_id, rsrc)) in self.resources.iter_mut().enumerate() {
-            if self.freed.contains(&idx) {
-                return Err(Error::ResourceNotFound)
-            }
-            if *rsrc_id == id {
-                *rsrc = None;
-                self.freed.push(idx);
-                return Ok(())
-            }
-        }
-        Err(Error::ResourceNotFound)
-    }
-}

+ 0 - 251
bin/darkwallet/src/text.rs

@@ -1,251 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2024 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use freetype as ft;
-
-use crate::gfx::{FreetypeFace, Rectangle};
-
-// From https://sourceforge.net/projects/freetype/files/freetype2/2.6/
-//
-// * An `FT_Face' object can only be safely used from one thread at
-//   a time.
-//
-// * An `FT_Library'  object can  now be used  without modification
-//   from multiple threads at the same time.
-//
-// * `FT_Face' creation and destruction  with the same `FT_Library'
-//   object can only be done from one thread at a time.
-//
-// One can use a single  `FT_Library' object across threads as long
-// as a mutex lock is used around `FT_New_Face' and `FT_Done_Face'.
-// Any calls to `FT_Load_Glyph' and similar API are safe and do not
-// need the lock  to be held as  long as the same  `FT_Face' is not
-// used from multiple threads at the same time.
-
-// Harfbuzz is threadsafe.
-
-// Notes:
-// * All ft init and face creation should happen at startup.
-// * FT faces protected behind an async Mutex
-// * Glyph cache. Key is (glyph_id, font_size)
-// * Glyph texture cache: (glyph_id, font_size, color)
-
-#[derive(Clone)]
-pub struct Glyph {
-    pub id: u32,
-    // Substring this glyph corresponds to
-    pub substr: String,
-
-    // The texture
-    pub bmp: Vec<u8>,
-    pub bmp_width: u16,
-    pub bmp_height: u16,
-
-    pub pos: Rectangle<f32>,
-}
-
-pub struct TextShaper {
-    pub font_faces: Vec<FreetypeFace>,
-}
-
-unsafe impl Send for TextShaper {}
-unsafe impl Sync for TextShaper {}
-
-impl TextShaper {
-    fn split_into_substrs(&self, text: String) -> Vec<(usize, String)> {
-        let mut current_idx = 0;
-        let mut current_str = String::new();
-        let mut substrs = vec![];
-        'next_char: for chr in text.chars() {
-            let idx = 'get_idx: {
-                for i in 0..self.font_faces.len() {
-                    let ft_face = &self.font_faces[i];
-                    if ft_face.get_char_index(chr as usize).is_some() {
-                        break 'get_idx i
-                    }
-                }
-
-                warn!("no font fallback for char: '{}'", chr);
-                // Skip this char
-                continue 'next_char
-            };
-            if current_idx != idx {
-                if !current_str.is_empty() {
-                    // Push
-                    substrs.push((current_idx, current_str.clone()));
-                }
-
-                current_str.clear();
-                current_idx = idx;
-            }
-            current_str.push(chr);
-        }
-        if !current_str.is_empty() {
-            // Push
-            substrs.push((current_idx, current_str));
-        }
-        substrs
-    }
-
-    pub fn shape(&self, text: String, font_size: f32, text_color: [f32; 4]) -> Vec<Glyph> {
-        let substrs = self.split_into_substrs(text.clone());
-
-        let mut glyphs: Vec<Glyph> = vec![];
-
-        let mut current_x = 0.;
-        let mut current_y = 0.;
-
-        for (face_idx, text) in substrs {
-            //debug!("substr {}", text);
-            let face = &self.font_faces[face_idx];
-            if face.has_fixed_sizes() {
-                // emojis required a fixed size
-                //face.set_char_size(109 * 64, 0, 72, 72).unwrap();
-                face.select_size(0).unwrap();
-            } else {
-                face.set_char_size(font_size as isize * 64, 0, 72, 72).unwrap();
-            }
-
-            let hb_font = harfbuzz_rs::Font::from_freetype_face(face.clone());
-            let buffer = harfbuzz_rs::UnicodeBuffer::new()
-                .set_cluster_level(harfbuzz_rs::ClusterLevel::MonotoneCharacters)
-                .add_str(&text);
-            let output = harfbuzz_rs::shape(&hb_font, buffer, &[]);
-
-            let positions = output.get_glyph_positions();
-            let infos = output.get_glyph_infos();
-
-            let mut prev_cluster = 0;
-
-            for (i, (position, info)) in positions.iter().zip(infos).enumerate() {
-                let gid = info.codepoint;
-                // Index within this substr
-                let curr_cluster = info.cluster as usize;
-
-                // Skip first time
-                if i != 0 {
-                    let substr = text[prev_cluster..curr_cluster].to_string();
-                    glyphs.last_mut().unwrap().substr = substr;
-                }
-
-                prev_cluster = curr_cluster;
-
-                let mut flags = ft::face::LoadFlag::DEFAULT;
-                if face.has_color() {
-                    flags |= ft::face::LoadFlag::COLOR;
-                }
-                // FIXME: glyph 884 hangs on android
-                // For now just avoid using emojis on android
-                //debug!("load_glyph {}", gid);
-                face.load_glyph(gid, flags).unwrap();
-                //debug!("load_glyph {} [done]", gid);
-
-                let glyph = face.glyph();
-                glyph.render_glyph(ft::RenderMode::Normal).unwrap();
-
-                let bmp = glyph.bitmap();
-                let buffer = bmp.buffer();
-                let bmp_width = bmp.width() as usize;
-                let bmp_height = bmp.rows() as usize;
-                let bearing_x = glyph.bitmap_left() as f32;
-                let bearing_y = glyph.bitmap_top() as f32;
-
-                let pixel_mode = bmp.pixel_mode().unwrap();
-                let bmp = match pixel_mode {
-                    ft::bitmap::PixelMode::Bgra => {
-                        let mut tdata = vec![];
-                        tdata.resize(4 * bmp_width * bmp_height, 0);
-                        // Convert from BGRA to RGBA
-                        for i in 0..bmp_width * bmp_height {
-                            let idx = i * 4;
-                            let b = buffer[idx];
-                            let g = buffer[idx + 1];
-                            let r = buffer[idx + 2];
-                            let a = buffer[idx + 3];
-                            tdata[idx] = r;
-                            tdata[idx + 1] = g;
-                            tdata[idx + 2] = b;
-                            tdata[idx + 3] = a;
-                        }
-                        tdata
-                    }
-                    ft::bitmap::PixelMode::Gray => {
-                        // Convert from greyscale to RGBA8
-                        let tdata: Vec<_> = buffer
-                            .iter()
-                            .flat_map(|coverage| {
-                                let r = (255. * text_color[0]) as u8;
-                                let g = (255. * text_color[1]) as u8;
-                                let b = (255. * text_color[2]) as u8;
-                                let α = ((*coverage as f32) * text_color[3]) as u8;
-                                vec![r, g, b, α]
-                            })
-                            .collect();
-                        tdata
-                    }
-                    _ => panic!("unsupport pixel mode: {:?}", pixel_mode),
-                };
-
-                let pos = if face.has_fixed_sizes() {
-                    // Downscale by height
-                    let w = (bmp_width as f32 * font_size) / bmp_height as f32;
-                    let h = font_size;
-
-                    // Shouldn't this use the bearing?
-                    let x = current_x;
-                    let y = current_y - h;
-
-                    current_x += w;
-
-                    Rectangle { x, y, w, h }
-                } else {
-                    let (w, h) = (bmp_width as f32, bmp_height as f32);
-
-                    let off_x = position.x_offset as f32 / 64.;
-                    let off_y = position.y_offset as f32 / 64.;
-
-                    let x = current_x + off_x + bearing_x;
-                    let y = current_y - off_y - bearing_y;
-
-                    let x_advance = position.x_advance as f32 / 64.;
-                    let y_advance = position.y_advance as f32 / 64.;
-                    current_x += x_advance;
-                    current_y += y_advance;
-
-                    Rectangle { x, y, w, h }
-                };
-
-                let glyph = Glyph {
-                    id: gid,
-                    substr: String::new(),
-                    bmp,
-                    bmp_width: bmp_width as u16,
-                    bmp_height: bmp_height as u16,
-                    pos,
-                };
-
-                glyphs.push(glyph);
-            }
-
-            let substr = text[prev_cluster..].to_string();
-            glyphs.last_mut().unwrap().substr = substr;
-        }
-
-        glyphs
-    }
-}

+ 1 - 1
bin/darkwallet/src/text2/atlas.rs → bin/darkwallet/src/text/atlas.rs

@@ -2,7 +2,7 @@ use miniquad::TextureId;
 
 use crate::{
     error::{Error, Result},
-    gfx2::{Rectangle, RenderApi, RenderApiPtr},
+    gfx::{Rectangle, RenderApi, RenderApiPtr},
     util::{ansi_texture, zip3},
 };
 

+ 1 - 1
bin/darkwallet/src/text2/mod.rs → bin/darkwallet/src/text/mod.rs

@@ -34,7 +34,7 @@ use std::{
 
 use crate::{
     error::Result,
-    gfx2::{Rectangle, RenderApi, RenderApiPtr},
+    gfx::{Rectangle, RenderApi, RenderApiPtr},
     util::ansi_texture,
 };
 

+ 1 - 1
bin/darkwallet/src/text2/old_atlas.rs → bin/darkwallet/src/text/old_atlas.rs

@@ -2,7 +2,7 @@ use miniquad::TextureId;
 
 use crate::{
     error::Result,
-    gfx2::{Rectangle, RenderApi, RenderApiPtr},
+    gfx::{Rectangle, RenderApi, RenderApiPtr},
     util::ansi_texture,
 };
 

+ 0 - 0
bin/darkwallet/src/text2/wrap.rs → bin/darkwallet/src/text/wrap.rs


+ 1 - 1
bin/darkwallet/src/ui/button.rs

@@ -24,7 +24,7 @@ use std::sync::{
 };
 
 use crate::{
-    gfx2::{
+    gfx::{
         DrawCall, DrawInstruction, DrawMesh, GraphicsEventPublisherPtr, Point, Rectangle,
         RenderApiPtr, Vertex,
     },

+ 6 - 6
bin/darkwallet/src/ui/chatview.rs

@@ -35,7 +35,7 @@ use std::{
 
 use crate::{
     error::Result,
-    gfx2::{
+    gfx::{
         DrawCall, DrawInstruction, DrawMesh, GraphicsEventPublisherPtr, Point, Rectangle,
         RenderApi, RenderApiPtr, Vertex,
     },
@@ -46,7 +46,7 @@ use crate::{
     },
     pubsub::Subscription,
     scene::{Pimpl, SceneGraph, SceneGraphPtr2, SceneNodeId},
-    text2::{self, Glyph, GlyphPositionIter, SpritePtr, TextShaper, TextShaperPtr},
+    text::{self, Glyph, GlyphPositionIter, SpritePtr, TextShaper, TextShaperPtr},
     util::zip3,
     ExecutorPtr,
 };
@@ -107,7 +107,7 @@ const PRELOAD_PAGES: usize = 10;
 #[derive(Clone)]
 struct Page {
     msgs: Vec<Message>,
-    atlas: text2::RenderedAtlas,
+    atlas: text::RenderedAtlas,
 }
 
 #[derive(Clone)]
@@ -120,7 +120,7 @@ type Page2Ptr = Arc<Page2>;
 
 struct Page2 {
     msgs: Vec<Message>,
-    atlas: SyncMutex<text2::RenderedAtlas>,
+    atlas: SyncMutex<text::RenderedAtlas>,
     // One draw call per page.
     // Resizing the canvas means we recalc wrapping and the mesh changes
     mesh_inf: SyncMutex<Option<PageMeshInfo>>,
@@ -128,7 +128,7 @@ struct Page2 {
 
 impl Page2 {
     async fn new(msgs: Vec<Message>, render_api: &RenderApi) -> Arc<Self> {
-        let mut atlas = text2::Atlas::new(render_api);
+        let mut atlas = text::Atlas::new(render_api);
         for msg in &msgs {
             atlas.push(&msg.glyphs);
         }
@@ -169,7 +169,7 @@ impl Page2 {
             // Finally is just the message itself
             let mut section = 2;
 
-            let mut lines = text2::wrap(clip.w, font_size, glyphs);
+            let mut lines = text::wrap(clip.w, font_size, glyphs);
             // We are drawing bottom up but line wrap gives us lines in normal order
             lines.reverse();
             let last_idx = lines.len() - 1;

+ 3 - 3
bin/darkwallet/src/ui/editbox.rs

@@ -29,7 +29,7 @@ use std::{
 
 use crate::{
     error::Result,
-    gfx2::{
+    gfx::{
         DrawCall, DrawInstruction, DrawMesh, GraphicsEventPublisherPtr, Point, Rectangle,
         RenderApi, RenderApiPtr, Vertex,
     },
@@ -40,7 +40,7 @@ use crate::{
     },
     pubsub::Subscription,
     scene::{Pimpl, SceneGraph, SceneGraphPtr2, SceneNodeId},
-    text2::{self, Glyph, GlyphPositionIter, SpritePtr, TextShaper, TextShaperPtr},
+    text::{self, Glyph, GlyphPositionIter, SpritePtr, TextShaper, TextShaperPtr},
     util::zip3,
     ExecutorPtr,
 };
@@ -361,7 +361,7 @@ impl EditBox {
         debug!(target: "ui::editbox", "    cursor_pos={cursor_pos}, is_focused={is_focused}");
 
         let glyphs = self.glyphs.lock().unwrap().clone();
-        let atlas = text2::make_texture_atlas(&self.render_api, &glyphs).await.unwrap();
+        let atlas = text::make_texture_atlas(&self.render_api, &glyphs).await.unwrap();
 
         let mut mesh = MeshBuilder::with_clip(clip.clone());
         self.draw_selected(&mut mesh, &glyphs, clip.h).unwrap();

+ 2 - 2
bin/darkwallet/src/ui/image.rs

@@ -26,14 +26,14 @@ use std::{
 };
 
 use crate::{
-    gfx2::{DrawCall, DrawInstruction, DrawMesh, Rectangle, RenderApi, RenderApiPtr, Vertex},
+    gfx::{DrawCall, DrawInstruction, DrawMesh, Rectangle, RenderApi, RenderApiPtr, Vertex},
     mesh::{Color, MeshBuilder, MeshInfo, COLOR_BLUE, COLOR_WHITE},
     prop::{
         PropertyBool, PropertyColor, PropertyFloat32, PropertyPtr, PropertyStr, PropertyUint32,
         Role,
     },
     scene::{Pimpl, SceneGraph, SceneGraphPtr2, SceneNodeId},
-    text2::{self, Glyph, GlyphPositionIter, SpritePtr, TextShaper, TextShaperPtr},
+    text::{self, Glyph, GlyphPositionIter, SpritePtr, TextShaper, TextShaperPtr},
     util::zip3,
     ExecutorPtr,
 };

+ 1 - 1
bin/darkwallet/src/ui/layer.rs

@@ -21,7 +21,7 @@ use rand::{rngs::OsRng, Rng};
 use std::sync::{Arc, Weak};
 
 use crate::{
-    gfx2::{DrawCall, DrawInstruction, Rectangle, RenderApiPtr},
+    gfx::{DrawCall, DrawInstruction, Rectangle, RenderApiPtr},
     prop::{PropertyBool, PropertyPtr, Role},
     scene::{Pimpl, SceneGraph, SceneGraphPtr2, SceneNodeId},
     ExecutorPtr,

+ 1 - 1
bin/darkwallet/src/ui/mesh.rs

@@ -20,7 +20,7 @@ use rand::{rngs::OsRng, Rng};
 use std::sync::{Arc, Weak};
 
 use crate::{
-    gfx2::{DrawCall, DrawInstruction, DrawMesh, Rectangle, RenderApiPtr, Vertex},
+    gfx::{DrawCall, DrawInstruction, DrawMesh, Rectangle, RenderApiPtr, Vertex},
     prop::{PropertyPtr, PropertyUint32, Role},
     scene::{Pimpl, SceneGraph, SceneGraphPtr2, SceneNodeId},
     ExecutorPtr,

+ 1 - 1
bin/darkwallet/src/ui/mod.rs

@@ -22,7 +22,7 @@ use std::sync::{Arc, Weak};
 use crate::{
     error::{Error, Result},
     expr::{SExprMachine, SExprVal},
-    gfx2::{DrawCall, Rectangle},
+    gfx::{DrawCall, Rectangle},
     prop::{PropertyPtr, Role},
     scene::{SceneGraph, SceneNode, SceneNodeId, SceneNodeType},
     ExecutorPtr,

+ 3 - 3
bin/darkwallet/src/ui/text.rs

@@ -22,14 +22,14 @@ use rand::{rngs::OsRng, Rng};
 use std::sync::{Arc, Mutex as SyncMutex, Weak};
 
 use crate::{
-    gfx2::{DrawCall, DrawInstruction, DrawMesh, Rectangle, RenderApi, RenderApiPtr, Vertex},
+    gfx::{DrawCall, DrawInstruction, DrawMesh, Rectangle, RenderApi, RenderApiPtr, Vertex},
     mesh::{Color, MeshBuilder, MeshInfo, COLOR_BLUE, COLOR_WHITE},
     prop::{
         PropertyBool, PropertyColor, PropertyFloat32, PropertyPtr, PropertyStr, PropertyUint32,
         Role,
     },
     scene::{Pimpl, SceneGraph, SceneGraphPtr2, SceneNodeId},
-    text2::{self, Glyph, GlyphPositionIter, SpritePtr, TextShaper, TextShaperPtr},
+    text::{self, Glyph, GlyphPositionIter, SpritePtr, TextShaper, TextShaperPtr},
     util::zip3,
     ExecutorPtr,
 };
@@ -137,7 +137,7 @@ impl Text {
     ) -> TextRenderInfo {
         debug!(target: "ui::text", "Rendering label '{}'", text);
         let glyphs = text_shaper.shape(text, font_size).await;
-        let atlas = text2::make_texture_atlas(render_api, &glyphs).await.unwrap();
+        let atlas = text::make_texture_atlas(render_api, &glyphs).await.unwrap();
 
         let mut mesh = MeshBuilder::new();
         let mut glyph_pos_iter = GlyphPositionIter::new(font_size, &glyphs, baseline);

+ 1 - 1
bin/darkwallet/src/ui/win.rs

@@ -19,7 +19,7 @@
 use std::sync::{Arc, Weak};
 
 use crate::{
-    gfx2::{DrawCall, GraphicsEventPublisherPtr, Rectangle, RenderApiPtr},
+    gfx::{DrawCall, GraphicsEventPublisherPtr, Rectangle, RenderApiPtr},
     prop::{PropertyPtr, Role},
     scene::{Pimpl, SceneGraph, SceneGraphPtr2, SceneNodeId},
     ExecutorPtr,