Add flashing pattern

This commit is contained in:
Austen Adler 2021-08-15 14:53:11 -04:00
parent ea30e00eba
commit 5dc0438dd8
3 changed files with 132 additions and 45 deletions

53
src/pattern/flashing.rs Normal file
View File

@ -0,0 +1,53 @@
use super::Pattern;
use crate::color::{self, Rgb};
use std::{
collections::{vec_deque, VecDeque},
convert::TryFrom,
iter,
};
#[derive(Clone, Debug)]
pub struct Flashing {
lights_buf: VecDeque<Rgb>,
width: u8,
colors: Vec<Rgb>,
}
impl Flashing {
pub fn new(colors: Vec<Rgb>, width: u8) -> Self {
Self {
colors,
width,
lights_buf: VecDeque::new(),
}
}
}
impl Pattern for Flashing {
fn step(&mut self) -> Result<bool, ()> {
self.lights_buf.rotate_right(self.width.into());
Ok(true)
}
fn init(&mut self, num_lights: u16) -> Result<(), ()> {
if self.lights_buf.len() == 0 {
return Err(());
}
let length_factor = u16::try_from(self.lights_buf.len())
.or(Err(()))?
.saturating_mul(u16::from(self.width));
let buf_length = color::min_with_factor(num_lights, length_factor)?;
self.lights_buf = self
.colors
.iter()
.flat_map(|&x| iter::repeat(x).take(self.width.into()))
.cycle()
.take(buf_length.into())
.collect();
Ok(())
}
fn get_strip(&self) -> vec_deque::Iter<Rgb> {
self.lights_buf.iter()
}
}

22
web/src/Colors.svelte Normal file
View File

