app.rs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  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 darkfi_serial::Encodable;
  20. use futures::{stream::FuturesUnordered, StreamExt};
  21. use std::{sync::Arc, thread};
  22. use crate::{
  23. expr::Op,
  24. gfx2::{GraphicsEventPublisherPtr, RenderApiPtr, Vertex},
  25. prop::{Property, PropertySubType, PropertyType},
  26. scene::{Pimpl, SceneGraph, SceneGraphPtr2, SceneNodeId, SceneNodeType},
  27. text2::TextShaperPtr,
  28. ui::{chatview, ChatView, EditBox, Image, Mesh, RenderLayer, Stoppable, Text, Window},
  29. };
  30. //fn print_type_of<T>(_: &T) {
  31. // println!("{}", std::any::type_name::<T>())
  32. //}
  33. pub struct AsyncRuntime {
  34. signal: smol::channel::Sender<()>,
  35. shutdown: smol::channel::Receiver<()>,
  36. exec_threadpool: std::sync::Mutex<Option<thread::JoinHandle<()>>>,
  37. ex: Arc<smol::Executor<'static>>,
  38. tasks: std::sync::Mutex<Vec<smol::Task<()>>>,
  39. }
  40. impl AsyncRuntime {
  41. pub fn new(ex: Arc<smol::Executor<'static>>) -> Self {
  42. let (signal, shutdown) = smol::channel::unbounded::<()>();
  43. Self {
  44. signal,
  45. shutdown,
  46. exec_threadpool: std::sync::Mutex::new(None),
  47. ex,
  48. tasks: std::sync::Mutex::new(vec![]),
  49. }
  50. }
  51. pub fn start(&self) {
  52. let n_threads = std::thread::available_parallelism().unwrap().get();
  53. let shutdown = self.shutdown.clone();
  54. let ex = self.ex.clone();
  55. let exec_threadpool = thread::spawn(move || {
  56. easy_parallel::Parallel::new()
  57. // N executor threads
  58. .each(0..n_threads, |_| smol::future::block_on(ex.run(shutdown.recv())))
  59. .run();
  60. });
  61. *self.exec_threadpool.lock().unwrap() = Some(exec_threadpool);
  62. debug!(target: "async_runtime", "Started runtime");
  63. }
  64. pub fn push_task(&self, task: smol::Task<()>) {
  65. self.tasks.lock().unwrap().push(task);
  66. }
  67. pub fn stop(&self) {
  68. // Go through event graph and call stop on everything
  69. // Depth first
  70. debug!(target: "app", "Stopping app...");
  71. let tasks = std::mem::take(&mut *self.tasks.lock().unwrap());
  72. // Close all tasks
  73. smol::future::block_on(async {
  74. // Perform cleanup code
  75. // If not finished in certain amount of time, then just exit
  76. let futures = FuturesUnordered::new();
  77. for task in tasks {
  78. futures.push(task.cancel());
  79. }
  80. let _: Vec<_> = futures.collect().await;
  81. });
  82. if !self.signal.close() {
  83. error!(target: "app", "exec threadpool was already shutdown");
  84. }
  85. let exec_threadpool = std::mem::replace(&mut *self.exec_threadpool.lock().unwrap(), None);
  86. let exec_threadpool = exec_threadpool.expect("threadpool wasnt started");
  87. exec_threadpool.join().unwrap();
  88. debug!(target: "app", "Stopped app");
  89. }
  90. }
  91. pub struct App {
  92. sg: SceneGraphPtr2,
  93. ex: Arc<smol::Executor<'static>>,
  94. render_api: RenderApiPtr,
  95. event_pub: GraphicsEventPublisherPtr,
  96. text_shaper: TextShaperPtr,
  97. }
  98. impl App {
  99. pub fn new(
  100. sg: SceneGraphPtr2,
  101. ex: Arc<smol::Executor<'static>>,
  102. render_api: RenderApiPtr,
  103. event_pub: GraphicsEventPublisherPtr,
  104. text_shaper: TextShaperPtr,
  105. ) -> Arc<Self> {
  106. Arc::new(Self { sg, ex, render_api, event_pub, text_shaper })
  107. }
  108. pub async fn start(self: Arc<Self>) {
  109. debug!(target: "app", "App::start()");
  110. // Setup UI
  111. let mut sg = self.sg.lock().await;
  112. let window = sg.add_node("window", SceneNodeType::Window);
  113. let mut prop = Property::new("screen_size", PropertyType::Float32, PropertySubType::Pixel);
  114. prop.set_array_len(2);
  115. // Window not yet initialized so we can't set these.
  116. //prop.set_f32(0, screen_width);
  117. //prop.set_f32(1, screen_height);
  118. window.add_property(prop).unwrap();
  119. let mut prop = Property::new("scale", PropertyType::Float32, PropertySubType::Pixel);
  120. prop.set_defaults_f32(vec![1.]).unwrap();
  121. window.add_property(prop).unwrap();
  122. let window_id = window.id;
  123. // Create Window
  124. // Window::new(window, weak sg)
  125. drop(sg);
  126. let pimpl = Window::new(
  127. self.ex.clone(),
  128. self.sg.clone(),
  129. window_id,
  130. self.render_api.clone(),
  131. self.event_pub.clone(),
  132. )
  133. .await;
  134. // -> reads any props it needs
  135. // -> starts procs
  136. let mut sg = self.sg.lock().await;
  137. let node = sg.get_node_mut(window_id).unwrap();
  138. node.pimpl = pimpl;
  139. sg.link(window_id, SceneGraph::ROOT_ID).unwrap();
  140. // Testing
  141. let node = sg.get_node(window_id).unwrap();
  142. node.set_property_f32("scale", 2.).unwrap();
  143. drop(sg);
  144. self.make_me_a_schema_plox().await;
  145. // Access drawable in window node and call draw()
  146. self.trigger_redraw().await;
  147. }
  148. pub async fn stop(&self) {
  149. let sg = self.sg.lock().await;
  150. let window_id = sg.lookup_node("/window").unwrap().id;
  151. self.stop_node(&sg, window_id).await;
  152. }
  153. #[async_recursion]
  154. async fn stop_node(&self, sg: &SceneGraph, node_id: SceneNodeId) {
  155. let node = sg.get_node(node_id).unwrap();
  156. for child_inf in node.get_children2() {
  157. self.stop_node(sg, child_inf.id).await;
  158. }
  159. match &node.pimpl {
  160. Pimpl::Window(win) => win.stop().await,
  161. Pimpl::RenderLayer(layer) => layer.stop().await,
  162. Pimpl::Mesh(mesh) => mesh.stop().await,
  163. _ => panic!("unhandled pimpl type"),
  164. };
  165. }
  166. async fn make_me_a_schema_plox(&self) {
  167. // Create a layer called view
  168. let mut sg = self.sg.lock().await;
  169. let layer_node_id = create_layer(&mut sg, "view");
  170. // Customize our layer
  171. let node = sg.get_node(layer_node_id).unwrap();
  172. let prop = node.get_property("rect").unwrap();
  173. prop.set_f32(0, 0.).unwrap();
  174. prop.set_f32(1, 0.).unwrap();
  175. let code = vec![Op::LoadVar("w".to_string())];
  176. prop.set_expr(2, code).unwrap();
  177. let code = vec![Op::LoadVar("h".to_string())];
  178. prop.set_expr(3, code).unwrap();
  179. node.set_property_bool("is_visible", true).unwrap();
  180. // Setup the pimpl
  181. let node_id = node.id;
  182. drop(sg);
  183. let pimpl =
  184. RenderLayer::new(self.ex.clone(), self.sg.clone(), node_id, self.render_api.clone())
  185. .await;
  186. let mut sg = self.sg.lock().await;
  187. let node = sg.get_node_mut(node_id).unwrap();
  188. node.pimpl = pimpl;
  189. let window_id = sg.lookup_node("/window").unwrap().id;
  190. sg.link(node_id, window_id).unwrap();
  191. // Create a bg mesh
  192. let node_id = create_mesh(&mut sg, "bg");
  193. let node = sg.get_node_mut(node_id).unwrap();
  194. let prop = node.get_property("rect").unwrap();
  195. prop.set_f32(0, 0.).unwrap();
  196. prop.set_f32(1, 0.).unwrap();
  197. let code = vec![Op::LoadVar("w".to_string())];
  198. prop.set_expr(2, code).unwrap();
  199. let code = vec![Op::LoadVar("h".to_string())];
  200. prop.set_expr(3, code).unwrap();
  201. // Setup the pimpl
  202. let node_id = node.id;
  203. let (x1, y1) = (0., 0.);
  204. let (x2, y2) = (1., 1.);
  205. let verts = vec![
  206. // top left
  207. Vertex { pos: [x1, y1], color: [0.3, 0., 0., 1.], uv: [0., 0.] },
  208. // top right
  209. Vertex { pos: [x2, y1], color: [0., 0., 0., 1.], uv: [1., 0.] },
  210. // bottom left
  211. Vertex { pos: [x1, y2], color: [0., 0., 0., 1.], uv: [0., 1.] },
  212. // bottom right
  213. Vertex { pos: [x2, y2], color: [0., 0., 0., 1.], uv: [1., 1.] },
  214. ];
  215. let indices = vec![0, 2, 1, 1, 2, 3];
  216. drop(sg);
  217. let pimpl = Mesh::new(
  218. self.ex.clone(),
  219. self.sg.clone(),
  220. node_id,
  221. self.render_api.clone(),
  222. verts,
  223. indices,
  224. )
  225. .await;
  226. let mut sg = self.sg.lock().await;
  227. let node = sg.get_node_mut(node_id).unwrap();
  228. node.pimpl = pimpl;
  229. sg.link(node_id, layer_node_id).unwrap();
  230. // Create another mesh
  231. let node_id = create_mesh(&mut sg, "box");
  232. let node = sg.get_node_mut(node_id).unwrap();
  233. let prop = node.get_property("rect").unwrap();
  234. prop.set_f32(0, 10.).unwrap();
  235. prop.set_f32(1, 10.).unwrap();
  236. prop.set_f32(2, 60.).unwrap();
  237. prop.set_f32(3, 60.).unwrap();
  238. // Setup the pimpl
  239. let (x1, y1) = (0., 0.);
  240. let (x2, y2) = (1., 1.);
  241. let verts = vec![
  242. // top left
  243. Vertex { pos: [x1, y1], color: [1., 0., 0., 1.], uv: [0., 0.] },
  244. // top right
  245. Vertex { pos: [x2, y1], color: [1., 0., 1., 1.], uv: [1., 0.] },
  246. // bottom left
  247. Vertex { pos: [x1, y2], color: [0., 0., 1., 1.], uv: [0., 1.] },
  248. // bottom right
  249. Vertex { pos: [x2, y2], color: [1., 1., 0., 1.], uv: [1., 1.] },
  250. ];
  251. let indices = vec![0, 2, 1, 1, 2, 3];
  252. drop(sg);
  253. let pimpl = Mesh::new(
  254. self.ex.clone(),
  255. self.sg.clone(),
  256. node_id,
  257. self.render_api.clone(),
  258. verts,
  259. indices,
  260. )
  261. .await;
  262. let mut sg = self.sg.lock().await;
  263. let node = sg.get_node_mut(node_id).unwrap();
  264. node.pimpl = pimpl;
  265. sg.link(node_id, layer_node_id).unwrap();
  266. // Debugging tool
  267. let node_id = create_mesh(&mut sg, "debugtool");
  268. let node = sg.get_node_mut(node_id).unwrap();
  269. let prop = node.get_property("rect").unwrap();
  270. prop.set_f32(0, 0.).unwrap();
  271. let code =
  272. vec![Op::Div((Box::new(Op::LoadVar("h".to_string())), Box::new(Op::ConstFloat32(2.))))];
  273. prop.set_expr(1, code).unwrap();
  274. let code = vec![Op::LoadVar("w".to_string())];
  275. prop.set_expr(2, code).unwrap();
  276. prop.set_f32(3, 5.).unwrap();
  277. node.set_property_u32("z_index", 2).unwrap();
  278. // Setup the pimpl
  279. let (x1, y1) = (0., 0.);
  280. let (x2, y2) = (1., 1.);
  281. let verts = vec![
  282. // top left
  283. Vertex { pos: [x1, y1], color: [0., 1., 0., 1.], uv: [0., 0.] },
  284. // top right
  285. Vertex { pos: [x2, y1], color: [0., 1., 0., 1.], uv: [1., 0.] },
  286. // bottom left
  287. Vertex { pos: [x1, y2], color: [0., 1., 0., 1.], uv: [0., 1.] },
  288. // bottom right
  289. Vertex { pos: [x2, y2], color: [0., 1., 0., 1.], uv: [1., 1.] },
  290. ];
  291. let indices = vec![0, 2, 1, 1, 2, 3];
  292. drop(sg);
  293. let pimpl = Mesh::new(
  294. self.ex.clone(),
  295. self.sg.clone(),
  296. node_id,
  297. self.render_api.clone(),
  298. verts,
  299. indices,
  300. )
  301. .await;
  302. let mut sg = self.sg.lock().await;
  303. let node = sg.get_node_mut(node_id).unwrap();
  304. node.pimpl = pimpl;
  305. sg.link(node_id, layer_node_id).unwrap();
  306. // Create KING GNU!
  307. let node_id = create_image(&mut sg, "king");
  308. let node = sg.get_node_mut(node_id).unwrap();
  309. let prop = node.get_property("rect").unwrap();
  310. prop.set_f32(0, 80.).unwrap();
  311. prop.set_f32(1, 10.).unwrap();
  312. prop.set_f32(2, 60.).unwrap();
  313. prop.set_f32(3, 60.).unwrap();
  314. node.set_property_str("path", "../../king.png").unwrap();
  315. // Setup the pimpl
  316. drop(sg);
  317. let pimpl =
  318. Image::new(self.ex.clone(), self.sg.clone(), node_id, self.render_api.clone()).await;
  319. let mut sg = self.sg.lock().await;
  320. let node = sg.get_node_mut(node_id).unwrap();
  321. node.pimpl = pimpl;
  322. sg.link(node_id, layer_node_id).unwrap();
  323. // Create some text
  324. let node_id = create_text(&mut sg, "label");
  325. let node = sg.get_node_mut(node_id).unwrap();
  326. let prop = node.get_property("rect").unwrap();
  327. prop.set_f32(0, 100.).unwrap();
  328. prop.set_f32(1, 100.).unwrap();
  329. prop.set_f32(2, 800.).unwrap();
  330. prop.set_f32(3, 200.).unwrap();
  331. node.set_property_f32("baseline", 40.).unwrap();
  332. node.set_property_f32("font_size", 60.).unwrap();
  333. node.set_property_str("text", "anon1🍆").unwrap();
  334. //node.set_property_str("text", "anon1").unwrap();
  335. let prop = node.get_property("text_color").unwrap();
  336. prop.set_f32(0, 0.).unwrap();
  337. prop.set_f32(1, 1.).unwrap();
  338. prop.set_f32(2, 0.).unwrap();
  339. prop.set_f32(3, 1.).unwrap();
  340. drop(sg);
  341. let pimpl = Text::new(
  342. self.ex.clone(),
  343. self.sg.clone(),
  344. node_id,
  345. self.render_api.clone(),
  346. self.text_shaper.clone(),
  347. )
  348. .await;
  349. let mut sg = self.sg.lock().await;
  350. let node = sg.get_node_mut(node_id).unwrap();
  351. node.pimpl = pimpl;
  352. sg.link(node_id, layer_node_id).unwrap();
  353. // Text edit
  354. let node_id = create_editbox(&mut sg, "editz");
  355. let node = sg.get_node(node_id).unwrap();
  356. node.set_property_bool("is_active", true).unwrap();
  357. let prop = node.get_property("rect").unwrap();
  358. prop.set_f32(0, 150.).unwrap();
  359. prop.set_f32(1, 150.).unwrap();
  360. prop.set_f32(2, 380.).unwrap();
  361. //let code = vec![Op::Sub((
  362. // Box::new(Op::LoadVar("h".to_string())),
  363. // Box::new(Op::ConstFloat32(60.)),
  364. //))];
  365. //prop.set_expr(1, code).unwrap();
  366. //let code = vec![Op::Sub((
  367. // Box::new(Op::LoadVar("w".to_string())),
  368. // Box::new(Op::ConstFloat32(120.)),
  369. //))];
  370. //prop.set_expr(2, code).unwrap();
  371. prop.set_f32(3, 60.).unwrap();
  372. node.set_property_f32("baseline", 40.).unwrap();
  373. node.set_property_f32("font_size", 20.).unwrap();
  374. node.set_property_f32("font_size", 40.).unwrap();
  375. node.set_property_str("text", "hello king!😁🍆jelly 🍆1234").unwrap();
  376. let prop = node.get_property("text_color").unwrap();
  377. prop.set_f32(0, 1.).unwrap();
  378. prop.set_f32(1, 1.).unwrap();
  379. prop.set_f32(2, 1.).unwrap();
  380. prop.set_f32(3, 1.).unwrap();
  381. let prop = node.get_property("cursor_color").unwrap();
  382. prop.set_f32(0, 1.).unwrap();
  383. prop.set_f32(1, 0.5).unwrap();
  384. prop.set_f32(2, 0.5).unwrap();
  385. prop.set_f32(3, 1.).unwrap();
  386. let prop = node.get_property("hi_bg_color").unwrap();
  387. prop.set_f32(0, 1.).unwrap();
  388. prop.set_f32(1, 1.).unwrap();
  389. prop.set_f32(2, 1.).unwrap();
  390. prop.set_f32(3, 0.5).unwrap();
  391. let prop = node.get_property("selected").unwrap();
  392. prop.set_null(0).unwrap();
  393. prop.set_null(1).unwrap();
  394. node.set_property_u32("z_index", 1).unwrap();
  395. //node.set_property_bool("debug", true).unwrap();
  396. drop(sg);
  397. let pimpl = EditBox::new(
  398. self.ex.clone(),
  399. self.sg.clone(),
  400. node_id,
  401. self.render_api.clone(),
  402. self.event_pub.clone(),
  403. self.text_shaper.clone(),
  404. )
  405. .await;
  406. let mut sg = self.sg.lock().await;
  407. let node = sg.get_node_mut(node_id).unwrap();
  408. node.pimpl = pimpl;
  409. sg.link(node_id, layer_node_id).unwrap();
  410. // ChatView
  411. let node_id = create_chatview(&mut sg, "chatty");
  412. let node = sg.get_node(node_id).unwrap();
  413. let prop = node.get_property("rect").unwrap();
  414. prop.set_f32(0, 0.).unwrap();
  415. let code =
  416. vec![Op::Div((Box::new(Op::LoadVar("h".to_string())), Box::new(Op::ConstFloat32(2.))))];
  417. prop.set_expr(1, code).unwrap();
  418. let code = vec![Op::LoadVar("w".to_string())];
  419. prop.set_expr(2, code).unwrap();
  420. let code = vec![Op::Sub((
  421. Box::new(Op::Div((
  422. Box::new(Op::LoadVar("h".to_string())),
  423. Box::new(Op::ConstFloat32(2.)),
  424. ))),
  425. Box::new(Op::ConstFloat32(200.)),
  426. ))];
  427. prop.set_expr(3, code).unwrap();
  428. node.set_property_f32("font_size", 20.).unwrap();
  429. node.set_property_f32("line_height", 30.).unwrap();
  430. node.set_property_f32("baseline", 10.).unwrap();
  431. node.set_property_u32("z_index", 1).unwrap();
  432. drop(sg);
  433. let db = sled::open("chatdb").expect("cannot open sleddb");
  434. let chat_tree = db.open_tree(b"chat").unwrap();
  435. //populate_tree(&chat_tree);
  436. let pimpl = ChatView::new(
  437. self.sg.clone(),
  438. node_id,
  439. self.render_api.clone(),
  440. self.text_shaper.clone(),
  441. chat_tree,
  442. )
  443. .await;
  444. let mut sg = self.sg.lock().await;
  445. let node = sg.get_node_mut(node_id).unwrap();
  446. node.pimpl = pimpl;
  447. sg.link(node_id, layer_node_id).unwrap();
  448. // On android lets scale the UI up
  449. // TODO: add support for fractional scaling
  450. // This also affects mouse/touch input since coords need to be accurately translated
  451. // Also we need to think about nesting of layers.
  452. //let window_node = sg.get_node_mut(window_id).unwrap();
  453. //win_node.set_property_f32("scale", 1.6).unwrap();
  454. }
  455. async fn trigger_redraw(&self) {
  456. let sg = self.sg.lock().await;
  457. let window_node = sg.lookup_node("/window").expect("no window attached!");
  458. match &window_node.pimpl {
  459. Pimpl::Window(win) => win.draw(&sg).await,
  460. _ => panic!("wrong pimpl"),
  461. }
  462. }
  463. }
  464. // Just for testing
  465. fn populate_tree(tree: &sled::Tree) {
  466. let chat_txt = include_str!("../chat.txt");
  467. for line in chat_txt.lines() {
  468. let parts: Vec<&str> = line.splitn(3, ' ').collect();
  469. assert_eq!(parts.len(), 3);
  470. let timest = parts[0].replace(':', "").parse::<u32>().unwrap();
  471. let nick = parts[1].to_string();
  472. let text = parts[2].to_string();
  473. // serial order is important here
  474. let key = timest.to_be_bytes();
  475. //timest.encode(&mut key).unwrap();
  476. let msg = chatview::ChatMsg { nick, text };
  477. let mut val = vec![];
  478. msg.encode(&mut val).unwrap();
  479. tree.insert(&key, val).unwrap();
  480. }
  481. }
  482. pub fn create_layer(sg: &mut SceneGraph, name: &str) -> SceneNodeId {
  483. let node = sg.add_node(name, SceneNodeType::RenderLayer);
  484. let prop = Property::new("is_visible", PropertyType::Bool, PropertySubType::Null);
  485. node.add_property(prop).unwrap();
  486. let mut prop = Property::new("rect", PropertyType::Float32, PropertySubType::Pixel);
  487. prop.set_array_len(4);
  488. prop.allow_exprs();
  489. node.add_property(prop).unwrap();
  490. node.id
  491. }
  492. pub fn create_mesh(sg: &mut SceneGraph, name: &str) -> SceneNodeId {
  493. let node = sg.add_node(name, SceneNodeType::RenderMesh);
  494. let mut prop = Property::new("rect", PropertyType::Float32, PropertySubType::Pixel);
  495. prop.set_array_len(4);
  496. prop.allow_exprs();
  497. node.add_property(prop).unwrap();
  498. let prop = Property::new("z_index", PropertyType::Uint32, PropertySubType::Null);
  499. node.add_property(prop).unwrap();
  500. node.id
  501. }
  502. pub fn create_image(sg: &mut SceneGraph, name: &str) -> SceneNodeId {
  503. let node = sg.add_node(name, SceneNodeType::RenderMesh);
  504. let mut prop = Property::new("rect", PropertyType::Float32, PropertySubType::Pixel);
  505. prop.set_array_len(4);
  506. prop.allow_exprs();
  507. node.add_property(prop).unwrap();
  508. let prop = Property::new("z_index", PropertyType::Uint32, PropertySubType::Null);
  509. node.add_property(prop).unwrap();
  510. let prop = Property::new("path", PropertyType::Str, PropertySubType::Null);
  511. node.add_property(prop).unwrap();
  512. node.id
  513. }
  514. fn create_text(sg: &mut SceneGraph, name: &str) -> SceneNodeId {
  515. let node = sg.add_node(name, SceneNodeType::RenderText);
  516. let mut prop = Property::new("rect", PropertyType::Float32, PropertySubType::Pixel);
  517. prop.set_array_len(4);
  518. prop.allow_exprs();
  519. node.add_property(prop).unwrap();
  520. let prop = Property::new("baseline", PropertyType::Float32, PropertySubType::Pixel);
  521. node.add_property(prop).unwrap();
  522. let prop = Property::new("font_size", PropertyType::Float32, PropertySubType::Pixel);
  523. node.add_property(prop).unwrap();
  524. let prop = Property::new("text", PropertyType::Str, PropertySubType::Null);
  525. node.add_property(prop).unwrap();
  526. let mut prop = Property::new("text_color", PropertyType::Float32, PropertySubType::Color);
  527. prop.set_array_len(4);
  528. prop.set_range_f32(0., 1.);
  529. node.add_property(prop).unwrap();
  530. let prop = Property::new("z_index", PropertyType::Uint32, PropertySubType::Null);
  531. node.add_property(prop).unwrap();
  532. let prop = Property::new("debug", PropertyType::Bool, PropertySubType::Null);
  533. node.add_property(prop).unwrap();
  534. node.id
  535. }
  536. fn create_editbox(sg: &mut SceneGraph, name: &str) -> SceneNodeId {
  537. let node = sg.add_node(name, SceneNodeType::EditBox);
  538. let mut prop = Property::new("is_active", PropertyType::Bool, PropertySubType::Null);
  539. prop.set_ui_text("Is Active", "An active EditBox can be focused");
  540. node.add_property(prop).unwrap();
  541. let mut prop = Property::new("is_focused", PropertyType::Bool, PropertySubType::Null);
  542. prop.set_ui_text("Is Focused", "A focused EditBox receives input");
  543. node.add_property(prop).unwrap();
  544. let mut prop = Property::new("rect", PropertyType::Float32, PropertySubType::Pixel);
  545. prop.set_array_len(4);
  546. prop.allow_exprs();
  547. node.add_property(prop).unwrap();
  548. let mut prop = Property::new("baseline", PropertyType::Float32, PropertySubType::Pixel);
  549. node.add_property(prop).unwrap();
  550. let mut prop = Property::new("scroll", PropertyType::Float32, PropertySubType::Pixel);
  551. node.add_property(prop).unwrap();
  552. let mut prop = Property::new("cursor_pos", PropertyType::Uint32, PropertySubType::Pixel);
  553. node.add_property(prop).unwrap();
  554. let mut prop = Property::new("font_size", PropertyType::Float32, PropertySubType::Pixel);
  555. node.add_property(prop).unwrap();
  556. let mut prop = Property::new("text", PropertyType::Str, PropertySubType::Null);
  557. node.add_property(prop).unwrap();
  558. let mut prop = Property::new("text_color", PropertyType::Float32, PropertySubType::Color);
  559. prop.set_array_len(4);
  560. prop.set_range_f32(0., 1.);
  561. node.add_property(prop).unwrap();
  562. let mut prop = Property::new("cursor_color", PropertyType::Float32, PropertySubType::Color);
  563. prop.set_array_len(4);
  564. prop.set_range_f32(0., 1.);
  565. node.add_property(prop).unwrap();
  566. let mut prop = Property::new("hi_bg_color", PropertyType::Float32, PropertySubType::Color);
  567. prop.set_array_len(4);
  568. prop.set_range_f32(0., 1.);
  569. node.add_property(prop).unwrap();
  570. let mut prop = Property::new("selected", PropertyType::Uint32, PropertySubType::Color);
  571. prop.set_array_len(2);
  572. prop.allow_null_values();
  573. node.add_property(prop).unwrap();
  574. let mut prop = Property::new("z_index", PropertyType::Uint32, PropertySubType::Null);
  575. node.add_property(prop).unwrap();
  576. let mut prop = Property::new("debug", PropertyType::Bool, PropertySubType::Null);
  577. node.add_property(prop).unwrap();
  578. node.id
  579. }
  580. fn create_chatview(sg: &mut SceneGraph, name: &str) -> SceneNodeId {
  581. let node = sg.add_node(name, SceneNodeType::ChatView);
  582. let mut prop = Property::new("rect", PropertyType::Float32, PropertySubType::Pixel);
  583. prop.set_array_len(4);
  584. prop.allow_exprs();
  585. node.add_property(prop).unwrap();
  586. let mut prop = Property::new("scroll", PropertyType::Float32, PropertySubType::Null);
  587. prop.set_ui_text("Scroll", "Scroll up from the bottom");
  588. node.add_property(prop).unwrap();
  589. let prop = Property::new("font_size", PropertyType::Float32, PropertySubType::Pixel);
  590. node.add_property(prop).unwrap();
  591. let prop = Property::new("line_height", PropertyType::Float32, PropertySubType::Pixel);
  592. node.add_property(prop).unwrap();
  593. let prop = Property::new("baseline", PropertyType::Float32, PropertySubType::Pixel);
  594. node.add_property(prop).unwrap();
  595. let mut prop = Property::new("z_index", PropertyType::Uint32, PropertySubType::Null);
  596. node.add_property(prop).unwrap();
  597. let mut prop = Property::new("debug", PropertyType::Bool, PropertySubType::Null);
  598. node.add_property(prop).unwrap();
  599. node.id
  600. }