pitrix/src/effect_animation.cpp

64 lines
2.2 KiB
C++

#include "effect_animation.h"
#include "functions.h"
AnimationEffect::AnimationEffect(AnimationData *anim) : AnimationEffect(anim, CRGB(0), 0, 0) {}
AnimationEffect::AnimationEffect(AnimationData *anim, CRGB background_color) : AnimationEffect(anim, background_color, 0, 0) {}
AnimationEffect::AnimationEffect(AnimationData *anim, CRGB bg_color, int x, int y) {
animation = anim;
background_color = bg_color;
xOffset = x;
yOffset = y;
}
void AnimationEffect::loop() {
Serial.printf("Animation.loop. Animation is %p.", (void *)animation);
CRGB colors[animation->color_count];
int led_index = 0;
uint8_t *color_data = new uint8_t[animation->color_count * 3];
memcpy_P(color_data, animation->colors, animation->color_count * 3);
for (int i = 0; i < animation->color_count; i++) colors[i] = CRGB(color_data[i * 3], color_data[i * 3 + 1], color_data[i * 3 + 2]);
free(color_data);
// Data is stored in progmem, so get it from there.
int length = animation->offsets[frame + 1] - animation->offsets[frame];
uint8_t *data = new uint8_t[length];
memcpy_P(data, animation->data + animation->offsets[frame], length);
for (int i = 0; i < length; i++) {
uint8_t color_index;
uint8_t count;
if (data[i] == 255) { // Run-length encoded data
color_index = data[i + 2];
count = data[i + 1];
i += 2;
} else {
color_index = data[i];
count = 1;
}
if (color_index == 0) { // color #0 = skip this pixels
led_index += count;
} else {
CRGB* color;
if (color_index == 1) {
color = &background_color;
} else if (color_index >= 2) {
color = &colors[color_index - 2];
}
for (int j = 0; j < count; j++) set(led_index++, color);
}
}
free(data);
if (frameSince == 0 || frameSince + frameDelay(animation, frame) < millis() || frameSince > millis()) {
frame = (frame + 1) % animation->frame_count;
frameSince = millis();
}
}
void AnimationEffect::set(int i, CRGB* color) {
setPixel(xOffset + (i % animation->w), yOffset + (i / animation->h), *color);
}
uint16_t AnimationEffect::frameDelay(AnimationData* animation, int frame) {
if (animation->individual_delays) return animation->delays[frame];
return animation->delays[0];
}