@ -0,0 +1,22 @@
<script lang="ts">
// From: https://css-tricks.com/snippets/javascript/random-hex-color/
function randomColor() {
return "#" + Math.floor(Math.random()*16777215).toString(16);
}
export let value = [randomColor()];
function newColor() {
console.log(value);
value = [...value, randomColor()];
}
function removeColor() {
if(newColor.length > 1) {
value = value.slice(0, -1);
}
}
</script>
{#each value as value}
<input type="color" bind:value={value} />
{/each}
<button type="button" on:click={newColor} href="#">+</button>
<button type="button" on:click={removeColor} href="#">-</button>

View File

@ -1,49 +1,53 @@
<script lang="ts"> <script lang="ts">
let url = "/api/setcolor"; import Colors from "./Colors.svelte";
let url = "/api/setcolor";
let possiblePatterns = [ let possiblePatterns = [
{name: "Solid", text: "Solid", formElements: [ {name: "Solid", text: "Solid", formElements: [
{name: "color", type: "color", label: "Color", value: "#000000"}, {name: "color", type: "color", label: "Color", value: "#000000"},
]}, ]},
{name: "Collide", text: "Collide", formElements: [ {name: "Collide", text: "Collide", formElements: [
{name: "left_color", type: "color", label: "Left Color", value: "#000000"}, {name: "left_color", type: "color", label: "Left Color", value: "#000000"},
{name: "right_color", type: "color", label: "Right Color", value: "#000000"}, {name: "right_color", type: "color", label: "Right Color", value: "#000000"},
{name: "conjoined_color", type: "color", label: "Conjoined Color", value: "#000000"}, {name: "conjoined_color", type: "color", label: "Conjoined Color", value: "#000000"},
]}, ]},
{name: "Fade", text: "Fade", formElements: [ {name: "Fade", text: "Fade", formElements: [
{name: "color", type: "color", label: "Color", value: "#000000"}, {name: "color", type: "color", label: "Color", value: "#000000"},
]}, ]},
{name: "MovingPixel", text: "MovingPixel", formElements: [ {name: "MovingPixel", text: "MovingPixel", formElements: [
{name: "color", type: "color", label: "Color", value: "#000000"}, {name: "color", type: "color", label: "Color", value: "#000000"},
]}, ]},
{name: "MovingRainbow", text: "MovingRainbow", formElements: [ {name: "MovingRainbow", text: "MovingRainbow", formElements: [
{name: "width", type: "number", label: "Width", value: "4"}, {name: "width", type: "number", label: "Width", value: "4"},
{name: "forward", type: "checkbox", label: "More Forward?", value: ""}, {name: "forward", type: "checkbox", label: "More Forward?", value: ""},
]}, ]},
{name: "Orb", text: "Orb", formElements: [ {name: "Orb", text: "Orb", formElements: [
{name: "color", type: "color", label: "Color", value: "#000000"}, {name: "color", type: "color", label: "Color", value: "#000000"},
{name: "center_width", type: "number", label: "Center Width", value: "1"}, {name: "center_width", type: "number", label: "Center Width", value: "1"},
{name: "backoff_width", type: "number", label: "Backoff Width", value: "0"}, {name: "backoff_width", type: "number", label: "Backoff Width", value: "0"},
]}, ]},
{name: "Flashing", text: "Flashing", formElements: [ {name: "Flashing", text: "Flashing", formElements: [
{name: "color", type: "color", label: "Color1", value: "#000000"}, {name: "color", type: "colors", label: "Color", value: []},
{name: "color", type: "color", label: "Color2", value: "#000000"}, // {name: "color", type: "color", label: "Color1", value: "#000000"},
{name: "color", type: "color", label: "Color3", value: "#000000"}, // {name: "color", type: "color", label: "Color2", value: "#000000"},
{name: "color", type: "color", label: "Color4", value: "#000000"}, // {name: "color", type: "color", label: "Color3", value: "#000000"},
{name: "color", type: "color", label: "Color5", value: "#000000"}, // {name: "color", type: "color", label: "Color4", value: "#000000"},
{name: "width", type: "number", label: "Width", value: "1"}, // {name: "color", type: "color", label: "Color5", value: "#000000"},
]}, {name: "width", type: "number", label: "Width", value: "1"},
]},
]; ];
let selectedPattern = possiblePatterns[0]; let selectedPattern = possiblePatterns[0];
function hexToRgb(hex) { function hexToRgb(hex) {
// Adapted from https://stackoverflow.com/a/5624139 // Adapted from https://stackoverflow.com/a/5624139
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); var result = /^#?([a-f\d]{1,2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
console.log(hex);
result.splice(0, 1); result.splice(0, 1);
return result ? result.map(r => parseInt(r, 16)) : null; return result ? result.map(r => parseInt(r, 16)) : null;
} }
function getFormData() { function getFormData() {
var ret = {}; var ret = {};
ret[selectedPattern.name] = selectedPattern.formElements.map(x => { ret[selectedPattern.name] = selectedPattern.formElements.map(x => {
switch(x.type) { switch(x.type) {
case "color": case "color":
@ -55,6 +59,10 @@
case "checkbox": case "checkbox":
return x.value === "on"; return x.value === "on";
break; break;
case "colors":
console.log(x);
return x.value.map(hexToRgb);
break;
default: default:
return x.value; return x.value;
} }
@ -62,11 +70,11 @@
return ret; return ret;
} }
function handleSubmit() { function handleSubmit() {
const response = fetch(url, { const response = fetch(url, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
}, },
body: JSON.stringify(getFormData()) body: JSON.stringify(getFormData())
}).then(r => console.log(response)); }).then(r => console.log(response));
@ -74,14 +82,18 @@
</script> </script>
<form on:submit|preventDefault={handleSubmit}> <form on:submit|preventDefault={handleSubmit}>
<select bind:value={selectedPattern}> <select bind:value={selectedPattern}>
{#each possiblePatterns as p} {#each possiblePatterns as p}
<option value={p}>{p.text}</option> <option value={p}>{p.text}</option>
{/each} {/each}
</select> </select>
{#each selectedPattern.formElements as fe} {#each selectedPattern.formElements as fe}
<label for={fe.name}>{fe.label}</label> <label for={fe.name}>{fe.label}</label>
<input type={fe.type} name={fe.name} on:input={(e) => fe.value = e.target.value} /> {#if fe.type === "colors"}
<Colors bind:value={fe.value}/>
{:else}
<input type={fe.type} name={fe.name} on:input={(e) => fe.value = e.target.value} />
{/if}
{/each} {/each}
<button type="submit">Submit</button> <button type="submit">Submit</button>
</form> </form>