mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Implement simple 'breathe' per-key effect
This commit is contained in:
52
asusctl/examples/aura-rgb-breathe.rs
Normal file
52
asusctl/examples/aura-rgb-breathe.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
//! Using a combination of key-colour array plus a key layout to generate outputs.
|
||||
|
||||
use rog_aura::{keys::Key, Colour, PerKey, Sequences, Speed};
|
||||
use rog_dbus::RogDbusClientBlocking;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let (client, _) = RogDbusClientBlocking::new().unwrap();
|
||||
|
||||
let mut seq = Sequences::new();
|
||||
let mut key = PerKey::new_breathe(Key::W, Colour(255, 127, 0), Colour(127, 0, 255), Speed::Med);
|
||||
|
||||
seq.push(key.clone());
|
||||
key.key = Key::A;
|
||||
seq.push(key.clone());
|
||||
key.key = Key::S;
|
||||
seq.push(key.clone());
|
||||
key.key = Key::D;
|
||||
seq.push(key.clone());
|
||||
|
||||
let mut key = PerKey::new_breathe(
|
||||
Key::Q,
|
||||
Colour(127, 127, 127),
|
||||
Colour(127, 255, 255),
|
||||
Speed::Low,
|
||||
);
|
||||
seq.push(key.clone());
|
||||
key.key = Key::E;
|
||||
seq.push(key.clone());
|
||||
|
||||
let mut key = PerKey::new_breathe(
|
||||
Key::N1,
|
||||
Colour(166, 127, 166),
|
||||
Colour(127, 155, 20),
|
||||
Speed::High,
|
||||
);
|
||||
key.key = Key::Tilde;
|
||||
seq.push(key.clone());
|
||||
key.key = Key::N2;
|
||||
seq.push(key.clone());
|
||||
key.key = Key::N3;
|
||||
seq.push(key.clone());
|
||||
key.key = Key::N4;
|
||||
seq.push(key.clone());
|
||||
|
||||
loop {
|
||||
seq.next_state();
|
||||
let packets = seq.create_packets();
|
||||
|
||||
client.proxies().led().per_key_raw(packets)?;
|
||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ impl From<u32> for LedBrightness {
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "dbus", derive(Type))]
|
||||
#[derive(Debug, Clone, PartialEq, Copy, Deserialize, Serialize)]
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Copy, Deserialize, Serialize)]
|
||||
pub struct Colour(pub u8, pub u8, pub u8);
|
||||
|
||||
impl Default for Colour {
|
||||
@@ -110,6 +110,15 @@ impl FromStr for Speed {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Speed> for u8 {
|
||||
fn from(s: Speed) -> u8 {
|
||||
match s {
|
||||
Speed::Low => 0,
|
||||
Speed::Med => 1,
|
||||
Speed::High => 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Used for Rainbow mode.
|
||||
///
|
||||
/// Enum corresponds to the required integer value
|
||||
|
||||
@@ -2,17 +2,27 @@ use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
use crate::{keys::Key, Colour, KeyColourArray, PerKeyRaw, Speed};
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
|
||||
pub struct PerKey {
|
||||
pub key: Key,
|
||||
pub action: ActionData,
|
||||
action: ActionData,
|
||||
/// The end resulting colour after stepping through effect
|
||||
#[serde(skip)]
|
||||
colour: Colour,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub enum ActionData {
|
||||
impl PerKey {
|
||||
pub fn new_breathe(key: Key, colour1: Colour, colour2: Colour, speed: Speed) -> Self {
|
||||
Self {
|
||||
key,
|
||||
action: ActionData::new_breathe(colour1, colour2, speed),
|
||||
colour: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub(super) enum ActionData {
|
||||
Static(Colour),
|
||||
Breathe {
|
||||
/// The starting colour
|
||||
@@ -23,13 +33,27 @@ pub enum ActionData {
|
||||
speed: Speed,
|
||||
/// Temporary data to help keep state
|
||||
#[serde(skip)]
|
||||
colour1_actual: Colour,
|
||||
/// Temporary data to help keep state
|
||||
colour_actual: Colour,
|
||||
#[serde(skip)]
|
||||
colour2_actual: Colour,
|
||||
count_flipped: bool,
|
||||
#[serde(skip)]
|
||||
use_colour1: bool,
|
||||
},
|
||||
}
|
||||
|
||||
impl ActionData {
|
||||
fn new_breathe(colour1: Colour, colour2: Colour, speed: Speed) -> Self {
|
||||
Self::Breathe {
|
||||
colour1,
|
||||
colour2,
|
||||
speed,
|
||||
colour_actual: Default::default(),
|
||||
count_flipped: false,
|
||||
use_colour1: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ActionData {
|
||||
fn default() -> Self {
|
||||
Self::Static(Colour::default())
|
||||
@@ -68,16 +92,49 @@ impl Sequences {
|
||||
|
||||
pub fn next_state(&mut self) {
|
||||
for effect in self.0.iter_mut() {
|
||||
match effect.action {
|
||||
ActionData::Static(c) => effect.colour = c,
|
||||
match &mut effect.action {
|
||||
ActionData::Static(c) => effect.colour = *c,
|
||||
ActionData::Breathe {
|
||||
colour1,
|
||||
colour2,
|
||||
speed,
|
||||
colour1_actual,
|
||||
colour2_actual,
|
||||
colour_actual,
|
||||
count_flipped: flipped,
|
||||
use_colour1,
|
||||
} => {
|
||||
effect.colour = colour1;
|
||||
let speed = 4 - <u8>::from(*speed);
|
||||
|
||||
let colour: &mut Colour;
|
||||
if *colour_actual == Colour(0, 0, 0) {
|
||||
*use_colour1 = !*use_colour1;
|
||||
}
|
||||
|
||||
if !*use_colour1 {
|
||||
colour = colour2;
|
||||
} else {
|
||||
colour = colour1;
|
||||
}
|
||||
|
||||
let r1_scale = colour.0 / speed / 2;
|
||||
let g1_scale = colour.1 / speed / 2;
|
||||
let b1_scale = colour.2 / speed / 2;
|
||||
|
||||
if *colour_actual == Colour(0, 0, 0) {
|
||||
*flipped = true;
|
||||
} else if colour_actual >= colour {
|
||||
*flipped = false;
|
||||
}
|
||||
|
||||
if !*flipped {
|
||||
colour_actual.0 = colour_actual.0.saturating_sub(r1_scale);
|
||||
colour_actual.1 = colour_actual.1.saturating_sub(g1_scale);
|
||||
colour_actual.2 = colour_actual.2.saturating_sub(b1_scale);
|
||||
} else {
|
||||
colour_actual.0 = colour_actual.0.saturating_add(r1_scale);
|
||||
colour_actual.1 = colour_actual.1.saturating_add(g1_scale);
|
||||
colour_actual.2 = colour_actual.2.saturating_add(b1_scale);
|
||||
}
|
||||
effect.colour = *colour_actual;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,14 +155,14 @@ impl Sequences {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{keys::Key, Colour, PerKey, Sequences};
|
||||
use crate::{keys::Key, ActionData, Colour, PerKey, Sequences, Speed};
|
||||
|
||||
#[test]
|
||||
fn single_key_next_state_then_create() {
|
||||
let mut seq = Sequences::new();
|
||||
seq.0.push(PerKey {
|
||||
key: Key::F,
|
||||
action: crate::ActionData::Static(Colour(255, 127, 0)),
|
||||
action: ActionData::Static(Colour(255, 127, 0)),
|
||||
colour: Default::default(),
|
||||
});
|
||||
|
||||
@@ -117,4 +174,32 @@ mod tests {
|
||||
assert_eq!(packets[5][34], 127);
|
||||
assert_eq!(packets[5][35], 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cycle_breathe() {
|
||||
let mut seq = Sequences::new();
|
||||
seq.0.push(PerKey {
|
||||
key: Key::F,
|
||||
action: ActionData::new_breathe(Colour(255, 127, 0), Colour(127, 0, 255), Speed::Med),
|
||||
colour: Default::default(),
|
||||
});
|
||||
|
||||
seq.next_state();
|
||||
let packets = seq.create_packets();
|
||||
|
||||
assert_eq!(packets[0][0], 0x5d);
|
||||
assert_eq!(packets[5][33], 124);
|
||||
assert_eq!(packets[5][34], 0);
|
||||
assert_eq!(packets[5][35], 0);
|
||||
|
||||
// dbg!(&packets[5][33..=35]);
|
||||
|
||||
seq.next_state();
|
||||
let packets = seq.create_packets();
|
||||
|
||||
assert_eq!(packets[0][0], 0x5d);
|
||||
assert_eq!(packets[5][33], 82);
|
||||
assert_eq!(packets[5][34], 0);
|
||||
assert_eq!(packets[5][35], 0);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user