use haply::{
device_model::{
BubbleNavigationSettings,
BubbleCenterSettings,
Command,
CollisionDetectionSettings,
Inverse3Configure,
Linear3D,
NavigationConfigure,
SdfPrimitive,
TransformPatch,
},
http::InverseHttpClient,
HaplyDevice,
};
use std::io::Write;
use std::time::Duration;
use tokio::time::{ interval, sleep };
const USE_HTTP: bool = false;
const HTTP_BASE: &str = "http://localhost:10001";
const WS_URL: &str = "ws://localhost:10001/";
const SESSION: &str = ":-1";
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let mut device = HaplyDevice::new(HTTP_BASE, WS_URL).await?;
let http = InverseHttpClient::new(HTTP_BASE);
sleep(Duration::from_millis(300)).await;
let state = device.read_state().await?;
let inv = state.inverse3.first().ok_or("No Inverse3 device connected")?;
let id = inv.device_id.clone();
println!("Using Inverse3 device: {}", id);
let nav_config = NavigationConfigure {
mode: "bubble".to_string(),
bubble: Some(BubbleNavigationSettings {
center: Some(BubbleCenterSettings {
position: Some(Linear3D { x: 0.0, y: -0.05, z: 0.18 }),
relative: Some(false),
follow: Some(false),
speed: None,
}),
shape: Some(SdfPrimitive::Sphere { r: 0.05 }),
velocity_zone_width: Some(0.03),
max_velocity: Some(0.5),
spring_surface: Some(7.0),
damping_surface: Some(0.7),
collision_detection: Some(CollisionDetectionSettings {
enabled: Some(false),
force_threshold: Some(1.0),
inflate_ratio: Some(2.0),
exit_ratio: Some(0.7),
}),
..Default::default()
}),
};
if USE_HTTP {
println!("Configuring navigation via HTTP...");
http.set_navigation("inverse3", &id, Some(SESSION), &nav_config).await?;
} else {
println!("Configuring navigation via WS...");
device.configure_inverse3(
&id,
Inverse3Configure {
navigation: Some(nav_config),
..Default::default()
},
Some(true)
).await?;
}
println!("Navigation active -- streaming position (Ctrl+C to stop)");
let mut ticker = interval(Duration::from_millis(50));
let mut tick_count: u32 = 0;
loop {
ticker.tick().await;
tick_count += 1;
if tick_count % 10 == 0 {
device.send_force_full_render().await?;
} else {
device.send_command().await?;
}
let state = device.read_state().await?;
if let Some(inv) = state.inverse3.first() {
let cursor = inv.state.cursor_position.unwrap_or_default();
let ws_pos = inv.state.transform
.as_ref()
.map(|t| t.position)
.unwrap_or_default();
let nav_center = inv.state.navigation
.as_ref()
.and_then(|n| n.bubble.as_ref())
.and_then(|b| b.center);
let nav_mode = inv.status.navigation
.as_ref()
.and_then(|s| s.mode.as_deref())
.unwrap_or("off");
print!(
"\rCursor: ({:.4},{:.4},{:.4}) WS: ({:.4},{:.4},{:.4}) Nav: {:?} Mode: {} ",
cursor.x,
cursor.y,
cursor.z,
ws_pos.x,
ws_pos.y,
ws_pos.z,
nav_center,
nav_mode
);
std::io::stdout().flush().unwrap();
}
}
}