mirror of
https://github.com/wled/WLED.git
synced 2025-04-20 12:57:19 +00:00
Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
353868414a | ||
![]() |
c661d8f5b7 | ||
![]() |
b941654a68 |
@ -7998,7 +7998,7 @@ uint16_t mode_particlefire(void) {
|
||||
uint32_t i; // index variable
|
||||
uint32_t numFlames; // number of flames: depends on fire width. for a fire width of 16 pixels, about 25-30 flames give good results
|
||||
|
||||
if (SEGMENT.call == 0) { // initialization TODO: make this a PSinit function, this is needed in every particle FX but first, get this working.
|
||||
if (SEGMENT.call == 0) { // initialization
|
||||
if (!initParticleSystem2D(PartSys, SEGMENT.virtualWidth(), 4)) //maximum number of source (PS may limit based on segment size); need 4 additional bytes for time keeping (uint32_t lastcall)
|
||||
return mode_static(); // allocation failed or not 2D
|
||||
SEGENV.aux0 = hw_random16(); // aux0 is wind position (index) in the perlin noise
|
||||
@ -8090,7 +8090,7 @@ uint16_t mode_particlepit(void) {
|
||||
ParticleSystem2D *PartSys = nullptr;
|
||||
|
||||
if (SEGMENT.call == 0) { // initialization
|
||||
if (!initParticleSystem2D(PartSys, 1, 0, true, false)) // init, request one source (actually dont really need one TODO: test if using zero sources also works)
|
||||
if (!initParticleSystem2D(PartSys, 0, 0, true, false)) // init
|
||||
return mode_static(); // allocation failed or not 2D
|
||||
PartSys->setKillOutOfBounds(true);
|
||||
PartSys->setGravity(); // enable with default gravity
|
||||
@ -8161,7 +8161,7 @@ uint16_t mode_particlewaterfall(void) {
|
||||
uint8_t numSprays;
|
||||
uint32_t i = 0;
|
||||
|
||||
if (SEGMENT.call == 0) { // initialization TODO: make this a PSinit function, this is needed in every particle FX but first, get this working.
|
||||
if (SEGMENT.call == 0) { // initialization
|
||||
if (!initParticleSystem2D(PartSys, 12)) // init, request 12 sources, no additional data needed
|
||||
return mode_static(); // allocation failed or not 2D
|
||||
|
||||
@ -8184,7 +8184,7 @@ uint16_t mode_particlewaterfall(void) {
|
||||
else
|
||||
PartSys = reinterpret_cast<ParticleSystem2D *>(SEGENV.data); // if not first call, just set the pointer to the PS
|
||||
if (PartSys == nullptr)
|
||||
return mode_static(); // something went wrong, no data! (TODO: ask how to handle this so it always works)
|
||||
return mode_static(); // something went wrong, no data!
|
||||
|
||||
// Particle System settings
|
||||
PartSys->updateSystem(); // update system properties (dimensions and data pointers)
|
||||
@ -8313,7 +8313,7 @@ uint16_t mode_particleperlin(void) {
|
||||
ParticleSystem2D *PartSys = nullptr;
|
||||
uint32_t i;
|
||||
|
||||
if (SEGMENT.call == 0) { // initialization TODO: make this a PSinit function, this is needed in every particle FX but first, get this working.
|
||||
if (SEGMENT.call == 0) { // initialization
|
||||
if (!initParticleSystem2D(PartSys, 1, 0, true)) // init with 1 source and advanced properties
|
||||
return mode_static(); // allocation failed or not 2D
|
||||
|
||||
@ -8374,20 +8374,19 @@ static const char _data_FX_MODE_PARTICLEPERLIN[] PROGMEM = "PS Fuzzy Noise@Speed
|
||||
uint16_t mode_particleimpact(void) {
|
||||
ParticleSystem2D *PartSys = nullptr;
|
||||
uint32_t i = 0;
|
||||
uint8_t MaxNumMeteors;
|
||||
uint32_t numMeteors;
|
||||
PSsettings2D meteorsettings;
|
||||
meteorsettings.asByte = 0b00101000; // PS settings for meteors: bounceY and gravity enabled
|
||||
|
||||
if (SEGMENT.call == 0) { // initialization TODO: make this a PSinit function, this is needed in every particle FX but first, get this working.
|
||||
if (SEGMENT.call == 0) { // initialization
|
||||
if (!initParticleSystem2D(PartSys, NUMBEROFSOURCES)) // init, no additional data needed
|
||||
return mode_static(); // allocation failed or not 2D
|
||||
PartSys->setKillOutOfBounds(true);
|
||||
PartSys->setGravity(); // enable default gravity
|
||||
PartSys->setBounceY(true); // always use ground bounce
|
||||
PartSys->setWallRoughness(220); // high roughness
|
||||
MaxNumMeteors = min(PartSys->numSources, (uint32_t)NUMBEROFSOURCES);
|
||||
for (i = 0; i < MaxNumMeteors; i++) {
|
||||
// PartSys->sources[i].source.y = 500;
|
||||
numMeteors = min(PartSys->numSources, (uint32_t)NUMBEROFSOURCES);
|
||||
for (i = 0; i < numMeteors; i++) {
|
||||
PartSys->sources[i].source.ttl = hw_random16(10 * i); // set initial delay for meteors
|
||||
PartSys->sources[i].source.vy = 10; // at positive speeds, no particles are emitted and if particle dies, it will be relaunched
|
||||
}
|
||||
@ -8396,7 +8395,7 @@ uint16_t mode_particleimpact(void) {
|
||||
PartSys = reinterpret_cast<ParticleSystem2D *>(SEGENV.data); // if not first call, just set the pointer to the PS
|
||||
|
||||
if (PartSys == nullptr)
|
||||
return mode_static(); // something went wrong, no data! (TODO: ask how to handle this so it always works)
|
||||
return mode_static(); // something went wrong, no data!
|
||||
|
||||
// Particle System settings
|
||||
PartSys->updateSystem(); // update system properties (dimensions and data pointers)
|
||||
@ -8406,29 +8405,18 @@ uint16_t mode_particleimpact(void) {
|
||||
uint8_t hardness = map(SEGMENT.custom2, 0, 255, PS_P_MINSURFACEHARDNESS - 2, 255);
|
||||
PartSys->setWallHardness(hardness);
|
||||
PartSys->enableParticleCollisions(SEGMENT.check3, hardness); // enable collisions and set particle collision hardness
|
||||
MaxNumMeteors = min(PartSys->numSources, (uint32_t)NUMBEROFSOURCES);
|
||||
uint8_t numMeteors = MaxNumMeteors; // TODO: clean this up map(SEGMENT.custom3, 0, 31, 1, MaxNumMeteors); // number of meteors to use for animation
|
||||
|
||||
numMeteors = min(PartSys->numSources, (uint32_t)NUMBEROFSOURCES);
|
||||
uint32_t emitparticles; // number of particles to emit for each rocket's state
|
||||
|
||||
for (i = 0; i < numMeteors; i++) {
|
||||
// determine meteor state by its speed:
|
||||
if ( PartSys->sources[i].source.vy < 0) { // moving down, emit sparks
|
||||
#ifdef ESP8266
|
||||
if ( PartSys->sources[i].source.vy < 0) // moving down, emit sparks
|
||||
emitparticles = 1;
|
||||
#else
|
||||
emitparticles = 2;
|
||||
#endif
|
||||
}
|
||||
else if ( PartSys->sources[i].source.vy > 0) // moving up means meteor is on 'standby'
|
||||
emitparticles = 0;
|
||||
else { // speed is zero, explode!
|
||||
PartSys->sources[i].source.vy = 10; // set source speed positive so it goes into timeout and launches again
|
||||
#ifdef ESP8266
|
||||
emitparticles = hw_random16(SEGMENT.intensity >> 3) + 5; // defines the size of the explosion
|
||||
#else
|
||||
emitparticles = map(SEGMENT.intensity, 0, 255, 10, hw_random16(PartSys->usedParticles>>2)); // defines the size of the explosion !!!TODO: check if this works on ESP8266, drop esp8266 def if it does
|
||||
#endif
|
||||
emitparticles = map(SEGMENT.intensity, 0, 255, 10, hw_random16(PartSys->usedParticles>>2)); // defines the size of the explosion
|
||||
}
|
||||
for (int e = emitparticles; e > 0; e--) {
|
||||
PartSys->sprayEmit(PartSys->sources[i]);
|
||||
@ -8449,13 +8437,13 @@ uint16_t mode_particleimpact(void) {
|
||||
PartSys->sources[i].source.vx = 0;
|
||||
PartSys->sources[i].sourceFlags.collide = true;
|
||||
#ifdef ESP8266
|
||||
PartSys->sources[i].maxLife = 180;
|
||||
PartSys->sources[i].minLife = 20;
|
||||
PartSys->sources[i].maxLife = 900;
|
||||
PartSys->sources[i].minLife = 100;
|
||||
#else
|
||||
PartSys->sources[i].maxLife = 250;
|
||||
PartSys->sources[i].minLife = 50;
|
||||
PartSys->sources[i].maxLife = 1250;
|
||||
PartSys->sources[i].minLife = 250;
|
||||
#endif
|
||||
PartSys->sources[i].source.ttl = hw_random16((512 - (SEGMENT.speed << 1))) + 40; // standby time til next launch (in frames)
|
||||
PartSys->sources[i].source.ttl = hw_random16((768 - (SEGMENT.speed << 1))) + 40; // standby time til next launch (in frames)
|
||||
PartSys->sources[i].vy = (SEGMENT.custom1 >> 2); // emitting speed y
|
||||
PartSys->sources[i].var = (SEGMENT.custom1 >> 2); // speed variation around vx,vy (+/- var)
|
||||
}
|
||||
@ -8470,13 +8458,17 @@ uint16_t mode_particleimpact(void) {
|
||||
PartSys->sources[i].source.hue = hw_random16(); // random color
|
||||
PartSys->sources[i].source.ttl = 500; // long life, will explode at bottom
|
||||
PartSys->sources[i].sourceFlags.collide = false; // trail particles will not collide
|
||||
PartSys->sources[i].maxLife = 60; // spark particle life
|
||||
PartSys->sources[i].minLife = 20;
|
||||
PartSys->sources[i].maxLife = 300; // spark particle life
|
||||
PartSys->sources[i].minLife = 100;
|
||||
PartSys->sources[i].vy = -9; // emitting speed (down)
|
||||
PartSys->sources[i].var = 3; // speed variation around vx,vy (+/- var)
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < PartSys->usedParticles; i++) {
|
||||
if (PartSys->particles[i].ttl > 5) PartSys->particles[i].ttl -= 5; //ttl is linked to brightness, this allows to use higher brightness but still a short spark lifespan
|
||||
}
|
||||
|
||||
PartSys->update(); // update and render
|
||||
return FRAMETIME;
|
||||
}
|
||||
@ -8880,7 +8872,7 @@ uint16_t mode_particleghostrider(void) {
|
||||
// emit two particles
|
||||
PartSys->angleEmit(PartSys->sources[0], emitangle, speed);
|
||||
PartSys->angleEmit(PartSys->sources[0], emitangle, speed);
|
||||
if (SEGMENT.call % (11 - (SEGMENT.custom2 / 25)) == 0) { // every nth frame, cycle color and emit particles //TODO: make this a segment call % SEGMENT.custom2 for better control
|
||||
if (SEGMENT.call % (11 - (SEGMENT.custom2 / 25)) == 0) { // every nth frame, cycle color and emit particles
|
||||
PartSys->sources[0].source.hue++;
|
||||
}
|
||||
if (SEGMENT.custom2 > 190) //fast color change
|
||||
@ -8900,7 +8892,7 @@ uint16_t mode_particleblobs(void) {
|
||||
ParticleSystem2D *PartSys = nullptr;
|
||||
|
||||
if (SEGMENT.call == 0) {
|
||||
if (!initParticleSystem2D(PartSys, 1, 0, true, true)) //init, request one source, no additional bytes, advanced size & size control (actually dont really need one TODO: test if using zero sources also works)
|
||||
if (!initParticleSystem2D(PartSys, 0, 0, true, true)) //init, no additional bytes, advanced size & size control
|
||||
return mode_static(); // allocation failed or not 2D
|
||||
PartSys->setBounceX(true);
|
||||
PartSys->setBounceY(true);
|
||||
@ -9521,8 +9513,8 @@ uint16_t mode_particleHourglass(void) {
|
||||
|
||||
uint32_t colormode = SEGMENT.custom1 >> 5; // 0-7
|
||||
|
||||
if ((SEGMENT.intensity | (PartSys->getAvailableParticles() << 8)) != *settingTracker) { // initialize, getAvailableParticles changes while in FX transition
|
||||
*settingTracker = SEGMENT.intensity | (PartSys->getAvailableParticles() << 8);
|
||||
if (SEGMENT.intensity != *settingTracker) { // initialize
|
||||
*settingTracker = SEGMENT.intensity;
|
||||
for (uint32_t i = 0; i < PartSys->usedParticles; i++) {
|
||||
PartSys->particleFlags[i].reversegrav = true; // resting particles dont fall
|
||||
*direction = 0; // down
|
||||
@ -9569,7 +9561,7 @@ uint16_t mode_particleHourglass(void) {
|
||||
}
|
||||
|
||||
// re-order particles in case collisions flipped particles (highest number index particle is on the "bottom")
|
||||
for (int i = 0; i < PartSys->usedParticles - 1; i++) {
|
||||
for (uint32_t i = 0; i < PartSys->usedParticles - 1; i++) {
|
||||
if (PartSys->particles[i].x < PartSys->particles[i+1].x && PartSys->particleFlags[i].fixed == false && PartSys->particleFlags[i+1].fixed == false) {
|
||||
std::swap(PartSys->particles[i].x, PartSys->particles[i+1].x);
|
||||
}
|
||||
@ -9680,10 +9672,7 @@ uint16_t mode_particleBalance(void) {
|
||||
if (SEGMENT.call == 0) { // initialization
|
||||
if (!initParticleSystem1D(PartSys, 1, 128)) // init, no additional data needed, use half of max particles
|
||||
return mode_static(); // allocation failed or is single pixel
|
||||
//PartSys->setKillOutOfBounds(true);
|
||||
PartSys->setParticleSize(1);
|
||||
SEGENV.aux0 = 0;
|
||||
SEGENV.aux1 = 0; //TODO: really need to set to zero or is it calloc'd?
|
||||
}
|
||||
else
|
||||
PartSys = reinterpret_cast<ParticleSystem1D *>(SEGENV.data); // if not first call, just set the pointer to the PS
|
||||
@ -9777,7 +9766,7 @@ uint16_t mode_particleChase(void) {
|
||||
uint32_t numParticles = 1 + map(SEGMENT.intensity, 0, 255, 2, 255 / (1 + (SEGMENT.custom1 >> 6))); // depends on intensity and particle size (custom1), minimum 1
|
||||
numParticles = min(numParticles, PartSys->usedParticles); // limit to available particles
|
||||
int32_t huestep = 1 + ((((uint32_t)SEGMENT.custom2 << 19) / numParticles) >> 16); // hue increment
|
||||
uint32_t settingssum = SEGMENT.speed + SEGMENT.intensity + SEGMENT.custom1 + SEGMENT.custom2 + SEGMENT.check1 + SEGMENT.check2 + SEGMENT.check3 + PartSys->getAvailableParticles(); // note: getAvailableParticles is used to enforce update during transitions
|
||||
uint32_t settingssum = SEGMENT.speed + SEGMENT.intensity + SEGMENT.custom1 + SEGMENT.custom2 + SEGMENT.check1 + SEGMENT.check2 + SEGMENT.check3;
|
||||
if (SEGENV.aux0 != settingssum) { // settings changed changed, update
|
||||
if (SEGMENT.check1)
|
||||
SEGENV.step = PartSys->advPartProps[0].size / 2 + (PartSys->maxX / numParticles);
|
||||
@ -9835,7 +9824,7 @@ uint16_t mode_particleChase(void) {
|
||||
globalhuestep = 2; // global hue change to add some color variation
|
||||
if ((SEGMENT.call & 0x1F) == 0)
|
||||
SEGENV.step += *stepdir; // change density
|
||||
for(int32_t i = 0; i < PartSys->usedParticles; i++) {
|
||||
for(uint32_t i = 0; i < PartSys->usedParticles; i++) {
|
||||
PartSys->particles[i].hue -= globalhuestep; // shift global hue (both directions)
|
||||
PartSys->particles[i].vx = 1 + (SEGMENT.speed >> 2) + ((int32_t(sin16_t(strip.now >> 1) + 32767) * (SEGMENT.speed >> 2)) >> 16);
|
||||
}
|
||||
@ -10007,7 +9996,7 @@ uint16_t mode_particleFire1D(void) {
|
||||
PartSys->setColorByAge(true);
|
||||
uint32_t emitparticles = 1;
|
||||
uint32_t j = hw_random16();
|
||||
for (uint i = 0; i < 3; i++) { // 3 base flames TODO: check if this is ok or needs adjustments
|
||||
for (uint i = 0; i < 3; i++) { // 3 base flames
|
||||
if (PartSys->sources[i].source.ttl > 50)
|
||||
PartSys->sources[i].source.ttl -= 10; // TODO: in 2D making the source fade out slow results in much smoother flames, need to check if it can be done the same
|
||||
else
|
||||
@ -10028,7 +10017,7 @@ uint16_t mode_particleFire1D(void) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
PartSys->sources[j].minLife = PartSys->sources[j].source.ttl + SEGMENT.intensity; // TODO: in 2D, emitted particle ttl depends on source TTL, mimic here the same way? OR: change 2D to the same way it is done here and ditch special fire treatment in emit?
|
||||
PartSys->sources[j].minLife = PartSys->sources[j].source.ttl + SEGMENT.intensity;
|
||||
PartSys->sources[j].maxLife = PartSys->sources[j].minLife + 50;
|
||||
PartSys->sources[j].v = SEGMENT.speed >> 2;
|
||||
if (SEGENV.call & 0x01) // every second frame
|
||||
@ -10266,7 +10255,7 @@ uint16_t mode_particleSpringy(void) {
|
||||
int32_t springlength = PartSys->maxX / (PartSys->usedParticles); // spring length (spacing between particles)
|
||||
int32_t springK = map(SEGMENT.speed, 0, 255, 5, 35); // spring constant (stiffness)
|
||||
|
||||
uint32_t settingssum = SEGMENT.custom1 + SEGMENT.check2 + PartSys->getAvailableParticles(); // note: getAvailableParticles is used to enforce update during transitions
|
||||
uint32_t settingssum = SEGMENT.custom1 + SEGMENT.check2;
|
||||
if (SEGENV.aux0 != settingssum) { // number of particles changed, update distribution
|
||||
for (int32_t i = 0; i < (int32_t)PartSys->usedParticles; i++) {
|
||||
PartSys->advPartProps[i].sat = 255; // full saturation
|
||||
@ -10289,7 +10278,7 @@ uint16_t mode_particleSpringy(void) {
|
||||
PartSys->particles[0].x = dxlimit; // limit the spring length
|
||||
springforce[0] += ((springlength >> 1) - (PartSys->particles[0].x)) * springK; // first particle anchors to x=0
|
||||
|
||||
for (int32_t i = 1; i < PartSys->usedParticles; i++) {
|
||||
for (uint32_t i = 1; i < PartSys->usedParticles; i++) {
|
||||
// reorder particles if they are out of order to prevent chaos
|
||||
if (PartSys->particles[i].x < PartSys->particles[i-1].x)
|
||||
std::swap(PartSys->particles[i].x, PartSys->particles[i-1].x); // swap particle positions to maintain order
|
||||
@ -10310,7 +10299,7 @@ uint16_t mode_particleSpringy(void) {
|
||||
}
|
||||
// apply spring forces to particles
|
||||
bool dampenoscillations = (SEGMENT.call % (9 - (SEGMENT.speed >> 5))) == 0; // dampen oscillation if particles are slow, more damping on stiffer springs
|
||||
for (int32_t i = 0; i < PartSys->usedParticles; i++) {
|
||||
for (uint32_t i = 0; i < PartSys->usedParticles; i++) {
|
||||
springforce[i] = springforce[i] / 64; // scale spring force (cannot use shifts because of negative values)
|
||||
int maxforce = 120; // limit spring force
|
||||
springforce[i] = springforce[i] > maxforce ? maxforce : springforce[i] < -maxforce ? -maxforce : springforce[i]; // limit spring force
|
||||
@ -10327,7 +10316,7 @@ uint16_t mode_particleSpringy(void) {
|
||||
PartSys->applyFriction((SEGMENT.intensity >> 2));
|
||||
|
||||
// add a small resetting force so particles return to resting position even under high damping
|
||||
for (int32_t i = 1; i < PartSys->usedParticles - 1; i++) {
|
||||
for (uint32_t i = 1; i < PartSys->usedParticles - 1; i++) {
|
||||
int restposition = (springlength >> 1) + i * springlength; // resting position
|
||||
int dx = restposition - PartSys->particles[i].x; // distance, always positive
|
||||
PartSys->applyForce(PartSys->particles[i], dx > 0 ? 1 : (dx < 0 ? -1 : 0), PartSys->advPartProps[i].forcecounter);
|
||||
@ -10377,7 +10366,7 @@ uint16_t mode_particleSpringy(void) {
|
||||
}
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < PartSys->usedParticles; i++) {
|
||||
for (uint32_t i = 0; i < PartSys->usedParticles; i++) {
|
||||
if (SEGMENT.custom2 == 255) { // map speed to hue
|
||||
int speedclr = ((int8_t(abs(PartSys->particles[i].vx))) >> 2) << 4; // scale for greater color variation, dump small values to avoid flickering
|
||||
//int speed = PartSys->particles[i].vx << 2; // +/- 512
|
||||
|
@ -1665,9 +1665,6 @@ void WS2812FX::service() {
|
||||
_segment_index++;
|
||||
}
|
||||
Segment::setClippingRect(0, 0); // disable clipping for overlays
|
||||
#if !(defined(WLED_DISABLE_PARTICLESYSTEM2D) && defined(WLED_DISABLE_PARTICLESYSTEM1D))
|
||||
servicePSmem(); // handle segment particle system memory
|
||||
#endif
|
||||
_isServicing = false;
|
||||
_triggered = false;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -30,28 +30,6 @@
|
||||
#define PSPRINTLN(x)
|
||||
#endif
|
||||
|
||||
// memory and transition manager
|
||||
struct partMem {
|
||||
void* particleMemPointer; // pointer to particle memory
|
||||
uint32_t buffersize; // buffer size in bytes
|
||||
uint8_t particleType; // type of particles currently in memory: 0 = none, particle struct size otherwise (required for 1D<->2D transitions)
|
||||
uint8_t id; // ID of segment this memory belongs to
|
||||
uint8_t watchdog; // counter to handle deallocation
|
||||
uint8_t inTransition; // to track PS to PS FX transitions (is set to new FX ID during transitions), not set if not both FX are PS FX
|
||||
uint8_t currentFX; // current FX ID, is set when transition is complete, used to detect back and forth transitions
|
||||
bool finalTransfer; // used to update buffer in rendering function after transition has ended
|
||||
bool transferParticles; // if set, particles in buffer are transferred to new FX
|
||||
};
|
||||
|
||||
void* particleMemoryManager(const uint32_t requestedParticles, size_t structSize, uint32_t &availableToPS, uint32_t numParticlesUsed, const uint8_t effectID); // update particle memory pointer, handles memory transitions
|
||||
void particleHandover(void *buffer, size_t structSize, int32_t numParticles);
|
||||
void updateUsedParticles(const uint32_t allocated, const uint32_t available, const uint8_t percentage, uint32_t &used);
|
||||
bool segmentIsOverlay(void); // check if segment is fully overlapping with at least one underlying segment
|
||||
partMem* getPartMem(void); // returns pointer to memory struct for current segment or nullptr
|
||||
void updateRenderingBuffer(uint32_t requiredpixels, bool isFramebuffer, bool initialize); // allocate CRGB rendering buffer, update size if needed
|
||||
void transferBuffer(uint32_t width, uint32_t height, bool useAdditiveTransfer = false); // transfer the buffer to the segment (supports 1D and 2D)
|
||||
void servicePSmem(); // increments watchdog, frees memory if idle too long
|
||||
|
||||
// limit speed of particles (used in 1D and 2D)
|
||||
static inline int32_t limitSpeed(const int32_t speed) {
|
||||
return speed > PS_P_MAXSPEED ? PS_P_MAXSPEED : (speed < -PS_P_MAXSPEED ? -PS_P_MAXSPEED : speed); // note: this is slightly faster than using min/max at the cost of 50bytes of flash
|
||||
@ -60,7 +38,7 @@ static inline int32_t limitSpeed(const int32_t speed) {
|
||||
|
||||
#ifndef WLED_DISABLE_PARTICLESYSTEM2D
|
||||
// memory allocation
|
||||
#define ESP8266_MAXPARTICLES 300 // enough up to 20x20 pixels
|
||||
#define ESP8266_MAXPARTICLES 256 // enough up to 16x16 pixels
|
||||
#define ESP8266_MAXSOURCES 24
|
||||
#define ESP32S2_MAXPARTICLES 1024 // enough up to 32x32 pixels
|
||||
#define ESP32S2_MAXSOURCES 64
|
||||
@ -178,7 +156,6 @@ public:
|
||||
void pointAttractor(const uint32_t particleindex, PSparticle &attractor, const uint8_t strength, const bool swallow);
|
||||
// set options note: inlining the set function uses more flash so dont optimize
|
||||
void setUsedParticles(const uint8_t percentage); // set the percentage of particles used in the system, 255=100%
|
||||
inline uint32_t getAvailableParticles(void) { return availableParticles; } // available particles in the buffer, use this to check if buffer changed during FX init
|
||||
void setCollisionHardness(const uint8_t hardness); // hardness for particle collisions (255 means full hard)
|
||||
void setWallHardness(const uint8_t hardness); // hardness for bouncing on the wall if bounceXY is set
|
||||
void setWallRoughness(const uint8_t roughness); // wall roughness randomizes wall collisions
|
||||
@ -210,12 +187,12 @@ public:
|
||||
|
||||
private:
|
||||
//rendering functions
|
||||
void ParticleSys_render();
|
||||
void render();
|
||||
[[gnu::hot]] void renderParticle(const uint32_t particleindex, const uint8_t brightness, const CRGB& color, const bool wrapX, const bool wrapY);
|
||||
//paricle physics applied by system if flags are set
|
||||
void applyGravity(); // applies gravity to all particles
|
||||
void handleCollisions();
|
||||
[[gnu::hot]] void collideParticles(PSparticle &particle1, PSparticle &particle2, const int32_t dx, const int32_t dy, const int32_t collDistSq);
|
||||
[[gnu::hot]] void collideParticles(PSparticle &particle1, PSparticle &particle2, const int32_t dx, const int32_t dy, const uint32_t collDistSq);
|
||||
void fireParticleupdate();
|
||||
//utility functions
|
||||
void updatePSpointers(const bool isadvanced, const bool sizecontrol); // update the data pointers to current segment data space
|
||||
@ -223,9 +200,9 @@ private:
|
||||
void getParticleXYsize(PSadvancedParticle *advprops, PSsizeControl *advsize, uint32_t &xsize, uint32_t &ysize);
|
||||
[[gnu::hot]] void bounce(int8_t &incomingspeed, int8_t ¶llelspeed, int32_t &position, const uint32_t maxposition); // bounce on a wall
|
||||
// note: variables that are accessed often are 32bit for speed
|
||||
CRGB *framebuffer; // local frame buffer for rendering
|
||||
PSsettings2D particlesettings; // settings used when updating particles (can also used by FX to move sources), do not edit properties directly, use functions above
|
||||
uint32_t numParticles; // total number of particles allocated by this system note: during transitions, less are available, use availableParticles
|
||||
uint32_t availableParticles; // number of particles available for use (can be more or less than numParticles, assigned by memory manager)
|
||||
uint32_t numParticles; // total number of particles allocated by this system
|
||||
uint32_t emitIndex; // index to count through particles to emit so searching for dead pixels is faster
|
||||
int32_t collisionHardness;
|
||||
uint32_t wallHardness;
|
||||
@ -233,7 +210,6 @@ private:
|
||||
uint32_t particleHardRadius; // hard surface radius of a particle, used for collision detection (32bit for speed)
|
||||
uint16_t collisionStartIdx; // particle array start index for collision detection
|
||||
uint8_t fireIntesity = 0; // fire intensity, used for fire mode (flash use optimization, better than passing an argument to render function)
|
||||
uint8_t fractionOfParticlesUsed; // percentage of particles used in the system (255=100%), used during transition updates
|
||||
uint8_t forcecounter; // counter for globally applied forces
|
||||
uint8_t gforcecounter; // counter for global gravity
|
||||
int8_t gforce; // gravity strength, default is 8 (negative is allowed, positive is downwards)
|
||||
@ -241,8 +217,6 @@ private:
|
||||
uint8_t particlesize; // global particle size, 0 = 1 pixel, 1 = 2 pixels, 255 = 10 pixels (note: this is also added to individual sized particles)
|
||||
uint8_t motionBlur; // motion blur, values > 100 gives smoother animations. Note: motion blurring does not work if particlesize is > 0
|
||||
uint8_t smearBlur; // 2D smeared blurring of full frame
|
||||
uint8_t effectID; // ID of the effect that is using this particle system, used for transitions
|
||||
uint32_t lastRender; // last time the particles were rendered, intermediate fix for speedup
|
||||
};
|
||||
|
||||
void blur2D(CRGB *colorbuffer, const uint32_t xsize, uint32_t ysize, const uint32_t xblur, const uint32_t yblur, const uint32_t xstart = 0, uint32_t ystart = 0, const bool isparticle = false);
|
||||
@ -258,7 +232,7 @@ bool allocateParticleSystemMemory2D(const uint32_t numparticles, const uint32_t
|
||||
////////////////////////
|
||||
#ifndef WLED_DISABLE_PARTICLESYSTEM1D
|
||||
// memory allocation
|
||||
#define ESP8266_MAXPARTICLES_1D 450
|
||||
#define ESP8266_MAXPARTICLES_1D 320
|
||||
#define ESP8266_MAXSOURCES_1D 16
|
||||
#define ESP32S2_MAXPARTICLES_1D 1300
|
||||
#define ESP32S2_MAXSOURCES_1D 32
|
||||
@ -349,7 +323,6 @@ public:
|
||||
void applyFriction(const int32_t coefficient); // apply friction to all used particles
|
||||
// set options
|
||||
void setUsedParticles(const uint8_t percentage); // set the percentage of particles used in the system, 255=100%
|
||||
inline uint32_t getAvailableParticles(void) { return availableParticles; } // available particles in the buffer, use this to check if buffer changed during FX init
|
||||
void setWallHardness(const uint8_t hardness); // hardness for bouncing on the wall if bounceXY is set
|
||||
void setSize(const uint32_t x); //set particle system size (= strip length)
|
||||
void setWrap(const bool enable);
|
||||
@ -377,23 +350,24 @@ public:
|
||||
|
||||
private:
|
||||
//rendering functions
|
||||
void ParticleSys_render(void);
|
||||
void render(void);
|
||||
[[gnu::hot]] void renderParticle(const uint32_t particleindex, const uint8_t brightness, const CRGB &color, const bool wrap);
|
||||
|
||||
//paricle physics applied by system if flags are set
|
||||
void applyGravity(); // applies gravity to all particles
|
||||
void handleCollisions();
|
||||
[[gnu::hot]] void collideParticles(PSparticle1D &particle1, const PSparticleFlags1D &particle1flags, PSparticle1D &particle2, const PSparticleFlags1D &particle2flags, const int32_t dx, const uint32_t dx_abs, const int32_t collisiondistance);
|
||||
[[gnu::hot]] void collideParticles(PSparticle1D &particle1, const PSparticleFlags1D &particle1flags, PSparticle1D &particle2, const PSparticleFlags1D &particle2flags, const int32_t dx, const uint32_t dx_abs, const uint32_t collisiondistance);
|
||||
|
||||
//utility functions
|
||||
void updatePSpointers(const bool isadvanced); // update the data pointers to current segment data space
|
||||
//void updateSize(PSadvancedParticle *advprops, PSsizeControl *advsize); // advanced size control
|
||||
[[gnu::hot]] void bounce(int8_t &incomingspeed, int8_t ¶llelspeed, int32_t &position, const uint32_t maxposition); // bounce on a wall
|
||||
// note: variables that are accessed often are 32bit for speed
|
||||
#ifndef ESP8266
|
||||
CRGB *framebuffer; // local frame buffer for rendering
|
||||
#endif
|
||||
PSsettings1D particlesettings; // settings used when updating particles
|
||||
uint32_t numParticles; // total number of particles allocated by this system note: never use more than this, even if more are available (only this many advanced particles are allocated)
|
||||
uint32_t availableParticles; // number of particles available for use (can be more or less than numParticles, assigned by memory manager)
|
||||
uint8_t fractionOfParticlesUsed; // percentage of particles used in the system (255=100%), used during transition updates
|
||||
uint32_t numParticles; // total number of particles allocated by this system
|
||||
uint32_t emitIndex; // index to count through particles to emit so searching for dead pixels is faster
|
||||
int32_t collisionHardness;
|
||||
uint32_t particleHardRadius; // hard surface radius of a particle, used for collision detection
|
||||
@ -406,8 +380,6 @@ private:
|
||||
uint8_t particlesize; // global particle size, 0 = 1 pixel, 1 = 2 pixels
|
||||
uint8_t motionBlur; // enable motion blur, values > 100 gives smoother animations
|
||||
uint8_t smearBlur; // smeared blurring of full frame
|
||||
uint8_t effectID; // ID of the effect that is using this particle system, used for transitions
|
||||
uint32_t lastRender; // last time the particles were rendered, intermediate fix for speedup
|
||||
};
|
||||
|
||||
bool initParticleSystem1D(ParticleSystem1D *&PartSys, const uint32_t requestedsources, const uint8_t fractionofparticles = 255, const uint32_t additionalbytes = 0, const bool advanced = false);
|
||||
|
@ -168,8 +168,8 @@
|
||||
<h3>Clock</h3>
|
||||
Analog Clock overlay: <input type="checkbox" name="OL" onchange="Cs()"><br>
|
||||
<div id="cac">
|
||||
First LED: <input name="O1" type="number" min="0" max="255" required> Last LED: <input name="O2" type="number" min="0" max="255" required><br>
|
||||
12h LED: <input name="OM" type="number" min="0" max="255" required><br>
|
||||
First LED: <input name="O1" type="number" min="0" max="1024" required> Last LED: <input name="O2" type="number" min="0" max="1024" required><br>
|
||||
12h LED: <input name="OM" type="number" min="0" max="1024" required><br>
|
||||
Show 5min marks: <input type="checkbox" name="O5"><br>
|
||||
Seconds (as trail): <input type="checkbox" name="OS"><br>
|
||||
Show clock overlay only if all LEDs are solid black: <input type="checkbox" name="OB"><br>
|
||||
|
@ -558,7 +558,7 @@ WLED_GLOBAL byte currentTimezone _INIT(WLED_TIMEZONE); // Timezone ID. Refer
|
||||
WLED_GLOBAL int utcOffsetSecs _INIT(WLED_UTC_OFFSET); // Seconds to offset from UTC before timzone calculation
|
||||
|
||||
WLED_GLOBAL byte overlayCurrent _INIT(0); // 0: no overlay 1: analog clock 2: was single-digit clock 3: was cronixie
|
||||
WLED_GLOBAL byte overlayMin _INIT(0), overlayMax _INIT(DEFAULT_LED_COUNT - 1); // boundaries of overlay mode
|
||||
WLED_GLOBAL uint16_t overlayMin _INIT(0), overlayMax _INIT(DEFAULT_LED_COUNT - 1); // boundaries of overlay mode
|
||||
|
||||
WLED_GLOBAL byte analogClock12pixel _INIT(0); // The pixel in your strip where "midnight" would be
|
||||
WLED_GLOBAL bool analogClockSecondsTrail _INIT(false); // Display seconds as trail of LEDs instead of a single pixel
|
||||
|
Loading…
x
Reference in New Issue
Block a user