Files
asusctl/rog-aura/src/sequencer.rs
2022-08-24 22:01:13 +12:00

121 lines
3.1 KiB
Rust

use serde_derive::{Deserialize, Serialize};
use crate::{keys::Key, Colour, KeyColourArray, PerKeyRaw, Speed};
#[derive(Debug, Default, Deserialize, Serialize)]
pub struct PerKey {
pub key: Key,
pub action: ActionData,
/// The end resulting colour after stepping through effect
#[serde(skip)]
colour: Colour,
}
#[derive(Debug, Deserialize, Serialize)]
pub enum ActionData {
Static(Colour),
Breathe {
/// The starting colour
colour1: Colour,
/// The secondary starting colour
colour2: Colour,
/// The speed at which to cycle between the colours
speed: Speed,
/// Temporary data to help keep state
#[serde(skip)]
colour1_actual: Colour,
/// Temporary data to help keep state
#[serde(skip)]
colour2_actual: Colour,
},
}
impl Default for ActionData {
fn default() -> Self {
Self::Static(Colour::default())
}
}
#[derive(Debug, Deserialize, Serialize, Default)]
pub struct Sequences(Vec<PerKey>);
impl Sequences {
#[inline]
pub fn new() -> Self {
Self(Vec::new())
}
#[inline]
pub fn push(&mut self, action: PerKey) {
self.0.push(action);
}
#[inline]
pub fn insert(&mut self, index: usize, action: PerKey) {
self.0.insert(index, action);
}
/// Remove an item at this position from the run buffer. If the `index` supplied
/// is not in range then `None` is returned, otherwise the `ActionData` at that location
/// is yeeted and returned.
#[inline]
pub fn remove_item(&mut self, index: usize) -> Option<PerKey> {
if index < self.0.len() {
return Some(self.0.remove(index));
}
None
}
pub fn next_state(&mut self) {
for effect in self.0.iter_mut() {
match effect.action {
ActionData::Static(c) => effect.colour = c,
ActionData::Breathe {
colour1,
colour2,
speed,
colour1_actual,
colour2_actual,
} => {
effect.colour = colour1;
}
}
}
}
pub fn create_packets(&self) -> PerKeyRaw {
let mut keys = KeyColourArray::new();
for effect in self.0.iter() {
if let Some(rgb) = keys.rgb_for_key(effect.key) {
rgb[0] = effect.colour.0;
rgb[1] = effect.colour.1;
rgb[2] = effect.colour.2;
}
}
keys.into()
}
}
#[cfg(test)]
mod tests {
use crate::{keys::Key, Colour, PerKey, Sequences};
#[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)),
colour: Default::default(),
});
seq.next_state();
let packets = seq.create_packets();
assert_eq!(packets[0][0], 0x5d);
assert_eq!(packets[5][33], 255);
assert_eq!(packets[5][34], 127);
assert_eq!(packets[5][35], 0);
}
}