layer.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  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, OnceLock, Weak};
  24. use crate::{
  25. gfx::{GfxDrawCall, GfxDrawInstruction, Point, Rectangle, RenderApi},
  26. prop::{PropertyBool, PropertyFloat32, PropertyPtr, PropertyRect, PropertyUint32, Role},
  27. scene::{Pimpl, SceneNodePtr, SceneNodeWeak},
  28. util::unixtime,
  29. ExecutorPtr,
  30. };
  31. use super::{
  32. get_children_ordered, get_ui_object3, get_ui_object_ptr, DrawUpdate, OnModify, UIObject,
  33. };
  34. pub const DEBUG_LAYER: bool = false;
  35. pub type LayerPtr = Arc<Layer>;
  36. pub struct Layer {
  37. node: SceneNodeWeak,
  38. render_api: RenderApi,
  39. tasks: OnceLock<Vec<smol::Task<()>>>,
  40. dc_key: u64,
  41. is_visible: PropertyBool,
  42. rect: PropertyRect,
  43. z_index: PropertyUint32,
  44. priority: PropertyUint32,
  45. parent_rect: SyncMutex<Option<Rectangle>>,
  46. }
  47. impl Layer {
  48. pub async fn new(node: SceneNodeWeak, render_api: RenderApi, ex: ExecutorPtr) -> Pimpl {
  49. let node_ref = &node.upgrade().unwrap();
  50. debug!(target: "ui::layer", "Layer::new({node_ref:?})");
  51. let is_visible = PropertyBool::wrap(node_ref, Role::Internal, "is_visible", 0).unwrap();
  52. let rect = PropertyRect::wrap(node_ref, Role::Internal, "rect").unwrap();
  53. let z_index = PropertyUint32::wrap(node_ref, Role::Internal, "z_index", 0).unwrap();
  54. let priority = PropertyUint32::wrap(node_ref, Role::Internal, "priority", 0).unwrap();
  55. let node_name = node_ref.name.clone();
  56. let node_id = node_ref.id;
  57. let self_ = Arc::new(Self {
  58. node,
  59. render_api,
  60. tasks: OnceLock::new(),
  61. dc_key: OsRng.gen(),
  62. is_visible,
  63. rect,
  64. z_index,
  65. priority,
  66. parent_rect: SyncMutex::new(None),
  67. });
  68. Pimpl::Layer(self_)
  69. }
  70. fn get_children(&self) -> Vec<SceneNodePtr> {
  71. let node = self.node.upgrade().unwrap();
  72. get_children_ordered(&node)
  73. }
  74. async fn redraw(self: Arc<Self>) {
  75. let timest = unixtime();
  76. debug!(target: "ui::layer", "Layer::redraw({:?})", self.node.upgrade().unwrap());
  77. let Some(parent_rect) = self.parent_rect.lock().unwrap().clone() else { return };
  78. let Some(draw_update) = self.get_draw_calls(parent_rect).await else {
  79. error!(target: "ui::layer", "Layer failed to draw");
  80. return;
  81. };
  82. self.render_api.replace_draw_calls(timest, draw_update.draw_calls);
  83. debug!(target: "ui::layer", "Layer::redraw({:?}) DONE [timest={timest}]", self.node.upgrade().unwrap());
  84. }
  85. async fn get_draw_calls(&self, parent_rect: Rectangle) -> Option<DrawUpdate> {
  86. self.rect.eval(&parent_rect).ok()?;
  87. let rect = self.rect.get();
  88. debug!(target: "ui::layer", "Layer::get_draw_calls() [rect={rect:?}, dc={}]", self.dc_key);
  89. // Apply viewport
  90. let mut draw_calls = vec![];
  91. let mut child_calls = vec![];
  92. // We should return a draw call so that if the layer is made visible, we can just
  93. // recalculate it and update in place.
  94. if self.is_visible.get() {
  95. for child in self.get_children() {
  96. let obj = get_ui_object3(&child);
  97. let Some(mut draw_update) = obj.draw(rect).await else {
  98. debug!(target: "ui::layer", "Skipped draw for {child:?}");
  99. continue
  100. };
  101. draw_calls.append(&mut draw_update.draw_calls);
  102. child_calls.push(draw_update.key);
  103. }
  104. }
  105. let dc = GfxDrawCall {
  106. instrs: vec![GfxDrawInstruction::ApplyView(rect)],
  107. dcs: child_calls,
  108. z_index: self.z_index.get(),
  109. };
  110. draw_calls.push((self.dc_key, dc));
  111. Some(DrawUpdate { key: self.dc_key, draw_calls })
  112. }
  113. }
  114. #[async_trait]
  115. impl UIObject for Layer {
  116. fn priority(&self) -> u32 {
  117. self.priority.get()
  118. }
  119. async fn start(self: Arc<Self>, ex: ExecutorPtr) {
  120. let me = Arc::downgrade(&self);
  121. let node_ref = &self.node.upgrade().unwrap();
  122. let node_name = node_ref.name.clone();
  123. let node_id = node_ref.id;
  124. let mut on_modify = OnModify::new(ex.clone(), node_name, node_id, me.clone());
  125. on_modify.when_change(self.is_visible.prop(), Self::redraw);
  126. on_modify.when_change(self.rect.prop(), Self::redraw);
  127. on_modify.when_change(self.z_index.prop(), Self::redraw);
  128. self.tasks.set(on_modify.tasks);
  129. for child in self.get_children() {
  130. let obj = get_ui_object_ptr(&child);
  131. obj.start(ex.clone()).await;
  132. }
  133. }
  134. async fn draw(&self, parent_rect: Rectangle) -> Option<DrawUpdate> {
  135. debug!(target: "ui::layer", "Layer::draw({:?})", self.node.upgrade().unwrap());
  136. *self.parent_rect.lock().unwrap() = Some(parent_rect);
  137. /*
  138. if !parent_rect.dim().contains(&offset_rect) {
  139. error!(
  140. target: "ui::layer",
  141. "layer rect {:?} is not inside parent {:?}",
  142. offset_rect, parent_rect
  143. );
  144. return None
  145. }
  146. */
  147. let update = self.get_draw_calls(parent_rect).await;
  148. debug!(target: "ui::layer", "Layer::draw({:?}) DONE", self.node.upgrade().unwrap());
  149. update
  150. }
  151. async fn handle_char(&self, key: char, mods: KeyMods, repeat: bool) -> bool {
  152. if !self.is_visible.get() {
  153. return false
  154. }
  155. for child in self.get_children() {
  156. let obj = get_ui_object3(&child);
  157. if obj.handle_char(key, mods, repeat).await {
  158. if DEBUG_LAYER {
  159. debug!(target: "layer", "handle_char({key:?}, {mods:?}, {repeat}) swallowed by {child:?}");
  160. }
  161. return true
  162. }
  163. }
  164. false
  165. }
  166. async fn handle_key_down(&self, key: KeyCode, mods: KeyMods, repeat: bool) -> bool {
  167. if !self.is_visible.get() {
  168. return false
  169. }
  170. for child in self.get_children() {
  171. let obj = get_ui_object3(&child);
  172. if obj.handle_key_down(key, mods, repeat).await {
  173. if DEBUG_LAYER {
  174. debug!(target: "layer", "handle_key_down({key:?}, {mods:?}, {repeat}) swallowed by {child:?}");
  175. }
  176. return true
  177. }
  178. }
  179. false
  180. }
  181. async fn handle_key_up(&self, key: KeyCode, mods: KeyMods) -> bool {
  182. if !self.is_visible.get() {
  183. return false
  184. }
  185. for child in self.get_children() {
  186. let obj = get_ui_object3(&child);
  187. if obj.handle_key_up(key, mods).await {
  188. if DEBUG_LAYER {
  189. debug!(target: "layer", "handle_key_up({key:?}, {mods:?}) swallowed by {child:?}");
  190. }
  191. return true
  192. }
  193. }
  194. false
  195. }
  196. async fn handle_mouse_btn_down(&self, btn: MouseButton, mut mouse_pos: Point) -> bool {
  197. if !self.is_visible.get() {
  198. return false
  199. }
  200. mouse_pos -= self.rect.get().pos();
  201. for child in self.get_children() {
  202. let obj = get_ui_object3(&child);
  203. if obj.handle_mouse_btn_down(btn, mouse_pos).await {
  204. if DEBUG_LAYER {
  205. debug!(target: "layer", "handle_mouse_btn_down({btn:?}, {mouse_pos:?}) swallowed by {child:?}");
  206. }
  207. return true
  208. }
  209. }
  210. false
  211. }
  212. async fn handle_mouse_btn_up(&self, btn: MouseButton, mut mouse_pos: Point) -> bool {
  213. if !self.is_visible.get() {
  214. return false
  215. }
  216. mouse_pos -= self.rect.get().pos();
  217. for child in self.get_children() {
  218. let obj = get_ui_object3(&child);
  219. if obj.handle_mouse_btn_up(btn, mouse_pos).await {
  220. if DEBUG_LAYER {
  221. debug!(target: "layer", "handle_mouse_btn_up({btn:?}, {mouse_pos:?}) swallowed by {child:?}");
  222. }
  223. return true
  224. }
  225. }
  226. false
  227. }
  228. async fn handle_mouse_move(&self, mut mouse_pos: Point) -> bool {
  229. if !self.is_visible.get() {
  230. return false
  231. }
  232. mouse_pos -= self.rect.get().pos();
  233. for child in self.get_children() {
  234. let obj = get_ui_object3(&child);
  235. if obj.handle_mouse_move(mouse_pos).await {
  236. if DEBUG_LAYER {
  237. debug!(target: "layer", "handle_mouse_move({mouse_pos:?}) swallowed by {child:?}");
  238. }
  239. return true
  240. }
  241. }
  242. false
  243. }
  244. async fn handle_mouse_wheel(&self, mut wheel_pos: Point) -> bool {
  245. if !self.is_visible.get() {
  246. return false
  247. }
  248. wheel_pos -= self.rect.get().pos();
  249. for child in self.get_children() {
  250. let obj = get_ui_object3(&child);
  251. if obj.handle_mouse_wheel(wheel_pos).await {
  252. return true
  253. }
  254. }
  255. false
  256. }
  257. async fn handle_touch(&self, phase: TouchPhase, id: u64, mut touch_pos: Point) -> bool {
  258. if !self.is_visible.get() {
  259. return false
  260. }
  261. touch_pos -= self.rect.get().pos();
  262. for child in self.get_children() {
  263. let obj = get_ui_object3(&child);
  264. if obj.handle_touch(phase, id, touch_pos).await {
  265. return true
  266. }
  267. }
  268. false
  269. }
  270. async fn handle_compose_text(&self, suggest_text: &str, is_commit: bool) -> bool {
  271. if !self.is_visible.get() {
  272. return false
  273. }
  274. for child in self.get_children() {
  275. let obj = get_ui_object3(&child);
  276. if obj.handle_compose_text(suggest_text, is_commit).await {
  277. return true
  278. }
  279. }
  280. false
  281. }
  282. async fn handle_set_compose_region(&self, start: usize, end: usize) -> bool {
  283. if !self.is_visible.get() {
  284. return false
  285. }
  286. for child in self.get_children() {
  287. let obj = get_ui_object3(&child);
  288. if obj.handle_set_compose_region(start, end).await {
  289. return true
  290. }
  291. }
  292. false
  293. }
  294. }