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