From 58e95eb2bce2093c6e4bee70ce106b4b099ef43a Mon Sep 17 00:00:00 2001
From: Michael Sippel <micha@fragmental.art>
Date: Thu, 2 May 2024 19:34:34 +0200
Subject: [PATCH] patterns from saturday - add wheel input parameter - gastel
 fade - alternate

---
 src/fixture.rs              |  3 +--
 src/main.rs                 | 52 ++++++++++++++++++++++++++++++++-----
 src/patterns/alternate.rs   | 47 +++++++++++++++++++++++++++++++++
 src/patterns/arctic_rain.rs |  2 +-
 src/patterns/gastel_fade.rs | 37 ++++++++++++++++++++++++++
 src/patterns/mod.rs         |  8 +++++-
 src/patterns/strobe.rs      |  6 ++---
 src/patterns/wheel.rs       | 48 ++++++++++++++++++++++++++++++++++
 src/scene_library.rs        |  6 +++++
 src/setup.rs                | 16 +++++++++++-
 src/stripe_driver.rs        |  2 ++
 11 files changed, 212 insertions(+), 15 deletions(-)
 create mode 100644 src/patterns/alternate.rs
 create mode 100644 src/patterns/gastel_fade.rs
 create mode 100644 src/patterns/wheel.rs

diff --git a/src/fixture.rs b/src/fixture.rs
index 075d330..9cc82c0 100644
--- a/src/fixture.rs
+++ b/src/fixture.rs
@@ -5,10 +5,9 @@ use {
     crate::view::ColorGrid
 };
 
-
-
 pub trait FixtureDriver {
     fn send(&self, pixels: &Vec<Rgb<u8>>);
+    fn sync(&self);
 }
 
 pub struct Fixture {
diff --git a/src/main.rs b/src/main.rs
index 913205c..3b079e1 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -43,7 +43,8 @@ pub struct Inputs {
     intensity: f32,
     cycle_len: Duration,
 
-    wave_peak: f32
+    wave_peak: f32,
+    wheel: i32
 }
 
 #[async_std::main]
@@ -68,7 +69,8 @@ async fn main() {
             cycle_len: Duration::from_millis(300),
             wave_peak: 0.5,
 
-            scene_select: 0
+            scene_select: 0,
+            wheel: 0
         }
     ));
 
