feat: upgrade to numerical IDs
This commit is contained in:
@@ -8,13 +8,13 @@ name = "task"
|
|||||||
# type = "lldb"
|
# type = "lldb"
|
||||||
|
|
||||||
# the program to run
|
# the program to run
|
||||||
program = "cargo"
|
program = "./target/debug/stardust-xr-server"
|
||||||
|
|
||||||
# the program arguments, e.g. args = ["arg1", "arg2"], optional
|
# the program arguments, e.g. args = ["arg1", "arg2"], optional
|
||||||
args = ["lrun", "--", "-f"]
|
# args = []
|
||||||
|
|
||||||
# current working directory, optional
|
# current working directory, optional
|
||||||
# cwd = "${workspace}"
|
cwd = "${workspace}"
|
||||||
|
|
||||||
# enviroment variables, optional
|
# enviroment variables, optional
|
||||||
# [configs.env]
|
# [configs.env]
|
||||||
|
|||||||
100
Cargo.lock
generated
100
Cargo.lock
generated
@@ -378,9 +378,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytemuck_derive"
|
name = "bytemuck_derive"
|
||||||
version = "1.6.1"
|
version = "1.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "369cfaf2a5bed5d8f8202073b2e093c9f508251de1551a0deb4253e4c7d80909"
|
checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -1257,9 +1257,9 @@ checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.10.5"
|
version = "0.12.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
@@ -1414,7 +1414,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "macros"
|
name = "macros"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/mvvvv/StereoKit-rust.git#348e8a458e0b329464fa292ec3635d3eaabd21d7"
|
source = "git+https://github.com/mvvvv/StereoKit-rust.git#e6d6858a24553e70bcb02e3b6e94f7603c663e3b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "manifest-dir-macros"
|
name = "manifest-dir-macros"
|
||||||
@@ -1680,7 +1680,7 @@ version = "0.5.11"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799"
|
checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate 1.3.1",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
@@ -1692,7 +1692,7 @@ version = "0.7.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b"
|
checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate 3.1.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.66",
|
"syn 2.0.66",
|
||||||
@@ -1952,9 +1952,9 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "polling"
|
name = "polling"
|
||||||
version = "3.7.0"
|
version = "3.7.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "645493cf344456ef24219d02a768cf1fb92ddf8c92161679ae3d91b91a637be3"
|
checksum = "5e6a007746f34ed64099e88783b0ae369eaa3da6392868ba262e2af9b8fbaea1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"concurrent-queue",
|
"concurrent-queue",
|
||||||
@@ -1999,10 +1999,19 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro-crate"
|
||||||
version = "1.0.84"
|
version = "3.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6"
|
checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284"
|
||||||
|
dependencies = [
|
||||||
|
"toml_edit 0.21.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.85"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
@@ -2385,6 +2394,15 @@ dependencies = [
|
|||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slotmap"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a"
|
||||||
|
dependencies = [
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.13.2"
|
version = "1.13.2"
|
||||||
@@ -2483,7 +2501,7 @@ checksum = "2f2b15926089e5526bb2dd738a2eb0e59034356e06eb71e1cd912358c0e62c4d"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "stardust-xr"
|
name = "stardust-xr"
|
||||||
version = "0.45.0"
|
version = "0.45.0"
|
||||||
source = "git+https://github.com/StardustXR/core.git?branch=dev#47208187ffdb00627fabbb3af2bd0a12a6208194"
|
source = "git+https://github.com/StardustXR/core.git?branch=dev#7ddbcb9be74df67efcde057f2b68ba8592507b13"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cluFlock",
|
"cluFlock",
|
||||||
"color-rs",
|
"color-rs",
|
||||||
@@ -2503,10 +2521,11 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "stardust-xr-schemas"
|
name = "stardust-xr-schemas"
|
||||||
version = "1.5.3"
|
version = "1.5.3"
|
||||||
source = "git+https://github.com/StardustXR/core.git?branch=dev#47208187ffdb00627fabbb3af2bd0a12a6208194"
|
source = "git+https://github.com/StardustXR/core.git?branch=dev#7ddbcb9be74df67efcde057f2b68ba8592507b13"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"flatbuffers",
|
"flatbuffers",
|
||||||
"flexbuffers",
|
"flexbuffers",
|
||||||
|
"fnv",
|
||||||
"kdl",
|
"kdl",
|
||||||
"manifest-dir-macros",
|
"manifest-dir-macros",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -2525,6 +2544,7 @@ dependencies = [
|
|||||||
"ctrlc",
|
"ctrlc",
|
||||||
"directories",
|
"directories",
|
||||||
"glam",
|
"glam",
|
||||||
|
"global_counter",
|
||||||
"input-event-codes",
|
"input-event-codes",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -2540,6 +2560,7 @@ dependencies = [
|
|||||||
"send_wrapper",
|
"send_wrapper",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
|
"slotmap",
|
||||||
"smithay",
|
"smithay",
|
||||||
"stardust-xr",
|
"stardust-xr",
|
||||||
"stardust-xr-server-codegen",
|
"stardust-xr-server-codegen",
|
||||||
@@ -2569,7 +2590,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "stereokit-rust"
|
name = "stereokit-rust"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/mvvvv/StereoKit-rust.git#348e8a458e0b329464fa292ec3635d3eaabd21d7"
|
source = "git+https://github.com/mvvvv/StereoKit-rust.git#e6d6858a24553e70bcb02e3b6e94f7603c663e3b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"android_logger",
|
"android_logger",
|
||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
@@ -2695,9 +2716,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.37.0"
|
version = "1.38.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
|
checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -2725,9 +2746,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-macros"
|
name = "tokio-macros"
|
||||||
version = "2.2.0"
|
version = "2.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
|
checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -2790,6 +2811,17 @@ dependencies = [
|
|||||||
"winnow 0.5.40",
|
"winnow 0.5.40",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.21.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap 2.2.6",
|
||||||
|
"toml_datetime",
|
||||||
|
"winnow 0.5.40",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_edit"
|
name = "toml_edit"
|
||||||
version = "0.22.13"
|
version = "0.22.13"
|
||||||
@@ -2800,7 +2832,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_spanned",
|
"serde_spanned",
|
||||||
"toml_datetime",
|
"toml_datetime",
|
||||||
"winnow 0.6.8",
|
"winnow 0.6.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3095,9 +3127,9 @@ checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-backend"
|
name = "wayland-backend"
|
||||||
version = "0.3.3"
|
version = "0.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9d50fa61ce90d76474c87f5fc002828d81b32677340112b4ef08079a9d459a40"
|
checksum = "34e9e6b6d4a2bb4e7e69433e0b35c7923b95d4dc8503a84d25ec917a4bbfdf07"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"downcast-rs",
|
"downcast-rs",
|
||||||
@@ -3109,9 +3141,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-client"
|
name = "wayland-client"
|
||||||
version = "0.31.2"
|
version = "0.31.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f"
|
checksum = "1e63801c85358a431f986cffa74ba9599ff571fc5774ac113ed3b490c19a1133"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
"rustix",
|
"rustix",
|
||||||
@@ -3132,9 +3164,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-cursor"
|
name = "wayland-cursor"
|
||||||
version = "0.31.1"
|
version = "0.31.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "71ce5fa868dd13d11a0d04c5e2e65726d0897be8de247c0c5a65886e283231ba"
|
checksum = "a206e8b2b53b1d3fcb9428fec72bc278ce539e2fa81fe2bfc1ab27703d5187b9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustix",
|
"rustix",
|
||||||
"wayland-client",
|
"wayland-client",
|
||||||
@@ -3196,9 +3228,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-scanner"
|
name = "wayland-scanner"
|
||||||
version = "0.31.1"
|
version = "0.31.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "63b3a62929287001986fb58c789dce9b67604a397c15c611ad9f747300b6c283"
|
checksum = "67da50b9f80159dec0ea4c11c13e24ef9e7574bd6ce24b01860a175010cea565"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quick-xml",
|
"quick-xml",
|
||||||
@@ -3207,9 +3239,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-server"
|
name = "wayland-server"
|
||||||
version = "0.31.1"
|
version = "0.31.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "00e6e4d5c285bc24ba4ed2d5a4bd4febd5fd904451f465973225c8e99772fdb7"
|
checksum = "63e89118bd072ba6ce0f9c2c92fa41f72d1d78a138d2abc497a80a8264565559"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
"downcast-rs",
|
"downcast-rs",
|
||||||
@@ -3221,9 +3253,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-sys"
|
name = "wayland-sys"
|
||||||
version = "0.31.1"
|
version = "0.31.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "15a0c8eaff5216d07f226cb7a549159267f3467b289d9a2e52fd3ef5aae2b7af"
|
checksum = "105b1842da6554f91526c14a2a2172897b7f745a805d62af4ce698706be79c12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dlib",
|
"dlib",
|
||||||
"log",
|
"log",
|
||||||
@@ -3577,9 +3609,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
version = "0.6.8"
|
version = "0.6.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d"
|
checksum = "86c949fede1d13936a99f14fafd3e76fd642b556dd2ce96287fbe2e0151bfac6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ nix = "0.29.0"
|
|||||||
wayland-scanner = "0.31.1"
|
wayland-scanner = "0.31.1"
|
||||||
wayland-backend = "0.3.3"
|
wayland-backend = "0.3.3"
|
||||||
toml = "0.8.10"
|
toml = "0.8.10"
|
||||||
|
global_counter = "=0.2.2"
|
||||||
|
slotmap = "1.0.7"
|
||||||
|
|
||||||
[dependencies.smithay]
|
[dependencies.smithay]
|
||||||
# git = "https://github.com/technobaboo/smithay.git"
|
# git = "https://github.com/technobaboo/smithay.git"
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ fn fold_tokens(a: TokenStream, b: TokenStream) -> TokenStream {
|
|||||||
quote!(#a #b)
|
quote!(#a #b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[proc_macro]
|
#[proc_macro]
|
||||||
// pub fn codegen_root_protocol(_input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
pub fn codegen_root_protocol(_input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
// codegen_protocol(ROOT_PROTOCOL)
|
codegen_protocol(ROOT_PROTOCOL)
|
||||||
// }
|
}
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn codegen_node_protocol(_input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
pub fn codegen_node_protocol(_input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
codegen_protocol(NODE_PROTOCOL)
|
codegen_protocol(NODE_PROTOCOL)
|
||||||
@@ -58,18 +58,17 @@ fn codegen_protocol(protocol: &'static str) -> proc_macro::TokenStream {
|
|||||||
let interface = protocol
|
let interface = protocol
|
||||||
.interface
|
.interface
|
||||||
.map(|p| {
|
.map(|p| {
|
||||||
let virtual_aspect_name = p.path[1..]
|
let node_id = p.node_id;
|
||||||
.split('/')
|
let node_id = quote! {
|
||||||
.map(ToString::to_string)
|
const INTERFACE_NODE_ID: u64 = #node_id;
|
||||||
.reduce(|a, b| format!("{a}_{b}"))
|
};
|
||||||
.unwrap_or_default()
|
let aspect = generate_aspect(&Aspect {
|
||||||
+ "_interface";
|
name: "interface".to_string(),
|
||||||
generate_aspect(&Aspect {
|
|
||||||
name: virtual_aspect_name,
|
|
||||||
description: protocol.description.clone(),
|
description: protocol.description.clone(),
|
||||||
inherits: vec![],
|
inherits: vec![],
|
||||||
members: p.members,
|
members: p.members,
|
||||||
})
|
});
|
||||||
|
quote!(#node_id #aspect)
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let custom_enums = protocol
|
let custom_enums = protocol
|
||||||
@@ -169,45 +168,6 @@ fn generate_custom_struct(custom_struct: &CustomStruct) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn generate_node(node: &Node) -> TokenStream {
|
|
||||||
// let node_name = Ident::new(&node.name, Span::call_site());
|
|
||||||
// let description = &node.description;
|
|
||||||
|
|
||||||
// let aspects = node
|
|
||||||
// .aspects
|
|
||||||
// .iter()
|
|
||||||
// .map(|a| {
|
|
||||||
// let aspect_name = Ident::new(&format!("{a}Aspect"), Span::call_site());
|
|
||||||
// quote!(impl #aspect_name for #node_name {})
|
|
||||||
// })
|
|
||||||
// .reduce(fold_tokens)
|
|
||||||
// .unwrap_or_default();
|
|
||||||
|
|
||||||
// quote! {
|
|
||||||
// #[doc = #description]
|
|
||||||
// #[derive(Debug)]
|
|
||||||
// pub struct #node_name (crate::node::Node);
|
|
||||||
// impl crate::node::NodeType for #node_name {
|
|
||||||
// fn node(&self) -> &crate::node::Node {
|
|
||||||
// &self.0
|
|
||||||
// }
|
|
||||||
// fn alias(&self) -> Self {
|
|
||||||
// #node_name(self.0.alias())
|
|
||||||
// }
|
|
||||||
// fn from_path(client: &std::sync::Arc<crate::client::Client>, path: String, destroyable: bool) -> Self {
|
|
||||||
// #node_name(crate::node::Node::from_path(client, path, destroyable))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// impl serde::Serialize for #node_name {
|
|
||||||
// fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
|
||||||
// let node_path = self.0.get_path().map_err(|e| serde::ser::Error::custom(e))?;
|
|
||||||
// serializer.serialize_str(&node_path)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// #aspects
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn generate_aspect(aspect: &Aspect) -> TokenStream {
|
fn generate_aspect(aspect: &Aspect) -> TokenStream {
|
||||||
let description = &aspect.description;
|
let description = &aspect.description;
|
||||||
let (client_members, server_members) = aspect.members.iter().split(|m| m.side == Side::Server);
|
let (client_members, server_members) = aspect.members.iter().split(|m| m.side == Side::Server);
|
||||||
@@ -234,6 +194,30 @@ fn generate_aspect(aspect: &Aspect) -> TokenStream {
|
|||||||
&format!("{}Aspect", &aspect.name.to_case(Case::Pascal)),
|
&format!("{}Aspect", &aspect.name.to_case(Case::Pascal)),
|
||||||
Span::call_site(),
|
Span::call_site(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let opcodes = aspect
|
||||||
|
.members
|
||||||
|
.iter()
|
||||||
|
.map(|m| {
|
||||||
|
let aspect_name = aspect.name.to_case(Case::ScreamingSnake);
|
||||||
|
let member_name = m.name.to_case(Case::ScreamingSnake);
|
||||||
|
let name_type = if m.side == Side::Client {
|
||||||
|
"CLIENT"
|
||||||
|
} else {
|
||||||
|
"SERVER"
|
||||||
|
};
|
||||||
|
let name = Ident::new(
|
||||||
|
&format!("{aspect_name}_{member_name}_{name_type}_OPCODE"),
|
||||||
|
Span::call_site(),
|
||||||
|
);
|
||||||
|
let opcode = m.opcode;
|
||||||
|
|
||||||
|
quote!(pub(crate) const #name: u64 = #opcode;)
|
||||||
|
})
|
||||||
|
.reduce(fold_tokens)
|
||||||
|
.unwrap_or_default();
|
||||||
|
let alias_info = generate_alias_info(aspect);
|
||||||
|
|
||||||
let server_side_members = server_members
|
let server_side_members = server_members
|
||||||
.map(generate_member)
|
.map(generate_member)
|
||||||
.reduce(fold_tokens)
|
.reduce(fold_tokens)
|
||||||
@@ -259,11 +243,45 @@ fn generate_aspect(aspect: &Aspect) -> TokenStream {
|
|||||||
#server_side_members
|
#server_side_members
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
quote!(#client_side_members #server_side_members)
|
quote!(#opcodes #alias_info #client_side_members #server_side_members)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_alias_opcodes(aspect: &Aspect, side: Side, _type: MemberType) -> TokenStream {
|
||||||
|
aspect
|
||||||
|
.members
|
||||||
|
.iter()
|
||||||
|
.filter(|m| m.side == side)
|
||||||
|
.filter(|m| m._type == _type)
|
||||||
|
.map(|m| m.opcode)
|
||||||
|
.map(|o| quote!(#o))
|
||||||
|
.reduce(|a, b| quote!(#a, #b))
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
fn generate_alias_info(aspect: &Aspect) -> TokenStream {
|
||||||
|
let aspect_alias_info_name = Ident::new(
|
||||||
|
&format!(
|
||||||
|
"{}_ASPECT_ALIAS_INFO",
|
||||||
|
aspect.name.to_case(Case::ScreamingSnake)
|
||||||
|
),
|
||||||
|
Span::call_site(),
|
||||||
|
);
|
||||||
|
let local_signals = generate_alias_opcodes(aspect, Side::Server, MemberType::Signal);
|
||||||
|
let local_methods = generate_alias_opcodes(aspect, Side::Server, MemberType::Method);
|
||||||
|
let remote_signals = generate_alias_opcodes(aspect, Side::Client, MemberType::Signal);
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
lazy_static::lazy_static! {
|
||||||
|
pub static ref #aspect_alias_info_name: crate::nodes::alias::AliasInfo = crate::nodes::alias::AliasInfo {
|
||||||
|
server_signals: vec![#local_signals],
|
||||||
|
server_methods: vec![#local_methods],
|
||||||
|
client_signals: vec![#remote_signals],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_member(member: &Member) -> TokenStream {
|
fn generate_member(member: &Member) -> TokenStream {
|
||||||
let name_str = &member.name;
|
let id = member.opcode;
|
||||||
let name = Ident::new(&member.name.to_case(Case::Snake), Span::call_site());
|
let name = Ident::new(&member.name.to_case(Case::Snake), Span::call_site());
|
||||||
let description = &member.description;
|
let description = &member.description;
|
||||||
|
|
||||||
@@ -298,8 +316,8 @@ fn generate_member(member: &Member) -> TokenStream {
|
|||||||
(Side::Client, MemberType::Method) => {
|
(Side::Client, MemberType::Method) => {
|
||||||
quote! {
|
quote! {
|
||||||
#[doc = #description]
|
#[doc = #description]
|
||||||
pub async fn #name(#argument_decls) -> color_eyre::eyre::Result<#return_type> {
|
pub async fn #name(#argument_decls) -> color_eyre::eyre::Result<(#return_type, Vec<std::os::fd::OwnedFd>)> {
|
||||||
_node.execute_remote_method(#name_str, &(#argument_uses)).await
|
_node.execute_remote_method_typed(#id, &(#argument_uses), vec![]).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -308,7 +326,7 @@ fn generate_member(member: &Member) -> TokenStream {
|
|||||||
#[doc = #description]
|
#[doc = #description]
|
||||||
pub fn #name(#argument_decls) -> color_eyre::eyre::Result<()> {
|
pub fn #name(#argument_decls) -> color_eyre::eyre::Result<()> {
|
||||||
let serialized = stardust_xr::schemas::flex::serialize((#argument_uses))?;
|
let serialized = stardust_xr::schemas::flex::serialize((#argument_uses))?;
|
||||||
_node.send_remote_signal(#name_str, serialized)
|
_node.send_remote_signal(#id, serialized)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -319,23 +337,7 @@ fn generate_member(member: &Member) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Side::Server, MemberType::Signal) => {
|
(Side::Server, MemberType::Signal) => {
|
||||||
let prefix =
|
|
||||||
if let Some(ArgumentType::Node { _type, return_info }) = &member.return_type {
|
|
||||||
if let Some(return_info) = return_info {
|
|
||||||
let parent_name = Ident::new(
|
|
||||||
&(name_str.to_case(Case::ScreamingSnake) + "_PARENT_PATH"),
|
|
||||||
Span::call_site(),
|
|
||||||
);
|
|
||||||
let parent_path = &return_info.parent;
|
|
||||||
quote!(const #parent_name: &'static str = #parent_path;)
|
|
||||||
} else {
|
|
||||||
TokenStream::default()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
TokenStream::default()
|
|
||||||
};
|
|
||||||
quote! {
|
quote! {
|
||||||
#prefix
|
|
||||||
#[doc = #description]
|
#[doc = #description]
|
||||||
fn #name(#argument_decls) -> color_eyre::eyre::Result<()>;
|
fn #name(#argument_decls) -> color_eyre::eyre::Result<()>;
|
||||||
}
|
}
|
||||||
@@ -343,8 +345,8 @@ fn generate_member(member: &Member) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn generate_handler(member: &Member) -> TokenStream {
|
fn generate_handler(member: &Member) -> TokenStream {
|
||||||
let member_name = &member.name;
|
let opcode = member.opcode;
|
||||||
let member_name_ident = Ident::new(&member_name, Span::call_site());
|
let member_name_ident = Ident::new(&member.name, Span::call_site());
|
||||||
|
|
||||||
let argument_names = member
|
let argument_names = member
|
||||||
.arguments
|
.arguments
|
||||||
@@ -375,13 +377,13 @@ fn generate_handler(member: &Member) -> TokenStream {
|
|||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
match member._type {
|
match member._type {
|
||||||
MemberType::Signal => quote! {
|
MemberType::Signal => quote! {
|
||||||
node.add_local_signal(#member_name, |_node, _calling_client, _message| {
|
node.add_local_signal(#opcode, |_node, _calling_client, _message| {
|
||||||
#deserialize
|
#deserialize
|
||||||
Self::#member_name_ident(_node, _calling_client.clone(), #argument_uses)
|
Self::#member_name_ident(_node, _calling_client.clone(), #argument_uses)
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
MemberType::Method => quote! {
|
MemberType::Method => quote! {
|
||||||
node.add_local_method(#member_name, |_node, _calling_client, _message, _method_response| {
|
node.add_local_method(#opcode, |_node, _calling_client, _message, _method_response| {
|
||||||
_method_response.wrap_async(async move {
|
_method_response.wrap_async(async move {
|
||||||
#deserialize
|
#deserialize
|
||||||
Ok((Self::#member_name_ident(_node, _calling_client.clone(), #argument_uses).await?, Vec::new()))
|
Ok((Self::#member_name_ident(_node, _calling_client.clone(), #argument_uses).await?, Vec::new()))
|
||||||
@@ -396,7 +398,7 @@ fn generate_argument_name(argument: &Argument) -> TokenStream {
|
|||||||
|
|
||||||
fn convert_deserializeable_argument_type(argument_type: &ArgumentType) -> ArgumentType {
|
fn convert_deserializeable_argument_type(argument_type: &ArgumentType) -> ArgumentType {
|
||||||
match argument_type {
|
match argument_type {
|
||||||
ArgumentType::Node { .. } => ArgumentType::String,
|
ArgumentType::Node { .. } => ArgumentType::NodeID,
|
||||||
ArgumentType::Vec(v) => {
|
ArgumentType::Vec(v) => {
|
||||||
ArgumentType::Vec(Box::new(convert_deserializeable_argument_type(v.as_ref())))
|
ArgumentType::Vec(Box::new(convert_deserializeable_argument_type(v.as_ref())))
|
||||||
}
|
}
|
||||||
@@ -414,8 +416,8 @@ fn generate_argument_deserialize(
|
|||||||
let name = Ident::new(&argument_name.to_case(Case::Snake), Span::call_site());
|
let name = Ident::new(&argument_name.to_case(Case::Snake), Span::call_site());
|
||||||
if let ArgumentType::Node { .. } = argument_type {
|
if let ArgumentType::Node { .. } = argument_type {
|
||||||
return match optional {
|
return match optional {
|
||||||
true => quote!(#name.map(|n| _calling_client.get_node(#argument_name, &n)?)),
|
true => quote!(#name.map(|n| _calling_client.get_node(#argument_name, n)?)),
|
||||||
false => quote!(_calling_client.get_node(#argument_name, &#name)?),
|
false => quote!(_calling_client.get_node(#argument_name, #name)?),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if optional {
|
if optional {
|
||||||
@@ -445,10 +447,10 @@ fn generate_argument_serialize(
|
|||||||
match argument_type {
|
match argument_type {
|
||||||
ArgumentType::Node {
|
ArgumentType::Node {
|
||||||
_type,
|
_type,
|
||||||
return_info: _,
|
return_id_parameter_name: _,
|
||||||
} => match optional {
|
} => match optional {
|
||||||
true => quote!(#name.map(|n| n.get_path())),
|
true => quote!(#name.map(|n| n.get_id())),
|
||||||
false => quote!(#name.get_path()),
|
false => quote!(#name.get_id()),
|
||||||
},
|
},
|
||||||
ArgumentType::Color => quote!([#name.c.r, #name.c.g, #name.c.b, #name.a]),
|
ArgumentType::Color => quote!([#name.c.r, #name.c.g, #name.c.b, #name.a]),
|
||||||
ArgumentType::Vec(v) => {
|
ArgumentType::Vec(v) => {
|
||||||
@@ -483,6 +485,7 @@ fn argument_type_option_name(argument_type: &ArgumentType) -> String {
|
|||||||
ArgumentType::Bytes => "Bytes".to_string(),
|
ArgumentType::Bytes => "Bytes".to_string(),
|
||||||
ArgumentType::Vec(v) => format!("{}Vector", argument_type_option_name(&v)),
|
ArgumentType::Vec(v) => format!("{}Vector", argument_type_option_name(&v)),
|
||||||
ArgumentType::Map(m) => format!("{}Map", argument_type_option_name(&m)),
|
ArgumentType::Map(m) => format!("{}Map", argument_type_option_name(&m)),
|
||||||
|
ArgumentType::NodeID => "Node ID".to_string(),
|
||||||
ArgumentType::Datamap => "Datamap".to_string(),
|
ArgumentType::Datamap => "Datamap".to_string(),
|
||||||
ArgumentType::ResourceID => "ResourceID".to_string(),
|
ArgumentType::ResourceID => "ResourceID".to_string(),
|
||||||
ArgumentType::Enum(e) => e.clone(),
|
ArgumentType::Enum(e) => e.clone(),
|
||||||
@@ -544,6 +547,7 @@ fn generate_argument_type(
|
|||||||
quote!(stardust_xr::values::Map<String, #t>)
|
quote!(stardust_xr::values::Map<String, #t>)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ArgumentType::NodeID => quote!(u64),
|
||||||
ArgumentType::Datamap => {
|
ArgumentType::Datamap => {
|
||||||
if !owned {
|
if !owned {
|
||||||
quote!(&stardust_xr::values::Datamap)
|
quote!(&stardust_xr::values::Datamap)
|
||||||
@@ -576,7 +580,7 @@ fn generate_argument_type(
|
|||||||
}
|
}
|
||||||
ArgumentType::Node {
|
ArgumentType::Node {
|
||||||
_type,
|
_type,
|
||||||
return_info: _,
|
return_id_parameter_name: _,
|
||||||
} => {
|
} => {
|
||||||
if !owned {
|
if !owned {
|
||||||
quote!(&std::sync::Arc<crate::nodes::Node>)
|
quote!(&std::sync::Arc<crate::nodes::Node>)
|
||||||
|
|||||||
@@ -1,21 +1,23 @@
|
|||||||
use super::{
|
use super::{
|
||||||
client_state::{ClientState, CLIENT_STATES},
|
client_state::{ClientStateParsed, CLIENT_STATES},
|
||||||
destroy_queue,
|
destroy_queue,
|
||||||
scenegraph::Scenegraph,
|
scenegraph::Scenegraph,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
core::{registry::OwnedRegistry, task},
|
core::{registry::OwnedRegistry, task},
|
||||||
nodes::{audio, data, drawable, fields, hmd, input, items, root::Root, spatial, Node},
|
nodes::{
|
||||||
|
audio, data, drawable, fields, hmd, input, items,
|
||||||
|
root::{ClientState, Root},
|
||||||
|
spatial, Node,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use color_eyre::eyre::{eyre, Result};
|
use color_eyre::eyre::{eyre, Result};
|
||||||
|
use global_counter::primitive::exact::CounterU32;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use stardust_xr::{
|
use stardust_xr::messenger::{self, MessageSenderHandle};
|
||||||
messenger::{self, MessageSenderHandle},
|
|
||||||
schemas::flex::serialize,
|
|
||||||
};
|
|
||||||
use std::{fmt::Debug, fs, iter::FromIterator, path::PathBuf, sync::Arc};
|
use std::{fmt::Debug, fs, iter::FromIterator, path::PathBuf, sync::Arc};
|
||||||
use tokio::{net::UnixStream, task::JoinHandle};
|
use tokio::{net::UnixStream, task::JoinHandle};
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
@@ -32,10 +34,11 @@ lazy_static! {
|
|||||||
disconnect_status: OnceCell::new(),
|
disconnect_status: OnceCell::new(),
|
||||||
|
|
||||||
message_sender_handle: None,
|
message_sender_handle: None,
|
||||||
|
id_counter: CounterU32::new(0),
|
||||||
scenegraph: Default::default(),
|
scenegraph: Default::default(),
|
||||||
root: OnceCell::new(),
|
root: OnceCell::new(),
|
||||||
base_resource_prefixes: Default::default(),
|
base_resource_prefixes: Default::default(),
|
||||||
state: Arc::new(ClientState::default()),
|
state: OnceCell::default(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +50,7 @@ pub fn get_env(pid: i32) -> Result<FxHashMap<String, String>, std::io::Error> {
|
|||||||
.map(|(k, v)| (k.to_string(), v.to_string())),
|
.map(|(k, v)| (k.to_string(), v.to_string())),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
pub fn state(env: &FxHashMap<String, String>) -> Option<Arc<ClientState>> {
|
pub fn state(env: &FxHashMap<String, String>) -> Option<Arc<ClientStateParsed>> {
|
||||||
let token = env.get("STARDUST_STARTUP_TOKEN")?;
|
let token = env.get("STARDUST_STARTUP_TOKEN")?;
|
||||||
CLIENT_STATES.lock().get(token).cloned()
|
CLIENT_STATES.lock().get(token).cloned()
|
||||||
}
|
}
|
||||||
@@ -60,11 +63,12 @@ pub struct Client {
|
|||||||
flush_join_handle: OnceCell<JoinHandle<Result<()>>>,
|
flush_join_handle: OnceCell<JoinHandle<Result<()>>>,
|
||||||
disconnect_status: OnceCell<Result<()>>,
|
disconnect_status: OnceCell<Result<()>>,
|
||||||
|
|
||||||
|
id_counter: CounterU32,
|
||||||
pub message_sender_handle: Option<MessageSenderHandle>,
|
pub message_sender_handle: Option<MessageSenderHandle>,
|
||||||
pub scenegraph: Arc<Scenegraph>,
|
pub scenegraph: Arc<Scenegraph>,
|
||||||
pub root: OnceCell<Arc<Root>>,
|
pub root: OnceCell<Arc<Root>>,
|
||||||
pub base_resource_prefixes: Mutex<Vec<PathBuf>>,
|
pub base_resource_prefixes: Mutex<Vec<PathBuf>>,
|
||||||
pub state: Arc<ClientState>,
|
pub state: OnceCell<ClientState>,
|
||||||
}
|
}
|
||||||
impl Client {
|
impl Client {
|
||||||
pub fn from_connection(connection: UnixStream) -> Result<Arc<Self>> {
|
pub fn from_connection(connection: UnixStream) -> Result<Arc<Self>> {
|
||||||
@@ -84,7 +88,7 @@ impl Client {
|
|||||||
let state = env
|
let state = env
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(state)
|
.and_then(state)
|
||||||
.unwrap_or_else(|| Arc::new(ClientState::default()));
|
.unwrap_or_else(|| Arc::new(ClientStateParsed::default()));
|
||||||
|
|
||||||
let client = CLIENTS.add(Client {
|
let client = CLIENTS.add(Client {
|
||||||
pid,
|
pid,
|
||||||
@@ -95,14 +99,15 @@ impl Client {
|
|||||||
flush_join_handle: OnceCell::new(),
|
flush_join_handle: OnceCell::new(),
|
||||||
disconnect_status: OnceCell::new(),
|
disconnect_status: OnceCell::new(),
|
||||||
|
|
||||||
|
id_counter: CounterU32::new(256),
|
||||||
message_sender_handle: Some(messenger_tx.handle()),
|
message_sender_handle: Some(messenger_tx.handle()),
|
||||||
scenegraph: scenegraph.clone(),
|
scenegraph: scenegraph.clone(),
|
||||||
root: OnceCell::new(),
|
root: OnceCell::new(),
|
||||||
base_resource_prefixes: Default::default(),
|
base_resource_prefixes: Default::default(),
|
||||||
state,
|
state: OnceCell::default(),
|
||||||
});
|
});
|
||||||
let _ = client.scenegraph.client.set(Arc::downgrade(&client));
|
let _ = client.scenegraph.client.set(Arc::downgrade(&client));
|
||||||
let _ = client.root.set(Root::create(&client)?);
|
let _ = client.root.set(Root::create(&client, state.root)?);
|
||||||
hmd::make_alias(&client)?;
|
hmd::make_alias(&client)?;
|
||||||
spatial::create_interface(&client)?;
|
spatial::create_interface(&client)?;
|
||||||
fields::create_interface(&client)?;
|
fields::create_interface(&client)?;
|
||||||
@@ -113,12 +118,7 @@ impl Client {
|
|||||||
items::camera::create_interface(&client)?;
|
items::camera::create_interface(&client)?;
|
||||||
items::panel::create_interface(&client)?;
|
items::panel::create_interface(&client)?;
|
||||||
|
|
||||||
client
|
let _ = client.state.set(state.apply_to(&client));
|
||||||
.root
|
|
||||||
.get()
|
|
||||||
.unwrap()
|
|
||||||
.node
|
|
||||||
.send_remote_signal("restore_state", serialize(client.state.apply_to(&client))?)?;
|
|
||||||
|
|
||||||
let pid_printable = pid
|
let pid_printable = pid
|
||||||
.map(|pid| pid.to_string())
|
.map(|pid| pid.to_string())
|
||||||
@@ -191,15 +191,19 @@ impl Client {
|
|||||||
let cwd_proc_path = format!("/proc/{pid}/cwd");
|
let cwd_proc_path = format!("/proc/{pid}/cwd");
|
||||||
std::fs::read_link(cwd_proc_path).ok()
|
std::fs::read_link(cwd_proc_path).ok()
|
||||||
}
|
}
|
||||||
pub async fn save_state(&self) -> Option<ClientState> {
|
pub async fn save_state(&self) -> Option<ClientStateParsed> {
|
||||||
let internal = self.root.get()?.save_state().await.ok()?;
|
let internal = self.root.get()?.save_state().await.ok()?;
|
||||||
Some(ClientState::from_deserialized(self, internal))
|
Some(ClientStateParsed::from_deserialized(self, internal))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_id(&self) -> u64 {
|
||||||
|
self.id_counter.inc() as u64
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_node(&self, name: &'static str, path: &str) -> Result<Arc<Node>> {
|
pub fn get_node(&self, name: &'static str, id: u64) -> Result<Arc<Node>> {
|
||||||
self.scenegraph
|
self.scenegraph
|
||||||
.get_node(path)
|
.get_node(id)
|
||||||
.ok_or_else(|| eyre!("{} not found", name))
|
.ok_or_else(|| eyre!("{} not found", name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use super::client::{get_env, Client};
|
use super::client::{get_env, Client};
|
||||||
use crate::nodes::{spatial::Spatial, Node};
|
use crate::nodes::{root::ClientState, spatial::Spatial, Node};
|
||||||
use glam::Mat4;
|
use glam::Mat4;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
@@ -11,7 +11,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
pub static ref CLIENT_STATES: Mutex<FxHashMap<String, Arc<ClientState>>> = Default::default();
|
pub static ref CLIENT_STATES: Mutex<FxHashMap<String, Arc<ClientStateParsed>>> = Default::default();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
@@ -31,28 +31,27 @@ impl LaunchInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct ClientState {
|
pub struct ClientStateParsed {
|
||||||
pub launch_info: Option<LaunchInfo>,
|
pub launch_info: Option<LaunchInfo>,
|
||||||
pub data: Vec<u8>,
|
pub data: Vec<u8>,
|
||||||
pub root: Mat4,
|
pub root: Mat4,
|
||||||
pub spatial_anchors: FxHashMap<String, Mat4>,
|
pub spatial_anchors: FxHashMap<String, Mat4>,
|
||||||
}
|
}
|
||||||
impl ClientState {
|
impl ClientStateParsed {
|
||||||
pub fn from_deserialized(client: &Client, state: ClientStateInternal) -> Self {
|
pub fn from_deserialized(client: &Client, state: ClientState) -> Self {
|
||||||
ClientState {
|
ClientStateParsed {
|
||||||
launch_info: LaunchInfo::from_client(client),
|
launch_info: LaunchInfo::from_client(client),
|
||||||
data: state.data.unwrap_or_default(),
|
data: state.data.unwrap_or_default(),
|
||||||
root: Self::spatial_transform(client, &state.root.unwrap_or_default())
|
root: Self::spatial_transform(client, state.root).unwrap_or_default(),
|
||||||
.unwrap_or_default(),
|
|
||||||
spatial_anchors: state
|
spatial_anchors: state
|
||||||
.spatial_anchors
|
.spatial_anchors
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|(k, v)| Some((k, Self::spatial_transform(client, &v)?)))
|
.filter_map(|(k, v)| Some((k, Self::spatial_transform(client, v)?)))
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn spatial_transform(client: &Client, path: &str) -> Option<Mat4> {
|
fn spatial_transform(client: &Client, id: u64) -> Option<Mat4> {
|
||||||
let node = client.scenegraph.get_node(path)?;
|
let node = client.scenegraph.get_node(id)?;
|
||||||
let spatial = node.get_aspect::<Spatial>().ok()?;
|
let spatial = node.get_aspect::<Spatial>().ok()?;
|
||||||
Some(spatial.global_transform())
|
Some(spatial.global_transform())
|
||||||
}
|
}
|
||||||
@@ -79,24 +78,20 @@ impl ClientState {
|
|||||||
std::fs::write(state_file_path, toml::to_string(&self).unwrap()).unwrap();
|
std::fs::write(state_file_path, toml::to_string(&self).unwrap()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_to(&self, client: &Arc<Client>) -> ClientStateInternal {
|
pub fn apply_to(&self, client: &Arc<Client>) -> ClientState {
|
||||||
if let Some(root) = client.root.get() {
|
if let Some(root) = client.root.get() {
|
||||||
root.set_transform(self.root)
|
root.set_transform(self.root)
|
||||||
}
|
}
|
||||||
ClientStateInternal {
|
ClientState {
|
||||||
data: Some(self.data.clone()),
|
data: Some(self.data.clone()),
|
||||||
root: Some("/".to_string()),
|
root: 0,
|
||||||
spatial_anchors: self
|
spatial_anchors: self
|
||||||
.spatial_anchors
|
.spatial_anchors
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(k, v)| {
|
.map(|(k, v)| {
|
||||||
(k.clone(), {
|
let node = Node::generate(client, true).add_to_scenegraph().unwrap();
|
||||||
let node = Node::create_parent_name(client, "/spatial/anchor", k, true)
|
|
||||||
.add_to_scenegraph()
|
|
||||||
.unwrap();
|
|
||||||
Spatial::add_to(&node, None, *v, false);
|
Spatial::add_to(&node, None, *v, false);
|
||||||
k.clone()
|
(k.clone(), node.get_id())
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
}
|
||||||
@@ -112,7 +107,7 @@ impl ClientState {
|
|||||||
Some(command)
|
Some(command)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Default for ClientState {
|
impl Default for ClientStateParsed {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
launch_info: None,
|
launch_info: None,
|
||||||
@@ -122,10 +117,3 @@ impl Default for ClientState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Serialize, Deserialize)]
|
|
||||||
pub struct ClientStateInternal {
|
|
||||||
data: Option<Vec<u8>>,
|
|
||||||
root: Option<String>,
|
|
||||||
spatial_anchors: FxHashMap<String, String>,
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! create_interface {
|
macro_rules! create_interface {
|
||||||
($iface:ident, $aspect:ident, $path:expr) => {
|
($iface:ident) => {
|
||||||
pub fn create_interface(client: &Arc<Client>) -> Result<()> {
|
pub fn create_interface(client: &Arc<Client>) -> Result<()> {
|
||||||
let node = Node::create_path(client, $path, false);
|
let node = Node::from_id(client, INTERFACE_NODE_ID, false);
|
||||||
<$iface as $aspect>::add_node_members(&node);
|
<$iface as self::InterfaceAspect>::add_node_members(&node);
|
||||||
node.add_to_scenegraph()?;
|
node.add_to_scenegraph()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ pub mod delta;
|
|||||||
pub mod destroy_queue;
|
pub mod destroy_queue;
|
||||||
pub mod eventloop;
|
pub mod eventloop;
|
||||||
pub mod idl_utils;
|
pub mod idl_utils;
|
||||||
pub mod node_collections;
|
|
||||||
pub mod registry;
|
pub mod registry;
|
||||||
pub mod resource;
|
pub mod resource;
|
||||||
pub mod scenegraph;
|
pub mod scenegraph;
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
use crate::nodes::Node;
|
|
||||||
use parking_lot::Mutex;
|
|
||||||
use rustc_hash::FxHashMap;
|
|
||||||
use std::{
|
|
||||||
borrow::Borrow,
|
|
||||||
hash::Hash,
|
|
||||||
sync::{Arc, Weak},
|
|
||||||
};
|
|
||||||
|
|
||||||
// #[derive(Default)]
|
|
||||||
// pub struct LifeLinkedNodeList {
|
|
||||||
// nodes: Mutex<Vec<Weak<Node>>>,
|
|
||||||
// }
|
|
||||||
// impl LifeLinkedNodeList {
|
|
||||||
// pub fn add(&self, node: Weak<Node>) {
|
|
||||||
// self.nodes.lock().push(node);
|
|
||||||
// }
|
|
||||||
// pub fn clear(&self) {
|
|
||||||
// self.nodes
|
|
||||||
// .lock()
|
|
||||||
// .iter()
|
|
||||||
// .filter_map(|node| node.upgrade())
|
|
||||||
// .for_each(|node| {
|
|
||||||
// node.destroy();
|
|
||||||
// });
|
|
||||||
// self.nodes.lock().clear();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// impl Drop for LifeLinkedNodeList {
|
|
||||||
// fn drop(&mut self) {
|
|
||||||
// self.clear();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
|
||||||
pub struct LifeLinkedNodeMap<K: Hash + Eq> {
|
|
||||||
nodes: Mutex<FxHashMap<K, Weak<Node>>>,
|
|
||||||
}
|
|
||||||
#[allow(dead_code)]
|
|
||||||
impl<K: Hash + Eq> LifeLinkedNodeMap<K> {
|
|
||||||
pub fn add(&self, key: K, node: &Arc<Node>) {
|
|
||||||
self.nodes.lock().insert(key, Arc::downgrade(node));
|
|
||||||
}
|
|
||||||
pub fn get<Q>(&self, key: &Q) -> Option<Arc<Node>>
|
|
||||||
where
|
|
||||||
Q: ?Sized,
|
|
||||||
K: Borrow<Q>,
|
|
||||||
Q: Hash + Eq,
|
|
||||||
{
|
|
||||||
self.nodes.lock().get(key).and_then(|n| n.upgrade())
|
|
||||||
}
|
|
||||||
pub fn nodes(&self) -> Vec<Arc<Node>> {
|
|
||||||
self.nodes
|
|
||||||
.lock()
|
|
||||||
.values()
|
|
||||||
.filter_map(|v| v.upgrade())
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
pub fn remove<Q>(&self, key: &Q) -> Option<Arc<Node>>
|
|
||||||
where
|
|
||||||
Q: ?Sized,
|
|
||||||
K: Borrow<Q>,
|
|
||||||
Q: Hash + Eq,
|
|
||||||
{
|
|
||||||
self.nodes.lock().remove(key).and_then(|n| n.upgrade())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear(&self) {
|
|
||||||
let mut nodes = self.nodes.lock();
|
|
||||||
nodes
|
|
||||||
.values()
|
|
||||||
.filter_map(|node| node.upgrade())
|
|
||||||
.for_each(|node| {
|
|
||||||
node.destroy();
|
|
||||||
});
|
|
||||||
nodes.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<K: Hash + Eq> Drop for LifeLinkedNodeMap<K> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
self.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -33,12 +33,38 @@ impl<T: Send + Sync + ?Sized> Registry<T> {
|
|||||||
self.lock()
|
self.lock()
|
||||||
.contains_key(&(ptr::addr_of!(*t) as *const () as usize))
|
.contains_key(&(ptr::addr_of!(*t) as *const () as usize))
|
||||||
}
|
}
|
||||||
|
pub fn get_changes(old: &Registry<T>, new: &Registry<T>) -> (Vec<Arc<T>>, Vec<Arc<T>>) {
|
||||||
|
let old = old.lock();
|
||||||
|
let new = new.lock();
|
||||||
|
|
||||||
|
let mut added = Vec::new();
|
||||||
|
let mut removed = Vec::new();
|
||||||
|
|
||||||
|
for (id, entry) in new.iter() {
|
||||||
|
if let Some(entry) = entry.upgrade() {
|
||||||
|
if !old.contains_key(id) {
|
||||||
|
added.push(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (id, entry) in old.iter() {
|
||||||
|
if let Some(entry) = entry.upgrade() {
|
||||||
|
if !new.contains_key(id) {
|
||||||
|
removed.push(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(added, removed)
|
||||||
|
}
|
||||||
pub fn get_valid_contents(&self) -> Vec<Arc<T>> {
|
pub fn get_valid_contents(&self) -> Vec<Arc<T>> {
|
||||||
self.lock()
|
self.lock()
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|pair| pair.1.upgrade())
|
.filter_map(|pair| pair.1.upgrade())
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
pub fn set(&self, other: &Registry<T>) {
|
||||||
|
*self.lock() = other.lock().clone();
|
||||||
|
}
|
||||||
pub fn take_valid_contents(&self) -> Vec<Arc<T>> {
|
pub fn take_valid_contents(&self) -> Vec<Arc<T>> {
|
||||||
self.0
|
self.0
|
||||||
.lock()
|
.lock()
|
||||||
@@ -48,6 +74,14 @@ impl<T: Send + Sync + ?Sized> Registry<T> {
|
|||||||
.filter_map(|pair| pair.1.upgrade())
|
.filter_map(|pair| pair.1.upgrade())
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
pub fn retain<F: Fn(&T) -> bool>(&self, f: F) {
|
||||||
|
self.lock().retain(|_, v| {
|
||||||
|
let Some(v) = v.upgrade() else {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
(f)(&v)
|
||||||
|
})
|
||||||
|
}
|
||||||
pub fn remove(&self, t: &T) {
|
pub fn remove(&self, t: &T) {
|
||||||
self.lock()
|
self.lock()
|
||||||
.remove(&(ptr::addr_of!(*t) as *const () as usize));
|
.remove(&(ptr::addr_of!(*t) as *const () as usize));
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ use tracing::{debug, debug_span};
|
|||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Scenegraph {
|
pub struct Scenegraph {
|
||||||
pub(super) client: OnceCell<Weak<Client>>,
|
pub(super) client: OnceCell<Weak<Client>>,
|
||||||
nodes: Mutex<FxHashMap<String, Arc<Node>>>,
|
nodes: Mutex<FxHashMap<u64, Arc<Node>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scenegraph {
|
impl Scenegraph {
|
||||||
@@ -34,12 +34,11 @@ impl Scenegraph {
|
|||||||
}
|
}
|
||||||
pub fn add_node_raw(&self, node: Arc<Node>) {
|
pub fn add_node_raw(&self, node: Arc<Node>) {
|
||||||
debug!(node = ?&*node, "Add node");
|
debug!(node = ?&*node, "Add node");
|
||||||
let path = node.get_path().to_string();
|
self.nodes.lock().insert(node.get_id(), node);
|
||||||
self.nodes.lock().insert(path, node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_node(&self, path: &str) -> Option<Arc<Node>> {
|
pub fn get_node(&self, node: u64) -> Option<Arc<Node>> {
|
||||||
let mut node = self.nodes.lock().get(path)?.clone();
|
let mut node = self.nodes.lock().get(&node)?.clone();
|
||||||
while let Ok(alias) = node.get_aspect::<Alias>() {
|
while let Ok(alias) = node.get_aspect::<Alias>() {
|
||||||
if alias.enabled.load(Ordering::Acquire) {
|
if alias.enabled.load(Ordering::Acquire) {
|
||||||
node = alias.original.upgrade()?;
|
node = alias.original.upgrade()?;
|
||||||
@@ -50,9 +49,9 @@ impl Scenegraph {
|
|||||||
Some(node)
|
Some(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_node(&self, path: &str) -> Option<Arc<Node>> {
|
pub fn remove_node(&self, node: u64) -> Option<Arc<Node>> {
|
||||||
debug!(path, "Remove node");
|
debug!(node, "Remove node");
|
||||||
self.nodes.lock().remove(path)
|
self.nodes.lock().remove(&node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,16 +93,16 @@ fn map_method_return<T: Serialize>(
|
|||||||
impl scenegraph::Scenegraph for Scenegraph {
|
impl scenegraph::Scenegraph for Scenegraph {
|
||||||
fn send_signal(
|
fn send_signal(
|
||||||
&self,
|
&self,
|
||||||
path: &str,
|
node: u64,
|
||||||
method: &str,
|
method: u64,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
fds: Vec<OwnedFd>,
|
fds: Vec<OwnedFd>,
|
||||||
) -> Result<(), ScenegraphError> {
|
) -> Result<(), ScenegraphError> {
|
||||||
let Some(client) = self.get_client() else {
|
let Some(client) = self.get_client() else {
|
||||||
return Err(ScenegraphError::SignalNotFound);
|
return Err(ScenegraphError::SignalNotFound);
|
||||||
};
|
};
|
||||||
debug_span!("Handle signal", path, method).in_scope(|| {
|
debug_span!("Handle signal", node, method).in_scope(|| {
|
||||||
self.get_node(path)
|
self.get_node(node)
|
||||||
.ok_or(ScenegraphError::NodeNotFound)?
|
.ok_or(ScenegraphError::NodeNotFound)?
|
||||||
.send_local_signal(
|
.send_local_signal(
|
||||||
client,
|
client,
|
||||||
@@ -117,8 +116,8 @@ impl scenegraph::Scenegraph for Scenegraph {
|
|||||||
}
|
}
|
||||||
fn execute_method(
|
fn execute_method(
|
||||||
&self,
|
&self,
|
||||||
path: &str,
|
node: u64,
|
||||||
method: &str,
|
method: u64,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
fds: Vec<OwnedFd>,
|
fds: Vec<OwnedFd>,
|
||||||
response: oneshot::Sender<Result<(Vec<u8>, Vec<OwnedFd>), ScenegraphError>>,
|
response: oneshot::Sender<Result<(Vec<u8>, Vec<OwnedFd>), ScenegraphError>>,
|
||||||
@@ -127,8 +126,8 @@ impl scenegraph::Scenegraph for Scenegraph {
|
|||||||
let _ = response.send(Err(ScenegraphError::MethodNotFound));
|
let _ = response.send(Err(ScenegraphError::MethodNotFound));
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
debug!(path, method, "Handle method");
|
debug!(node, method, "Handle method");
|
||||||
let Some(node) = self.get_node(path) else {
|
let Some(node) = self.get_node(node) else {
|
||||||
let _ = response.send(Err(ScenegraphError::NodeNotFound));
|
let _ = response.send(Err(ScenegraphError::NodeNotFound));
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use crate::wayland::X_DISPLAY;
|
|||||||
|
|
||||||
use self::core::eventloop::EventLoop;
|
use self::core::eventloop::EventLoop;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use core::client_state::ClientState;
|
use core::client_state::ClientStateParsed;
|
||||||
use directories::ProjectDirs;
|
use directories::ProjectDirs;
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use stardust_xr::server;
|
use stardust_xr::server;
|
||||||
@@ -364,8 +364,8 @@ fn restore_session(
|
|||||||
};
|
};
|
||||||
clients
|
clients
|
||||||
.filter_map(Result::ok)
|
.filter_map(Result::ok)
|
||||||
.filter_map(|c| ClientState::from_file(&c.path()))
|
.filter_map(|c| ClientStateParsed::from_file(&c.path()))
|
||||||
.filter_map(ClientState::launch_command)
|
.filter_map(ClientStateParsed::launch_command)
|
||||||
.filter_map(|startup_command| {
|
.filter_map(|startup_command| {
|
||||||
run_client(
|
run_client(
|
||||||
startup_command,
|
startup_command,
|
||||||
|
|||||||
@@ -1,17 +1,28 @@
|
|||||||
use super::{Aspect, Node};
|
use super::{Aspect, Node};
|
||||||
use crate::core::client::Client;
|
use crate::core::{client::Client, registry::Registry};
|
||||||
use color_eyre::eyre::{ensure, Result};
|
use color_eyre::eyre::Result;
|
||||||
use portable_atomic::AtomicBool;
|
use portable_atomic::AtomicBool;
|
||||||
use std::sync::{Arc, Weak};
|
use std::{
|
||||||
|
ops::Add,
|
||||||
|
sync::{Arc, Weak},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct AliasInfo {
|
pub struct AliasInfo {
|
||||||
pub(super) server_signals: Vec<&'static str>,
|
pub(super) server_signals: Vec<u64>,
|
||||||
pub(super) server_methods: Vec<&'static str>,
|
pub(super) server_methods: Vec<u64>,
|
||||||
pub(super) client_signals: Vec<&'static str>,
|
pub(super) client_signals: Vec<u64>,
|
||||||
|
}
|
||||||
|
impl Add for AliasInfo {
|
||||||
|
type Output = AliasInfo;
|
||||||
|
fn add(mut self, mut rhs: Self) -> Self::Output {
|
||||||
|
self.server_signals.append(&mut rhs.server_signals);
|
||||||
|
self.server_methods.append(&mut rhs.server_methods);
|
||||||
|
self.client_signals.append(&mut rhs.client_signals);
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub struct Alias {
|
pub struct Alias {
|
||||||
pub enabled: Arc<AtomicBool>,
|
pub enabled: Arc<AtomicBool>,
|
||||||
pub(super) node: Weak<Node>,
|
pub(super) node: Weak<Node>,
|
||||||
@@ -21,32 +32,86 @@ pub struct Alias {
|
|||||||
}
|
}
|
||||||
impl Alias {
|
impl Alias {
|
||||||
pub fn create(
|
pub fn create(
|
||||||
client: &Arc<Client>,
|
|
||||||
parent: &str,
|
|
||||||
name: &str,
|
|
||||||
original: &Arc<Node>,
|
original: &Arc<Node>,
|
||||||
|
client: &Arc<Client>,
|
||||||
info: AliasInfo,
|
info: AliasInfo,
|
||||||
|
list: Option<&AliasList>,
|
||||||
) -> Result<Arc<Node>> {
|
) -> Result<Arc<Node>> {
|
||||||
ensure!(
|
let node = Node::generate(client, true).add_to_scenegraph()?;
|
||||||
client
|
Self::add_to(&node, original, info)?;
|
||||||
.scenegraph
|
if let Some(list) = list {
|
||||||
.get_node(&(parent.to_string() + "/" + name))
|
list.add(&node);
|
||||||
.is_none(),
|
}
|
||||||
"Node already exists"
|
Ok(node)
|
||||||
);
|
}
|
||||||
|
pub fn create_with_id(
|
||||||
|
original: &Arc<Node>,
|
||||||
|
client: &Arc<Client>,
|
||||||
|
new_id: u64,
|
||||||
|
info: AliasInfo,
|
||||||
|
list: Option<&AliasList>,
|
||||||
|
) -> Result<Arc<Node>> {
|
||||||
|
let node = Node::from_id(client, new_id, true).add_to_scenegraph()?;
|
||||||
|
Self::add_to(&node, original, info)?;
|
||||||
|
if let Some(list) = list {
|
||||||
|
list.add(&node);
|
||||||
|
}
|
||||||
|
Ok(node)
|
||||||
|
}
|
||||||
|
|
||||||
let node = Node::create_parent_name(client, parent, name, true).add_to_scenegraph()?;
|
fn add_to(new_node: &Arc<Node>, original: &Arc<Node>, info: AliasInfo) -> Result<()> {
|
||||||
let alias = Alias {
|
let alias = Alias {
|
||||||
enabled: Arc::new(AtomicBool::new(true)),
|
enabled: Arc::new(AtomicBool::new(true)),
|
||||||
node: Arc::downgrade(&node),
|
node: Arc::downgrade(&new_node),
|
||||||
original: Arc::downgrade(original),
|
original: Arc::downgrade(original),
|
||||||
info,
|
info,
|
||||||
};
|
};
|
||||||
let alias = original.aliases.add(alias);
|
let alias = original.aliases.add(alias);
|
||||||
node.add_aspect_raw(alias);
|
new_node.add_aspect_raw(alias);
|
||||||
Ok(node)
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Aspect for Alias {
|
impl Aspect for Alias {
|
||||||
const NAME: &'static str = "Alias";
|
const NAME: &'static str = "Alias";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_original(node: Arc<Node>) -> Option<Arc<Node>> {
|
||||||
|
let Ok(alias) = node.get_aspect::<Alias>() else {
|
||||||
|
return Some(node);
|
||||||
|
};
|
||||||
|
get_original(alias.original.upgrade()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
pub struct AliasList(Registry<Node>);
|
||||||
|
impl AliasList {
|
||||||
|
fn add(&self, node: &Arc<Node>) {
|
||||||
|
self.0.add_raw(node);
|
||||||
|
}
|
||||||
|
pub fn get<A: Aspect>(&self, aspect: &A) -> Option<Arc<Node>> {
|
||||||
|
self.0.get_valid_contents().into_iter().find(|node| {
|
||||||
|
let Ok(aspect2) = node.get_aspect::<A>() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
Arc::as_ptr(&aspect2) != (aspect as *const A)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pub fn get_aliases(&self) -> Vec<Arc<Node>> {
|
||||||
|
self.0.get_valid_contents()
|
||||||
|
}
|
||||||
|
pub fn remove_aspect<A: Aspect>(&self, aspect: &A) {
|
||||||
|
self.0.retain(|node| {
|
||||||
|
let Ok(aspect2) = node.get_aspect::<A>() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
Arc::as_ptr(&aspect2) != (aspect as *const A)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Drop for AliasList {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
for node in self.0.take_valid_contents() {
|
||||||
|
node.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -101,20 +101,19 @@ pub fn update() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
create_interface!(AudioInterface, AudioInterfaceAspect, "/audio");
|
create_interface!(AudioInterface);
|
||||||
struct AudioInterface;
|
struct AudioInterface;
|
||||||
impl AudioInterfaceAspect for AudioInterface {
|
impl InterfaceAspect for AudioInterface {
|
||||||
#[doc = "Create a sound node. WAV and MP3 are supported."]
|
#[doc = "Create a sound node. WAV and MP3 are supported."]
|
||||||
fn create_sound(
|
fn create_sound(
|
||||||
_node: Arc<Node>,
|
_node: Arc<Node>,
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
name: String,
|
id: u64,
|
||||||
parent: Arc<Node>,
|
parent: Arc<Node>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
resource: ResourceID,
|
resource: ResourceID,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let node =
|
let node = Node::from_id(&calling_client, id, true);
|
||||||
Node::create_parent_name(&calling_client, Self::CREATE_SOUND_PARENT_PATH, &name, true);
|
|
||||||
let parent = parent.get_aspect::<Spatial>()?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let transform = transform.to_mat4(true, true, true);
|
let transform = transform.to_mat4(true, true, true);
|
||||||
let node = node.add_to_scenegraph()?;
|
let node = node.add_to_scenegraph()?;
|
||||||
|
|||||||
@@ -1,24 +1,22 @@
|
|||||||
use super::alias::AliasInfo;
|
use super::alias::AliasList;
|
||||||
use super::fields::Field;
|
use super::fields::Field;
|
||||||
use super::spatial::{parse_transform, Spatial};
|
use super::spatial::{parse_transform, Spatial};
|
||||||
use super::{Alias, Aspect, Node};
|
use super::{Alias, Aspect, Node};
|
||||||
use crate::core::client::Client;
|
use crate::core::client::Client;
|
||||||
use crate::core::node_collections::LifeLinkedNodeMap;
|
|
||||||
use crate::core::registry::Registry;
|
use crate::core::registry::Registry;
|
||||||
use crate::create_interface;
|
use crate::create_interface;
|
||||||
use crate::nodes::fields::FIELD_ALIAS_INFO;
|
use crate::nodes::fields::FIELD_ALIAS_INFO;
|
||||||
use crate::nodes::spatial::Transform;
|
use crate::nodes::spatial::Transform;
|
||||||
use color_eyre::eyre::{bail, ensure, eyre, Result};
|
use color_eyre::eyre::{bail, ensure, eyre, Result};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use nanoid::nanoid;
|
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use rustc_hash::FxHashMap;
|
use slotmap::{DefaultKey, Key, KeyData, SlotMap};
|
||||||
use stardust_xr::schemas::flex::flexbuffers;
|
use stardust_xr::schemas::flex::flexbuffers;
|
||||||
use stardust_xr::values::Datamap;
|
use stardust_xr::values::Datamap;
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref KEYMAPS: Mutex<FxHashMap<String, String>> = Mutex::new(FxHashMap::default());
|
pub static ref KEYMAPS: Mutex<SlotMap<DefaultKey, String>> = Mutex::new(SlotMap::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
static PULSE_SENDER_REGISTRY: Registry<PulseSender> = Registry::new();
|
static PULSE_SENDER_REGISTRY: Registry<PulseSender> = Registry::new();
|
||||||
@@ -58,14 +56,16 @@ stardust_xr_server_codegen::codegen_data_protocol!();
|
|||||||
pub struct PulseSender {
|
pub struct PulseSender {
|
||||||
node: Weak<Node>,
|
node: Weak<Node>,
|
||||||
pub mask: Datamap,
|
pub mask: Datamap,
|
||||||
aliases: LifeLinkedNodeMap<String>,
|
aliases: AliasList,
|
||||||
|
field_aliases: AliasList,
|
||||||
}
|
}
|
||||||
impl PulseSender {
|
impl PulseSender {
|
||||||
pub fn add_to(node: &Arc<Node>, mask: Datamap) -> Result<Arc<PulseSender>> {
|
pub fn add_to(node: &Arc<Node>, mask: Datamap) -> Result<Arc<PulseSender>> {
|
||||||
let sender = PulseSender {
|
let sender = PulseSender {
|
||||||
node: Arc::downgrade(node),
|
node: Arc::downgrade(node),
|
||||||
mask,
|
mask,
|
||||||
aliases: LifeLinkedNodeMap::default(),
|
aliases: AliasList::default(),
|
||||||
|
field_aliases: AliasList::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// <PulseSender as PulseSenderAspect>::add_node_members(node);
|
// <PulseSender as PulseSenderAspect>::add_node_members(node);
|
||||||
@@ -91,44 +91,41 @@ impl PulseSender {
|
|||||||
};
|
};
|
||||||
// Receiver itself
|
// Receiver itself
|
||||||
let Ok(rx_alias) = Alias::create(
|
let Ok(rx_alias) = Alias::create(
|
||||||
&tx_client,
|
|
||||||
tx_node.get_path(),
|
|
||||||
receiver.uid.as_str(),
|
|
||||||
&rx_node,
|
&rx_node,
|
||||||
AliasInfo {
|
&tx_client,
|
||||||
server_methods: vec!["send_data"],
|
PULSE_RECEIVER_ASPECT_ALIAS_INFO.clone(),
|
||||||
..Default::default()
|
Some(&self.aliases),
|
||||||
},
|
|
||||||
) else {
|
) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
self.aliases.add(receiver.uid.clone(), &rx_alias);
|
|
||||||
|
|
||||||
// Receiver's field
|
// Receiver's field
|
||||||
let Ok(rx_field_alias) = Alias::create(
|
let Ok(rx_field_alias) = Alias::create(
|
||||||
|
&rx_node
|
||||||
|
.get_aspect::<PulseReceiver>()
|
||||||
|
.unwrap()
|
||||||
|
.field
|
||||||
|
.spatial_ref()
|
||||||
|
.node()
|
||||||
|
.unwrap(),
|
||||||
&tx_client,
|
&tx_client,
|
||||||
rx_alias.get_path(),
|
|
||||||
"field",
|
|
||||||
&rx_node.get_aspect::<PulseReceiver>().unwrap().field_node,
|
|
||||||
FIELD_ALIAS_INFO.clone(),
|
FIELD_ALIAS_INFO.clone(),
|
||||||
|
Some(&self.aliases),
|
||||||
) else {
|
) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
self.aliases
|
|
||||||
.add(receiver.uid.clone() + "-field", &rx_field_alias);
|
|
||||||
|
|
||||||
let _ =
|
let _ = pulse_sender_client::new_receiver(&tx_node, &rx_alias, &rx_field_alias);
|
||||||
pulse_sender_client::new_receiver(&tx_node, &receiver.uid, &rx_alias, &rx_field_alias);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_drop_receiver(&self, receiver: &PulseReceiver) {
|
fn handle_drop_receiver(&self, receiver: &PulseReceiver) {
|
||||||
let uid = receiver.uid.as_str();
|
let id = receiver.node.upgrade().unwrap().get_id();
|
||||||
self.aliases.remove(uid);
|
self.aliases.remove_aspect(receiver);
|
||||||
self.aliases.remove(&(uid.to_string() + "-field"));
|
self.field_aliases.remove_aspect(receiver.field.as_ref());
|
||||||
let Some(tx_node) = self.node.upgrade() else {
|
let Some(tx_node) = self.node.upgrade() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let _ = pulse_sender_client::drop_receiver(&tx_node, uid);
|
let _ = pulse_sender_client::drop_receiver(&tx_node, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Aspect for PulseSender {
|
impl Aspect for PulseSender {
|
||||||
@@ -142,21 +139,19 @@ impl Drop for PulseSender {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct PulseReceiver {
|
pub struct PulseReceiver {
|
||||||
uid: String,
|
|
||||||
pub node: Weak<Node>,
|
pub node: Weak<Node>,
|
||||||
pub field_node: Arc<Node>,
|
pub field: Arc<Field>,
|
||||||
pub mask: Datamap,
|
pub mask: Datamap,
|
||||||
}
|
}
|
||||||
impl PulseReceiver {
|
impl PulseReceiver {
|
||||||
pub fn add_to(
|
pub fn add_to(
|
||||||
node: &Arc<Node>,
|
node: &Arc<Node>,
|
||||||
field_node: Arc<Node>,
|
field: Arc<Field>,
|
||||||
mask: Datamap,
|
mask: Datamap,
|
||||||
) -> Result<Arc<PulseReceiver>> {
|
) -> Result<Arc<PulseReceiver>> {
|
||||||
let receiver = PulseReceiver {
|
let receiver = PulseReceiver {
|
||||||
uid: nanoid!(),
|
|
||||||
node: Arc::downgrade(node),
|
node: Arc::downgrade(node),
|
||||||
field_node,
|
field,
|
||||||
mask,
|
mask,
|
||||||
};
|
};
|
||||||
let receiver = PULSE_RECEIVER_REGISTRY.add(receiver);
|
let receiver = PULSE_RECEIVER_REGISTRY.add(receiver);
|
||||||
@@ -186,7 +181,7 @@ impl PulseReceiverAspect for PulseReceiver {
|
|||||||
"Message ({data:?}) does not contain the same keys as the receiver's mask ({:?})",
|
"Message ({data:?}) does not contain the same keys as the receiver's mask ({:?})",
|
||||||
this_receiver.mask
|
this_receiver.mask
|
||||||
);
|
);
|
||||||
pulse_receiver_client::data(&node, &sender.uid, &data)?;
|
pulse_receiver_client::data(&node, &sender, &data)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -199,24 +194,19 @@ impl Drop for PulseReceiver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
create_interface!(DataInterface, DataInterfaceAspect, "/data");
|
create_interface!(DataInterface);
|
||||||
struct DataInterface;
|
struct DataInterface;
|
||||||
impl DataInterfaceAspect for DataInterface {
|
impl InterfaceAspect for DataInterface {
|
||||||
fn create_pulse_sender(
|
fn create_pulse_sender(
|
||||||
_node: Arc<Node>,
|
_node: Arc<Node>,
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
name: String,
|
id: u64,
|
||||||
parent: Arc<Node>,
|
parent: Arc<Node>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
mask: Datamap,
|
mask: Datamap,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
get_mask(&mask)?;
|
get_mask(&mask)?;
|
||||||
let node = Node::create_parent_name(
|
let node = Node::from_id(&calling_client, id, true);
|
||||||
&calling_client,
|
|
||||||
Self::CREATE_PULSE_SENDER_PARENT_PATH,
|
|
||||||
&name,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
let parent = parent.get_aspect::<Spatial>()?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let transform = transform.to_mat4(true, true, false);
|
let transform = transform.to_mat4(true, true, false);
|
||||||
|
|
||||||
@@ -229,22 +219,17 @@ impl DataInterfaceAspect for DataInterface {
|
|||||||
fn create_pulse_receiver(
|
fn create_pulse_receiver(
|
||||||
_node: Arc<Node>,
|
_node: Arc<Node>,
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
name: String,
|
id: u64,
|
||||||
parent: Arc<Node>,
|
parent: Arc<Node>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
field: Arc<Node>,
|
field: Arc<Node>,
|
||||||
mask: Datamap,
|
mask: Datamap,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
get_mask(&mask)?;
|
get_mask(&mask)?;
|
||||||
let node = Node::create_parent_name(
|
let node = Node::from_id(&calling_client, id, true);
|
||||||
&calling_client,
|
|
||||||
Self::CREATE_PULSE_RECEIVER_PARENT_PATH,
|
|
||||||
&name,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
let parent = parent.get_aspect::<Spatial>()?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let transform = parse_transform(transform, true, true, false);
|
let transform = parse_transform(transform, true, true, false);
|
||||||
let _ = field.get_aspect::<Field>()?;
|
let field = field.get_aspect::<Field>()?;
|
||||||
|
|
||||||
let node = node.add_to_scenegraph()?;
|
let node = node.add_to_scenegraph()?;
|
||||||
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||||
@@ -256,7 +241,7 @@ impl DataInterfaceAspect for DataInterface {
|
|||||||
_node: Arc<Node>,
|
_node: Arc<Node>,
|
||||||
_calling_client: Arc<Client>,
|
_calling_client: Arc<Client>,
|
||||||
keymap: String,
|
keymap: String,
|
||||||
) -> Result<String> {
|
) -> Result<u64> {
|
||||||
let mut keymaps = KEYMAPS.lock();
|
let mut keymaps = KEYMAPS.lock();
|
||||||
if let Some(found_keymap_id) = keymaps
|
if let Some(found_keymap_id) = keymaps
|
||||||
.iter()
|
.iter()
|
||||||
@@ -264,22 +249,20 @@ impl DataInterfaceAspect for DataInterface {
|
|||||||
.map(|(k, _v)| k)
|
.map(|(k, _v)| k)
|
||||||
.last()
|
.last()
|
||||||
{
|
{
|
||||||
return Ok(found_keymap_id.clone());
|
return Ok(found_keymap_id.data().as_ffi());
|
||||||
}
|
}
|
||||||
|
|
||||||
let generated_id = nanoid!();
|
let key = keymaps.insert(keymap);
|
||||||
keymaps.insert(generated_id.clone(), keymap);
|
Ok(key.data().as_ffi())
|
||||||
|
|
||||||
Ok(generated_id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_keymap(
|
async fn get_keymap(
|
||||||
_node: Arc<Node>,
|
_node: Arc<Node>,
|
||||||
_calling_client: Arc<Client>,
|
_calling_client: Arc<Client>,
|
||||||
keymap_id: String,
|
keymap_id: u64,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let keymaps = KEYMAPS.lock();
|
let keymaps = KEYMAPS.lock();
|
||||||
let Some(keymap) = keymaps.get(&keymap_id) else {
|
let Some(keymap) = keymaps.get(KeyData::from_ffi(keymap_id).into()) else {
|
||||||
bail!("Could not find keymap. Try registering it")
|
bail!("Could not find keymap. Try registering it")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -40,10 +40,10 @@ static QUEUED_SKYLIGHT: Mutex<Option<PathBuf>> = Mutex::new(None);
|
|||||||
static QUEUED_SKYTEX: Mutex<Option<PathBuf>> = Mutex::new(None);
|
static QUEUED_SKYTEX: Mutex<Option<PathBuf>> = Mutex::new(None);
|
||||||
|
|
||||||
stardust_xr_server_codegen::codegen_drawable_protocol!();
|
stardust_xr_server_codegen::codegen_drawable_protocol!();
|
||||||
create_interface!(DrawableInterface, DrawableInterfaceAspect, "/drawable");
|
create_interface!(DrawableInterface);
|
||||||
|
|
||||||
pub struct DrawableInterface;
|
pub struct DrawableInterface;
|
||||||
impl DrawableInterfaceAspect for DrawableInterface {
|
impl InterfaceAspect for DrawableInterface {
|
||||||
fn set_sky_tex(_node: Arc<Node>, calling_client: Arc<Client>, tex: ResourceID) -> Result<()> {
|
fn set_sky_tex(_node: Arc<Node>, calling_client: Arc<Client>, tex: ResourceID) -> Result<()> {
|
||||||
let resource_path = get_resource_file(&tex, &calling_client, &[OsStr::new("hdr")])
|
let resource_path = get_resource_file(&tex, &calling_client, &[OsStr::new("hdr")])
|
||||||
.ok_or(eyre::eyre!("Could not find resource"))?;
|
.ok_or(eyre::eyre!("Could not find resource"))?;
|
||||||
@@ -65,13 +65,12 @@ impl DrawableInterfaceAspect for DrawableInterface {
|
|||||||
fn create_lines(
|
fn create_lines(
|
||||||
_node: Arc<Node>,
|
_node: Arc<Node>,
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
name: String,
|
id: u64,
|
||||||
parent: Arc<Node>,
|
parent: Arc<Node>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
lines: Vec<Line>,
|
lines: Vec<Line>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let node =
|
let node = Node::from_id(&calling_client, id, true);
|
||||||
Node::create_parent_name(&calling_client, Self::CREATE_LINES_PARENT_PATH, &name, true);
|
|
||||||
let parent = parent.get_aspect::<Spatial>()?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let transform = transform.to_mat4(true, true, true);
|
let transform = transform.to_mat4(true, true, true);
|
||||||
|
|
||||||
@@ -84,13 +83,12 @@ impl DrawableInterfaceAspect for DrawableInterface {
|
|||||||
fn load_model(
|
fn load_model(
|
||||||
_node: Arc<Node>,
|
_node: Arc<Node>,
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
name: String,
|
id: u64,
|
||||||
parent: Arc<Node>,
|
parent: Arc<Node>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
model: ResourceID,
|
model: ResourceID,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let node =
|
let node = Node::from_id(&calling_client, id, true);
|
||||||
Node::create_parent_name(&calling_client, Self::LOAD_MODEL_PARENT_PATH, &name, true);
|
|
||||||
let parent = parent.get_aspect::<Spatial>()?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let transform = transform.to_mat4(true, true, true);
|
let transform = transform.to_mat4(true, true, true);
|
||||||
let node = node.add_to_scenegraph()?;
|
let node = node.add_to_scenegraph()?;
|
||||||
@@ -102,14 +100,13 @@ impl DrawableInterfaceAspect for DrawableInterface {
|
|||||||
fn create_text(
|
fn create_text(
|
||||||
_node: Arc<Node>,
|
_node: Arc<Node>,
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
name: String,
|
id: u64,
|
||||||
parent: Arc<Node>,
|
parent: Arc<Node>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
text: String,
|
text: String,
|
||||||
style: TextStyle,
|
style: TextStyle,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let node =
|
let node = Node::from_id(&calling_client, id, true);
|
||||||
Node::create_parent_name(&calling_client, Self::CREATE_TEXT_PARENT_PATH, &name, true);
|
|
||||||
let parent = parent.get_aspect::<Spatial>()?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let transform = transform.to_mat4(true, true, true);
|
let transform = transform.to_mat4(true, true, true);
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
use super::{MaterialParameter, ModelAspect, ModelPartAspect, Node};
|
|
||||||
use crate::core::client::Client;
|
use crate::core::client::Client;
|
||||||
use crate::core::node_collections::LifeLinkedNodeMap;
|
|
||||||
use crate::core::registry::Registry;
|
use crate::core::registry::Registry;
|
||||||
use crate::core::resource::get_resource_file;
|
use crate::core::resource::get_resource_file;
|
||||||
|
use crate::nodes::alias::{Alias, AliasList};
|
||||||
use crate::nodes::spatial::Spatial;
|
use crate::nodes::spatial::Spatial;
|
||||||
use crate::nodes::Aspect;
|
use crate::nodes::{Aspect, Node};
|
||||||
use color_eyre::eyre::{eyre, Result};
|
use color_eyre::eyre::{bail, eyre, Result};
|
||||||
use glam::{Mat4, Vec2, Vec3};
|
use glam::{Mat4, Vec2, Vec3};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
@@ -19,9 +18,10 @@ use stereokit_rust::sk::MainThreadToken;
|
|||||||
use stereokit_rust::{material::Material, model::Model as SKModel, tex::Tex, util::Color128};
|
use stereokit_rust::{material::Material, model::Model as SKModel, tex::Tex, util::Color128};
|
||||||
|
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
|
|
||||||
|
use super::{MaterialParameter, ModelAspect, ModelPartAspect, MODEL_PART_ASPECT_ALIAS_INFO};
|
||||||
|
|
||||||
static MODEL_REGISTRY: Registry<Model> = Registry::new();
|
static MODEL_REGISTRY: Registry<Model> = Registry::new();
|
||||||
static HOLDOUT_MATERIAL: OnceCell<Arc<SendWrapper<Material>>> = OnceCell::new();
|
static HOLDOUT_MATERIAL: OnceCell<Arc<SendWrapper<Material>>> = OnceCell::new();
|
||||||
|
|
||||||
@@ -69,11 +69,12 @@ impl MaterialParameter {
|
|||||||
|
|
||||||
pub struct ModelPart {
|
pub struct ModelPart {
|
||||||
id: i32,
|
id: i32,
|
||||||
path: PathBuf,
|
path: String,
|
||||||
space: Arc<Spatial>,
|
space: Arc<Spatial>,
|
||||||
model: Weak<Model>,
|
model: Weak<Model>,
|
||||||
pending_material_parameters: Mutex<FxHashMap<String, MaterialParameter>>,
|
pending_material_parameters: Mutex<FxHashMap<String, MaterialParameter>>,
|
||||||
pending_material_replacement: Mutex<Option<Arc<SendWrapper<Material>>>>,
|
pending_material_replacement: Mutex<Option<Arc<SendWrapper<Material>>>>,
|
||||||
|
aliases: AliasList,
|
||||||
}
|
}
|
||||||
impl ModelPart {
|
impl ModelPart {
|
||||||
fn create_for_model(model: &Arc<Model>, sk_model: &SKModel) {
|
fn create_for_model(model: &Arc<Model>, sk_model: &SKModel) {
|
||||||
@@ -91,26 +92,21 @@ impl ModelPart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn create(model: &Arc<Model>, part: &stereokit_rust::model::ModelNode) -> Option<Arc<Self>> {
|
fn create(model: &Arc<Model>, part: &stereokit_rust::model::ModelNode) -> Option<Arc<Self>> {
|
||||||
let parent_node = part
|
let mut parts = model.parts.lock();
|
||||||
|
let parent_part = part
|
||||||
.get_parent()
|
.get_parent()
|
||||||
.and_then(|part| model.parts.get(part.get_id()));
|
.and_then(|part| parts.iter().find(|p| p.id == *part.get_id()));
|
||||||
let parent_part = parent_node
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|node| node.get_aspect::<ModelPart>().ok());
|
|
||||||
|
|
||||||
let stardust_model_part = model.space.node()?;
|
let stardust_model_part = model.space.node()?;
|
||||||
let client = stardust_model_part.get_client()?;
|
let client = stardust_model_part.get_client()?;
|
||||||
let mut part_path = parent_part.map(|n| n.path.clone()).unwrap_or_default();
|
let mut part_path = parent_part
|
||||||
part_path.push(part.get_name().unwrap());
|
.map(|n| n.path.clone() + "/")
|
||||||
|
.unwrap_or_default();
|
||||||
|
part_path += part.get_name().unwrap();
|
||||||
|
|
||||||
let node = client.scenegraph.add_node(Node::create_parent_name(
|
let node = client.scenegraph.add_node(Node::generate(&client, false));
|
||||||
&client,
|
let spatial_parent = parent_part
|
||||||
stardust_model_part.get_path(),
|
.map(|n| n.space.clone())
|
||||||
part_path.to_str()?,
|
|
||||||
false,
|
|
||||||
));
|
|
||||||
let spatial_parent = parent_node
|
|
||||||
.and_then(|n| n.get_aspect::<Spatial>().ok())
|
|
||||||
.unwrap_or_else(|| model.space.clone());
|
.unwrap_or_else(|| model.space.clone());
|
||||||
|
|
||||||
let local_transform = unsafe { part.get_local_transform().m };
|
let local_transform = unsafe { part.get_local_transform().m };
|
||||||
@@ -121,11 +117,7 @@ impl ModelPart {
|
|||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
let _ = node
|
let _ = space.bounding_box_calc.set(|node| {
|
||||||
.get_aspect::<Spatial>()
|
|
||||||
.unwrap()
|
|
||||||
.bounding_box_calc
|
|
||||||
.set(|node| {
|
|
||||||
let Ok(model_part) = node.get_aspect::<ModelPart>() else {
|
let Ok(model_part) = node.get_aspect::<ModelPart>() else {
|
||||||
return Bounds::default();
|
return Bounds::default();
|
||||||
};
|
};
|
||||||
@@ -135,8 +127,8 @@ impl ModelPart {
|
|||||||
let Some(sk_model) = model.sk_model.get() else {
|
let Some(sk_model) = model.sk_model.get() else {
|
||||||
return Bounds::default();
|
return Bounds::default();
|
||||||
};
|
};
|
||||||
let nodes = sk_model.get_nodes();
|
let model_nodes = sk_model.get_nodes();
|
||||||
let Some(model_node) = nodes.get_index(model_part.id) else {
|
let Some(model_node) = model_nodes.get_index(model_part.id) else {
|
||||||
return Bounds::default();
|
return Bounds::default();
|
||||||
};
|
};
|
||||||
let Some(sk_mesh) = model_node.get_mesh() else {
|
let Some(sk_mesh) = model_node.get_mesh() else {
|
||||||
@@ -152,10 +144,11 @@ impl ModelPart {
|
|||||||
model: Arc::downgrade(model),
|
model: Arc::downgrade(model),
|
||||||
pending_material_parameters: Mutex::new(FxHashMap::default()),
|
pending_material_parameters: Mutex::new(FxHashMap::default()),
|
||||||
pending_material_replacement: Mutex::new(None),
|
pending_material_replacement: Mutex::new(None),
|
||||||
|
aliases: AliasList::default(),
|
||||||
});
|
});
|
||||||
<ModelPart as ModelPartAspect>::add_node_members(&node);
|
<ModelPart as ModelPartAspect>::add_node_members(&node);
|
||||||
node.add_aspect_raw(model_part.clone());
|
node.add_aspect_raw(model_part.clone());
|
||||||
model.parts.add(*part.get_id(), &node);
|
parts.push(model_part.clone());
|
||||||
Some(model_part)
|
Some(model_part)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,9 +248,8 @@ pub struct Model {
|
|||||||
space: Arc<Spatial>,
|
space: Arc<Spatial>,
|
||||||
_resource_id: ResourceID,
|
_resource_id: ResourceID,
|
||||||
sk_model: OnceCell<SKModel>,
|
sk_model: OnceCell<SKModel>,
|
||||||
parts: LifeLinkedNodeMap<i32>,
|
parts: Mutex<Vec<Arc<ModelPart>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Model {
|
impl Model {
|
||||||
pub fn add_to(node: &Arc<Node>, resource_id: ResourceID) -> Result<Arc<Model>> {
|
pub fn add_to(node: &Arc<Node>, resource_id: ResourceID) -> Result<Arc<Model>> {
|
||||||
let pending_model_path = get_resource_file(
|
let pending_model_path = get_resource_file(
|
||||||
@@ -272,8 +264,9 @@ impl Model {
|
|||||||
space: node.get_aspect::<Spatial>().unwrap().clone(),
|
space: node.get_aspect::<Spatial>().unwrap().clone(),
|
||||||
_resource_id: resource_id,
|
_resource_id: resource_id,
|
||||||
sk_model: OnceCell::new(),
|
sk_model: OnceCell::new(),
|
||||||
parts: LifeLinkedNodeMap::default(),
|
parts: Mutex::new(Vec::default()),
|
||||||
});
|
});
|
||||||
|
<Model as ModelAspect>::add_node_members(node);
|
||||||
MODEL_REGISTRY.add_raw(&model);
|
MODEL_REGISTRY.add_raw(&model);
|
||||||
|
|
||||||
// technically doing this in anything but the main thread isn't a good idea but dangit we need those model nodes ASAP
|
// technically doing this in anything but the main thread isn't a good idea but dangit we need those model nodes ASAP
|
||||||
@@ -291,11 +284,11 @@ impl Model {
|
|||||||
let Some(sk_model) = self.sk_model.get() else {
|
let Some(sk_model) = self.sk_model.get() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
for model_node_node in self.parts.nodes() {
|
let parts = self.parts.lock();
|
||||||
if let Ok(model_node) = model_node_node.get_aspect::<ModelPart>() {
|
for model_node in &*parts {
|
||||||
model_node.update();
|
model_node.update();
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
drop(parts);
|
||||||
|
|
||||||
if self.enabled.load(Ordering::Relaxed) {
|
if self.enabled.load(Ordering::Relaxed) {
|
||||||
sk_model.draw(token, self.space.global_transform(), None, None);
|
sk_model.draw(token, self.space.global_transform(), None, None);
|
||||||
@@ -308,12 +301,32 @@ unsafe impl Sync for Model {}
|
|||||||
impl Aspect for Model {
|
impl Aspect for Model {
|
||||||
const NAME: &'static str = "Model";
|
const NAME: &'static str = "Model";
|
||||||
}
|
}
|
||||||
impl ModelAspect for Model {}
|
impl ModelAspect for Model {
|
||||||
|
#[doc = "Bind a model part to the node with the ID input."]
|
||||||
|
fn bind_model_part(
|
||||||
|
node: Arc<Node>,
|
||||||
|
calling_client: Arc<Client>,
|
||||||
|
id: u64,
|
||||||
|
part_path: String,
|
||||||
|
) -> color_eyre::eyre::Result<()> {
|
||||||
|
let model = node.get_aspect::<Model>()?;
|
||||||
|
let parts = model.parts.lock();
|
||||||
|
let Some(part) = parts.iter().find(|p| p.path == part_path) else {
|
||||||
|
let paths = parts.iter().map(|p| &p.path).collect::<Vec<_>>();
|
||||||
|
bail!("Couldn't find model part at path {part_path}, all available paths: {paths:?}",)
|
||||||
|
};
|
||||||
|
Alias::create_with_id(
|
||||||
|
&part.space.node().unwrap(),
|
||||||
|
&calling_client,
|
||||||
|
id,
|
||||||
|
MODEL_PART_ASPECT_ALIAS_INFO.clone(),
|
||||||
|
Some(&part.aliases),
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
impl Drop for Model {
|
impl Drop for Model {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// if let Some(sk_model) = self.sk_model.take() {
|
|
||||||
// destroy_queue::add(sk_model);
|
|
||||||
// }
|
|
||||||
MODEL_REGISTRY.remove(self);
|
MODEL_REGISTRY.remove(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,10 @@ use self::sphere::SphereField;
|
|||||||
use self::torus::TorusField;
|
use self::torus::TorusField;
|
||||||
|
|
||||||
use super::alias::AliasInfo;
|
use super::alias::AliasInfo;
|
||||||
use super::spatial::Spatial;
|
use super::spatial::{
|
||||||
|
Spatial, SPATIAL_REF_GET_LOCAL_BOUNDING_BOX_SERVER_OPCODE,
|
||||||
|
SPATIAL_REF_GET_RELATIVE_BOUNDING_BOX_SERVER_OPCODE, SPATIAL_REF_GET_TRANSFORM_SERVER_OPCODE,
|
||||||
|
};
|
||||||
use super::{Aspect, Node};
|
use super::{Aspect, Node};
|
||||||
use crate::core::client::Client;
|
use crate::core::client::Client;
|
||||||
use crate::create_interface;
|
use crate::create_interface;
|
||||||
@@ -24,7 +27,15 @@ use std::sync::Arc;
|
|||||||
// TODO: get SDFs working properly with non-uniform scale and so on, output distance relative to the spatial it's compared against
|
// TODO: get SDFs working properly with non-uniform scale and so on, output distance relative to the spatial it's compared against
|
||||||
|
|
||||||
pub static FIELD_ALIAS_INFO: Lazy<AliasInfo> = Lazy::new(|| AliasInfo {
|
pub static FIELD_ALIAS_INFO: Lazy<AliasInfo> = Lazy::new(|| AliasInfo {
|
||||||
server_methods: vec!["distance", "normal", "closest_point", "ray_march"],
|
server_methods: vec![
|
||||||
|
SPATIAL_REF_GET_TRANSFORM_SERVER_OPCODE,
|
||||||
|
SPATIAL_REF_GET_LOCAL_BOUNDING_BOX_SERVER_OPCODE,
|
||||||
|
SPATIAL_REF_GET_RELATIVE_BOUNDING_BOX_SERVER_OPCODE,
|
||||||
|
FIELD_DISTANCE_SERVER_OPCODE,
|
||||||
|
FIELD_NORMAL_SERVER_OPCODE,
|
||||||
|
FIELD_CLOSEST_POINT_SERVER_OPCODE,
|
||||||
|
FIELD_RAY_MARCH_SERVER_OPCODE,
|
||||||
|
],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -200,26 +211,20 @@ impl Deref for Field {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
create_interface!(FieldInterface, FieldInterfaceAspect, "/field");
|
create_interface!(FieldInterface);
|
||||||
pub struct FieldInterface;
|
pub struct FieldInterface;
|
||||||
impl FieldInterfaceAspect for FieldInterface {
|
impl InterfaceAspect for FieldInterface {
|
||||||
fn create_box_field(
|
fn create_box_field(
|
||||||
_node: Arc<Node>,
|
_node: Arc<Node>,
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
name: String,
|
id: u64,
|
||||||
parent: Arc<Node>,
|
parent: Arc<Node>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
size: mint::Vector3<f32>,
|
size: mint::Vector3<f32>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let transform = transform.to_mat4(true, true, false);
|
let transform = transform.to_mat4(true, true, false);
|
||||||
let parent = parent.get_aspect::<Spatial>()?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let node = Node::create_parent_name(
|
let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?;
|
||||||
&calling_client,
|
|
||||||
Self::CREATE_BOX_FIELD_PARENT_PATH,
|
|
||||||
&name,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
.add_to_scenegraph()?;
|
|
||||||
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||||
BoxField::add_to(&node, size);
|
BoxField::add_to(&node, size);
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -228,7 +233,7 @@ impl FieldInterfaceAspect for FieldInterface {
|
|||||||
fn create_cylinder_field(
|
fn create_cylinder_field(
|
||||||
_node: Arc<Node>,
|
_node: Arc<Node>,
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
name: String,
|
id: u64,
|
||||||
parent: Arc<Node>,
|
parent: Arc<Node>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
length: f32,
|
length: f32,
|
||||||
@@ -236,13 +241,7 @@ impl FieldInterfaceAspect for FieldInterface {
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let transform = transform.to_mat4(true, true, false);
|
let transform = transform.to_mat4(true, true, false);
|
||||||
let parent = parent.get_aspect::<Spatial>()?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let node = Node::create_parent_name(
|
let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?;
|
||||||
&calling_client,
|
|
||||||
Self::CREATE_CYLINDER_FIELD_PARENT_PATH,
|
|
||||||
&name,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
.add_to_scenegraph()?;
|
|
||||||
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||||
CylinderField::add_to(&node, length, radius);
|
CylinderField::add_to(&node, length, radius);
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -251,19 +250,13 @@ impl FieldInterfaceAspect for FieldInterface {
|
|||||||
fn create_sphere_field(
|
fn create_sphere_field(
|
||||||
_node: Arc<Node>,
|
_node: Arc<Node>,
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
name: String,
|
id: u64,
|
||||||
parent: Arc<Node>,
|
parent: Arc<Node>,
|
||||||
position: mint::Vector3<f32>,
|
position: mint::Vector3<f32>,
|
||||||
radius: f32,
|
radius: f32,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let parent = parent.get_aspect::<Spatial>()?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let node = Node::create_parent_name(
|
let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?;
|
||||||
&calling_client,
|
|
||||||
Self::CREATE_SPHERE_FIELD_PARENT_PATH,
|
|
||||||
&name,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
.add_to_scenegraph()?;
|
|
||||||
Spatial::add_to(
|
Spatial::add_to(
|
||||||
&node,
|
&node,
|
||||||
Some(parent.clone()),
|
Some(parent.clone()),
|
||||||
@@ -277,7 +270,7 @@ impl FieldInterfaceAspect for FieldInterface {
|
|||||||
fn create_torus_field(
|
fn create_torus_field(
|
||||||
_node: Arc<Node>,
|
_node: Arc<Node>,
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
name: String,
|
id: u64,
|
||||||
parent: Arc<Node>,
|
parent: Arc<Node>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
radius_a: f32,
|
radius_a: f32,
|
||||||
@@ -285,13 +278,7 @@ impl FieldInterfaceAspect for FieldInterface {
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let transform = transform.to_mat4(true, true, false);
|
let transform = transform.to_mat4(true, true, false);
|
||||||
let parent = parent.get_aspect::<Spatial>()?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let node = Node::create_parent_name(
|
let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?;
|
||||||
&calling_client,
|
|
||||||
Self::CREATE_TORUS_FIELD_PARENT_PATH,
|
|
||||||
&name,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
.add_to_scenegraph()?;
|
|
||||||
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||||
TorusField::add_to(&node, radius_a, radius_b);
|
TorusField::add_to(&node, radius_a, radius_b);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
use super::{alias::Alias, spatial::Spatial, Node};
|
use super::{
|
||||||
use crate::{
|
alias::Alias,
|
||||||
core::client::{Client, INTERNAL_CLIENT},
|
spatial::{Spatial, SPATIAL_ASPECT_ALIAS_INFO},
|
||||||
nodes::alias::AliasInfo,
|
Node,
|
||||||
};
|
};
|
||||||
|
use crate::core::client::{Client, INTERNAL_CLIENT};
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use glam::{vec3, Mat4};
|
use glam::{vec3, Mat4};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -13,31 +14,21 @@ lazy_static::lazy_static! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn create() -> Arc<Node> {
|
fn create() -> Arc<Node> {
|
||||||
let node = Arc::new(Node::create_parent_name(&INTERNAL_CLIENT, "", "hmd", false));
|
let node = Arc::new(Node::generate(&INTERNAL_CLIENT, false));
|
||||||
Spatial::add_to(&node, None, Mat4::IDENTITY, false);
|
Spatial::add_to(&node, None, Mat4::IDENTITY, false);
|
||||||
|
|
||||||
node
|
node
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn frame() {
|
pub fn frame() {
|
||||||
let spatial = HMD.get_aspect::<Spatial>().unwrap();
|
let spatial = HMD.get_aspect::<Spatial>().unwrap();
|
||||||
let hmd_pose = Input::get_head();
|
let hmd_pose = Input::get_head();
|
||||||
*spatial.transform.lock() = Mat4::from_scale_rotation_translation(
|
spatial.set_local_transform(Mat4::from_scale_rotation_translation(
|
||||||
vec3(1.0, 1.0, 1.0),
|
vec3(1.0, 1.0, 1.0),
|
||||||
hmd_pose.orientation.into(),
|
hmd_pose.orientation.into(),
|
||||||
hmd_pose.position.into(),
|
hmd_pose.position.into(),
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_alias(client: &Arc<Client>) -> Result<Arc<Node>> {
|
pub fn make_alias(client: &Arc<Client>) -> Result<Arc<Node>> {
|
||||||
Alias::create(
|
Alias::create(&HMD, client, SPATIAL_ASPECT_ALIAS_INFO.clone(), None)
|
||||||
client,
|
|
||||||
"",
|
|
||||||
"hmd",
|
|
||||||
&HMD,
|
|
||||||
AliasInfo {
|
|
||||||
server_signals: vec!["get_bounds", "get_transform"],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,30 +2,23 @@ use super::{
|
|||||||
input_handler_client, InputHandlerAspect, InputLink, INPUT_HANDLER_REGISTRY,
|
input_handler_client, InputHandlerAspect, InputLink, INPUT_HANDLER_REGISTRY,
|
||||||
INPUT_METHOD_REGISTRY,
|
INPUT_METHOD_REGISTRY,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::nodes::{alias::AliasList, fields::Field, spatial::Spatial, Aspect, Node};
|
||||||
core::node_collections::LifeLinkedNodeMap,
|
|
||||||
nodes::{fields::Field, spatial::Spatial, Aspect, Node},
|
|
||||||
};
|
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use stardust_xr::values::Datamap;
|
use stardust_xr::values::Datamap;
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::Arc;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
pub struct InputHandler {
|
pub struct InputHandler {
|
||||||
pub uid: String,
|
|
||||||
pub node: Weak<Node>,
|
|
||||||
pub spatial: Arc<Spatial>,
|
pub spatial: Arc<Spatial>,
|
||||||
pub field: Arc<Field>,
|
pub field: Arc<Field>,
|
||||||
pub(super) method_aliases: LifeLinkedNodeMap<usize>,
|
pub(super) method_aliases: AliasList,
|
||||||
}
|
}
|
||||||
impl InputHandler {
|
impl InputHandler {
|
||||||
pub fn add_to(node: &Arc<Node>, field: &Arc<Field>) -> Result<()> {
|
pub fn add_to(node: &Arc<Node>, field: &Arc<Field>) -> Result<()> {
|
||||||
let handler = InputHandler {
|
let handler = InputHandler {
|
||||||
uid: node.uid.clone(),
|
|
||||||
node: Arc::downgrade(node),
|
|
||||||
spatial: node.get_aspect::<Spatial>().unwrap().clone(),
|
spatial: node.get_aspect::<Spatial>().unwrap().clone(),
|
||||||
field: field.clone(),
|
field: field.clone(),
|
||||||
method_aliases: LifeLinkedNodeMap::default(),
|
method_aliases: AliasList::default(),
|
||||||
};
|
};
|
||||||
for method in INPUT_METHOD_REGISTRY.get_valid_contents() {
|
for method in INPUT_METHOD_REGISTRY.get_valid_contents() {
|
||||||
method.make_alias(&handler);
|
method.make_alias(&handler);
|
||||||
@@ -44,20 +37,16 @@ impl InputHandler {
|
|||||||
input_link: &InputLink,
|
input_link: &InputLink,
|
||||||
datamap: Datamap,
|
datamap: Datamap,
|
||||||
) {
|
) {
|
||||||
let Some(node) = self.node.upgrade() else {
|
let Some(node) = self.spatial.node() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(method_alias) = input_link
|
let Some(method_alias) = self.method_aliases.get(input_link.method.as_ref()) else {
|
||||||
.handler
|
|
||||||
.method_aliases
|
|
||||||
.get(&(Arc::as_ptr(&input_link.method) as usize))
|
|
||||||
else {
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let _ = input_handler_client::input(
|
let _ = input_handler_client::input(
|
||||||
&node,
|
&node,
|
||||||
&method_alias,
|
&method_alias,
|
||||||
&input_link.serialize(order, captured, datamap),
|
&input_link.serialize(method_alias.id, order, captured, datamap),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
use super::{
|
use super::{
|
||||||
input_method_client, InputDataTrait, InputDataType, InputHandler, InputMethodAspect,
|
input_method_client, InputDataTrait, InputDataType, InputHandler, InputMethodAspect,
|
||||||
InputMethodRefAspect, INPUT_HANDLER_REGISTRY, INPUT_METHOD_REGISTRY,
|
InputMethodRefAspect, INPUT_HANDLER_REGISTRY, INPUT_METHOD_ASPECT_ALIAS_INFO,
|
||||||
|
INPUT_METHOD_REF_ASPECT_ALIAS_INFO, INPUT_METHOD_REGISTRY,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
core::{client::Client, node_collections::LifeLinkedNodeMap, registry::Registry},
|
core::{client::Client, registry::Registry},
|
||||||
nodes::{
|
nodes::{
|
||||||
alias::{Alias, AliasInfo},
|
alias::{Alias, AliasList},
|
||||||
fields::{Field, FIELD_ALIAS_INFO},
|
fields::{Field, FIELD_ALIAS_INFO},
|
||||||
spatial::Spatial,
|
spatial::Spatial,
|
||||||
Aspect, Node,
|
Aspect, Node,
|
||||||
@@ -19,7 +20,6 @@ use std::sync::{Arc, Weak};
|
|||||||
|
|
||||||
pub struct InputMethod {
|
pub struct InputMethod {
|
||||||
pub node: Weak<Node>,
|
pub node: Weak<Node>,
|
||||||
pub uid: String,
|
|
||||||
pub enabled: Mutex<bool>,
|
pub enabled: Mutex<bool>,
|
||||||
pub spatial: Arc<Spatial>,
|
pub spatial: Arc<Spatial>,
|
||||||
pub data: Mutex<InputDataType>,
|
pub data: Mutex<InputDataType>,
|
||||||
@@ -27,7 +27,8 @@ pub struct InputMethod {
|
|||||||
|
|
||||||
pub capture_requests: Registry<InputHandler>,
|
pub capture_requests: Registry<InputHandler>,
|
||||||
pub captures: Registry<InputHandler>,
|
pub captures: Registry<InputHandler>,
|
||||||
pub(super) handler_aliases: LifeLinkedNodeMap<String>,
|
handler_aliases: AliasList,
|
||||||
|
handler_field_aliases: AliasList,
|
||||||
pub(super) handler_order: Mutex<Vec<Weak<InputHandler>>>,
|
pub(super) handler_order: Mutex<Vec<Weak<InputHandler>>>,
|
||||||
}
|
}
|
||||||
impl InputMethod {
|
impl InputMethod {
|
||||||
@@ -38,14 +39,15 @@ impl InputMethod {
|
|||||||
) -> Result<Arc<InputMethod>> {
|
) -> Result<Arc<InputMethod>> {
|
||||||
let method = InputMethod {
|
let method = InputMethod {
|
||||||
node: Arc::downgrade(node),
|
node: Arc::downgrade(node),
|
||||||
uid: node.uid.clone(),
|
|
||||||
enabled: Mutex::new(true),
|
enabled: Mutex::new(true),
|
||||||
spatial: node.get_aspect::<Spatial>().unwrap().clone(),
|
spatial: node.get_aspect::<Spatial>().unwrap().clone(),
|
||||||
data: Mutex::new(data),
|
data: Mutex::new(data),
|
||||||
|
datamap: Mutex::new(datamap),
|
||||||
|
|
||||||
capture_requests: Registry::new(),
|
capture_requests: Registry::new(),
|
||||||
captures: Registry::new(),
|
captures: Registry::new(),
|
||||||
datamap: Mutex::new(datamap),
|
handler_aliases: AliasList::default(),
|
||||||
handler_aliases: LifeLinkedNodeMap::default(),
|
handler_field_aliases: AliasList::default(),
|
||||||
handler_order: Mutex::new(Vec::new()),
|
handler_order: Mutex::new(Vec::new()),
|
||||||
};
|
};
|
||||||
for handler in INPUT_HANDLER_REGISTRY.get_valid_contents() {
|
for handler in INPUT_HANDLER_REGISTRY.get_valid_contents() {
|
||||||
@@ -63,28 +65,21 @@ impl InputMethod {
|
|||||||
let Some(method_node) = self.node.upgrade() else {
|
let Some(method_node) = self.node.upgrade() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(handler_node) = handler.node.upgrade() else {
|
let Some(handler_node) = handler.spatial.node() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(client) = handler_node.get_client() else {
|
let Some(client) = handler_node.get_client() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Ok(method_alias) = Alias::create(
|
let Ok(method_alias) = Alias::create(
|
||||||
&client,
|
|
||||||
handler_node.get_path(),
|
|
||||||
&self.uid,
|
|
||||||
&method_node,
|
&method_node,
|
||||||
AliasInfo {
|
&client,
|
||||||
server_signals: vec!["capture"],
|
INPUT_METHOD_ASPECT_ALIAS_INFO.clone(),
|
||||||
..Default::default()
|
Some(&handler.method_aliases),
|
||||||
},
|
|
||||||
) else {
|
) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
method_alias.enabled.store(false, Ordering::Relaxed);
|
method_alias.enabled.store(false, Ordering::Relaxed);
|
||||||
handler
|
|
||||||
.method_aliases
|
|
||||||
.add(self as *const InputMethod as usize, &method_alias);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn distance(&self, to: &Field) -> f32 {
|
pub fn distance(&self, to: &Field) -> f32 {
|
||||||
@@ -102,57 +97,45 @@ impl InputMethod {
|
|||||||
let Some(method_client) = method_node.get_client() else {
|
let Some(method_client) = method_node.get_client() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(handler_node) = handler.node.upgrade() else {
|
let Some(handler_node) = handler.spatial.node() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
// Receiver itself
|
// Receiver itself
|
||||||
let Ok(handler_alias) = Alias::create(
|
let Ok(handler_alias) = Alias::create(
|
||||||
&method_client,
|
|
||||||
method_node.get_path(),
|
|
||||||
handler.uid.as_str(),
|
|
||||||
&handler_node,
|
&handler_node,
|
||||||
AliasInfo {
|
&method_client,
|
||||||
server_methods: vec!["get_transform"],
|
INPUT_METHOD_REF_ASPECT_ALIAS_INFO.clone(),
|
||||||
..Default::default()
|
Some(&self.handler_aliases),
|
||||||
},
|
|
||||||
) else {
|
) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
self.handler_aliases
|
|
||||||
.add(handler.uid.clone(), &handler_alias);
|
|
||||||
|
|
||||||
let Some(handler_field_node) = handler.field.spatial_ref().node.upgrade() else {
|
let Some(handler_field_node) = handler.field.spatial_ref().node() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
// Handler's field
|
// Handler's field
|
||||||
let Ok(rx_field_alias) = Alias::create(
|
let Ok(rx_field_alias) = Alias::create(
|
||||||
&method_client,
|
|
||||||
handler_alias.get_path(),
|
|
||||||
"field",
|
|
||||||
&handler_field_node,
|
&handler_field_node,
|
||||||
|
&method_client,
|
||||||
FIELD_ALIAS_INFO.clone(),
|
FIELD_ALIAS_INFO.clone(),
|
||||||
|
Some(&self.handler_field_aliases),
|
||||||
) else {
|
) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
self.handler_aliases
|
|
||||||
.add(handler.uid.clone() + "-field", &rx_field_alias);
|
|
||||||
|
|
||||||
let _ = input_method_client::create_handler(
|
let _ = input_method_client::create_handler(&method_node, &handler_alias, &rx_field_alias);
|
||||||
&method_node,
|
|
||||||
&handler.uid,
|
|
||||||
&handler_node,
|
|
||||||
&rx_field_alias,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
pub(super) fn handle_drop_handler(&self, handler: &InputHandler) {
|
pub(super) fn handle_drop_handler(&self, handler: &InputHandler) {
|
||||||
let uid = handler.uid.as_str();
|
|
||||||
self.handler_aliases.remove(uid);
|
|
||||||
self.handler_aliases.remove(&(uid.to_string() + "-field"));
|
|
||||||
let Some(tx_node) = self.node.upgrade() else {
|
let Some(tx_node) = self.node.upgrade() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
let Some(handler_alias) = self.handler_aliases.get(handler) else {
|
||||||
let _ = input_method_client::destroy_handler(&tx_node, &uid);
|
return;
|
||||||
|
};
|
||||||
|
let _ = input_method_client::destroy_handler(&tx_node, handler_alias.id);
|
||||||
|
self.handler_aliases.remove_aspect(handler);
|
||||||
|
self.handler_field_aliases
|
||||||
|
.remove_aspect(handler.field.as_ref());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Aspect for InputMethod {
|
impl Aspect for InputMethod {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ impl InputLink {
|
|||||||
self.handler.send_input(order, captured, self, datamap);
|
self.handler.send_input(order, captured, self, datamap);
|
||||||
}
|
}
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
fn serialize(&self, order: u32, captured: bool, datamap: Datamap) -> InputData {
|
fn serialize(&self, id: u64, order: u32, captured: bool, datamap: Datamap) -> InputData {
|
||||||
let mut input = self.method.data.lock().clone();
|
let mut input = self.method.data.lock().clone();
|
||||||
input.update_to(
|
input.update_to(
|
||||||
self,
|
self,
|
||||||
@@ -46,7 +46,7 @@ impl InputLink {
|
|||||||
);
|
);
|
||||||
|
|
||||||
InputData {
|
InputData {
|
||||||
uid: self.method.uid.clone(),
|
id,
|
||||||
input,
|
input,
|
||||||
distance: self.method.distance(&self.handler.field),
|
distance: self.method.distance(&self.handler.field),
|
||||||
datamap,
|
datamap,
|
||||||
@@ -77,14 +77,14 @@ impl InputDataTrait for InputDataType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
create_interface!(InputInterface, InputInterfaceAspect, "/input");
|
create_interface!(InputInterface);
|
||||||
pub struct InputInterface;
|
pub struct InputInterface;
|
||||||
impl InputInterfaceAspect for InputInterface {
|
impl InterfaceAspect for InputInterface {
|
||||||
#[doc = "Create an input method node"]
|
#[doc = "Create an input method node"]
|
||||||
fn create_input_method(
|
fn create_input_method(
|
||||||
_node: Arc<Node>,
|
_node: Arc<Node>,
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
name: String,
|
id: u64,
|
||||||
parent: Arc<Node>,
|
parent: Arc<Node>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
initial_data: InputDataType,
|
initial_data: InputDataType,
|
||||||
@@ -93,8 +93,7 @@ impl InputInterfaceAspect for InputInterface {
|
|||||||
let parent = parent.get_aspect::<Spatial>()?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let transform = transform.to_mat4(true, true, true);
|
let transform = transform.to_mat4(true, true, true);
|
||||||
|
|
||||||
let node = Node::create_parent_name(&calling_client, "/input/method", &name, true)
|
let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?;
|
||||||
.add_to_scenegraph()?;
|
|
||||||
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||||
InputMethod::add_to(&node, initial_data, datamap)?;
|
InputMethod::add_to(&node, initial_data, datamap)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -104,7 +103,7 @@ impl InputInterfaceAspect for InputInterface {
|
|||||||
fn create_input_handler(
|
fn create_input_handler(
|
||||||
_node: Arc<Node>,
|
_node: Arc<Node>,
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
name: String,
|
id: u64,
|
||||||
parent: Arc<Node>,
|
parent: Arc<Node>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
field: Arc<Node>,
|
field: Arc<Node>,
|
||||||
@@ -113,8 +112,7 @@ impl InputInterfaceAspect for InputInterface {
|
|||||||
let transform = transform.to_mat4(true, true, true);
|
let transform = transform.to_mat4(true, true, true);
|
||||||
let field = field.get_aspect::<Field>()?;
|
let field = field.get_aspect::<Field>()?;
|
||||||
|
|
||||||
let node = Node::create_parent_name(&calling_client, "/input/handler", &name, true)
|
let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?;
|
||||||
.add_to_scenegraph()?;
|
|
||||||
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||||
InputHandler::add_to(&node, &field)?;
|
InputHandler::add_to(&node, &field)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -145,7 +143,7 @@ pub fn process_input() {
|
|||||||
.iter()
|
.iter()
|
||||||
.filter_map(Weak::upgrade)
|
.filter_map(Weak::upgrade)
|
||||||
.filter(|handler| {
|
.filter(|handler| {
|
||||||
let Some(node) = handler.node.upgrade() else {
|
let Some(node) = handler.spatial.node() else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
node.enabled()
|
node.enabled()
|
||||||
@@ -159,7 +157,7 @@ pub fn process_input() {
|
|||||||
if let Some(method_alias) = input_link
|
if let Some(method_alias) = input_link
|
||||||
.handler
|
.handler
|
||||||
.method_aliases
|
.method_aliases
|
||||||
.get(&(Arc::as_ptr(&input_link.method) as usize))
|
.get(input_link.method.as_ref())
|
||||||
.and_then(|a| a.get_aspect::<Alias>().ok())
|
.and_then(|a| a.get_aspect::<Alias>().ok())
|
||||||
{
|
{
|
||||||
method_alias.enabled.store(true, Ordering::Release);
|
method_alias.enabled.store(true, Ordering::Release);
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
use super::{create_item_acceptor_flex, register_item_ui_flex, Item, ItemInterface, ItemType};
|
use super::{
|
||||||
|
create_item_acceptor_flex, register_item_ui_flex, Item, ItemAcceptor, ItemInterface, ItemType,
|
||||||
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
core::{
|
core::{client::Client, registry::Registry, scenegraph::MethodResponseSender},
|
||||||
client::{Client, INTERNAL_CLIENT},
|
|
||||||
registry::Registry,
|
|
||||||
scenegraph::MethodResponseSender,
|
|
||||||
},
|
|
||||||
create_interface,
|
create_interface,
|
||||||
nodes::{
|
nodes::{
|
||||||
drawable::{model::ModelPart, shaders::UNLIT_SHADER_BYTES},
|
drawable::{model::ModelPart, shaders::UNLIT_SHADER_BYTES},
|
||||||
@@ -17,7 +15,6 @@ use color_eyre::eyre::{bail, eyre, Result};
|
|||||||
use glam::Mat4;
|
use glam::Mat4;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use mint::{ColumnMatrix4, Vector2};
|
use mint::{ColumnMatrix4, Vector2};
|
||||||
use nanoid::nanoid;
|
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use send_wrapper::SendWrapper;
|
use send_wrapper::SendWrapper;
|
||||||
@@ -37,14 +34,13 @@ stardust_xr_server_codegen::codegen_item_camera_protocol!();
|
|||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub(super) static ref ITEM_TYPE_INFO_CAMERA: TypeInfo = TypeInfo {
|
pub(super) static ref ITEM_TYPE_INFO_CAMERA: TypeInfo = TypeInfo {
|
||||||
type_name: "camera",
|
type_name: "camera",
|
||||||
aliased_local_signals: vec!["apply_preview_material", "frame"],
|
alias_info: CAMERA_ITEM_ASPECT_ALIAS_INFO.clone(),
|
||||||
aliased_local_methods: vec![],
|
ui_node_id: INTERFACE_NODE_ID,
|
||||||
aliased_remote_signals: vec![],
|
|
||||||
ui: Default::default(),
|
ui: Default::default(),
|
||||||
items: Registry::new(),
|
items: Registry::new(),
|
||||||
acceptors: Registry::new(),
|
acceptors: Registry::new(),
|
||||||
new_acceptor_fn: |node, uid, acceptor, acceptor_field| {
|
new_acceptor_fn: |node, acceptor, acceptor_field| {
|
||||||
let _ = camera_item_ui_client::create_acceptor(node, uid, acceptor, acceptor_field);
|
let _ = camera_item_ui_client::create_acceptor(node, acceptor, acceptor_field);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -62,11 +58,11 @@ pub struct CameraItem {
|
|||||||
applied_to: Registry<ModelPart>,
|
applied_to: Registry<ModelPart>,
|
||||||
apply_to: Registry<ModelPart>,
|
apply_to: Registry<ModelPart>,
|
||||||
}
|
}
|
||||||
|
#[allow(unused)]
|
||||||
impl CameraItem {
|
impl CameraItem {
|
||||||
pub fn add_to(node: &Arc<Node>, proj_matrix: Mat4, px_size: Vector2<u32>) {
|
pub fn add_to(node: &Arc<Node>, proj_matrix: Mat4, px_size: Vector2<u32>) {
|
||||||
Item::add_to(
|
Item::add_to(
|
||||||
node,
|
node,
|
||||||
nanoid!(),
|
|
||||||
&ITEM_TYPE_INFO_CAMERA,
|
&ITEM_TYPE_INFO_CAMERA,
|
||||||
ItemType::Camera(CameraItem {
|
ItemType::Camera(CameraItem {
|
||||||
space: node.get_aspect::<Spatial>().unwrap().clone(),
|
space: node.get_aspect::<Spatial>().unwrap().clone(),
|
||||||
@@ -80,11 +76,7 @@ impl CameraItem {
|
|||||||
apply_to: Registry::new(),
|
apply_to: Registry::new(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
node.add_local_method("frame", CameraItem::frame_flex);
|
// <CameraItem as CameraItemAspect>::node_methods(node);
|
||||||
node.add_local_signal(
|
|
||||||
"apply_preview_material",
|
|
||||||
CameraItem::apply_preview_material_flex,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frame_flex(
|
fn frame_flex(
|
||||||
@@ -118,11 +110,11 @@ impl CameraItem {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_ui_item_created(&self, node: &Node, uid: &str, item: &Arc<Node>) {
|
pub fn send_ui_item_created(&self, node: &Node, item: &Arc<Node>) {
|
||||||
let _ = camera_item_ui_client::create_item(node, uid, item);
|
let _ = camera_item_ui_client::create_item(node, item);
|
||||||
}
|
}
|
||||||
pub fn send_acceptor_item_created(&self, node: &Node, uid: &str, item: &Arc<Node>) {
|
pub fn send_acceptor_item_created(&self, node: &Node, item: &Arc<Node>) {
|
||||||
let _ = camera_item_acceptor_client::capture_item(node, uid, item);
|
let _ = camera_item_acceptor_client::capture_item(node, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&self, token: &MainThreadToken) {
|
pub fn update(&self, token: &MainThreadToken) {
|
||||||
@@ -166,6 +158,13 @@ impl CameraItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl CameraItemAspect for CameraItem {}
|
||||||
|
|
||||||
|
impl CameraItemAcceptorAspect for ItemAcceptor {
|
||||||
|
fn capture_item(node: Arc<Node>, _calling_client: Arc<Client>, item: Arc<Node>) -> Result<()> {
|
||||||
|
super::acceptor_capture_item_flex(node, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update(token: &MainThreadToken) {
|
pub fn update(token: &MainThreadToken) {
|
||||||
for camera in ITEM_TYPE_INFO_CAMERA.items.get_valid_contents() {
|
for camera in ITEM_TYPE_INFO_CAMERA.items.get_valid_contents() {
|
||||||
@@ -176,31 +175,24 @@ pub fn update(token: &MainThreadToken) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
create_interface!(ItemInterface, ItemCameraInterfaceAspect, "/item/camera");
|
create_interface!(ItemInterface);
|
||||||
impl ItemCameraInterfaceAspect for ItemInterface {
|
impl InterfaceAspect for ItemInterface {
|
||||||
#[doc = "Create a camera item at a specific location"]
|
#[doc = "Create a camera item at a specific location"]
|
||||||
fn create_camera_item(
|
fn create_camera_item(
|
||||||
_node: Arc<Node>,
|
_node: Arc<Node>,
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
name: String,
|
id: u64,
|
||||||
parent: Arc<Node>,
|
parent: Arc<Node>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
proj_matrix: ColumnMatrix4<f32>,
|
proj_matrix: ColumnMatrix4<f32>,
|
||||||
px_size: Vector2<u32>,
|
px_size: Vector2<u32>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let parent_name = format!("/item/{}/item", ITEM_TYPE_INFO_CAMERA.type_name);
|
|
||||||
let space = parent.get_aspect::<Spatial>()?;
|
let space = parent.get_aspect::<Spatial>()?;
|
||||||
let transform = transform.to_mat4(true, true, false);
|
let transform = transform.to_mat4(true, true, false);
|
||||||
|
|
||||||
let node = Node::create_parent_name(&INTERNAL_CLIENT, &parent_name, &name, false)
|
let node = Node::from_id(&calling_client, id, false).add_to_scenegraph()?;
|
||||||
.add_to_scenegraph()?;
|
|
||||||
Spatial::add_to(&node, None, transform * space.global_transform(), false);
|
Spatial::add_to(&node, None, transform * space.global_transform(), false);
|
||||||
CameraItem::add_to(&node, proj_matrix.into(), px_size);
|
CameraItem::add_to(&node, proj_matrix.into(), px_size);
|
||||||
node.get_aspect::<Item>().unwrap().make_alias_named(
|
|
||||||
&calling_client,
|
|
||||||
&parent_name,
|
|
||||||
&name,
|
|
||||||
)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,14 +205,14 @@ impl ItemCameraInterfaceAspect for ItemInterface {
|
|||||||
fn create_camera_item_acceptor(
|
fn create_camera_item_acceptor(
|
||||||
_node: Arc<Node>,
|
_node: Arc<Node>,
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
name: String,
|
id: u64,
|
||||||
parent: Arc<Node>,
|
parent: Arc<Node>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
field: Arc<Node>,
|
field: Arc<Node>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
create_item_acceptor_flex(
|
create_item_acceptor_flex(
|
||||||
calling_client,
|
calling_client,
|
||||||
name,
|
id,
|
||||||
parent,
|
parent,
|
||||||
transform,
|
transform,
|
||||||
&ITEM_TYPE_INFO_CAMERA,
|
&ITEM_TYPE_INFO_CAMERA,
|
||||||
|
|||||||
@@ -3,41 +3,23 @@ pub mod panel;
|
|||||||
|
|
||||||
use self::camera::CameraItem;
|
use self::camera::CameraItem;
|
||||||
use self::panel::PanelItemTrait;
|
use self::panel::PanelItemTrait;
|
||||||
use super::fields::Field;
|
use super::alias::AliasList;
|
||||||
|
use super::fields::{Field, FIELD_ALIAS_INFO};
|
||||||
use super::spatial::Spatial;
|
use super::spatial::Spatial;
|
||||||
use super::{Alias, Aspect, Message, Node};
|
use super::{Alias, Aspect, Node};
|
||||||
use crate::core::client::Client;
|
use crate::core::client::Client;
|
||||||
use crate::core::node_collections::LifeLinkedNodeMap;
|
|
||||||
use crate::core::registry::Registry;
|
use crate::core::registry::Registry;
|
||||||
use crate::nodes::alias::AliasInfo;
|
use crate::nodes::alias::AliasInfo;
|
||||||
use crate::nodes::spatial::Transform;
|
use crate::nodes::spatial::Transform;
|
||||||
use color_eyre::eyre::{ensure, Result};
|
use color_eyre::eyre::{ensure, Result};
|
||||||
use lazy_static::lazy_static;
|
|
||||||
use nanoid::nanoid;
|
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use portable_atomic::Ordering;
|
|
||||||
use stardust_xr::schemas::flex::deserialize;
|
|
||||||
|
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
|
|
||||||
stardust_xr_server_codegen::codegen_item_protocol!();
|
stardust_xr_server_codegen::codegen_item_protocol!();
|
||||||
|
|
||||||
lazy_static! {
|
fn capture(item: &Arc<Item>, acceptor: &Arc<ItemAcceptor>) {
|
||||||
static ref ITEM_ALIAS_LOCAL_SIGNALS: Vec<&'static str> = vec![
|
|
||||||
"get_bounds",
|
|
||||||
"get_transform",
|
|
||||||
"set_transform",
|
|
||||||
"set_spatial_parent",
|
|
||||||
"set_spatial_parent_in_place",
|
|
||||||
"set_zoneable",
|
|
||||||
"release",
|
|
||||||
];
|
|
||||||
static ref ITEM_ALIAS_LOCAL_METHODS: Vec<&'static str> = vec![];
|
|
||||||
static ref ITEM_ALIAS_REMOTE_SIGNALS: Vec<&'static str> = vec![];
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn capture(item: &Arc<Item>, acceptor: &Arc<ItemAcceptor>) {
|
|
||||||
if item.captured_acceptor.lock().strong_count() > 0 {
|
if item.captured_acceptor.lock().strong_count() > 0 {
|
||||||
release(item);
|
release(item);
|
||||||
}
|
}
|
||||||
@@ -60,14 +42,12 @@ fn release(item: &Item) {
|
|||||||
|
|
||||||
pub struct TypeInfo {
|
pub struct TypeInfo {
|
||||||
pub type_name: &'static str,
|
pub type_name: &'static str,
|
||||||
pub aliased_local_signals: Vec<&'static str>,
|
pub alias_info: AliasInfo,
|
||||||
pub aliased_local_methods: Vec<&'static str>,
|
pub ui_node_id: u64,
|
||||||
pub aliased_remote_signals: Vec<&'static str>,
|
|
||||||
pub ui: Mutex<Weak<ItemUI>>,
|
pub ui: Mutex<Weak<ItemUI>>,
|
||||||
pub items: Registry<Item>,
|
pub items: Registry<Item>,
|
||||||
pub acceptors: Registry<ItemAcceptor>,
|
pub acceptors: Registry<ItemAcceptor>,
|
||||||
pub new_acceptor_fn:
|
pub new_acceptor_fn: fn(node: &Node, acceptor: &Arc<Node>, acceptor_field: &Arc<Node>),
|
||||||
fn(node: &Node, uid: &str, acceptor: &Arc<Node>, acceptor_field: &Arc<Node>),
|
|
||||||
}
|
}
|
||||||
impl Hash for TypeInfo {
|
impl Hash for TypeInfo {
|
||||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
@@ -83,7 +63,6 @@ impl Eq for TypeInfo {}
|
|||||||
|
|
||||||
pub struct Item {
|
pub struct Item {
|
||||||
node: Weak<Node>,
|
node: Weak<Node>,
|
||||||
uid: String,
|
|
||||||
type_info: &'static TypeInfo,
|
type_info: &'static TypeInfo,
|
||||||
captured_acceptor: Mutex<Weak<ItemAcceptor>>,
|
captured_acceptor: Mutex<Weak<ItemAcceptor>>,
|
||||||
pub specialization: ItemType,
|
pub specialization: ItemType,
|
||||||
@@ -91,20 +70,18 @@ pub struct Item {
|
|||||||
impl Item {
|
impl Item {
|
||||||
pub fn add_to(
|
pub fn add_to(
|
||||||
node: &Arc<Node>,
|
node: &Arc<Node>,
|
||||||
uid: String,
|
|
||||||
type_info: &'static TypeInfo,
|
type_info: &'static TypeInfo,
|
||||||
specialization: ItemType,
|
specialization: ItemType,
|
||||||
) -> Arc<Self> {
|
) -> Arc<Self> {
|
||||||
let item = Item {
|
let item = Item {
|
||||||
node: Arc::downgrade(node),
|
node: Arc::downgrade(node),
|
||||||
uid,
|
|
||||||
type_info,
|
type_info,
|
||||||
captured_acceptor: Default::default(),
|
captured_acceptor: Default::default(),
|
||||||
specialization,
|
specialization,
|
||||||
};
|
};
|
||||||
let item = type_info.items.add(item);
|
let item = type_info.items.add(item);
|
||||||
|
|
||||||
node.add_local_signal("release", Item::release_flex);
|
<Item as ItemAspect>::add_node_members(node);
|
||||||
if let Some(ui) = type_info.ui.lock().upgrade() {
|
if let Some(ui) = type_info.ui.lock().upgrade() {
|
||||||
ui.handle_create_item(&item);
|
ui.handle_create_item(&item);
|
||||||
}
|
}
|
||||||
@@ -122,54 +99,25 @@ impl Item {
|
|||||||
|
|
||||||
item
|
item
|
||||||
}
|
}
|
||||||
fn make_alias_named(
|
fn make_alias(&self, client: &Arc<Client>, alias_list: &AliasList) -> Result<Arc<Node>> {
|
||||||
&self,
|
|
||||||
client: &Arc<Client>,
|
|
||||||
parent: &str,
|
|
||||||
name: &str,
|
|
||||||
) -> Result<Arc<Node>> {
|
|
||||||
Alias::create(
|
Alias::create(
|
||||||
client,
|
|
||||||
parent,
|
|
||||||
name,
|
|
||||||
&self.node.upgrade().unwrap(),
|
&self.node.upgrade().unwrap(),
|
||||||
AliasInfo {
|
client,
|
||||||
server_signals: [
|
self.type_info.alias_info.clone() + ITEM_ASPECT_ALIAS_INFO.clone(),
|
||||||
&self.type_info.aliased_local_signals,
|
Some(alias_list),
|
||||||
ITEM_ALIAS_LOCAL_SIGNALS.as_slice(),
|
|
||||||
]
|
|
||||||
.concat(),
|
|
||||||
server_methods: [
|
|
||||||
&self.type_info.aliased_local_methods,
|
|
||||||
ITEM_ALIAS_LOCAL_METHODS.as_slice(),
|
|
||||||
]
|
|
||||||
.concat(),
|
|
||||||
client_signals: [
|
|
||||||
&self.type_info.aliased_remote_signals,
|
|
||||||
ITEM_ALIAS_REMOTE_SIGNALS.as_slice(),
|
|
||||||
]
|
|
||||||
.concat(),
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
fn make_alias(&self, client: &Arc<Client>, parent: &str) -> Result<Arc<Node>> {
|
|
||||||
self.make_alias_named(client, parent, &self.uid)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn release_flex(
|
|
||||||
node: Arc<Node>,
|
|
||||||
_calling_client: Arc<Client>,
|
|
||||||
_message: Message,
|
|
||||||
) -> Result<()> {
|
|
||||||
let item = node.get_aspect::<Item>()?;
|
|
||||||
release(&item);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
impl Aspect for Item {
|
impl Aspect for Item {
|
||||||
const NAME: &'static str = "Item";
|
const NAME: &'static str = "Item";
|
||||||
}
|
}
|
||||||
|
impl ItemAspect for Item {
|
||||||
|
fn release(node: Arc<Node>, _calling_client: Arc<Client>) -> Result<()> {
|
||||||
|
let item = node.get_aspect::<Item>()?;
|
||||||
|
release(&item);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
impl Drop for Item {
|
impl Drop for Item {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.type_info.items.remove(self);
|
self.type_info.items.remove(self);
|
||||||
@@ -185,16 +133,16 @@ pub enum ItemType {
|
|||||||
Panel(Arc<dyn PanelItemTrait>),
|
Panel(Arc<dyn PanelItemTrait>),
|
||||||
}
|
}
|
||||||
impl ItemType {
|
impl ItemType {
|
||||||
fn send_ui_item_created(&self, node: &Node, uid: &str, item: &Arc<Node>) {
|
fn send_ui_item_created(&self, node: &Node, item: &Arc<Node>) {
|
||||||
match self {
|
match self {
|
||||||
ItemType::Camera(c) => c.send_ui_item_created(node, uid, item),
|
ItemType::Camera(c) => c.send_ui_item_created(node, item),
|
||||||
ItemType::Panel(p) => p.send_ui_item_created(node, uid, item),
|
ItemType::Panel(p) => p.send_ui_item_created(node, item),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn send_acceptor_item_created(&self, node: &Node, uid: &str, item: &Arc<Node>) {
|
fn send_acceptor_item_created(&self, node: &Node, item: &Arc<Node>) {
|
||||||
match self {
|
match self {
|
||||||
ItemType::Camera(c) => c.send_acceptor_item_created(node, uid, item),
|
ItemType::Camera(c) => c.send_acceptor_item_created(node, item),
|
||||||
ItemType::Panel(p) => p.send_acceptor_item_created(node, uid, item),
|
ItemType::Panel(p) => p.send_acceptor_item_created(node, item),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,9 +160,9 @@ impl ItemType {
|
|||||||
pub struct ItemUI {
|
pub struct ItemUI {
|
||||||
node: Weak<Node>,
|
node: Weak<Node>,
|
||||||
type_info: &'static TypeInfo,
|
type_info: &'static TypeInfo,
|
||||||
item_aliases: LifeLinkedNodeMap<String>,
|
item_aliases: AliasList,
|
||||||
acceptor_aliases: LifeLinkedNodeMap<String>,
|
acceptor_aliases: AliasList,
|
||||||
acceptor_field_aliases: LifeLinkedNodeMap<String>,
|
acceptor_field_aliases: AliasList,
|
||||||
}
|
}
|
||||||
impl ItemUI {
|
impl ItemUI {
|
||||||
fn add_to(node: &Arc<Node>, type_info: &'static TypeInfo) -> Result<()> {
|
fn add_to(node: &Arc<Node>, type_info: &'static TypeInfo) -> Result<()> {
|
||||||
@@ -226,9 +174,9 @@ impl ItemUI {
|
|||||||
let ui = Arc::new(ItemUI {
|
let ui = Arc::new(ItemUI {
|
||||||
node: Arc::downgrade(node),
|
node: Arc::downgrade(node),
|
||||||
type_info,
|
type_info,
|
||||||
item_aliases: Default::default(),
|
item_aliases: AliasList::default(),
|
||||||
acceptor_aliases: Default::default(),
|
acceptor_aliases: AliasList::default(),
|
||||||
acceptor_field_aliases: Default::default(),
|
acceptor_field_aliases: AliasList::default(),
|
||||||
});
|
});
|
||||||
*type_info.ui.lock() = Arc::downgrade(&ui);
|
*type_info.ui.lock() = Arc::downgrade(&ui);
|
||||||
node.add_aspect_raw(ui.clone());
|
node.add_aspect_raw(ui.clone());
|
||||||
@@ -250,26 +198,44 @@ impl ItemUI {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Ok(item_alias) = item.make_alias(&client, &(node.get_path().to_string() + "/item"))
|
let Ok(item_alias) = item.make_alias(&client, &self.item_aliases) else {
|
||||||
else {
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
self.item_aliases.add(item.uid.clone(), &item_alias);
|
|
||||||
|
|
||||||
item.specialization
|
item.specialization.send_ui_item_created(&node, &item_alias);
|
||||||
.send_ui_item_created(&node, &item.uid, &item_alias);
|
|
||||||
}
|
}
|
||||||
fn handle_capture_item(&self, item: &Item, acceptor: &ItemAcceptor) {
|
fn handle_capture_item(&self, item: &Item, acceptor: &ItemAcceptor) {
|
||||||
let _ =
|
let Some(item_alias) = self.item_aliases.get(item) else {
|
||||||
item_ui_client::capture_item(&self.node.upgrade().unwrap(), &item.uid, &acceptor.uid);
|
return;
|
||||||
|
};
|
||||||
|
let Some(acceptor_alias) = self.acceptor_aliases.get(acceptor) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let _ = item_ui_client::capture_item(
|
||||||
|
&self.node.upgrade().unwrap(),
|
||||||
|
item_alias.id,
|
||||||
|
acceptor_alias.id,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
fn handle_release_item(&self, item: &Item, acceptor: &ItemAcceptor) {
|
fn handle_release_item(&self, item: &Item, acceptor: &ItemAcceptor) {
|
||||||
let _ =
|
let Some(item_alias) = self.item_aliases.get(item) else {
|
||||||
item_ui_client::release_item(&self.node.upgrade().unwrap(), &item.uid, &acceptor.uid);
|
return;
|
||||||
|
};
|
||||||
|
let Some(acceptor_alias) = self.acceptor_aliases.get(acceptor) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let _ = item_ui_client::release_item(
|
||||||
|
&self.node.upgrade().unwrap(),
|
||||||
|
item_alias.id,
|
||||||
|
acceptor_alias.id,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
fn handle_destroy_item(&self, item: &Item) {
|
fn handle_destroy_item(&self, item: &Item) {
|
||||||
let _ = item_ui_client::destroy_item(&self.node.upgrade().unwrap(), &item.uid);
|
let Some(item_alias) = self.item_aliases.get(item) else {
|
||||||
self.item_aliases.remove(&item.uid);
|
return;
|
||||||
|
};
|
||||||
|
let _ = item_ui_client::destroy_item(&self.node.upgrade().unwrap(), item_alias.id);
|
||||||
|
self.item_aliases.remove_aspect(item);
|
||||||
}
|
}
|
||||||
fn handle_create_acceptor(&self, acceptor: &ItemAcceptor) {
|
fn handle_create_acceptor(&self, acceptor: &ItemAcceptor) {
|
||||||
let Some(node) = self.node.upgrade() else {
|
let Some(node) = self.node.upgrade() else {
|
||||||
@@ -279,28 +245,40 @@ impl ItemUI {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Ok((acceptor_alias, acceptor_field_alias)) = acceptor.make_aliases(
|
let Some(acceptor_node) = acceptor.spatial.node() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Ok(acceptor_alias) = Alias::create(
|
||||||
|
&acceptor_node,
|
||||||
&client,
|
&client,
|
||||||
&format!("/item/{}/acceptor", self.type_info.type_name),
|
ITEM_ACCEPTOR_ASPECT_ALIAS_INFO.clone(),
|
||||||
|
Some(&self.acceptor_aliases),
|
||||||
) else {
|
) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
self.acceptor_aliases
|
|
||||||
.add(acceptor.uid.clone(), &acceptor_alias);
|
|
||||||
self.acceptor_field_aliases
|
|
||||||
.add(acceptor.uid.clone(), &acceptor_field_alias);
|
|
||||||
|
|
||||||
(acceptor.type_info.new_acceptor_fn)(
|
let Some(acceptor_field_node) = acceptor.field.spatial_ref().node() else {
|
||||||
&node,
|
return;
|
||||||
&acceptor.uid,
|
};
|
||||||
&acceptor_alias,
|
let Ok(acceptor_field_alias) = Alias::create(
|
||||||
&acceptor_field_alias,
|
&acceptor_field_node,
|
||||||
);
|
&client,
|
||||||
|
FIELD_ALIAS_INFO.clone(),
|
||||||
|
Some(&self.acceptor_aliases),
|
||||||
|
) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
(acceptor.type_info.new_acceptor_fn)(&node, &acceptor_alias, &acceptor_field_alias);
|
||||||
}
|
}
|
||||||
fn handle_destroy_acceptor(&self, acceptor: &ItemAcceptor) {
|
fn handle_destroy_acceptor(&self, acceptor: &ItemAcceptor) {
|
||||||
let _ = item_ui_client::destroy_acceptor(&self.node.upgrade().unwrap(), &acceptor.uid);
|
let acceptor_alias = self.acceptor_aliases.get(acceptor).unwrap();
|
||||||
self.acceptor_aliases.remove(&acceptor.uid);
|
let _ = item_ui_client::destroy_acceptor(&self.node.upgrade().unwrap(), acceptor_alias.id);
|
||||||
self.acceptor_field_aliases.remove(&acceptor.uid);
|
|
||||||
|
self.acceptor_aliases
|
||||||
|
.remove_aspect(acceptor.spatial.as_ref());
|
||||||
|
self.acceptor_field_aliases
|
||||||
|
.remove_aspect(acceptor.field.as_ref());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Aspect for ItemUI {
|
impl Aspect for ItemUI {
|
||||||
@@ -313,69 +291,29 @@ impl Drop for ItemUI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct ItemAcceptor {
|
pub struct ItemAcceptor {
|
||||||
uid: String,
|
spatial: Arc<Spatial>,
|
||||||
node: Weak<Node>,
|
|
||||||
pub type_info: &'static TypeInfo,
|
pub type_info: &'static TypeInfo,
|
||||||
field: Arc<Field>,
|
field: Arc<Field>,
|
||||||
accepted_aliases: LifeLinkedNodeMap<String>,
|
accepted_aliases: AliasList,
|
||||||
accepted_registry: Registry<Item>,
|
accepted_registry: Registry<Item>,
|
||||||
}
|
}
|
||||||
impl ItemAcceptor {
|
impl ItemAcceptor {
|
||||||
fn add_to(node: &Arc<Node>, type_info: &'static TypeInfo, field: Arc<Field>) {
|
fn add_to(node: &Arc<Node>, type_info: &'static TypeInfo, field: Arc<Field>) {
|
||||||
let acceptor = type_info.acceptors.add(ItemAcceptor {
|
let acceptor = type_info.acceptors.add(ItemAcceptor {
|
||||||
uid: nanoid!(),
|
spatial: node.get_aspect::<Spatial>().unwrap(),
|
||||||
node: Arc::downgrade(node),
|
|
||||||
type_info,
|
type_info,
|
||||||
field,
|
field,
|
||||||
accepted_aliases: Default::default(),
|
accepted_aliases: AliasList::default(),
|
||||||
accepted_registry: Registry::new(),
|
accepted_registry: Registry::new(),
|
||||||
});
|
});
|
||||||
node.add_local_signal("capture", ItemAcceptor::capture_flex);
|
|
||||||
if let Some(ui) = type_info.ui.lock().upgrade() {
|
if let Some(ui) = type_info.ui.lock().upgrade() {
|
||||||
ui.handle_create_acceptor(&acceptor);
|
ui.handle_create_acceptor(&acceptor);
|
||||||
}
|
}
|
||||||
node.add_aspect_raw(acceptor);
|
node.add_aspect_raw(acceptor.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn capture_flex(node: Arc<Node>, calling_client: Arc<Client>, message: Message) -> Result<()> {
|
|
||||||
if !node.enabled.load(Ordering::Relaxed) {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let acceptor = node.get_aspect::<ItemAcceptor>().unwrap();
|
|
||||||
let item_path: &str = deserialize(message.as_ref())?;
|
|
||||||
let item_node = calling_client.get_node("Item", item_path)?;
|
|
||||||
let item = item_node.get_aspect::<Item>()?;
|
|
||||||
capture(&item, &acceptor);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_aliases(&self, client: &Arc<Client>, parent: &str) -> Result<(Arc<Node>, Arc<Node>)> {
|
|
||||||
let acceptor_node = &self.node.upgrade().unwrap();
|
|
||||||
let acceptor_alias = Alias::create(
|
|
||||||
client,
|
|
||||||
parent,
|
|
||||||
&self.uid,
|
|
||||||
acceptor_node,
|
|
||||||
AliasInfo {
|
|
||||||
server_signals: vec!["capture"],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let acceptor_field_alias = Alias::create(
|
|
||||||
client,
|
|
||||||
acceptor_alias.get_path(),
|
|
||||||
"field",
|
|
||||||
&self.field.spatial_ref().node.upgrade().unwrap(),
|
|
||||||
AliasInfo::default(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok((acceptor_alias, acceptor_field_alias))
|
|
||||||
}
|
|
||||||
fn handle_capture(&self, item: &Arc<Item>) {
|
fn handle_capture(&self, item: &Arc<Item>) {
|
||||||
let Some(node) = self.node.upgrade() else {
|
let Some(node) = self.spatial.node() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(client) = node.get_client() else {
|
let Some(client) = node.get_client() else {
|
||||||
@@ -383,21 +321,22 @@ impl ItemAcceptor {
|
|||||||
};
|
};
|
||||||
|
|
||||||
self.accepted_registry.add_raw(item);
|
self.accepted_registry.add_raw(item);
|
||||||
let Ok(alias_node) = item.make_alias(&client, &node.path) else {
|
let Ok(alias_node) = item.make_alias(&client, &self.accepted_aliases) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
self.accepted_aliases.add(item.uid.clone(), &alias_node);
|
|
||||||
|
|
||||||
item.specialization
|
item.specialization
|
||||||
.send_acceptor_item_created(&node, &item.uid, &alias_node);
|
.send_acceptor_item_created(&node, &alias_node);
|
||||||
}
|
}
|
||||||
fn handle_release(&self, item: &Item) {
|
fn handle_release(&self, item: &Item) {
|
||||||
if let Some(node) = self.node.upgrade() {
|
|
||||||
let _ = item_acceptor_client::release_item(&node, &item.uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.accepted_registry.remove(item);
|
self.accepted_registry.remove(item);
|
||||||
self.accepted_aliases.remove(&item.uid);
|
self.accepted_aliases.remove_aspect(item);
|
||||||
|
|
||||||
|
let Some(node) = self.spatial.node() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let alias = self.accepted_aliases.get(item).unwrap();
|
||||||
|
let _ = item_acceptor_client::release_item(&node, alias.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Aspect for ItemAcceptor {
|
impl Aspect for ItemAcceptor {
|
||||||
@@ -420,14 +359,13 @@ pub fn register_item_ui_flex(
|
|||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
type_info: &'static TypeInfo,
|
type_info: &'static TypeInfo,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ui = Node::create_parent_name(&calling_client, "/item", type_info.type_name, true)
|
let ui = Node::from_id(&calling_client, type_info.ui_node_id, true).add_to_scenegraph()?;
|
||||||
.add_to_scenegraph()?;
|
|
||||||
ItemUI::add_to(&ui, type_info)?;
|
ItemUI::add_to(&ui, type_info)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn create_item_acceptor_flex(
|
fn create_item_acceptor_flex(
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
name: String,
|
id: u64,
|
||||||
parent: Arc<Node>,
|
parent: Arc<Node>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
type_info: &'static TypeInfo,
|
type_info: &'static TypeInfo,
|
||||||
@@ -437,17 +375,19 @@ fn create_item_acceptor_flex(
|
|||||||
let field = field.get_aspect::<Field>()?;
|
let field = field.get_aspect::<Field>()?;
|
||||||
let transform = transform.to_mat4(true, true, false);
|
let transform = transform.to_mat4(true, true, false);
|
||||||
|
|
||||||
let node = Node::create_parent_name(
|
let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?;
|
||||||
&calling_client,
|
|
||||||
&format!("/item/{}/acceptor", type_info.type_name),
|
|
||||||
&name,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
.add_to_scenegraph()?;
|
|
||||||
Spatial::add_to(&node, Some(space.clone()), transform, false);
|
Spatial::add_to(&node, Some(space.clone()), transform, false);
|
||||||
ItemAcceptor::add_to(&node, type_info, field);
|
ItemAcceptor::add_to(&node, type_info, field);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn acceptor_capture_item_flex(node: Arc<Node>, item: Arc<Node>) -> Result<()> {
|
||||||
|
let acceptor = node.get_aspect::<ItemAcceptor>()?;
|
||||||
|
let item = item.get_aspect::<Item>()?;
|
||||||
|
capture(&item, &acceptor);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
struct ItemInterface;
|
struct ItemInterface;
|
||||||
// create_interface!(ItemInterface, ItemInterfaceAspect, "/item");
|
// create_interface!(ItemInterface);
|
||||||
|
|||||||
@@ -15,51 +15,22 @@ use color_eyre::eyre::Result;
|
|||||||
use glam::Mat4;
|
use glam::Mat4;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use mint::Vector2;
|
use mint::Vector2;
|
||||||
use nanoid::nanoid;
|
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
use tracing::{debug, info};
|
use tracing::{debug, info};
|
||||||
|
|
||||||
use super::{create_item_acceptor_flex, register_item_ui_flex, ItemInterface};
|
use super::{create_item_acceptor_flex, register_item_ui_flex, ItemAcceptor, ItemInterface};
|
||||||
|
|
||||||
stardust_xr_server_codegen::codegen_item_panel_protocol!();
|
stardust_xr_server_codegen::codegen_item_panel_protocol!();
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref ITEM_TYPE_INFO_PANEL: TypeInfo = TypeInfo {
|
pub static ref ITEM_TYPE_INFO_PANEL: TypeInfo = TypeInfo {
|
||||||
type_name: "panel",
|
type_name: "panel",
|
||||||
aliased_local_signals: vec![
|
alias_info: PANEL_ITEM_ASPECT_ALIAS_INFO.clone(),
|
||||||
"apply_surface_material",
|
ui_node_id: INTERFACE_NODE_ID,
|
||||||
"close_toplevel",
|
|
||||||
"auto_size_toplevel",
|
|
||||||
"set_toplevel_size",
|
|
||||||
"set_toplevel_focused_visuals",
|
|
||||||
"pointer_motion",
|
|
||||||
"pointer_button",
|
|
||||||
"pointer_scroll",
|
|
||||||
"keyboard_keymap",
|
|
||||||
"keyboard_key",
|
|
||||||
"touch_down",
|
|
||||||
"touch_move",
|
|
||||||
"touch_up",
|
|
||||||
"reset_touches",
|
|
||||||
],
|
|
||||||
aliased_local_methods: vec![],
|
|
||||||
aliased_remote_signals: vec![
|
|
||||||
"toplevel_parent_changed",
|
|
||||||
"toplevel_title_changed",
|
|
||||||
"toplevel_app_id_changed",
|
|
||||||
"toplevel_fullscreen_active",
|
|
||||||
"toplevel_move_request",
|
|
||||||
"toplevel_resize_request",
|
|
||||||
"toplevel_size_changed",
|
|
||||||
"set_cursor",
|
|
||||||
"new_child",
|
|
||||||
"reposition_child",
|
|
||||||
"drop_child",
|
|
||||||
],
|
|
||||||
ui: Default::default(),
|
ui: Default::default(),
|
||||||
items: Registry::new(),
|
items: Registry::new(),
|
||||||
acceptors: Registry::new(),
|
acceptors: Registry::new(),
|
||||||
new_acceptor_fn: |node, uid, acceptor, acceptor_field| {
|
new_acceptor_fn: |node, acceptor, acceptor_field| {
|
||||||
let _ = panel_item_ui_client::create_acceptor(node, uid, acceptor, acceptor_field);
|
let _ = panel_item_ui_client::create_acceptor(node, acceptor, acceptor_field);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -85,7 +56,7 @@ pub trait Backend: Send + Sync + 'static {
|
|||||||
scroll_steps: Option<Vector2<f32>>,
|
scroll_steps: Option<Vector2<f32>>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn keyboard_keys(&self, surface: &SurfaceId, keymap_id: &str, keys: Vec<i32>);
|
fn keyboard_keys(&self, surface: &SurfaceId, keymap_id: u64, keys: Vec<i32>);
|
||||||
|
|
||||||
fn touch_down(&self, surface: &SurfaceId, id: u32, position: Vector2<f32>);
|
fn touch_down(&self, surface: &SurfaceId, id: u32, position: Vector2<f32>);
|
||||||
fn touch_move(&self, id: u32, position: Vector2<f32>);
|
fn touch_move(&self, id: u32, position: Vector2<f32>);
|
||||||
@@ -101,13 +72,12 @@ pub fn panel_item_from_node(node: &Node) -> Option<Arc<dyn PanelItemTrait>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait PanelItemTrait: Backend + Send + Sync + 'static {
|
pub trait PanelItemTrait: Backend + Send + Sync + 'static {
|
||||||
fn send_ui_item_created(&self, node: &Node, uid: &str, item: &Arc<Node>);
|
fn send_ui_item_created(&self, node: &Node, item: &Arc<Node>);
|
||||||
fn send_acceptor_item_created(&self, node: &Node, uid: &str, item: &Arc<Node>);
|
fn send_acceptor_item_created(&self, node: &Node, item: &Arc<Node>);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PanelItem<B: Backend + ?Sized> {
|
pub struct PanelItem<B: Backend + ?Sized> {
|
||||||
pub uid: String,
|
pub node: Weak<Node>,
|
||||||
node: Weak<Node>,
|
|
||||||
pub backend: Box<B>,
|
pub backend: Box<B>,
|
||||||
}
|
}
|
||||||
impl<B: Backend + ?Sized> PanelItem<B> {
|
impl<B: Backend + ?Sized> PanelItem<B> {
|
||||||
@@ -118,20 +88,13 @@ impl<B: Backend + ?Sized> PanelItem<B> {
|
|||||||
.and_then(|pid| get_env(pid).ok())
|
.and_then(|pid| get_env(pid).ok())
|
||||||
.and_then(|env| state(&env));
|
.and_then(|env| state(&env));
|
||||||
|
|
||||||
let uid = nanoid!();
|
let node = Arc::new(Node::generate(&INTERNAL_CLIENT, true));
|
||||||
let node = Arc::new(Node::create_parent_name(
|
|
||||||
&INTERNAL_CLIENT,
|
|
||||||
"/item/panel/item",
|
|
||||||
&uid,
|
|
||||||
true,
|
|
||||||
));
|
|
||||||
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false);
|
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false);
|
||||||
if let Some(startup_settings) = &startup_settings {
|
if let Some(startup_settings) = &startup_settings {
|
||||||
spatial.set_local_transform(startup_settings.root);
|
spatial.set_local_transform(startup_settings.root);
|
||||||
}
|
}
|
||||||
|
|
||||||
let panel_item = Arc::new(PanelItem {
|
let panel_item = Arc::new(PanelItem {
|
||||||
uid: uid.clone(),
|
|
||||||
node: Arc::downgrade(&node),
|
node: Arc::downgrade(&node),
|
||||||
backend,
|
backend,
|
||||||
});
|
});
|
||||||
@@ -139,7 +102,6 @@ impl<B: Backend + ?Sized> PanelItem<B> {
|
|||||||
let generic_panel_item: Arc<dyn PanelItemTrait> = panel_item.clone();
|
let generic_panel_item: Arc<dyn PanelItemTrait> = panel_item.clone();
|
||||||
Item::add_to(
|
Item::add_to(
|
||||||
&node,
|
&node,
|
||||||
uid,
|
|
||||||
&ITEM_TYPE_INFO_PANEL,
|
&ITEM_TYPE_INFO_PANEL,
|
||||||
ItemType::Panel(generic_panel_item),
|
ItemType::Panel(generic_panel_item),
|
||||||
);
|
);
|
||||||
@@ -158,7 +120,7 @@ impl<B: Backend + ?Sized> PanelItem<B> {
|
|||||||
// Remote signals
|
// Remote signals
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
impl<B: Backend + ?Sized> PanelItem<B> {
|
impl<B: Backend + ?Sized> PanelItem<B> {
|
||||||
pub fn toplevel_parent_changed(&self, parent: &str) {
|
pub fn toplevel_parent_changed(&self, parent: u64) {
|
||||||
let Some(node) = self.node.upgrade() else {
|
let Some(node) = self.node.upgrade() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@@ -212,23 +174,23 @@ impl<B: Backend + ?Sized> PanelItem<B> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_child(&self, uid: &str, info: ChildInfo) {
|
pub fn create_child(&self, id: u64, info: &ChildInfo) {
|
||||||
let Some(node) = self.node.upgrade() else {
|
let Some(node) = self.node.upgrade() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
panel_item_client::create_child(&node, uid, &info);
|
panel_item_client::create_child(&node, id, info);
|
||||||
}
|
}
|
||||||
pub fn reposition_child(&self, uid: &str, geometry: Geometry) {
|
pub fn reposition_child(&self, id: u64, geometry: &Geometry) {
|
||||||
let Some(node) = self.node.upgrade() else {
|
let Some(node) = self.node.upgrade() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
panel_item_client::reposition_child(&node, uid, &geometry);
|
panel_item_client::reposition_child(&node, id, geometry);
|
||||||
}
|
}
|
||||||
pub fn destroy_child(&self, uid: &str) {
|
pub fn destroy_child(&self, id: u64) {
|
||||||
let Some(node) = self.node.upgrade() else {
|
let Some(node) = self.node.upgrade() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
panel_item_client::destroy_child(&node, uid);
|
panel_item_client::destroy_child(&node, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,13 +335,13 @@ impl<B: Backend + ?Sized> PanelItemAspect for PanelItem<B> {
|
|||||||
node: Arc<Node>,
|
node: Arc<Node>,
|
||||||
_calling_client: Arc<Client>,
|
_calling_client: Arc<Client>,
|
||||||
surface: SurfaceId,
|
surface: SurfaceId,
|
||||||
keymap_id: String,
|
keymap_id: u64,
|
||||||
keys: Vec<i32>,
|
keys: Vec<i32>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let Some(panel_item) = panel_item_from_node(&node) else {
|
let Some(panel_item) = panel_item_from_node(&node) else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
panel_item.keyboard_keys(&surface, &keymap_id, keys);
|
panel_item.keyboard_keys(&surface, keymap_id, keys);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -430,18 +392,25 @@ impl<B: Backend + ?Sized> PanelItemAspect for PanelItem<B> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<B: Backend + ?Sized> PanelItemTrait for PanelItem<B> {
|
|
||||||
fn send_ui_item_created(&self, node: &Node, uid: &str, item: &Arc<Node>) {
|
impl PanelItemAcceptorAspect for ItemAcceptor {
|
||||||
let Ok(init_data) = self.backend.start_data() else {
|
fn capture_item(node: Arc<Node>, _calling_client: Arc<Client>, item: Arc<Node>) -> Result<()> {
|
||||||
return;
|
super::acceptor_capture_item_flex(node, item)
|
||||||
};
|
|
||||||
let _ = panel_item_ui_client::create_item(node, uid, item, init_data);
|
|
||||||
}
|
}
|
||||||
fn send_acceptor_item_created(&self, node: &Node, uid: &str, item: &Arc<Node>) {
|
}
|
||||||
|
|
||||||
|
impl<B: Backend + ?Sized> PanelItemTrait for PanelItem<B> {
|
||||||
|
fn send_ui_item_created(&self, node: &Node, item: &Arc<Node>) {
|
||||||
let Ok(init_data) = self.backend.start_data() else {
|
let Ok(init_data) = self.backend.start_data() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let _ = panel_item_acceptor_client::capture_item(node, uid, item, init_data);
|
let _ = panel_item_ui_client::create_item(node, item, init_data);
|
||||||
|
}
|
||||||
|
fn send_acceptor_item_created(&self, node: &Node, item: &Arc<Node>) {
|
||||||
|
let Ok(init_data) = self.backend.start_data() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let _ = panel_item_acceptor_client::capture_item(node, item, init_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<B: Backend + ?Sized> Backend for PanelItem<B> {
|
impl<B: Backend + ?Sized> Backend for PanelItem<B> {
|
||||||
@@ -488,7 +457,7 @@ impl<B: Backend + ?Sized> Backend for PanelItem<B> {
|
|||||||
.pointer_scroll(surface, scroll_distance, scroll_steps)
|
.pointer_scroll(surface, scroll_distance, scroll_steps)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keyboard_keys(&self, surface: &SurfaceId, keymap_id: &str, keys: Vec<i32>) {
|
fn keyboard_keys(&self, surface: &SurfaceId, keymap_id: u64, keys: Vec<i32>) {
|
||||||
self.backend.keyboard_keys(surface, keymap_id, keys)
|
self.backend.keyboard_keys(surface, keymap_id, keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,12 +477,12 @@ impl<B: Backend + ?Sized> Backend for PanelItem<B> {
|
|||||||
impl<B: Backend + ?Sized> Drop for PanelItem<B> {
|
impl<B: Backend + ?Sized> Drop for PanelItem<B> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// Dropped panel item, basically just a debug breakpoint place
|
// Dropped panel item, basically just a debug breakpoint place
|
||||||
info!("Dropped panel item {}", self.uid);
|
info!("Dropped panel item");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
create_interface!(ItemInterface, ItemPanelInterfaceAspect, "/item/panel");
|
create_interface!(ItemInterface);
|
||||||
impl ItemPanelInterfaceAspect for ItemInterface {
|
impl InterfaceAspect for ItemInterface {
|
||||||
#[doc = "Register this client to manage the items of a certain type and create default 3D UI for them."]
|
#[doc = "Register this client to manage the items of a certain type and create default 3D UI for them."]
|
||||||
fn register_panel_item_ui(_node: Arc<Node>, calling_client: Arc<Client>) -> Result<()> {
|
fn register_panel_item_ui(_node: Arc<Node>, calling_client: Arc<Client>) -> Result<()> {
|
||||||
register_item_ui_flex(calling_client, &ITEM_TYPE_INFO_PANEL)
|
register_item_ui_flex(calling_client, &ITEM_TYPE_INFO_PANEL)
|
||||||
@@ -523,14 +492,14 @@ impl ItemPanelInterfaceAspect for ItemInterface {
|
|||||||
fn create_panel_item_acceptor(
|
fn create_panel_item_acceptor(
|
||||||
_node: Arc<Node>,
|
_node: Arc<Node>,
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
name: String,
|
id: u64,
|
||||||
parent: Arc<Node>,
|
parent: Arc<Node>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
field: Arc<Node>,
|
field: Arc<Node>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
create_item_acceptor_flex(
|
create_item_acceptor_flex(
|
||||||
calling_client,
|
calling_client,
|
||||||
name,
|
id,
|
||||||
parent,
|
parent,
|
||||||
transform,
|
transform,
|
||||||
&ITEM_TYPE_INFO_PANEL,
|
&ITEM_TYPE_INFO_PANEL,
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ pub mod root;
|
|||||||
pub mod spatial;
|
pub mod spatial;
|
||||||
|
|
||||||
use color_eyre::eyre::{eyre, Result};
|
use color_eyre::eyre::{eyre, Result};
|
||||||
use nanoid::nanoid;
|
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use portable_atomic::{AtomicBool, Ordering};
|
use portable_atomic::{AtomicBool, Ordering};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
@@ -56,13 +55,12 @@ stardust_xr_server_codegen::codegen_node_protocol!();
|
|||||||
|
|
||||||
pub struct Node {
|
pub struct Node {
|
||||||
enabled: Arc<AtomicBool>,
|
enabled: Arc<AtomicBool>,
|
||||||
pub(super) uid: String,
|
id: u64,
|
||||||
path: String,
|
|
||||||
client: Weak<Client>,
|
client: Weak<Client>,
|
||||||
message_sender_handle: Option<MessageSenderHandle>,
|
message_sender_handle: Option<MessageSenderHandle>,
|
||||||
// trailing_slash_pos: usize,
|
|
||||||
local_signals: Mutex<FxHashMap<String, Signal>>,
|
local_signals: Mutex<FxHashMap<u64, Signal>>,
|
||||||
local_methods: Mutex<FxHashMap<String, Method>>,
|
local_methods: Mutex<FxHashMap<u64, Method>>,
|
||||||
aliases: Registry<Alias>,
|
aliases: Registry<Alias>,
|
||||||
aspects: Aspects,
|
aspects: Aspects,
|
||||||
destroyable: bool,
|
destroyable: bool,
|
||||||
@@ -71,32 +69,19 @@ impl Node {
|
|||||||
pub fn get_client(&self) -> Option<Arc<Client>> {
|
pub fn get_client(&self) -> Option<Arc<Client>> {
|
||||||
self.client.upgrade()
|
self.client.upgrade()
|
||||||
}
|
}
|
||||||
// pub fn get_name(&self) -> &str {
|
pub fn get_id(&self) -> u64 {
|
||||||
// &self.path[self.trailing_slash_pos + 1..]
|
self.id
|
||||||
// }
|
|
||||||
pub fn get_path(&self) -> &str {
|
|
||||||
self.path.as_str()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_parent_name(
|
pub fn generate(client: &Arc<Client>, destroyable: bool) -> Self {
|
||||||
client: &Arc<Client>,
|
Self::from_id(client, client.generate_id(), destroyable)
|
||||||
parent: &str,
|
|
||||||
name: &str,
|
|
||||||
destroyable: bool,
|
|
||||||
) -> Self {
|
|
||||||
let mut path = parent.to_string();
|
|
||||||
path.push('/');
|
|
||||||
path.push_str(name);
|
|
||||||
Self::create_path(client, path, destroyable)
|
|
||||||
}
|
}
|
||||||
pub fn create_path(client: &Arc<Client>, path: impl ToString, destroyable: bool) -> Self {
|
pub fn from_id(client: &Arc<Client>, id: u64, destroyable: bool) -> Self {
|
||||||
let node = Node {
|
let node = Node {
|
||||||
enabled: Arc::new(AtomicBool::new(true)),
|
enabled: Arc::new(AtomicBool::new(true)),
|
||||||
uid: nanoid!(),
|
|
||||||
client: Arc::downgrade(client),
|
client: Arc::downgrade(client),
|
||||||
message_sender_handle: client.message_sender_handle.clone(),
|
message_sender_handle: client.message_sender_handle.clone(),
|
||||||
path: path.to_string(),
|
id,
|
||||||
// trailing_slash_pos: parent.len(),
|
|
||||||
local_signals: Default::default(),
|
local_signals: Default::default(),
|
||||||
local_methods: Default::default(),
|
local_methods: Default::default(),
|
||||||
aliases: Default::default(),
|
aliases: Default::default(),
|
||||||
@@ -118,7 +103,7 @@ impl Node {
|
|||||||
}
|
}
|
||||||
pub fn destroy(&self) {
|
pub fn destroy(&self) {
|
||||||
if let Some(client) = self.get_client() {
|
if let Some(client) = self.get_client() {
|
||||||
client.scenegraph.remove_node(self.get_path());
|
client.scenegraph.remove_node(self.get_id());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,11 +121,11 @@ impl Node {
|
|||||||
// Ok(serialize(pid)?.into())
|
// Ok(serialize(pid)?.into())
|
||||||
// }
|
// }
|
||||||
|
|
||||||
pub fn add_local_signal(&self, name: &str, signal: Signal) {
|
pub fn add_local_signal(&self, id: u64, signal: Signal) {
|
||||||
self.local_signals.lock().insert(name.to_string(), signal);
|
self.local_signals.lock().insert(id, signal);
|
||||||
}
|
}
|
||||||
pub fn add_local_method(&self, name: &str, method: Method) {
|
pub fn add_local_method(&self, id: u64, method: Method) {
|
||||||
self.local_methods.lock().insert(name.to_string(), method);
|
self.local_methods.lock().insert(id, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_aspect<A: Aspect>(&self, aspect: A) -> Arc<A> {
|
pub fn add_aspect<A: Aspect>(&self, aspect: A) -> Arc<A> {
|
||||||
@@ -156,7 +141,7 @@ impl Node {
|
|||||||
pub fn send_local_signal(
|
pub fn send_local_signal(
|
||||||
self: Arc<Self>,
|
self: Arc<Self>,
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
method: &str,
|
method: u64,
|
||||||
message: Message,
|
message: Message,
|
||||||
) -> Result<(), ScenegraphError> {
|
) -> Result<(), ScenegraphError> {
|
||||||
if let Ok(alias) = self.get_aspect::<Alias>() {
|
if let Ok(alias) = self.get_aspect::<Alias>() {
|
||||||
@@ -172,7 +157,7 @@ impl Node {
|
|||||||
let signal = self
|
let signal = self
|
||||||
.local_signals
|
.local_signals
|
||||||
.lock()
|
.lock()
|
||||||
.get(method)
|
.get(&method)
|
||||||
.cloned()
|
.cloned()
|
||||||
.ok_or(ScenegraphError::SignalNotFound)?;
|
.ok_or(ScenegraphError::SignalNotFound)?;
|
||||||
signal(self, calling_client, message).map_err(|error| ScenegraphError::SignalError {
|
signal(self, calling_client, message).map_err(|error| ScenegraphError::SignalError {
|
||||||
@@ -183,7 +168,7 @@ impl Node {
|
|||||||
pub fn execute_local_method(
|
pub fn execute_local_method(
|
||||||
self: Arc<Self>,
|
self: Arc<Self>,
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
method: &str,
|
method: u64,
|
||||||
message: Message,
|
message: Message,
|
||||||
response: MethodResponseSender,
|
response: MethodResponseSender,
|
||||||
) {
|
) {
|
||||||
@@ -206,14 +191,14 @@ impl Node {
|
|||||||
response,
|
response,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let Some(method) = self.local_methods.lock().get(method).cloned() else {
|
let Some(method) = self.local_methods.lock().get(&method).cloned() else {
|
||||||
response.send(Err(ScenegraphError::MethodNotFound));
|
response.send(Err(ScenegraphError::MethodNotFound));
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
method(self, calling_client, message, response);
|
method(self, calling_client, message, response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn send_remote_signal(&self, method: &str, message: impl Into<Message>) -> Result<()> {
|
pub fn send_remote_signal(&self, method: u64, message: impl Into<Message>) -> Result<()> {
|
||||||
let message = message.into();
|
let message = message.into();
|
||||||
self.aliases
|
self.aliases
|
||||||
.get_valid_contents()
|
.get_valid_contents()
|
||||||
@@ -230,16 +215,14 @@ impl Node {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
let path = self.path.clone();
|
|
||||||
let method = method.to_string();
|
|
||||||
if let Some(handle) = self.message_sender_handle.as_ref() {
|
if let Some(handle) = self.message_sender_handle.as_ref() {
|
||||||
handle.signal(path.as_str(), method.as_str(), &message.data, message.fds)?;
|
handle.signal(self.id, method, &message.data, message.fds)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub async fn execute_remote_method_typed<S: Serialize, D: DeserializeOwned>(
|
pub async fn execute_remote_method_typed<S: Serialize, D: DeserializeOwned>(
|
||||||
&self,
|
&self,
|
||||||
method: &str,
|
method: u64,
|
||||||
input: S,
|
input: S,
|
||||||
fds: Vec<OwnedFd>,
|
fds: Vec<OwnedFd>,
|
||||||
) -> Result<(D, Vec<OwnedFd>)> {
|
) -> Result<(D, Vec<OwnedFd>)> {
|
||||||
@@ -250,7 +233,7 @@ impl Node {
|
|||||||
|
|
||||||
let serialized = serialize(input)?;
|
let serialized = serialize(input)?;
|
||||||
let result = message_sender_handle
|
let result = message_sender_handle
|
||||||
.method(self.path.as_str(), method, &serialized, fds)?
|
.method(self.id, method, &serialized, fds)?
|
||||||
.await
|
.await
|
||||||
.map_err(|e| eyre!(e))?;
|
.map_err(|e| eyre!(e))?;
|
||||||
|
|
||||||
@@ -261,10 +244,7 @@ impl Node {
|
|||||||
}
|
}
|
||||||
impl Debug for Node {
|
impl Debug for Node {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.debug_struct("Node")
|
f.debug_struct("Node").field("id", &self.id).finish()
|
||||||
.field("uid", &self.uid)
|
|
||||||
.field("path", &self.path)
|
|
||||||
.finish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl OwnedAspect for Node {
|
impl OwnedAspect for Node {
|
||||||
|
|||||||
@@ -1,128 +1,73 @@
|
|||||||
use super::spatial::Spatial;
|
use super::spatial::Spatial;
|
||||||
use super::{Message, Node};
|
use super::Node;
|
||||||
use crate::core::client::Client;
|
use crate::core::client::Client;
|
||||||
use crate::core::client_state::{ClientState, ClientStateInternal};
|
use crate::core::client_state::ClientStateParsed;
|
||||||
use crate::core::registry::Registry;
|
use crate::core::registry::Registry;
|
||||||
use crate::core::scenegraph::MethodResponseSender;
|
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
use crate::wayland::WAYLAND_DISPLAY;
|
use crate::wayland::WAYLAND_DISPLAY;
|
||||||
#[cfg(feature = "xwayland")]
|
#[cfg(feature = "xwayland")]
|
||||||
use crate::wayland::X_DISPLAY;
|
use crate::wayland::X_DISPLAY;
|
||||||
use crate::STARDUST_INSTANCE;
|
use crate::STARDUST_INSTANCE;
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::{bail, Result};
|
||||||
use glam::Mat4;
|
use glam::Mat4;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use stardust_xr::schemas::flex::{deserialize, serialize};
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tracing::{info, instrument};
|
use tracing::info;
|
||||||
|
|
||||||
static ROOT_REGISTRY: Registry<Root> = Registry::new();
|
static ROOT_REGISTRY: Registry<Root> = Registry::new();
|
||||||
|
|
||||||
pub struct Root {
|
stardust_xr_server_codegen::codegen_root_protocol!();
|
||||||
pub node: Arc<Node>,
|
|
||||||
send_frame_event: AtomicBool,
|
pub struct Root(Arc<Node>);
|
||||||
}
|
|
||||||
impl Root {
|
impl Root {
|
||||||
pub fn create(client: &Arc<Client>) -> Result<Arc<Self>> {
|
pub fn create(client: &Arc<Client>, transform: Mat4) -> Result<Arc<Self>> {
|
||||||
let node = Node::create_parent_name(client, "", "", false);
|
let node = Node::from_id(client, 0, false);
|
||||||
node.add_local_signal("subscribe_frame", Root::subscribe_frame_flex);
|
<Self as RootAspect>::add_node_members(&node);
|
||||||
node.add_local_signal("set_base_prefixes", Root::set_base_prefixes_flex);
|
|
||||||
node.add_local_method("state_token", Root::state_token_flex);
|
|
||||||
node.add_local_method(
|
|
||||||
"get_connection_environment",
|
|
||||||
get_connection_environment_flex,
|
|
||||||
);
|
|
||||||
let node = node.add_to_scenegraph()?;
|
let node = node.add_to_scenegraph()?;
|
||||||
let _ = Spatial::add_to(&node, None, client.state.root, false);
|
let _ = Spatial::add_to(&node, None, transform, false);
|
||||||
|
|
||||||
Ok(ROOT_REGISTRY.add(Root {
|
Ok(ROOT_REGISTRY.add(Root(node)))
|
||||||
node,
|
|
||||||
send_frame_event: AtomicBool::from(false),
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subscribe_frame_flex(
|
|
||||||
_node: Arc<Node>,
|
|
||||||
calling_client: Arc<Client>,
|
|
||||||
_message: Message,
|
|
||||||
) -> Result<()> {
|
|
||||||
calling_client
|
|
||||||
.root
|
|
||||||
.get()
|
|
||||||
.unwrap()
|
|
||||||
.send_frame_event
|
|
||||||
.store(true, Ordering::Relaxed);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(level = "debug")]
|
|
||||||
pub fn send_frame_events(delta: f64) {
|
pub fn send_frame_events(delta: f64) {
|
||||||
if let Ok(data) = serialize((delta, 0.0)) {
|
let info = FrameInfo {
|
||||||
|
delta: delta as f32,
|
||||||
|
elapsed: 0.0,
|
||||||
|
};
|
||||||
for root in ROOT_REGISTRY.get_valid_contents() {
|
for root in ROOT_REGISTRY.get_valid_contents() {
|
||||||
if root.send_frame_event.load(Ordering::Relaxed) {
|
let _ = root_client::frame(&root.0, &info);
|
||||||
let _ = root.node.send_remote_signal("frame", data.clone());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_base_prefixes_flex(
|
|
||||||
_node: Arc<Node>,
|
|
||||||
calling_client: Arc<Client>,
|
|
||||||
message: Message,
|
|
||||||
) -> Result<()> {
|
|
||||||
let prefixes: Vec<PathBuf> = deserialize(message.as_ref())?;
|
|
||||||
info!(?calling_client, ?prefixes, "Set base prefixes");
|
|
||||||
*calling_client.base_resource_prefixes.lock() = prefixes;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn state_token_flex(
|
|
||||||
_node: Arc<Node>,
|
|
||||||
calling_client: Arc<Client>,
|
|
||||||
message: Message,
|
|
||||||
response: MethodResponseSender,
|
|
||||||
) {
|
|
||||||
response.wrap_sync(|| {
|
|
||||||
let state: ClientStateInternal = deserialize(message.as_ref())?;
|
|
||||||
let token = ClientState::from_deserialized(&calling_client, state).token();
|
|
||||||
Ok(serialize(token)?.into())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_transform(&self, transform: Mat4) {
|
pub fn set_transform(&self, transform: Mat4) {
|
||||||
let spatial = self.node.get_aspect::<Spatial>().unwrap();
|
let spatial = self.0.get_aspect::<Spatial>().unwrap();
|
||||||
spatial.set_spatial_parent(None).unwrap();
|
spatial.set_spatial_parent(None).unwrap();
|
||||||
spatial.set_local_transform(transform);
|
spatial.set_local_transform(transform);
|
||||||
}
|
}
|
||||||
pub async fn save_state(&self) -> Result<ClientStateInternal> {
|
pub async fn save_state(&self) -> Result<ClientState> {
|
||||||
self.node
|
Ok(root_client::save_state(&self.0).await?.0)
|
||||||
.execute_remote_method_typed("save_state", (), Vec::new())
|
|
||||||
.await
|
|
||||||
.map(|(m, _)| m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for Root {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
ROOT_REGISTRY.remove(self);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl RootAspect for Root {
|
||||||
|
async fn get_state(_node: Arc<Node>, calling_client: Arc<Client>) -> Result<ClientState> {
|
||||||
|
let Some(state) = calling_client.state.get() else {
|
||||||
|
bail!("Couldn't get state");
|
||||||
|
};
|
||||||
|
Ok(state.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc = "Get a hashmap of all the environment variables to connect a given app to the stardust server"]
|
||||||
|
async fn get_connection_environment(
|
||||||
|
_node: Arc<Node>,
|
||||||
|
_calling_client: Arc<Client>,
|
||||||
|
) -> Result<stardust_xr::values::Map<String, String>> {
|
||||||
macro_rules! var_env_insert {
|
macro_rules! var_env_insert {
|
||||||
($env:ident, $name:ident) => {
|
($env:ident, $name:ident) => {
|
||||||
$env.insert(stringify!($name).to_string(), $name.get().unwrap().clone());
|
$env.insert(stringify!($name).to_string(), $name.get().unwrap().clone());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub fn get_connection_environment_flex(
|
|
||||||
_node: Arc<Node>,
|
|
||||||
_calling_client: Arc<Client>,
|
|
||||||
_message: Message,
|
|
||||||
response: MethodResponseSender,
|
|
||||||
) {
|
|
||||||
response.wrap_sync(move || {
|
|
||||||
let mut env: FxHashMap<String, String> = FxHashMap::default();
|
let mut env: FxHashMap<String, String> = FxHashMap::default();
|
||||||
var_env_insert!(env, STARDUST_INSTANCE);
|
var_env_insert!(env, STARDUST_INSTANCE);
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
@@ -140,6 +85,38 @@ pub fn get_connection_environment_flex(
|
|||||||
env.insert("SDL_VIDEODRIVER".to_string(), "wayland".to_string());
|
env.insert("SDL_VIDEODRIVER".to_string(), "wayland".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(serialize(env)?.into())
|
Ok(env)
|
||||||
});
|
}
|
||||||
|
|
||||||
|
#[doc = "Generate a client state token and return it back.\n\n When launching a new client, set the environment variable `STARDUST_STARTUP_TOKEN` to the returned string.\n Make sure the environment variable shows in `/proc/{pid}/environ` as that's the only reliable way to pass the value to the server (suggestions welcome).\n"]
|
||||||
|
async fn client_state_token(
|
||||||
|
_node: Arc<Node>,
|
||||||
|
calling_client: Arc<Client>,
|
||||||
|
state: ClientState,
|
||||||
|
) -> Result<String> {
|
||||||
|
Ok(ClientStateParsed::from_deserialized(&calling_client, state).token())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc = "Set initial list of folders to look for namespaced resources in"]
|
||||||
|
fn set_base_prefixes(
|
||||||
|
_node: Arc<Node>,
|
||||||
|
calling_client: Arc<Client>,
|
||||||
|
prefixes: Vec<String>,
|
||||||
|
) -> Result<()> {
|
||||||
|
info!(?calling_client, ?prefixes, "Set base prefixes");
|
||||||
|
*calling_client.base_resource_prefixes.lock() =
|
||||||
|
prefixes.into_iter().map(PathBuf::from).collect();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc = "Cleanly disconnect from the server"]
|
||||||
|
fn disconnect(_node: Arc<Node>, calling_client: Arc<Client>) -> color_eyre::eyre::Result<()> {
|
||||||
|
calling_client.disconnect(Ok(()));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Drop for Root {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
ROOT_REGISTRY.remove(self);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ use crate::create_interface;
|
|||||||
use color_eyre::eyre::{eyre, Result};
|
use color_eyre::eyre::{eyre, Result};
|
||||||
use glam::{vec3a, Mat4, Quat, Vec3};
|
use glam::{vec3a, Mat4, Quat, Vec3};
|
||||||
use mint::Vector3;
|
use mint::Vector3;
|
||||||
use nanoid::nanoid;
|
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
@@ -40,20 +39,18 @@ impl Transform {
|
|||||||
static ZONEABLE_REGISTRY: Registry<Spatial> = Registry::new();
|
static ZONEABLE_REGISTRY: Registry<Spatial> = Registry::new();
|
||||||
|
|
||||||
pub struct Spatial {
|
pub struct Spatial {
|
||||||
uid: String,
|
node: Weak<Node>,
|
||||||
pub(super) node: Weak<Node>,
|
|
||||||
parent: Mutex<Option<Arc<Spatial>>>,
|
parent: Mutex<Option<Arc<Spatial>>>,
|
||||||
old_parent: Mutex<Option<Arc<Spatial>>>,
|
old_parent: Mutex<Option<Arc<Spatial>>>,
|
||||||
pub(super) transform: Mutex<Mat4>,
|
transform: Mutex<Mat4>,
|
||||||
zone: Mutex<Weak<Zone>>,
|
zone: Mutex<Weak<Zone>>,
|
||||||
children: Registry<Spatial>,
|
children: Registry<Spatial>,
|
||||||
pub(super) bounding_box_calc: OnceCell<fn(&Node) -> Bounds>,
|
pub bounding_box_calc: OnceCell<fn(&Node) -> Bounds>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Spatial {
|
impl Spatial {
|
||||||
pub fn new(node: Weak<Node>, parent: Option<Arc<Spatial>>, transform: Mat4) -> Arc<Self> {
|
pub fn new(node: Weak<Node>, parent: Option<Arc<Spatial>>, transform: Mat4) -> Arc<Self> {
|
||||||
Arc::new(Spatial {
|
Arc::new(Spatial {
|
||||||
uid: nanoid!(),
|
|
||||||
node,
|
node,
|
||||||
parent: Mutex::new(parent),
|
parent: Mutex::new(parent),
|
||||||
old_parent: Mutex::new(None),
|
old_parent: Mutex::new(None),
|
||||||
@@ -232,7 +229,7 @@ impl Spatial {
|
|||||||
self.zone
|
self.zone
|
||||||
.lock()
|
.lock()
|
||||||
.upgrade()
|
.upgrade()
|
||||||
.and_then(|zone| zone.field.upgrade())
|
.map(|zone| zone.field.clone())
|
||||||
.map(|field| field.distance(self, vec3a(0.0, 0.0, 0.0)))
|
.map(|field| field.distance(self, vec3a(0.0, 0.0, 0.0)))
|
||||||
.unwrap_or(f32::MAX)
|
.unwrap_or(f32::MAX)
|
||||||
}
|
}
|
||||||
@@ -359,13 +356,12 @@ impl SpatialAspect for Spatial {
|
|||||||
}
|
}
|
||||||
impl PartialEq for Spatial {
|
impl PartialEq for Spatial {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.uid == other.uid
|
self.node.as_ptr() == other.node.as_ptr()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Debug for Spatial {
|
impl Debug for Spatial {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.debug_struct("Spatial")
|
f.debug_struct("Spatial")
|
||||||
.field("uid", &self.uid)
|
|
||||||
.field("parent", &self.parent)
|
.field("parent", &self.parent)
|
||||||
.field("old_parent", &self.old_parent)
|
.field("old_parent", &self.old_parent)
|
||||||
.field("transform", &self.transform)
|
.field("transform", &self.transform)
|
||||||
@@ -374,7 +370,7 @@ impl Debug for Spatial {
|
|||||||
}
|
}
|
||||||
impl Drop for Spatial {
|
impl Drop for Spatial {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
zone::release_drop(self);
|
zone::release(self);
|
||||||
ZONEABLE_REGISTRY.remove(self);
|
ZONEABLE_REGISTRY.remove(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -397,26 +393,25 @@ pub fn parse_transform(transform: Transform, position: bool, rotation: bool, sca
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct SpatialInterface;
|
pub struct SpatialInterface;
|
||||||
impl SpatialInterfaceAspect for SpatialInterface {
|
impl InterfaceAspect for SpatialInterface {
|
||||||
fn create_spatial(
|
fn create_spatial(
|
||||||
_node: Arc<Node>,
|
_node: Arc<Node>,
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
name: String,
|
id: u64,
|
||||||
parent: Arc<Node>,
|
parent: Arc<Node>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
zoneable: bool,
|
zoneable: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let parent = parent.get_aspect::<Spatial>()?;
|
let parent = parent.get_aspect::<Spatial>()?;
|
||||||
let transform = parse_transform(transform, true, true, true);
|
let transform = parse_transform(transform, true, true, true);
|
||||||
let node = Node::create_parent_name(&calling_client, "/spatial/spatial", &name, true)
|
let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?;
|
||||||
.add_to_scenegraph()?;
|
|
||||||
Spatial::add_to(&node, Some(parent.clone()), transform, zoneable);
|
Spatial::add_to(&node, Some(parent.clone()), transform, zoneable);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn create_zone(
|
fn create_zone(
|
||||||
_node: Arc<Node>,
|
_node: Arc<Node>,
|
||||||
calling_client: Arc<Client>,
|
calling_client: Arc<Client>,
|
||||||
name: String,
|
id: u64,
|
||||||
parent: Arc<Node>,
|
parent: Arc<Node>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
field: Arc<Node>,
|
field: Arc<Node>,
|
||||||
@@ -425,12 +420,11 @@ impl SpatialInterfaceAspect for SpatialInterface {
|
|||||||
let transform = parse_transform(transform, true, true, false);
|
let transform = parse_transform(transform, true, true, false);
|
||||||
let field = field.get_aspect::<Field>()?;
|
let field = field.get_aspect::<Field>()?;
|
||||||
|
|
||||||
let node = Node::create_parent_name(&calling_client, "/spatial/zone", &name, true)
|
let node = Node::from_id(&calling_client, id, true).add_to_scenegraph()?;
|
||||||
.add_to_scenegraph()?;
|
|
||||||
let space = Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
let space = Spatial::add_to(&node, Some(parent.clone()), transform, false);
|
||||||
Zone::add_to(&node, space, &field);
|
Zone::add_to(&node, space, field);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
create_interface!(SpatialInterface, SpatialInterfaceAspect, "/spatial");
|
create_interface!(SpatialInterface);
|
||||||
|
|||||||
@@ -1,166 +1,147 @@
|
|||||||
use super::{Spatial, ZoneAspect, ZONEABLE_REGISTRY};
|
use super::{
|
||||||
|
Spatial, ZoneAspect, SPATIAL_ASPECT_ALIAS_INFO, SPATIAL_REF_ASPECT_ALIAS_INFO,
|
||||||
|
ZONEABLE_REGISTRY,
|
||||||
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
core::{client::Client, registry::Registry},
|
core::{client::Client, registry::Registry},
|
||||||
nodes::{
|
nodes::{
|
||||||
alias::{Alias, AliasInfo},
|
alias::{get_original, Alias, AliasList},
|
||||||
fields::Field,
|
fields::Field,
|
||||||
Aspect, Node,
|
Aspect, Node,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use color_eyre::eyre::Result;
|
||||||
use glam::vec3a;
|
use glam::vec3a;
|
||||||
use parking_lot::Mutex;
|
|
||||||
use rustc_hash::FxHashMap;
|
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
|
|
||||||
pub fn capture(spatial: &Arc<Spatial>, zone: &Arc<Zone>) {
|
pub fn capture(spatial: &Arc<Spatial>, zone: &Arc<Zone>) {
|
||||||
let old_distance = spatial.zone_distance();
|
let old_distance = spatial.zone_distance();
|
||||||
let new_distance = zone
|
let new_distance = zone.field.distance(spatial, vec3a(0.0, 0.0, 0.0));
|
||||||
.field
|
|
||||||
.upgrade()
|
|
||||||
.map(|field| field.distance(spatial, vec3a(0.0, 0.0, 0.0)))
|
|
||||||
.unwrap_or(f32::MAX);
|
|
||||||
if new_distance.abs() < old_distance.abs() {
|
if new_distance.abs() < old_distance.abs() {
|
||||||
release(spatial);
|
release(spatial);
|
||||||
*spatial.old_parent.lock() = spatial.get_parent();
|
*spatial.old_parent.lock() = spatial.get_parent();
|
||||||
*spatial.zone.lock() = Arc::downgrade(zone);
|
*spatial.zone.lock() = Arc::downgrade(zone);
|
||||||
zone.captured.add_raw(spatial);
|
let Some(zone_node) = zone.spatial.node.upgrade() else {
|
||||||
let Some(node) = zone.spatial.node.upgrade() else {
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let _ = super::zone_client::capture(&node, &spatial.uid);
|
let Some(spatial_node) = spatial.node.upgrade() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Ok(spatial_alias) = Alias::create(
|
||||||
|
&spatial_node,
|
||||||
|
&zone_node.get_client().unwrap(),
|
||||||
|
SPATIAL_ASPECT_ALIAS_INFO.clone(),
|
||||||
|
Some(&zone.captured),
|
||||||
|
) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let _ = super::zone_client::capture(&zone_node, &spatial_alias);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn release(spatial: &Arc<Spatial>) {
|
pub fn release(spatial: &Spatial) {
|
||||||
|
let Some(spatial_node) = spatial.node.upgrade() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let spatial = spatial_node.get_aspect::<Spatial>().unwrap();
|
||||||
|
|
||||||
let _ = spatial.set_spatial_parent_in_place(spatial.old_parent.lock().take().as_ref());
|
let _ = spatial.set_spatial_parent_in_place(spatial.old_parent.lock().take().as_ref());
|
||||||
let mut spatial_zone = spatial.zone.lock();
|
let mut spatial_zone = spatial.zone.lock();
|
||||||
|
|
||||||
if let Some(spatial_zone) = spatial_zone.upgrade() {
|
if let Some(spatial_zone) = spatial_zone.upgrade() {
|
||||||
|
spatial_zone.captured.remove_aspect(spatial.as_ref());
|
||||||
let Some(node) = spatial_zone.spatial.node.upgrade() else {
|
let Some(node) = spatial_zone.spatial.node.upgrade() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
spatial_zone.captured.remove(spatial);
|
let _ = super::zone_client::release(&node, spatial_node.id);
|
||||||
let _ = super::zone_client::release(&node, &spatial.uid);
|
|
||||||
}
|
}
|
||||||
*spatial_zone = Weak::new();
|
*spatial_zone = Weak::new();
|
||||||
}
|
}
|
||||||
pub(super) fn release_drop(spatial: &Spatial) {
|
|
||||||
let spatial_zone = spatial.zone.lock();
|
|
||||||
if let Some(spatial_zone) = spatial_zone.upgrade() {
|
|
||||||
let Some(node) = spatial_zone.spatial.node.upgrade() else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
spatial_zone.captured.remove(spatial);
|
|
||||||
let _ = super::zone_client::release(&node, &spatial.uid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Zone {
|
pub struct Zone {
|
||||||
spatial: Arc<Spatial>,
|
spatial: Arc<Spatial>,
|
||||||
pub field: Weak<Field>,
|
pub field: Arc<Field>,
|
||||||
zoneables: Mutex<FxHashMap<String, Arc<Node>>>,
|
intersecting_spatials: Registry<Spatial>,
|
||||||
captured: Registry<Spatial>,
|
intersecting: AliasList,
|
||||||
|
captured: AliasList,
|
||||||
}
|
}
|
||||||
impl Zone {
|
impl Zone {
|
||||||
pub fn add_to(node: &Arc<Node>, spatial: Arc<Spatial>, field: &Arc<Field>) -> Arc<Zone> {
|
pub fn add_to(node: &Arc<Node>, spatial: Arc<Spatial>, field: Arc<Field>) -> Arc<Zone> {
|
||||||
let zone = Arc::new(Zone {
|
let zone = Arc::new(Zone {
|
||||||
spatial,
|
spatial,
|
||||||
field: Arc::downgrade(field),
|
field,
|
||||||
zoneables: Mutex::new(FxHashMap::default()),
|
intersecting_spatials: Registry::default(),
|
||||||
captured: Registry::new(),
|
intersecting: AliasList::default(),
|
||||||
|
captured: AliasList::default(),
|
||||||
});
|
});
|
||||||
<Zone as ZoneAspect>::add_node_members(node);
|
<Zone as ZoneAspect>::add_node_members(node);
|
||||||
node.add_aspect_raw(zone.clone());
|
node.add_aspect_raw(zone.clone());
|
||||||
zone
|
zone
|
||||||
}
|
}
|
||||||
|
pub fn update(&self) -> Result<()> {
|
||||||
|
let node = self.spatial.node().unwrap();
|
||||||
|
|
||||||
|
let current_zoneables = Registry::new();
|
||||||
|
for zoneable in ZONEABLE_REGISTRY.get_valid_contents() {
|
||||||
|
let distance = self.field.distance(&zoneable, [0.0; 3].into());
|
||||||
|
if distance > 0.0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let Some(zone) = zoneable.zone.lock().upgrade() {
|
||||||
|
let zoneable_distance = zone.field.distance(&zoneable, [0.0; 3].into());
|
||||||
|
if zoneable_distance < distance {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current_zoneables.add_raw(&zoneable);
|
||||||
|
}
|
||||||
|
|
||||||
|
let (added, removed) =
|
||||||
|
Registry::get_changes(&self.intersecting_spatials, ¤t_zoneables);
|
||||||
|
for added in added {
|
||||||
|
let Some(added_node) = added.node() else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let Ok(alias) = Alias::create(
|
||||||
|
&added_node,
|
||||||
|
&self.spatial.node().unwrap().get_client().unwrap(),
|
||||||
|
SPATIAL_REF_ASPECT_ALIAS_INFO.clone(),
|
||||||
|
Some(&self.intersecting),
|
||||||
|
) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let _ = super::zone_client::enter(&node, &alias);
|
||||||
|
}
|
||||||
|
for removed in removed {
|
||||||
|
let Some(removed_node) = removed.node() else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
release(&removed);
|
||||||
|
let _ = super::zone_client::leave(&node, removed_node.id);
|
||||||
|
self.intersecting.remove_aspect(removed.as_ref());
|
||||||
|
}
|
||||||
|
self.intersecting_spatials.set(¤t_zoneables);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
impl Aspect for Zone {
|
impl Aspect for Zone {
|
||||||
const NAME: &'static str = "Zone";
|
const NAME: &'static str = "Zone";
|
||||||
}
|
}
|
||||||
impl ZoneAspect for Zone {
|
impl ZoneAspect for Zone {
|
||||||
fn update(node: Arc<Node>, _calling_client: Arc<Client>) -> color_eyre::eyre::Result<()> {
|
fn update(node: Arc<Node>, _calling_client: Arc<Client>) -> Result<()> {
|
||||||
let zone = node.get_aspect::<Zone>()?;
|
let zone = node.get_aspect::<Zone>()?;
|
||||||
let Some(field) = zone.field.upgrade() else {
|
let _ = zone.update();
|
||||||
return Err(color_eyre::eyre::eyre!("Zone's field has been destroyed"));
|
|
||||||
};
|
|
||||||
let Some((zone_client, zone_node)) = zone
|
|
||||||
.spatial
|
|
||||||
.node
|
|
||||||
.upgrade()
|
|
||||||
.and_then(|n| n.get_client().zip(Some(n)))
|
|
||||||
else {
|
|
||||||
return Err(color_eyre::eyre::eyre!("No client on node?"));
|
|
||||||
};
|
|
||||||
let mut old_zoneables = zone.zoneables.lock();
|
|
||||||
for (_uid, zoneable) in old_zoneables.iter() {
|
|
||||||
zoneable.destroy();
|
|
||||||
}
|
|
||||||
let captured = zone.captured.get_valid_contents();
|
|
||||||
let zoneables = ZONEABLE_REGISTRY
|
|
||||||
.get_valid_contents()
|
|
||||||
.into_iter()
|
|
||||||
.filter(|zoneable| zoneable.node.upgrade().is_some())
|
|
||||||
.filter(|zoneable| {
|
|
||||||
if captured
|
|
||||||
.iter()
|
|
||||||
.any(|captured| Arc::ptr_eq(captured, zoneable))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
let spatial_zone_distance = zoneable.zone_distance();
|
|
||||||
let self_zone_distance = field.distance(zoneable, vec3a(0.0, 0.0, 0.0));
|
|
||||||
self_zone_distance < 0.0 && spatial_zone_distance > self_zone_distance
|
|
||||||
})
|
|
||||||
.filter_map(|zoneable| {
|
|
||||||
let alias = Alias::create(
|
|
||||||
&zone_client,
|
|
||||||
zone_node.get_path(),
|
|
||||||
&zoneable.uid,
|
|
||||||
&zoneable.node.upgrade().unwrap(),
|
|
||||||
AliasInfo {
|
|
||||||
server_signals: vec![
|
|
||||||
"set_transform",
|
|
||||||
"set_spatial_parent",
|
|
||||||
"set_spatial_parent_in_place",
|
|
||||||
],
|
|
||||||
server_methods: vec!["get_bounds", "get_transform"],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.ok()?;
|
|
||||||
Some((zoneable.uid.clone(), alias))
|
|
||||||
})
|
|
||||||
.collect::<FxHashMap<String, Arc<Node>>>();
|
|
||||||
|
|
||||||
for (uid, zoneable) in zoneables
|
|
||||||
.iter()
|
|
||||||
.filter(|(k, _)| !old_zoneables.contains_key(*k))
|
|
||||||
{
|
|
||||||
super::zone_client::enter(&node, uid, zoneable)?;
|
|
||||||
}
|
|
||||||
for left_uid in old_zoneables.keys().filter(|k| !zoneables.contains_key(*k)) {
|
|
||||||
super::zone_client::leave(&node, &left_uid)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
*old_zoneables = zoneables;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn capture(
|
fn capture(node: Arc<Node>, _calling_client: Arc<Client>, spatial: Arc<Node>) -> Result<()> {
|
||||||
node: Arc<Node>,
|
|
||||||
_calling_client: Arc<Client>,
|
|
||||||
spatial: Arc<Node>,
|
|
||||||
) -> color_eyre::eyre::Result<()> {
|
|
||||||
let zone = node.get_aspect::<Zone>()?;
|
let zone = node.get_aspect::<Zone>()?;
|
||||||
let spatial = spatial.get_aspect()?;
|
let spatial = spatial.get_aspect()?;
|
||||||
capture(&spatial, &zone);
|
capture(&spatial, &zone);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn release(
|
fn release(_node: Arc<Node>, _calling_client: Arc<Client>, spatial: Arc<Node>) -> Result<()> {
|
||||||
_node: Arc<Node>,
|
|
||||||
_calling_client: Arc<Client>,
|
|
||||||
spatial: Arc<Node>,
|
|
||||||
) -> color_eyre::eyre::Result<()> {
|
|
||||||
let spatial = spatial.get_aspect()?;
|
let spatial = spatial.get_aspect()?;
|
||||||
release(&spatial);
|
release(&spatial);
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -168,7 +149,13 @@ impl ZoneAspect for Zone {
|
|||||||
}
|
}
|
||||||
impl Drop for Zone {
|
impl Drop for Zone {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
for captured in self.captured.get_valid_contents() {
|
for captured in self
|
||||||
|
.captured
|
||||||
|
.get_aliases()
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(get_original)
|
||||||
|
.filter_map(|n| n.get_aspect::<Spatial>().ok())
|
||||||
|
{
|
||||||
release(&captured);
|
release(&captured);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use glam::{vec3, Mat4};
|
use glam::{vec3, Mat4};
|
||||||
use nanoid::nanoid;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use stardust_xr::values::Datamap;
|
use stardust_xr::values::Datamap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -34,8 +33,7 @@ pub struct EyePointer {
|
|||||||
}
|
}
|
||||||
impl EyePointer {
|
impl EyePointer {
|
||||||
pub fn new() -> Result<Self> {
|
pub fn new() -> Result<Self> {
|
||||||
let node = Node::create_parent_name(&INTERNAL_CLIENT, "", &nanoid!(), false)
|
let node = Node::generate(&INTERNAL_CLIENT, false).add_to_scenegraph()?;
|
||||||
.add_to_scenegraph()?;
|
|
||||||
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false);
|
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false);
|
||||||
let pointer = InputMethod::add_to(
|
let pointer = InputMethod::add_to(
|
||||||
&node,
|
&node,
|
||||||
@@ -62,7 +60,7 @@ impl EyePointer {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
// filter out all the disabled handlers
|
// filter out all the disabled handlers
|
||||||
.filter(|handler| {
|
.filter(|handler| {
|
||||||
let Some(node) = handler.node.upgrade() else {
|
let Some(node) = handler.spatial.node() else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
node.enabled()
|
node.enabled()
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use crate::{
|
|||||||
data::{
|
data::{
|
||||||
mask_matches, pulse_receiver_client, PulseSender, KEYMAPS, PULSE_RECEIVER_REGISTRY,
|
mask_matches, pulse_receiver_client, PulseSender, KEYMAPS, PULSE_RECEIVER_REGISTRY,
|
||||||
},
|
},
|
||||||
fields::{Field, Ray},
|
fields::Ray,
|
||||||
input::{InputDataType, InputHandler, InputMethod, Pointer, INPUT_HANDLER_REGISTRY},
|
input::{InputDataType, InputHandler, InputMethod, Pointer, INPUT_HANDLER_REGISTRY},
|
||||||
spatial::Spatial,
|
spatial::Spatial,
|
||||||
Node,
|
Node,
|
||||||
@@ -13,8 +13,8 @@ use crate::{
|
|||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use glam::{vec3, Mat4, Vec3};
|
use glam::{vec3, Mat4, Vec3};
|
||||||
use mint::Vector2;
|
use mint::Vector2;
|
||||||
use nanoid::nanoid;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use slotmap::DefaultKey;
|
||||||
use stardust_xr::values::Datamap;
|
use stardust_xr::values::Datamap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use stereokit_rust::system::{Input, Key};
|
use stereokit_rust::system::{Input, Key};
|
||||||
@@ -62,8 +62,10 @@ impl Default for KeyboardEvent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub struct MousePointer {
|
pub struct MousePointer {
|
||||||
node: Arc<Node>,
|
node: Arc<Node>,
|
||||||
|
keymap: DefaultKey,
|
||||||
spatial: Arc<Spatial>,
|
spatial: Arc<Spatial>,
|
||||||
pointer: Arc<InputMethod>,
|
pointer: Arc<InputMethod>,
|
||||||
capture: Option<Arc<InputHandler>>,
|
capture: Option<Arc<InputHandler>>,
|
||||||
@@ -73,8 +75,7 @@ pub struct MousePointer {
|
|||||||
}
|
}
|
||||||
impl MousePointer {
|
impl MousePointer {
|
||||||
pub fn new() -> Result<Self> {
|
pub fn new() -> Result<Self> {
|
||||||
let node = Node::create_parent_name(&INTERNAL_CLIENT, "", &nanoid!(), false)
|
let node = Node::generate(&INTERNAL_CLIENT, false).add_to_scenegraph()?;
|
||||||
.add_to_scenegraph()?;
|
|
||||||
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false);
|
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false);
|
||||||
let pointer = InputMethod::add_to(
|
let pointer = InputMethod::add_to(
|
||||||
&node,
|
&node,
|
||||||
@@ -82,8 +83,7 @@ impl MousePointer {
|
|||||||
Datamap::from_typed(MouseEvent::default())?,
|
Datamap::from_typed(MouseEvent::default())?,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
KEYMAPS.lock().insert(
|
let keymap = KEYMAPS.lock().insert(
|
||||||
"flatscreen".to_string(),
|
|
||||||
Keymap::new_from_names(&Context::new(0), "evdev", "", "", "", None, 0)
|
Keymap::new_from_names(&Context::new(0), "evdev", "", "", "", None, 0)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get_as_string(FORMAT_TEXT_V1),
|
.get_as_string(FORMAT_TEXT_V1),
|
||||||
@@ -97,6 +97,7 @@ impl MousePointer {
|
|||||||
|
|
||||||
Ok(MousePointer {
|
Ok(MousePointer {
|
||||||
node,
|
node,
|
||||||
|
keymap,
|
||||||
spatial,
|
spatial,
|
||||||
pointer,
|
pointer,
|
||||||
capture: None,
|
capture: None,
|
||||||
@@ -206,7 +207,7 @@ impl MousePointer {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
// filter out all the disabled handlers
|
// filter out all the disabled handlers
|
||||||
.filter(|handler| {
|
.filter(|handler| {
|
||||||
let Some(node) = handler.node.upgrade() else {
|
let Some(node) = handler.spatial.node() else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
node.enabled()
|
node.enabled()
|
||||||
@@ -253,7 +254,7 @@ impl MousePointer {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|rx| mask_matches(&rx.mask, &self.keyboard_sender.mask))
|
.filter(|rx| mask_matches(&rx.mask, &self.keyboard_sender.mask))
|
||||||
.map(|rx| {
|
.map(|rx| {
|
||||||
let result = rx.field_node.get_aspect::<Field>().unwrap().ray_march(Ray {
|
let result = rx.field.ray_march(Ray {
|
||||||
origin: vec3(0.0, 0.0, 0.0),
|
origin: vec3(0.0, 0.0, 0.0),
|
||||||
direction: vec3(0.0, 0.0, -1.0),
|
direction: vec3(0.0, 0.0, -1.0),
|
||||||
space: self.spatial.clone(),
|
space: self.spatial.clone(),
|
||||||
@@ -291,7 +292,7 @@ impl MousePointer {
|
|||||||
if !self.keyboard_datamap.keys.is_empty() {
|
if !self.keyboard_datamap.keys.is_empty() {
|
||||||
pulse_receiver_client::data(
|
pulse_receiver_client::data(
|
||||||
&rx.node.upgrade().unwrap(),
|
&rx.node.upgrade().unwrap(),
|
||||||
&self.node.uid,
|
&self.node,
|
||||||
&Datamap::from_typed(&self.keyboard_datamap).unwrap(),
|
&Datamap::from_typed(&self.keyboard_datamap).unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@@ -34,17 +34,7 @@ pub struct SkController {
|
|||||||
}
|
}
|
||||||
impl SkController {
|
impl SkController {
|
||||||
pub fn new(handed: Handed) -> Result<Self> {
|
pub fn new(handed: Handed) -> Result<Self> {
|
||||||
let _node = Node::create_parent_name(
|
let _node = Node::generate(&INTERNAL_CLIENT, false).add_to_scenegraph()?;
|
||||||
&INTERNAL_CLIENT,
|
|
||||||
"",
|
|
||||||
if handed == Handed::Left {
|
|
||||||
"controller_left"
|
|
||||||
} else {
|
|
||||||
"controller_right"
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.add_to_scenegraph()?;
|
|
||||||
Spatial::add_to(&_node, None, Mat4::IDENTITY, false);
|
Spatial::add_to(&_node, None, Mat4::IDENTITY, false);
|
||||||
let model = Model::from_memory("cursor.glb", include_bytes!("cursor.glb"), None)?;
|
let model = Model::from_memory("cursor.glb", include_bytes!("cursor.glb"), None)?;
|
||||||
let tip = InputDataType::Tip(Tip::default());
|
let tip = InputDataType::Tip(Tip::default());
|
||||||
@@ -135,7 +125,7 @@ impl SkController {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
// filter out all the disabled handlers
|
// filter out all the disabled handlers
|
||||||
.filter(|handler| {
|
.filter(|handler| {
|
||||||
let Some(node) = handler.node.upgrade() else {
|
let Some(node) = handler.spatial.node() else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
node.enabled()
|
node.enabled()
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ use crate::nodes::{
|
|||||||
};
|
};
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use glam::{Mat4, Quat, Vec3};
|
use glam::{Mat4, Quat, Vec3};
|
||||||
use nanoid::nanoid;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use stardust_xr::values::Datamap;
|
use stardust_xr::values::Datamap;
|
||||||
use std::f32::INFINITY;
|
use std::f32::INFINITY;
|
||||||
@@ -41,8 +40,7 @@ pub struct SkHand {
|
|||||||
}
|
}
|
||||||
impl SkHand {
|
impl SkHand {
|
||||||
pub fn new(handed: Handed) -> Result<Self> {
|
pub fn new(handed: Handed) -> Result<Self> {
|
||||||
let _node = Node::create_parent_name(&INTERNAL_CLIENT, "", &nanoid!(), false)
|
let _node = Node::generate(&INTERNAL_CLIENT, false).add_to_scenegraph()?;
|
||||||
.add_to_scenegraph()?;
|
|
||||||
Spatial::add_to(&_node, None, Mat4::IDENTITY, false);
|
Spatial::add_to(&_node, None, Mat4::IDENTITY, false);
|
||||||
let hand = InputDataType::Hand(Hand {
|
let hand = InputDataType::Hand(Hand {
|
||||||
right: handed == Handed::Right,
|
right: handed == Handed::Right,
|
||||||
@@ -156,7 +154,7 @@ impl SkHand {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
// filter out all the disabled handlers
|
// filter out all the disabled handlers
|
||||||
.filter(|handler| {
|
.filter(|handler| {
|
||||||
let Some(node) = handler.node.upgrade() else {
|
let Some(node) = handler.spatial.node() else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
node.enabled()
|
node.enabled()
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ use std::sync::Arc;
|
|||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use glam::Mat4;
|
use glam::Mat4;
|
||||||
use mint::Vector2;
|
use mint::Vector2;
|
||||||
use nanoid::nanoid;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use stardust_xr::values::Datamap;
|
use stardust_xr::values::Datamap;
|
||||||
use stereokit_rust::system::World;
|
use stereokit_rust::system::World;
|
||||||
@@ -40,15 +39,14 @@ pub struct PlaySpace {
|
|||||||
}
|
}
|
||||||
impl PlaySpace {
|
impl PlaySpace {
|
||||||
pub fn new() -> Result<Self> {
|
pub fn new() -> Result<Self> {
|
||||||
let node = Node::create_parent_name(&INTERNAL_CLIENT, "", &nanoid!(), false)
|
let node = Node::generate(&INTERNAL_CLIENT, false).add_to_scenegraph()?;
|
||||||
.add_to_scenegraph()?;
|
|
||||||
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false);
|
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false);
|
||||||
BoxField::add_to(&node, [0.0; 3].into());
|
BoxField::add_to(&node, [0.0; 3].into());
|
||||||
let field = node.get_aspect::<Field>()?.clone();
|
let field = node.get_aspect::<Field>()?.clone();
|
||||||
|
|
||||||
let pulse_rx = PulseReceiver::add_to(
|
let pulse_rx = PulseReceiver::add_to(
|
||||||
&node,
|
&node,
|
||||||
node.clone(),
|
field.clone(),
|
||||||
Datamap::from_typed(PlaySpaceMap::default())?,
|
Datamap::from_typed(PlaySpaceMap::default())?,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use crate::{
|
|||||||
use mint::Vector2;
|
use mint::Vector2;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
use slotmap::KeyData;
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::input::{AxisRelativeDirection, ButtonState, KeyState},
|
backend::input::{AxisRelativeDirection, ButtonState, KeyState},
|
||||||
delegate_seat,
|
delegate_seat,
|
||||||
@@ -212,7 +213,7 @@ impl SeatWrapper {
|
|||||||
pointer.frame(&mut state);
|
pointer.frame(&mut state);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn keyboard_keys(&self, surface: WlSurface, keymap_id: &str, keys: Vec<i32>) {
|
pub fn keyboard_keys(&self, surface: WlSurface, keymap_id: u64, keys: Vec<i32>) {
|
||||||
let Some(state) = self.wayland_state.upgrade() else {
|
let Some(state) = self.wayland_state.upgrade() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@@ -220,7 +221,7 @@ impl SeatWrapper {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let keymaps = KEYMAPS.lock();
|
let keymaps = KEYMAPS.lock();
|
||||||
let Some(keymap) = keymaps.get(keymap_id).cloned() else {
|
let Some(keymap) = keymaps.get(KeyData::from_ffi(keymap_id).into()).cloned() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use crate::nodes::{
|
|||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use mint::Vector2;
|
use mint::Vector2;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
use rand::Rng;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use smithay::{
|
use smithay::{
|
||||||
delegate_xdg_shell,
|
delegate_xdg_shell,
|
||||||
@@ -184,7 +185,7 @@ impl XdgShellHandler for WaylandState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn new_popup(&mut self, popup: PopupSurface, positioner: PositionerState) {
|
fn new_popup(&mut self, popup: PopupSurface, positioner: PositionerState) {
|
||||||
let uid = nanoid::nanoid!();
|
let uid = rand::thread_rng().gen_range(0..u64::MAX);
|
||||||
let Some(parent) = popup.get_parent_surface() else {
|
let Some(parent) = popup.get_parent_surface() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@@ -194,8 +195,8 @@ impl XdgShellHandler for WaylandState {
|
|||||||
if popup.send_configure().is_err() {
|
if popup.send_configure().is_err() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
utils::insert_data(popup.wl_surface(), SurfaceId::Child(uid.clone()));
|
utils::insert_data(popup.wl_surface(), SurfaceId::Child(uid));
|
||||||
utils::insert_data(popup.wl_surface(), uid.clone());
|
utils::insert_data(popup.wl_surface(), uid);
|
||||||
utils::insert_data(popup.wl_surface(), Arc::downgrade(&panel_item));
|
utils::insert_data(popup.wl_surface(), Arc::downgrade(&panel_item));
|
||||||
CoreSurface::add_to(
|
CoreSurface::add_to(
|
||||||
self.display_handle.clone(),
|
self.display_handle.clone(),
|
||||||
@@ -203,9 +204,7 @@ impl XdgShellHandler for WaylandState {
|
|||||||
{
|
{
|
||||||
let popup = popup.clone();
|
let popup = popup.clone();
|
||||||
move || {
|
move || {
|
||||||
panel_item
|
panel_item.backend.new_popup(uid, popup.clone(), positioner);
|
||||||
.backend
|
|
||||||
.new_popup(&uid, popup.clone(), positioner);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -228,14 +227,14 @@ impl XdgShellHandler for WaylandState {
|
|||||||
let Some(panel_item) = surface_panel_item(popup.wl_surface()) else {
|
let Some(panel_item) = surface_panel_item(popup.wl_surface()) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(uid) = utils::get_data::<String>(popup.wl_surface())
|
let Some(SurfaceId::Child(uid)) = utils::get_data::<SurfaceId>(popup.wl_surface())
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.cloned()
|
.cloned()
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
panel_item.backend.reposition_popup(&uid, popup, positioner)
|
panel_item.backend.reposition_popup(uid, popup, positioner)
|
||||||
}
|
}
|
||||||
fn popup_destroyed(&mut self, popup: PopupSurface) {
|
fn popup_destroyed(&mut self, popup: PopupSurface) {
|
||||||
if let Some(core_surface) = CoreSurface::from_wl_surface(popup.wl_surface()) {
|
if let Some(core_surface) = CoreSurface::from_wl_surface(popup.wl_surface()) {
|
||||||
@@ -244,14 +243,14 @@ impl XdgShellHandler for WaylandState {
|
|||||||
let Some(panel_item) = surface_panel_item(popup.wl_surface()) else {
|
let Some(panel_item) = surface_panel_item(popup.wl_surface()) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(uid) = utils::get_data::<String>(popup.wl_surface())
|
let Some(SurfaceId::Child(uid)) = utils::get_data::<SurfaceId>(popup.wl_surface())
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.cloned()
|
.cloned()
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
panel_item.backend.seat.unfocus(popup.wl_surface(), self);
|
panel_item.backend.seat.unfocus(popup.wl_surface(), self);
|
||||||
panel_item.backend.drop_popup(&uid);
|
panel_item.backend.drop_popup(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn grab(&mut self, _popup: PopupSurface, _seat: WlSeat, _serial: Serial) {}
|
fn grab(&mut self, _popup: PopupSurface, _seat: WlSeat, _serial: Serial) {}
|
||||||
@@ -330,7 +329,7 @@ delegate_xdg_shell!(WaylandState);
|
|||||||
|
|
||||||
pub struct XdgBackend {
|
pub struct XdgBackend {
|
||||||
toplevel: Mutex<Option<ToplevelSurface>>,
|
toplevel: Mutex<Option<ToplevelSurface>>,
|
||||||
popups: Mutex<FxHashMap<String, (PopupSurface, PositionerState)>>,
|
popups: Mutex<FxHashMap<u64, (PopupSurface, PositionerState)>>,
|
||||||
pub seat: Arc<SeatWrapper>,
|
pub seat: Arc<SeatWrapper>,
|
||||||
}
|
}
|
||||||
impl XdgBackend {
|
impl XdgBackend {
|
||||||
@@ -354,20 +353,18 @@ impl XdgBackend {
|
|||||||
surface_panel_item(self.toplevel.lock().clone()?.wl_surface())
|
surface_panel_item(self.toplevel.lock().clone()?.wl_surface())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_popup(&self, uid: &str, popup: PopupSurface, positioner: PositionerState) {
|
pub fn new_popup(&self, id: u64, popup: PopupSurface, positioner: PositionerState) {
|
||||||
let Some(panel_item) = self.panel_item() else {
|
let Some(panel_item) = self.panel_item() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
self.popups
|
self.popups.lock().insert(id, (popup, positioner));
|
||||||
.lock()
|
|
||||||
.insert(uid.to_string(), (popup, positioner));
|
|
||||||
|
|
||||||
panel_item.create_child(uid, self.child_data(uid).unwrap());
|
panel_item.create_child(id, &self.child_data(id).unwrap());
|
||||||
}
|
}
|
||||||
pub fn reposition_popup(&self, uid: &str, _popup: PopupSurface, positioner: PositionerState) {
|
pub fn reposition_popup(&self, id: u64, _popup: PopupSurface, positioner: PositionerState) {
|
||||||
let mut popups = self.popups.lock();
|
let mut popups = self.popups.lock();
|
||||||
let Some((_, old_positioner)) = popups.get_mut(uid) else {
|
let Some((_, old_positioner)) = popups.get_mut(&id) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(panel_item) = self.panel_item() else {
|
let Some(panel_item) = self.panel_item() else {
|
||||||
@@ -376,18 +373,19 @@ impl XdgBackend {
|
|||||||
let geometry = positioner.get_geometry();
|
let geometry = positioner.get_geometry();
|
||||||
|
|
||||||
*old_positioner = positioner;
|
*old_positioner = positioner;
|
||||||
panel_item.reposition_child(uid, geometry.into());
|
panel_item.reposition_child(id, &geometry.into());
|
||||||
}
|
}
|
||||||
pub fn drop_popup(&self, uid: &str) {
|
pub fn drop_popup(&self, id: u64) {
|
||||||
let Some(panel_item) = self.panel_item() else {
|
let Some(panel_item) = self.panel_item() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
panel_item.destroy_child(uid);
|
panel_item.destroy_child(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn child_data(&self, uid: &str) -> Option<ChildInfo> {
|
fn child_data(&self, id: u64) -> Option<ChildInfo> {
|
||||||
let (popup, positioner) = self.popups.lock().get(uid)?.clone();
|
let (popup, positioner) = self.popups.lock().get(&id)?.clone();
|
||||||
Some(ChildInfo {
|
Some(ChildInfo {
|
||||||
|
id,
|
||||||
parent: (*utils::get_data::<SurfaceId>(&popup.get_parent_surface()?)?).clone(),
|
parent: (*utils::get_data::<SurfaceId>(&popup.get_parent_surface()?)?).clone(),
|
||||||
geometry: positioner.get_geometry().into(),
|
geometry: positioner.get_geometry().into(),
|
||||||
})
|
})
|
||||||
@@ -443,12 +441,14 @@ impl Backend for XdgBackend {
|
|||||||
.map(|s| Vector2::from([s.w as u32, s.h as u32]))
|
.map(|s| Vector2::from([s.w as u32, s.h as u32]))
|
||||||
.or_else(|| toplevel_core_surface.size())
|
.or_else(|| toplevel_core_surface.size())
|
||||||
.unwrap_or(Vector2::from([0; 2]));
|
.unwrap_or(Vector2::from([0; 2]));
|
||||||
let toplevel = ToplevelInfo {
|
let parent = toplevel
|
||||||
parent: toplevel
|
|
||||||
.parent()
|
.parent()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(surface_panel_item)
|
.and_then(surface_panel_item)
|
||||||
.map(|p| p.uid.clone()),
|
.and_then(|p| p.node.upgrade())
|
||||||
|
.map(|p| p.get_id());
|
||||||
|
let toplevel = ToplevelInfo {
|
||||||
|
parent,
|
||||||
title,
|
title,
|
||||||
app_id,
|
app_id,
|
||||||
size,
|
size,
|
||||||
@@ -491,7 +491,7 @@ impl Backend for XdgBackend {
|
|||||||
.popups
|
.popups
|
||||||
.lock()
|
.lock()
|
||||||
.keys()
|
.keys()
|
||||||
.map(|k| (k.clone(), self.child_data(k).unwrap()))
|
.map(|k| self.child_data(*k).unwrap())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(PanelItemInitData {
|
Ok(PanelItemInitData {
|
||||||
@@ -588,7 +588,7 @@ impl Backend for XdgBackend {
|
|||||||
self.seat.pointer_scroll(scroll_distance, scroll_steps)
|
self.seat.pointer_scroll(scroll_distance, scroll_steps)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keyboard_keys(&self, surface: &SurfaceId, keymap_id: &str, keys: Vec<i32>) {
|
fn keyboard_keys(&self, surface: &SurfaceId, keymap_id: u64, keys: Vec<i32>) {
|
||||||
let Some(surface) = self.wl_surface_from_id(&surface) else {
|
let Some(surface) = self.wl_surface_from_id(&surface) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user