No description
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-01-20 13:11:50 -05:00
src Initial commit: Controller Light API v1.0.0 2026-01-20 13:06:23 -05:00
Cargo.toml Update repository URL in Cargo.toml 2026-01-20 13:11:50 -05:00
README.md Update README with correct git repository URL 2026-01-20 13:09:26 -05:00

Controller Light API

A standardized API for controlling DualSense controller lights from Skyline plugins running in the Citron emulator.

Quick Start

Add the dependency to your plugin's Cargo.toml:

[dependencies]
controller_light_api = { git = "https://git.citron-emu.org/SylveonDeko/controller_light_api", branch = "main" }
# Or use a local path during development:
# controller_light_api = { path = "../controller_light_api" }

Use the API in your plugin:

use controller_light_api::{set_color, pulse, flash, set_off};

// Set solid red color
set_color(1.0, 0.0, 0.0);

// Pulse blue at 2Hz
pulse(0.0, 0.0, 1.0, 2.0);

// Flash yellow warning
flash(1.0, 1.0, 0.0, 4.0);

// Turn off (reverts to ambient LED)
set_off();

API Reference

Functions

set_off()

Turn off plugin-controlled light. Reverts to ambient LED if enabled.

set_color(r: f32, g: f32, b: f32)

Set a solid color.

  • r, g, b: Color components (0.0-1.0)

pulse(r: f32, g: f32, b: f32, frequency: f32)

Set a pulsing color effect (smooth fade in/out).

  • r, g, b: Color components (0.0-1.0)
  • frequency: Pulse frequency in Hz (typically 0.5-5.0)

flash(r: f32, g: f32, b: f32, frequency: f32)

Set a flashing color effect (on/off blink).

  • r, g, b: Color components (0.0-1.0)
  • frequency: Flash frequency in Hz (typically 1.0-10.0)

Convenience Functions

set_color_rgb(255, 128, 0)     // Set color using 0-255 range
set_color_hex(0xFF8000)        // Set color using hex value
pulse_rgb(255, 0, 0, 1.5)      // Pulse with 0-255 range
flash_rgb(255, 255, 0, 4.0)    // Flash with 0-255 range

Preset Colors & Effects

// Player colors
player_1()  // Red
player_2()  // Blue
player_3()  // Yellow
player_4()  // Green
player_5()  // Pink
player_6()  // Cyan
player_7()  // Orange
player_8()  // Purple

// Common effects
low_health()       // Red pulse at 1.5Hz
critical_health()  // Fast red flash at 4Hz
healing()          // Green pulse at 1Hz
damage()           // Fast red flash at 8Hz
power_up()         // Yellow flash at 6Hz

Example: Smash Ultimate

use controller_light_api::{set_color, pulse, flash, set_off, player_1};

// Set player color at match start
fn on_match_start(player_index: u8) {
    match player_index {
        0 => player_1(),
        1 => controller_light_api::player_2(),
        2 => controller_light_api::player_3(),
        3 => controller_light_api::player_4(),
        _ => set_off(),
    }
}

// Flash on taking damage
fn on_damage_taken(damage: f32) {
    if damage > 50.0 {
        flash(1.0, 0.0, 0.0, 10.0); // Heavy hit
    } else {
        flash(1.0, 0.5, 0.0, 6.0);  // Light hit
    }
}

// Pulse based on percentage
fn update_percentage(percent: f32) {
    if percent > 150.0 {
        pulse(1.0, 0.0, 0.0, 3.0);      // Critical - fast red pulse
    } else if percent > 100.0 {
        pulse(1.0, 0.3, 0.0, 1.5);      // High - orange pulse
    } else if percent > 50.0 {
        set_color(1.0, 0.8, 0.2);       // Medium - yellow
    } else {
        set_color(0.2, 1.0, 0.4);       // Low - green
    }
}

How It Works

The API maintains a shared memory region marked with "CLGT" that the Citron emulator scans for. When found, the emulator reads light state at 30Hz and applies it to connected DualSense controllers.

+-----------------------------------------------------+
|  Your Plugin                                        |
|  set_color(1.0, 0.0, 0.0)                           |
|                    |                                |
|                    v                                |
|  +-----------------------------------------------+  |
|  | Shared Memory: "CLGT" + light state           |  |
|  +-----------------------------------------------+  |
+-----------------------------------------------------+
                     |
                     v (emulator reads at 30Hz)
+-----------------------------------------------------+
|  Citron Emulator -> DualSense Controller Light      |
+-----------------------------------------------------+

Priority

When a plugin sets a light color (mode != Off), it overrides the ambient LED feature. When the plugin calls set_off(), the ambient LED resumes automatically (if enabled in settings).

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