use crate::{
maths::{Bool32T, Bounds, Pose, Vec3},
system::BtnState,
ui::IdHashT,
};
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum InteractorType {
Point = 0,
Line = 1,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum InteractorActivation {
State = 0,
Position = 1,
}
bitflags::bitflags! {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(C)]
pub struct InteractorEvent: u32 {
const Poke = 1 << 1;
const Grip = 1 << 2;
const Pinch = 1 << 3;
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum DefaultInteractors {
Default = 0,
None = 1,
}
unsafe extern "C" {
pub fn interactor_create(
shape_type: InteractorType,
events: InteractorEvent,
activation_type: InteractorActivation,
input_source_id: i32,
capsule_radius: f32,
secondary_motion_dimensions: i32,
) -> i32;
pub fn interactor_destroy(interactor: i32);
pub fn interactor_update(
interactor: i32,
capsule_start: Vec3,
capsule_end: Vec3,
motion: Pose,
motion_anchor: Vec3,
secondary_motion: Vec3,
active: BtnState,
tracked: BtnState,
);
pub fn interactor_set_min_distance(interactor: i32, min_distance: f32);
pub fn interactor_get_min_distance(interactor: i32) -> f32;
pub fn interactor_get_capsule_start(interactor: i32) -> Vec3;
pub fn interactor_get_capsule_end(interactor: i32) -> Vec3;
pub fn interactor_set_radius(interactor: i32, radius: f32);
pub fn interactor_get_radius(interactor: i32) -> f32;
pub fn interactor_get_tracked(interactor: i32) -> BtnState;
pub fn interactor_get_focused(interactor: i32) -> IdHashT;
pub fn interactor_get_active(interactor: i32) -> IdHashT;
pub fn interactor_get_focus_bounds(
interactor: i32,
out_pose_world: *mut Pose,
out_bounds_local: *mut Bounds,
out_at_local: *mut Vec3,
) -> Bool32T;
pub fn interactor_get_motion(interactor: i32) -> Pose;
pub fn interactor_count() -> i32;
pub fn interactor_get(index: i32) -> i32;
pub fn interaction_set_default_interactors(default_interactors: DefaultInteractors);
pub fn interaction_get_default_interactors() -> DefaultInteractors;
pub fn interaction_set_default_draw(draw_interactors: Bool32T);
pub fn interaction_get_default_draw() -> Bool32T;
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Interactor {
inst: i32,
}
impl Interactor {
pub fn create(
shape_type: InteractorType,
events: InteractorEvent,
activation_type: InteractorActivation,
input_source_id: i32,
capsule_radius: f32,
secondary_motion_dimensions: i32,
) -> Self {
let inst = unsafe {
interactor_create(
shape_type,
events,
activation_type,
input_source_id,
capsule_radius,
secondary_motion_dimensions,
)
};
Self { inst }
}
#[allow(clippy::too_many_arguments)]
pub fn update(
&self,
capsule_start: impl Into<Vec3>,
capsule_end: impl Into<Vec3>,
motion: impl Into<Pose>,
motion_anchor: impl Into<Vec3>,
secondary_motion: impl Into<Vec3>,
active: BtnState,
tracked: BtnState,
) {
unsafe {
interactor_update(
self.inst,
capsule_start.into(),
capsule_end.into(),
motion.into(),
motion_anchor.into(),
secondary_motion.into(),
active,
tracked,
);
}
}
pub fn destroy(&self) {
unsafe {
interactor_destroy(self.inst);
}
}
pub fn get_min_distance(&self) -> f32 {
unsafe { interactor_get_min_distance(self.inst) }
}
pub fn min_distance(&self, min_distance: f32) {
unsafe { interactor_set_min_distance(self.inst, min_distance) }
}
pub fn get_radius(&self) -> f32 {
unsafe { interactor_get_radius(self.inst) }
}
pub fn radius(&self, radius: f32) {
unsafe { interactor_set_radius(self.inst, radius) }
}
pub fn get_start(&self) -> Vec3 {
unsafe { interactor_get_capsule_start(self.inst) }
}
pub fn get_end(&self) -> Vec3 {
unsafe { interactor_get_capsule_end(self.inst) }
}
pub fn get_tracked(&self) -> BtnState {
unsafe { interactor_get_tracked(self.inst) }
}
pub fn get_focused(&self) -> IdHashT {
unsafe { interactor_get_focused(self.inst) }
}
pub fn get_active(&self) -> IdHashT {
unsafe { interactor_get_active(self.inst) }
}
pub fn get_motion(&self) -> Pose {
unsafe { interactor_get_motion(self.inst) }
}
pub fn try_get_focus_bounds(&self) -> Option<(Pose, Bounds, Vec3)> {
let mut pose_world = Pose::IDENTITY;
let mut bounds_local = Bounds::default();
let mut at_local = Vec3::ZERO;
let result =
unsafe { interactor_get_focus_bounds(self.inst, &mut pose_world, &mut bounds_local, &mut at_local) };
if result != 0 { Some((pose_world, bounds_local, at_local)) } else { None }
}
pub fn count() -> i32 {
unsafe { interactor_count() }
}
pub fn get(index: i32) -> Self {
let inst = unsafe { interactor_get(index) };
Self { inst }
}
}
pub struct Interaction;
impl Interaction {
pub fn get_default_interactors() -> DefaultInteractors {
unsafe { interaction_get_default_interactors() }
}
pub fn set_default_interactors(default_interactors: DefaultInteractors) {
unsafe { interaction_set_default_interactors(default_interactors) }
}
pub fn get_default_draw() -> bool {
unsafe { interaction_get_default_draw() != 0 }
}
pub fn set_default_draw(draw_interactors: bool) {
unsafe { interaction_set_default_draw(if draw_interactors { 1 } else { 0 }) }
}
}