stardust_xr_fusion/
root.rs1use crate::client::ClientHandle;
2use crate::spatial::{SpatialRef, SpatialRefAspect};
3use rustc_hash::FxHashMap;
4use serde::Serialize;
5use serde::de::DeserializeOwned;
6use stardust_xr::schemas::flex::flexbuffers::{self, SerializationError};
7use std::sync::Arc;
8
9pub use crate::protocol::root::*;
10
11impl Default for ClientState {
13 fn default() -> Self {
14 ClientState {
15 data: None,
16 root: 0,
17 spatial_anchors: Default::default(),
18 }
19 }
20}
21impl ClientState {
22 pub fn new<T: Serialize>(
23 data: Option<T>,
24 root: &impl SpatialRefAspect,
25 spatial_anchors: FxHashMap<String, &impl SpatialRefAspect>,
26 ) -> Result<Self, SerializationError> {
27 Ok(ClientState {
28 data: data.map(flexbuffers::to_vec).transpose()?,
29 root: root.id(),
30 spatial_anchors: spatial_anchors
31 .into_iter()
32 .map(|(k, v)| (k, v.id()))
33 .collect(),
34 })
35 }
36 pub fn from_data_root<T: Serialize>(
37 data: Option<T>,
38 root: &impl SpatialRefAspect,
39 ) -> Result<Self, SerializationError> {
40 Self::new(data, root, FxHashMap::<String, &SpatialRef>::default())
41 }
42 pub fn from_root_anchors(
43 root: &impl SpatialRefAspect,
44 spatial_anchors: FxHashMap<String, &impl SpatialRefAspect>,
45 ) -> Result<Self, SerializationError> {
46 Self::new(None::<()>, root, spatial_anchors)
47 }
48 pub fn from_root(root: &impl SpatialRefAspect) -> Result<Self, SerializationError> {
49 Self::from_data_root(None::<()>, root)
50 }
51
52 pub fn data<T: DeserializeOwned>(&self) -> Option<T> {
53 flexbuffers::from_buffer(&self.data.as_ref()?.as_slice()).ok()
54 }
55 pub fn root(&self, client: &Arc<ClientHandle>) -> SpatialRef {
56 SpatialRef::from_id(client, self.root, false)
57 }
58 pub fn spatial_anchors(&self, client: &Arc<ClientHandle>) -> FxHashMap<String, SpatialRef> {
59 self.spatial_anchors
60 .iter()
61 .map(|(k, v)| (k.to_string(), SpatialRef::from_id(client, *v, false)))
62 .collect()
63 }
64}
65
66#[tokio::test]
67async fn fusion_root_save_state() {
68 use crate::Client;
69 let mut client = Client::connect().await.expect("Couldn't connect");
70 client
71 .sync_event_loop(|client, flow| {
72 let root = client.get_root();
73 while let Some(event) = root.recv_root_event() {
74 match event {
75 RootEvent::Ping { response } => response.send_ok(()),
76 RootEvent::Frame { info: _ } => (),
77 RootEvent::SaveState { response } => {
78 response.send(ClientState::from_data_root(Some(()), root));
79 flow.stop();
80 }
81 }
82 }
83 })
84 .await
85 .unwrap();
86}