FastLED 3.9.15
Loading...
Searching...
No Matches
complex.h
Go to the documentation of this file.
1
2
3/*
4This demo is best viewed using the FastLED compiler.
5
6Windows/MacOS binaries: https://github.com/FastLED/FastLED/releases
7
8Python
9
10Install: pip install fastled
11Run: fastled <this sketch directory>
12This will compile and preview the sketch in the browser, and enable
13all the UI elements you see below.
14*/
15
16#include <Arduino.h>
17#include <FastLED.h>
18
19#include "fl/gfx/draw_visitor.h"
20#include "fl/math/math.h"
21#include "fl/gfx/raster.h"
22#include "fl/math/time_alpha.h"
23#include "fl/ui/ui.h"
24#include "fl/gfx/xypath.h"
25#include "fl/fx/time.h"
26
27// Sketch.
28#include "src/wave.h"
29#include "src/xypaths.h"
30
31#include "fl/stl/cstring.h"
32
33#define HEIGHT 64
34#define WIDTH 64
35#define NUM_LEDS ((WIDTH) * (HEIGHT))
36#define IS_SERPINTINE true
37#define TIME_ANIMATION 1000 // ms
38
40
42// fl::XYPathPtr shape = XYPath::NewRosePath(WIDTH, HEIGHT);
43
44// Speed up writing to the super sampled waveFx by writing
45// to a raster. This will allow duplicate writes to be removed.
46
47fl::WaveEffect wave_fx; // init in setup().
49
50
53
54fl::XYPathPtr getShape(int which) {
55 int len = shapes.size();
56 which = which % len;
57 if (which < 0) {
58 which += len;
59 }
60 return shapes[which];
61}
62
64fl::UITitle title("XYPath Demo");
65fl::UIDescription description("Use a path on the WaveFx");
67fl::UISlider whichShape("Which Shape", 0.0f, 0.0f, shapes.size() - 1, 1.0f);
68fl::UICheckbox useWaveFx("Use WaveFX", true);
69fl::UISlider transition("Transition", 0.0f, 0.0f, 1.0f, 0.01f);
70
71fl::UISlider scale("Scale", 1.0f, 0.0f, 1.0f, 0.01f);
72fl::UISlider speed("Speed", 1.0f, -20.0f, 20.0f, 0.01f);
73fl::UISlider numberOfSteps("Number of Steps", 32.0f, 1.0f, 100.0f, 1.0f);
74fl::UISlider maxAnimation("Max Animation", 1.0f, 5.0f, 20.0f, 1.f);
75fl::UICheckbox isotropicStencil("Isotropic stencil (rounder ripples)", false);
76
78
80 speed.onChanged([](float value) { time_warp.setSpeed(speed.value()); });
81 maxAnimation.onChanged(
82 [](float value) { shapeProgress.set_max_clamp(maxAnimation.value()); });
83
84 trigger.onChanged([]() {
85 // shapeProgress.trigger(millis());
86 FL_WARN("Trigger pressed");
87 });
88 useWaveFx.onChanged([](bool on) {
89 if (on) {
90 FL_WARN("WaveFX enabled");
91 } else {
92 FL_WARN("WaveFX disabled");
93 }
94 });
95}
96
97void setup() {
98 Serial.begin(115200);
99 auto screenmap = xyMap.toScreenMap();
100 screenmap.setDiameter(.2);
101 FastLED.addLeds<NEOPIXEL, 2>(leds, NUM_LEDS).setScreenMap(screenmap);
103 // Initialize wave simulation. Please don't use static constructors, keep it
104 // in setup().
105 trigger.click();
107}
108
110
111float getAnimationTime(uint32_t now) {
112 float pointf = shapeProgress.updatef(now);
113 return pointf + transition.value();
114}
115
116void clearLeds() { fl::memset(leds, 0, NUM_LEDS * sizeof(fl::CRGB)); }
117
118void loop() {
119 // Your code here
120 clearLeds();
121 const uint32_t now = millis();
122 uint32_t now_warped = time_warp.update(now);
123
124 // Apply UI stencil choice to both wave layers.
128 wave_fx.wave_fx_low->setStencil(stencil);
129 wave_fx.wave_fx_high->setStencil(stencil);
130
131 auto shape = getShape(whichShape.as<int>());
132 shape->setScale(scale.value());
133
134 float curr_alpha = getAnimationTime(now_warped);
135 static float s_prev_alpha = 0.0f; // okay static in header
136
137 // unconditionally apply the circle.
138 if (trigger) {
139 // trigger the transition
140 time_warp.reset(now);
141 now_warped = time_warp.update(now);
142 shapeProgress.trigger(now_warped);
143 FL_WARN("Transition triggered on " << shape->name());
144 curr_alpha = getAnimationTime(now_warped);
145 s_prev_alpha = curr_alpha;
146 }
147
148 // FL_WARN("Current alpha: " << curr_alpha);
149 // FL_WARN("maxAnimation: " << maxAnimation.value());
150
151 const bool is_active =
152 true || curr_alpha < maxAnimation.value() && curr_alpha > 0.0f;
153
154 // if (shapeProgress.isActive(now)) {
155 static uint32_t frame = 0;
156 frame++;
157 clearLeds();
158 const fl::CRGB purple = fl::CRGB(255, 0, 255);
159 const int number_of_steps = numberOfSteps.value();
160 raster.reset();
161 // float factor = s_prev_alpha; // 0->1.f
162 // factor = fl::min(factor/4.0f, 0.05f);
163
164 float diff = curr_alpha - s_prev_alpha;
165 diff *= 1.0f;
166 float factor = fl::max(s_prev_alpha - diff, 0.f);
167
168 for (int i = 0; i < number_of_steps; ++i) {
169 float a =
170 fl::map_range<float>(i, 0, number_of_steps - 1, factor, curr_alpha);
171 if (a < .04) {
172 // shorter tails at first.
173 a = map_range<float>(a, 0.0f, .04f, 0.0f, .04f);
174 }
175 float diff_max_alpha = maxAnimation.value() - curr_alpha;
176 if (diff_max_alpha < 0.94) {
177 // shorter tails at the end.
178 a = map_range<float>(a, curr_alpha, maxAnimation.value(),
179 curr_alpha, maxAnimation.value());
180 }
181 uint8_t alpha =
182 fl::map_range<float>(i, 0.0f, number_of_steps - 1, 64, 255);
183 if (!is_active) {
184 alpha = 0;
185 }
186 fl::Tile2x2_u8 subpixel = shape->at_subpixel(a);
187 subpixel.scale(alpha);
188 // subpixels.push_back(subpixel);
189 raster.rasterize(subpixel);
190 }
191
192 s_prev_alpha = curr_alpha;
193
194
195 if (useWaveFx && is_active) {
196 fl::DrawRasterToWaveSimulator draw_wave_fx(&wave_fx);
197 raster.draw(xyMap, draw_wave_fx);
198 } else {
199 raster.draw(purple, xyMap, leds);
200 }
201
202 int first = xyMap(1, 1);
203 int last = xyMap(WIDTH - 2, HEIGHT - 2);
204
205 leds[first] = fl::CRGB(255, 0, 0);
206 leds[last] = fl::CRGB(0, 255, 0);
207 if (useWaveFx) {
208 // fxBlend.draw(fl::Fx::DrawContext(now, leds));
209 wave_fx.draw(fl::Fx::DrawContext(now, leds));
210 }
211
212 EVERY_N_SECONDS(1) {
213 uint32_t frame_time = millis() - now;
214 FL_WARN("Frame time: " << frame_time << "ms");
215 }
216
217 FastLED.show();
218}
fl::XYMap xyMap
#define NUM_LEDS
fl::UIDescription description("Demo of the Animatrix effects. @author of fx is StefanPetrick")
fl::UITitle title("Animartrix")
fl::CRGB leds[NUM_LEDS]
fl::ScreenMap screenmap
#define IS_SERPINTINE
Definition simple.h:49
#define TIME_ANIMATION
Definition simple.h:50
WaveEffect NewWaveSimulation2D(const fl::XYMap &xymap)
Definition wave.cpp:42
fl::vector< fl::XYPathPtr > CreateXYPaths(int width, int height)
Definition xypaths.cpp:29
FL_DISABLE_WARNING_PUSH FL_DISABLE_WARNING_GLOBAL_CONSTRUCTORS CFastLED FastLED
Global LED strip management instance.
fl::UISlider scale("Scale", 4,.1, 4,.1)
uint16_t speed
Definition Noise.ino:66
#define WIDTH
#define HEIGHT
::fl::DrawContext DrawContext
Definition fx.h:21
void scale(u8 scale)
fl::XYPathPtr getShape(int which)
Definition complex.h:54
fl::UICheckbox useWaveFx("Use WaveFX", true)
void setup()
Definition complex.h:97
fl::XYRaster raster(WIDTH, HEIGHT)
void clearLeds()
Definition complex.h:116
fl::UISlider transition("Transition", 0.0f, 0.0f, 1.0f, 0.01f)
fl::UIButton trigger("Trigger")
void setupUiCallbacks()
Definition complex.h:79
fl::TimeClampedTransition shapeProgress(TIME_ANIMATION)
float getAnimationTime(uint32_t now)
Definition complex.h:111
fl::UISlider maxAnimation("Max Animation", 1.0f, 5.0f, 20.0f, 1.f)
fl::UICheckbox isotropicStencil("Isotropic stencil (rounder ripples)", false)
fl::UISlider whichShape("Which Shape", 0.0f, 0.0f, shapes.size() - 1, 1.0f)
fl::UISlider numberOfSteps("Number of Steps", 32.0f, 1.0f, 100.0f, 1.0f)
void loop()
Definition complex.h:118
fl::UICheckbox useWaveFx("Use WaveFX", true)
fl::XYRaster raster(WIDTH, HEIGHT)
fl::vector< fl::XYPathPtr > shapes
Definition Downscale.h:49
fl::UISlider transition("Transition", 0.0f, 0.0f, 1.0f, 0.01f)
fl::TimeWarp time_warp
Definition Downscale.h:52
fl::UIButton trigger("Trigger")
WaveEffect wave_fx
Definition Downscale.h:48
fl::TimeClampedTransition shapeProgress(TIME_ANIMATION)
fl::UISlider maxAnimation("Max Animation", 1.0f, 5.0f, 20.0f, 1.f)
fl::UICheckbox isotropicStencil("Isotropic stencil (rounder ripples)", false)
fl::UISlider whichShape("Which Shape", 0.0f, 0.0f, shapes.size() - 1, 1.0f)
fl::UISlider numberOfSteps("Number of Steps", 32.0f, 1.0f, 100.0f, 1.0f)
#define EVERY_N_SECONDS(N)
Checks whether to execute a block of code every N seconds.
Definition lib8tion.h:1010
#define FL_WARN(X)
Definition log.h:276
fl::CRGB CRGB
Definition video.h:15
constexpr common_type_t< T, U > max(T a, U b) FL_NOEXCEPT
Definition math.h:75
XYRasterU8Sparse XYRaster
Definition raster.h:8
FASTLED_FORCE_INLINE U map_range(T value, T in_min, T in_max, U out_min, U out_max) FL_NOEXCEPT
Definition math.h:174
void * memset(void *s, int c, size_t n) FL_NOEXCEPT
Representation of an 8-bit RGB pixel (Red, Green, Blue)
Definition crgb.h:38
#define Serial
Definition serial.h:304
Aggregator header for the fl/ui/ family of per-element UI types.