mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
Basic fade in/out of gifs
This commit is contained in:
@@ -1,7 +1,18 @@
|
||||
use std::{
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
},
|
||||
thread::sleep,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
#[cfg(feature = "dbus")]
|
||||
use zvariant_derive::Type;
|
||||
|
||||
use crate::{error::AnimeError, AnimTime, AnimeGif};
|
||||
|
||||
/// The first 7 bytes of a USB packet are accounted for by `USB_PREFIX1` and `USB_PREFIX2`
|
||||
const BLOCK_START: usize = 7;
|
||||
/// *Not* inclusive, the byte before this is the final for each "pane"
|
||||
@@ -79,3 +90,93 @@ impl From<AnimeDataBuffer> for AnimePacketType {
|
||||
buffers
|
||||
}
|
||||
}
|
||||
|
||||
/// This runs the animations as a blocking loop by using the `callback` to write data
|
||||
pub fn run_animation(
|
||||
frames: &AnimeGif,
|
||||
do_early_return: Arc<AtomicBool>,
|
||||
callback: &dyn Fn(AnimeDataBuffer),
|
||||
) -> Result<(), AnimeError> {
|
||||
let mut count = 0;
|
||||
let start = Instant::now();
|
||||
|
||||
let mut timed = false;
|
||||
let mut run_time = frames.total_frame_time();
|
||||
println!("Real gif run length = {:?}", run_time);
|
||||
if let AnimTime::Fade(time) = frames.duration() {
|
||||
if let Some(middle) = time.show_for() {
|
||||
run_time = middle + time.total_fade_time();
|
||||
}
|
||||
timed = true;
|
||||
} else if let AnimTime::Time(time) = frames.duration() {
|
||||
run_time = time;
|
||||
timed = true;
|
||||
}
|
||||
|
||||
// After setting up all the data
|
||||
let mut fade_in = Duration::from_millis(0);
|
||||
let mut fade_out = Duration::from_millis(0);
|
||||
let mut fade_in_step = 0.0;
|
||||
let mut fade_in_accum = 0.0;
|
||||
let mut fade_out_step = 0.0;
|
||||
let mut fade_out_accum;
|
||||
if let AnimTime::Fade(time) = frames.duration() {
|
||||
fade_in = time.fade_in();
|
||||
fade_out = time.fade_out();
|
||||
fade_in_step = 1.0 / fade_in.as_secs_f32();
|
||||
fade_out_step = 1.0 / fade_out.as_secs_f32();
|
||||
|
||||
if time.total_fade_time() > run_time {
|
||||
println!("Total fade in/out time larger than gif run time. Setting fades to half");
|
||||
fade_in = run_time / 2;
|
||||
fade_in_step = 1.0 / (run_time / 2).as_secs_f32();
|
||||
|
||||
fade_out = run_time / 2;
|
||||
fade_out_step = 1.0 / (run_time / 2).as_secs_f32();
|
||||
}
|
||||
}
|
||||
|
||||
'animation: loop {
|
||||
for frame in frames.frames() {
|
||||
let frame_start = Instant::now();
|
||||
if do_early_return.load(Ordering::SeqCst) {
|
||||
return Ok(());
|
||||
}
|
||||
let mut output = frame.frame().clone();
|
||||
|
||||
if let AnimTime::Fade(_) = frames.duration() {
|
||||
if frame_start <= start + fade_in {
|
||||
for pixel in output.get_mut() {
|
||||
*pixel = (*pixel as f32 * fade_in_accum) as u8;
|
||||
}
|
||||
fade_in_accum = fade_in_step * (frame_start - start).as_secs_f32();
|
||||
} else if frame_start > (start + run_time) - fade_out {
|
||||
if run_time > (frame_start - start) {
|
||||
fade_out_accum =
|
||||
fade_out_step * (run_time - (frame_start - start)).as_secs_f32();
|
||||
} else {
|
||||
fade_out_accum = 0.0;
|
||||
}
|
||||
for pixel in output.get_mut() {
|
||||
*pixel = (*pixel as f32 * fade_out_accum) as u8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
callback(output);
|
||||
|
||||
if timed && Instant::now().duration_since(start) > run_time {
|
||||
break 'animation;
|
||||
}
|
||||
|
||||
sleep(frame.delay());
|
||||
}
|
||||
if let AnimTime::Count(times) = frames.duration() {
|
||||
count += 1;
|
||||
if count >= times {
|
||||
break 'animation;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user