#pragma once #include "effects/Common.h" #include "helpers/ColorRGBW.h" #include "helpers/ColorConversions.h" #pragma pack(push, 1) struct EffectStaticDetailedConfig { EffectStaticDetailedConfig(const ColorRGBW &c = ColorRGBW{0, 0, 0, 0}, uint16_t beg = 0, uint16_t en = 0) : color(c), begin(beg), end(en) {} ColorRGBW color; uint16_t increment = 1; float begin = 0.0f; float end = 0.0f; float transition_time_in_ms = 0.0f; }; #pragma pack(pop) template class EffectStaticDetailed { public: static constexpr auto NUM_LEDS = numLeds(); static constexpr int DELAY_MS = 10; using ConfigType = EffectStaticDetailedConfig; EffectStaticDetailed(const EffectStaticDetailedConfig &cfg, TLedStrip &ledStrip) : config_(cfg), ledStrip_(ledStrip) { for (int i = 0; i < NUM_LEDS; ++i) state_[i] = getLedRGBW(ledStrip_, i); beginIdx_ = constrain(static_cast(cfg.begin * NUM_LEDS + 0.5f), 0, NUM_LEDS - 1); endIdx_ = constrain(static_cast(cfg.end * NUM_LEDS + 0.5f), 0, NUM_LEDS - 1); } bool finished() const { return finished_; } int operator()() { if (finished_) return 1000000; const float progress = static_cast(DELAY_MS * calls_) / config_.transition_time_in_ms; // Finished case if(progress > 1.0) { finished_ = true; return 10000000; } // In-progress case clear(ledStrip_); for(int i = beginIdx_; i != endIdx_; i += config_.increment) { ColorRGBW newColor = hsv2rgb(interpolate(rgb2hsv(state_[i]), rgb2hsv(config_.color), progress)); newColor.w = config_.color.w * progress + state_[i].w * (1 - progress); setLedRGBW(ledStrip_, i, newColor); if(i >= NUM_LEDS) i = 0; } ++calls_; return DELAY_MS; } private: EffectStaticDetailedConfig config_; TLedStrip &ledStrip_; ColorRGBW state_[NUM_LEDS]; int beginIdx_; int endIdx_; int calls_ = 0; bool finished_ = false; }; // Traits template <> struct EffectIdToConfig { using type = EffectStaticDetailedConfig; }; template <> struct EffectConfigToId { static constexpr auto id = EffectId::STATIC_DETAILED; }; template struct EffectIdToClass { using type = EffectStaticDetailed; };