stereokit_rust/
lib.rs

1//! StereoKit-rust is a binding for the [StereoKit](https://StereoKit.net) C API.
2//! If the name of this crate contains "_rust" (not great for a Rust crate, we agree) it is to emphasize the fact that
3//! StereoKit is first and foremost a C, C++, C# project.
4//! StereoKit allows you to create VR/MR applications with ease on every headset platforms that run OpenXR.
5//!
6//! <img src="https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/StereoKit-rust.png" alt="screenshot" width="300">
7//!
8//! [StereoKit-rust GitHub repository](https://github.com/mvvvv/StereoKit-rust/) /
9//! [StereoKit GitHub repository](https://github.com/StereoKit/StereoKit/)
10//!
11//! # How to read this documentation
12//! If you already know the name of what you are looking for, the fastest way to
13//! find it is to use the <a href="#" onclick="window.searchState.focus();">search
14//! bar</a> at the top of the page.
15//! Otherwise, you may want to jump to one of these useful sections:
16//! * [Installation](#installation)
17//! * [Usage](#usage)
18//! * [Examples](#examples)
19//! * [How to build and test your application](#how-to-build-and-test-your-application)
20//! * [StereoKit-rust modules](#modules)
21//! * [StereoKit-rust Macros](#macros)
22//!
23//! # Installation:
24//! StereoKit-rust is a binding and therefore requires some tools and libraries to compile StereoKitC:
25//! ### On `Windows`:
26//!   - Considering that you have already installed "`Visual Studio Build Tools 2022(Developpment Desktop C++)`" in order to
27//!     have `Rust` compiling with `stable-????-pc-windows-msvc` toolchain.
28//!   - Get the following tools and dev libraries : "`Git`", "`CMake`" and "`DotNet SDK v8+`".
29//!
30//! ### On `Linux`:
31//!   - Considering that you have already installed `Rust` with `stable-?????-unknown-linux-gnu` toolchain and the linux package
32//!     `build-essential`.
33//!   - Get the following tools and dev libraries : `git` `clang` `cmake` `lld` `ninja-build` `libx11-dev`
34//!     `libxfixes-dev` `libegl-dev` `libgbm-dev` `libfontconfig-dev` `libxkbcommon-x11-dev`.
35//!
36//! Installing the stereokit_rust tools with `cargo install -F no-event-loop stereokit-rust` should help you to check
37//! the missing dependencies.
38//!
39//! # Usage
40//! You have to chose between `event-loop` and `no-event-loop` features. The feature `no-event-loop` is the
41//! lighter but you can't use the [`framework`].
42//!
43//! ## Features
44//! - **`event-loop`**: Enables the framework with Winit integration for window management and event handling.
45//! - **`no-event-loop`**: Lighter weight option without framework support.
46//! - **`test-xr-mode`**: For testing - replaces `AppMode::Offscreen` with `AppMode::XR` in test macros to test with real XR devices.
47//! - **`dynamic-openxr`**: Includes OpenXR loader dynamically for Android builds (APK).
48//! - **`build-dynamic-openxr`**: Builds OpenXR loader from Khronos OpenXR project for Android builds (APK).
49//!
50//! Using `event-loop` your `Cargo.toml` should contain the following lines:
51//! ```toml
52//! [lib]
53//! crate-type = ["lib", "cdylib"]
54//!
55//! [dependencies]
56//! stereokit-rust = { version = "0.4.0", features= ["event-loop"] }
57//! winit = { version = "0.30", features = [ "android-native-activity" ] }
58//!
59//! [target.'cfg(target_os = "android")'.dependencies]
60//! stereokit-rust = { version = "0.4.0" , features = ["event-loop", "build-dynamic-openxr"] }
61//! log = "0.4"
62//! android_logger = "0.15"
63//! ndk-context = "0.1.1"
64//! ndk = "0.9.0"
65//! ```
66//!
67//! # Examples
68//! Here is a simple "Hello World" StereoKit-rust app for all platforms:
69//! ```bash
70//! cargo new --lib vr_app
71//! cd vr_app
72//! ```
73//!
74//! In `src/bin/main_vr_app.rs`, if you intend to build a PC VR/MR app:
75//! ```ignore
76//! #[allow(dead_code)]
77//! #[cfg(not(target_os = "android"))]
78//! fn main() {
79//!     use stereokit_rust::sk::{SkSettings, Sk};
80//!     use vr_app::the_main;
81//!     // Initialize StereoKit with default settings
82//!     let mut settings = SkSettings::default();
83//!     settings.app_name("Test");
84//!     # settings.mode(stereokit_rust::sk::AppMode::Offscreen);
85//!     let (sk, event_loop) = settings.init_with_event_loop()
86//!         .expect("Should initialize StereoKit");
87//!     the_main(sk, event_loop);
88//!     Sk::shutdown();
89//! }
90//!
91//! #[allow(dead_code)]
92//! #[cfg(target_os = "android")]
93//! //fake main fn for android as entry is lib.rs/android_main(...)
94//! fn main() {}
95//!
96//! # use stereokit_rust::prelude::*;
97//! # use winit::event_loop::EventLoop;
98//! # pub fn the_main(sk: Sk, event_loop: EventLoop<StepperAction>) {}
99//! ```
100//!
101//! In `src/lib.rs` where you can remove the `target_os = "android" code` if you don't want to build for Android:
102//! ```ignore
103//! use stereokit_rust::{framework::SkClosures, prelude::*, sk::Sk, ui::Ui};
104//! use winit::event_loop::EventLoop;
105//!
106//! #[cfg(target_os = "android")]
107//! use winit::platform::android::activity::AndroidApp;
108//!
109//! #[unsafe(no_mangle)]
110//! #[cfg(target_os = "android")]
111//! pub fn android_main(app: AndroidApp) {
112//!     use stereokit_rust::sk::SkSettings;
113//!     // Initialize StereoKit with default settings
114//!     let mut settings = SkSettings::default();
115//!     settings.app_name("Test");
116//!     android_logger::init_once(
117//!         android_logger::Config::default()
118//!               .with_max_level(log::LevelFilter::Debug)
119//!               .with_tag("STKit-rs"),
120//!     );
121//!     let (sk, event_loop) = settings.init_with_event_loop(app).unwrap();
122//!     the_main(sk, event_loop);
123//! }
124//!
125//! /// Main function for All!
126//! pub fn the_main(sk: Sk, event_loop: EventLoop<StepperAction>) {
127//!     // Create a grabbable window with a button to exit the application
128//!     let mut window_pose = Ui::popup_pose([0.0, -0.4, 0.0]);
129//!     // Main loop
130//!     SkClosures::new(sk, |sk, _token| {
131//!         // Exit button
132//!         Ui::window_begin("Hello world!", &mut window_pose, None, None, None);
133//!         if Ui::button("Exit", None) {
134//!             sk.quit(None)
135//!         }
136//!         Ui::window_end();
137//!     })
138//!     .run(event_loop);
139//! }
140//! ```
141//!
142//! Hundreds of examples (which are also unit tests) are available in this documentation. If you like to learn by
143//! examples, check out  the modules in the following order: [`sk`], [`mesh`], [`model`], [`maths`], [`ui`], [`framework`],
144//! [`tools`], [`sound`], [`interactor`], [`system`], [`material`], [`shader`], [`tex`], [`sprite`], [`font`], [`render_list`].
145//!
146//! # How to build and test your application:
147//!
148//! * [Building your PC VR/MR app](#building-your-pc-vrmr-app).
149//! * [Building your Android VR/MR app](#building-your-android-vrmr-app).
150//! * [Building your Windows GNU PC VR/MR app](#building-your-windows-gnu-pc-vrmr-app).
151//! * [Building your Linux AARCH64 PC VR/MR app](#building-your-linux-aarch64-pc-vrmr-app).
152//! * [Building your Linux X86_64 PC VR/MR app](#building-your-linux-x86_64-pc-vrmr-app).
153//!
154//! ## Building your PC VR/MR app:
155//! * Launch `cargo run --bin main_vr_app` to compile and run your app in debug mode on your PC with or without a headset.
156//!   (using Wayland on Linux may require to unset temporarily the DISPLAY variable: `DISPLAY= cargo run`)
157//! * Launch `cargo build_sk_rs --bin main_vr_app <build_directory>` to compile your app and assets in release mode for your PC.
158//!
159//! To test with your headset, make sure you have [OpenXR installed](https://www.khronos.org/openxr/) with an active
160//! runtine (SteamVR, Monado, WiVRn, ALVR ...).
161//!
162//! ## Building your Android VR/MR app:
163//! This can be done from a PC running Windows, Mac or Linux:
164//! * Install [sdkmanager](https://developer.android.com/studio/command-line/sdkmanager) (or Android Studio if you
165//!   intend to use it). You'll need a Java JDK (v17 is fine).
166//! * Using sdkmanager, install platform-tools(v32), latest build-tools and the latest ndk.
167//! * Set ANDROID_HOME environment variable to its path (this path contains the `build_tools` directory).
168//! * Set the NDK path (which ends with it's version number) into the ANDROID_NDK_ROOT environment variable.
169//! * Install [Ninja](https://ninja-build.org/)
170//! * Check that `adb` ($ANDROID_HOME/platform_tools/adb) is connecting to your headset.
171//! * Download the target: `rustup target add aarch64-linux-android` for most existing android headsets.
172//! * Create a keystore for signing your app (using keytool or Android Studio).
173//! ##### If you don't need some java/kotlin code, you can use cargo-apk  (cargo-xbuild is an alternative but lacks some documentation):
174//!   - Install: `cargo install cargo-apk`.
175//!   - The manifest file will be generated from the `Cargo.toml` (see the `package.metadata.android` section). Here are
176//!     some examples:
177//!     - [StereoKit-template](https://github.com/mvvvv/stereokit-template/blob/main/Cargo.toml#L27)
178//!     - [StereoKit-rust](https://github.com/mvvvv/StereoKit-rust/blob/master/Cargo.toml#L77)
179//!   - Create a res directory with the icons of your app (i.e. with <https://icon.kitchen>)
180//!   - Set the path and password to your keystore in the `Cargo.toml` [package.metadata.android.signing.release] or
181//!     in the `CARGO_APK_RELEASE_KEYSTORE` and  `CARGO_APK_RELEASE_KEYSTORE_PASSWORD` environment variables.
182//!   - Launch the debug on your headset: `cargo apk run --lib`
183//!   - Generate the release apk: `cargo apk build --lib --release`. The apk will be in `target/release/apk/`.
184//! ##### Otherwise, you have to use Gradle with cargo-ndk:
185//!   - Install: `cargo install cargo-ndk`.
186//!   - Clone or extract a ZIP of [gradle template](https://github.com/mvvvv/stereokit-template/tree/gradle).
187//!   - Name your project in the `package.name` entry in `Cargo.toml`.
188//!   - Set `cargo.libName` (same as `package.name` from `Cargo.toml`), `android.applicationId` and `android.main` in
189//!     `gradle.properties`.
190//!   - In `app/src/main/AndroidManifest.xml` delete or modify the path and package name of `MainActivity.java` (your
191//!     choice impacts android.main ↑ and android:hasCode attribute).
192//!   - Replace the content of the res directory with the icons of your app (i.e. with <https://icon.kitchen>)
193//!   - Store your keystore values in one of the hidden gradle properties files (ie. `~/.gradle/gradle.properties`)
194//!     to store and forget the confidential values:
195//!     - RELEASE_STORE_FILE=/home/**/**/my_release_key.keystore
196//!     - RELEASE_STORE_PASSWORD=******
197//!     - RELEASE_KEY_ALIAS=*****
198//!     - RELEASE_KEY_PASSWORD=******
199//!   - If any, remove the .git folder.
200//!   - Launch the debug on your connected headset:
201//!     - On Windows, launch: `./gradlew.bat run && cmd /c logcat.cmd` or `(./gradlew.bat run) -and (cmd /c logcat.cmd)`
202//!     - On others, launch: `./gradlew run && ./logcat.cmd`
203//!   - Generate the release apk: `./gradlew buildRelease`. The apk will be in `app/build/outputs/apk/release`
204//!
205//! ## Building your Windows GNU PC VR/MR app:
206//! Thanks to Steam Proton, you can run your Windows exe on Linux. It's even better than native build thanks to D3D11
207//! to Vulkan translation. Knowing that, we work to build Windows .exe files on Linux using GNU toolchain.
208//!
209//! Build your app for Windows_x64 using GNU toolchain from Linux and Windows (and probably Mac):
210//! * Install mingw-w64 (MSYS2 on windows).
211//! * Add the `Rust` target gnu for windows:`rustup target add x86_64-pc-windows-gnu`
212//! * On 'Non Windows OS': we need wine to compile the shaders:
213//!   - Add i386 architecture (i.e. `sudo dpkg --add-architecture i386` on Ubuntu).
214//!   - Install wine and winetricks.
215//!   - Install needed tools and libs: `winetricks corefonts d3dx9 d3dcompiler_47 dxvk`.
216//! * Create a directory where necessary libs will be stored (i.e. ../x64-mingw-libs/) then add a link to the DLLs or
217//!   static libs (*.a) the build will need after or during its creation. Example on Ubuntu 24.XX:
218//!   - If you want to use DLLs:
219//!      - `ln -s /usr/lib/gcc/x86_64-w64-mingw32/13-win32/libgcc_s_seh-1.dll ../x64-mingw-libs/`
220//!      - `ln -s /usr/lib/gcc/x86_64-w64-mingw32/13-win32/libstdc++-6.dll ../x64-mingw-libs/`
221//!   - If you want to use static libs:
222//!      - `ln -s /usr/lib/gcc/x86_64-w64-mingw32/13-win32/libgcc_eh.a ../x64-mingw-libs/`
223//!      - `ln -s /usr/lib/gcc/x86_64-w64-mingw32/13-win32/libstdc++.a ../x64-mingw-libs/`
224//! * Launch: `cargo build_sk_rs --bin main_vr_app --x64-win-gnu ../x64-mingw-libs/ <the path of your exportable repository>`
225//! * To run your_app.exe on Linux:
226//!   - Add a non-steam game to your library then launch it when WiVRn or SteamVR are started.
227//!   - If you only need the simulator: `wine your_app.exe`.
228//!
229//! ## Building your Linux aarch64 PC VR/MR app:
230//! If you are on aarch64 Linux, you just have to follow the instructions in [`Building your PC VR/MR app`](#building-your-pc-vrmr-app).
231//! If you are on a x86_64 architecture you are able to cross-compile your app for aarch64:
232//! * Install g++-aarch64-linux-gnu
233//! * Get the libraries `libx11-dev:arm64` `libxfixes-dev:arm64` `libegl-dev:arm64` `libgbm-dev:arm64` `libfontconfig-dev:arm64`.
234//!   On Ubuntu 24:XX this can be done by adding a foreign architecture `dpkg --add-architecture arm64` with depot
235//!   `http://ports.ubuntu.com/ubuntu-ports`. To avoid errors during `apt update` you'll have to specify the architectures
236//!   of all depots in `/etc/apt/sources.list.d/ubuntu.sources`
237//! * Add the rust target aarch64 for Linux:`rustup target add aarch64-unknown-linux-gnu`
238//! * Add a section `[target.aarch64-unknown-linux-gnu]` in your config.toml for setting `linker = "aarch64-linux-gnu-gcc"`
239//! * Launch `cargo build_sk_rs --bin main_vr_app --aarch64-linux <the path of your exportable repository>`
240//!
241//! ## Building your Linux x86_64 PC VR/MR app:
242//! If you are on x86_64 Linux, you just have to follow the instructions in [`Building your PC VR/MR app`](#building-your-pc-vrmr-app).
243//! If you are on aarch64 architecture you should be able to cross-compile for x86_64:
244//! (This hasn't been tested yet, if you are interested in testing it, please let us now)
245//! * Install g++-x86-64-linux-gnu
246//! * Get the libraries `libx11-dev:amd64` `libxfixes-dev:amd64` `libegl-dev:amd64` `libgbm-dev:amd64` `libfontconfig-dev:amd64`.
247//!   On Ubuntu 24:XX this can be done by adding a foreign architecture `dpkg --add-architecture amd64` with depot
248//!   `http://ports.ubuntu.com/ubuntu-ports`. To avoid errors during `apt update` you'll have to specify the architectures
249//!   of all depots in `/etc/apt/sources.list.d/ubuntu.sources`
250//! * Add the rust target aarch64 for linux:`rustup target add x86_64-unknown-linux-gnu`
251//! * Add a section `[target.x86_64-unknown-linux-gnu]` in your config.toml for setting `linker = "x86_64-linux-gnu-gcc"`
252//! * Launch `cargo build_sk_rs --bin main_vr_app --x64-linux <the path of your exportable repository>`.
253
254use std::{ffi::NulError, path::PathBuf};
255
256#[cfg(feature = "event-loop")]
257pub use stereokit_macros::IStepper;
258
259pub use stereokit_macros::include_asset_tree;
260
261#[cfg(feature = "event-loop")]
262pub use stereokit_macros::test_init_sk_event_loop as test_init_sk;
263#[cfg(feature = "no-event-loop")]
264pub use stereokit_macros::test_init_sk_no_event_loop as test_init_sk;
265
266pub use stereokit_macros::offscreen_mode_stop_here;
267pub use stereokit_macros::xr_mode_stop_here;
268
269#[cfg(feature = "event-loop")]
270pub use stereokit_macros::test_screenshot_event_loop as test_screenshot;
271#[cfg(feature = "no-event-loop")]
272pub use stereokit_macros::test_screenshot_no_event_loop as test_screenshot;
273
274#[cfg(feature = "event-loop")]
275pub use stereokit_macros::test_steps_event_loop as test_steps;
276#[cfg(feature = "no-event-loop")]
277pub use stereokit_macros::test_steps_no_event_loop as test_steps;
278
279/// Some of the errors you might encounter when using StereoKit-rust.
280use thiserror::Error;
281
282/// Anchor related structs and functions.
283///
284/// With examples which are also unit tests.
285pub mod anchor;
286
287/// Font related structs and functions.
288///
289/// ## Examples
290/// which are also unit tests:
291///
292/// [![Font](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/font.jpeg)](font::Font)
293pub mod font;
294
295/// A namespace containing features exclusive to the rust bindings for StereoKit.
296///
297/// These are higher level pieces of functionality that do not necessarily adhere to the same goals and restrictions as
298/// StereoKit’s core functionality does. This corresponds to the C# namespace:
299/// <https://stereokit.net/Pages/StereoKit.Framework.html>
300/// - An event loop manager based on Winit.
301/// - HandMenuRadial related structs, enums and functions.
302///
303/// At the core of this framework is the [`crate::IStepper`] derive macro, which allows you to create a stepper that can
304/// be run in the event loop.
305/// ## Examples
306/// which are also unit tests:
307/// ```
308/// # stereokit_rust::test_init_sk!(); // !!!! Get a proper way to initialize sk !!!!
309/// use stereokit_rust::{ font::Font, maths::{Matrix, Quat, Vec3},
310///                       system::{Text, TextStyle}, util::named_colors};
311///
312/// #[derive(IStepper)]
313/// pub struct MyStepper {
314///     id: StepperId,
315///     sk_info: Option<Rc<RefCell<SkInfo>>>,
316///
317///     transform: Matrix,
318///     pub text: String,
319///     text_style: Option<TextStyle>,
320/// }
321/// unsafe impl Send for MyStepper {}
322/// impl Default for MyStepper {
323///     fn default() -> Self {
324///         Self {
325///             id: "MyStepper".to_string(),
326///             sk_info: None,
327///
328///             transform: Matrix::IDENTITY,
329///             text: "IStepper\nderive\nmacro".to_owned(),
330///             text_style: None,
331///         }
332///     }
333/// }
334/// impl MyStepper {
335///     fn start(&mut self) -> bool {
336///         self.transform = Matrix::t_r([0.05, 0.0, -0.2], [0.0, 200.0, 0.0]);
337///         self.text_style = Some(Text::make_style(Font::default(), 0.3, named_colors::RED));
338///         true
339///     }
340///     fn check_event(&mut self, _id: &StepperId, _key: &str, _value: &str) {}
341///     fn draw(&mut self, token: &MainThreadToken) {
342///         Text::add_at(token, &self.text, self.transform, self.text_style,
343///                      None, None, None, None, None, None);
344///     }
345/// }
346///
347/// sk.send_event(StepperAction::add_default::<MyStepper>("My_Basic_Stepper_ID"));
348///
349/// filename_scr = "screenshots/istepper_macro.jpeg";
350/// test_screenshot!( // !!!! Get a proper main loop !!!!
351///     // No code here as we only use MyStepper
352/// );
353/// ```
354/// [![IStepper derive macro](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/istepper_macro.jpeg)](IStepper)
355///
356/// [![SkClosures](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sk_closures.jpeg)](framework::SkClosures)
357/// [![IStepper](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/a_stepper.jpeg)](framework::IStepper)
358/// [![StepperAction](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/stepper_actions.jpeg)](framework::StepperAction)
359/// [![Steppers](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/steppers.jpeg)](framework::Steppers)
360/// [![StepperClosures](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/stepper_closures.jpeg)](framework::StepperClosures)
361pub mod framework;
362
363/// Material specific structs, enums and functions.
364///
365/// ## Examples
366/// which are also unit tests:
367///
368/// [![Material](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/materials.jpeg)](material::Material)
369/// [![Material Transparency](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/material_transparency.jpeg)](material::Material::transparency)
370/// [![Material Face Cull](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/material_face_cull.jpeg)](material::Material::face_cull)
371/// [![Material Parameter Info](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/param_infos.jpeg)](material::ParamInfos)
372/// [![Material Parameter Info with id](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/param_infos_with_id.jpeg)](material::ParamInfos::set_data_with_id)
373pub mod material;
374
375/// Vec2, 3 and4, Quat and Matrix, Bounds, Plane and Ray related structs, enums and functions.
376///
377/// ## Examples
378/// which are also unit tests:
379///
380/// [![Matrix](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/matrix.jpeg)](maths::Matrix)
381/// [![Bounds](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/bounds.jpeg)](maths::Bounds)
382/// [![Plane](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/plane.jpeg)](maths::Plane)
383/// [![Pose](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/pose.jpeg)](maths::Pose)
384/// [![Sphere](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sphere.jpeg)](maths::Sphere)
385/// [![Ray](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ray.jpeg)](maths::Ray)
386/// [![Intersect Meshes](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/intersect_meshes.jpeg)](maths::Ray::intersect_mesh)
387/// [![Intersect Model](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/intersect_model.jpeg)](maths::Ray::intersect_model)
388pub mod maths;
389
390/// Mesh related structs, enums and functions.
391///
392/// ## Examples
393/// which are also unit tests:
394///
395/// [![Mesh](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/meshes.jpeg)](mesh::Mesh)
396/// [![Vertex](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/basic_mesh.jpeg)](mesh::Vertex)
397/// [![Mesh bounds](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/mesh_bounds.jpeg)](mesh::Mesh::bounds)
398/// [![Mesh set_verts](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/mesh_set_verts.jpeg)](mesh::Mesh::set_verts)
399/// [![Mesh set_inds](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/mesh_set_inds.jpeg)](mesh::Mesh::set_inds)
400/// [![Mesh draw](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/mesh_draw.jpeg)](mesh::Mesh::draw)
401/// [![Mesh intersect](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/mesh_intersect.jpeg)](mesh::Mesh::intersect)
402pub mod mesh;
403
404/// Model specific structs, enums and functions.
405///
406/// ## Examples
407/// which are also unit tests:
408///
409/// [![Model](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/model.jpeg)](model::Model)
410/// [![Model from memory](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/model_from_memory.jpeg)](model::Model::from_memory)
411/// [![Model from file](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/model_from_file.jpeg)](model::Model::from_file)
412/// [![Model from mesh](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/model_from_mesh.jpeg)](model::Model::from_mesh)
413/// [![Model bounds](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/model_bounds.jpeg)](model::Model::bounds)
414/// [![Model draw](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/model_draw.jpeg)](model::Model::draw)
415/// [![Model draw with material](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/model_draw_with_material.jpeg)](model::Model::draw_with_material)
416/// [![Model intersect](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/model_intersect.jpeg)](model::Model::intersect)
417/// [![Model Anims](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/anims.jpeg)](model::Anims)
418/// [![Model Nodes](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/model_nodes.jpeg)](model::Nodes)
419/// [![ModelNode](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/model_node.jpeg)](model::ModelNode)
420pub mod model;
421
422/// Prelude for StereoKit-rust. The basis for all StereoKit-rust programs.
423pub mod prelude;
424
425/// RenderList related structs, enums and functions.
426///
427/// ## Examples
428/// which are also unit tests:
429///
430/// [![RenderList](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/render_list.jpeg)](render_list::RenderList)
431/// [![RenderList add mesh](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/render_list_add_mesh.jpeg)](render_list::RenderList::add_mesh)
432/// [![RenderList add model](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/render_list_add_model.jpeg)](render_list::RenderList::add_model)
433/// [![RenderList draw now](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/render_list_draw_now.jpeg)](render_list::RenderList::draw_now)
434/// [![RenderList push](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/render_list_push.jpeg)](render_list::RenderList::push)
435pub mod render_list;
436
437/// Shader specific structs, enums and functions.
438///
439/// ## Examples
440/// which are also unit tests:
441///
442/// [![Shader](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/shaders.jpeg)](shader::Shader)
443pub mod shader;
444
445/// Sk related structs, enums and functions.
446///
447/// ## Examples
448/// which are also unit tests:
449///
450/// [![Sk basic example](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sk_basic_example.jpeg)](sk::SkSettings::init_with_event_loop)
451#[cfg(feature = "event-loop")]
452pub mod sk;
453
454/// StereoKit-rust specific structs, enums and functions.
455#[cfg(feature = "no-event-loop")]
456pub mod sk;
457
458/// Sound specific structs, enums and functions.
459///
460/// ## Examples
461/// which are also unit tests:
462///
463/// [![Sound](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sound.jpeg)](sound::Sound)
464/// [![SoundInst](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sound_inst.jpeg)](sound::SoundInst)
465pub mod sound;
466
467/// Sprite related structs, enums and functions.
468///
469/// ## Examples
470/// which are also unit tests:
471///
472/// [![Sprite](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sprite.jpeg)](sprite::Sprite)
473/// [![Sprite from Tex](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sprite_from_tex.jpeg)](sprite::Sprite::from_tex)
474/// [![Sprite from File](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sprite_from_file.jpeg)](sprite::Sprite::from_file)
475/// [![Sprite draw](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sprite_draw.jpeg)](sprite::Sprite::draw)
476///
477/// [![Sprite grid](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sprite_grid.jpeg)](sprite::Sprite::grid)
478/// [![Sprite list](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sprite_list.jpeg)](sprite::Sprite::list)
479/// [![Sprite arrow left](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sprite_arrow_left.jpeg)](sprite::Sprite::arrow_left)
480/// [![Sprite arrow right](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sprite_arrow_right.jpeg)](sprite::Sprite::arrow_right)
481/// [![Sprite arrow up](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sprite_arrow_up.jpeg)](sprite::Sprite::arrow_up)
482/// [![Sprite arrow down](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sprite_arrow_down.jpeg)](sprite::Sprite::arrow_down)
483/// [![Sprite radio off](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sprite_radio_off.jpeg)](sprite::Sprite::radio_off)
484/// [![Sprite radio on](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sprite_radio_on.jpeg)](sprite::Sprite::radio_on)
485/// [![Sprite toggle off](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sprite_toggle_off.jpeg)](sprite::Sprite::toggle_off)
486/// [![Sprite toggle on](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sprite_toggle_on.jpeg)](sprite::Sprite::toggle_on)
487/// [![Sprite backspace](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sprite_backspace.jpeg)](sprite::Sprite::backspace)
488/// [![Sprite close](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sprite_close.jpeg)](sprite::Sprite::close)
489/// [![Sprite shift](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sprite_shift.jpeg)](sprite::Sprite::shift)
490pub mod sprite;
491
492/// Interactor related structs, enums and functions.
493///
494pub mod interactor;
495
496/// Sprite specific structs, enums and functions.
497///
498/// ## Examples
499/// which are also unit tests:
500///
501/// [![Assets](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/assets.jpeg)](system::Assets)
502/// [![Assets block for priority](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/assets_block_for_priority.jpeg)](system::Assets::block_for_priority)
503/// [![Hierarchy](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/hierarchy.jpeg)](system::Hierarchy)
504/// [![Hierarchy ray](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/hierarchy_ray.jpeg)](system::Hierarchy::to_local_ray)
505/// [![Hand](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/hand.jpeg)](system::Hand)
506/// [![Controller](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/controller.jpeg)](system::Controller)
507/// [![Lines](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/lines.jpeg)](system::Lines)
508/// [![Microphone](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/microphone.jpeg)](system::Microphone)
509/// [![Renderer](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/renderer.jpeg)](system::Renderer)
510/// [![Screenshots capture](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/screenshot_capture.jpeg)](system::Renderer::screenshot_capture)
511/// [![TextStyle](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/text_style.jpeg)](system::TextStyle)
512/// [![Text](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/text.jpeg)](system::Text)
513pub mod system;
514
515/// Tex related structs, enums and functions.
516///
517/// ## Examples
518/// which are also unit tests:
519///
520/// [![Tex](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/tex.jpeg)](tex::Tex)
521/// [![Tex from file](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/tex_from_file.jpeg)](tex::Tex::from_file)
522/// [![Tex gen_particle](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/tex_gen_particle.jpeg)](tex::Tex::gen_particle)
523/// [![SHCubemap](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/sh_cubemap.jpeg)](tex::SHCubemap)
524pub mod tex;
525
526/// Many `non-canonical`` tools related structs, enums and functions.
527///
528/// ## Examples
529/// which are also unit tests:
530///
531/// [![FileBrowser](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/file_browser.jpeg)](tools::file_browser::FileBrowser)
532/// [![FlyOver](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/fly_over.jpeg)](tools::fly_over::FlyOver)
533/// [![Log window](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/log_window.jpeg)](tools::log_window::LogWindow)
534/// [![Hud Notification](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/hud_notification.jpeg)](tools::notif::HudNotification)
535/// [![Screenshot viewer](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/screenshot_viewer.jpeg)](tools::screenshot::ScreenshotViewer)
536/// [![Title](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/title.jpeg)](tools::title::Title)
537pub mod tools;
538
539/// The UI module is a collection of functions and structs that allow you to create a user interface.
540///
541/// ## Examples
542/// which are also unit tests:
543///
544/// [![Ui](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui.jpeg)](ui::Ui)
545/// [![Ui color_scheme](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_color_scheme.jpeg)](ui::Ui::color_scheme)
546/// [![Ui button](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_button.jpeg)](ui::Ui::button)
547/// [![Ui button_img](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_button_img.jpeg)](ui::Ui::button_img)
548/// [![Ui button_round](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_button_round.jpeg)](ui::Ui::button_round)
549/// [![Ui handle](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_handle.jpeg)](ui::Ui::handle)
550/// [![Ui handle_begin](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_handle_begin.jpeg)](ui::Ui::handle_begin)
551/// [![Ui hseparator](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_hseparator.jpeg)](ui::Ui::hseparator)
552/// [![Ui hslider](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_hslider.jpeg)](ui::Ui::hslider)
553/// [![Ui vslider](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_vslider.jpeg)](ui::Ui::vslider)
554/// [![Ui slider_behavior](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_slider_behavior.jpeg)](ui::Ui::slider_behavior)
555/// [![Ui image](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_image.jpeg)](ui::Ui::image)
556/// [![Ui input](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_input.jpeg)](ui::Ui::input)
557/// [![Ui label](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_label.jpeg)](ui::Ui::label)
558/// [![Ui layout_area](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_layout_area.jpeg)](ui::Ui::layout_area)
559/// [![Ui layout_push](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_layout_push.jpeg)](ui::Ui::layout_push)
560/// [![Ui model](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_model.jpeg)](ui::Ui::model)
561/// [![Ui panel_at](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_panel_at.jpeg)](ui::Ui::panel_at)
562/// [![Ui panel_begin](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_panel_begin.jpeg)](ui::Ui::panel_begin)
563/// [![Ui progress_bar_at](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_progress_bar_at.jpeg)](ui::Ui::progress_bar_at)
564/// [![Ui push_surface](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_push_surface.jpeg)](ui::Ui::push_surface)
565/// [![Ui push_text_style](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_push_text_style.jpeg)](ui::Ui::push_text_style)
566/// [![Ui push_tint](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_push_tint.jpeg)](ui::Ui::push_tint)
567/// [![Ui gen_quadrant_mesh](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_gen_quadrant_mesh.jpeg)](ui::Ui::gen_quadrant_mesh)
568/// [![Ui radio button](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_radio.jpeg)](ui::Ui::radio_img)
569/// [![Ui toggle](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_toggle.jpeg)](ui::Ui::toggle)
570/// [![Ui draw_element](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_draw_element.jpeg)](ui::Ui::draw_element)
571/// [![Ui set_theme_color](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_set_theme_color.jpeg)](ui::Ui::set_theme_color)
572/// [![Ui text](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_text.jpeg)](ui::Ui::text)
573/// [![Ui window](https://raw.githubusercontent.com/mvvvv/StereoKit-rust/refs/heads/master/screenshots/ui_window.jpeg)](ui::Ui::window_begin)
574pub mod ui;
575
576/// Many utility structs, enums and functions.
577pub mod util;
578
579/// Some of the errors you might encounter when using StereoKit-rust.
580#[derive(Error, Debug)]
581pub enum StereoKitError {
582    #[error("unable to create model from file path {0}")]
583    ModelFile(String),
584    #[error("unable to find model with id {0}")]
585    ModelFind(String),
586    #[error("failed to create model {0} from memory for reason {1}")]
587    ModelFromMem(String, String),
588    #[error("failed to create model {0} from file for reason {1}")]
589    ModelFromFile(PathBuf, String),
590    #[error("failed to generate mesh {0}")]
591    MeshGen(String),
592    #[error("failed to find mesh {0}")]
593    MeshFind(String),
594    #[error("failed to convert to CString {0} in mesh_find")]
595    MeshCString(String),
596    #[error("failed to convert to CString {0} in tex_find")]
597    TexCString(String),
598    #[error("failed to find tex {0}")]
599    TexFind(String),
600    #[error("failed to copy tex {0}")]
601    TexCopy(String),
602    #[error("failed to create a tex from raw memory")]
603    TexMemory,
604    #[error("failed to create a tex from file {0} for reason {1}")]
605    TexFile(PathBuf, String),
606    #[error("failed to create a tex from multiple files {0} for reason {1}")]
607    TexFiles(PathBuf, String),
608    #[error("failed to create a tex from color {0} for reason {1}")]
609    TexColor(String, String),
610    #[error("failed to create a tex rendertarget {0} for reason {1}")]
611    TexRenderTarget(String, String),
612    #[error("failed to find font {0} for reason {1}")]
613    FontFind(String, String),
614    #[error("failed to create font from file {0} for reason {1}")]
615    FontFile(PathBuf, String),
616    #[error("failed to create font from multiple files {0} for reason {1}")]
617    FontFiles(String, String),
618    #[error("failed to create font family {0} for reason {1}")]
619    FontFamily(String, String),
620    #[error("failed to find shader {0} for reason {1}")]
621    ShaderFind(String, String),
622    #[error("failed to create shader from file {0} for reason {1}")]
623    ShaderFile(PathBuf, String),
624    #[error("failed to create shader from raw memory")]
625    ShaderMem,
626    #[error("failed to find material {0} for reason {1}")]
627    MaterialFind(String, String),
628    #[error("failed to create sprite from texture")]
629    SpriteCreate,
630    #[error("failed to create sprite from file {0}")]
631    SpriteFile(PathBuf),
632    #[error("failed to find sprite {0} for reason {1}")]
633    SpriteFind(String, String),
634    #[error("failed to find sound {0} for reason {1}")]
635    SoundFind(String, String),
636    #[error("failed to find render list {0} for reason {1}")]
637    RenderListFind(String, String),
638    #[error("failed to create sound from file {0}")]
639    SoundFile(PathBuf),
640    #[error("failed to create sound streaming {0}")]
641    SoundCreate(String),
642    #[error("failed to create anchor {0}")]
643    AnchorCreate(String),
644    #[error("failed to find anchor {0} for reason {1}")]
645    AnchorFind(String, String),
646    #[error("failed to init stereokit with settings {0}")]
647    SkInit(String),
648    #[cfg(feature = "event-loop")]
649    #[error("failed to init stereokit event_loop")]
650    SkInitEventLoop(#[from] winit::error::EventLoopError),
651    #[error("failed to get a string from native C {0}")]
652    CStrError(String),
653    #[error("failed to read a file {0}: {1}")]
654    ReadFileError(PathBuf, String),
655    #[error("failed to write a file {0}: {1}")]
656    WriteFileError(PathBuf, String),
657    #[error("Directory {0} do not exist or is not a directory")]
658    DirectoryError(String),
659    #[error(transparent)]
660    Other(#[from] NulError),
661}