If the code hasn't been touched in this long, its probably release-worthy.

This commit is contained in:
2022-06-11 11:02:27 +02:00
parent 0c9eb831dd
commit d14fa7fde1
59 changed files with 1610 additions and 842 deletions

View File

@ -1,75 +1,74 @@
#include "../Figments/Figments.h"
#include "../sprites/Chime.h"
#include "../sprites/Blob.h"
#include "Chimes.h"
#include "../Static.h"
#define CHIME_LENGTH 23
#define CHIME_COUNT 4
#define BLOB_COUNT 10
ChimesAnimation::ChimesAnimation() : Figment("Chimes", Task::Stopped) {
}
class ChimesAnimation: public Figment {
public:
ChimesAnimation(Task::State initialState) : Figment("Chimes", initialState) {
m_chimes.forEach([](Chime<CHIME_LENGTH> &chime) {
chime.setPos(random(Chime<CHIME_LENGTH>::Length * 5));
chime.setHue(random(255));
chime.setSpeed(random(90) + 138);
chime.setBrightness(200);
chime.setOffset(random(1024));
});
m_blobs.forEach([](Blob &blob) {
blob.setPos(random(255));
blob.setHue(random(255));
blob.setBrightness(random(255));
if (random(255) % 2) {
blob.setVelocity(-1);
} else {
blob.setVelocity(1);
void ChimesAnimation::randomize() {
m_isRandom = true;
m_chimes.forEach([](Chime<CHIME_LENGTH> &chime) {
chime.setPos(random(Chime<CHIME_LENGTH>::Length * 5));
chime.setHue(random(255));
chime.setSpeed(random(90) + 138);
chime.setBrightness(200);
chime.setOffset(random(1024));
});
m_blobs.forEach([](Blob &blob) {
blob.setPos(random(255));
blob.setHue(random(255));
blob.setBrightness(random(255));
if (random(255) % 2) {
blob.setVelocity(-1);
} else {
blob.setVelocity(1);
}
});
}
void ChimesAnimation::handleEvent(const InputEvent& evt) {
if (evt.intent == InputEvent::UserInput) {
if (strcmp(evt.asString(), "blobs") == 0) {
m_blobs.toggle();
} else if (strcmp(evt.asString(), "chimes") == 0) {
m_chimes.toggle();
}
});
} else if (evt.intent == InputEvent::SetColor) {
m_flashBrightness.set(255, 0);
m_flashColor = evt.asRGB();
uint8_t flashHue = rgb2hsv_approximate(m_flashColor).hue;
m_blobs.forEach([&](Blob& blob) {
blob.setHue(flashHue);
});
m_chimes.forEach([&](Chime<CHIME_LENGTH>& chime) {
chime.setHue(flashHue);
});
} else if (evt.intent == InputEvent::Beat) {
m_isRandom = false;
}
}
void handleEvent(const InputEvent& evt) override {
if (evt.intent == InputEvent::UserInput) {
if (strcmp(evt.asString(), "blobs") == 0) {
m_blobs.toggle();
} else if (strcmp(evt.asString(), "chimes") == 0) {
m_chimes.toggle();
}
} else if (evt.intent == InputEvent::SetColor) {
m_flashBrightness.set(255, 0);
m_flashColor = evt.asRGB();
uint8_t flashHue = rgb2hsv_approximate(m_flashColor).hue;
m_blobs.forEach([&](Blob& blob) {
blob.setHue(flashHue);
});
m_chimes.forEach([&](Chime<CHIME_LENGTH>& chime) {
chime.setHue(flashHue);
});
}
}
void ChimesAnimation::loop() {
if (!m_isRandom) {
randomize();
}
m_chimes.update();
m_blobs.update();
m_flashColor.update();
EVERY_N_MILLISECONDS(5) {
m_flashBrightness.update();
}
}
void loop() override {
m_chimes.update();
m_blobs.update();
m_flashColor.update();
EVERY_N_MILLISECONDS(5) {
m_flashBrightness.update();
}
}
void ChimesAnimation::render(Display* dpy) const {
m_chimes.render(dpy);
m_blobs.render(dpy);
Surface fullSurface(dpy, {0, 0}, {255, 0});
CRGB scaledColor = CRGB(m_flashColor).nscale8_video(std::max((uint8_t)10, ease8InOutCubic(m_flashBrightness)));
fullSurface.paintWith([&](CRGB& pixel) {
pixel = blend(scaledColor, pixel, 200);
//pixel = scaledColor;
});
}
void render(Display* dpy) const override {
m_chimes.render(dpy);
m_blobs.render(dpy);
Surface fullSurface(dpy, {0, 0}, {255, 0});
CRGB scaledColor = CRGB(m_flashColor).nscale8_video(std::max((uint8_t)10, ease8InOutCubic(m_flashBrightness)));
fullSurface.paintWith([&](CRGB& pixel) {
pixel = blend(scaledColor, pixel, 200);
//pixel = scaledColor;
});
}
SpriteList<Chime<CHIME_LENGTH>, CHIME_COUNT> m_chimes;
SpriteList<Blob, BLOB_COUNT> m_blobs;
AnimatedRGB m_flashColor;
AnimatedNumber m_flashBrightness;
};
STATIC_ALLOC(ChimesAnimation);
STATIC_TASK(ChimesAnimation);

24
src/animations/Chimes.h Normal file
View File

@ -0,0 +1,24 @@
#include "../Figments/Figments.h"
#include "../sprites/Chime.h"
#include "../sprites/Blob.h"
#define CHIME_LENGTH 23
#define CHIME_COUNT 4
#define BLOB_COUNT 10
class ChimesAnimation: public Figment {
public:
ChimesAnimation();
void handleEvent(const InputEvent& evt) override;
void loop() override;
void render(Display* dpy) const override;
private:
SpriteList<Chime<CHIME_LENGTH>, CHIME_COUNT> m_chimes;
SpriteList<Blob, BLOB_COUNT> m_blobs;
AnimatedRGB m_flashColor;
AnimatedNumber m_flashBrightness;
void randomize();
bool m_isRandom = false;
};

View File

@ -1,64 +1,58 @@
#include <Figments.h>
#include <ArduinoLog.h>
#include "Drain.h"
#include "../Static.h"
class DrainAnimation: public Figment {
public:
DrainAnimation::DrainAnimation() : Figment("Drain", Task::Stopped) {}
DrainAnimation(Task::State initialState) : Figment("Drain", initialState) {}
void loop() override {
EVERY_N_MILLISECONDS(8) {
m_pos++;
m_fillColor.update();
}
EVERY_N_MILLISECONDS(50) {
if (random(255) >= 10) {
m_burst -= m_burst / 10;
}
void DrainAnimation::loop() {
EVERY_N_MILLISECONDS(8) {
m_pos++;
m_fillColor.update();
}
EVERY_N_MILLISECONDS(50) {
if (random(255) >= 10) {
m_burst -= m_burst / 10;
}
}
}
void handleEvent(const InputEvent& event) override {
if (event.intent == InputEvent::SetColor) {
m_fillColor = event.asRGB();
} else if (event.intent == InputEvent::Acceleration) {
m_pos += log10(event.asInt());
uint16_t burstInc = event.asInt() / 6;
m_burst = (m_burst > 0xFFFF - burstInc) ? 0xFFFF : m_burst + burstInc;
}
void DrainAnimation::handleEvent(const InputEvent& event) {
if (event.intent == InputEvent::SetColor) {
m_fillColor = event.asRGB();
} else if (event.intent == InputEvent::Acceleration) {
m_pos += log10(event.asInt());
uint16_t burstInc = event.asInt() / 6;
m_burst = (m_burst > 0xFFFF - burstInc) ? 0xFFFF : m_burst + burstInc;
}
}
void DrainAnimation::render(Display* dpy) const {
dpy->clear();
Surface leftPanel{dpy, {0, 0}, {128, 0}};
Surface rightPanel{dpy, {128, 0}, {255, 0}};
fillRange(dpy, leftPanel.start, leftPanel.end, rgb2hsv_approximate(m_fillColor));
fillRange(dpy, rightPanel.end, rightPanel.start, rgb2hsv_approximate(m_fillColor));
}
void DrainAnimation::fillRange(Display* dpy, const PhysicalCoordinates &start, const PhysicalCoordinates& end, const CHSV &baseColor) const {
int length = end.x - start.x;
int direction = 1;
if (length < 0) {
direction = -1;
}
AnimatedRGB m_fillColor;
uint8_t frac = length == 0 ? 0 : 255 / std::abs(length);
for(int i = 0; i < std::abs(length); i++) {
auto coords = PhysicalCoordinates((start.x + (i * direction)), 0);
void render(Display* dpy) const override {
dpy->clear();
Surface leftPanel{dpy, {0, 0}, {128, 0}};
Surface rightPanel{dpy, {128, 0}, {255, 0}};
fillRange(dpy, leftPanel.start, leftPanel.end, rgb2hsv_approximate(m_fillColor));
fillRange(dpy, rightPanel.end, rightPanel.start, rgb2hsv_approximate(m_fillColor));
const uint8_t localScale = inoise8(i * 80, m_pos * 3);
const uint8_t dimPosition = lerp8by8(50, 190, scale8(sin8((frac * i) / 2), localScale));
const uint8_t withBurst = ease8InOutCubic(lerp16by16(dimPosition, 255, m_burst));
auto scaledColor = CHSV(baseColor.hue, lerp8by8(100, 255, localScale), withBurst);
CRGB src(dpy->pixelAt(coords));
dpy->pixelAt(coords) = blend(scaledColor, src, 200);
}
}
void fillRange(Display* dpy, const PhysicalCoordinates &start, const PhysicalCoordinates& end, const CHSV &baseColor) const {
int length = end.x - start.x;
int direction = 1;
if (length < 0) {
direction = -1;
}
uint8_t frac = 255 / std::abs(length);
for(int i = 0; i < std::abs(length); i++) {
auto coords = PhysicalCoordinates((start.x + (i * direction)), 0);
const uint8_t localScale = inoise8(i * 80, m_pos * 3);
const uint8_t dimPosition = lerp8by8(50, 190, scale8(sin8((frac * i) / 2), localScale));
const uint8_t withBurst = ease8InOutCubic(lerp16by16(dimPosition, 255, m_burst));
auto scaledColor = CHSV(baseColor.hue, lerp8by8(100, 255, localScale), withBurst);
CRGB src(dpy->pixelAt(coords));
dpy->pixelAt(coords) = blend(scaledColor, src, 200);
}
}
uint16_t m_pos;
uint16_t m_burst;
};
STATIC_ALLOC(DrainAnimation);
STATIC_TASK(DrainAnimation);

View File

@ -1,63 +1,16 @@
#pragma once
#include <Figments.h>
#include <ArduinoLog.h>
class DrainAnimation: public Figment {
public:
DrainAnimation(Task::State initialState) : Figment("Drain", initialState) {}
void loop() override {
EVERY_N_MILLISECONDS(8) {
m_pos++;
m_fillColor.update();
}
EVERY_N_MILLISECONDS(50) {
if (random(255) >= 10) {
m_burst -= m_burst / 10;
}
}
}
void handleEvent(const InputEvent& event) override {
if (event.intent == InputEvent::SetColor) {
m_fillColor = event.asRGB();
} else if (event.intent == InputEvent::Acceleration) {
m_pos += log10(event.asInt());
uint16_t burstInc = event.asInt() / 6;
m_burst = (m_burst > 0xFFFF - burstInc) ? 0xFFFF : m_burst + burstInc;
}
}
DrainAnimation();
void loop() override;
void handleEvent(const InputEvent& event) override;
void render(Display* dpy) const override;
private:
AnimatedRGB m_fillColor;
void render(Display* dpy) const override {
dpy->clear();
Surface leftPanel{dpy, {0, 0}, {128, 0}};
Surface rightPanel{dpy, {128, 0}, {255, 0}};
fillRange(dpy, leftPanel.start, leftPanel.end, rgb2hsv_approximate(m_fillColor));
fillRange(dpy, rightPanel.end, rightPanel.start, rgb2hsv_approximate(m_fillColor));
}
void fillRange(Display* dpy, const PhysicalCoordinates &start, const PhysicalCoordinates& end, const CHSV &baseColor) const {
int length = end.x - start.x;
int direction = 1;
if (length < 0) {
direction = -1;
}
uint8_t frac = 255 / std::abs(length);
for(int i = 0; i < std::abs(length); i++) {
auto coords = PhysicalCoordinates((start.x + (i * direction)), 0);
const uint8_t localScale = inoise8(i * 80, m_pos * 3);
const uint8_t dimPosition = lerp8by8(50, 190, scale8(sin8((frac * i) / 2), localScale));
const uint8_t withBurst = ease8InOutCubic(lerp16by16(dimPosition, 255, m_burst));
auto scaledColor = CHSV(baseColor.hue, lerp8by8(100, 255, localScale), withBurst);
CRGB src(dpy->pixelAt(coords));
dpy->pixelAt(coords) = blend(scaledColor, src, 200);
}
}
void fillRange(Display* dpy, const PhysicalCoordinates &start, const PhysicalCoordinates& end, const CHSV &baseColor) const;
uint16_t m_pos;
uint16_t m_burst;
};

View File

@ -1,47 +1,33 @@
#pragma once
#include "Flashlight.h"
#include "../Static.h"
#include <Figments.h>
#include "../sprites/Blob.h"
class Flashlight: public Figment {
public:
Flashlight(Task::State initialState) : Figment("Flashlight", initialState) {
m_blobs.forEach([](Blob &blob) {
blob.setHue(random(255));
blob.setSaturation(10);
blob.setPos(random(255));
});
}
void handleEvent(const InputEvent& evt) override {
if (evt.intent == InputEvent::Acceleration) {
if (evt.asInt() > 10) {
m_blobs.forEach([](Blob& blob) {blob.update();});
}
Flashlight::Flashlight() : Figment("Flashlight", Task::Stopped) {
m_blobs.forEach([](Blob &blob) {
blob.setHue(random(255));
blob.setSaturation(10);
blob.setPos(random(255));
if (random(255) >= 128) {
blob.setVelocity(-1);
}
});
}
/*if (evt.intent() == InputEvent::UserInput) {
if (evt.asInt() == 1) {
m_blobs.forEach([](Blob& blob) {blob.setPos(random(255));});
}
if (evt.asInt() == 2) {
m_blobs.forEach([](Blob& chime) {blob.setPos(0);});
}
}*/
}
void loop() override {
m_blobs.update();
}
void render(Display* dpy) const override {
m_blobs.render(dpy);
for(int i = 0; i < dpy->pixelCount();i++) {
dpy->pixelAt(i) |= 100;
void Flashlight::handleEvent(const InputEvent& evt) {
if (evt.intent == InputEvent::Acceleration) {
if (evt.asInt() > 10) {
m_blobs.forEach([](Blob& blob) {blob.update();});
}
}
}
}
private:
static constexpr int blobCount = 30;
SpriteList<Blob, blobCount> m_blobs;
};
void Flashlight::loop() {
m_blobs.update();
}
void Flashlight::render(Display* dpy) const {
m_blobs.render(dpy);
Surface(dpy, {0, 0}, {255, 0}) |= 100;
}
STATIC_ALLOC(Flashlight);
STATIC_TASK(Flashlight);

View File

@ -0,0 +1,15 @@
#pragma once
#include <Figments.h>
#include "../sprites/Blob.h"
class Flashlight: public Figment {
public:
Flashlight();
void handleEvent(const InputEvent& evt) override;
void loop() override;
void render(Display* dpy) const override;
private:
static constexpr int blobCount = 30;
SpriteList<Blob, blobCount> m_blobs;
};

View File

@ -1,42 +0,0 @@
#include <Figments.h>
template<uint8_t MaxBrightness = 255, uint32_t MaxMilliAmps = 500, uint32_t Voltage = 5>
class Power: public Figment {
public:
Power() : Figment("Power") {}
void handleEvent(const InputEvent& evt) override {
switch (evt.intent) {
case InputEvent::PowerToggle:
m_powerState = m_powerState.value() <= 128 ? 255 : 0;
//Log.info("POWER TOGGLE %d", m_powerState.value());
break;
case InputEvent::SetPower:
m_powerState = evt.asInt() == 0 ? 0 : 255;
break;
case InputEvent::SetBrightness:
m_brightness = evt.asInt();
default:
return;
}
}
void loop() override {
m_powerState.update();
m_brightness.update();
}
void render(Display* dpy) const override {
const uint8_t clippedBrightness = min((uint8_t)m_brightness, MaxBrightness);
const uint8_t scaledBrightness = scale8(m_powerState, clippedBrightness);
const uint8_t videoBrightness = brighten8_video(scaledBrightness);
const uint8_t powerBrightness = calculate_max_brightness_for_power_mW(videoBrightness, Watts);
FastLED.setBrightness(powerBrightness);
}
static constexpr uint32_t Watts = Voltage * MaxMilliAmps;
private:
AnimatedNumber m_powerState = 255;
AnimatedNumber m_brightness = MaxBrightness;
};

54
src/animations/Power.h Normal file
View File

@ -0,0 +1,54 @@
#pragma once
#include <Figments.h>
template<uint8_t MaxBrightness = 255, uint32_t MaxMilliAmps = 500, uint32_t Voltage = 5>
class Power: public Figment {
public:
Power() : Figment("Power") {}
void handleEvent(const InputEvent& evt) override {
switch (evt.intent) {
case InputEvent::PowerToggle:
m_powerState = m_powerState.value() <= 128 ? 255 : 0;
//Log.info("POWER TOGGLE %d", m_powerState.value());
break;
case InputEvent::SetPower:
m_powerState = evt.asInt() == 0 ? 0 : 255;
Log.notice("Power is now %d", m_powerState);
break;
case InputEvent::SetBrightness:
m_brightness = evt.asInt();
m_brightness = 255;
break;
case InputEvent::Beat:
m_beatDecay.set(0, 255);
break;
default:
return;
}
}
void loop() override {
m_powerState.update();
m_brightness.update();
EVERY_N_MILLISECONDS(20) {
m_beatDecay.update(13);
}
}
void render(Display* dpy) const override {
const uint8_t decayedBrightness = scale8((uint8_t)m_brightness, ease8InOutCubic((uint8_t)m_beatDecay));
const uint8_t clippedBrightness = std::min(decayedBrightness, MaxBrightness);
const uint8_t scaledBrightness = scale8(m_powerState, clippedBrightness);
const uint8_t videoBrightness = brighten8_video(scaledBrightness);
const uint8_t powerBrightness = calculate_max_brightness_for_power_mW(videoBrightness, Watts);
FastLED.setBrightness(powerBrightness);
}
static constexpr uint32_t Watts = Voltage * MaxMilliAmps;
private:
AnimatedNumber m_powerState = 255;
AnimatedNumber m_brightness = MaxBrightness;
AnimatedNumber m_beatDecay = 255;
};

View File

@ -1,50 +1,72 @@
#include <Figments.h>
#include "../sprites/Blob.h"
#include "SolidAnimation.h"
#include "../Static.h"
class SolidAnimation: public Figment {
private:
AnimatedNumber m_red, m_green, m_blue;
static constexpr int blobCount = 20;
SpriteList<Blob, blobCount> m_blobs;
SolidAnimation::SolidAnimation() : Figment("Solid", Task::Stopped) {
}
public:
SolidAnimation(Task::State initialState) : Figment("Solid", initialState) {
m_blobs.forEach([](Blob& blob) {
blob.setPos(random(140));
blob.setBrightness(random(255));
if (random(255) % 2) {
blob.setVelocity(-1);
}
void SolidAnimation::randomize() {
m_isRandom = true;
m_blobs.forEach([](Blob& blob) {
blob.setPos(random(140));
blob.setBrightness(random(255));
if (random(255) % 2) {
blob.setVelocity(-1);
}
});
}
void SolidAnimation::handleEvent(const InputEvent& evt) {
if (evt.intent == InputEvent::SetColor) {
CRGB nextColor = evt.asRGB();
m_red.set(nextColor.red);
m_green.set(nextColor.green);
m_blue.set(nextColor.blue);
m_changePct.set(0, 255);
m_prevColor = m_curColor;
m_curColor = nextColor;
m_horizontal = !m_horizontal;
} else if (evt.intent == InputEvent::Beat) {
m_isRandom = false;
}
}
void SolidAnimation::loop() {
if (!m_isRandom) {
randomize();
}
m_red.update(15);
m_green.update(15);
m_blue.update(15);
EVERY_N_MILLIS(16) {
m_changePct.update(12);
}
EVERY_N_MILLIS(6) {
CRGB rgb{m_red, m_green, m_blue};
CHSV hsv = rgb2hsv_approximate(rgb);
m_blobs.forEach([=](Blob& blob) {
blob.setHue(hsv.hue);
blob.setSaturation(hsv.saturation);
});
m_blobs.update();
}
}
void handleEvent(const InputEvent& evt) override {
if (evt.intent == InputEvent::SetColor) {
CRGB nextColor = evt.asRGB();
m_red.set(nextColor.red);
m_green.set(nextColor.green);
m_blue.set(nextColor.blue);
}
}
#include <Perfcounter.h>
void loop() override {
m_red.update();
m_green.update();
m_blue.update();
EVERY_N_MILLIS(6) {
CRGB rgb{m_red, m_green, m_blue};
CHSV hsv = rgb2hsv_approximate(rgb);
m_blobs.forEach([=](Blob& blob) {
blob.setHue(hsv.hue);
blob.setSaturation(hsv.saturation);
});
m_blobs.update();
}
void SolidAnimation::render(Display* dpy) const {
PerfCounter _("solidRender");
CRGB color(m_red.value(), m_green.value(), m_blue.value());
uint8_t frame = ease8InOutApprox(m_changePct);
if (frame == 255) {
Surface(dpy, {0, 0}, {255, 255}) = color;
} else {
uint8_t cutoff = (frame / 2);
uint8_t rotation = m_horizontal ? 0 : 128;
Surface(dpy, {0, 0}, {128 - cutoff, 255}, rotation) = m_prevColor;
Surface(dpy, {128 - cutoff, 0}, {128 + cutoff, 255}, rotation) = color;
Surface(dpy, {128 + cutoff, 0}, {255, 255}, rotation) = m_prevColor;
}
void render(Display* dpy) const override {
CRGB color(m_red.value(), m_green.value(), m_blue.value());
Surface(dpy, {0, 0}, {255, 0}) = color;
m_blobs.render(dpy);
}
};
m_blobs.render(dpy);
}
STATIC_ALLOC(SolidAnimation);
STATIC_TASK(SolidAnimation);

View File

@ -0,0 +1,21 @@
#pragma once
#include <Figments.h>
#include "../sprites/Blob.h"
class SolidAnimation: public Figment {
private:
AnimatedNumber m_red, m_green, m_blue, m_changePct;
CRGB m_curColor;
CRGB m_prevColor;
static constexpr int blobCount = 20;
SpriteList<Blob, blobCount> m_blobs;
void randomize();
bool m_isRandom = false;
bool m_horizontal = false;
public:
SolidAnimation();
void handleEvent(const InputEvent& evt) override;
void loop() override;
void render(Display* dpy) const override;
};

View File

@ -32,3 +32,4 @@ UpdateStatus::render(Display* dpy) const
}
STATIC_ALLOC(UpdateStatus);
STATIC_TASK(UpdateStatus);

View File

@ -1,3 +1,4 @@
#pragma once
#include <Figments.h>
class UpdateStatus: public Figment {