141 lines
3.8 KiB
C++
141 lines
3.8 KiB
C++
#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;
|
|
bool forward;
|
|
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))
|
|
{
|
|
if (cfg.forward)
|
|
{
|
|
currentPosition_ = 0;
|
|
direction_ = 1;
|
|
}
|
|
else
|
|
{
|
|
currentPosition_ = float(NUM_LEDS) / 2.0f + bellCurveWidth_ / 2;
|
|
direction_ = -1;
|
|
}
|
|
}
|
|
|
|
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);
|
|
setLedRGBW(ledStrip_, led1, color);
|
|
setLedRGBW(ledStrip_, led2, color);
|
|
}
|
|
}
|
|
currentPosition_ += direction_ * speed_;
|
|
currentPosition_ = std::min(currentPosition_, float(NUM_LEDS) / 2.0f + bellCurveWidth_ / 2);
|
|
currentPosition_ = std::max(currentPosition_, 0.0f);
|
|
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;
|
|
return hsv2rgb(result);
|
|
}
|
|
|
|
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_;
|
|
float direction_;
|
|
};
|
|
|
|
// 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>;
|
|
}; |