|
@@ -1,5 +1,7 @@
|
|
|
use async_lock::Mutex;
|
|
use async_lock::Mutex;
|
|
|
|
|
+use async_recursion::async_recursion;
|
|
|
use futures::{stream::FuturesUnordered, StreamExt};
|
|
use futures::{stream::FuturesUnordered, StreamExt};
|
|
|
|
|
+use rand::{rngs::OsRng, Rng};
|
|
|
use std::{
|
|
use std::{
|
|
|
sync::{mpsc, Arc, Weak},
|
|
sync::{mpsc, Arc, Weak},
|
|
|
thread,
|
|
thread,
|
|
@@ -8,9 +10,13 @@ use std::{
|
|
|
use crate::{
|
|
use crate::{
|
|
|
chatapp,
|
|
chatapp,
|
|
|
error::{Error, Result},
|
|
error::{Error, Result},
|
|
|
- expr::Op,
|
|
|
|
|
- gfx2::{GraphicsEvent, RenderApiPtr},
|
|
|
|
|
- prop::{Property, PropertySubType, PropertyType},
|
|
|
|
|
|
|
+ expr::{Op, SExprMachine, SExprVal},
|
|
|
|
|
+ gfx::Rectangle,
|
|
|
|
|
+ gfx2::{DrawCall, DrawInstruction, DrawMesh, GraphicsEvent, RenderApiPtr, Vertex},
|
|
|
|
|
+ prop::{
|
|
|
|
|
+ Property, PropertyBool, PropertyColor, PropertyFloat32, PropertyPtr, PropertyStr,
|
|
|
|
|
+ PropertySubType, PropertyType, PropertyUint32,
|
|
|
|
|
+ },
|
|
|
pubsub::PublisherPtr,
|
|
pubsub::PublisherPtr,
|
|
|
scene::{
|
|
scene::{
|
|
|
MethodResponseFn, Pimpl, SceneGraph, SceneGraphPtr2, SceneNode, SceneNodeId, SceneNodeInfo,
|
|
MethodResponseFn, Pimpl, SceneGraph, SceneGraphPtr2, SceneNode, SceneNodeId, SceneNodeInfo,
|
|
@@ -79,46 +85,87 @@ impl App {
|
|
|
|
|
|
|
|
sg.link(window_id, SceneGraph::ROOT_ID).unwrap();
|
|
sg.link(window_id, SceneGraph::ROOT_ID).unwrap();
|
|
|
|
|
|
|
|
|
|
+ // Testing
|
|
|
|
|
+ let node = sg.get_node(window_id).unwrap();
|
|
|
|
|
+ node.set_property_f32("scale", 2.).unwrap();
|
|
|
|
|
+
|
|
|
|
|
+ drop(sg);
|
|
|
|
|
+
|
|
|
self.make_me_a_schema_plox().await;
|
|
self.make_me_a_schema_plox().await;
|
|
|
|
|
|
|
|
// Access drawable in window node and call draw()
|
|
// Access drawable in window node and call draw()
|
|
|
self.trigger_redraw().await;
|
|
self.trigger_redraw().await;
|
|
|
-
|
|
|
|
|
- let node = sg.get_node(window_id).unwrap();
|
|
|
|
|
- node.set_property_f32("scale", 2.).unwrap();
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
async fn make_me_a_schema_plox(&self) {
|
|
async fn make_me_a_schema_plox(&self) {
|
|
|
|
|
+ // Create a layer called view
|
|
|
let mut sg = self.sg.lock().await;
|
|
let mut sg = self.sg.lock().await;
|
|
|
let layer_node_id = chatapp::create_layer(&mut sg, "view");
|
|
let layer_node_id = chatapp::create_layer(&mut sg, "view");
|
|
|
|
|
|
|
|
// Customize our layer
|
|
// Customize our layer
|
|
|
let node = sg.get_node(layer_node_id).unwrap();
|
|
let node = sg.get_node(layer_node_id).unwrap();
|
|
|
let prop = node.get_property("rect").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_f32(0, 0.).unwrap();
|
|
|
|
|
+ prop.set_f32(1, 0.).unwrap();
|
|
|
|
|
+ let code = vec![Op::LoadVar("sw".to_string())];
|
|
|
prop.set_expr(2, code).unwrap();
|
|
prop.set_expr(2, code).unwrap();
|
|
|
- let code = vec![Op::Float32ToUint32((Box::new(Op::LoadVar("sh".to_string()))))];
|
|
|
|
|
|
|
+ let code = vec![Op::LoadVar("sh".to_string())];
|
|
|
prop.set_expr(3, code).unwrap();
|
|
prop.set_expr(3, code).unwrap();
|
|
|
|
|
+ node.set_property_bool("is_visible", true).unwrap();
|
|
|
|
|
|
|
|
// Setup the pimpl
|
|
// Setup the pimpl
|
|
|
let node_id = node.id;
|
|
let node_id = node.id;
|
|
|
drop(sg);
|
|
drop(sg);
|
|
|
- let pimpl = RenderLayer::new().await;
|
|
|
|
|
|
|
+ let pimpl = RenderLayer::new(self.sg.clone(), node_id).await;
|
|
|
let mut sg = self.sg.lock().await;
|
|
let mut sg = self.sg.lock().await;
|
|
|
let node = sg.get_node_mut(node_id).unwrap();
|
|
let node = sg.get_node_mut(node_id).unwrap();
|
|
|
node.pimpl = pimpl;
|
|
node.pimpl = pimpl;
|
|
|
|
|
|
|
|
let window_id = sg.lookup_node("/window").unwrap().id;
|
|
let window_id = sg.lookup_node("/window").unwrap().id;
|
|
|
sg.link(node_id, window_id).unwrap();
|
|
sg.link(node_id, window_id).unwrap();
|
|
|
|
|
+
|
|
|
|
|
+ // Create a mesh
|
|
|
|
|
+ let node_id = chatapp::create_mesh(&mut sg, "bg");
|
|
|
|
|
+
|
|
|
|
|
+ let node = sg.get_node_mut(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();
|
|
|
|
|
+
|
|
|
|
|
+ // Setup the pimpl
|
|
|
|
|
+ let node_id = node.id;
|
|
|
|
|
+ let (x1, y1) = (0., 0.);
|
|
|
|
|
+ let (x2, y2) = (1., 1.);
|
|
|
|
|
+ let verts = vec![
|
|
|
|
|
+ // top left
|
|
|
|
|
+ Vertex { pos: [x1, y1], color: [1., 0., 0., 1.], uv: [0., 0.] },
|
|
|
|
|
+ // top right
|
|
|
|
|
+ Vertex { pos: [x2, y1], color: [1., 0., 1., 1.], uv: [1., 0.] },
|
|
|
|
|
+ // bottom left
|
|
|
|
|
+ Vertex { pos: [x1, y2], color: [0., 0., 1., 1.], uv: [0., 1.] },
|
|
|
|
|
+ // bottom right
|
|
|
|
|
+ Vertex { pos: [x2, y2], color: [1., 1., 0., 1.], uv: [1., 1.] },
|
|
|
|
|
+ ];
|
|
|
|
|
+ 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 mut sg = self.sg.lock().await;
|
|
|
|
|
+ let node = sg.get_node_mut(node_id).unwrap();
|
|
|
|
|
+ node.pimpl = pimpl;
|
|
|
|
|
+
|
|
|
|
|
+ sg.link(node_id, layer_node_id).unwrap();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
async fn trigger_redraw(&self) {
|
|
async fn trigger_redraw(&self) {
|
|
|
let sg = self.sg.lock().await;
|
|
let sg = self.sg.lock().await;
|
|
|
let window_node = sg.lookup_node("/window").expect("no window attached!");
|
|
let window_node = sg.lookup_node("/window").expect("no window attached!");
|
|
|
match &window_node.pimpl {
|
|
match &window_node.pimpl {
|
|
|
- Pimpl::Window(win) => win.draw().await,
|
|
|
|
|
|
|
+ Pimpl::Window(win) => win.draw(&sg).await,
|
|
|
_ => panic!("wrong pimpl"),
|
|
_ => panic!("wrong pimpl"),
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -137,11 +184,11 @@ fn print_type_of<T>(_: &T) {
|
|
|
pub type WindowPtr = Arc<Window>;
|
|
pub type WindowPtr = Arc<Window>;
|
|
|
|
|
|
|
|
pub struct Window {
|
|
pub struct Window {
|
|
|
- sg: SceneGraphPtr2,
|
|
|
|
|
node_id: SceneNodeId,
|
|
node_id: SceneNodeId,
|
|
|
- render_api: RenderApiPtr,
|
|
|
|
|
resize_task: smol::Task<()>,
|
|
resize_task: smol::Task<()>,
|
|
|
modify_task: smol::Task<()>,
|
|
modify_task: smol::Task<()>,
|
|
|
|
|
+ screen_size_prop: PropertyPtr,
|
|
|
|
|
+ render_api: RenderApiPtr,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl Window {
|
|
impl Window {
|
|
@@ -162,7 +209,7 @@ impl Window {
|
|
|
|
|
|
|
|
// Start a task monitoring for window resize events
|
|
// Start a task monitoring for window resize events
|
|
|
// which updates screen_size
|
|
// which updates screen_size
|
|
|
- let ev_sub = event_pub.clone().subscribe();
|
|
|
|
|
|
|
+ let ev_sub = event_pub.subscribe();
|
|
|
let screen_size_prop2 = screen_size_prop.clone();
|
|
let screen_size_prop2 = screen_size_prop.clone();
|
|
|
let resize_task = ex.spawn(async move {
|
|
let resize_task = ex.spawn(async move {
|
|
|
loop {
|
|
loop {
|
|
@@ -211,31 +258,52 @@ impl Window {
|
|
|
panic!("self destroyed before modify_task was stopped!");
|
|
panic!("self destroyed before modify_task was stopped!");
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- self_.draw().await;
|
|
|
|
|
|
|
+ let sg = sg.lock().await;
|
|
|
|
|
+ self_.draw(&sg).await;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- Self { sg, node_id, render_api, resize_task, modify_task }
|
|
|
|
|
|
|
+ Self { node_id, resize_task, modify_task, screen_size_prop, render_api }
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
Pimpl::Window(self_)
|
|
Pimpl::Window(self_)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- async fn draw(&self) {
|
|
|
|
|
- // This should remain locked for the entire draw
|
|
|
|
|
- let sg = self.sg.lock().await;
|
|
|
|
|
|
|
+ async fn draw(&self, sg: &SceneGraph) {
|
|
|
|
|
+ debug!("Window::draw()");
|
|
|
|
|
+ // SceneGraph should remain locked for the entire draw
|
|
|
let self_node = sg.get_node(self.node_id).unwrap();
|
|
let self_node = sg.get_node(self.node_id).unwrap();
|
|
|
|
|
|
|
|
|
|
+ let screen_width = self.screen_size_prop.get_f32(0).unwrap();
|
|
|
|
|
+ let screen_height = self.screen_size_prop.get_f32(1).unwrap();
|
|
|
|
|
+
|
|
|
|
|
+ let parent_rect = Rectangle { x: 0., y: 0., w: screen_width, h: screen_height };
|
|
|
|
|
+
|
|
|
|
|
+ let mut draw_calls = vec![];
|
|
|
|
|
+ let mut child_calls = vec![];
|
|
|
for child_inf in self_node.get_children2() {
|
|
for child_inf in self_node.get_children2() {
|
|
|
let node = sg.get_node(child_inf.id).unwrap();
|
|
let node = sg.get_node(child_inf.id).unwrap();
|
|
|
|
|
+ debug!("Window::draw() calling draw() for node '{}':{}", node.name, node.id);
|
|
|
|
|
|
|
|
- let sg_ref: &SceneGraph = &sg;
|
|
|
|
|
- match &node.pimpl {
|
|
|
|
|
- //Pimpl::RenderLayer(layer) => layer.draw(sg_ref).await,
|
|
|
|
|
- _ => error!("unhandled pimpl type"),
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ let dcs = match &node.pimpl {
|
|
|
|
|
+ Pimpl::RenderLayer(layer) => layer.draw(sg, &parent_rect).await,
|
|
|
|
|
+ _ => {
|
|
|
|
|
+ error!("unhandled pimpl type");
|
|
|
|
|
+ continue
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+ let Some((dc_key, mut dcs)) = dcs else { continue };
|
|
|
|
|
+ draw_calls.append(&mut dcs);
|
|
|
|
|
+ child_calls.push(dc_key);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ let root_dc = DrawCall { instrs: vec![], dcs: child_calls };
|
|
|
|
|
+ draw_calls.push((0, root_dc));
|
|
|
|
|
+ println!("{:?}", draw_calls);
|
|
|
|
|
+
|
|
|
|
|
+ self.render_api.replace_draw_calls(draw_calls).await;
|
|
|
|
|
+ debug!("Window::draw() - replaced draw call");
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -248,14 +316,224 @@ impl Stoppable for Window {
|
|
|
|
|
|
|
|
pub type RenderLayerPtr = Arc<RenderLayer>;
|
|
pub type RenderLayerPtr = Arc<RenderLayer>;
|
|
|
|
|
|
|
|
-pub struct RenderLayer {}
|
|
|
|
|
|
|
+pub struct RenderLayer {
|
|
|
|
|
+ sg: SceneGraphPtr2,
|
|
|
|
|
+ node_id: SceneNodeId,
|
|
|
|
|
+
|
|
|
|
|
+ dc_key: u64,
|
|
|
|
|
+
|
|
|
|
|
+ is_visible: PropertyBool,
|
|
|
|
|
+ rect: PropertyPtr,
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
impl RenderLayer {
|
|
impl RenderLayer {
|
|
|
- pub async fn new() -> Pimpl {
|
|
|
|
|
- let self_ = Arc::new(Self {});
|
|
|
|
|
|
|
+ pub async fn new(sg_ptr: SceneGraphPtr2, node_id: SceneNodeId) -> Pimpl {
|
|
|
|
|
+ let sg_ptr2 = sg_ptr.clone();
|
|
|
|
|
+ let sg = sg_ptr2.lock().await;
|
|
|
|
|
+ let node = sg.get_node(node_id).unwrap();
|
|
|
|
|
+
|
|
|
|
|
+ let is_visible =
|
|
|
|
|
+ PropertyBool::wrap(node, "is_visible", 0).expect("RenderLayer::is_visible");
|
|
|
|
|
+ let rect = node.get_property("rect").expect("RenderLayer::rect");
|
|
|
|
|
+
|
|
|
|
|
+ let self_ = Arc::new(Self { sg: sg_ptr, node_id, dc_key: OsRng.gen(), is_visible, rect });
|
|
|
|
|
|
|
|
Pimpl::RenderLayer(self_)
|
|
Pimpl::RenderLayer(self_)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- pub async fn draw(&self, sg: &SceneGraph) {}
|
|
|
|
|
|
|
+ fn get_rect(&self, parent_rect: &Rectangle<f32>) -> Result<Rectangle<f32>> {
|
|
|
|
|
+ if self.rect.array_len != 4 {
|
|
|
|
|
+ return Err(Error::PropertyWrongLen)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let mut rect = [0.; 4];
|
|
|
|
|
+ for i in 0..4 {
|
|
|
|
|
+ if self.rect.is_expr(i)? {
|
|
|
|
|
+ let expr = self.rect.get_expr(i).unwrap();
|
|
|
|
|
+
|
|
|
|
|
+ let machine = SExprMachine {
|
|
|
|
|
+ globals: vec![
|
|
|
|
|
+ ("sw".to_string(), SExprVal::Float32(parent_rect.w)),
|
|
|
|
|
+ ("sh".to_string(), SExprVal::Float32(parent_rect.h)),
|
|
|
|
|
+ ],
|
|
|
|
|
+ stmts: &expr,
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ rect[i] = machine.call()?.as_f32()?;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ rect[i] = self.rect.get_f32(i)?;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ Ok(Rectangle::from_array(rect))
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ #[async_recursion]
|
|
|
|
|
+ pub async fn draw(
|
|
|
|
|
+ &self,
|
|
|
|
|
+ sg: &SceneGraph,
|
|
|
|
|
+ parent_rect: &Rectangle<f32>,
|
|
|
|
|
+ ) -> Option<(u64, Vec<(u64, DrawCall)>)> {
|
|
|
|
|
+ debug!("RenderLayer::draw()");
|
|
|
|
|
+ let node = sg.get_node(self.node_id).unwrap();
|
|
|
|
|
+
|
|
|
|
|
+ if !self.is_visible.get() {
|
|
|
|
|
+ debug!("invisible layer node '{}':{}", node.name, node.id);
|
|
|
|
|
+ return None
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let Ok(rect) = self.get_rect(parent_rect) else {
|
|
|
|
|
+ panic!("malformed rect property for node '{}':{}", node.name, node.id)
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ if !parent_rect.includes(&rect) {
|
|
|
|
|
+ error!(
|
|
|
|
|
+ "layer '{}':{} rect {:?} is not inside parent {:?}",
|
|
|
|
|
+ node.name, node.id, rect, parent_rect
|
|
|
|
|
+ );
|
|
|
|
|
+ return None
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Apply viewport
|
|
|
|
|
+
|
|
|
|
|
+ let mut draw_calls = vec![];
|
|
|
|
|
+ let mut child_calls = vec![];
|
|
|
|
|
+ for child_inf in node.get_children2() {
|
|
|
|
|
+ let node = sg.get_node(child_inf.id).unwrap();
|
|
|
|
|
+
|
|
|
|
|
+ let dcs = match &node.pimpl {
|
|
|
|
|
+ Pimpl::RenderLayer(layer) => layer.draw(&sg, &rect).await,
|
|
|
|
|
+ Pimpl::Mesh(mesh) => mesh.draw(&sg, &rect),
|
|
|
|
|
+ _ => {
|
|
|
|
|
+ error!("unhandled pimpl type");
|
|
|
|
|
+ continue
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+ let Some((dc_key, mut dcs)) = dcs else { continue };
|
|
|
|
|
+ draw_calls.append(&mut dcs);
|
|
|
|
|
+ child_calls.push(dc_key);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let dc = DrawCall { instrs: vec![DrawInstruction::ApplyViewport(rect)], dcs: child_calls };
|
|
|
|
|
+ draw_calls.push((self.dc_key, dc));
|
|
|
|
|
+ Some((self.dc_key, draw_calls))
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+pub struct Mesh {
|
|
|
|
|
+ render_api: RenderApiPtr,
|
|
|
|
|
+ vertex_buffer: miniquad::BufferId,
|
|
|
|
|
+ index_buffer: miniquad::BufferId,
|
|
|
|
|
+ // Texture
|
|
|
|
|
+ num_elements: i32,
|
|
|
|
|
+
|
|
|
|
|
+ dc_key: u64,
|
|
|
|
|
+
|
|
|
|
|
+ node_id: SceneNodeId,
|
|
|
|
|
+ rect: PropertyPtr,
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+impl Mesh {
|
|
|
|
|
+ pub async fn new(
|
|
|
|
|
+ sg: SceneGraphPtr2,
|
|
|
|
|
+ node_id: SceneNodeId,
|
|
|
|
|
+ render_api: RenderApiPtr,
|
|
|
|
|
+ verts: Vec<Vertex>,
|
|
|
|
|
+ indices: Vec<u16>,
|
|
|
|
|
+ ) -> Pimpl {
|
|
|
|
|
+ let num_elements = indices.len() as i32;
|
|
|
|
|
+ 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 rect = node.get_property("rect").expect("RenderLayer::rect");
|
|
|
|
|
+
|
|
|
|
|
+ Pimpl::Mesh(Self {
|
|
|
|
|
+ render_api,
|
|
|
|
|
+ vertex_buffer,
|
|
|
|
|
+ index_buffer,
|
|
|
|
|
+ num_elements,
|
|
|
|
|
+ dc_key: OsRng.gen(),
|
|
|
|
|
+ node_id,
|
|
|
|
|
+ rect,
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Merge with RenderLayer::get_rect()
|
|
|
|
|
+ fn get_rect(&self, parent_rect: &Rectangle<f32>) -> Result<Rectangle<f32>> {
|
|
|
|
|
+ if self.rect.array_len != 4 {
|
|
|
|
|
+ return Err(Error::PropertyWrongLen)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ let mut rect = [0.; 4];
|
|
|
|
|
+ for i in 0..4 {
|
|
|
|
|
+ if self.rect.is_expr(i)? {
|
|
|
|
|
+ let expr = self.rect.get_expr(i).unwrap();
|
|
|
|
|
+
|
|
|
|
|
+ let machine = SExprMachine {
|
|
|
|
|
+ globals: vec![
|
|
|
|
|
+ ("lw".to_string(), SExprVal::Float32(parent_rect.w)),
|
|
|
|
|
+ ("lh".to_string(), SExprVal::Float32(parent_rect.h)),
|
|
|
|
|
+ ],
|
|
|
|
|
+ stmts: &expr,
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ rect[i] = machine.call()?.as_f32()?;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ rect[i] = self.rect.get_f32(i)?;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ Ok(Rectangle::from_array(rect))
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pub fn draw(
|
|
|
|
|
+ &self,
|
|
|
|
|
+ sg: &SceneGraph,
|
|
|
|
|
+ parent_rect: &Rectangle<f32>,
|
|
|
|
|
+ ) -> Option<(u64, Vec<(u64, DrawCall)>)> {
|
|
|
|
|
+ // Only used for debug messages
|
|
|
|
|
+ let node = sg.get_node(self.node_id).unwrap();
|
|
|
|
|
+
|
|
|
|
|
+ let mesh = DrawMesh {
|
|
|
|
|
+ vertex_buffer: self.vertex_buffer,
|
|
|
|
|
+ index_buffer: self.index_buffer,
|
|
|
|
|
+ texture: None,
|
|
|
|
|
+ num_elements: self.num_elements,
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ let Ok(rect) = self.get_rect(parent_rect) else {
|
|
|
|
|
+ panic!("malformed rect property for node '{}':{}", node.name, node.id)
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // FIXME: all these rects must be aggregated down the tree
|
|
|
|
|
+ let scale_x = rect.w / parent_rect.w;
|
|
|
|
|
+ let scale_y = rect.h / parent_rect.h;
|
|
|
|
|
+ let model = glam::Mat4::from_translation(glam::Vec3::new(rect.x, rect.y, 0.)) *
|
|
|
|
|
+ glam::Mat4::from_scale(glam::Vec3::new(scale_x, scale_y, 1.));
|
|
|
|
|
+
|
|
|
|
|
+ Some((
|
|
|
|
|
+ self.dc_key,
|
|
|
|
|
+ vec![(
|
|
|
|
|
+ self.dc_key,
|
|
|
|
|
+ DrawCall {
|
|
|
|
|
+ instrs: vec![
|
|
|
|
|
+ DrawInstruction::ApplyMatrix(glam::Mat4::IDENTITY),
|
|
|
|
|
+ DrawInstruction::Draw(mesh),
|
|
|
|
|
+ ],
|
|
|
|
|
+ dcs: vec![],
|
|
|
|
|
+ },
|
|
|
|
|
+ )],
|
|
|
|
|
+ ))
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+impl Stoppable for Mesh {
|
|
|
|
|
+ async fn stop(self) {
|
|
|
|
|
+ // TODO: Delete own draw call
|
|
|
|
|
+
|
|
|
|
|
+ // Free buffers
|
|
|
|
|
+ // Should this be in drop?
|
|
|
|
|
+ self.render_api.delete_buffer(self.vertex_buffer);
|
|
|
|
|
+ self.render_api.delete_buffer(self.index_buffer);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|