anime: add zbus methods

This commit is contained in:
Luke D Jones
2021-04-10 14:21:22 +12:00
parent ece565de1c
commit e515741efa
28 changed files with 741 additions and 299 deletions

View File

@@ -1,5 +1,5 @@
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "zbus")]
#[cfg(feature = "z")]
use zvariant_derive::Type;
/// The first 7 bytes of a USB packet are accounted for by `USB_PREFIX1` and `USB_PREFIX2`
@@ -16,7 +16,7 @@ const USB_PREFIX2: [u8; 7] = [0x5e, 0xc0, 0x02, 0x74, 0x02, 0x73, 0x02];
/// The minimal serializable data that can be transferred over wire types.
/// Other data structures in `rog_anime` will convert to this.
#[cfg_attr(feature = "zbus", derive(Type))]
#[cfg_attr(feature = "z", derive(Type))]
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct AniMeDataBuffer(Vec<u8>);

View File

@@ -3,6 +3,9 @@ use png_pong::decode::Error as PngError;
use std::error::Error;
use std::fmt;
#[cfg(feature = "z")]
use zbus::fdo;
#[derive(Debug)]
pub enum AnimeError {
NoFrames,
@@ -12,6 +15,8 @@ pub enum AnimeError {
Format,
/// The input was incorrect size, expected size is `IncorrectSize(width, height)`
IncorrectSize(u32, u32),
#[cfg(feature = "z")]
Zbus(fdo::Error)
}
impl fmt::Display for AnimeError {
@@ -28,6 +33,8 @@ impl fmt::Display for AnimeError {
"The input image size is incorrect, expected {}x{}",
width, height
),
#[cfg(feature = "z")]
AnimeError::Zbus(e) => write!(f, "ZBUS error: {}", e),
}
}
}
@@ -51,3 +58,10 @@ impl From<DecodingError> for AnimeError {
AnimeError::Gif(err)
}
}
#[cfg(feature = "z")]
impl From<AnimeError> for fdo::Error {
fn from(err: AnimeError) -> Self {
fdo::Error::Failed(format!("{}", err))
}
}

View File

@@ -24,6 +24,7 @@ impl AniMeFrame {
#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
pub enum AnimTime {
/// Time in milliseconds for animation to run
Time(Duration),
Cycles(u32),
Infinite,
@@ -35,7 +36,6 @@ impl Default for AnimTime {
}
}
/// A gif animation. This is a collection of frames from the gif, and a duration
/// that the animation should be shown for.
#[derive(Debug, Clone, Deserialize, Serialize)]

View File

@@ -1,13 +1,44 @@
use std::{path::Path, time::Duration};
use std::{
path::{Path, PathBuf},
time::Duration,
};
use glam::Vec2;
use serde_derive::{Deserialize, Serialize};
use crate::{AniMeDataBuffer, AniMeGif, AniMeImage, AnimTime, error::AnimeError};
use crate::{error::AnimeError, AniMeDataBuffer, AniMeGif, AniMeImage, AnimTime};
#[derive(Debug, Clone, Deserialize, Serialize)]
pub enum AnimeAction {
/// Full gif sequence. Immutable.
AsusAnimation {
file: PathBuf,
time: AnimTime,
brightness: f32,
},
/// Basic image, can have properties changed
ImageAnimation {
file: PathBuf,
scale: f32,
angle: f32,
translation: Vec2,
time: AnimTime,
brightness: f32,
},
Image {
file: PathBuf,
scale: f32,
angle: f32,
translation: Vec2,
brightness: f32,
},
/// A pause to be used between sequences
Pause(Duration),
}
///
#[derive(Debug, Deserialize, Serialize)]
pub enum Action {
pub enum ActionData {
/// Full gif sequence. Immutable.
Animation(AniMeGif),
/// Basic image, can have properties changed and image updated via those properties
@@ -26,40 +57,92 @@ pub enum Action {
/// An optimised precomputed set of actions
#[derive(Debug, Deserialize, Serialize, Default)]
pub struct Sequences(Vec<Action>);
pub struct Sequences(Vec<ActionData>);
impl Sequences {
pub fn new() -> Self {
Self(Vec::new())
}
pub fn add_asus_gif(
pub fn insert(&mut self, index: usize, action: &AnimeAction) -> Result<(), AnimeError> {
match action {
AnimeAction::AsusAnimation {
file,
time: duration,
brightness,
} => self.insert_asus_gif(index, &file, *duration, *brightness)?,
AnimeAction::ImageAnimation {
file,
scale,
angle,
translation,
time: duration,
brightness,
} => self.insert_image_gif(
index,
&file,
*scale,
*angle,
*translation,
*duration,
*brightness,
)?,
AnimeAction::Image {
file,
scale,
angle,
translation,
brightness,
} => self.insert_png(index, &file, *scale, *angle, *translation, *brightness)?,
AnimeAction::Pause(duration) => self.insert_pause(index, *duration),
};
Ok(())
}
pub fn remove_item(&mut self, index: usize) -> Option<ActionData> {
if index < self.0.len() {
return Some(self.0.remove(index));
}
None
}
fn insert_asus_gif(
&mut self,
mut index: usize,
file: &Path,
duration: AnimTime,
brightness: f32,
) -> Result<(), AnimeError> {
if index > self.0.len() {
index = self.0.len() - 1;
}
let frames = AniMeGif::create_diagonal_gif(file, duration, brightness)?;
self.0.push(Action::Animation(frames));
self.0.insert(index, ActionData::Animation(frames));
Ok(())
}
pub fn add_png(
fn insert_png(
&mut self,
mut index: usize,
file: &Path,
scale: f32,
angle: f32,
translation: Vec2,
brightness: f32,
) -> Result<(), AnimeError> {
if index > self.0.len() {
index = self.0.len() - 1;
}
let image = AniMeImage::from_png(file, scale, angle, translation, brightness)?;
let data = <AniMeDataBuffer>::from(&image);
self.0.push(Action::Image(Box::new(data)));
self.0.insert(index, ActionData::Image(Box::new(data)));
Ok(())
}
pub fn add_image_gif(
#[allow(clippy::too_many_arguments)]
fn insert_image_gif(
&mut self,
mut index: usize,
file: &Path,
scale: f32,
angle: f32,
@@ -67,15 +150,20 @@ impl Sequences {
duration: AnimTime,
brightness: f32,
) -> Result<(), AnimeError> {
if index > self.0.len() {
index = self.0.len() - 1;
}
let frames =
AniMeGif::create_png_gif(file, scale, angle, translation, duration, brightness)?;
self.0.push(Action::Animation(frames));
self.0.insert(index, ActionData::Animation(frames));
Ok(())
}
pub fn add_pause(&mut self, duration: Duration) -> Result<(), AnimeError> {
self.0.push(Action::Pause(duration));
Ok(())
fn insert_pause(&mut self, mut index: usize, duration: Duration) {
if index > self.0.len() {
index = self.0.len() - 1;
}
self.0.insert(index, ActionData::Pause(duration));
}
pub fn iter(&self) -> ActionIterator {
@@ -92,9 +180,9 @@ pub struct ActionIterator<'a> {
}
impl<'a> Iterator for ActionIterator<'a> {
type Item = &'a Action;
type Item = &'a ActionData;
fn next(&mut self) -> Option<&'a Action> {
fn next(&mut self) -> Option<&'a ActionData> {
if self.next_idx == self.actions.0.len() {
self.next_idx = 0;
return None;