No description
- Rust 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| src | ||
| Cargo.toml | ||
| README.md | ||
Adaptive Trigger API
A standardized API for controlling DualSense adaptive triggers from Skyline plugins running in the Citron emulator.
Quick Start
Add the dependency to your plugin's Cargo.toml:
[dependencies]
adaptive_trigger_api = { git = "https://git.citron-emu.org/SylveonDeko/adaptive_trigger_api", branch = "main" }
# Or use a local path during development:
# adaptive_trigger_api = { path = "../adaptive_trigger_api" }
Use the API in your plugin:
use adaptive_trigger_api::{Trigger, set_feedback, set_vibration, set_off};
// Apply resistance to right trigger (like holding a heavy object)
set_feedback(Trigger::Right, 0.2, 0.8);
// Vibrate both triggers (warning/impact feedback)
set_vibration(Trigger::Both, 0.0, 0.7, 20.0);
// Reset trigger to normal
set_off(Trigger::Left);
API Reference
Triggers
pub enum Trigger {
Left, // ZL / L2
Right, // ZR / R2
Both, // Both triggers simultaneously
}
Functions
set_off(trigger: Trigger)
Reset trigger to normal (no effect).
set_feedback(trigger: Trigger, position: f32, strength: f32)
Continuous resistance starting at a position.
position: Where resistance starts (0.0 = beginning, 1.0 = fully pressed)strength: How strong the resistance is (0.0 = none, 1.0 = maximum)
Use cases: Holding objects, pressure, tension
set_weapon(trigger: Trigger, start: f32, end: f32, strength: f32)
Weapon-style effect with a click point.
start: Where resistance begins (0.0-1.0)end: Where resistance ends/clicks (0.0-1.0)strength: Effect intensity (0.0-1.0)
Use cases: Gun triggers, bow draws, button clicks
set_vibration(trigger: Trigger, position: f32, amplitude: f32, frequency: f32)
Vibration effect on the trigger.
position: Where vibration is felt (0.0-1.0)amplitude: Vibration intensity (0.0-1.0)frequency: Speed in Hz (typically 1-40)
Use cases: Warnings, impacts, engine rumble
Convenience Functions
reset_all() // Turn off both triggers
set_left_feedback(position, strength) // Left trigger only
set_right_feedback(position, strength) // Right trigger only
set_both_vibration(pos, amp, freq) // Both triggers
Example: Shield Pressure
use adaptive_trigger_api::{Trigger, set_feedback, set_vibration, set_off};
fn update_shield(shield_health: f32, max_shield: f32) {
if shield_health <= 0.0 {
// Shield broken - intense vibration
set_vibration(Trigger::Both, 0.0, 1.0, 40.0);
return;
}
// Calculate resistance (more as shield depletes)
let normalized = shield_health / max_shield;
let resistance = 1.0 - normalized;
// Apply to both triggers
set_feedback(Trigger::Both, 0.1, resistance);
// Warning vibration when critical
if normalized < 0.2 {
set_vibration(Trigger::Both, 0.3, 0.6, 25.0);
}
}
How It Works
The API maintains a shared memory region marked with "ADTR" that the Citron emulator scans for. When found, the emulator reads trigger states at 60Hz and applies them to connected DualSense controllers.
┌─────────────────────────────────────────────────┐
│ Your Plugin │
│ set_feedback(Trigger::Right, 0.2, 0.8) │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────┐ │
│ │ Shared Memory: "ADTR" + trigger states │ │
│ └───────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
│
▼ (emulator reads at 60Hz)
┌─────────────────────────────────────────────────┐
│ Citron Emulator → DualSense Controller │
└─────────────────────────────────────────────────┘
Requirements
- Citron emulator with DualSense support
- DualSense controller connected via USB or Bluetooth
- macOS (currently, other platforms coming soon)
License
GPL-2.0-or-later