add basic scene selection
This commit is contained in:
parent
13d58a7ac5
commit
06ea05e112
1 changed files with 146 additions and 16 deletions
162
src/main.rs
162
src/main.rs
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
_=>{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
Loading…
Reference in a new issue