add basic scene selection

This commit is contained in:
Michael Sippel 2024-04-26 14:26:40 +02:00
parent 13d58a7ac5
commit 06ea05e112
Signed by: senvas
GPG key ID: F96CF119C34B64A6

View file

@ -7,7 +7,7 @@ use {
winit::event::{Event, WindowEvent}, winit::event::{Event, WindowEvent},
winit::event_loop::{ControlFlow, EventLoop}, winit::event_loop::{ControlFlow, EventLoop},
winit::window::WindowBuilder, winit::window::WindowBuilder,
prisma::{Rgb,Hsv,FromColor}, prisma::{Rgb,Hsv,FromColor, Lerp},
cgmath::{Point2, Vector2}, cgmath::{Point2, Vector2},
std::time::Duration, std::time::Duration,
angle::Turns angle::Turns
@ -31,6 +31,9 @@ use crate::{
#[derive(Clone)] #[derive(Clone)]
struct Inputs { struct Inputs {
t: Duration, t: Duration,
transition_time: Duration,
scene_select: usize,
intensity: f32, intensity: f32,
cycle_len: Duration, cycle_len: Duration,
@ -78,16 +81,109 @@ impl ColorGrid for Anim2 {
fn get(&self, p: &Vector2<f32>) -> Rgb<f32> { fn get(&self, p: &Vector2<f32>) -> Rgb<f32> {
let inputs = self.inputs.read().unwrap().clone(); let inputs = self.inputs.read().unwrap().clone();
// let millis = self // let millis = self
let i = ( inputs.t.as_millis() as f32 / (4.0*inputs.cycle_len.as_millis() as f32) ) % 1.0;
Rgb::from_color( Rgb::from_color(
&Hsv::<f32, Turns<f32>>::new( &Hsv::<f32, Turns<f32>>::new(
Turns( 0.0 ), Turns( i ),
0.5, 0.5,
( inputs.t.as_millis() as f32 / inputs.cycle_len.as_millis() as f32 ) % 1.0 (4.0*i) %1.0
) )
) )
} }
} }
enum Waveform {
Sawtooth{ pulse_width: Duration },
Square{ },
}
struct Strobe {
inputs: Arc<RwLock< Inputs >>,
//waveform: Waveform,
subdivision: u32,
}
impl ColorGrid for Strobe {
fn get(&self, p: &Vector2<f32>) -> Rgb<f32> {
let inputs = self.inputs.read().unwrap().clone();
let t = (self.subdivision as f32 * inputs.t.as_millis() as f32 / inputs.cycle_len.as_millis() as f32) % 1.0;
if t < 0.6 {
Rgb::new(0.6, 0.6, 0.6)
} else {
Rgb::new(0.0, 0.0, 0.0)
}
}
}
pub struct SceneLibrary {
library: Vec< Box<dyn ColorGrid> >,
current_scene: RwLock<usize>,
inputs: Arc<RwLock< Inputs >>,
transition_length: Duration,
// transition_curve: enum { Constant, Linear, Sigmoid, Sinus }
}
impl SceneLibrary {
pub fn new( inputs: Arc<RwLock<Inputs>> ) -> Self {
SceneLibrary {
library: vec![
// 0
Box::new( Breathing{ inputs: inputs.clone() } ),
// 1 - 4
Box::new( Strobe{ inputs: inputs.clone(), subdivision: 4 } ),
Box::new( Strobe{ inputs: inputs.clone(), subdivision: 8 } ),
Box::new( Strobe{ inputs: inputs.clone(), subdivision: 12 } ),
Box::new( Strobe{ inputs: inputs.clone(), subdivision: 16 } ),
// others
Box::new( Anim2{ inputs: inputs.clone() } ),
],
current_scene: RwLock::new(0),
inputs,
transition_length: Duration::from_millis(200),
}
}
}
impl ColorGrid for SceneLibrary {
fn get(&self, p: &Vector2<f32>) -> Rgb<f32> {
let inputs = self.inputs.read().unwrap().clone();
let sc = *self.current_scene.read().unwrap();
if inputs.scene_select == sc {
// display only one animation
self.library[ sc ].get(p)
} else {
// display transition
let cur_scene = &self.library[ sc ];
let nxt_scene = &self.library[ inputs.scene_select ];
// crossfade param
let w = ( inputs.transition_time.as_millis() as f32 / self.transition_length.as_millis() as f32 );
if w >= 1.0 {
// change own state:
*self.current_scene.write().unwrap() = inputs.scene_select;
}
cur_scene.get(p)
.lerp(
&nxt_scene.get(p),
w
)
}
}
}
#[async_std::main] #[async_std::main]
async fn main() { async fn main() {
let event_loop = EventLoop::new().unwrap(); let event_loop = EventLoop::new().unwrap();
@ -100,14 +196,17 @@ async fn main() {
let socket = Arc::new(RwLock::new(std::net::UdpSocket::bind("0.0.0.0:4210").expect("failed to bind UDP socket"))); let socket = Arc::new(RwLock::new(std::net::UdpSocket::bind("0.0.0.0:4210").expect("failed to bind UDP socket")));
socket.write().unwrap().set_read_timeout(Some(std::time::Duration::from_millis(500))); socket.write().unwrap().set_read_timeout(Some(std::time::Duration::from_millis(500)));
socket.write().unwrap().set_write_timeout(Some(std::time::Duration::from_millis(50))); socket.write().unwrap().set_write_timeout(Some(std::time::Duration::from_millis(50)));
let inputs = Arc::new(RwLock::new( let inputs = Arc::new(RwLock::new(
Inputs { Inputs {
t: Duration::from_millis(0), t: Duration::from_millis(0),
transition_time: Duration::from_millis(0),
intensity: 0.5, intensity: 0.5,
cycle_len: Duration::from_millis(300), cycle_len: Duration::from_millis(300),
wave_peak: 0.5, wave_peak: 0.5,
scene_select: 0
} }
)); ));
@ -133,14 +232,13 @@ async fn main() {
.offset(Vector2::new(0.5, 0.0)) .offset(Vector2::new(0.5, 0.0))
], ],
Box::new( Box::new( SceneLibrary::new(inputs.clone()) )
Anim2{ inputs: inputs.clone() }
)
); );
let tbegin = std::time::Instant::now(); let mut tbegin = std::time::Instant::now();
let mut transition_begin = std::time::Instant::now();
let mut last_tap = std::time::Instant::now(); let mut last_tap = std::time::Instant::now();
event_loop.run(move |event, elwt| { event_loop.run(move |event, elwt| {
let tcur = std::time::Instant::now(); let tcur = std::time::Instant::now();
elwt.set_control_flow(ControlFlow::WaitUntil( elwt.set_control_flow(ControlFlow::WaitUntil(
@ -148,12 +246,11 @@ async fn main() {
)); ));
inputs.write().unwrap().t = tcur - tbegin; inputs.write().unwrap().t = tcur - tbegin;
inputs.write().unwrap().transition_time = tcur - transition_begin;
lighting_setup.update_buffers(); lighting_setup.update_buffers();
//lighting_setup.update_outputs(); //lighting_setup.update_outputs();
match event { match event {
//Event::
Event::WindowEvent { window_id, event: WindowEvent::RedrawRequested } if window_id == window.id() => { Event::WindowEvent { window_id, event: WindowEvent::RedrawRequested } if window_id == window.id() => {
let (width, height) = { let (width, height) = {
let size = window.inner_size(); let size = window.inner_size();
@ -178,12 +275,45 @@ async fn main() {
winit::keyboard::Key::Character(c) => { winit::keyboard::Key::Character(c) => {
eprintln!("pressed {}", c); eprintln!("pressed {}", c);
if c == "x" { match &c[0..1] {
// tap tempo "x" => {
let old_tap = last_tap; // tap tempo
last_tap = std::time::Instant::now(); let old_tap = last_tap;
last_tap = std::time::Instant::now();
inputs.write().unwrap().cycle_len = last_tap - old_tap; if (last_tap - old_tap) < Duration::from_millis(20000) {
inputs.write().unwrap().cycle_len = last_tap - old_tap;
}
}
"q" => {
// sync
inputs.write().unwrap().t = Duration::from_millis(0);
tbegin = std::time::Instant::now();
},
"0" => {
inputs.write().unwrap().scene_select = 0;
transition_begin = std::time::Instant::now();
}
"1" => {
inputs.write().unwrap().scene_select = 1;
transition_begin = std::time::Instant::now();
}
"2" => {
inputs.write().unwrap().scene_select = 2;
transition_begin = std::time::Instant::now();
}
"3" => {
inputs.write().unwrap().scene_select = 3;
transition_begin = std::time::Instant::now();
}
"4" => {
inputs.write().unwrap().scene_select = 4;
transition_begin = std::time::Instant::now();
}
_=>{}
} }
} }
_ => {} _ => {}