From 084fa44330ae5e1032f1679dbd3af11ecac44962 Mon Sep 17 00:00:00 2001 From: Nova Date: Thu, 23 Feb 2023 08:43:09 -0500 Subject: [PATCH 1/8] feat: update fusion and molecules --- Cargo.lock | 186 ++++++++++++++++++++++++++++++------------- Cargo.toml | 9 ++- examples/app_grid.rs | 2 +- src/main.rs | 2 +- src/protostar.rs | 26 +++--- 5 files changed, 152 insertions(+), 73 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2dfdd5b..cc0d90b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -101,9 +101,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.13.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" [[package]] name = "bit_field" @@ -429,6 +429,18 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +[[package]] +name = "enum_dispatch" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11f36e95862220b211a6e2aa5eca09b4fa391b13cd52ceb8035a24bf65a79de2" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "errno" version = "0.2.8" @@ -492,13 +504,12 @@ checksum = "cda653ca797810c02f7ca4b804b40b8b95ae046eb989d356bce17919a8c25499" [[package]] name = "flatbuffers" -version = "2.1.2" +version = "23.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b428b715fdbdd1c364b84573b5fdc0f84f8e423661b9f398735278bc7f2b6a" +checksum = "77f5399c2c9c50ae9418e522842ad362f61ee48b346ac106807bd355a8a7c619" dependencies = [ "bitflags", - "smallvec", - "thiserror", + "rustc_version", ] [[package]] @@ -549,14 +560,14 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2be17a530a842f8a7a60f4397a08e8f08872849a5e31b20c7bd7301dac483296" dependencies = [ - "roxmltree", + "roxmltree 0.15.1", ] [[package]] name = "fontdb" -version = "0.10.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8131752b3f3b876a20f42b3d08233ad177d6e7ec6d18aaa6954489a201071be5" +checksum = "ff20bef7942a72af07104346154a70a70b089c572e454b41bef6eb6cb10e9c06" dependencies = [ "fontconfig-parser", "log", @@ -605,6 +616,16 @@ dependencies = [ "weezl", ] +[[package]] +name = "gif" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" +dependencies = [ + "color_quant", + "weezl", +] + [[package]] name = "gimli" version = "0.27.0" @@ -620,6 +641,15 @@ dependencies = [ "mint", ] +[[package]] +name = "glam" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e4afd9ad95555081e109fe1d21f2a30c691b5f0919c67dfa690a2e1eb6bd51c" +dependencies = [ + "mint", +] + [[package]] name = "half" version = "1.8.2" @@ -693,7 +723,7 @@ dependencies = [ "byteorder", "color_quant", "exr", - "gif", + "gif 0.11.4", "jpeg-decoder", "num-rational", "num-traits", @@ -704,9 +734,9 @@ dependencies = [ [[package]] name = "imagesize" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df19da1e92fbfec043ca97d622955381b1f3ee72a180ec999912df31b1ccd951" +checksum = "b72ad49b554c1728b1e83254a1b1565aea4161e28dabbfa171fc15fe62299caf" [[package]] name = "indenter" @@ -772,6 +802,15 @@ dependencies = [ "arrayvec", ] +[[package]] +name = "kurbo" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e119590a03caff1f7a582e8ee8c2164ddcc975791701188132fd1d1b518d3871" +dependencies = [ + "arrayvec", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1224,7 +1263,7 @@ dependencies = [ "directories", "dirs", "ez-pixmap", - "glam", + "glam 0.22.0", "image", "lazy_static", "manifest-dir-macros", @@ -1232,6 +1271,7 @@ dependencies = [ "nix", "resvg", "rustc-hash", + "stardust-xr-fusion", "stardust-xr-molecules", "tempdir", "tokio", @@ -1400,18 +1440,18 @@ dependencies = [ [[package]] name = "resvg" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c115863f2d3621999cf187e318bc92b16402dfeff6a48c74df700d77381394c1" +checksum = "76888219c0881e22b0ceab06fddcfe83163cd81642bd60c7842387f9c968a72e" dependencies = [ - "gif", + "gif 0.12.0", "jpeg-decoder", "log", "pico-args", "png", "rgb", "svgfilters", - "svgtypes", + "svgtypes 0.10.0", "tiny-skia", "usvg", "usvg-text-layout", @@ -1426,6 +1466,19 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "rosvgtree" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdc23d1ace03d6b8153c7d16f0708cd80b61ee8e80304954803354e67e40d150" +dependencies = [ + "log", + "roxmltree 0.18.0", + "simplecss", + "siphasher", + "svgtypes 0.9.0", +] + [[package]] name = "roxmltree" version = "0.15.1" @@ -1435,6 +1488,15 @@ dependencies = [ "xmlparser", ] +[[package]] +name = "roxmltree" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8f595a457b6b8c6cda66a48503e92ee8d19342f905948f29c383200ec9eb1d8" +dependencies = [ + "xmlparser", +] + [[package]] name = "rustc-demangle" version = "0.1.21" @@ -1447,6 +1509,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.36.7" @@ -1463,9 +1534,9 @@ dependencies = [ [[package]] name = "rustybuzz" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab9e34ecf6900625412355a61bda0bd68099fe674de707c67e5e4aed2c05e489" +checksum = "162bdf42e261bee271b3957691018634488084ef577dddeb6420a9684cab2a6a" dependencies = [ "bitflags", "bytemuck", @@ -1504,6 +1575,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" +[[package]] +name = "semver" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" + [[package]] name = "serde" version = "1.0.152" @@ -1595,9 +1672,7 @@ dependencies = [ [[package]] name = "stardust-xr" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8541caad6c5c3e9c43ce4fa43a330f7a3df5ec293c88fd062fff46172ceb97" +version = "0.11.0" dependencies = [ "chrono", "cluFlock", @@ -1615,14 +1690,12 @@ dependencies = [ [[package]] name = "stardust-xr-fusion" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd60cde6226782ea4b2eac83740f140c59adb7ab1cc38618401e474cc1663edd" +version = "0.38.0" dependencies = [ "anyhow", "color-rs", + "enum_dispatch", "flagset", - "glam", "mint", "nanoid", "parking_lot 0.12.1", @@ -1638,13 +1711,10 @@ dependencies = [ [[package]] name = "stardust-xr-molecules" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8675431b05c71a734748badea127c2872d2f6754a2da80f418b6e53a43347ffa" +version = "0.21.0" dependencies = [ "color-rs", - "flexbuffers", - "glam", + "glam 0.23.0", "lazy_static", "mint", "rustc-hash", @@ -1657,13 +1727,11 @@ dependencies = [ [[package]] name = "stardust-xr-schemas" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b2b760187d18535aadf608d6221506b1364a4fff14653f31c51a2fd6696fd9" +version = "1.4.0" dependencies = [ "flatbuffers", "flexbuffers", - "glam", + "glam 0.22.0", "mint", "ouroboros", "serde", @@ -1703,10 +1771,21 @@ dependencies = [ [[package]] name = "svgtypes" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22975e8a2bac6a76bb54f898a6b18764633b00e780330f0b689f65afb3975564" +checksum = "c9ee29c1407a5b18ccfe5f6ac82ac11bab3b14407e09c209a6c1a32098b19734" dependencies = [ + "kurbo 0.8.3", + "siphasher", +] + +[[package]] +name = "svgtypes" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98ffacedcdcf1da6579c907279b4f3c5492fbce99fbbf227f5ed270a589c2765" +dependencies = [ + "kurbo 0.9.0", "siphasher", ] @@ -1802,9 +1881,9 @@ dependencies = [ [[package]] name = "tiny-skia" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ae12c22601b6853f4d93abb178e13bf0e1cc8e2454100c85d4d3a59ac71b3f7" +checksum = "bfef3412c6975196fdfac41ef232f910be2bb37b9dd3313a49a1a6bc815a5bdb" dependencies = [ "arrayref", "arrayvec", @@ -1816,9 +1895,9 @@ dependencies = [ [[package]] name = "tiny-skia-path" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd665853ce64402daabef6edda442dbb4f8ee93ea80957b66ba1af419f11a104" +checksum = "a4b5edac058fc98f51c935daea4d805b695b38e2f151241cad125ade2a2ac20d" dependencies = [ "arrayref", "bytemuck", @@ -1827,9 +1906,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.24.1" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9f76183f91ecfb55e1d7d5602bd1d979e38a3a522fe900241cf195624d67ae" +checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" dependencies = [ "autocfg", "bytes", @@ -1939,9 +2018,9 @@ dependencies = [ [[package]] name = "ttf-parser" -version = "0.17.1" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375812fa44dab6df41c195cd2f7fecb488f6c09fbaafb62807488cefab642bff" +checksum = "0609f771ad9c6155384897e1df4d948e692667cc0588548b68eb44d052b27633" [[package]] name = "tween" @@ -2011,32 +2090,29 @@ dependencies = [ [[package]] name = "usvg" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b5b7c2b30845b3348c067ca3d09e20cc6e327c288f0ca4c48698712abf432e9" +checksum = "63b6bb4e62619d9f68aa2d8a823fea2bff302340a1f2d45c264d5b0be170832e" dependencies = [ "base64", "data-url", "flate2", "imagesize", - "kurbo", + "kurbo 0.9.0", "log", "rctree", - "roxmltree", - "simplecss", - "siphasher", + "rosvgtree", "strict-num", - "svgtypes", ] [[package]] name = "usvg-text-layout" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c9550670848028641bf976b06f5c520ffdcd6f00ee7ee7eb0853f78e2c249d7" +checksum = "195386e01bc35f860db024de275a76e7a31afdf975d18beb6d0e44764118b4db" dependencies = [ "fontdb", - "kurbo", + "kurbo 0.9.0", "log", "rustybuzz", "unicode-bidi", diff --git a/Cargo.toml b/Cargo.toml index d800206..b5b5bf3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,9 +15,10 @@ lazy_static = "1.4.0" manifest-dir-macros = "0.1.16" mint = "0.5.9" nix = "0.26.1" -resvg = "0.28.0" +resvg = "0.29.0" rustc-hash = "1.1.0" -stardust-xr-molecules = "0.17.0" +stardust-xr-fusion = "0.38.0" +stardust-xr-molecules = "0.21.0" tokio = { version = "1.24.1", features = ["full"] } tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } tween = "2.0.0" @@ -26,3 +27,7 @@ walkdir = "2.3.2" [dev-dependencies] tempdir = "0.3.7" + +[patch.crates-io] +stardust-xr-molecules = { path = "../../molecules" } +stardust-xr-fusion = { path = "../../core/fusion" } \ No newline at end of file diff --git a/examples/app_grid.rs b/examples/app_grid.rs index 393c421..82bb2e0 100644 --- a/examples/app_grid.rs +++ b/examples/app_grid.rs @@ -5,7 +5,7 @@ use protostar::{ protostar::ProtoStar, xdg::{get_desktop_files, parse_desktop_file, DesktopFile}, }; -use stardust_xr_molecules::fusion::{ +use stardust_xr_fusion::{ client::{Client, FrameInfo, RootHandler}, spatial::Spatial, }; diff --git a/src/main.rs b/src/main.rs index a47c509..008a92f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ use color_eyre::{ }; use manifest_dir_macros::directory_relative_path; use protostar::{protostar::ProtoStar, xdg::parse_desktop_file}; -use stardust_xr_molecules::fusion::client::Client; +use stardust_xr_fusion::client::Client; use std::path::PathBuf; #[derive(Debug, Parser)] diff --git a/src/protostar.rs b/src/protostar.rs index 89dc36d..9d3b92c 100644 --- a/src/protostar.rs +++ b/src/protostar.rs @@ -3,18 +3,16 @@ use color_eyre::eyre::{eyre, Result}; use glam::Quat; use mint::Vector3; use nix::unistd::{execv, fork}; -use stardust_xr_molecules::{ - fusion::{ - client::{Client, FrameInfo, RootHandler}, - core::values::Transform, - drawable::{MaterialParameter, Model, ResourceID}, - fields::BoxField, - node::NodeType, - spatial::Spatial, - startup_settings::StartupSettings, - }, - GrabData, Grabbable, +use stardust_xr_fusion::{ + client::{Client, FrameInfo, RootHandler}, + core::values::Transform, + drawable::{MaterialParameter, Model, ResourceID}, + fields::BoxField, + node::NodeType, + spatial::Spatial, + startup_settings::StartupSettings, }; +use stardust_xr_molecules::{GrabData, Grabbable}; use std::{f32::consts::PI, ffi::CStr, sync::Arc}; use tween::{QuartInOut, Tweener}; use ustr::ustr; @@ -79,8 +77,7 @@ impl ProtoStar { match icon.as_ref() { Some(Icon::Png(_)) => [0.05, 0.0665, 0.005], _ => [0.05; 3], - } - .into(), + }, )?; let grabbable = Grabbable::new( parent, @@ -88,6 +85,7 @@ impl ProtoStar { &field, GrabData { max_distance: 0.025, + ..Default::default() }, )?; field.set_spatial_parent(grabbable.content_parent())?; @@ -115,7 +113,7 @@ impl ProtoStar { } impl RootHandler for ProtoStar { fn frame(&mut self, info: FrameInfo) { - self.grabbable.update(); + self.grabbable.update(&info); if let Some(icon_shrink) = &mut self.icon_shrink { if !icon_shrink.is_finished() { From 5c8e2dbadb92f7dfb83c607ba897634bc0a7ae12 Mon Sep 17 00:00:00 2001 From: Nova Date: Thu, 23 Feb 2023 09:43:11 -0500 Subject: [PATCH 2/8] fix: remove patches --- Cargo.lock | 8 ++++++++ Cargo.toml | 6 +----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cc0d90b..61ed0a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1673,6 +1673,8 @@ dependencies = [ [[package]] name = "stardust-xr" version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "798fb96a582da0fe0c791cfc10005a5eff3fbe3024e73b139456e63eda1380f4" dependencies = [ "chrono", "cluFlock", @@ -1691,6 +1693,8 @@ dependencies = [ [[package]] name = "stardust-xr-fusion" version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f6c2945a8246880297b1f059e48a8eeb6ba39c58f67e83c05725b86f869149" dependencies = [ "anyhow", "color-rs", @@ -1712,6 +1716,8 @@ dependencies = [ [[package]] name = "stardust-xr-molecules" version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ae6569520bc27bd6fc015e4e0a687bb730631dc039bb5c5c14c2ad40457cfac" dependencies = [ "color-rs", "glam 0.23.0", @@ -1728,6 +1734,8 @@ dependencies = [ [[package]] name = "stardust-xr-schemas" version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bebfbddbcba7db7ce8180bb373c9ad5a7d58ff60ee213ca07562820d7e8aab0" dependencies = [ "flatbuffers", "flexbuffers", diff --git a/Cargo.toml b/Cargo.toml index b5b5bf3..9b2ccf8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,8 +26,4 @@ ustr = "0.9.0" walkdir = "2.3.2" [dev-dependencies] -tempdir = "0.3.7" - -[patch.crates-io] -stardust-xr-molecules = { path = "../../molecules" } -stardust-xr-fusion = { path = "../../core/fusion" } \ No newline at end of file +tempdir = "0.3.7" \ No newline at end of file From 8cd432c9269e4bb802b49337afd649d2aa4e9f2a Mon Sep 17 00:00:00 2001 From: Bennyboiii Date: Thu, 9 Mar 2023 21:11:26 -0500 Subject: [PATCH 3/8] added a dock (sirius) --- examples/sirius.rs | 159 +++++++++++++++++++++++++++++++++++++++ res/protostar/button.glb | Bin 0 -> 21236 bytes 2 files changed, 159 insertions(+) create mode 100644 examples/sirius.rs create mode 100644 res/protostar/button.glb diff --git a/examples/sirius.rs b/examples/sirius.rs new file mode 100644 index 0000000..8fc0acc --- /dev/null +++ b/examples/sirius.rs @@ -0,0 +1,159 @@ +#![allow(dead_code)] + +use color_eyre::eyre::Result; +use glam::Vec3; +use manifest_dir_macros::directory_relative_path; +use protostar::protostar::ProtoStar; +use stardust_xr_fusion::{ + client::{Client, FrameInfo, RootHandler}, + core::values::Transform, + drawable::{MaterialParameter, Model, ResourceID}, + node::NodeError, input::{InputData, InputDataType}, spatial::Spatial, fields::BoxField, +}; +use stardust_xr_molecules::{touch_plane::TouchPlane, Grabbable, GrabData}; + + + +#[tokio::main(flavor = "current_thread")] +async fn main() -> Result<()> { + color_eyre::install()?; + let (client, event_loop) = Client::connect_with_async_loop().await?; + client.set_base_prefixes(&[directory_relative_path!("res")]); + + let _wrapped_root = client.wrap_root(Sirius::new(&client)?)?; + + tokio::select! { + _ = tokio::signal::ctrl_c() => (), + e = event_loop => e??, + } + Ok(()) +} + +struct Star { + cli: ProtoStar +} + +impl Star { + fn new(parent: &Spatial, name: Option<&str>,path: &str) -> Option { + let cli = ProtoStar::new_raw(parent, Vec3::default(), name, None, path.to_string()).unwrap(); + Some(Star { + cli, + }) + } +} + +impl RootHandler for Star { + fn frame(&mut self, info: FrameInfo) { + self.cli.frame(info); + } +} + +struct Sirius { + touch_plane: TouchPlane, + model: Model, + root: Spatial, + clients: Vec, + visibility: bool, + grabbable: Grabbable, + +} +impl Sirius { + fn new(client: &Client) -> Result { + let client_list: Vec<(Option<&str>, &str)> = Vec::from([ + (Some("Magnetar"), "$HOME/repos/stardust/telescope/repos/magnetar/target/release/magnetar"), + (Some("Atmosphere"), "$HOME/repos/stardust/telescope/repos/atmosphere/target/release/atmosphere"), + (Some("Manifold"), "$HOME/repos/stardust/telescope/repos/manifold/target/release/manifold"), + ]); + let root = Spatial::create(client.get_root(), Transform::default(), false).unwrap(); + + let field = BoxField::create(&root, Transform::default(), Vec3::from([0.1;3])).unwrap(); + let grabbable = Grabbable::new(&root, Transform::default(), &field, GrabData::default())?; + let touch_plane = TouchPlane::new(grabbable.content_parent(), Transform::default(), [0.1; 2], 0.03)?; + let mut clients = Vec::new(); + for clientkv in client_list { + clients.push(Star::new(grabbable.content_parent(), clientkv.0, clientkv.1).unwrap()); + } + let model = Model::create( + grabbable.content_parent(), + Transform::default(), + &ResourceID::new_namespaced("protostar", "button"), + )?; + field.set_spatial_parent(grabbable.content_parent())?; + let visibility = false; + + Ok(Sirius { touch_plane, model , root, clients, visibility, grabbable}) + } + +// fn left_hand(input_data: &InputData, _: &()) -> bool { +// match &input_data.input { +// InputDataType::Hand(h) => !h.right, +// _ => false, +// } +// } +} +impl RootHandler for Sirius { + fn frame(&mut self, info: FrameInfo) { + + for app in &mut self.clients { + app.frame(info); + } + + self.grabbable.update(&info); + self.touch_plane.update(); + if self.touch_plane.touch_started() { + println!("Touch started"); + self.visibility = !self.visibility; + match self.visibility { + true => for star in self.clients.iter().enumerate() { + let mut starpos = (star.0 as f32 +1.0)/10.0; + match starpos % 0.2 == 0.0 { + true => starpos = -starpos/2.0, + false => starpos = (starpos - 0.1)/2.0, + } + println!("{}", starpos); + star.1.cli.content_parent().set_position(Some(&self.grabbable.content_parent()), Vec3::from([starpos,0.1,0.0])).ok(); + }, + false => for star in &self.clients { + star.cli.content_parent().set_position(Some(&self.grabbable.content_parent()), Vec3::from([0.0,0.0,0.0])).ok(); + }, + + } + let color = [0.0, 1.0, 0.0, 1.0]; + self.model + .set_material_parameter(0, "color", MaterialParameter::Color(color)) + .unwrap(); + self.model + .set_material_parameter( + 0, + "emission_factor", + MaterialParameter::Color(color.map(|c| c * 0.75)), + ) + .unwrap(); + } + + if self.touch_plane.touch_stopped() { + println!("Touch ended"); + let color = [1.0, 0.0, 0.0, 1.0]; + self.model + .set_material_parameter(0, "color", MaterialParameter::Color(color)) + .unwrap(); + self.model + .set_material_parameter( + 0, + "emission_factor", + MaterialParameter::Color(color.map(|c| c * 0.5)), + ) + .unwrap(); + } + } +} + +fn position(data: &InputData) -> Vec3 { + match &data.input { + InputDataType::Hand(h) => h.palm.position.into(), + InputDataType::Pointer(w) => w.deepest_point.into(), + InputDataType::Tip(t) => t.origin.into(), + } + + +} diff --git a/res/protostar/button.glb b/res/protostar/button.glb new file mode 100644 index 0000000000000000000000000000000000000000..ed080bac8d7207e228ed2d16dc5d05edb9ade1f5 GIT binary patch literal 21236 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 Date: Thu, 9 Mar 2023 21:25:05 -0500 Subject: [PATCH 4/8] updated packages --- Cargo.toml | 29 +++++++++ src/protostar.rs | 162 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 Cargo.toml create mode 100644 src/protostar.rs diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..9b2ccf8 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "protostar" +version = "0.4.0" +edition = "2021" + +[dependencies] +clap = { version = "4.1.3", features = ["derive"] } +color-eyre = "0.6.2" +directories = "4.0.1" +dirs = "4.0.0" +ez-pixmap = "0.2.2" +glam = { version = "0.22.0", features = ["mint"] } +image = "0.24.5" +lazy_static = "1.4.0" +manifest-dir-macros = "0.1.16" +mint = "0.5.9" +nix = "0.26.1" +resvg = "0.29.0" +rustc-hash = "1.1.0" +stardust-xr-fusion = "0.38.0" +stardust-xr-molecules = "0.21.0" +tokio = { version = "1.24.1", features = ["full"] } +tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } +tween = "2.0.0" +ustr = "0.9.0" +walkdir = "2.3.2" + +[dev-dependencies] +tempdir = "0.3.7" \ No newline at end of file diff --git a/src/protostar.rs b/src/protostar.rs new file mode 100644 index 0000000..9d3b92c --- /dev/null +++ b/src/protostar.rs @@ -0,0 +1,162 @@ +use crate::xdg::{DesktopFile, Icon, RawIconType}; +use color_eyre::eyre::{eyre, Result}; +use glam::Quat; +use mint::Vector3; +use nix::unistd::{execv, fork}; +use stardust_xr_fusion::{ + client::{Client, FrameInfo, RootHandler}, + core::values::Transform, + drawable::{MaterialParameter, Model, ResourceID}, + fields::BoxField, + node::NodeType, + spatial::Spatial, + startup_settings::StartupSettings, +}; +use stardust_xr_molecules::{GrabData, Grabbable}; +use std::{f32::consts::PI, ffi::CStr, sync::Arc}; +use tween::{QuartInOut, Tweener}; +use ustr::ustr; + +fn model_from_icon(parent: &Spatial, icon: &Icon) -> Result { + let model = match icon { + Icon::Png(path) => { + let model = Model::create( + parent, + Transform::from_rotation(Quat::from_rotation_y(PI)), + &ResourceID::new_namespaced("protostar", "cartridge"), + )?; + model.set_material_parameter( + 0, + "diffuse", + MaterialParameter::Texture(ResourceID::Direct(path.clone())), + )?; + model + } + Icon::Gltf(path) => Model::create( + parent, + Transform::from_scale([0.05; 3]), + &ResourceID::new_direct(path)?, + )?, + }; + Ok(model) +} + +pub struct ProtoStar { + client: Arc, + grabbable: Grabbable, + field: BoxField, + icon: Model, + icon_shrink: Option>, + execute_command: String, +} +impl ProtoStar { + pub fn create_from_desktop_file(parent: &Spatial, desktop_file: DesktopFile) -> Result { + // dbg!(&desktop_file); + let mut raw_icons = desktop_file.get_raw_icons(); + let last_icon = raw_icons.pop(); + let icon = raw_icons + .into_iter() + .find(|i| match i { + RawIconType::Png(_) => false, + RawIconType::Svg(_) => false, + RawIconType::Gltf(_) => true, + }) + .or(last_icon) + .map(|i| dbg!(i.process(64)).ok()) + .ok_or_else(|| eyre!("No compatible icons found"))?; + Self::new_raw( + parent, + icon, + desktop_file.command.ok_or_else(|| eyre!("No command"))?, + ) + } + pub fn new_raw(parent: &Spatial, icon: Option, execute_command: String) -> Result { + let field = BoxField::create( + parent, + Transform::default(), + match icon.as_ref() { + Some(Icon::Png(_)) => [0.05, 0.0665, 0.005], + _ => [0.05; 3], + }, + )?; + let grabbable = Grabbable::new( + parent, + Transform::default(), + &field, + GrabData { + max_distance: 0.025, + ..Default::default() + }, + )?; + field.set_spatial_parent(grabbable.content_parent())?; + let icon = icon + .map(|i| model_from_icon(grabbable.content_parent(), &i)) + .unwrap_or_else(|| { + Ok(Model::create( + grabbable.content_parent(), + Transform::from_scale([0.05; 3]), + &ResourceID::new_namespaced("protostar", "default_icon"), + )?) + })?; + Ok(ProtoStar { + client: parent.client()?, + grabbable, + field, + icon, + icon_shrink: None, + execute_command, + }) + } + pub fn content_parent(&self) -> &Spatial { + self.grabbable.content_parent() + } +} +impl RootHandler for ProtoStar { + fn frame(&mut self, info: FrameInfo) { + self.grabbable.update(&info); + + if let Some(icon_shrink) = &mut self.icon_shrink { + if !icon_shrink.is_finished() { + let scale = icon_shrink.move_by(info.delta); + self.icon + .set_scale(None, Vector3::from([scale; 3])) + .unwrap(); + } else { + self.client.stop_loop(); + } + } else if self.grabbable.grab_action().actor_stopped() { + let startup_settings = StartupSettings::create(&self.field.client().unwrap()).unwrap(); + self.icon + .set_spatial_parent_in_place(self.client.get_root()) + .unwrap(); + self.grabbable + .content_parent() + .set_rotation( + Some(&self.field.client().unwrap().get_root()), + Quat::IDENTITY, + ) + .unwrap(); + startup_settings + .set_root(self.grabbable.content_parent()) + .unwrap(); + self.icon_shrink = Some(Tweener::quart_in_out(1.0, 0.0, 0.25)); + let future = startup_settings.generate_startup_token().unwrap(); + let executable = dbg!(self.execute_command.clone()); + tokio::task::spawn(async move { + std::env::set_var("STARDUST_STARTUP_TOKEN", future.await.unwrap()); + if unsafe { fork() }.unwrap().is_parent() { + println!("Launching \"{}\"...", &executable); + execv::<&CStr>( + ustr("/bin/sh").as_cstr(), + &[ + ustr("/bin/sh").as_cstr(), + ustr("-c").as_cstr(), + ustr(&executable).as_cstr(), + ], + ) + .unwrap(); + } + }); + } + } +} From 79b3568f353a18504ff86f398b5c72e759cd59c5 Mon Sep 17 00:00:00 2001 From: Bennyboiii <32402247+Bennyboiii@users.noreply.github.com> Date: Fri, 10 Mar 2023 13:11:30 -0500 Subject: [PATCH 5/8] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index bf01292..d811646 100644 --- a/README.md +++ b/README.md @@ -10,3 +10,6 @@ TODO: 3. ~~Use XDG_CACHE_DIR to rasterize svgs (done)~~ 4. Make sure it's using the current icon theme 5. Design a better app launcher ui + +TO RUN DOCK +cargo run --example sirius From d661b5ecb3151254848dd0439561963c3755eba5 Mon Sep 17 00:00:00 2001 From: Bennyboiii Date: Fri, 10 Mar 2023 13:37:36 -0500 Subject: [PATCH 6/8] fix for new version of protostar --- examples/hexagon_launcher.rs | 4 +- examples/sirius.rs | 10 +- src/xdg.rs | 245 ++++++++++++++--------------------- 3 files changed, 105 insertions(+), 154 deletions(-) diff --git a/examples/hexagon_launcher.rs b/examples/hexagon_launcher.rs index 318c68e..71720cf 100644 --- a/examples/hexagon_launcher.rs +++ b/examples/hexagon_launcher.rs @@ -34,7 +34,7 @@ const HEX_DIRECTION_VECTORS: [Hex; 6] = [ Hex { q: 1, r: -1, s: 0 }, Hex { q: 0, r: -1, s: 1 }, Hex { q: -1, r: 0, s: 1 }, - Hex { q: -1, r: 1, s: 0 }, + Hex{ q: -1, r: 1, s: 0 }, Hex { q: 0, r: 1, s: -1 }, ]; @@ -162,7 +162,7 @@ impl App { ) -> Option { let position = position.into(); let protostar = - ProtoStar::create_from_desktop_file(parent, position, desktop_file.clone()).ok()?; + ProtoStar::create_from_desktop_file(parent, desktop_file.clone()).ok()?; Some(App { _desktop_file: desktop_file, protostar, diff --git a/examples/sirius.rs b/examples/sirius.rs index 8fc0acc..542c1ef 100644 --- a/examples/sirius.rs +++ b/examples/sirius.rs @@ -34,8 +34,8 @@ struct Star { } impl Star { - fn new(parent: &Spatial, name: Option<&str>,path: &str) -> Option { - let cli = ProtoStar::new_raw(parent, Vec3::default(), name, None, path.to_string()).unwrap(); + fn new(parent: &Spatial, _name: Option<&str>,path: &str) -> Option { + let cli = ProtoStar::new_raw(parent, None, path.to_string()).unwrap(); Some(Star { cli, }) @@ -60,9 +60,9 @@ struct Sirius { impl Sirius { fn new(client: &Client) -> Result { let client_list: Vec<(Option<&str>, &str)> = Vec::from([ - (Some("Magnetar"), "$HOME/repos/stardust/telescope/repos/magnetar/target/release/magnetar"), - (Some("Atmosphere"), "$HOME/repos/stardust/telescope/repos/atmosphere/target/release/atmosphere"), - (Some("Manifold"), "$HOME/repos/stardust/telescope/repos/manifold/target/release/manifold"), + (Some("Magnetar"), "/home/bc/repos/stardust/telescope/repos/magnetar/target/release/magnetar"), + (Some("Atmosphere"), "/home/bc/repos/stardust/telescope/repos/atmosphere/target/release/atmosphere"), + (Some("Manifold"), "/home/bc/repos/stardust/telescope/repos/manifold/target/release/manifold"), ]); let root = Spatial::create(client.get_root(), Transform::default(), false).unwrap(); diff --git a/src/xdg.rs b/src/xdg.rs index 9390232..bd18044 100644 --- a/src/xdg.rs +++ b/src/xdg.rs @@ -1,52 +1,40 @@ -use cached::proc_macro::cached; use color_eyre::eyre::Result; -use linicon; -use regex::Regex; use resvg::render; use resvg::tiny_skia::{Pixmap, Transform}; use resvg::usvg::{FitTo, Tree}; use std::ffi::OsString; use std::fs::create_dir_all; use std::io::{BufRead, BufReader, ErrorKind}; -use std::os::unix::fs::symlink; use std::path::{Path, PathBuf}; use std::str::FromStr; use std::{env, fs}; use walkdir::WalkDir; -fn get_data_dirs() -> Vec { - let xdg_data_dirs_str = std::env::var("XDG_DATA_DIRS").unwrap_or_default(); - let xdg_data_dirs = xdg_data_dirs_str - .split(":") - .filter_map(|dir| PathBuf::from_str(dir).ok()); - - let data_home = dirs::home_dir() - .unwrap_or(PathBuf::from_str("/usr/share/").expect( - "No XDG_DATA_DIR set, no HOME directory found and no /usr/share direcotry found", - )) - .join(".local") - .join("share"); - - xdg_data_dirs - .chain([data_home].into_iter()) - .filter(|dir| dir.exists() && dir.is_dir()) - .collect() -} - -fn get_app_dirs() -> Vec { - get_data_dirs() - .into_iter() - .map(|dir| dir.join("applications")) - .filter(|dir| dir.exists() && dir.is_dir()) - .collect() -} +const ICON_SIZES: &[&str] = &["128x128", "scalable", "256x256", "64x64", "32x32"]; pub fn get_desktop_files() -> Vec { + // Get the XDG data directories + let xdg_data_dirs = + std::env::var("XDG_DATA_DIRS").unwrap_or("/usr/local/share:/usr/share".to_string()); + + // Append the applications directory to each data directory + let app_dirs = xdg_data_dirs + .split(":") + .map(|dir| Path::new(dir).join("applications")); + + // Get the user's local applications directory + let local_app_dir = dirs::home_dir() + .unwrap() + .join(".local") + .join("share") + .join("applications"); + let desktop_extension = OsString::from_str("desktop").unwrap(); + // Get the list of directories to search - let app_dirs = get_app_dirs(); app_dirs - .into_iter() + .chain(Some(local_app_dir)) + .filter(|dir| dir.exists() && dir.is_dir()) .flat_map(|dir| { // Follow symlinks and recursively search directories WalkDir::new(dir) @@ -87,10 +75,6 @@ pub fn parse_desktop_file(path: PathBuf) -> Result { let mut command = None; let mut categories = Vec::new(); let mut icon = None; - let mut no_display = false; - let mut desktop_entry_found = false; - - let re = Regex::new(r"^\[([^\]]*)\]$").unwrap(); // Loop through each line of the file for line in reader.lines() { @@ -104,14 +88,6 @@ pub fn parse_desktop_file(path: PathBuf) -> Result { continue; } - if let Some(captures) = re.captures(&line) { - let entry = captures.get(1).unwrap(); - desktop_entry_found = entry.as_str().contains("Desktop Entry"); - } - - if !desktop_entry_found { - continue; - } // Split the line into a key-value pair by looking for the first "=" character let parts = line.split_once('='); let (key, value) = match parts { @@ -131,12 +107,6 @@ pub fn parse_desktop_file(path: PathBuf) -> Result { .collect() } "Icon" => icon = Some(value.to_string()), - "NoDisplay" => { - no_display = match value { - "true" => true, - _ => false, - } - } _ => (), // Ignore unknown keys } } @@ -148,7 +118,6 @@ pub fn parse_desktop_file(path: PathBuf) -> Result { command, categories, icon, - no_display, }) } @@ -180,81 +149,76 @@ pub struct DesktopFile { pub command: Option, pub categories: Vec, pub icon: Option, - pub no_display: bool, } impl DesktopFile { - pub fn get_raw_icons(&self) -> Vec { + pub fn get_raw_icons(&self) -> Vec { // Get the name of the icon from the DesktopFile struct let Some(icon_name) = self.icon.as_ref() else { return Vec::new(); }; let test_icon_path = self.path.join(Path::new(icon_name)); if test_icon_path.exists() { - if let Some(icon) = Icon::from_path(test_icon_path, 128) { - return vec![icon]; - } + return RawIconType::from_path(test_icon_path) + .map(|i| vec![i]) + .unwrap_or_default(); } - let cache_icon_path = get_image_cache_dir().join(icon_name).canonicalize(); - if cache_icon_path.is_ok() { - if let Some(icon) = Icon::from_path(cache_icon_path.unwrap(), 128) { - return vec![icon]; - } - } + let Ok(icon_name) = OsString::from_str(icon_name) else { return Vec::new(); }; - let mut icons_iter = linicon::lookup_icon(icon_name) - .use_fallback_themes(false) - .peekable(); + // Get the current icon theme from the XDG_ICON_THEME environment variable, or use "hicolor" as the default theme if the variable is not defined + let icon_theme = env::var_os("XDG_ICON_THEME").unwrap_or("hicolor".into()); - if icons_iter.peek().is_none() { - //dbg!("No icons found in current theme"); - icons_iter = linicon::lookup_icon(icon_name).peekable(); - } + // Get the XDG_DATA_HOME and XDG_DATA_DIRS environment variables, and split the XDG_DATA_DIRS variable into a list of directories + let Some(xdg_data_dirs) = env::var_os("XDG_DATA_DIRS") else { return Vec::new(); }; + let Ok(binding) = xdg_data_dirs.into_string() else { return Vec::new(); }; + let xdg_data_dirs = binding.split(":").map(Path::new); - let sized_png: Vec = icons_iter - .filter_map(|i| i.ok()) - .filter(|i| i.icon_type != linicon::IconType::XMP) //TODO: support XMP - .map(|i| Icon::from_path(i.path, i.max_size - 2).unwrap()) - .collect(); - sized_png + // Concatenate the XDG_DATA_HOME and XDG_DATA_DIRS directories with the default path for icon themes + xdg_data_dirs // XDG_DATA_DIRS directories + .flat_map(|dir| { + let icons_path = dir.join("icons").join(&icon_theme); + ICON_SIZES + .iter() + .map(|path| icons_path.join(path).join("apps")) + .collect::>() + }) + .filter_map(|dir| { + let dir = fs::read_dir(dir).ok()?; + Some( + dir.filter_map(|e| e.ok()) + .map(|file| file.path()) + .filter(|file| file.file_stem() == Some(&icon_name)), + ) + }) + .flatten() + .filter_map(RawIconType::from_path) + .collect() } } -#[derive(Debug, PartialEq, Eq, Clone)] -pub struct Icon { - pub icon_type: IconType, - pub path: PathBuf, - pub size: u16, +#[derive(Debug, PartialEq, Eq)] +pub enum RawIconType { + Png(PathBuf), + Svg(PathBuf), + Gltf(PathBuf), } - -#[derive(Debug, PartialEq, Eq, Clone)] -pub enum IconType { - Png, - Svg, - Gltf, -} -impl Icon { - pub fn from_path(path: PathBuf, size: u16) -> Option { - let icon_type = match path.extension().and_then(|ext| ext.to_str()) { - Some("png") => IconType::Png, - Some("svg") => IconType::Svg, - Some("glb") | Some("gltf") => IconType::Gltf, - _ => return None, - }; - return Some(Icon { - icon_type, - path, - size, - }); +impl RawIconType { + pub fn from_path(path: PathBuf) -> Option { + match path.extension().and_then(|ext| ext.to_str()) { + Some("png") => Some(RawIconType::Png(path)), + Some("svg") => Some(RawIconType::Svg(path)), + Some("glb") | Some("gltf") => Some(RawIconType::Gltf(path)), + _ => None, + } } - pub fn cached_process(self, size: u16) -> Result { - let new_path = - get_image_cache_dir().join(self.path.with_extension("").file_name().unwrap()); - if !new_path.exists() { - _ = symlink(self.path.clone(), new_path); - } - match self.icon_type { - IconType::Svg => Ok(Icon::from_path(get_png_from_svg(self.path, size)?, size).unwrap()), - _ => Ok(self), + pub fn process(self, size: u32) -> Result { + match self { + RawIconType::Png(path) => Ok(Icon::Png(path)), + RawIconType::Svg(path) => { + let png_path = path.with_extension("png"); + render_svg_to_png(path, &png_path, size)?; + Ok(Icon::Png(png_path)) + } + RawIconType::Gltf(path) => Ok(Icon::Gltf(path)), } } } @@ -268,7 +232,6 @@ fn test_get_icon_path() { command: None, categories: vec![], icon: Some("krita".into()), - no_display: false, }; // Call the get_icon_path() function with a size argument and store the result @@ -276,49 +239,37 @@ fn test_get_icon_path() { dbg!(&icon_paths); // Assert that the get_icon_path() function returns the expected result - assert!(icon_paths.contains( - &Icon::from_path( - PathBuf::from("/usr/share/icons/hicolor/32x32/apps/krita.png"), - 32 - ) - .unwrap() - )); + assert!(icon_paths.contains(&RawIconType::Png(PathBuf::from( + "/usr/share/icons/hicolor/16x16/apps/krita.png" + )))); } -#[cached] -pub fn get_image_cache_dir() -> PathBuf { - let cache_dir; - if let Ok(xdg_cache_home) = std::env::var("XDG_CACHE_HOME") { - cache_dir = - PathBuf::from_str(&xdg_cache_home).unwrap_or(dirs::home_dir().unwrap().join(".cache")) - } else { - cache_dir = dirs::home_dir().unwrap().join(".cache"); - } - let image_cache_dir = cache_dir.join("protostar_icon_cache"); - create_dir_all(&image_cache_dir).expect("Could not create image cache directory"); - return image_cache_dir; +#[derive(Debug, PartialEq, Eq)] +pub enum Icon { + Png(PathBuf), + Gltf(PathBuf), } -pub fn get_png_from_svg(svg_path: impl AsRef, size: u16) -> Result { +pub fn render_svg_to_png( + cache_dir: impl AsRef, + svg_path: impl AsRef, + size: u32, +) -> Result { let svg_path = fs::canonicalize(svg_path)?; - let svg_data = fs::read(svg_path.as_path())?; - let tree = Tree::from_data(svg_data.as_slice(), &resvg::usvg::Options::default()) - .map_err(|_| ErrorKind::InvalidData)?; - - let png_path = get_image_cache_dir().join(format!( - "{}-{}.png", - svg_path.file_name().unwrap().to_str().unwrap(), - svg_data.len() - )); - - if png_path.exists() { - return Ok(png_path); - } - - let mut pixmap = Pixmap::new(size.into(), size.into()).unwrap(); + let tree = Tree::from_data( + fs::read(svg_path.as_path())?.as_slice(), + &resvg::usvg::Options::default(), + ) + .map_err(|_| ErrorKind::InvalidData)?; + create_dir_all(cache_dir.as_ref())?; + let png_path = cache_dir + .as_ref() + .join(svg_path.file_name().unwrap()) + .with_extension("png"); + let mut pixmap = Pixmap::new(size, size).unwrap(); render( &tree, - FitTo::Width(size.into()), + FitTo::Width(size), Transform::identity(), pixmap.as_mut(), ); @@ -342,7 +293,7 @@ fn test_render_svg_to_png() { fs::write(&svg_path, test_svg_data).unwrap(); // Call the function with the test input and output paths and a size of 200 - let png_path = get_png_from_svg(&svg_path, 200).unwrap(); + let png_path = render_svg_to_png(".", &svg_path, 200).unwrap(); dbg!(&png_path); // Check that the output file exists From 4dd80754d3b85fe83d422b64776e90ac1824cc4d Mon Sep 17 00:00:00 2001 From: Bennyboiii Date: Fri, 10 Mar 2023 14:25:43 -0500 Subject: [PATCH 7/8] better paths --- examples/sirius.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/examples/sirius.rs b/examples/sirius.rs index 542c1ef..a2e5a58 100644 --- a/examples/sirius.rs +++ b/examples/sirius.rs @@ -34,8 +34,8 @@ struct Star { } impl Star { - fn new(parent: &Spatial, _name: Option<&str>,path: &str) -> Option { - let cli = ProtoStar::new_raw(parent, None, path.to_string()).unwrap(); + fn new(parent: &Spatial, _name: Option<&str>,path: String) -> Option { + let cli = ProtoStar::new_raw(parent, None, path).unwrap(); Some(Star { cli, }) @@ -48,6 +48,13 @@ impl RootHandler for Star { } } +const LOCATION_OF_TELESCOPE: &str = "/home/bc/repos/stardust/"; +const EXECUTABLES: [&str; 3] = [ + "magnetar", + "atmosphere", + "manifold", +]; + struct Sirius { touch_plane: TouchPlane, model: Model, @@ -59,11 +66,10 @@ struct Sirius { } impl Sirius { fn new(client: &Client) -> Result { - let client_list: Vec<(Option<&str>, &str)> = Vec::from([ - (Some("Magnetar"), "/home/bc/repos/stardust/telescope/repos/magnetar/target/release/magnetar"), - (Some("Atmosphere"), "/home/bc/repos/stardust/telescope/repos/atmosphere/target/release/atmosphere"), - (Some("Manifold"), "/home/bc/repos/stardust/telescope/repos/manifold/target/release/manifold"), - ]); + let mut client_list: Vec<(Option<&str>, String)> = Vec::new(); + for executable in EXECUTABLES { + client_list.push((Some(executable), format!("{}telescope/{}/target/release/{}", LOCATION_OF_TELESCOPE, executable, executable))); + } let root = Spatial::create(client.get_root(), Transform::default(), false).unwrap(); let field = BoxField::create(&root, Transform::default(), Vec3::from([0.1;3])).unwrap(); From ed451ef39801093c28b21d632512eaf6bbe4da7d Mon Sep 17 00:00:00 2001 From: Bennyboiii <32402247+Bennyboiii@users.noreply.github.com> Date: Sat, 11 Mar 2023 20:43:55 -0500 Subject: [PATCH 8/8] fixed pathing --- examples/sirius.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/sirius.rs b/examples/sirius.rs index a2e5a58..fa02356 100644 --- a/examples/sirius.rs +++ b/examples/sirius.rs @@ -68,7 +68,7 @@ impl Sirius { fn new(client: &Client) -> Result { let mut client_list: Vec<(Option<&str>, String)> = Vec::new(); for executable in EXECUTABLES { - client_list.push((Some(executable), format!("{}telescope/{}/target/release/{}", LOCATION_OF_TELESCOPE, executable, executable))); + client_list.push((Some(executable), format!("{}telescope/repos/{}/target/release/{}", LOCATION_OF_TELESCOPE, executable, executable))); } let root = Spatial::create(client.get_root(), Transform::default(), false).unwrap();