Alexa swipe effect
This commit is contained in:
142
espmusicmouse/lib/ledtl/effects/AlexaSwipe.h
Normal file
142
espmusicmouse/lib/ledtl/effects/AlexaSwipe.h
Normal file
@@ -0,0 +1,142 @@
|
||||
#pragma once
|
||||
|
||||
#include "effects/Common.h"
|
||||
#include "helpers/ColorRGBW.h"
|
||||
#include "helpers/ColorHSV.h"
|
||||
#include "helpers/ColorConversions.h"
|
||||
#include "helpers/BellCurve.h"
|
||||
|
||||
struct EffectAlexaSwipeConfig
|
||||
{
|
||||
float primaryColorWidth; // in degrees
|
||||
float transitionWidth;
|
||||
float swipeSpeed; // in degrees per second
|
||||
float bellCurveWidthInLeds;
|
||||
float startPosition;
|
||||
ColorRGBW primaryColor;
|
||||
ColorRGBW secondaryColor;
|
||||
};
|
||||
|
||||
template <typename TLedStrip>
|
||||
class EffectAlexaSwipe
|
||||
{
|
||||
public:
|
||||
static constexpr auto NUM_LEDS = numLeds<TLedStrip>();
|
||||
static constexpr int DELAY_MS = 10;
|
||||
|
||||
using ConfigType = EffectAlexaSwipeConfig;
|
||||
|
||||
EffectAlexaSwipe(const EffectAlexaSwipeConfig &cfg, TLedStrip &ledStrip)
|
||||
: ledStrip_(ledStrip),
|
||||
currentPosition_(0),
|
||||
transitionWidth_(cfg.transitionWidth / 360.0f * NUM_LEDS),
|
||||
invTransitionWidth_(1.0f / transitionWidth_),
|
||||
primaryColorWidth_(cfg.primaryColorWidth / 360.0f * NUM_LEDS + cfg.bellCurveWidthInLeds),
|
||||
bellCurveWidth_(cfg.bellCurveWidthInLeds),
|
||||
invBellCurveWidth_(1.0f / cfg.bellCurveWidthInLeds),
|
||||
speed_(cfg.swipeSpeed / 360 / 1000 * NUM_LEDS * DELAY_MS),
|
||||
startPosition_(cfg.startPosition / 360.0f * NUM_LEDS),
|
||||
primaryColor_(rgb2hsv(cfg.primaryColor)),
|
||||
secondaryColor_(rgb2hsv(cfg.secondaryColor))
|
||||
{
|
||||
//#ifndef PLATFORM_NATIVE
|
||||
// Serial.printf("Primary color %f, %f, %f\n", primaryColor_.h, primaryColor_.s, primaryColor_.v);
|
||||
// Serial.printf("Secondary color %f, %f, %f\n", secondaryColor_.h, secondaryColor_.s, secondaryColor_.v);
|
||||
//#endif
|
||||
}
|
||||
|
||||
int operator()()
|
||||
{
|
||||
clear(ledStrip_);
|
||||
|
||||
const auto width = std::min(int(currentPosition_ + 1), int(NUM_LEDS / 2));
|
||||
|
||||
setLedRGBW(ledStrip_, startPosition_, getColor(currentPosition_));
|
||||
for (int i = 1; i < width; ++i)
|
||||
{
|
||||
const float x = currentPosition_ - float(i);
|
||||
if (x > 0.0f)
|
||||
{
|
||||
const int led1 = startPosition_ + i;
|
||||
const int led2 = startPosition_ - i;
|
||||
const ColorRGBW color = getColor(x);
|
||||
//#ifndef PLATFORM_NATIVE
|
||||
// Serial.printf("Setting %d and %d to %d, %d, %d\n", led1, led2, color.r, color.g, color.b);
|
||||
//#endif
|
||||
setLedRGBW(ledStrip_, led1, color);
|
||||
setLedRGBW(ledStrip_, led2, color);
|
||||
}
|
||||
}
|
||||
currentPosition_ += speed_;
|
||||
currentPosition_ = std::min(currentPosition_, float(NUM_LEDS) / 2.0f + bellCurveWidth_ / 2);
|
||||
return DELAY_MS;
|
||||
}
|
||||
|
||||
//private:
|
||||
void getParams(float x, float &interpFac, float &brightness)
|
||||
{
|
||||
brightness = (x < bellCurveWidth_) ? bellCurveApproximation(bellCurveWidth_ / 2 - x, invBellCurveWidth_) : 1.0f;
|
||||
if (x < primaryColorWidth_)
|
||||
interpFac = 0.0f;
|
||||
else if (x > primaryColorWidth_ + transitionWidth_)
|
||||
interpFac = 1.0f;
|
||||
else
|
||||
interpFac = (x - primaryColorWidth_) * invTransitionWidth_;
|
||||
}
|
||||
|
||||
// x is positive distance from running front
|
||||
ColorRGBW getColor(float x)
|
||||
{
|
||||
float interpFac;
|
||||
float brightness;
|
||||
getParams(x, interpFac, brightness);
|
||||
ColorHSV result{
|
||||
interpFac * secondaryColor_.h + (1.0f - interpFac) * primaryColor_.h,
|
||||
interpFac * secondaryColor_.s + (1.0f - interpFac) * primaryColor_.s,
|
||||
interpFac * secondaryColor_.v + (1.0f - interpFac) * primaryColor_.v};
|
||||
result.v *= brightness;
|
||||
|
||||
const auto converted = hsv2rgb(result);
|
||||
//#ifndef PLATFORM_NATIVE
|
||||
// Serial.printf("Coord %f, interp %f, bright %f, h %f, s %f, v %f, r %d, g %d, b %d\n", x,
|
||||
// interpFac, brightness, result.h, result.s, result.v, converted.r,
|
||||
// converted.g, converted.b);
|
||||
//#endif
|
||||
return converted;
|
||||
}
|
||||
|
||||
TLedStrip &ledStrip_;
|
||||
|
||||
// in number of leds
|
||||
float currentPosition_;
|
||||
float transitionWidth_;
|
||||
float invTransitionWidth_;
|
||||
float primaryColorWidth_;
|
||||
float bellCurveWidth_;
|
||||
float invBellCurveWidth_;
|
||||
float speed_;
|
||||
|
||||
int startPosition_;
|
||||
|
||||
const ColorHSV primaryColor_;
|
||||
const ColorHSV secondaryColor_;
|
||||
};
|
||||
|
||||
// Traits
|
||||
template <>
|
||||
struct EffectIdToConfig<EffectId::ALEXA_SWIPE>
|
||||
{
|
||||
using type = EffectAlexaSwipeConfig;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct EffectConfigToId<EffectAlexaSwipeConfig>
|
||||
{
|
||||
static constexpr auto id = EffectId::ALEXA_SWIPE;
|
||||
};
|
||||
|
||||
template <typename TLedStrip>
|
||||
struct EffectIdToClass<EffectId::ALEXA_SWIPE, TLedStrip>
|
||||
{
|
||||
using type = EffectAlexaSwipe<TLedStrip>;
|
||||
};
|
||||
@@ -28,11 +28,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
static constexpr int normalizeIdx(int idx)
|
||||
{
|
||||
return (idx < 0) ? (idx + NUM_LEDS) : (idx >= NUM_LEDS ? idx - NUM_LEDS : idx);
|
||||
}
|
||||
|
||||
int operator()()
|
||||
{
|
||||
int startLed = int(currentPosition_);
|
||||
@@ -41,20 +36,20 @@ public:
|
||||
|
||||
clear(ledStrip_);
|
||||
// center
|
||||
setLedRGBW(ledStrip_, normalizeIdx(startLed),
|
||||
setLedRGBW(ledStrip_, startLed,
|
||||
config_.color * bellCurveApproximation(distDown, invWidth_));
|
||||
|
||||
// down
|
||||
for (int i = 1; i < widthInLeds_ / 2 + 1; ++i)
|
||||
{
|
||||
setLedRGBW(ledStrip_, normalizeIdx(startLed - i),
|
||||
setLedRGBW(ledStrip_, startLed - i,
|
||||
config_.color * bellCurveApproximation(distDown + i, invWidth_));
|
||||
}
|
||||
|
||||
// up
|
||||
for (int i = 1; i < widthInLeds_ / 2 + 1; ++i)
|
||||
{
|
||||
setLedRGBW(ledStrip_, normalizeIdx(startLed + i),
|
||||
setLedRGBW(ledStrip_, startLed + i,
|
||||
config_.color * bellCurveApproximation(distUp + i - 1, invWidth_));
|
||||
}
|
||||
|
||||
@@ -62,7 +57,6 @@ public:
|
||||
if (currentPosition_ > NUM_LEDS)
|
||||
currentPosition_ -= NUM_LEDS;
|
||||
|
||||
//Serial.printf("Current pos %f led %d width %d\n", currentPosition_, normalizeIdx(startLed), widthInLeds_ / 2 + 1);
|
||||
return DELAY_MS;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,7 @@ enum class EffectId
|
||||
{
|
||||
STATIC,
|
||||
CIRCULAR,
|
||||
CIRCLE_WAVE,
|
||||
COLOR_FADE,
|
||||
RAINBOW_FADE,
|
||||
ALEXA_SWIPE,
|
||||
};
|
||||
|
||||
template <EffectId id>
|
||||
|
||||
Reference in New Issue
Block a user