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:
@@ -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))]
|
#[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);
|
pub struct Colour(pub u8, pub u8, pub u8);
|
||||||
|
|
||||||
impl Default for Colour {
|
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.
|
/// Used for Rainbow mode.
|
||||||
///
|
///
|
||||||
/// Enum corresponds to the required integer value
|
/// Enum corresponds to the required integer value
|
||||||
|
|||||||
+99
-14
@@ -2,17 +2,27 @@ use serde_derive::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use crate::{keys::Key, Colour, KeyColourArray, PerKeyRaw, Speed};
|
use crate::{keys::Key, Colour, KeyColourArray, PerKeyRaw, Speed};
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
|
||||||
pub struct PerKey {
|
pub struct PerKey {
|
||||||
pub key: Key,
|
pub key: Key,
|
||||||
pub action: ActionData,
|
action: ActionData,
|
||||||
/// The end resulting colour after stepping through effect
|
/// The end resulting colour after stepping through effect
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
colour: Colour,
|
colour: Colour,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
impl PerKey {
|
||||||
pub enum ActionData {
|
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),
|
Static(Colour),
|
||||||
Breathe {
|
Breathe {
|
||||||
/// The starting colour
|
/// The starting colour
|
||||||
@@ -23,13 +33,27 @@ pub enum ActionData {
|
|||||||
speed: Speed,
|
speed: Speed,
|
||||||
/// Temporary data to help keep state
|
/// Temporary data to help keep state
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
colour1_actual: Colour,
|
colour_actual: Colour,
|
||||||
/// Temporary data to help keep state
|
|
||||||
#[serde(skip)]
|
#[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 {
|
impl Default for ActionData {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::Static(Colour::default())
|
Self::Static(Colour::default())
|
||||||
@@ -68,16 +92,49 @@ impl Sequences {
|
|||||||
|
|
||||||
pub fn next_state(&mut self) {
|
pub fn next_state(&mut self) {
|
||||||
for effect in self.0.iter_mut() {
|
for effect in self.0.iter_mut() {
|
||||||
match effect.action {
|
match &mut effect.action {
|
||||||
ActionData::Static(c) => effect.colour = c,
|
ActionData::Static(c) => effect.colour = *c,
|
||||||
ActionData::Breathe {
|
ActionData::Breathe {
|
||||||
colour1,
|
colour1,
|
||||||
colour2,
|
colour2,
|
||||||
speed,
|
speed,
|
||||||
colour1_actual,
|
colour_actual,
|
||||||
colour2_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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{keys::Key, Colour, PerKey, Sequences};
|
use crate::{keys::Key, ActionData, Colour, PerKey, Sequences, Speed};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn single_key_next_state_then_create() {
|
fn single_key_next_state_then_create() {
|
||||||
let mut seq = Sequences::new();
|
let mut seq = Sequences::new();
|
||||||
seq.0.push(PerKey {
|
seq.0.push(PerKey {
|
||||||
key: Key::F,
|
key: Key::F,
|
||||||
action: crate::ActionData::Static(Colour(255, 127, 0)),
|
action: ActionData::Static(Colour(255, 127, 0)),
|
||||||
colour: Default::default(),
|
colour: Default::default(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -117,4 +174,32 @@ mod tests {
|
|||||||
assert_eq!(packets[5][34], 127);
|
assert_eq!(packets[5][34], 127);
|
||||||
assert_eq!(packets[5][35], 0);
|
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