#pragma once #include "effects/Common.h" #include "helpers/ColorRGBW.h" #include "helpers/BellCurve.h" struct EffectCircularConfig { float speed; // in degrees per second float width; // width in degrees ColorRGBW color; }; template class EffectCircular { public: static constexpr auto NUM_LEDS = numLeds(); static constexpr int DELAY_MS = 10; using ConfigType = EffectCircularConfig; EffectCircular(const EffectCircularConfig &cfg, TLedStrip &ledStrip) : config_(cfg), ledStrip_(ledStrip), currentPosition_(0), widthInLeds_((numLeds(ledStrip) * cfg.width / 360)), invWidth_(1.0f / widthInLeds_) { } int operator()() { int startLed = int(currentPosition_); float distDown = currentPosition_ - float(startLed); float distUp = 1.f - distDown; clear(ledStrip_); // center setLedRGBW(ledStrip_, startLed, config_.color * bellCurveApproximation(distDown, invWidth_)); // down for (int i = 1; i < widthInLeds_ / 2 + 1; ++i) { setLedRGBW(ledStrip_, startLed - i, config_.color * bellCurveApproximation(distDown + i, invWidth_)); } // up for (int i = 1; i < widthInLeds_ / 2 + 1; ++i) { setLedRGBW(ledStrip_, startLed + i, config_.color * bellCurveApproximation(distUp + i - 1, invWidth_)); } currentPosition_ += config_.speed / 1000 / 360 * NUM_LEDS * DELAY_MS; if (currentPosition_ > NUM_LEDS) currentPosition_ -= NUM_LEDS; return DELAY_MS; } private: EffectCircularConfig config_; TLedStrip &ledStrip_; float currentPosition_; // between 0 and num leds int widthInLeds_; float invWidth_; }; // Traits template <> struct EffectIdToConfig { using type = EffectCircularConfig; }; template <> struct EffectConfigToId { static constexpr auto id = EffectId::CIRCULAR; }; template struct EffectIdToClass { using type = EffectCircular; };