# LeapRS [![Github](https://img.shields.io/badge/github-plule%2Fleaprs-8da0cb?style=flat-square)](https://github.com/plule/leaprs) [![Crates.io](https://img.shields.io/crates/v/leaprs?style=flat-square)](https://crates.io/crates/leaprs) [![docs.rs](https://img.shields.io/docsrs/leaprs?style=flat-square)](https://docs.rs/leaprs) ![Crates.io](https://img.shields.io/crates/l/leaprs?style=flat-square) LeapRS is an unofficial safe wrapper for LeapC, the [Leap Motion C API](https://docs.ultraleap.com/tracking-api/). It uses the generated binding provided by [leap-sys](https://crates.io/crates/leap-sys). This is an API for accessing Leap Motion/Ultraleap hand tracking device. It works on Linux and Windows. ![leaprs](images/leaprs.png)

**Warning**: This library is not complete and not fully tested. Moreover, it includes unsafe
code to interact with the C API. It should be treated with caution in its
current state.

## Scope The goal of LeapRS is to cover entirely LeapC in a safe way. It is intended to be as close as possible to the original C library. As such, it's fairly low level and carries most of the difficulties of using LeapC. It is not intended to provide any full featured framework such as having a worker thread and provide an async API. It is intended to be usable to create such framework though. ### API Coverage The current coverage includes most of the necessary functions to interact with a Leap Motion device in a single or a multi device environment. The interpolation and distortion methods are not fully translated and not fully tested. The allocation API is not exposed. ## Setup Add `leaprs` to the current project: `cargo add leaprs` You also need to install the [LeapMotion Tracking Software](https://developer.leapmotion.com/tracking-software-download). This library was created for the version named `Geminy` (5.6.1). If you install this software in a custom path, you need to define the environment variable `LEAPSDK_LIB_PATH` (default: `C:\Program Files\Ultraleap\LeapSDK\lib\x64` on Windows and `/usr/share/doc/ultraleap-hand-tracking-service` on Linux). At runtime, the application requires the LeapC.dll file to be available. The easiest way to do it during development is to add its folder to the `PATH` environment variable. For distribution, refer to the SDK licensing. ## Quick start The main entrypoint is [Connection::create]. For most of the basic usage of hand tracking, you will have to use [Connection::poll] and retrieve the underlying event with [ConnectionMessage::event]. The various possible events are described in the [EventRef] enum, including [EventRef::Tracking] containing the hand positions. ```rust use leaprs::*; let mut c = Connection::create(ConnectionConfig::default()).unwrap(); c.open().unwrap(); for _ in 0..10 { if let Ok(msg) = c.poll(1000) { match msg.event() { EventRef::Tracking(e) => println!("{} hand(s)", e.hands().len()), _ => {} } } } ``` Most of the types in `leaprs` are wrappers with no data around the underlying `LeapC` structures. These wrappers expose both: - Handy methods for accessing the data, for example [TrackingEventRef::hands] lists the visible hands - Direct access to the underlying data via the `Deref` trait, for example [HandRef] gives direct access to [leap_sys::LEAP_HAND::confidence]: `hand_ref.confidence` When both members are available (`.hands` and `.hands()`), the function is the recommended one to get a safe wrapper. The field access can be useful to circumvent a `leaprs` limitation. ## `glam` and `nalgebra` Integration `leaprs` includes opt-in `glam` and `nalgebra` integrations. They are two popular linear algebra library. Both are commonly used, and these features can help integrating with ecosystem using these crates. `glam` is used by `Bevy`, and `nalgebra` is used by `Fyrox`. ### glam `cargo build --features glam` ```rust use leaprs::*; use glam::{Vec3, Quat}; let mut c = Connection::create(ConnectionConfig::default()).unwrap(); c.open().unwrap(); for _ in 0..10 { if let Ok(msg) = c.poll(1000) { match msg.event() { EventRef::Tracking(e) => { for hand in e.hands() { let position: Vec3 = hand.palm().position().into(); let orientation: Quat = hand.palm().orientation().into(); } }, _ => {} } } } ``` ### nalgebra `cargo build --features nalgebra` ```rust use leaprs::*; use nalgebra::{Vector3, UnitQuaternion}; let mut c = Connection::create(ConnectionConfig::default()).unwrap(); c.open().unwrap(); for _ in 0..10 { if let Ok(msg) = c.poll(1000) { match msg.event() { EventRef::Tracking(e) => { for hand in e.hands() { let position: Vector3 = hand.palm().position().into(); let orientation: UnitQuaternion = hand.palm().orientation().into(); } }, _ => {} } } } ``` ## Using with previous SDK versions Disabling the `geminy` feature enables building application for the previous SDK generation (Orion). In Cargo.toml: ```toml [dependencies = { version = "*", default-features = false }] ``` You also need to point the `LEAPSDK_LIB_PATH` to a SDK with the Orion version. ## License Licensed under either of Apache License, Version 2.0 or MIT license at your option. This license only covers the `leaprs` wrapper, and not the underlying `LeapC` library. ## Implementation The enum safety is provided through [num_enum](https://docs.rs/num_enum/latest/num_enum/). The bitflags are wrapped using [bitflags](https://docs.rs/bitflags/latest/bitflags/). Most struct are simple wrappers around their C counter-part. Most of the time, the C struct is the only member of the wrapper, except when external allocation is needed (when providing a pre-allocated array to LeapC). Accessors are then exposing all the functions and members associated with these structs in a consistent way. ## Tests The test require to have the Leap software up and running, and to have a device connected.