@@ -84,10 +86,11 @@ async fn main() {
             Fixture::new_stripe()
                 .with_driver( Box::new(StripeDriver::new("192.168.0.112:4210", socket.clone())) )
                 .offset(Vector2::new(-0.4, 0.0)),
-
+/*
             Fixture::new_stripe()
                 .with_driver( Box::new(StripeDriver::new("192.168.0.113:4210", socket.clone())) )
-                .offset(Vector2::new(0.4, 0.0)),
+            .offset(Vector2::new(0.4, 0.0)),
+            */
 
             Fixture::new_stripe()
                 .with_driver( Box::new(StripeDriver::new("192.168.0.114:4210", socket.clone())))
@@ -100,17 +103,25 @@ async fn main() {
     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 z = 0;
+
+    let mut active = true;
 
     event_loop.run(move |event, elwt| {
         let tcur = std::time::Instant::now();
-        elwt.set_control_flow(ControlFlow::WaitUntil(
+        elwt.set_control_flow(ControlFlow::
+                              WaitUntil(
             tcur + Duration::from_millis(10)
         ));
-
         inputs.write().unwrap().t = tcur - tbegin;
         inputs.write().unwrap().transition_time = tcur - transition_begin;
         lighting_setup.update_buffers();
-        lighting_setup.update_outputs();
+
+        if active {
+            for i in 1..4 {
+                lighting_setup.update_outputs(i);
+            }
+        }
 
         match event {
             Event::WindowEvent { window_id, event: WindowEvent::RedrawRequested } if window_id == window.id() => {
@@ -186,6 +197,33 @@ async fn main() {
                                     inputs.write().unwrap().scene_select = 7;
                                     transition_begin = std::time::Instant::now();
                                 }
+                                "8" => {
+                                    inputs.write().unwrap().scene_select = 8;
+                                    transition_begin = std::time::Instant::now();
+                                }
+                                "9" => {
+                                    inputs.write().unwrap().scene_select = 9;
+                                    transition_begin = std::time::Instant::now();
+                                }
+                                "a" => {
+                                    inputs.write().unwrap().scene_select = 10;
+                                    transition_begin = std::time::Instant::now();
+                                }
+                                "m" => {
+                                    if active {
+                                        eprintln!("DEACTIVATED");
+                                        active = false;
+                                    } else {
+                                        active = true;
+                                        eprintln!("ACTIVATED");
+                                    }
+                                }
+                                "+" => {
+                                    inputs.write().unwrap().wheel +=1;
+                                }
+                                "-" => {
+                                    inputs.write().unwrap().wheel -=1;
+                                }
 
                                 _=>{}
                             }
diff --git a/src/patterns/alternate.rs b/src/patterns/alternate.rs
new file mode 100644
index 0000000..2e4f3dd
--- /dev/null
+++ b/src/patterns/alternate.rs
@@ -0,0 +1,47 @@
+use {
+    std::num::NonZeroU32,
+    std::sync::{Arc, RwLock, Mutex},
+    std::rc::Rc,
+    winit::event::{Event, WindowEvent},
+    winit::event_loop::{ControlFlow, EventLoop},
+    winit::window::WindowBuilder,
+    prisma::{Rgb,Hsv,FromColor, Lerp},
+    cgmath::{Point2, Vector2},
+    std::time::Duration,
+    angle::Turns,
+
+    crate::{Inputs, view::ColorGrid}
+};
+
+pub struct Alternate {
+    pub inputs: Arc<RwLock< Inputs >>,
+}
+
+impl ColorGrid for Alternate {
+    fn get(&self, p: &Vector2<f32>) -> Rgb<f32> {
+        let inputs = self.inputs.read().unwrap().clone();
+
+        let switch = 0;
+
+        let t = (inputs.wheel as f32 * inputs.t.as_millis() as f32 / inputs.cycle_len.as_millis() as f32) % 1.0;
+
+        if ((50.0+p.y*128.0) / inputs.wheel as f32) as u32 % 2 == 0 {
+            if t < 0.5 {
+                Rgb::new(0.5, 0.2, 0.2)
+            } else {
+                Rgb::new(0.05, 0.05, 0.05)
+            }
+        } else {
+            if t < 0.5 {
+                Rgb::new(0.05, 0.05, 0.05)
+            } else {
+                Rgb::new(0.3, 0.3, 0.6)
+            }   
+        }
+
+
+
+    }
+}
+
+
diff --git a/src/patterns/arctic_rain.rs b/src/patterns/arctic_rain.rs
index 1dd44c6..7339f3c 100644
--- a/src/patterns/arctic_rain.rs
+++ b/src/patterns/arctic_rain.rs
@@ -26,7 +26,7 @@ impl ColorGrid for ArcticRain {
         let col1 =
         Rgb::from_color(
             &Hsv::<f32, Turns<f32>>::new(
-                Turns( 0.65 ),
+                Turns( 0.65 + 0.3*(inputs.wheel%10) as f32*0.1 ),
                 0.9,
                 1.0 - ((i + (2.0-p.y/4.0)) * 12.0) % 1.0,
 //                (f32::sin(-p.y+i) * 12.0) % 1.0,
diff --git a/src/patterns/gastel_fade.rs b/src/patterns/gastel_fade.rs
new file mode 100644
index 0000000..2df81ee
--- /dev/null
+++ b/src/patterns/gastel_fade.rs
@@ -0,0 +1,37 @@
+use {
+    std::num::NonZeroU32,
+    std::sync::{Arc, RwLock, Mutex},
+    std::rc::Rc,
+    winit::event::{Event, WindowEvent},
+    winit::event_loop::{ControlFlow, EventLoop},
+    winit::window::WindowBuilder,
+    prisma::{Rgb,Hsv,FromColor, Lerp},
+    cgmath::{Point2, Vector2},
+    std::time::Duration,
+    angle::Turns,
+
+    crate::{Inputs, view::ColorGrid, util::get_angle}
+};
+
+pub struct GastelFade { pub inputs: Arc<RwLock< Inputs >> }
+impl ColorGrid for GastelFade {
+    fn get(&self, p: &Vector2<f32>) -> Rgb<f32> {
+        let inputs = self.inputs.read().unwrap().clone();
+
+        let i = ( inputs.t.as_millis() as f32 / (4.0*inputs.cycle_len.as_millis() as f32) ) % 1.0;
+
+        let w = (inputs.t.as_millis() as f32 / (inputs.wheel as f32*inputs.cycle_len.as_millis() as f32)) % 1.0;
+
+        Rgb::from_color(
+            &Hsv::<f32, Turns<f32>>::new(
+                Turns( 0.73 + f32::cos(i/100.0)*0.2 ),
+                w,
+                if i < 0.25 {
+                    1.0
+                } else {
+                    f32::cos(i*3.0)
+                }
+            )
+        )
+    }
+}
diff --git a/src/patterns/mod.rs b/src/patterns/mod.rs
index 4fa24ae..98529f0 100644
--- a/src/patterns/mod.rs
+++ b/src/patterns/mod.rs
@@ -3,6 +3,9 @@ pub mod breathing;
 pub mod strobe;
 pub mod arctic_rain;
 pub mod pastel_fade;
+pub mod gastel_fade;
+pub mod wheel;
+pub mod alternate;
 
 #[path = "uboot_prüfstand_fade.rs"]
 pub mod uboot;
@@ -12,7 +15,10 @@ pub use {
     strobe::Strobe,
     arctic_rain::ArcticRain,
     pastel_fade::PastelFade,
-    uboot::UbootPrüfstandFade
+    gastel_fade::GastelFade,
+    uboot::UbootPrüfstandFade,
+    wheel::Wheel,
+    alternate::Alternate
 };
 
     
diff --git a/src/patterns/strobe.rs b/src/patterns/strobe.rs
index 79386d3..185bd62 100644
--- a/src/patterns/strobe.rs
+++ b/src/patterns/strobe.rs
@@ -22,12 +22,12 @@ 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;
+        let t = (inputs.wheel 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)
+            Rgb::new(0.3, 0.3, 0.3)
         } else {
-            Rgb::new(0.0, 0.0, 0.0)
+            Rgb::new(0.05, 0.05, 0.05)
         }
     }
 }
diff --git a/src/patterns/wheel.rs b/src/patterns/wheel.rs
new file mode 100644
index 0000000..2be54ed
--- /dev/null
+++ b/src/patterns/wheel.rs
@@ -0,0 +1,48 @@
+use {
+    std::num::NonZeroU32,
+    std::sync::{Arc, RwLock, Mutex},
+    std::rc::Rc,
+    winit::event::{Event, WindowEvent},
+    winit::event_loop::{ControlFlow, EventLoop},
+    winit::window::WindowBuilder,
+    prisma::{Rgb,Hsv,FromColor, Lerp},
+    cgmath::{Point2, Vector2},
+    std::time::Duration,
+    angle::Turns,
+
+    crate::{Inputs, view::ColorGrid, util::get_angle}
+};
+
+
+pub struct Wheel { pub inputs: Arc<RwLock< Inputs >> }
+impl ColorGrid for Wheel {
+    fn get(&self, p: &Vector2<f32>) -> Rgb<f32> {
+        let inputs = self.inputs.read().unwrap().clone();
+
+        let millis = inputs.t.as_millis();
+
+        let p1 = p + Vector2::new(0.0,0.5);
+        let r2 = p1.x*p1.x + p1.y*p1.y;
+        let v = if r2 > 1.0 { 1.0 } else { r2 };
+        let phi = ( get_angle(&p1) );
+        let mirrorphi = if phi < 0.5 { phi } else { 1.0-phi };
+        let gamma =
+            0.5 + 0.5*f32::cos(
+                    (5.0) *
+                    mirrorphi *
+                    (
+                       inputs.t.as_millis() as f32
+                            / (inputs.cycle_len.as_millis() as f32 * (1.0 + (inputs.wheel as f32).abs()))
+                    )
+            );
+
+        Rgb::from_color(
+            &Hsv::<f32, Turns<f32>>::new(
+                Turns( gamma*0.5 ),
+                0.5 + r2 * 0.5,
+                (inputs.wheel as f32 / 16.0),
+            )
+        )
+    }
+}
+
diff --git a/src/scene_library.rs b/src/scene_library.rs
index e7231fa..3c703c1 100644
--- a/src/scene_library.rs
+++ b/src/scene_library.rs
@@ -42,6 +42,12 @@ impl SceneLibrary {
                 Box::new( PastelFade{ inputs: inputs.clone() } ),
                 Box::new( UbootPrüfstandFade{ inputs: inputs.clone() } ),
                 Box::new( ArcticRain{ inputs: inputs.clone() } ),
+
+                Box::new( GastelFade{ inputs: inputs.clone() } ),
+                Box::new( Wheel{ inputs: inputs.clone() } ),
+
+
+                Box::new( Alternate{ inputs: inputs.clone() } ),
             ],
             current_scene: RwLock::new(0),
             inputs,
diff --git a/src/setup.rs b/src/setup.rs
index 269013a..72c3aba 100644
--- a/src/setup.rs
+++ b/src/setup.rs
@@ -31,12 +31,26 @@ impl LightingSetup {
         }
     }
 
-    pub fn update_outputs(&mut self) {
+    pub fn update_outputs(&mut self, id: usize) {
+        /*
         for fixture in self.fixtures.iter() {
             if let Some(driver) = fixture.driver.as_ref() {
                 driver.send( &fixture.buffer );
             }
+    }*/
+
+        let fixture = &self.fixtures[id];
+        if let Some(driver) = fixture.driver.as_ref() {
+            driver.send( &fixture.buffer );
+            //driver.sync();
         }
+        /*
+        for fixture in self.fixtures.iter() {
+            if let Some(driver) = fixture.driver.as_ref() {
+                driver.sync();
+            }
+    }
+        */
     }
 
     pub fn draw_preview(
diff --git a/src/stripe_driver.rs b/src/stripe_driver.rs
index 4a98b91..49876cd 100644
--- a/src/stripe_driver.rs
+++ b/src/stripe_driver.rs
@@ -30,7 +30,9 @@ impl FixtureDriver for StripeDriver {
         }
 
         self.socket.write().unwrap().send_to(&buf, &self.addr);
+    }
 
+    fn sync(&self) {
         let mut  rbuf = [0 as u8; 8];
         match
             self.socket.write().unwrap().recv(&mut rbuf) {