#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); while (endIdx_ < beginIdx_) endIdx_ += NUM_LEDS; } bool finished() const { return finished_; } int operator()() { if (finished_) return 1000000; const float progress = config_.transition_time_in_ms > 0.0f ? static_cast(DELAY_MS * calls_) / config_.transition_time_in_ms : 1.f; // Finished case if (config_.transition_time_in_ms <= 0.0f || progress >= 1.0) { finished_ = true; clear(ledStrip_); for (int i = beginIdx_; i < endIdx_; i += config_.increment) setLedRGBW(ledStrip_, i % NUM_LEDS, config_.color); return 10000000; } // In-progress case clear(ledStrip_); for (int i = beginIdx_; i < endIdx_; i += config_.increment) { const auto idx = i % NUM_LEDS; ColorRGBW newColor = ColorRGBW::interpolate(state_[idx], config_.color, progress); setLedRGBW(ledStrip_, idx, newColor); } ++calls_; return DELAY_MS; } private: static int int_interpolate(int prev, int next, float progress) { return static_cast(prev) * (1 - progress) + static_cast(next) * progress; } 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; };