layer.rs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2024 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use async_recursion::async_recursion;
  19. use async_trait::async_trait;
  20. use atomic_float::AtomicF32;
  21. use miniquad::{KeyCode, KeyMods, MouseButton, TouchPhase};
  22. use rand::{rngs::OsRng, Rng};
  23. use std::sync::{atomic::Ordering, Arc, Mutex as SyncMutex, Weak};
  24. use crate::{
  25. gfx::{GfxDrawCall, GfxDrawInstruction, Point, Rectangle, RenderApiPtr},
  26. prop::{PropertyBool, PropertyFloat32, PropertyPtr, PropertyRect, PropertyUint32, Role},
  27. scene::{Pimpl, SceneNodePtr, SceneNodeWeak},
  28. ExecutorPtr,
  29. };
  30. use super::{get_children_ordered, get_ui_object3, DrawUpdate, OnModify, UIObject};
  31. pub type LayerPtr = Arc<Layer>;
  32. pub struct Layer {
  33. node: SceneNodeWeak,
  34. render_api: RenderApiPtr,
  35. _tasks: Vec<smol::Task<()>>,
  36. dc_key: u64,
  37. is_visible: PropertyBool,
  38. rect: PropertyRect,
  39. z_index: PropertyUint32,
  40. parent_rect: SyncMutex<Option<Rectangle>>,
  41. }
  42. impl Layer {
  43. pub async fn new(node: SceneNodeWeak, render_api: RenderApiPtr, ex: ExecutorPtr) -> Pimpl {
  44. debug!(target: "ui::layer", "Layer::new()");
  45. let node_ref = &node.upgrade().unwrap();
  46. let is_visible = PropertyBool::wrap(node_ref, Role::Internal, "is_visible", 0).unwrap();
  47. let rect = PropertyRect::wrap(node_ref, Role::Internal, "rect").unwrap();
  48. let z_index = PropertyUint32::wrap(node_ref, Role::Internal, "z_index", 0).unwrap();
  49. let node_name = node_ref.name.clone();
  50. let node_id = node_ref.id;
  51. let self_ = Arc::new_cyclic(|me: &Weak<Self>| {
  52. let mut on_modify = OnModify::new(ex.clone(), node_name, node_id, me.clone());
  53. on_modify.when_change(is_visible.prop(), Self::redraw);
  54. on_modify.when_change(rect.prop(), Self::redraw);
  55. on_modify.when_change(z_index.prop(), Self::redraw);
  56. Self {
  57. node,
  58. render_api,
  59. _tasks: on_modify.tasks,
  60. dc_key: OsRng.gen(),
  61. is_visible,
  62. rect,
  63. z_index,
  64. parent_rect: SyncMutex::new(None),
  65. }
  66. });
  67. Pimpl::Layer(self_)
  68. }
  69. fn get_children(&self) -> Vec<SceneNodePtr> {
  70. let node = self.node.upgrade().unwrap();
  71. get_children_ordered(&node)
  72. }
  73. async fn redraw(self: Arc<Self>) {
  74. let Some(parent_rect) = self.parent_rect.lock().unwrap().clone() else { return };
  75. let Some(draw_update) = self.get_draw_calls(parent_rect).await else {
  76. error!(target: "ui::layer", "Layer failed to draw");
  77. return;
  78. };
  79. self.render_api.replace_draw_calls(draw_update.draw_calls);
  80. debug!(target: "ui::layer", "replace draw calls done");
  81. }
  82. async fn get_draw_calls(&self, parent_rect: Rectangle) -> Option<DrawUpdate> {
  83. debug!(target: "ui::layer", "Layer::get_draw_calls()");
  84. self.rect.eval(&parent_rect).ok()?;
  85. let rect = self.rect.get();
  86. // Apply viewport
  87. let mut draw_calls = vec![];
  88. let mut child_calls = vec![];
  89. let mut freed_textures = vec![];
  90. let mut freed_buffers = vec![];
  91. // We should return a draw call so that if the layer is made visible, we can just
  92. // recalculate it and update in place.
  93. if self.is_visible.get() {
  94. for child in self.get_children() {
  95. let obj = get_ui_object3(&child);
  96. let Some(mut draw_update) = obj.draw(rect).await else {
  97. debug!(target: "ui::layer", "Skipped draw() of {child:?}");
  98. continue
  99. };
  100. draw_calls.append(&mut draw_update.draw_calls);
  101. child_calls.push(draw_update.key);
  102. freed_textures.append(&mut draw_update.freed_textures);
  103. freed_buffers.append(&mut draw_update.freed_buffers);
  104. }
  105. }
  106. let dc = GfxDrawCall {
  107. instrs: vec![GfxDrawInstruction::ApplyView(rect)],
  108. dcs: child_calls,
  109. z_index: self.z_index(),
  110. };
  111. draw_calls.push((self.dc_key, dc));
  112. Some(DrawUpdate { key: self.dc_key, draw_calls, freed_textures, freed_buffers })
  113. }
  114. }
  115. #[async_trait]
  116. impl UIObject for Layer {
  117. fn z_index(&self) -> u32 {
  118. self.z_index.get()
  119. }
  120. async fn draw(&self, parent_rect: Rectangle) -> Option<DrawUpdate> {
  121. debug!(target: "ui::layer", "Layer::draw()");
  122. *self.parent_rect.lock().unwrap() = Some(parent_rect);
  123. /*
  124. if !parent_rect.dim().contains(&offset_rect) {
  125. error!(
  126. target: "ui::layer",
  127. "layer rect {:?} is not inside parent {:?}",
  128. offset_rect, parent_rect
  129. );
  130. return None
  131. }
  132. */
  133. self.get_draw_calls(parent_rect).await
  134. }
  135. async fn handle_char(&self, key: char, mods: KeyMods, repeat: bool) -> bool {
  136. if !self.is_visible.get() {
  137. return false
  138. }
  139. for child in self.get_children() {
  140. let obj = get_ui_object3(&child);
  141. if obj.handle_char(key, mods, repeat).await {
  142. return true
  143. }
  144. }
  145. false
  146. }
  147. async fn handle_key_down(&self, key: KeyCode, mods: KeyMods, repeat: bool) -> bool {
  148. if !self.is_visible.get() {
  149. return false
  150. }
  151. for child in self.get_children() {
  152. let obj = get_ui_object3(&child);
  153. if obj.handle_key_down(key, mods, repeat).await {
  154. //debug!(target: "layer", "handle_key_down({key:?}, {mods:?}, {repeat}) swallowed by {child:?}");
  155. return true
  156. }
  157. }
  158. false
  159. }
  160. async fn handle_key_up(&self, key: KeyCode, mods: KeyMods) -> bool {
  161. if !self.is_visible.get() {
  162. return false
  163. }
  164. for child in self.get_children() {
  165. let obj = get_ui_object3(&child);
  166. if obj.handle_key_up(key, mods).await {
  167. return true
  168. }
  169. }
  170. false
  171. }
  172. async fn handle_mouse_btn_down(&self, btn: MouseButton, mut mouse_pos: Point) -> bool {
  173. if !self.is_visible.get() {
  174. return false
  175. }
  176. mouse_pos -= self.rect.get().pos();
  177. for child in self.get_children() {
  178. let obj = get_ui_object3(&child);
  179. if obj.handle_mouse_btn_down(btn, mouse_pos).await {
  180. return true
  181. }
  182. }
  183. false
  184. }
  185. async fn handle_mouse_btn_up(&self, btn: MouseButton, mut mouse_pos: Point) -> bool {
  186. if !self.is_visible.get() {
  187. return false
  188. }
  189. mouse_pos -= self.rect.get().pos();
  190. for child in self.get_children() {
  191. let obj = get_ui_object3(&child);
  192. if obj.handle_mouse_btn_up(btn, mouse_pos).await {
  193. return true
  194. }
  195. }
  196. false
  197. }
  198. async fn handle_mouse_move(&self, mut mouse_pos: Point) -> bool {
  199. if !self.is_visible.get() {
  200. return false
  201. }
  202. mouse_pos -= self.rect.get().pos();
  203. for child in self.get_children() {
  204. let obj = get_ui_object3(&child);
  205. if obj.handle_mouse_move(mouse_pos).await {
  206. return true
  207. }
  208. }
  209. false
  210. }
  211. async fn handle_mouse_wheel(&self, mut wheel_pos: Point) -> bool {
  212. if !self.is_visible.get() {
  213. return false
  214. }
  215. wheel_pos -= self.rect.get().pos();
  216. for child in self.get_children() {
  217. let obj = get_ui_object3(&child);
  218. if obj.handle_mouse_wheel(wheel_pos).await {
  219. return true
  220. }
  221. }
  222. false
  223. }
  224. async fn handle_touch(&self, phase: TouchPhase, id: u64, mut touch_pos: Point) -> bool {
  225. if !self.is_visible.get() {
  226. return false
  227. }
  228. touch_pos -= self.rect.get().pos();
  229. for child in self.get_children() {
  230. let obj = get_ui_object3(&child);
  231. if obj.handle_touch(phase, id, touch_pos).await {
  232. return true
  233. }
  234. }
  235. false
  236. }
  237. }