# StickUp
> ๐ **Update: v0.2.0 is here!**
> StickUp now supports full per-frame state snapshots, binding resolution (`"joy0.axis1"`), and cleaner device management via the new `DeviceManager`.
> Built to scale with sim rigs, overlays, game engines, and beyond.
## Already passed 500 downloads in 24 hours โ thank you to everyone testing and sharing it
[](https://crates.io/crates/stickup)
[](https://crates.io/crates/stickup)
[](https://discord.gg/EKeBNYnaSh)
[](https://ko-fi.com/belegrades)
[](https://x.com/BelegradeOfRuin)
---
## ๐ Security Note
The name stickup was previously used in 2023 for a malicious crate which has since been removed from crates.io. (I wasn't aware of this at the time of publishing.)
This version โ authored by Belegrade Studio โ is a clean and fully rewritten project, unrelated to the original.
โ
No build.rs
โ
No network activity
โ
100% open and auditable
Transparency and trust matter. You're welcome to inspect the source or reach out directly
---
**StickUp** is a modular, high-performance input framework for Rust.
It supports both HID and virtual devices with precision, persistence, and clarity.
> Created by **Belegrade Studio** as part of the **CelerisTech** stack.
---
## โจ Features
- ๐ Plug-and-play device management via `DeviceManager`
- ๐ฎ Unified `Device` trait for axis + button input
- ๐ง Persistent device identity (hardware fingerprint)
- ๐งฐ Binding resolution like `"joy0.axis1"` โ `Option<f32>`
- ๐ Per-frame polling and snapshot state tracking
- ๐ง Hotplug-friendly and fully extendable
- ๐ Supports `hid` and `virtual` backends via features
- ๐ก Zero magic โ minimal, intentional design
---
## ๐ฆ Installation
```toml
stickup = { version = "0.2.0", features = ["hid", "virtual"] }
```
---
## ๐ Quick Start
```rust
use stickup::DeviceManager;
fn main() {
let mut input = DeviceManager::new();
input.snapshot(); // poll + build snapshot
if let Some(throttle) = input.get_axis("joy0.throttle") {
println!("Throttle: {:.2}", throttle);
}
if input.is_pressed("joy1.trigger") {
println!("Trigger is pressed!");
}
}
```
---
## ๐ Full Snapshot Example
```rust
let mut input = DeviceManager::new();
let state = input.snapshot();
for (id, device_state) in state.iter() {
println!("Device: {id}");
for (axis, value) in &device_state.axes {
println!(" Axis {axis}: {value:.2}");
}
for (button, pressed) in &device_state.buttons {
println!(" Button {button}: {}", if *pressed { "Pressed" } else { "Released" });
}
}
```
---
## ๐งฌ Device Identity
StickUp assigns a stable, persistent ID to each device:
```
vendor_id:product_id:serial_number
# Example: 044f:0402:ABCD1234
```
---
## ๐ Examples
Run any with:
```sh
cargo run --example <name>
```
- `poll` โ Print a full snapshot of all input state
- `virtual_demo` โ Feed input into a simulated virtual device
---
## ๐ ๏ธ Optional Features
| `hid` (default) | Enables HID device support via `hidapi` |
| `virtual` | Enables manually fed virtual devices |
---
## ๐งญ Philosophy
StickUp is about **presence, clarity, and persistence**.
It doesn't guess. It doesn't simulate. It reflects exactly what your device is doing โ no more, no less.
---
## ๐ License
This project is licensed under the **Pact of the Amaranth Rite**.
See [`LICENSE`](./LICENSE) for details.
### Third-Party Dependencies
StickUp uses the following libraries, each under permissive open source licenses:
- [`hidapi`](https://github.com/libusb/hidapi) โ MIT/Apache-2.0 (HID support)
- [`serde`](https://github.com/serde-rs/serde) โ MIT/Apache-2.0 (serialization)
- [`serde_json`](https://github.com/serde-rs/json) โ MIT/Apache-2.0 (layout/config IO)
- [`toml`](https://github.com/alexcrichton/toml-rs) โ MIT/Apache-2.0 (if config parsing used)
---
## ๐ฌ Connect
- โ๏ธ Email: [belegrade@belegrades.gg](mailto:belegrade@belegrades.gg)
- ๐ฌ Discord: [Join the Chat](https://discord.gg/EKeBNYnaSh)
- ๐ฎ Sim pilots & devs: Iโd love to hear how youโre using StickUp.