use crate::{
StereoKitError,
anchor::{_AnchorT, Anchor},
font::{_FontT, Font, FontT},
material::{_MaterialT, Material, MaterialBuffer, MaterialBufferT, MaterialT},
maths::{Bool32T, Matrix, Pose, Quat, Ray, Rect, Vec2, Vec3, ray_from_mouse},
mesh::{_MeshT, Mesh, MeshT},
model::{_ModelT, Model, ModelT},
render_list::{_RenderListT, RenderList},
shader::{_ShaderT, Shader, ShaderT},
sk::{MainThreadToken, OriginMode},
sound::{_SoundT, Sound, SoundT},
sprite::{_SpriteT, Sprite},
tex::{_TexT, Tex, TexFormat, TexT},
util::{Color32, Color128, SphericalHarmonics},
};
use std::{
ffi::{CStr, CString, c_char, c_ushort, c_void},
fmt,
mem::{size_of, transmute_copy},
path::Path,
ptr::{NonNull, null, null_mut},
};
pub use crate::interactor::{
DefaultInteractors, Interaction, Interactor, InteractorActivation, InteractorEvent, InteractorType,
};
pub trait IAsset {
fn get_id(&self) -> &str;
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(C)]
pub enum AssetState {
Unsupported = -3,
NotFound = -2,
Error = -1,
None = 0,
Loading = 1,
LoadedMeta = 2,
Loaded = 3,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum AssetType {
None = 0,
Mesh = 1,
Tex = 2,
Shader = 3,
Material = 4,
Model = 5,
Font = 6,
Sprite = 7,
Sound = 8,
Solid = 9,
Anchor = 10,
RenderList = 11,
}
pub struct Assets;
pub type AssetT = *mut c_void;
unsafe extern "C" {
pub fn assets_releaseref_threadsafe(asset: *mut c_void);
pub fn assets_current_task() -> i32;
pub fn assets_total_tasks() -> i32;
pub fn assets_current_task_priority() -> i32;
pub fn assets_block_for_priority(priority: i32);
pub fn assets_count() -> i32;
pub fn assets_get_index(index: i32) -> AssetT;
pub fn assets_get_type(index: i32) -> AssetType;
pub fn asset_get_type(asset: AssetT) -> AssetType;
pub fn asset_set_id(asset: AssetT, id: *const c_char);
pub fn asset_get_id(asset: AssetT) -> *const c_char;
pub fn asset_addref(asset: AssetT);
pub fn asset_release(asset: AssetT);
}
#[derive(Debug)]
pub enum Asset {
None,
Mesh(Mesh),
Tex(Tex),
Shader(Shader),
Material(Material),
Model(Model),
Font(Font),
Sprite(Sprite),
Sound(Sound),
Solid(*mut c_void),
Anchor(Anchor),
RenderList(RenderList),
}
impl fmt::Display for Asset {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Asset::None => write!(f, "None"),
Asset::Mesh(v) => write!(f, "Mesh : {}", v.get_id()),
Asset::Tex(v) => write!(f, "Tex : {}", v.get_id()),
Asset::Shader(v) => write!(f, "Shader : {}", v.get_id()),
Asset::Material(v) => write!(f, "Material : {}", v.get_id()),
Asset::Model(v) => write!(f, "Model : {}", v.get_id()),
Asset::Font(v) => write!(f, "Font : {}", v.get_id()),
Asset::Sprite(v) => write!(f, "Sprite : {}", v.get_id()),
Asset::Sound(v) => write!(f, "Sound : {}", v.get_id()),
Asset::Solid(_) => write!(f, "Solid : ... deprecated ..."),
Asset::Anchor(v) => write!(f, "Anchor : {}", v.get_id()),
Asset::RenderList(v) => write!(f, "RenderList : {}", v.get_id()),
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct AssetIter {
index: i32,
pub asset_type: AssetType,
}
impl Iterator for AssetIter {
type Item = Asset;
fn next(&mut self) -> Option<Self::Item> {
self.index += 1;
let count = unsafe { assets_count() };
if self.asset_type == AssetType::None {
if self.index < count {
match unsafe { assets_get_type(self.index) } {
AssetType::None => {
Log::err(format!("Asset at index {:?}/{:?} is AssetType::None", self.index, count));
None
}
asset_type => {
let asset_id = unsafe { assets_get_index(self.index) };
Some(self.to_asset(asset_type, asset_id))
}
}
} else {
None
}
} else {
while self.index < count {
if unsafe { assets_get_type(self.index) } == self.asset_type {
let asset_id = unsafe { assets_get_index(self.index) };
return Some(self.to_asset(self.asset_type, asset_id));
} else {
self.index += 1;
}
}
None
}
}
}
impl AssetIter {
fn to_asset(self, asset_type: AssetType, c_id: *mut c_void) -> Asset {
match asset_type {
AssetType::None => Asset::None,
AssetType::Mesh => Asset::Mesh(Mesh(NonNull::new(c_id as *mut _MeshT).unwrap())),
AssetType::Tex => Asset::Tex(Tex(NonNull::new(c_id as *mut _TexT).unwrap())),
AssetType::Shader => Asset::Shader(Shader(NonNull::new(c_id as *mut _ShaderT).unwrap())),
AssetType::Material => Asset::Material(Material(NonNull::new(c_id as *mut _MaterialT).unwrap())),
AssetType::Model => Asset::Model(Model(NonNull::new(c_id as *mut _ModelT).unwrap())),
AssetType::Font => Asset::Font(Font(NonNull::new(c_id as *mut _FontT).unwrap())),
AssetType::Sprite => Asset::Sprite(Sprite(NonNull::new(c_id as *mut _SpriteT).unwrap())),
AssetType::Sound => Asset::Sound(Sound(NonNull::new(c_id as *mut _SoundT).unwrap())),
AssetType::Solid => todo!("Solids are deprecated!"),
AssetType::Anchor => Asset::Anchor(Anchor(NonNull::new(c_id as *mut _AnchorT).unwrap())),
AssetType::RenderList => Asset::RenderList(RenderList(NonNull::new(c_id as *mut _RenderListT).unwrap())),
}
}
pub fn iterate(asset_type: Option<AssetType>) -> AssetIter {
let asset_type = asset_type.unwrap_or(AssetType::None);
AssetIter { index: -1, asset_type }
}
}
impl Assets {
pub const MODEL_FORMATS: [&'static str; 5] = [".gltf", ".glb", ".obj", ".stl", ".ply"];
pub const TEXTURE_FORMATS: [&'static str; 11] =
[".jpg", ".jpeg", ".png", ".hdr", ".tga", ".bmp", ".psd", ".pic", ".qoi", ".gif", ".ktx2"];
pub const SOUND_FORMATS: [&'static str; 2] = [".wav", ".mp3"];
pub fn all() -> AssetIter {
AssetIter::iterate(None)
}
pub fn all_of_type(asset_type: AssetType) -> AssetIter {
AssetIter::iterate(Some(asset_type))
}
pub fn current_task() -> i32 {
unsafe { assets_current_task() }
}
pub fn current_task_priority() -> i32 {
unsafe { assets_current_task_priority() }
}
pub fn total_tasks() -> i32 {
unsafe { assets_total_tasks() }
}
pub fn block_for_priority(priority: i32) {
unsafe { assets_block_for_priority(priority) }
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum BackendXRType {
None = 0,
Simulator = 1,
OpenXR = 2,
WebXR = 3,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum BackendPlatform {
Win32 = 0,
Uwp = 1,
Linux = 2,
Android = 3,
Web = 4,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum BackendGraphics {
None = 0,
D3D11 = 1,
OpenGLGLX = 2,
OpenGLWGL = 3,
OpenGLESEGL = 4,
WebGL = 5,
}
pub type OpenXRHandleT = u64;
pub struct Backend;
pub type VoidFunction = unsafe extern "system" fn();
unsafe extern "C" {
pub fn backend_xr_get_type() -> BackendXRType;
pub fn backend_openxr_get_instance() -> OpenXRHandleT;
pub fn backend_openxr_get_session() -> OpenXRHandleT;
pub fn backend_openxr_get_system_id() -> OpenXRHandleT;
pub fn backend_openxr_get_space() -> OpenXRHandleT;
pub fn backend_openxr_get_time() -> i64;
pub fn backend_openxr_get_eyes_sample_time() -> i64;
pub fn backend_openxr_get_function(function_name: *const c_char) -> Option<VoidFunction>;
pub fn backend_openxr_ext_enabled(extension_name: *const c_char) -> Bool32T;
pub fn backend_openxr_ext_request(extension_name: *const c_char);
pub fn backend_openxr_ext_exclude(extension_name: *const c_char);
pub fn backend_openxr_use_minimum_exts(use_minimum_exts: Bool32T);
pub fn backend_openxr_composition_layer(XrCompositionLayerBaseHeader: *mut c_void, data_size: i32, sort_order: i32);
pub fn backend_openxr_end_frame_chain(XrBaseHeader: *mut c_void, data_size: i32);
pub fn backend_openxr_set_hand_joint_scale(joint_scale_factor: f32);
pub fn backend_openxr_add_callback_pre_session_create(
xr_pre_session_create_callback: ::std::option::Option<unsafe extern "C" fn(context: *mut c_void)>,
context: *mut c_void,
);
pub fn backend_openxr_add_callback_poll_event(
xr_poll_event_callback: ::std::option::Option<
unsafe extern "C" fn(context: *mut c_void, xr_event_data_buffer: *mut c_void),
>,
context: *mut c_void,
);
pub fn backend_openxr_remove_callback_poll_event(
xr_poll_event_callback: ::std::option::Option<
unsafe extern "C" fn(context: *mut c_void, xr_event_data_buffer: *mut c_void),
>,
);
pub fn backend_platform_get() -> BackendPlatform;
pub fn backend_android_get_java_vm() -> *mut c_void;
pub fn backend_android_get_activity() -> *mut c_void;
pub fn backend_android_get_jni_env() -> *mut c_void;
pub fn backend_graphics_get() -> BackendGraphics;
pub fn backend_d3d11_get_d3d_device() -> *mut c_void;
pub fn backend_d3d11_get_d3d_context() -> *mut c_void;
pub fn backend_d3d11_get_deferred_d3d_context() -> *mut c_void;
pub fn backend_d3d11_get_deferred_mtx() -> *mut c_void;
pub fn backend_d3d11_get_main_thread_id() -> u32;
pub fn backend_opengl_wgl_get_hdc() -> *mut c_void;
pub fn backend_opengl_wgl_get_hglrc() -> *mut c_void;
pub fn backend_opengl_glx_get_context() -> *mut c_void;
pub fn backend_opengl_glx_get_display() -> *mut c_void;
pub fn backend_opengl_glx_get_drawable() -> *mut c_void;
pub fn backend_opengl_egl_get_context() -> *mut c_void;
pub fn backend_opengl_egl_get_config() -> *mut c_void;
pub fn backend_opengl_egl_get_display() -> *mut c_void;
}
impl Backend {
pub fn graphics() -> BackendGraphics {
unsafe { backend_graphics_get() }
}
pub fn platform() -> BackendPlatform {
unsafe { backend_platform_get() }
}
pub fn xr_type() -> BackendXRType {
unsafe { backend_xr_get_type() }
}
}
pub struct BackendOpenXR;
impl BackendOpenXR {
pub fn eyes_sample_time() -> i64 {
unsafe { backend_openxr_get_eyes_sample_time() }
}
pub fn instance() -> OpenXRHandleT {
unsafe { backend_openxr_get_instance() }
}
pub fn session() -> OpenXRHandleT {
unsafe { backend_openxr_get_session() }
}
pub fn space() -> OpenXRHandleT {
unsafe { backend_openxr_get_space() }
}
pub fn system_id() -> OpenXRHandleT {
unsafe { backend_openxr_get_system_id() }
}
pub fn time() -> i64 {
unsafe { backend_openxr_get_time() }
}
pub fn use_minimum_exts(value: bool) {
unsafe { backend_openxr_use_minimum_exts(value as Bool32T) }
}
pub fn add_composition_layer<T>(xr_composition_layer_x: &mut T, sort_order: i32) {
let size = size_of::<T>();
let ptr = xr_composition_layer_x as *mut _ as *mut c_void;
unsafe { backend_openxr_composition_layer(ptr, size as i32, sort_order) }
}
pub fn add_end_frame_chain<T>(xr_base_header: &mut T) {
let size = size_of::<T>();
let ptr = xr_base_header as *mut _ as *mut c_void;
unsafe { backend_openxr_end_frame_chain(ptr, size as i32) }
}
pub fn exclude_ext(extension_name: impl AsRef<str>) {
let c_str = CString::new(extension_name.as_ref()).unwrap();
unsafe { backend_openxr_ext_exclude(c_str.as_ptr()) }
}
pub fn request_ext(extension_name: impl AsRef<str>) {
let c_str = CString::new(extension_name.as_ref()).unwrap();
unsafe { backend_openxr_ext_request(c_str.as_ptr()) }
}
pub fn ext_enabled(extension_name: impl AsRef<str>) -> bool {
if Backend::xr_type() == BackendXRType::OpenXR {
let c_str = CString::new(extension_name.as_ref()).unwrap();
unsafe { backend_openxr_ext_enabled(c_str.as_ptr()) != 0 }
} else {
false
}
}
pub fn get_function_ptr(function_name: impl AsRef<str>) -> Option<VoidFunction> {
let c_str = CString::new(function_name.as_ref()).unwrap();
unsafe { backend_openxr_get_function(c_str.as_ptr()) }
}
pub fn get_function<T>(function_name: impl AsRef<str>) -> Option<T> {
let c_str = CString::new(function_name.as_ref()).unwrap();
let function = unsafe { backend_openxr_get_function(c_str.as_ptr()) };
unsafe { transmute_copy(&function) }
}
pub fn set_hand_joint_scale(joint_scale_factor: f32) {
unsafe { backend_openxr_set_hand_joint_scale(joint_scale_factor) }
}
}
pub struct BackendAndroid;
impl BackendAndroid {
pub fn activity() -> *mut c_void {
unsafe { backend_android_get_activity() }
}
pub fn java_vm() -> *mut c_void {
unsafe { backend_android_get_java_vm() }
}
pub fn jni_environment() -> *mut c_void {
unsafe { backend_android_get_jni_env() }
}
}
pub struct BackendD3D11;
impl BackendD3D11 {
pub fn d3d_context() -> *mut c_void {
unsafe { backend_d3d11_get_d3d_context() }
}
pub fn d3d_device() -> *mut c_void {
unsafe { backend_d3d11_get_d3d_device() }
}
}
pub struct BackendOpenGLWGL;
impl BackendOpenGLWGL {
pub fn hdc() -> *mut c_void {
unsafe { backend_opengl_wgl_get_hdc() }
}
pub fn hglrc() -> *mut c_void {
unsafe { backend_opengl_wgl_get_hglrc() }
}
}
pub struct BackendOpenGLESEGL;
impl BackendOpenGLESEGL {
pub fn context() -> *mut c_void {
unsafe { backend_opengl_egl_get_context() }
}
pub fn display() -> *mut c_void {
unsafe { backend_opengl_egl_get_display() }
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum HierarchyParent {
Inherit = 0,
Ignore = 1,
}
pub struct Hierarchy;
unsafe extern "C" {
pub fn hierarchy_push(transform: *const Matrix, parent_behavior: HierarchyParent);
pub fn hierarchy_push_pose(pose: *const Pose, parent_behavior: HierarchyParent);
pub fn hierarchy_pop();
pub fn hierarchy_set_enabled(enabled: Bool32T);
pub fn hierarchy_is_enabled() -> Bool32T;
pub fn hierarchy_to_world() -> *const Matrix;
pub fn hierarchy_to_local() -> *const Matrix;
pub fn hierarchy_to_local_point(world_pt: *const Vec3) -> Vec3;
pub fn hierarchy_to_local_direction(world_dir: *const Vec3) -> Vec3;
pub fn hierarchy_to_local_rotation(world_orientation: *const Quat) -> Quat;
pub fn hierarchy_to_local_pose(world_pose: *const Pose) -> Pose;
pub fn hierarchy_to_local_ray(world_ray: Ray) -> Ray;
pub fn hierarchy_to_world_point(local_pt: *const Vec3) -> Vec3;
pub fn hierarchy_to_world_direction(local_dir: *const Vec3) -> Vec3;
pub fn hierarchy_to_world_rotation(local_orientation: *const Quat) -> Quat;
pub fn hierarchy_to_world_pose(local_pose: *const Pose) -> Pose;
pub fn hierarchy_to_world_ray(local_ray: Ray) -> Ray;
}
impl Hierarchy {
pub fn enabled(_token: &MainThreadToken, enable: bool) {
unsafe { hierarchy_set_enabled(enable as Bool32T) }
}
pub fn is_enabled(_token: &MainThreadToken) -> bool {
unsafe { hierarchy_is_enabled() != 0 }
}
pub fn pop(_token: &MainThreadToken) {
unsafe { hierarchy_pop() }
}
pub fn push<M: Into<Matrix>>(_token: &MainThreadToken, transform: M, parent_behavior: Option<HierarchyParent>) {
let parent_behavior = parent_behavior.unwrap_or(HierarchyParent::Inherit);
unsafe { hierarchy_push(&transform.into(), parent_behavior) }
}
pub fn to_local_point<V: Into<Vec3>>(_token: &MainThreadToken, world_point: V) -> Vec3 {
unsafe { hierarchy_to_local_point(&world_point.into()) }
}
pub fn to_local_rotation<Q: Into<Quat>>(_token: &MainThreadToken, world_orientation: Q) -> Quat {
unsafe { hierarchy_to_local_rotation(&world_orientation.into()) }
}
pub fn to_local_pose<P: Into<Pose>>(_token: &MainThreadToken, world_pose: P) -> Pose {
unsafe { hierarchy_to_local_pose(&world_pose.into()) }
}
pub fn to_local_ray<R: Into<Ray>>(_token: &MainThreadToken, world_ray: R) -> Ray {
unsafe { hierarchy_to_local_ray(world_ray.into()) }
}
pub fn to_local_direction<V: Into<Vec3>>(_token: &MainThreadToken, world_direction: V) -> Vec3 {
unsafe { hierarchy_to_local_direction(&world_direction.into()) }
}
pub fn to_world_point<V: Into<Vec3>>(_token: &MainThreadToken, local_point: V) -> Vec3 {
unsafe { hierarchy_to_world_point(&local_point.into()) }
}
pub fn to_world_rotation<Q: Into<Quat>>(_token: &MainThreadToken, local_orientation: Q) -> Quat {
unsafe { hierarchy_to_world_rotation(&local_orientation.into()) }
}
pub fn to_world_pose<P: Into<Pose>>(_token: &MainThreadToken, local_pose: P) -> Pose {
unsafe { hierarchy_to_world_pose(&local_pose.into()) }
}
pub fn to_world_ray<P: Into<Ray>>(_token: &MainThreadToken, local_ray: P) -> Ray {
unsafe { hierarchy_to_world_ray(local_ray.into()) }
}
pub fn to_world_direction<V: Into<Vec3>>(_token: &MainThreadToken, local_direction: V) -> Vec3 {
unsafe { hierarchy_to_world_direction(&local_direction.into()) }
}
}
bitflags::bitflags! {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct InputSource: u32 {
const Any = 2147483647;
const None = 0;
const Hand = 1;
const HandLeft = 2;
const HandRight = 4;
#[deprecated(since = "0.4.0", note = "Use Input::get_eyes() instead")]
const Gaze = 16;
#[deprecated(since = "0.4.0", note = "Use Input::get_eyes() instead")]
const GazeHead = 32;
#[deprecated(since = "0.4.0", note = "Use Input::get_eyes() instead")]
const GazeEyes = 64;
#[deprecated(since = "0.4.0", note = "Use Input::get_eyes() instead")]
const GazeCurzor = 128;
#[deprecated(since = "0.4.0", note = "Not working any more")]
const CanPress = 256;
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum Handed {
Left = 0,
Right = 1,
Max = 2,
}
bitflags::bitflags! {
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, PartialOrd)]
#[repr(C)]
pub struct BtnState: u32 {
const Inactive = 0;
const Active = 1 << 0;
const JustInactive = 1 << 1;
const JustActive = 1 << 2;
const Changed = Self::JustInactive.bits() | Self::JustActive.bits();
const Any = 0x7FFFFFFF;
}
}
impl BtnState {
pub fn make(was_active: bool, is_active: bool) -> BtnState {
let mut result = if is_active { BtnState::Active } else { BtnState::Inactive };
if was_active && !is_active {
result |= BtnState::JustInactive;
}
if is_active && !was_active {
result |= BtnState::JustActive;
}
result
}
pub fn is_active(&self) -> bool {
(*self & BtnState::Active) > BtnState::Inactive
}
pub fn is_just_active(&self) -> bool {
(*self & BtnState::JustActive) > BtnState::Inactive
}
pub fn is_just_inactive(&self) -> bool {
(*self & BtnState::JustInactive) > BtnState::Inactive
}
pub fn is_changed(&self) -> bool {
(*self & BtnState::Changed) > BtnState::Inactive
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum TrackState {
Lost = 0,
Inferred = 1,
Known = 2,
}
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct Pointer {
pub source: InputSource,
pub tracked: BtnState,
pub state: BtnState,
pub ray: Ray,
pub orientation: Quat,
}
impl Pointer {
pub fn get_pose(&self) -> Pose {
Pose::new(self.ray.position, Some(self.orientation))
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[repr(C)]
pub struct HandJoint {
pub position: Vec3,
pub orientation: Quat,
pub radius: f32,
}
#[derive(Debug, Copy, Clone)]
#[repr(u32)]
pub enum FingerId {
Thumb = 0,
Index = 1,
Middle = 2,
Ring = 3,
Little = 4,
}
#[derive(Debug, Copy, Clone)]
#[repr(u32)]
pub enum JointId {
Root = 0,
KnuckleMajor = 1,
KnuckleMid = 2,
KnuckleMinor = 3,
Tip = 4,
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[repr(u32)]
pub enum HandSource {
None = 0,
Simulated = 1,
Articulated = 2,
Overridden = 3,
}
pub type HandSimId = i32;
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct Hand {
pub fingers: [[HandJoint; 5usize]; 5usize],
pub wrist: Pose,
pub palm: Pose,
pub aim: Pose,
pub pinch_pt: Vec3,
pub handed: Handed,
pub tracked: BtnState,
pub pinch: BtnState,
pub grip: BtnState,
pub aim_ready: BtnState,
pub size: f32,
pub pinch_activation: f32,
pub grip_activation: f32,
}
impl Hand {
pub fn get(&self, finger: FingerId, joint: JointId) -> HandJoint {
self.fingers[finger as usize][joint as usize]
}
pub fn get_u(&self, finger: usize, joint: usize) -> HandJoint {
self.fingers[finger][joint]
}
pub fn is_gripped(&self) -> bool {
(self.grip & BtnState::Active) > BtnState::Inactive
}
pub fn is_just_gripped(&self) -> bool {
(self.grip & BtnState::JustActive) > BtnState::Inactive
}
pub fn is_just_ungripped(&self) -> bool {
(self.grip & BtnState::JustInactive) > BtnState::Inactive
}
pub fn is_pinched(&self) -> bool {
(self.pinch & BtnState::Active) > BtnState::Inactive
}
pub fn is_just_pinched(&self) -> bool {
(self.pinch & BtnState::JustActive) > BtnState::Inactive
}
pub fn is_just_unpinched(&self) -> bool {
(self.pinch & BtnState::JustInactive) > BtnState::Inactive
}
pub fn is_tracked(&self) -> bool {
(self.tracked & BtnState::Active) > BtnState::Inactive
}
pub fn is_just_tracked(&self) -> bool {
(self.tracked & BtnState::JustActive) > BtnState::Inactive
}
pub fn is_just_untracked(&self) -> bool {
(self.tracked & BtnState::JustInactive) > BtnState::Inactive
}
pub fn material(&mut self, material: impl AsRef<Material>) -> &mut Self {
unsafe { input_hand_material(self.handed, material.as_ref().0.as_ptr()) }
self
}
pub fn visible(&mut self, visible: bool) -> &mut Self {
unsafe { input_hand_visible(self.handed, visible as Bool32T) }
self
}
}
#[derive(Debug, Copy, Clone)]
#[repr(u32)]
pub enum ControllerKey {
None_ = 0,
Trigger = 1,
Grip = 2,
X1 = 3,
X2 = 4,
Stick = 5,
Menu = 6,
}
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct Controller {
pub pose: Pose,
pub palm: Pose,
pub aim: Pose,
pub tracked: BtnState,
pub tracked_pos: TrackState,
pub tracked_rot: TrackState,
pub stick_click: BtnState,
pub x1: BtnState,
pub x2: BtnState,
pub trigger: f32,
pub grip: f32,
pub stick: Vec2,
}
impl Controller {
pub fn is_x1_pressed(&self) -> bool {
(self.x1 & BtnState::Active) > BtnState::Inactive
}
pub fn is_x1_just_pressed(&self) -> bool {
(self.x1 & BtnState::JustActive) > BtnState::Inactive
}
pub fn is_x1_just_unpressed(&self) -> bool {
(self.x1 & BtnState::JustInactive) > BtnState::Inactive
}
pub fn is_x2_pressed(&self) -> bool {
(self.x2 & BtnState::Active) > BtnState::Inactive
}
pub fn is_x2_just_pressed(&self) -> bool {
(self.x2 & BtnState::JustActive) > BtnState::Inactive
}
pub fn is_x2_just_unpressed(&self) -> bool {
(self.x2 & BtnState::JustInactive) > BtnState::Inactive
}
pub fn is_stick_clicked(&self) -> bool {
(self.stick_click & BtnState::Active) > BtnState::Inactive
}
pub fn is_stick_just_clicked(&self) -> bool {
(self.stick_click & BtnState::JustActive) > BtnState::Inactive
}
pub fn is_stick_just_unclicked(&self) -> bool {
(self.stick_click & BtnState::JustInactive) > BtnState::Inactive
}
pub fn is_tracked(&self) -> bool {
(self.tracked & BtnState::Active) > BtnState::Inactive
}
pub fn is_just_tracked(&self) -> bool {
(self.tracked & BtnState::JustActive) > BtnState::Inactive
}
pub fn is_just_untracked(&self) -> bool {
(self.tracked & BtnState::JustInactive) > BtnState::Inactive
}
}
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct Mouse {
pub available: Bool32T,
pub pos: Vec2,
pub pos_change: Vec2,
pub scroll: f32,
pub scroll_change: f32,
}
impl Mouse {
pub fn get_ray(&self) -> Ray {
let mut out_ray = Ray::default();
unsafe { ray_from_mouse(self.pos, &mut out_ray) };
out_ray
}
pub fn is_available(&self) -> bool {
self.available != 0
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum Key {
None = 0,
MouseLeft = 1,
MouseRight = 2,
MouseCenter = 4,
MouseForward = 5,
MouseBack = 6,
Backspace = 8,
Tab = 9,
Return = 13,
Shift = 16,
Ctrl = 17,
Alt = 18,
CapsLock = 20,
Esc = 27,
Space = 32,
End = 35,
Home = 36,
Left = 37,
Right = 39,
Up = 38,
Down = 40,
PageUp = 33,
PageDown = 34,
PrintScreen = 42,
KeyInsert = 45,
Del = 46,
Key0 = 48,
Key1 = 49,
Key2 = 50,
Key3 = 51,
Key4 = 52,
Key5 = 53,
Key6 = 54,
Key7 = 55,
Key8 = 56,
Key9 = 57,
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90,
Numpad0 = 96,
Numpad1 = 97,
Numpad2 = 98,
Numpad3 = 99,
Numpad4 = 100,
Numpad5 = 101,
Numpad6 = 102,
Numpad7 = 103,
Numpad8 = 104,
Numpad9 = 105,
F1 = 112,
F2 = 113,
F3 = 114,
F4 = 115,
F5 = 116,
F6 = 117,
F7 = 118,
F8 = 119,
F9 = 120,
F10 = 121,
F11 = 122,
F12 = 123,
Comma = 188,
Period = 190,
SlashFwd = 191,
SlashBack = 220,
Semicolon = 186,
Apostrophe = 222,
BracketOpen = 219,
BracketClose = 221,
Minus = 189,
Equals = 187,
Backtick = 192,
LCmd = 91,
RCmd = 92,
Multiply = 106,
Add = 107,
Subtract = 109,
Decimal = 110,
Divide = 111,
}
pub struct Input;
unsafe extern "C" {
pub fn input_pointer_count(filter: InputSource) -> i32;
pub fn input_pointer(index: i32, filter: InputSource) -> Pointer;
pub fn input_hand(hand: Handed) -> *const Hand;
pub fn input_hand_override(hand: Handed, in_arr_hand_joints: *const HandJoint);
pub fn input_hand_source(hand: Handed) -> HandSource;
pub fn input_controller(hand: Handed) -> *const Controller;
pub fn input_controller_menu() -> BtnState;
pub fn input_controller_model_set(hand: Handed, model: ModelT);
pub fn input_controller_model_get(hand: Handed) -> ModelT;
pub fn input_head() -> Pose;
pub fn input_eyes() -> Pose;
pub fn input_eyes_tracked() -> BtnState;
pub fn input_mouse() -> *const Mouse;
pub fn input_key(key: Key) -> BtnState;
pub fn input_key_inject_press(key: Key);
pub fn input_key_inject_release(key: Key);
pub fn input_text_consume() -> u32;
pub fn input_text_reset();
pub fn input_text_inject_char(character: u32);
pub fn input_hand_visible(hand: Handed, visible: Bool32T);
pub fn input_hand_material(hand: Handed, material: MaterialT);
pub fn input_get_finger_glow() -> Bool32T;
pub fn input_set_finger_glow(visible: Bool32T);
pub fn input_hand_sim_pose_add(
in_arr_palm_relative_hand_joints_25: *const Pose,
button1: ControllerKey,
and_button2: ControllerKey,
or_hotkey1: Key,
and_hotkey2: Key,
) -> HandSimId;
pub fn input_hand_sim_pose_remove(id: HandSimId);
pub fn input_hand_sim_pose_clear();
#[deprecated(since = "0.4.0", note = "Not working anymore")]
pub fn input_subscribe(
source: InputSource,
input_event: BtnState,
input_event_callback: Option<
unsafe extern "C" fn(source: InputSource, input_event: BtnState, in_pointer: *const Pointer),
>,
);
#[deprecated(since = "0.4.0", note = "Not working anymore")]
pub fn input_unsubscribe(
source: InputSource,
input_event: BtnState,
input_event_callback: Option<
unsafe extern "C" fn(source: InputSource, input_event: BtnState, in_pointer: *const Pointer),
>,
);
#[deprecated(since = "0.4.0", note = "Not working anymore")]
pub fn input_fire_event(source: InputSource, input_event: BtnState, pointer: *const Pointer);
}
impl Input {
pub fn set_controller_model(handed: Handed, model: Option<&Model>) {
match model {
Some(model) => unsafe { input_controller_model_set(handed, model.0.as_ptr()) },
None => unsafe { input_controller_model_set(handed, null_mut()) },
}
}
pub fn controller(handed: Handed) -> Controller {
unsafe { *input_controller(handed) }
}
#[deprecated(since = "0.4.0", note = "Not working anymore")]
#[allow(deprecated)]
pub fn fire_event(event_source: InputSource, event_types: BtnState, pointer: &Pointer) {
unsafe { input_fire_event(event_source, event_types, pointer) };
}
pub fn hand(handed: Handed) -> Hand {
unsafe { *input_hand(handed) }
}
pub fn hand_clear_override(hand: Handed) {
unsafe { input_hand_override(hand, null()) };
}
pub fn hand_override(hand: Handed, joints: &[HandJoint]) {
unsafe { input_hand_override(hand, joints.as_ptr()) };
}
pub fn hand_material(hand: Handed, material: Option<Material>) {
match material {
Some(material) => unsafe { input_hand_material(hand, material.0.as_ptr()) },
None => unsafe { input_hand_material(hand, null_mut()) },
}
}
pub fn hand_sim_pose_add(
hand_joints_palm_relative_25: &[Pose],
button1: ControllerKey,
and_button2: ControllerKey,
or_hotkey1: Key,
and_hotkey2: Key,
) -> HandSimId {
unsafe {
input_hand_sim_pose_add(
hand_joints_palm_relative_25.as_ptr(),
button1,
and_button2,
or_hotkey1,
and_hotkey2,
)
}
}
pub fn hand_sim_pose_clear() {
unsafe { input_hand_sim_pose_clear() };
}
pub fn hand_sim_pose_remove(id: HandSimId) {
unsafe { input_hand_sim_pose_remove(id) };
}
pub fn hand_source(hand: Handed) -> HandSource {
unsafe { input_hand_source(hand) }
}
pub fn hand_visible(hand: Handed, visible: bool) {
unsafe { input_hand_visible(hand, visible as Bool32T) };
}
pub fn finger_glow(visible: bool) {
unsafe { input_set_finger_glow(visible as Bool32T) };
}
pub fn key(key: Key) -> BtnState {
unsafe { input_key(key) }
}
pub fn key_inject_press(key: Key) {
unsafe { input_key_inject_press(key) };
}
pub fn key_inject_release(key: Key) {
unsafe { input_key_inject_release(key) };
}
pub fn pointer(index: i32, filter: Option<InputSource>) -> Pointer {
let filter = filter.unwrap_or(InputSource::Any);
unsafe { input_pointer(index, filter) }
}
pub fn pointer_count(filter: Option<InputSource>) -> i32 {
let filter = filter.unwrap_or(InputSource::Any);
unsafe { input_pointer_count(filter) }
}
pub fn text_consume() -> Option<char> {
char::from_u32(unsafe { input_text_consume() })
}
pub fn text_reset() {
unsafe { input_text_reset() };
}
pub fn text_inject_char(character: char) {
unsafe { input_text_inject_char(character as u32) };
}
pub fn text_inject_chars(str: impl AsRef<str>) {
for character in str.as_ref().chars() {
unsafe { input_text_inject_char(character as u32) }
}
}
#[deprecated(since = "0.4.0", note = "Not working anymore")]
#[allow(deprecated)]
pub fn subscribe(
event_source: InputSource,
event_types: BtnState,
on_event: Option<unsafe extern "C" fn(source: InputSource, input_event: BtnState, in_pointer: *const Pointer)>,
) {
unsafe { input_subscribe(event_source, event_types, on_event) }
}
#[deprecated(since = "0.4.0", note = "Not working anymore")]
#[allow(deprecated)]
pub fn unsubscribe(
event_source: InputSource,
event_types: BtnState,
on_event: Option<unsafe extern "C" fn(source: InputSource, input_event: BtnState, in_pointer: *const Pointer)>,
) {
unsafe { input_unsubscribe(event_source, event_types, on_event) }
}
pub fn get_controller_model(handed: Handed) -> Model {
match NonNull::new(unsafe { input_controller_model_get(handed) }) {
Some(model) => Model(model),
None => Model::new(),
}
}
pub fn get_controller_menu_button() -> BtnState {
unsafe { input_controller_menu() }
}
pub fn get_eyes() -> Pose {
unsafe { input_eyes() }
}
pub fn get_eyes_tracked() -> BtnState {
unsafe { input_eyes_tracked() }
}
pub fn get_head() -> Pose {
unsafe { input_head() }
}
pub fn get_mouse() -> Mouse {
unsafe { *input_mouse() }
}
pub fn get_finger_glow() -> bool {
unsafe { input_get_finger_glow() != 0 }
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[repr(C)]
pub struct LinePoint {
pub pt: Vec3,
pub thickness: f32,
pub color: Color32,
}
impl LinePoint {
pub fn new(pt: impl Into<Vec3>, thickness: f32, color: Color32) -> Self {
Self { pt: pt.into(), thickness, color }
}
}
pub struct Lines;
unsafe extern "C" {
pub fn line_add(start: Vec3, end: Vec3, color_start: Color32, color_end: Color32, thickness: f32);
pub fn line_addv(start: LinePoint, end: LinePoint);
pub fn line_add_axis(pose: Pose, size: f32);
pub fn line_add_list(points: *const Vec3, count: i32, color: Color32, thickness: f32);
pub fn line_add_listv(in_arr_points: *const LinePoint, count: i32);
}
impl Lines {
pub fn add<V: Into<Vec3>>(
_token: &MainThreadToken,
start: V,
end: V,
color_start: Color32,
color_end: Option<Color32>,
thickness: f32,
) {
let color_end = color_end.unwrap_or(color_start);
unsafe { line_add(start.into(), end.into(), color_start, color_end, thickness) }
}
pub fn add_ray<R: Into<Ray>>(
_token: &MainThreadToken,
ray: R,
length: f32,
color_start: Color32,
color_end: Option<Color32>,
thickness: f32,
) {
let color_end = color_end.unwrap_or(color_start);
let ray: Ray = ray.into();
unsafe { line_add(ray.position, ray.get_at(length), color_start, color_end, thickness) }
}
pub fn add_list(_token: &MainThreadToken, points: &[LinePoint]) {
unsafe { line_add_listv(points.as_ptr(), points.len() as i32) }
}
pub fn add_axis<P: Into<Pose>>(token: &MainThreadToken, at_pose: P, size: Option<f32>, thickness: Option<f32>) {
let at_pose: Pose = at_pose.into();
let size = size.unwrap_or(0.01);
match thickness {
Some(thickness) => {
Self::add(
token,
at_pose.position,
at_pose.orientation.mul_vec3(at_pose.position + Vec3::X) * size,
Color32::new(255, 0, 0, 255),
None,
thickness,
);
Self::add(
token,
at_pose.position,
at_pose.orientation.mul_vec3(at_pose.position + Vec3::Y) * size,
Color32::new(0, 255, 0, 255),
None,
thickness,
);
Self::add(
token,
at_pose.position,
at_pose.orientation.mul_vec3(at_pose.position + Vec3::Z) * size,
Color32::new(0, 0, 255, 255),
None,
thickness,
);
Self::add(
token,
at_pose.position,
at_pose.orientation.mul_vec3(at_pose.position + Vec3::FORWARD) * size * 0.5,
Color32::new(255, 255, 255, 255),
None,
thickness,
)
}
None => unsafe { line_add_axis(at_pose, size) },
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum LogColors {
Ansi = 0,
None = 1,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum LogLevel {
None = 0,
Diagnostic = 1,
Inform = 2,
Warning = 3,
Error = 4,
}
#[derive(Debug, Clone)]
pub struct LogItem {
pub level: LogLevel,
pub text: String,
pub count: i32,
}
pub struct Log;
unsafe extern "C" {
pub fn log_diag(text: *const c_char);
pub fn log_info(text: *const c_char);
pub fn log_warn(text: *const c_char);
pub fn log_err(text: *const c_char);
pub fn log_write(level: LogLevel, text: *const c_char);
pub fn log_set_filter(level: LogLevel);
pub fn log_set_colors(colors: LogColors);
pub fn log_subscribe(
log_callback: Option<unsafe extern "C" fn(context: *mut c_void, level: LogLevel, text: *const c_char)>,
context: *mut c_void,
);
pub fn log_unsubscribe(
log_callback: Option<unsafe extern "C" fn(context: *mut c_void, level: LogLevel, text: *const c_char)>,
context: *mut c_void,
);
}
unsafe extern "C" fn log_trampoline<'a, F: FnMut(LogLevel, &str) + 'a>(
context: *mut c_void,
log_level: LogLevel,
text: *const c_char,
) {
let closure = unsafe { &mut *(context as *mut &mut F) };
let c_str = unsafe { CStr::from_ptr(text).to_str().unwrap().trim_end() };
closure(log_level, c_str)
}
impl Log {
pub fn filter(filter: LogLevel) {
unsafe { log_set_filter(filter) }
}
pub fn colors(colors: LogColors) {
unsafe { log_set_colors(colors) }
}
pub fn err<S: AsRef<str>>(text: S) {
let c_str = CString::new(text.as_ref()).unwrap();
unsafe { log_err(c_str.as_ptr()) }
}
pub fn info<S: AsRef<str>>(text: S) {
let c_str = CString::new(text.as_ref()).unwrap();
unsafe { log_info(c_str.as_ptr()) }
}
pub fn warn<S: AsRef<str>>(text: S) {
let c_str = CString::new(text.as_ref()).unwrap();
unsafe { log_warn(c_str.as_ptr()) }
}
pub fn diag<S: AsRef<str>>(text: S) {
let c_str = CString::new(text.as_ref()).unwrap();
unsafe { log_diag(c_str.as_ptr()) }
}
pub fn write<S: AsRef<str>>(level: LogLevel, text: S) {
let c_str = CString::new(text.as_ref()).unwrap();
unsafe { log_write(level, c_str.as_ptr()) }
}
pub fn subscribe<'a, F: FnMut(LogLevel, &str) + 'a>(mut on_log: F) {
let mut closure = &mut on_log;
unsafe { log_subscribe(Some(log_trampoline::<F>), &mut closure as *mut _ as *mut c_void) }
}
pub fn unsubscribe<'a, F: FnMut(LogLevel, &str) + 'a>(mut on_log: F) {
let mut closure = &mut on_log;
unsafe { log_unsubscribe(Some(log_trampoline::<F>), &mut closure as *mut _ as *mut c_void) }
}
}
#[repr(C)]
#[derive(Debug, PartialEq)]
pub struct Microphone {
sound: Sound,
}
unsafe extern "C" {
pub fn mic_get_stream() -> SoundT;
pub fn mic_is_recording() -> Bool32T;
pub fn mic_device_count() -> i32;
pub fn mic_device_name(index: i32) -> *const c_char;
pub fn mic_start(device_name: *const c_char) -> Bool32T;
pub fn mic_stop();
}
impl Microphone {
pub fn sound() -> Result<Sound, StereoKitError> {
Ok(Sound(
NonNull::new(unsafe { mic_get_stream() })
.ok_or(StereoKitError::SoundCreate("microphone stream".to_string()))?,
))
}
pub fn is_recording() -> bool {
unsafe { mic_is_recording() != 0 }
}
pub fn get_devices() -> Vec<String> {
let mut devices = Vec::new();
for iter in 0..unsafe { mic_device_count() } {
let device_name = unsafe { CStr::from_ptr(mic_device_name(iter)) }.to_str().unwrap().to_string();
devices.push(device_name);
}
devices
}
pub fn start(device_name: Option<String>) -> bool {
if let Some(device_name) = device_name
&& !device_name.is_empty()
{
let cstr = CString::new(device_name).unwrap();
return unsafe { mic_start(cstr.as_ptr() as *const c_char) != 0 };
}
unsafe { mic_start(null_mut() as *const c_char) != 0 }
}
pub fn stop() {
unsafe { mic_stop() }
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum RenderClear {
None = 0,
Color = 1,
Depth = 2,
All = 3,
}
bitflags::bitflags! {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct RenderLayer: u32 {
const Layer0 = 1 << 0;
const Layer1 = 1 << 1;
const Layer2 = 1 << 2;
const Layer3 = 1 << 3;
const Layer4 = 1 << 4;
const Layer5 = 1 << 5;
const Layer6 = 1 << 6;
const Layer7 = 1 << 7;
const Layer8 = 1 << 8;
const Layer9 = 1 << 9;
const VFX = 10;
const FirstPerson = 1 << 11;
const ThirdPerson = 1 << 12;
const All = 0xFFFF;
const AllRegular = Self::Layer0.bits() | Self::Layer1.bits() | Self::Layer2.bits() | Self::Layer3.bits() | Self::Layer4.bits() | Self::Layer5.bits() | Self::Layer6.bits() | Self::Layer7.bits() | Self::Layer8.bits() | Self::Layer9.bits();
const AllFirstPerson = Self::All.bits() & !Self::ThirdPerson.bits();
const AllThirdPerson = Self::All.bits() & !Self::FirstPerson.bits();
}
}
impl Default for RenderLayer {
fn default() -> Self {
RenderLayer::All
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum Projection {
Perspective = 0,
Orthographic = 1,
}
pub struct Renderer;
unsafe extern "C" {
pub fn render_set_clip(near_plane: f32, far_plane: f32);
pub fn render_get_clip(out_near_plane: *mut f32, out_far_plane: *mut f32);
pub fn render_set_fov(vertical_field_of_view_degrees: f32);
pub fn render_get_fov() -> f32;
pub fn render_set_ortho_clip(near_plane: f32, far_plane: f32);
pub fn render_set_ortho_size(viewport_height_meters: f32);
pub fn render_get_ortho_size() -> f32;
pub fn render_set_projection(proj: Projection);
pub fn render_get_projection() -> Projection;
pub fn render_get_cam_root() -> Matrix;
pub fn render_set_cam_root(cam_root: *const Matrix);
pub fn render_set_skytex(sky_texture: TexT);
pub fn render_get_skytex() -> TexT;
pub fn render_set_skymaterial(sky_material: MaterialT);
pub fn render_get_skymaterial() -> MaterialT;
pub fn render_set_skylight(light_info: *const SphericalHarmonics);
pub fn render_get_skylight() -> SphericalHarmonics;
pub fn render_set_filter(layer_filter: RenderLayer);
pub fn render_get_filter() -> RenderLayer;
pub fn render_set_scaling(display_tex_scale: f32);
pub fn render_get_scaling() -> f32;
pub fn render_set_viewport_scaling(viewport_rect_scale: f32);
pub fn render_get_viewport_scaling() -> f32;
pub fn render_set_multisample(display_tex_multisample: i32);
pub fn render_get_multisample() -> i32;
pub fn render_override_capture_filter(use_override_filter: Bool32T, layer_filter: RenderLayer);
pub fn render_get_capture_filter() -> RenderLayer;
pub fn render_has_capture_filter() -> Bool32T;
pub fn render_set_clear_color(color_gamma: Color128);
pub fn render_get_clear_color() -> Color128;
pub fn render_enable_skytex(show_sky: Bool32T);
pub fn render_enabled_skytex() -> Bool32T;
pub fn render_global_texture(register_slot: i32, texture: TexT);
pub fn render_global_buffer(register_slot: i32, buffer: MaterialBufferT);
pub fn render_add_mesh(
mesh: MeshT,
material: MaterialT,
transform: *const Matrix,
color_linear: Color128,
layer: RenderLayer,
);
pub fn render_add_model(model: ModelT, transform: *const Matrix, color_linear: Color128, layer: RenderLayer);
pub fn render_add_model_mat(
model: ModelT,
material_override: MaterialT,
transform: *const Matrix,
color_linear: Color128,
layer: RenderLayer,
);
pub fn render_blit(to_rendertarget: TexT, material: MaterialT);
pub fn render_screenshot(
file_utf8: *const c_char,
file_quality_100: i32,
viewpoint: Pose,
width: i32,
height: i32,
field_of_view_degrees: f32,
);
pub fn render_screenshot_capture(
render_on_screenshot_callback: ::std::option::Option<
unsafe extern "C" fn(color_buffer: *mut Color32, width: i32, height: i32, context: *mut c_void),
>,
viewpoint: Pose,
width: i32,
height: i32,
field_of_view_degrees: f32,
tex_format: TexFormat,
context: *mut c_void,
);
pub fn render_screenshot_viewpoint(
render_on_screenshot_callback: ::std::option::Option<
unsafe extern "C" fn(color_buffer: *mut Color32, width: i32, height: i32, context: *mut c_void),
>,
camera: Matrix,
projection: Matrix,
width: i32,
height: i32,
layer_filter: RenderLayer,
clear: RenderClear,
viewport: Rect,
tex_format: TexFormat,
context: *mut c_void,
);
pub fn render_to(
to_rendertarget: TexT,
to_target_index: i32,
camera: *const Matrix,
projection: *const Matrix,
layer_filter: RenderLayer,
material_variant: i32,
clear: RenderClear,
viewport: Rect,
);
pub fn render_MaterialTo(
to_rendertarget: TexT,
override_material: MaterialT,
camera: *const Matrix,
projection: *const Matrix,
layer_filter: RenderLayer,
clear: RenderClear,
viewport: Rect,
);
pub fn render_get_device(device: *mut *mut c_void, context: *mut *mut c_void);
}
unsafe extern "C" fn sc_capture_trampoline<F: FnMut(&[Color32], usize, usize)>(
color_buffer: *mut Color32,
width: i32,
height: i32,
context: *mut c_void,
) {
let closure = unsafe { &mut *(context as *mut &mut F) };
closure(
unsafe { std::slice::from_raw_parts(color_buffer, (width * height) as usize) },
width as usize,
height as usize,
)
}
impl Renderer {
pub fn camera_root(transform: impl Into<Matrix>) {
unsafe { render_set_cam_root(&transform.into()) }
}
pub fn clear_color(color_gamma: impl Into<Color128>) {
unsafe { render_set_clear_color(color_gamma.into()) }
}
pub fn enable_sky(enable: bool) {
unsafe { render_enable_skytex(enable as Bool32T) }
}
pub fn layer_filter(filter: RenderLayer) {
unsafe { render_set_filter(filter) }
}
pub fn multisample(level: i32) {
unsafe { render_set_multisample(level) }
}
pub fn projection(projection: Projection) {
unsafe { render_set_projection(projection) }
}
pub fn scaling(scaling: f32) {
unsafe { render_set_scaling(scaling) }
}
pub fn viewport_scaling(scaling: f32) {
unsafe { render_set_viewport_scaling(scaling) }
}
pub fn sky_light(light_info: SphericalHarmonics) {
unsafe { render_set_skylight(&light_info) }
}
pub fn sky_tex(tex: impl AsRef<Tex>) {
unsafe { render_set_skytex(tex.as_ref().0.as_ptr()) }
}
pub fn sky_material(material: impl AsRef<Material>) {
unsafe { render_set_skymaterial(material.as_ref().0.as_ptr()) }
}
pub fn add_mesh(
_token: &MainThreadToken,
mesh: impl AsRef<Mesh>,
material: impl AsRef<Material>,
transform: impl Into<Matrix>,
color: Option<Color128>,
layer: Option<RenderLayer>,
) {
let color = color.unwrap_or(Color128::WHITE);
let layer = layer.unwrap_or(RenderLayer::Layer0);
unsafe {
render_add_mesh(mesh.as_ref().0.as_ptr(), material.as_ref().0.as_ptr(), &transform.into(), color, layer)
}
}
pub fn add_model(
_token: &MainThreadToken,
model: impl AsRef<Model>,
transform: impl Into<Matrix>,
color: Option<Color128>,
layer: Option<RenderLayer>,
) {
let color = color.unwrap_or(Color128::WHITE);
let layer = layer.unwrap_or(RenderLayer::Layer0);
unsafe { render_add_model(model.as_ref().0.as_ptr(), &transform.into(), color, layer) }
}
pub fn blit(to_render_target: impl AsRef<Tex>, material: impl AsRef<Material>) {
unsafe { render_blit(to_render_target.as_ref().0.as_ptr(), material.as_ref().0.as_ptr()) }
}
pub fn override_capture_filter(use_override_filter: bool, override_filter: RenderLayer) {
unsafe { render_override_capture_filter(use_override_filter as Bool32T, override_filter) }
}
#[allow(clippy::too_many_arguments)]
pub fn render_to<M: Into<Matrix>>(
_token: &MainThreadToken,
to_render_target: impl AsRef<Tex>,
to_target_index: Option<i32>,
camera: M,
projection: M,
layer_filter: Option<RenderLayer>,
material_variant: Option<i32>,
clear: Option<RenderClear>,
viewport: Option<Rect>,
) {
let to_target_index = to_target_index.unwrap_or(0);
let layer_filter = layer_filter.unwrap_or(RenderLayer::All);
let material_variant = material_variant.unwrap_or(0);
let clear = clear.unwrap_or(RenderClear::All);
let viewport = viewport.unwrap_or_default();
unsafe {
render_to(
to_render_target.as_ref().0.as_ptr(),
to_target_index,
&camera.into(),
&projection.into(),
layer_filter,
material_variant,
clear,
viewport,
)
}
}
pub fn set_global_texture(_token: &MainThreadToken, texture_register: i32, tex: Option<&Tex>) {
if let Some(tex) = tex {
unsafe { render_global_texture(texture_register, tex.0.as_ptr()) }
} else {
unsafe { render_global_texture(texture_register, null_mut()) }
}
}
pub fn set_global_buffer<T>(buffer_register: i32, buffer: &MaterialBuffer<T>) {
unsafe {
render_global_buffer(buffer_register, buffer.as_ref().as_ptr());
}
}
pub fn unset_global_buffer(buffer_register: i32) {
unsafe { render_global_buffer(buffer_register, std::ptr::null_mut()) }
}
pub fn screenshot(
_token: &MainThreadToken,
filename: impl AsRef<Path>,
file_quality: i32,
viewpoint: Pose,
width: i32,
height: i32,
field_of_view: Option<f32>,
) {
let path = filename.as_ref();
let c_str = CString::new(path.to_str().unwrap_or("!!!path.to_str error!!!").to_owned()).unwrap();
let field_of_view = field_of_view.unwrap_or(90.0);
unsafe { render_screenshot(c_str.as_ptr(), file_quality, viewpoint, width, height, field_of_view) }
}
pub fn screenshot_capture<F: FnMut(&[Color32], usize, usize)>(
_token: &MainThreadToken,
mut on_screenshot: F,
viewpoint: Pose,
width: i32,
height: i32,
field_of_view: Option<f32>,
tex_format: Option<TexFormat>,
) {
let field_of_view = field_of_view.unwrap_or(90.0);
let tex_format = tex_format.unwrap_or(TexFormat::RGBA32);
let mut closure = &mut on_screenshot;
unsafe {
render_screenshot_capture(
Some(sc_capture_trampoline::<F>),
viewpoint,
width,
height,
field_of_view,
tex_format,
&mut closure as *mut _ as *mut c_void,
)
}
}
#[allow(clippy::too_many_arguments)]
pub fn screenshot_viewpoint<M: Into<Matrix>, F: FnMut(&[Color32], usize, usize)>(
_token: &MainThreadToken,
mut on_screenshot: F,
camera: M,
projection: M,
width: i32,
height: i32,
render_layer: Option<RenderLayer>,
clear: Option<RenderClear>,
viewport: Option<Rect>,
tex_format: Option<TexFormat>,
) {
let tex_format = tex_format.unwrap_or(TexFormat::RGBA32);
let render_layer = render_layer.unwrap_or(RenderLayer::all());
let clear = clear.unwrap_or(RenderClear::All);
let viewport = viewport.unwrap_or_default();
let mut closure = &mut on_screenshot;
unsafe {
render_screenshot_viewpoint(
Some(sc_capture_trampoline::<F>),
camera.into(),
projection.into(),
width,
height,
render_layer,
clear,
viewport,
tex_format,
&mut closure as *mut _ as *mut c_void,
)
}
}
pub fn set_clip(near_plane: f32, far_plane: f32) {
unsafe { render_set_clip(near_plane, far_plane) }
}
pub fn set_fov(vertical_field_of_view: f32) {
unsafe { render_set_fov(vertical_field_of_view) }
}
pub fn set_ortho_clip(near_plane: f32, far_plane: f32) {
unsafe { render_set_ortho_clip(near_plane, far_plane) }
}
pub fn set_ortho_size(view_port_height_meters: f32) {
unsafe { render_set_ortho_size(view_port_height_meters) }
}
pub fn get_camera_root() -> Matrix {
unsafe { render_get_cam_root() }
}
pub fn get_clip() -> (f32, f32) {
let mut near_plane = 0.0;
let mut far_plane = 0.0;
unsafe { render_get_clip(&mut near_plane, &mut far_plane) }
(near_plane, far_plane)
}
pub fn get_fov() -> f32 {
unsafe { render_get_fov() }
}
pub fn get_ortho_size() -> f32 {
unsafe { render_get_ortho_size() }
}
pub fn get_capture_filter() -> RenderLayer {
unsafe { render_get_capture_filter() }
}
pub fn get_clear_color() -> Color128 {
unsafe { render_get_clear_color() }
}
pub fn get_enable_sky() -> bool {
unsafe { render_enabled_skytex() != 0 }
}
pub fn has_capture_filter() -> bool {
unsafe { render_has_capture_filter() != 0 }
}
pub fn get_layer_filter() -> RenderLayer {
unsafe { render_get_filter() }
}
pub fn get_multisample() -> i32 {
unsafe { render_get_multisample() }
}
pub fn get_projection() -> Projection {
unsafe { render_get_projection() }
}
pub fn get_scaling() -> f32 {
unsafe { render_get_scaling() }
}
pub fn get_viewport_scaling() -> f32 {
unsafe { render_get_viewport_scaling() }
}
pub fn get_sky_light() -> SphericalHarmonics {
unsafe { render_get_skylight() }
}
pub fn get_sky_tex() -> Tex {
let skytex_ptr = unsafe { render_get_skytex() };
if let Some(nonnull_ptr) = NonNull::new(skytex_ptr) {
Tex(nonnull_ptr)
} else {
Log::warn("render_get_skytex() returned null, returning error texture");
Tex::error()
}
}
pub fn get_sky_material() -> Material {
Material(NonNull::new(unsafe { render_get_skymaterial() }).unwrap())
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct TextStyle {
_id: u32,
}
unsafe extern "C" {
pub fn text_make_style(font: FontT, layout_height: f32, color_gamma: Color128) -> TextStyle;
pub fn text_make_style_shader(font: FontT, layout_height: f32, shader: ShaderT, color_gamma: Color128)
-> TextStyle;
pub fn text_make_style_mat(
font: FontT,
layout_height: f32,
material: MaterialT,
color_gamma: Color128,
) -> TextStyle;
pub fn text_style_get_line_height_pct(style: TextStyle) -> f32;
pub fn text_style_set_line_height_pct(style: TextStyle, height_percent: f32);
pub fn text_style_get_layout_height(style: TextStyle) -> f32;
pub fn text_style_set_layout_height(style: TextStyle, height_meters: f32);
pub fn text_style_get_total_height(style: TextStyle) -> f32;
pub fn text_style_set_total_height(style: TextStyle, height_meters: f32);
pub fn text_style_get_material(style: TextStyle) -> MaterialT;
pub fn text_style_get_ascender(style: TextStyle) -> f32;
pub fn text_style_get_descender(style: TextStyle) -> f32;
pub fn text_style_get_cap_height(style: TextStyle) -> f32;
pub fn text_style_get_baseline(style: TextStyle) -> f32;
}
impl Default for TextStyle {
fn default() -> Self {
Self { _id: 0 }
}
}
impl TextStyle {
pub fn from_font(font: impl AsRef<Font>, layout_height_meters: f32, color_gamma: impl Into<Color128>) -> Self {
unsafe { text_make_style(font.as_ref().0.as_ptr(), layout_height_meters, color_gamma.into()) }
}
pub fn from_font_and_shader(
font: impl AsRef<Font>,
layout_height_meters: f32,
shader: impl AsRef<Shader>,
color_gamma: impl Into<Color128>,
) -> Self {
unsafe {
text_make_style_shader(
font.as_ref().0.as_ptr(),
layout_height_meters,
shader.as_ref().0.as_ptr(),
color_gamma.into(),
)
}
}
pub fn from_font_and_material(
font: impl AsRef<Font>,
layout_height_meters: f32,
material: impl AsRef<Material>,
color_gamma: impl Into<Color128>,
) -> Self {
unsafe {
text_make_style_mat(
font.as_ref().0.as_ptr(),
layout_height_meters,
material.as_ref().0.as_ptr(),
color_gamma.into(),
)
}
}
#[deprecated(since = "0.40.0", note = "please use TextStyle::layout_height")]
pub fn char_height(&mut self, char_height: f32) {
unsafe { text_style_set_layout_height(*self, char_height) }
}
pub fn layout_height(&mut self, height_meters: f32) {
unsafe { text_style_set_layout_height(*self, height_meters) }
}
pub fn total_height(&mut self, height_meters: f32) {
unsafe { text_style_set_total_height(*self, height_meters) }
}
pub fn line_height_pct(&mut self, height_percent: f32) {
unsafe { text_style_set_line_height_pct(*self, height_percent) }
}
pub fn get_material(&self) -> Material {
Material(NonNull::new(unsafe { text_style_get_material(*self) }).unwrap())
}
#[deprecated(since = "0.40.0", note = "please use get_layout_height")]
pub fn get_char_height(&self) -> f32 {
unsafe { text_style_get_layout_height(*self) }
}
pub fn get_layout_height(&self) -> f32 {
unsafe { text_style_get_layout_height(*self) }
}
pub fn get_total_height(&self) -> f32 {
unsafe { text_style_get_total_height(*self) }
}
pub fn get_line_height_pct(&self) -> f32 {
unsafe { text_style_get_line_height_pct(*self) }
}
pub fn get_cap_height(&self) -> f32 {
unsafe { text_style_get_cap_height(*self) }
}
pub fn get_ascender(&self) -> f32 {
unsafe { text_style_get_ascender(*self) }
}
pub fn get_descender(&self) -> f32 {
unsafe { text_style_get_descender(*self) }
}
}
bitflags::bitflags! {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct Align: u32 {
const XLeft = 1 << 0;
const YTop = 1 << 1;
const XCenter = 1 << 2;
const YCenter = 1 << 3;
const XRight = 1 << 4;
const YBottom = 1 << 5;
const Center = Self::XCenter.bits() | Self::YCenter.bits();
const CenterLeft = Self::XLeft.bits() | Self::YCenter.bits();
const CenterRight = Self::XRight.bits() | Self::YCenter.bits();
const TopCenter = Self::XCenter.bits() | Self::YTop.bits();
const TopLeft = Self::XLeft.bits() | Self::YTop.bits();
const TopRight = Self::XRight.bits() | Self::YTop.bits();
const BottomCenter = Self::XCenter.bits() | Self::YBottom.bits();
const BottomLeft = Self::XLeft.bits() | Self::YBottom.bits();
const BottomRight = Self::XRight.bits() | Self::YBottom.bits();
}
}
bitflags::bitflags! {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct Pivot: u32 {
const XLeft = 1 << 0;
const YTop = 1 << 1;
const XCenter = 1 << 2;
const YCenter = 1 << 3;
const XRight = 1 << 4;
const YBottom = 1 << 5;
const Center = Self::XCenter.bits() | Self::YCenter.bits();
const CenterLeft = Self::XLeft.bits() | Self::YCenter.bits();
const CenterRight = Self::XRight.bits() | Self::YCenter.bits();
const TopCenter = Self::XCenter.bits() | Self::YTop.bits();
const TopLeft = Self::XLeft.bits() | Self::YTop.bits();
const TopRight = Self::XRight.bits() | Self::YTop.bits();
const BottomCenter = Self::XCenter.bits() | Self::YBottom.bits();
const BottomLeft = Self::XLeft.bits() | Self::YBottom.bits();
const BottomRight = Self::XRight.bits() | Self::YBottom.bits();
}
}
bitflags::bitflags! {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct TextFit: u32 {
const None = 0;
const Wrap = 1;
const Clip = 2;
const Squeeze = 4;
const Exact = 8;
const Overflow = 16;
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum TextContext {
Text = 0,
Number = 1,
Uri = 2,
Password = 3,
}
pub struct Text;
unsafe extern "C" {
pub fn text_add_at(
text_utf8: *const c_char,
transform: *const Matrix,
style: TextStyle,
position: Pivot,
align: Align,
off_x: f32,
off_y: f32,
off_z: f32,
vertex_tint_linear: Color128,
);
pub fn text_add_at_16(
text_utf16: *const c_ushort,
transform: *const Matrix,
style: TextStyle,
position: Pivot,
align: Align,
off_x: f32,
off_y: f32,
off_z: f32,
vertex_tint_linear: Color128,
);
pub fn text_add_in(
text_utf8: *const c_char,
transform: *const Matrix,
size: Vec2,
fit: TextFit,
style: TextStyle,
position: Pivot,
align: Align,
off_x: f32,
off_y: f32,
off_z: f32,
vertex_tint_linear: Color128,
) -> f32;
pub fn text_add_in_16(
text_utf16: *const c_ushort,
transform: *const Matrix,
size: Vec2,
fit: TextFit,
style: TextStyle,
position: Pivot,
align: Align,
off_x: f32,
off_y: f32,
off_z: f32,
vertex_tint_linear: Color128,
) -> f32;
pub fn text_size_layout(text_utf8: *const c_char, style: TextStyle) -> Vec2;
pub fn text_size_layout_constrained(text_utf8: *const c_char, style: TextStyle, max_width: f32) -> Vec2;
pub fn text_size_layout_16(text_utf16: *const c_ushort, style: TextStyle) -> Vec2;
pub fn text_size_layout_constrained_16(text_utf16: *const c_ushort, style: TextStyle, max_width: f32) -> Vec2;
pub fn text_size_render(layout_size: Vec2, style: TextStyle, y_offset: *mut f32) -> Vec2;
pub fn text_char_at(
text_utf8: *const c_char,
style: TextStyle,
char_index: i32,
opt_size: *mut Vec2,
fit: TextFit,
position: Pivot,
align: Align,
) -> Vec2;
pub fn text_char_at_16(
text_utf16: *const c_ushort,
style: TextStyle,
char_index: i32,
opt_size: *mut Vec2,
fit: TextFit,
position: Pivot,
align: Align,
) -> Vec2;
}
impl Text {
pub fn make_style(
font: impl AsRef<Font>,
layout_height_meters: f32,
color_gamma: impl Into<Color128>,
) -> TextStyle {
unsafe { text_make_style(font.as_ref().0.as_ptr(), layout_height_meters, color_gamma.into()) }
}
pub fn make_style_with_shader(
font: impl AsRef<Font>,
layout_height_meters: f32,
shader: impl AsRef<Shader>,
color_gamma: impl Into<Color128>,
) -> TextStyle {
unsafe {
text_make_style_shader(
font.as_ref().0.as_ptr(),
layout_height_meters,
shader.as_ref().0.as_ptr(),
color_gamma.into(),
)
}
}
pub fn make_style_with_material(
font: impl AsRef<Font>,
layout_height_meters: f32,
material: impl AsRef<Material>,
color_gamma: impl Into<Color128>,
) -> TextStyle {
unsafe {
text_make_style_mat(
font.as_ref().0.as_ptr(),
layout_height_meters,
material.as_ref().0.as_ptr(),
color_gamma.into(),
)
}
}
#[allow(clippy::too_many_arguments)]
pub fn add_at(
_token: &MainThreadToken,
text: impl AsRef<str>,
transform: impl Into<Matrix>,
text_style: Option<TextStyle>,
vertex_tint_linear: Option<Color128>,
position: Option<Pivot>,
align: Option<Align>,
off_x: Option<f32>,
off_y: Option<f32>,
off_z: Option<f32>,
) {
let c_str = CString::new(text.as_ref()).unwrap();
let style = text_style.unwrap_or_default();
let vertex_tint_linear = vertex_tint_linear.unwrap_or(Color128::WHITE);
let position = position.unwrap_or(Pivot::Center);
let align = align.unwrap_or(Align::Center);
let off_x = off_x.unwrap_or(0.0);
let off_y = off_y.unwrap_or(0.0);
let off_z = off_z.unwrap_or(0.0);
unsafe {
text_add_at(
c_str.as_ptr(),
&transform.into(),
style,
position,
align,
off_x,
off_y,
off_z,
vertex_tint_linear,
)
}
}
#[allow(clippy::too_many_arguments)]
pub fn add_in(
_token: &MainThreadToken,
text: impl AsRef<str>,
transform: impl Into<Matrix>,
size: impl Into<Vec2>,
fit: TextFit,
text_style: Option<TextStyle>,
vertex_tint_linear: Option<Color128>,
position: Option<Pivot>,
align: Option<Align>,
off_x: Option<f32>,
off_y: Option<f32>,
off_z: Option<f32>,
) -> f32 {
let c_str = CString::new(text.as_ref()).unwrap();
let style = text_style.unwrap_or_default();
let vertex_tint_linear = vertex_tint_linear.unwrap_or(Color128::WHITE);
let position = position.unwrap_or(Pivot::Center);
let align = align.unwrap_or(Align::Center);
let off_x = off_x.unwrap_or(0.0);
let off_y = off_y.unwrap_or(0.0);
let off_z = off_z.unwrap_or(0.0);
unsafe {
text_add_in(
c_str.as_ptr(),
&transform.into(),
size.into(),
fit,
style,
position,
align,
off_x,
off_y,
off_z,
vertex_tint_linear,
)
}
}
#[deprecated(since = "0.40.0", note = "please Text::use size_layout")]
pub fn size(text: impl AsRef<str>, text_style: Option<TextStyle>, max_width: Option<f32>) -> Vec2 {
let c_str = CString::new(text.as_ref()).unwrap();
let style = text_style.unwrap_or_default();
if let Some(max_width) = max_width {
unsafe { text_size_layout_constrained(c_str.as_ptr(), style, max_width) }
} else {
unsafe { text_size_layout(c_str.as_ptr(), style) }
}
}
pub fn size_layout(text: impl AsRef<str>, text_style: Option<TextStyle>, max_width: Option<f32>) -> Vec2 {
let c_str = CString::new(text.as_ref()).unwrap();
let style = text_style.unwrap_or_default();
if let Some(max_width) = max_width {
unsafe { text_size_layout_constrained(c_str.as_ptr(), style, max_width) }
} else {
unsafe { text_size_layout(c_str.as_ptr(), style) }
}
}
pub fn size_render(size_layout: impl Into<Vec2>, text_style: Option<TextStyle>, y_offset: &mut f32) -> Vec2 {
let style = text_style.unwrap_or_default();
unsafe { text_size_render(size_layout.into(), style, y_offset) }
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum WorldRefresh {
Area = 0,
Timer = 1,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum SpatialNodeType {
Static = 0,
Dynamic = 1,
}
pub struct World;
unsafe extern "C" {
pub fn world_has_bounds() -> Bool32T;
pub fn world_get_bounds_size() -> Vec2;
pub fn world_get_bounds_pose() -> Pose;
pub fn world_from_spatial_graph(spatial_graph_node_id: *mut u8, dynamic: SpatialNodeType, qpc_time: i64) -> Pose;
pub fn world_from_perception_anchor(perception_spatial_anchor: *mut c_void) -> Pose;
pub fn world_try_from_spatial_graph(
spatial_graph_node_id: *mut u8,
dynamic: SpatialNodeType,
qpc_time: i64,
out_pose: *mut Pose,
) -> Bool32T;
pub fn world_try_from_perception_anchor(perception_spatial_anchor: *mut c_void, out_pose: *mut Pose) -> Bool32T;
pub fn world_raycast(ray: Ray, out_intersection: *mut Ray) -> Bool32T;
pub fn world_set_occlusion_enabled(enabled: Bool32T);
pub fn world_get_occlusion_enabled() -> Bool32T;
pub fn world_set_raycast_enabled(enabled: Bool32T);
pub fn world_get_raycast_enabled() -> Bool32T;
pub fn world_set_occlusion_material(material: MaterialT);
pub fn world_get_occlusion_material() -> MaterialT;
pub fn world_set_refresh_type(refresh_type: WorldRefresh);
pub fn world_get_refresh_type() -> WorldRefresh;
pub fn world_set_refresh_radius(radius_meters: f32);
pub fn world_get_refresh_radius() -> f32;
pub fn world_set_refresh_interval(every_seconds: f32);
pub fn world_get_refresh_interval() -> f32;
pub fn world_get_tracked() -> BtnState;
pub fn world_get_origin_mode() -> OriginMode;
pub fn world_get_origin_offset() -> Pose;
pub fn world_set_origin_offset(offset: Pose);
}
impl World {
pub fn occlusion_enabled(enabled: bool) {
unsafe { world_set_occlusion_enabled(enabled as Bool32T) }
}
pub fn occlusion_material(material: impl AsRef<Material>) {
unsafe { world_set_occlusion_material(material.as_ref().0.as_ptr()) }
}
pub fn origin_offset(offset: impl Into<Pose>) {
unsafe { world_set_origin_offset(offset.into()) }
}
pub fn raycast_enabled(enabled: bool) {
unsafe { world_set_raycast_enabled(enabled as Bool32T) }
}
pub fn refresh_interval(speed: f32) {
unsafe { world_set_refresh_interval(speed) }
}
pub fn refresh_radius(distance: f32) {
unsafe { world_set_refresh_radius(distance) }
}
pub fn refresh_type(refresh_type: WorldRefresh) {
unsafe { world_set_refresh_type(refresh_type) }
}
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub fn from_perception_anchor(perception_spatial_anchor: *mut c_void) -> Option<Pose> {
let mut pose = Pose::IDENTITY;
if unsafe { world_try_from_perception_anchor(perception_spatial_anchor, &mut pose) != 0 } {
Some(pose)
} else {
None
}
}
pub fn from_spatial_node(
spatial_graph_node_id: impl AsRef<str>,
spatial_node_type: SpatialNodeType,
qpc_time: i64,
) -> Option<Pose> {
let c_str = CString::new(spatial_graph_node_id.as_ref()).unwrap();
let mut pose = Pose::IDENTITY;
if unsafe {
world_try_from_spatial_graph(c_str.as_ptr() as *mut u8, spatial_node_type, qpc_time, &mut pose) != 0
} {
Some(pose)
} else {
None
}
}
pub fn raycast(ray: impl Into<Ray>) -> Option<Ray> {
let mut intersection = Ray::default();
if unsafe { world_raycast(ray.into(), &mut intersection) != 0 } { Some(intersection) } else { None }
}
pub fn get_bounds_pose() -> Pose {
unsafe { world_get_bounds_pose() }
}
pub fn get_bounds_size() -> Vec2 {
unsafe { world_get_bounds_size() }
}
pub fn has_bounds() -> bool {
unsafe { world_has_bounds() != 0 }
}
pub fn get_occlusion_enabled() -> bool {
unsafe { world_get_occlusion_enabled() != 0 }
}
pub fn get_occlusion_material() -> Material {
Material(NonNull::new(unsafe { world_get_occlusion_material() }).unwrap())
}
pub fn get_origin_mode() -> OriginMode {
unsafe { world_get_origin_mode() }
}
pub fn get_tracked() -> BtnState {
unsafe { world_get_tracked() }
}
pub fn get_origin_offset() -> Pose {
unsafe { world_get_origin_offset() }
}
pub fn get_raycast_enabled() -> bool {
unsafe { world_get_raycast_enabled() != 0 }
}
pub fn get_refresh_interval() -> f32 {
unsafe { world_get_refresh_interval() }
}
pub fn get_refresh_radius() -> f32 {
unsafe { world_get_refresh_radius() }
}
pub fn get_refresh_type() -> WorldRefresh {
unsafe { world_get_refresh_type() }
}
}