From 33a67b239b57adfd5a16425158a78438d8bb87ef Mon Sep 17 00:00:00 2001 From: darkfi Date: Thu, 20 Jun 2024 12:27:36 +0200 Subject: [PATCH] wallet: Mesh::on_modify rect property calls redraw --- bin/darkwallet/src/app.rs | 26 ++++++++++++---- bin/darkwallet/src/scene.rs | 2 +- bin/darkwallet/src/ui/layer.rs | 9 +++--- bin/darkwallet/src/ui/mesh.rs | 55 ++++++++++++++++++++++++++-------- bin/darkwallet/src/ui/mod.rs | 2 +- bin/darkwallet/src/ui/win.rs | 4 +-- 6 files changed, 71 insertions(+), 27 deletions(-) diff --git a/bin/darkwallet/src/app.rs b/bin/darkwallet/src/app.rs index db9e4b54c..9609ad3c3 100644 --- a/bin/darkwallet/src/app.rs +++ b/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; diff --git a/bin/darkwallet/src/scene.rs b/bin/darkwallet/src/scene.rs index 5a0c5ff27..147cb6896 100644 --- a/bin/darkwallet/src/scene.rs +++ b/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 { diff --git a/bin/darkwallet/src/ui/layer.rs b/bin/darkwallet/src/ui/layer.rs index 2c08005e0..f425a2294 100644 --- a/bin/darkwallet/src/ui/layer.rs +++ b/bin/darkwallet/src/ui/layer.rs @@ -28,9 +28,9 @@ pub struct RenderLayer { impl RenderLayer { pub async fn new( + ex: Arc>, sg_ptr: SceneGraphPtr2, node_id: SceneNodeId, - ex: Arc>, 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 { + pub fn draw(&self, sg: &SceneGraph, parent_rect: &Rectangle) -> Option { 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"); diff --git a/bin/darkwallet/src/ui/mesh.rs b/bin/darkwallet/src/ui/mesh.rs index aa24abb09..3384eb9f1 100644 --- a/bin/darkwallet/src/ui/mesh.rs +++ b/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; 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>, 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); - Pimpl::Mesh(Self { - render_api, - vertex_buffer, - index_buffer, - num_elements, - dc_key: OsRng.gen(), - node_id, - rect, - }) + let self_ = Arc::new_cyclic(|me: &Weak| { + 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_) + } + + async fn redraw(self: Arc) { + 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 { diff --git a/bin/darkwallet/src/ui/mod.rs b/bin/darkwallet/src/ui/mod.rs index cfc03f7a5..71c2339bb 100644 --- a/bin/darkwallet/src/ui/mod.rs +++ b/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; diff --git a/bin/darkwallet/src/ui/win.rs b/bin/darkwallet/src/ui/win.rs index f02bfafdf..e62aa660a 100644 --- a/bin/darkwallet/src/ui/win.rs +++ b/bin/darkwallet/src/ui/win.rs @@ -21,9 +21,9 @@ pub struct Window { impl Window { pub async fn new( + ex: Arc>, sg: SceneGraphPtr2, node_id: SceneNodeId, - ex: Arc>, 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