diff --git a/CHANGELOG.md b/CHANGELOG.md index 1db752d6a..c4252b5d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. ## [14.4.1.1] ### Added - Command ``SetOption163 1`` to disable display of Device name in GUI header +- Berry `animate.crenel` primitive ### Breaking Changed diff --git a/lib/libesp32/berry_animate/src/embedded/animate_2_animate_effects.be b/lib/libesp32/berry_animate/src/embedded/animate_2_animate_effects.be index d2653db67..6132b406a 100644 --- a/lib/libesp32/berry_animate/src/embedded/animate_2_animate_effects.be +++ b/lib/libesp32/berry_animate/src/embedded/animate_2_animate_effects.be @@ -148,6 +148,131 @@ class Animate_pulse : Animate_painter end animate.pulse = global.Animate_pulse +########################################################################################## +# +# class Animate_crenel +# +# Display a color crenel +# +# pos (1) +# | +# v (*4) +# ______ ____ +# | | | +# _________| |_________| +# +# | 2 | 3 | +# +# 1: `pos`, start of the pulse (in pixel) +# 2: `pulse_size`, number of pixels of the pulse +# 3: `low_size`, number of pixel until next pos - full cycle is 3 + 4 +# 4: `nb_pulse`, number of pulses, of `-1` is infinite +# +########################################################################################## + +#@ solidify:Animate_crenel,weak +class Animate_crenel : Animate_painter + var color + var back_color + var pos + var pulse_size + var low_size + var nb_pulse + + def init(color, pulse_size, low_size, nb_pulse) + super(self).init() + + if (color == nil) color = 0xFFFFFF end # white by default + if (pulse_size == nil) pulse_size = 1 end + if (low_size == nil) low_size = 3 end + if (nb_pulse == nil) nb_pulse = -1 end + + self.color = color + self.back_color = 0xFF000000 # default to transparent + if pulse_size < 0 pulse_size = 0 end + self.pulse_size = pulse_size + if low_size < 0 low_size = 0 end + self.low_size = low_size + self.nb_pulse = nb_pulse + self.pos = 0 + end + + ## + ## Setters - to be used as cb for animators + ## + def set_color(color) + self.color = color + end + + def set_back_color(c) + self.back_color = c + end + + def set_pos(pos) + self.pos = pos + end + + def set_pulse_size(pulse_size) + self.pulse_size = pulse_size + end + + def set_nb_pulse(nb_pulse) + self.nb_pulse = nb_pulse + end + + def set_low_size(low_size) + self.low_size = low_size + end + + # return true if buffer was filled successfully + def paint(frame) + var back_color = self.back_color + if (back_color != 0xFF000000) + frame.fill_pixels(back_color) # fill with transparent color + end + var pos = self.pos + var pulse_size = self.pulse_size + var low_size = self.low_size + var color = self.color + var pixel_size = frame.pixel_size + var period = int(pulse_size + low_size) + var nb_pulse = self.nb_pulse + if (period <= 0) period = 1 end # make sure with have a meaningful period so we can iterate on it + + if (nb_pulse == 0) return end # nothing to paint + if (nb_pulse < 0) + # in case of infinite number of crenels, we find the position of the first visible falling range `(pos + pulse_size - 1)` + pos = ((pos + pulse_size - 1) % period) - pulse_size + 1 + else + while (pos < -period) && (nb_pulse != 0) + pos += period + nb_pulse -= 1 + end + end + + while (pos < pixel_size) && (nb_pulse != 0) # we iterate on pos (by `period` ranges) + var i = 0 + if (pos < 0) + i = - pos + end + # invariant: pos + i >= 0 + if type(self.color) == 'int' + while (i < pulse_size) && (pos + i < pixel_size) + frame[pos + i] = color + i += 1 + end + elif type(self.color) == 'instance' + self.color.get_color(tasmota.scale_int(i, 0, pulse_size - 1, 0, 255)) + end + pos += period + nb_pulse -= 1 + end + + return true + end +end +animate.crenel = global.Animate_crenel + # # Unit tests # @@ -183,4 +308,109 @@ pulse.set_slew_size(0) pulse.paint(frame) assert(frame.tohex() == '00000000000000000000000000000000000000000000000000000000000000000000000000000000') +# test for crenel + +frame = animate.frame(10) +assert(frame.tohex() == '00000000000000000000000000000000000000000000000000000000000000000000000000000000') + +var crenel = animate.crenel(0x00FF00, 2, 3, -1) +crenel.paint(frame) +assert(frame.tohex() == '00FF000000FF000000000000000000000000000000FF000000FF0000000000000000000000000000') + +crenel.set_back_color(0x00000000) +crenel.set_pos(1) +crenel.paint(frame) +assert(frame.tohex() == '0000000000FF000000FF000000000000000000000000000000FF000000FF00000000000000000000') + +crenel.set_back_color(0x00000000) +crenel.set_low_size(1) +crenel.paint(frame) +assert(frame.tohex() == '0000000000FF000000FF00000000000000FF000000FF00000000000000FF000000FF000000000000') + +crenel.set_back_color(0x00000000) +crenel.set_pos(0) +crenel.paint(frame) +assert(frame.tohex() == '00FF000000FF00000000000000FF000000FF00000000000000FF000000FF00000000000000FF0000') + +crenel.set_back_color(0x00000000) +crenel.set_nb_pulse(2) +crenel.paint(frame) +assert(frame.tohex() == '00FF000000FF00000000000000FF000000FF00000000000000000000000000000000000000000000') + + +crenel = animate.crenel(0xFFEEDD, 2, 3, 2) +crenel.set_back_color(0x00000000) +crenel.paint(frame) +assert(frame.tohex() == 'DDEEFF00DDEEFF00000000000000000000000000DDEEFF00DDEEFF00000000000000000000000000') + +crenel.set_back_color(0x00000000) +crenel.set_pos(-1) +crenel.paint(frame) +assert(frame.tohex() == 'DDEEFF00000000000000000000000000DDEEFF00DDEEFF0000000000000000000000000000000000') + +crenel.set_back_color(0x00000000) +crenel.set_pos(-2) +crenel.paint(frame) +assert(frame.tohex() == '000000000000000000000000DDEEFF00DDEEFF000000000000000000000000000000000000000000') + +crenel.set_back_color(0x00000000) +crenel.set_pos(-3) +crenel.paint(frame) +assert(frame.tohex() == '0000000000000000DDEEFF00DDEEFF00000000000000000000000000000000000000000000000000') + +crenel.set_back_color(0x00000000) +crenel.set_pos(-4) +crenel.paint(frame) +assert(frame.tohex() == '00000000DDEEFF00DDEEFF0000000000000000000000000000000000000000000000000000000000') + +crenel.set_back_color(0x00000000) +crenel.set_pos(-5) +crenel.paint(frame) +assert(frame.tohex() == 'DDEEFF00DDEEFF000000000000000000000000000000000000000000000000000000000000000000') + +crenel.set_back_color(0x00000000) +crenel.set_pos(-6) +crenel.paint(frame) +assert(frame.tohex() == 'DDEEFF00000000000000000000000000000000000000000000000000000000000000000000000000') + +crenel.set_back_color(0x00000000) +crenel.set_pos(-7) +crenel.paint(frame) +assert(frame.tohex() == '00000000000000000000000000000000000000000000000000000000000000000000000000000000') + +crenel.set_back_color(0x00000000) +crenel.set_pos(-8) +crenel.paint(frame) +assert(frame.tohex() == '00000000000000000000000000000000000000000000000000000000000000000000000000000000') + +crenel.set_back_color(0x00000000) +crenel.set_pos(1) +crenel.paint(frame) +assert(frame.tohex() == '00000000DDEEFF00DDEEFF00000000000000000000000000DDEEFF00DDEEFF000000000000000000') + +crenel.set_back_color(0x00000000) +crenel.set_pos(2) +crenel.paint(frame) +assert(frame.tohex() == '0000000000000000DDEEFF00DDEEFF00000000000000000000000000DDEEFF00DDEEFF0000000000') + +crenel.set_back_color(0x00000000) +crenel.set_pos(3) +crenel.paint(frame) +assert(frame.tohex() == '000000000000000000000000DDEEFF00DDEEFF00000000000000000000000000DDEEFF00DDEEFF00') + +crenel.set_back_color(0x00000000) +crenel.set_pos(4) +crenel.paint(frame) +assert(frame.tohex() == '00000000000000000000000000000000DDEEFF00DDEEFF00000000000000000000000000DDEEFF00') + +crenel.set_back_color(0x00000000) +crenel.set_pos(5) +crenel.paint(frame) +assert(frame.tohex() == '0000000000000000000000000000000000000000DDEEFF00DDEEFF00000000000000000000000000') + +crenel.set_back_color(0x00000000) +crenel.set_pulse_size(10) +crenel.paint(frame) +assert(frame.tohex() == '0000000000000000000000000000000000000000DDEEFF00DDEEFF00DDEEFF00DDEEFF00DDEEFF00') + end