scene.rs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. use async_channel::Sender;
  2. use async_lock::Mutex;
  3. use darkfi_serial::{SerialDecodable, SerialEncodable};
  4. use futures::{stream::FuturesUnordered, StreamExt};
  5. use std::{fmt, str::FromStr, sync::Arc};
  6. use crate::{
  7. error::{Error, Result},
  8. prop::{Property, PropertyPtr, PropertyType},
  9. ui,
  10. };
  11. pub type SceneNodeId = u32;
  12. #[derive(Debug, Copy, Clone, PartialEq, SerialEncodable, SerialDecodable)]
  13. #[repr(u8)]
  14. pub enum SceneNodeType {
  15. Null = 0,
  16. Root = 1,
  17. Window = 2,
  18. WindowInput = 6,
  19. Keyboard = 7,
  20. Mouse = 8,
  21. RenderLayer = 3,
  22. RenderObject = 4,
  23. RenderMesh = 5,
  24. RenderText = 9,
  25. RenderTexture = 13,
  26. Fonts = 10,
  27. Font = 11,
  28. Plugins = 14,
  29. Plugin = 15,
  30. ChatView = 16,
  31. EditBox = 17,
  32. }
  33. pub struct ScenePath(Vec<String>);
  34. impl<S: Into<String>> From<S> for ScenePath {
  35. fn from(path: S) -> Self {
  36. let path: String = path.into();
  37. (&path).parse().expect("invalid ScenePath &str")
  38. }
  39. }
  40. impl fmt::Display for ScenePath {
  41. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  42. write!(f, "/")?;
  43. for token in &self.0 {
  44. write!(f, "{}/", token)?;
  45. }
  46. Ok(())
  47. }
  48. }
  49. impl FromStr for ScenePath {
  50. type Err = Error;
  51. fn from_str(s: &str) -> Result<Self> {
  52. if s.is_empty() || s.chars().nth(0).unwrap() != '/' {
  53. return Err(Error::InvalidScenePath);
  54. }
  55. if s == "/" {
  56. return Ok(ScenePath(vec![]));
  57. }
  58. let mut tokens = s.split('/');
  59. // Should start with a /
  60. let initial = tokens.next().expect("should not be empty");
  61. if !initial.is_empty() {
  62. return Err(Error::InvalidScenePath);
  63. }
  64. let mut path = vec![];
  65. for token in tokens {
  66. // There should not be any double slashes //
  67. if token.is_empty() {
  68. return Err(Error::InvalidScenePath);
  69. }
  70. path.push(token.to_string());
  71. }
  72. Ok(ScenePath(path))
  73. }
  74. }
  75. pub type SceneGraphPtr = Arc<std::sync::Mutex<SceneGraph>>;
  76. pub type SceneGraphPtr2 = Arc<Mutex<SceneGraph>>;
  77. pub struct SceneGraph {
  78. // Node 0 is always the root
  79. nodes: Vec<SceneNode>,
  80. freed: Vec<SceneNodeId>,
  81. }
  82. impl SceneGraph {
  83. pub const ROOT_ID: SceneNodeId = 0;
  84. pub fn new() -> Self {
  85. let root = SceneNode {
  86. name: "/".to_string(),
  87. id: 0,
  88. typ: SceneNodeType::Root,
  89. parents: vec![],
  90. children: vec![],
  91. props: vec![],
  92. sigs: vec![],
  93. methods: vec![],
  94. pimpl: Pimpl::Null,
  95. };
  96. Self { nodes: vec![root], freed: vec![] }
  97. }
  98. pub fn add_node<S: Into<String>>(&mut self, name: S, typ: SceneNodeType) -> &mut SceneNode {
  99. let node = SceneNode {
  100. name: name.into(),
  101. // We set this at the end
  102. id: 0,
  103. typ,
  104. parents: vec![],
  105. children: vec![],
  106. props: vec![],
  107. sigs: vec![],
  108. methods: vec![],
  109. pimpl: Pimpl::Null,
  110. };
  111. let node_id = if self.freed.is_empty() {
  112. let node_id = self.nodes.len() as SceneNodeId;
  113. self.nodes.push(node);
  114. node_id
  115. } else {
  116. let node_id = self.freed.pop().unwrap();
  117. let _ = std::mem::replace(&mut self.nodes[node_id as usize], node);
  118. node_id
  119. };
  120. self.nodes[node_id as usize].id = node_id;
  121. &mut self.nodes[node_id as usize]
  122. }
  123. pub fn remove_node(&mut self, id: SceneNodeId) -> Result<()> {
  124. let node = self.get_node_mut(id).ok_or(Error::NodeNotFound)?;
  125. if !node.parents.is_empty() {
  126. return Err(Error::NodeHasParents);
  127. }
  128. if !node.children.is_empty() {
  129. return Err(Error::NodeHasChildren);
  130. }
  131. node.name.clear();
  132. node.typ = SceneNodeType::Null;
  133. node.props.clear();
  134. self.freed.push(id);
  135. Ok(())
  136. }
  137. fn root(&self) -> &SceneNode {
  138. &self.nodes[0]
  139. }
  140. fn root_mut(&mut self) -> &mut SceneNode {
  141. &mut self.nodes[0]
  142. }
  143. fn exists(&self, id: SceneNodeId) -> bool {
  144. id < self.nodes.len() as SceneNodeId && !self.freed.contains(&id)
  145. }
  146. pub fn get_node(&self, id: SceneNodeId) -> Option<&SceneNode> {
  147. if self.exists(id) {
  148. Some(&self.nodes[id as usize])
  149. } else {
  150. None
  151. }
  152. }
  153. pub fn get_node_mut(&mut self, id: SceneNodeId) -> Option<&mut SceneNode> {
  154. if self.exists(id) {
  155. Some(&mut self.nodes[id as usize])
  156. } else {
  157. None
  158. }
  159. }
  160. pub fn link(&mut self, child_id: SceneNodeId, parent_id: SceneNodeId) -> Result<()> {
  161. // Check both nodes are not already linked
  162. let is_linked = self.is_linked(child_id, parent_id)?;
  163. if is_linked {
  164. return Err(Error::NodesAreLinked);
  165. }
  166. let parent = self.get_node(parent_id).unwrap();
  167. let parent_inf =
  168. SceneNodeInfo { name: parent.name.clone(), id: parent_id, typ: parent.typ };
  169. let child_name = &self.get_node(child_id).unwrap().name;
  170. if parent.has_child(child_name) {
  171. return Err(Error::NodeChildNameConflict);
  172. }
  173. // Link parent into child
  174. let child = self.get_node_mut(child_id).unwrap();
  175. if child.has_parent(&parent_inf.name) {
  176. return Err(Error::NodeParentNameConflict);
  177. }
  178. let child_inf = SceneNodeInfo { name: child.name.clone(), id: child_id, typ: child.typ };
  179. assert!(!child.has_parent_id(parent_id));
  180. child.parents.push(parent_inf);
  181. // Link child into parent
  182. let parent = self.get_node_mut(parent_id).unwrap();
  183. assert!(!parent.has_child(&child_inf.name));
  184. parent.children.push(child_inf);
  185. Ok(())
  186. }
  187. pub fn unlink(&mut self, child_id: SceneNodeId, parent_id: SceneNodeId) -> Result<()> {
  188. // Check both nodes are actually linked
  189. let is_linked = self.is_linked(child_id, parent_id)?;
  190. if !is_linked {
  191. return Err(Error::NodesNotLinked);
  192. }
  193. // Unlink parent from child
  194. let child = self.get_node_mut(child_id).unwrap();
  195. child.remove_parent(parent_id);
  196. // Unlink child from parent
  197. let parent = self.get_node_mut(parent_id).unwrap();
  198. parent.remove_child(child_id);
  199. Ok(())
  200. }
  201. pub fn is_linked(&self, child_id: SceneNodeId, parent_id: SceneNodeId) -> Result<bool> {
  202. let parent = self.get_node(parent_id).ok_or(Error::ParentNodeNotFound)?;
  203. let child = self.get_node(child_id).ok_or(Error::ChildNodeNotFound)?;
  204. let parent_has_child = parent.has_child_id(child_id);
  205. let child_has_parent = child.has_parent_id(parent_id);
  206. // Internal consistency checks
  207. if parent_has_child {
  208. assert!(child_has_parent);
  209. } else {
  210. assert!(!child_has_parent);
  211. }
  212. Ok(parent_has_child)
  213. }
  214. pub fn lookup_node_id<P: Into<ScenePath>>(&self, path: P) -> Option<SceneNodeId> {
  215. let path: ScenePath = path.into();
  216. let mut current_id = Self::ROOT_ID;
  217. for node_name in path.0 {
  218. let parent_node = self.get_node(current_id).unwrap();
  219. match parent_node.get_child(&node_name) {
  220. Some(child_id) => {
  221. current_id = child_id;
  222. }
  223. None => return None,
  224. }
  225. }
  226. Some(current_id)
  227. }
  228. pub fn lookup_node<P: Into<ScenePath>>(&self, path: P) -> Option<&SceneNode> {
  229. let node_id = self.lookup_node_id(path)?;
  230. Some(self.get_node(node_id).unwrap())
  231. }
  232. pub fn lookup_node_mut<P: Into<ScenePath>>(&mut self, path: P) -> Option<&mut SceneNode> {
  233. let node_id = self.lookup_node_id(path)?;
  234. Some(self.get_node_mut(node_id).unwrap())
  235. }
  236. pub fn rename_node<S: Into<String>>(
  237. &mut self,
  238. node_id: SceneNodeId,
  239. node_name: S,
  240. ) -> Result<()> {
  241. let node_name = node_name.into();
  242. for sibling_inf in self.node_siblings(node_id)? {
  243. if sibling_inf.name == node_name {
  244. return Err(Error::NodeSiblingNameConflict)
  245. }
  246. }
  247. let node = self.get_node_mut(node_id).unwrap();
  248. node.name = node_name.clone();
  249. // Now update it for all children and parents too
  250. let parent_ids: Vec<_> = node.parents.iter().map(|parent_inf| parent_inf.id).collect();
  251. let child_ids: Vec<_> = node.children.iter().map(|child_inf| child_inf.id).collect();
  252. 'next_parent: for parent_id in parent_ids {
  253. let parent = self.get_node_mut(parent_id).unwrap();
  254. for child in &mut parent.children {
  255. if child.id == node_id {
  256. child.name = node_name.clone();
  257. continue 'next_parent
  258. }
  259. }
  260. panic!("child {} not found in parent {}!", node_id, parent.id)
  261. }
  262. 'next_child: for child_id in child_ids {
  263. let child = self.get_node_mut(child_id).unwrap();
  264. for parent in &mut child.parents {
  265. if parent.id == node_id {
  266. parent.name = node_name.clone();
  267. continue 'next_child
  268. }
  269. }
  270. panic!("parent {} not found in child {}!", node_id, child.id)
  271. }
  272. Ok(())
  273. }
  274. fn node_siblings(&self, node_id: SceneNodeId) -> Result<Vec<SceneNodeInfo>> {
  275. let mut siblings = vec![];
  276. let node = self.get_node(node_id).ok_or(Error::NodeNotFound)?;
  277. for parent_inf in &node.parents {
  278. let parent = self.get_node(parent_inf.id).ok_or(Error::ParentNodeNotFound)?;
  279. let mut sibling_infs = parent
  280. .children
  281. .iter()
  282. .cloned()
  283. .filter(|child_inf| child_inf.id != node_id)
  284. .collect();
  285. siblings.append(&mut sibling_infs);
  286. }
  287. Ok(siblings)
  288. }
  289. pub fn scan_dangling(&self) -> Vec<SceneNodeId> {
  290. let mut dangling = vec![];
  291. for node in &self.nodes {
  292. if node.id == Self::ROOT_ID {
  293. continue
  294. }
  295. if self.freed.contains(&node.id) {
  296. continue
  297. }
  298. if node.parents.is_empty() {
  299. dangling.push(node.id);
  300. }
  301. }
  302. dangling
  303. }
  304. }
  305. #[derive(Clone)]
  306. pub struct SceneNodeInfo {
  307. pub name: String,
  308. pub id: SceneNodeId,
  309. pub typ: SceneNodeType,
  310. }
  311. pub struct SceneNode {
  312. pub name: String,
  313. pub id: SceneNodeId,
  314. pub typ: SceneNodeType,
  315. pub parents: Vec<SceneNodeInfo>,
  316. pub children: Vec<SceneNodeInfo>,
  317. pub props: Vec<PropertyPtr>,
  318. pub sigs: Vec<Signal>,
  319. pub methods: Vec<Method>,
  320. pub pimpl: Pimpl,
  321. }
  322. impl SceneNode {
  323. fn has_parent_id(&self, parent_id: SceneNodeId) -> bool {
  324. self.parents.iter().any(|parent| parent.id == parent_id)
  325. }
  326. fn has_child_id(&self, child_id: SceneNodeId) -> bool {
  327. self.children.iter().any(|child| child.id == child_id)
  328. }
  329. fn has_parent(&self, parent_name: &str) -> bool {
  330. self.parents.iter().any(|parent| parent.name == parent_name)
  331. }
  332. fn has_child(&self, child_name: &str) -> bool {
  333. self.children.iter().any(|child| child.name == child_name)
  334. }
  335. fn get_child(&self, child_name: &str) -> Option<SceneNodeId> {
  336. for child in &self.children {
  337. if child.name == child_name {
  338. return Some(child.id);
  339. }
  340. }
  341. None
  342. }
  343. // Panics if parent is not linked
  344. fn remove_parent(&mut self, parent_id: SceneNodeId) {
  345. let parent_idx = self.parents.iter().position(|parent| parent.id == parent_id).unwrap();
  346. self.parents.swap_remove(parent_idx);
  347. }
  348. // Panics if child is not linked
  349. fn remove_child(&mut self, child_id: SceneNodeId) {
  350. let child_idx = self.children.iter().position(|child| child.id == child_id).unwrap();
  351. self.children.swap_remove(child_idx);
  352. }
  353. pub fn get_children(&self, allowed_types: &[SceneNodeType]) -> Vec<SceneNodeInfo> {
  354. self.children
  355. .iter()
  356. .cloned()
  357. .filter(move |child_inf| allowed_types.contains(&child_inf.typ))
  358. .collect()
  359. }
  360. pub fn get_children2(&self) -> Vec<SceneNodeInfo> {
  361. self.children.iter().cloned().collect()
  362. }
  363. pub fn add_property(&mut self, prop: Property) -> Result<()> {
  364. if self.has_property(&prop.name) {
  365. return Err(Error::PropertyAlreadyExists);
  366. }
  367. self.props.push(Arc::new(prop));
  368. Ok(())
  369. }
  370. fn has_property(&self, name: &str) -> bool {
  371. self.props.iter().any(|prop| prop.name == name)
  372. }
  373. pub fn get_property(&self, name: &str) -> Option<PropertyPtr> {
  374. self.props.iter().find(|prop| prop.name == name).map(|prop| prop.clone())
  375. }
  376. // Convenience methods
  377. pub fn get_property_bool(&self, name: &str) -> Result<bool> {
  378. self.get_property(name).ok_or(Error::PropertyNotFound)?.get_bool(0)
  379. }
  380. pub fn get_property_u32(&self, name: &str) -> Result<u32> {
  381. self.get_property(name).ok_or(Error::PropertyNotFound)?.get_u32(0)
  382. }
  383. pub fn get_property_f32(&self, name: &str) -> Result<f32> {
  384. self.get_property(name).ok_or(Error::PropertyNotFound)?.get_f32(0)
  385. }
  386. pub fn get_property_str(&self, name: &str) -> Result<String> {
  387. self.get_property(name).ok_or(Error::PropertyNotFound)?.get_str(0)
  388. }
  389. pub fn get_property_enum(&self, name: &str) -> Result<String> {
  390. self.get_property(name).ok_or(Error::PropertyNotFound)?.get_enum(0)
  391. }
  392. pub fn get_property_node_id(&self, name: &str) -> Result<SceneNodeId> {
  393. self.get_property(name).ok_or(Error::PropertyNotFound)?.get_node_id(0)
  394. }
  395. // Setters
  396. pub fn set_property_bool(&self, name: &str, val: bool) -> Result<()> {
  397. self.get_property(name).ok_or(Error::PropertyNotFound)?.set_bool(0, val)
  398. }
  399. pub fn set_property_u32(&self, name: &str, val: u32) -> Result<()> {
  400. self.get_property(name).ok_or(Error::PropertyNotFound)?.set_u32(0, val)
  401. }
  402. pub fn set_property_f32(&self, name: &str, val: f32) -> Result<()> {
  403. self.get_property(name).ok_or(Error::PropertyNotFound)?.set_f32(0, val)
  404. }
  405. pub fn set_property_str<S: Into<String>>(&self, name: &str, val: S) -> Result<()> {
  406. self.get_property(name).ok_or(Error::PropertyNotFound)?.set_str(0, val)
  407. }
  408. pub fn set_property_node_id(&self, name: &str, val: SceneNodeId) -> Result<()> {
  409. self.get_property(name).ok_or(Error::PropertyNotFound)?.set_node_id(0, val)
  410. }
  411. pub fn add_signal<S: Into<String>>(
  412. &mut self,
  413. name: S,
  414. desc: S,
  415. fmt: Vec<(S, S, PropertyType)>,
  416. ) -> Result<()> {
  417. let name = name.into();
  418. if self.has_signal(&name) {
  419. return Err(Error::SignalAlreadyExists);
  420. }
  421. let fmt = fmt
  422. .into_iter()
  423. .map(|(n, d, t)| CallArg { name: n.into(), desc: d.into(), typ: t })
  424. .collect();
  425. self.sigs.push(Signal {
  426. name: name.into(),
  427. desc: desc.into(),
  428. fmt,
  429. slots: vec![],
  430. freed: vec![],
  431. });
  432. Ok(())
  433. }
  434. fn has_signal(&self, name: &str) -> bool {
  435. self.sigs.iter().any(|sig| sig.name == name)
  436. }
  437. pub fn get_signal(&self, name: &str) -> Option<&Signal> {
  438. self.sigs.iter().find(|sig| sig.name == name)
  439. }
  440. fn get_signal_mut(&mut self, name: &str) -> Option<&mut Signal> {
  441. self.sigs.iter_mut().find(|sig| sig.name == name)
  442. }
  443. pub fn register(&mut self, sig_name: &str, slot: Slot) -> Result<SlotId> {
  444. let sig = self.get_signal_mut(sig_name).ok_or(Error::SignalNotFound)?;
  445. let slot_id = if sig.freed.is_empty() {
  446. let slot_id = sig.slots.len() as SlotId;
  447. sig.slots.push(slot);
  448. slot_id
  449. } else {
  450. let slot_id = sig.freed.pop().unwrap();
  451. let _ = std::mem::replace(&mut sig.slots[slot_id as usize], slot);
  452. slot_id
  453. };
  454. Ok(slot_id)
  455. }
  456. pub fn unregister(&mut self, sig_name: &str, slot_id: SlotId) -> Result<()> {
  457. let sig = self.get_signal_mut(sig_name).ok_or(Error::SignalNotFound)?;
  458. if !sig.slot_exists(slot_id) {
  459. return Err(Error::SlotNotFound);
  460. }
  461. sig.freed.push(slot_id);
  462. Ok(())
  463. }
  464. pub async fn trigger(&self, sig_name: &str, data: Vec<u8>) -> Result<()> {
  465. let sig = self.get_signal(sig_name).ok_or(Error::SignalNotFound)?;
  466. let futures = FuturesUnordered::new();
  467. for (_, slot) in sig.get_slots() {
  468. // Trigger the slot
  469. futures.push(async {
  470. // Ignore the result
  471. let _ = slot.notify.send(data.clone()).await;
  472. });
  473. }
  474. let _: Vec<_> = futures.collect().await;
  475. Ok(())
  476. }
  477. pub fn add_method<S: Into<String>>(
  478. &mut self,
  479. name: S,
  480. args: Vec<(S, S, PropertyType)>,
  481. result: Vec<(S, S, PropertyType)>,
  482. method_fn: MethodRequestFn,
  483. ) -> Result<()> {
  484. let name = name.into();
  485. if self.has_signal(&name) {
  486. return Err(Error::MethodAlreadyExists);
  487. }
  488. let args = args
  489. .into_iter()
  490. .map(|(n, d, t)| CallArg { name: n.into(), desc: d.into(), typ: t })
  491. .collect();
  492. let result = result
  493. .into_iter()
  494. .map(|(n, d, t)| CallArg { name: n.into(), desc: d.into(), typ: t })
  495. .collect();
  496. self.methods.push(Method { name: name.into(), args, result, method_fn });
  497. Ok(())
  498. }
  499. pub fn get_method(&self, name: &str) -> Option<&Method> {
  500. self.methods.iter().find(|method| method.name == name)
  501. }
  502. fn get_method_mut(&mut self, name: &str) -> Option<&mut Method> {
  503. self.methods.iter_mut().find(|method| method.name == name)
  504. }
  505. pub fn call_method(
  506. &mut self,
  507. name: &str,
  508. arg_data: Vec<u8>,
  509. response_fn: MethodResponseFn,
  510. ) -> Result<()> {
  511. let method = self.get_method(name).ok_or(Error::MethodNotFound)?;
  512. (method.method_fn)(arg_data, response_fn);
  513. Ok(())
  514. }
  515. }
  516. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  517. pub struct CallArg {
  518. pub name: String,
  519. pub desc: String,
  520. pub typ: PropertyType,
  521. }
  522. type SlotFn = Box<dyn Fn(Vec<u8>) + Send>;
  523. pub type SlotId = u32;
  524. pub struct Slot {
  525. pub name: String,
  526. pub notify: Sender<Vec<u8>>,
  527. }
  528. pub struct Signal {
  529. pub name: String,
  530. pub desc: String,
  531. pub fmt: Vec<CallArg>,
  532. slots: Vec<Slot>,
  533. freed: Vec<SlotId>,
  534. }
  535. impl Signal {
  536. fn slot_exists(&self, slot_id: SlotId) -> bool {
  537. if slot_id >= self.slots.len() as SlotId {
  538. return false;
  539. }
  540. return !self.freed.contains(&slot_id);
  541. }
  542. pub fn get_slots<'a>(&'a self) -> impl Iterator<Item = (SlotId, &'a Slot)> {
  543. self.slots
  544. .iter()
  545. .enumerate()
  546. .filter(|(slot_id, _)| !self.freed.contains(&(*slot_id as SlotId)))
  547. .map(|(slot_id, slot)| (slot_id as SlotId, slot))
  548. }
  549. pub fn lookup_slot_id(&self, slot_name: &str) -> Option<SlotId> {
  550. for (slot_id, slot) in self.get_slots() {
  551. if slot.name == slot_name {
  552. return Some(slot_id);
  553. }
  554. }
  555. None
  556. }
  557. }
  558. type MethodRequestFn = Box<dyn Fn(Vec<u8>, MethodResponseFn) + Send + Sync>;
  559. pub type MethodResponseFn = Box<dyn Fn(Result<Vec<u8>>) + Send + Sync>;
  560. pub struct Method {
  561. pub name: String,
  562. pub args: Vec<CallArg>,
  563. pub result: Vec<CallArg>,
  564. method_fn: MethodRequestFn,
  565. }
  566. pub enum Pimpl {
  567. Null,
  568. //EditBox(editbox::EditBoxPtr),
  569. //ChatView(chatview::ChatViewPtr),
  570. Window(ui::WindowPtr),
  571. RenderLayer(ui::RenderLayerPtr),
  572. Mesh(ui::MeshPtr),
  573. }
  574. impl std::fmt::Debug for SceneNode {
  575. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  576. write!(f, "'{}':{}", self.name, self.id)
  577. }
  578. }