win.rs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. use std::sync::{Arc, Weak};
  2. use crate::{
  3. gfx2::{DrawCall, GraphicsEventPublisherPtr, Rectangle, RenderApiPtr},
  4. prop::PropertyPtr,
  5. scene::{Pimpl, SceneGraph, SceneGraphPtr2, SceneNodeId},
  6. };
  7. use super::{OnModify, Stoppable};
  8. pub type WindowPtr = Arc<Window>;
  9. pub struct Window {
  10. node_id: SceneNodeId,
  11. // Task is dropped at the end of the scope for Window, hence ending it
  12. #[allow(dead_code)]
  13. tasks: Vec<smol::Task<()>>,
  14. screen_size_prop: PropertyPtr,
  15. render_api: RenderApiPtr,
  16. }
  17. impl Window {
  18. pub async fn new(
  19. ex: Arc<smol::Executor<'static>>,
  20. sg: SceneGraphPtr2,
  21. node_id: SceneNodeId,
  22. render_api: RenderApiPtr,
  23. event_pub: GraphicsEventPublisherPtr,
  24. ) -> Pimpl {
  25. debug!(target: "app", "Window::new()");
  26. let scene_graph = sg.lock().await;
  27. let node = scene_graph.get_node(node_id).unwrap();
  28. let node_name = node.name.clone();
  29. let screen_size_prop = node.get_property("screen_size").unwrap();
  30. let scale_prop = node.get_property("scale").unwrap();
  31. drop(scene_graph);
  32. let self_ = Arc::new_cyclic(|me: &Weak<Self>| {
  33. // Start a task monitoring for window resize events
  34. // which updates screen_size
  35. let ev_sub = event_pub.subscribe_resize();
  36. let screen_size_prop2 = screen_size_prop.clone();
  37. let me2 = me.clone();
  38. let sg2 = sg.clone();
  39. let resize_task = ex.spawn(async move {
  40. loop {
  41. let Ok((w, h)) = ev_sub.receive().await else {
  42. debug!(target: "app", "Event relayer closed");
  43. break
  44. };
  45. debug!(target: "app", "Window resized ({w}, {h})");
  46. // Now update the properties
  47. screen_size_prop2.set_f32(0, w).unwrap();
  48. screen_size_prop2.set_f32(1, h).unwrap();
  49. let Some(self_) = me2.upgrade() else {
  50. // Should not happen
  51. panic!("self destroyed before modify_task was stopped!");
  52. };
  53. let sg = sg2.lock().await;
  54. self_.draw(&sg).await;
  55. }
  56. });
  57. let sg2 = sg.clone();
  58. let redraw_fn = move |self_: Arc<Self>| {
  59. let sg = sg2.clone();
  60. async move {
  61. let sg = sg.lock().await;
  62. self_.draw(&sg).await;
  63. }
  64. };
  65. let mut on_modify = OnModify::new(ex.clone(), node_name, node_id, me.clone());
  66. on_modify.when_change(scale_prop, redraw_fn);
  67. let mut tasks = on_modify.tasks;
  68. tasks.push(resize_task);
  69. Self { node_id, tasks, screen_size_prop, render_api }
  70. });
  71. Pimpl::Window(self_)
  72. }
  73. pub async fn draw(&self, sg: &SceneGraph) {
  74. debug!(target: "app", "Window::draw()");
  75. // SceneGraph should remain locked for the entire draw
  76. let self_node = sg.get_node(self.node_id).unwrap();
  77. let screen_width = self.screen_size_prop.get_f32(0).unwrap();
  78. let screen_height = self.screen_size_prop.get_f32(1).unwrap();
  79. let parent_rect = Rectangle::from_array([0., 0., screen_width, screen_height]);
  80. let mut draw_calls = vec![];
  81. let mut child_calls = vec![];
  82. for child_inf in self_node.get_children2() {
  83. let node = sg.get_node(child_inf.id).unwrap();
  84. debug!(target: "app", "Window::draw() calling draw() for node '{}':{}", node.name, node.id);
  85. let dcs = match &node.pimpl {
  86. Pimpl::RenderLayer(layer) => layer.draw(sg, &parent_rect),
  87. _ => {
  88. error!(target: "app", "unhandled pimpl type");
  89. continue
  90. }
  91. };
  92. let Some(mut draw_update) = dcs else { continue };
  93. draw_calls.append(&mut draw_update.draw_calls);
  94. child_calls.push(draw_update.key);
  95. }
  96. let root_dc = DrawCall { instrs: vec![], dcs: child_calls };
  97. draw_calls.push((0, root_dc));
  98. //debug!(" => {:?}", draw_calls);
  99. self.render_api.replace_draw_calls(draw_calls).await;
  100. debug!("Window::draw() - replaced draw call");
  101. }
  102. }
  103. // Nodes should be stopped before being removed
  104. impl Stoppable for Window {
  105. async fn stop(&self) {}
  106. }