Przeglądaj źródła

wallet: Mesh::on_modify rect property calls redraw

darkfi 2 lat temu
rodzic
commit
33a67b239b

+ 20 - 6
bin/darkwallet/src/app.rs

@@ -122,9 +122,9 @@ impl App {
         // Window::new(window, weak sg)
         drop(sg);
         let pimpl = Window::new(
+            self.ex.clone(),
             self.sg.clone(),
             window_id,
-            self.ex.clone(),
             self.render_api.clone(),
             self.event_pub.clone(),
         )
@@ -189,7 +189,7 @@ impl App {
         let node_id = node.id;
         drop(sg);
         let pimpl =
-            RenderLayer::new(self.sg.clone(), node_id, self.ex.clone(), self.render_api.clone())
+            RenderLayer::new(self.ex.clone(), self.sg.clone(), node_id, self.render_api.clone())
                 .await;
         let mut sg = self.sg.lock().await;
         let node = sg.get_node_mut(node_id).unwrap();
@@ -226,8 +226,15 @@ impl App {
         ];
         let indices = vec![0, 2, 1, 1, 2, 3];
         drop(sg);
-        let pimpl =
-            Mesh::new(self.sg.clone(), node_id, self.render_api.clone(), verts, indices).await;
+        let pimpl = Mesh::new(
+            self.ex.clone(),
+            self.sg.clone(),
+            node_id,
+            self.render_api.clone(),
+            verts,
+            indices,
+        )
+        .await;
         let mut sg = self.sg.lock().await;
         let node = sg.get_node_mut(node_id).unwrap();
         node.pimpl = pimpl;
@@ -260,8 +267,15 @@ impl App {
         ];
         let indices = vec![0, 2, 1, 1, 2, 3];
         drop(sg);
-        let pimpl =
-            Mesh::new(self.sg.clone(), node_id, self.render_api.clone(), verts, indices).await;
+        let pimpl = Mesh::new(
+            self.ex.clone(),
+            self.sg.clone(),
+            node_id,
+            self.render_api.clone(),
+            verts,
+            indices,
+        )
+        .await;
         let mut sg = self.sg.lock().await;
         let node = sg.get_node_mut(node_id).unwrap();
         node.pimpl = pimpl;

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

@@ -631,7 +631,7 @@ pub enum Pimpl {
     //ChatView(chatview::ChatViewPtr),
     Window(ui::WindowPtr),
     RenderLayer(ui::RenderLayerPtr),
-    Mesh(ui::Mesh),
+    Mesh(ui::MeshPtr),
 }
 
 impl std::fmt::Debug for SceneNode {

+ 4 - 5
bin/darkwallet/src/ui/layer.rs

@@ -28,9 +28,9 @@ pub struct RenderLayer {
 
 impl RenderLayer {
     pub async fn new(
+        ex: Arc<smol::Executor<'static>>,
         sg_ptr: SceneGraphPtr2,
         node_id: SceneNodeId,
-        ex: Arc<smol::Executor<'static>>,
         render_api: RenderApiPtr,
     ) -> Pimpl {
         let sg = sg_ptr.lock().await;
@@ -68,7 +68,7 @@ impl RenderLayer {
             return;
         };
 
-        let Some(draw_update) = self.draw(&sg, &parent_rect).await else {
+        let Some(draw_update) = self.draw(&sg, &parent_rect) else {
             error!("RenderLayer {:?} failed to draw", node);
             return;
         };
@@ -76,8 +76,7 @@ impl RenderLayer {
         debug!("replace draw calls done");
     }
 
-    #[async_recursion]
-    pub async fn draw(&self, sg: &SceneGraph, parent_rect: &Rectangle) -> Option<DrawUpdate> {
+    pub fn draw(&self, sg: &SceneGraph, parent_rect: &Rectangle) -> Option<DrawUpdate> {
         debug!(target: "app", "RenderLayer::draw()");
         let node = sg.get_node(self.node_id).unwrap();
 
@@ -117,7 +116,7 @@ impl RenderLayer {
             let node = sg.get_node(child_inf.id).unwrap();
 
             let dcs = match &node.pimpl {
-                Pimpl::RenderLayer(layer) => layer.draw(&sg, &rect).await,
+                Pimpl::RenderLayer(layer) => layer.draw(&sg, &rect),
                 Pimpl::Mesh(mesh) => mesh.draw(&sg, &rect),
                 _ => {
                     error!(target: "app", "unhandled pimpl type");

+ 43 - 12
bin/darkwallet/src/ui/mesh.rs

@@ -1,4 +1,5 @@
 use rand::{rngs::OsRng, Rng};
+use std::sync::{Arc, Weak};
 
 use crate::{
     gfx2::{DrawCall, DrawInstruction, DrawMesh, Rectangle, RenderApiPtr, Vertex},
@@ -6,9 +7,12 @@ use crate::{
     scene::{Pimpl, SceneGraph, SceneGraphPtr2, SceneNodeId},
 };
 
-use super::{eval_rect, read_rect, DrawUpdate, Stoppable};
+use super::{eval_rect, get_parent_rect, read_rect, DrawUpdate, OnModify, Stoppable};
+
+pub type MeshPtr = Arc<Mesh>;
 
 pub struct Mesh {
+    sg: SceneGraphPtr2,
     render_api: RenderApiPtr,
     vertex_buffer: miniquad::BufferId,
     index_buffer: miniquad::BufferId,
@@ -23,6 +27,7 @@ pub struct Mesh {
 
 impl Mesh {
     pub async fn new(
+        ex: Arc<smol::Executor<'static>>,
         sg: SceneGraphPtr2,
         node_id: SceneNodeId,
         render_api: RenderApiPtr,
@@ -33,19 +38,45 @@ impl Mesh {
         let vertex_buffer = render_api.new_vertex_buffer(verts).await.unwrap();
         let index_buffer = render_api.new_index_buffer(indices).await.unwrap();
 
-        let mut sg = sg.lock().await;
-        let node = sg.get_node_mut(node_id).unwrap();
+        let scene_graph = sg.lock().await;
+        let node = scene_graph.get_node(node_id).unwrap();
+        let node_name = node.name.clone();
         let rect = node.get_property("rect").expect("RenderLayer::rect");
+        drop(scene_graph);
+
+        let self_ = Arc::new_cyclic(|me: &Weak<Self>| {
+            let mut on_modify = OnModify::new(ex, node_name, node_id, me.clone());
+            on_modify.when_change(rect.clone(), Self::redraw);
+
+            Self {
+                sg,
+                render_api,
+                vertex_buffer,
+                index_buffer,
+                num_elements,
+                dc_key: OsRng.gen(),
+                node_id,
+                rect,
+            }
+        });
+
+        Pimpl::Mesh(self_)
+    }
 
-        Pimpl::Mesh(Self {
-            render_api,
-            vertex_buffer,
-            index_buffer,
-            num_elements,
-            dc_key: OsRng.gen(),
-            node_id,
-            rect,
-        })
+    async fn redraw(self: Arc<Self>) {
+        let sg = self.sg.lock().await;
+        let node = sg.get_node(self.node_id).unwrap();
+
+        let Some(parent_rect) = get_parent_rect(&sg, node) else {
+            return;
+        };
+
+        let Some(draw_update) = self.draw(&sg, &parent_rect) else {
+            error!("Mesh {:?} failed to draw", node);
+            return;
+        };
+        self.render_api.replace_draw_calls(draw_update.draw_calls).await;
+        debug!("replace draw calls done");
     }
 
     pub fn draw(&self, sg: &SceneGraph, parent_rect: &Rectangle) -> Option<DrawUpdate> {

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

@@ -9,7 +9,7 @@ use crate::{
 };
 
 mod mesh;
-pub use mesh::Mesh;
+pub use mesh::{Mesh, MeshPtr};
 mod layer;
 pub use layer::{RenderLayer, RenderLayerPtr};
 mod win;

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

@@ -21,9 +21,9 @@ pub struct Window {
 
 impl Window {
     pub async fn new(
+        ex: Arc<smol::Executor<'static>>,
         sg: SceneGraphPtr2,
         node_id: SceneNodeId,
-        ex: Arc<smol::Executor<'static>>,
         render_api: RenderApiPtr,
         event_pub: GraphicsEventPublisherPtr,
     ) -> Pimpl {
@@ -103,7 +103,7 @@ impl Window {
             debug!(target: "app", "Window::draw() calling draw() for node '{}':{}", node.name, node.id);
 
             let dcs = match &node.pimpl {
-                Pimpl::RenderLayer(layer) => layer.draw(sg, &parent_rect).await,
+                Pimpl::RenderLayer(layer) => layer.draw(sg, &parent_rect),
                 _ => {
                     error!(target: "app", "unhandled pimpl type");
                     continue