From 46b9823af4f88bfce613d2fc6e4328452ae99fc9 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Thu, 25 Dec 2025 23:59:47 +0100 Subject: [PATCH] Berry animation more examples (#24258) --- .../chap_2_10_palette_rotation.anim | 2 +- .../chap_2_20_palette_rotation.anim | 2 +- .../chap_3_10_color_transition.anim | 2 +- .../chap_4_10_color_pattern.anim | 2 +- .../chap_4_12_color_pattern_spatial_2.anim | 2 +- .../chap_4_15_color_pattern_spatial_osc.anim | 2 +- ...hap_4_18_color_pattern_spatial_rotate.anim | 2 +- .../chap_4_30_color_pattern_meter.anim | 2 +- .../chap_4_35_color_pattern_meter_random.anim | 2 +- .../chap_5_40_cylon_rainbow.anim | 2 +- .../chap_5_50_cylon_as_opacity.anim | 2 +- .../chap_6_20_shutter_rotating_colors.anim | 4 +- ..._6_30_shutter_central_rotating_colors.anim | 4 +- .../chap_6_40_shutter_central_inoutin.anim | 4 +- .../chap_7_40_crenel_colors.anim | 2 +- .../chap_7_50_crenel_opacity.anim | 2 +- .../chap_8_10_template_cylon_simple.anim | 8 ++- .../chap_8_20_template_color_cycle.anim | 23 +++++++ ...hap_8_21_template_shutter_bidir_flags.anim | 65 ------------------ ...ap_8_30_template_shutter_bidir_flags.anim} | 35 +++++----- .../anim_tutorials/png/chap_8_10.png | Bin 0 -> 10314 bytes .../anim_tutorials/png/chap_8_20.png | Bin 0 -> 3651 bytes .../anim_tutorials/png/chap_8_30.png | Bin 0 -> 45261 bytes .../providers/color_cycle_color_provider.be | 10 +-- .../src/solidify/solidified_animation.h | 40 ++++++----- 25 files changed, 93 insertions(+), 126 deletions(-) create mode 100644 lib/libesp32/berry_animation/anim_tutorials/chap_8_20_template_color_cycle.anim delete mode 100644 lib/libesp32/berry_animation/anim_tutorials/chap_8_21_template_shutter_bidir_flags.anim rename lib/libesp32/berry_animation/anim_tutorials/{chap_8_22_template_shutter_bidir.anim => chap_8_30_template_shutter_bidir_flags.anim} (61%) create mode 100644 lib/libesp32/berry_animation/anim_tutorials/png/chap_8_10.png create mode 100644 lib/libesp32/berry_animation/anim_tutorials/png/chap_8_20.png create mode 100644 lib/libesp32/berry_animation/anim_tutorials/png/chap_8_30.png diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_2_10_palette_rotation.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_2_10_palette_rotation.anim index c67652c79..e442b1aff 100644 --- a/lib/libesp32/berry_animation/anim_tutorials/chap_2_10_palette_rotation.anim +++ b/lib/libesp32/berry_animation/anim_tutorials/chap_2_10_palette_rotation.anim @@ -3,6 +3,6 @@ # Define a color attribute that cycles over time, cycle is 5 seconds # PALETTE_RAINBOW defines 7 rainbow colors at roughly the same brightness # PALETTE_RAINBOW_W adds 8th color white -color rainbow_color = color_cycle(palette=PALETTE_RAINBOW_W, cycle_period=5s) +color rainbow_color = color_cycle(colors=PALETTE_RAINBOW_W, cycle_period=5s) animation back = solid(color=rainbow_color) run back \ No newline at end of file diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_2_20_palette_rotation.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_2_20_palette_rotation.anim index b794a432b..bd7194b6f 100644 --- a/lib/libesp32/berry_animation/anim_tutorials/chap_2_20_palette_rotation.anim +++ b/lib/libesp32/berry_animation/anim_tutorials/chap_2_20_palette_rotation.anim @@ -14,7 +14,7 @@ palette rainbow_with_white = [ ] # Define a color attribute that cycles over time, cycle is 5 seconds -color rainbow_color = color_cycle(palette=rainbow_with_white, cycle_period=5s) +color rainbow_color = color_cycle(colors=rainbow_with_white, cycle_period=5s) # Define a solid background with this dynamic color animation back = solid(color=rainbow_color) diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_3_10_color_transition.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_3_10_color_transition.anim index c8e94d536..7d20e8244 100644 --- a/lib/libesp32/berry_animation/anim_tutorials/chap_3_10_color_transition.anim +++ b/lib/libesp32/berry_animation/anim_tutorials/chap_3_10_color_transition.anim @@ -2,6 +2,6 @@ animation back = rich_palette_animation() # Equivalent to -# animation back = rich_palette_animation(palette=PALETTE_PALETTE_RAINBOW, cycle_period=5s, +# animation back = rich_palette_animation(colors=PALETTE_PALETTE_RAINBOW, cycle_period=5s, # transition_type=SINE, brightness=100%) run back \ No newline at end of file diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_4_10_color_pattern.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_4_10_color_pattern.anim index 725e20acf..3d3b4743c 100644 --- a/lib/libesp32/berry_animation/anim_tutorials/chap_4_10_color_pattern.anim +++ b/lib/libesp32/berry_animation/anim_tutorials/chap_4_10_color_pattern.anim @@ -2,7 +2,7 @@ # Define a smooth palette using PALETTE_RAINBOW_W (7 colors + white) # 'cycle_period = 0' means that the colors don't change in time, only spatial change -color rainbow_rich_color = rich_palette(palette=PALETTE_RAINBOW_W, cycle_period=0) +color rainbow_rich_color = rich_palette(colors=PALETTE_RAINBOW_W, cycle_period=0) # Define a gradient across the whole strip animation back_pattern = palette_gradient_animation(color_source = rainbow_rich_color) diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_4_12_color_pattern_spatial_2.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_4_12_color_pattern_spatial_2.anim index f5c704fce..2b0593347 100644 --- a/lib/libesp32/berry_animation/anim_tutorials/chap_4_12_color_pattern_spatial_2.anim +++ b/lib/libesp32/berry_animation/anim_tutorials/chap_4_12_color_pattern_spatial_2.anim @@ -3,7 +3,7 @@ # Define a smooth palette using PALETTE_RAINBOW_W (7 colors + white) # 'cycle_period = 0' means that the colors don't change in time, only spatial change -color rainbow_rich_color = rich_palette(palette=PALETTE_RAINBOW_W, cycle_period=0) +color rainbow_rich_color = rich_palette(colors=PALETTE_RAINBOW_W, cycle_period=0) # Because strip_length is dynamic, we need to map it to a variable and can't use the function directly in formulas set strip_len = strip_length() diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_4_15_color_pattern_spatial_osc.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_4_15_color_pattern_spatial_osc.anim index 77ac0b88a..2f8a3412a 100644 --- a/lib/libesp32/berry_animation/anim_tutorials/chap_4_15_color_pattern_spatial_osc.anim +++ b/lib/libesp32/berry_animation/anim_tutorials/chap_4_15_color_pattern_spatial_osc.anim @@ -2,7 +2,7 @@ # Define a smooth palette using PALETTE_RAINBOW_W (7 colors + white) # 'cycle_period = 0' means that the colors don't change in time, only spatial change -color rainbow_rich_color = rich_palette(palette=PALETTE_RAINBOW_W, cycle_period=0) +color rainbow_rich_color = rich_palette(colors=PALETTE_RAINBOW_W, cycle_period=0) # Because strip_length is dynamic, we need to map it to a variable and can't use the function directly in formulas set strip_len = strip_length() diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_4_18_color_pattern_spatial_rotate.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_4_18_color_pattern_spatial_rotate.anim index 189b1a247..ea9df22fa 100644 --- a/lib/libesp32/berry_animation/anim_tutorials/chap_4_18_color_pattern_spatial_rotate.anim +++ b/lib/libesp32/berry_animation/anim_tutorials/chap_4_18_color_pattern_spatial_rotate.anim @@ -2,7 +2,7 @@ # Define a smooth palette using PALETTE_RAINBOW_W (7 colors + white) # 'cycle_period = 0' means that the colors don't change in time, only spatial change -color rainbow_rich_color = rich_palette(palette=PALETTE_RAINBOW_W, cycle_period=0) +color rainbow_rich_color = rich_palette(colors=PALETTE_RAINBOW_W, cycle_period=0) # define a gradient across the whole strip animation back = palette_gradient_animation(color_source = rainbow_rich_color, shift_period = 5s) diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_4_30_color_pattern_meter.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_4_30_color_pattern_meter.anim index b3516240f..a14ffec65 100644 --- a/lib/libesp32/berry_animation/anim_tutorials/chap_4_30_color_pattern_meter.anim +++ b/lib/libesp32/berry_animation/anim_tutorials/chap_4_30_color_pattern_meter.anim @@ -13,7 +13,7 @@ palette vue_meter_palette = [ ] # Define a color palette pattern for 'vue_meter_palette' -color rainbow_rich_color = rich_palette(palette=vue_meter_palette, cycle_period=0, transition_type=LINEAR) +color rainbow_rich_color = rich_palette(colors=vue_meter_palette, cycle_period=0, transition_type=LINEAR) # Define a sawtooth value from 0% to 100% set level = sawtooth(min_value = 0%, max_value=100%, duration = 2s) diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_4_35_color_pattern_meter_random.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_4_35_color_pattern_meter_random.anim index 60ef64b30..c8a3e2676 100644 --- a/lib/libesp32/berry_animation/anim_tutorials/chap_4_35_color_pattern_meter_random.anim +++ b/lib/libesp32/berry_animation/anim_tutorials/chap_4_35_color_pattern_meter_random.anim @@ -24,7 +24,7 @@ palette vue_meter_palette = [ ] # Define a color palette pattern for 'vue_meter_palette' -color rainbow_rich_color = rich_palette(palette=vue_meter_palette, cycle_period=0, transition_type=LINEAR) +color rainbow_rich_color = rich_palette(colors=vue_meter_palette, cycle_period=0, transition_type=LINEAR) # Define a vue-meter based on all elements above animation back = palette_meter_animation(color_source = rainbow_rich_color, level = rand_meter()) diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_5_40_cylon_rainbow.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_5_40_cylon_rainbow.anim index 5db22a77a..d8c303423 100644 --- a/lib/libesp32/berry_animation/anim_tutorials/chap_5_40_cylon_rainbow.anim +++ b/lib/libesp32/berry_animation/anim_tutorials/chap_5_40_cylon_rainbow.anim @@ -16,7 +16,7 @@ run stars # We can combine a dynamic 'pos' value with a dynamic 'color' animation back = beacon_animation( - color = rich_palette(palette=PALETTE_RAINBOW_W2, cycle_period=5s) + color = rich_palette(colors=PALETTE_RAINBOW_W2, cycle_period=5s) pos = cosine_osc(min_value = -1, max_value = strip_len - 2, duration = 5s) beacon_size = 3 # small 3 pixels eye slew_size = 2 # with 2 pixel shading around diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_5_50_cylon_as_opacity.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_5_50_cylon_as_opacity.anim index b9462f1a8..e1e787c75 100644 --- a/lib/libesp32/berry_animation/anim_tutorials/chap_5_50_cylon_as_opacity.anim +++ b/lib/libesp32/berry_animation/anim_tutorials/chap_5_50_cylon_as_opacity.anim @@ -8,7 +8,7 @@ set strip_len = strip_length() # Define a pattern that goes from red to blue to red across the strip palette red_blue_red_palette = [ red, 0x3333FF, red ] # Embed this raw palette into a rich_palette color provider -color red_blue_red_color = rich_palette(palette=red_blue_red_palette) +color red_blue_red_color = rich_palette(colors=red_blue_red_palette) # Define a moving beacon to be used as an opacity mask animation moving_eye = beacon_animation( diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_6_20_shutter_rotating_colors.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_6_20_shutter_rotating_colors.anim index cb79f842a..cfd6f1a3a 100644 --- a/lib/libesp32/berry_animation/anim_tutorials/chap_6_20_shutter_rotating_colors.anim +++ b/lib/libesp32/berry_animation/anim_tutorials/chap_6_20_shutter_rotating_colors.anim @@ -12,8 +12,8 @@ set shutter_size = sawtooth(min_value = 0, max_value = strip_len, # Define 2 color providers cycling through palette rainbow with white # 'col2' is shifted by 1 color from 'col1' -color col1 = color_cycle(palette=PALETTE_RAINBOW_W, cycle_period=0) -color col2 = color_cycle(palette=PALETTE_RAINBOW_W, cycle_period=0) +color col1 = color_cycle(colors=PALETTE_RAINBOW_W, cycle_period=0) +color col2 = color_cycle(colors=PALETTE_RAINBOW_W, cycle_period=0) col2.next = 1 # Writing 1 to 'next' actually advances the color # Using beacon_animation to move a shutter from left to right diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_6_30_shutter_central_rotating_colors.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_6_30_shutter_central_rotating_colors.anim index e78c061c6..4fca327c4 100644 --- a/lib/libesp32/berry_animation/anim_tutorials/chap_6_30_shutter_central_rotating_colors.anim +++ b/lib/libesp32/berry_animation/anim_tutorials/chap_6_30_shutter_central_rotating_colors.anim @@ -13,8 +13,8 @@ set shutter_size = sawtooth(min_value = 0, max_value = strip_len, # Define 2 color providers cycling through palette rainbow with white # 'col2' is shifted by 1 color from 'col1' -color col1 = color_cycle(palette=PALETTE_RAINBOW_W, cycle_period=0) -color col2 = color_cycle(palette=PALETTE_RAINBOW_W, cycle_period=0) +color col1 = color_cycle(colors=PALETTE_RAINBOW_W, cycle_period=0) +color col2 = color_cycle(colors=PALETTE_RAINBOW_W, cycle_period=0) col2.next = 1 # Writing 1 to 'next' actually advances the color # Using beacon_animation to move a shutter from in to out diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_6_40_shutter_central_inoutin.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_6_40_shutter_central_inoutin.anim index c3fe34f0c..9eb25cfac 100644 --- a/lib/libesp32/berry_animation/anim_tutorials/chap_6_40_shutter_central_inoutin.anim +++ b/lib/libesp32/berry_animation/anim_tutorials/chap_6_40_shutter_central_inoutin.anim @@ -13,8 +13,8 @@ set shutter_size = sawtooth(min_value = 0, max_value = strip_len, # Define 2 color providers cycling through palette rainbow with white # 'col2' is shifted by 1 color from 'col1' -color col1 = color_cycle(palette=PALETTE_RAINBOW_W, cycle_period=0) -color col2 = color_cycle(palette=PALETTE_RAINBOW_W, cycle_period=0) +color col1 = color_cycle(colors=PALETTE_RAINBOW_W, cycle_period=0) +color col2 = color_cycle(colors=PALETTE_RAINBOW_W, cycle_period=0) col2.next = 1 # Writing 1 to 'next' actually advances the color # Using beacon_animation to move a shutter from in to out diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_7_40_crenel_colors.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_7_40_crenel_colors.anim index 2567887f4..95cc99b21 100644 --- a/lib/libesp32/berry_animation/anim_tutorials/chap_7_40_crenel_colors.anim +++ b/lib/libesp32/berry_animation/anim_tutorials/chap_7_40_crenel_colors.anim @@ -1,7 +1,7 @@ # @desc Crenel static with variable color # Define a color attribute that cycles over time, cycle is 5 seconds -color rainbow_color = rich_palette(palette=PALETTE_RAINBOW_W2, cycle_period=5s) +color rainbow_color = rich_palette(colors=PALETTE_RAINBOW_W2, cycle_period=5s) # Define a simple crenel 2+2 animation back = crenel_animation( diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_7_50_crenel_opacity.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_7_50_crenel_opacity.anim index 1ef3d328c..0a8fd8ece 100644 --- a/lib/libesp32/berry_animation/anim_tutorials/chap_7_50_crenel_opacity.anim +++ b/lib/libesp32/berry_animation/anim_tutorials/chap_7_50_crenel_opacity.anim @@ -13,7 +13,7 @@ animation mask = crenel_animation( ) # Define a smooth palette using PALETTE_RAINBOW_W (7 colors + white) -color rainbow_rich_color = rich_palette(palette=PALETTE_RAINBOW_W, cycle_period=0) +color rainbow_rich_color = rich_palette(colors=PALETTE_RAINBOW_W, cycle_period=0) # Define a gradient across the whole strip and use crenel as opacity mask animation pattern = palette_gradient_animation( color_source = rainbow_rich_color # use the rainow pattern diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_8_10_template_cylon_simple.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_8_10_template_cylon_simple.anim index ed51f8ef9..9606891f8 100644 --- a/lib/libesp32/berry_animation/anim_tutorials/chap_8_10_template_cylon_simple.anim +++ b/lib/libesp32/berry_animation/anim_tutorials/chap_8_10_template_cylon_simple.anim @@ -1,9 +1,11 @@ -# @desc Cylon-style scanning eye using template with customizable color +# @desc Template example fir Cylon-style scanning eye +# Define a full template with parameters: eye_color, back_color, period, priority template animation cylon_eye { param eye_color type color default red param back_color type color default transparent param period type time default 5s + param priority default 5 set strip_len = strip_length() @@ -13,11 +15,11 @@ template animation cylon_eye { pos = cosine_osc(min_value = -1, max_value = strip_len - 2, duration = period) beacon_size = 3 # small 3 pixels eye slew_size = 2 # with 2 pixel shading around - priority = 5 + priority = priority ) run eye_animation } animation eye = cylon_eye() -run eye +run eye \ No newline at end of file diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_8_20_template_color_cycle.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_8_20_template_color_cycle.anim new file mode 100644 index 000000000..07b14638f --- /dev/null +++ b/lib/libesp32/berry_animation/anim_tutorials/chap_8_20_template_color_cycle.anim @@ -0,0 +1,23 @@ +# @desc Rainbow colors cycling with custom palette + +# Define a full template with parameters: colors, cycle_period +template animation color_cycle2 { + param colors type palette + param cycle_period default 5s + + # Define a color attribute that cycles over time, cycle is 5 seconds + color rainbow_color = color_cycle(colors=colors, cycle_period=cycle_period) + + # Define a solid background with this dynamic color + animation back = solid(color=rainbow_color) + run back +} + +palette rgb = [ + 0xFC0000 # Red + 0x00FF00 # Green + 0x0080FF # Blue +] + +animation main = color_cycle2(colors = rgb, cycle_period = 2s) +run main \ No newline at end of file diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_8_21_template_shutter_bidir_flags.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_8_21_template_shutter_bidir_flags.anim deleted file mode 100644 index c9a781c2c..000000000 --- a/lib/libesp32/berry_animation/anim_tutorials/chap_8_21_template_shutter_bidir_flags.anim +++ /dev/null @@ -1,65 +0,0 @@ -# @desc Bidirectional shutter effect with rainbow colors - -template animation shutter_bidir { - param colors type palette - param period default 5s - - set strip_len = strip_length() - set shutter_size = sawtooth(min_value = 0, max_value = strip_len, duration = period) - - color col1 = color_cycle(palette=colors, cycle_period=0) - color col2 = color_cycle(palette=colors, cycle_period=0) - col2.next = 1 - - # shutter moving from left to right - animation shutter_lr_animation = beacon_animation( - color = col2 - back_color = col1 - pos = 0 - beacon_size = shutter_size - slew_size = 0 - priority = 5 - ) - - # shutter moving from right to left - animation shutter_rl_animation = beacon_animation( - color = col1 - back_color = col2 - pos = 0 - beacon_size = strip_len - shutter_size - slew_size = 0 - priority = 5 - ) - - sequence shutter_seq repeat forever { - repeat col1.palette_size times { - restart shutter_size - play shutter_lr_animation for period - col1.next = 1 - col2.next = 1 - } - repeat col1.palette_size times { - restart shutter_size - play shutter_rl_animation for period - col1.next = 1 - col2.next = 1 - } - } - - run shutter_seq -} - -# define a palette of rainbow colors including white with constant brightness -palette rainbow_with_white = [ - 0xFC0000 # Red - 0xFF8000 # Orange - 0xFFFF00 # Yellow - 0x00FF00 # Green - 0x00FFFF # Cyan - 0x0080FF # Blue - 0x8000FF # Violet - 0xCCCCCC # White -] - -animation main = shutter_bidir(colors = rainbow_with_white, period = 1.5s) -run main diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_8_22_template_shutter_bidir.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_8_30_template_shutter_bidir_flags.anim similarity index 61% rename from lib/libesp32/berry_animation/anim_tutorials/chap_8_22_template_shutter_bidir.anim rename to lib/libesp32/berry_animation/anim_tutorials/chap_8_30_template_shutter_bidir_flags.anim index 725c1c591..7f050e7ab 100644 --- a/lib/libesp32/berry_animation/anim_tutorials/chap_8_22_template_shutter_bidir.anim +++ b/lib/libesp32/berry_animation/anim_tutorials/chap_8_30_template_shutter_bidir_flags.anim @@ -1,24 +1,26 @@ -# @desc Advanced shutter template with ascending/descending flags +# @desc Template to illustrate the parameters and flags +# Define a template to package the shutter in-out-in from 6.40 +# with flags to enable or disable in-out or out-in template animation shutter_bidir { param colors type palette param period default 2s - param ascending type bool default true # define to true to enable 'ascending' part - param descending type bool default true # define to true to enable 'descending' part + param inout type bool default true # define to true to enable 'inout' part + param outin type bool default true # define to true to enable 'outin' part # since 'strip_length()' is a value provider, it must be assigned to a variable before being used set strip_len = strip_length() - # animated value for the size of the shutter, evolving linearly in time (sawtooth from 0% to 100%) + # Define animated value for the size of the shutter, evolving linearly in time (sawtooth from 0% to 100%) set shutter_size = sawtooth(min_value = 0, max_value = strip_len, duration = period) - # define two rotating palettes, shifted by one color - color col1 = color_cycle(palette=colors, cycle_period=0) - color col2 = color_cycle(palette=colors, cycle_period=0) + # Define two rotating palettes, shifted by one color + color col1 = color_cycle(colors=colors, cycle_period=0) + color col2 = color_cycle(colors=colors, cycle_period=0) col2.next = 1 # move 'col2' to the next color so it's shifte by one compared to 'col1' - # shutter moving in ascending - animation shutter_lr_animation = beacon_animation( + # Shutter moving in in-out + animation shutter_inout_animation = beacon_animation( color = col2 back_color = col1 pos = 0 @@ -27,8 +29,8 @@ template animation shutter_bidir { priority = 5 ) - # shutter moving in descending - animation shutter_rl_animation = beacon_animation( + # shutter moving in out-in + animation shutter_outin_animation = beacon_animation( color = col1 back_color = col2 pos = 0 @@ -40,24 +42,23 @@ template animation shutter_bidir { # this is the overall sequence composed of two sub-sequences # the first in ascending mode, the second in descending sequence shutter_seq repeat forever { - if ascending { # un only if 'ascending' is true + if inout { # un only if 'ascending' is true repeat col1.palette_size times { # run the shutter animation restart shutter_size # resync all times for this animation, to avoid temporal drift - play shutter_lr_animation for period # run the animation + play shutter_inout_animation for period # run the animation col1.next = 1 # then move to next color for both palettes col2.next = 1 } } - if descending { # run only if 'descending' is true + if outin { # run only if 'descending' is true repeat col1.palette_size times { restart shutter_size - play shutter_rl_animation for period + play shutter_outin_animation for period col1.next = 1 col2.next = 1 } } } - run shutter_seq } @@ -74,4 +75,4 @@ palette rainbow_with_white = [ ] animation main = shutter_bidir(colors = rainbow_with_white, period = 1.5s) -run main +run main \ No newline at end of file diff --git a/lib/libesp32/berry_animation/anim_tutorials/png/chap_8_10.png b/lib/libesp32/berry_animation/anim_tutorials/png/chap_8_10.png new file mode 100644 index 0000000000000000000000000000000000000000..d458768126c243128d0b49d374a179dbab3bb771 GIT binary patch literal 10314 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 Fe*>K3G#3B> literal 0 HcmV?d00001 diff --git a/lib/libesp32/berry_animation/anim_tutorials/png/chap_8_20.png b/lib/libesp32/berry_animation/anim_tutorials/png/chap_8_20.png new file mode 100644 index 0000000000000000000000000000000000000000..d06b78defb15ea23d34e27ffe72e597542a40f71 GIT binary patch literal 3651 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

kFBttt`K#hTsf@DJKteGI-q0&WvK zY4h)J{=QmEaG|^@h!;yI&FpdjzVLohGX`gp;j%Xe){ZL`I3D$wP7HaHx9E_ghYw5TY_1N7;56C3cO$nH(x?*ylRxYOeVkcc0p z(>IF)jy}R-r-3>>i$20)VVt=eTs%#n`eX%5bloj}M^^w`$ABKEFm3>uD?9rhj07r; zw{+k-DkAQG?J!;JI0L(|Ko2BiKSU<0VA!BP#!ih^#4aq*S!ArNigzuB4gO=SJ@YF( zkVC=UO2)oR=8gjrG?Q!-W8nmD^R7q4scmP1m4|v3Wo`&9F{Q!Z^qDaeN{3_Y?PRus?w}$d5x-(i-yvetz#HB&xu4C>+bB9ZS#6_l zn;`0DQZR3rhWEatc-X&uu5&!g+fBfErL<9^pRr#ntu1aSlixNIP9eznon!^xeRPQj z5^)>9@-oE6si|-bffkx)mt)QiiwMm!| zsE{h50<)Dy4<5$+9DE3#ej^p&Sps2jDX@0f0SWR!2votiy_4|h2$?5RcOLwsY;)c! zsccJgLwvvYcDE0#Pg&37vEG0tM=b9HKUneVMiLq%wT+rMoaz0Lg5wq`0H;@i0`HWQ z;iNC_jY;1l@&O|UJ{@=+HAh=EcF2ht!6QAqVP{HBlUI9o_3`qnYiwfGh!hwnpcWWb z5AFD(fB8H4Q_3TlTKCSFU>fWtYoHM2{RPutpC}DP-8pktx2M60GrRll-AAP8%Vi)|?^xF~e5lXaD7DxcA2^4fs8f75n&oPm6>pRB>V89ktGC-N{3r}@mv4&i1s`H zZRjT0UNqU1qx|9ItYg?-!H7`W_wmp{hbCi7;CpiZ5MR1wh!)@N^;Gs_Q|pT#sdN!Fl7 zhYe45#5bYor$jLjU2@62<=F2aEu%a5uH=&bc z`VeKooKs1`Sq6n5nvCyq!`1-9pZ;rj^{hht#Oe$g|9-}g3qXQ0;Ou|%zZYuP8rhlu z-S&@SD!RqN$_hCEmfVC4P`s<}glTY&sDVTdzGXQl3nM=^QT3hWpiJ;+=E9Xv>o5(@ zlQnp+ywD6t&`fke6oQ`rdld31@gNkwrb69F-T{4C_bD(MyroctA0*X-~Mrw1c_cpQHokH`5Q_R8{&pD=j0M9`1P=Ga@R*to2=z!XR%D^RPmjEG_5lQbv3myA&nMJPt4c4)rLU$Fk@%T*8I)1iL z6p@N|EOS=Q_>ND3=jAK$_{J)`=r`cT1gVihRzs<4{U9Jg&d7vnh}!eo&HUM(cmLTO zsoTN4`-ftv*jPi2k^YU}p%&n?teYLIdcC!PwL)d@WYmn?an@~FUhYon0cI)q7m zW=(90ee2GmiuwzKCHnPUJErNMJ4l5U7_5%z0E;+6a&}EVxeiEBR@^6Ng~$0lM|e@b zR|O8vW5E(a1yPR!%S7?;5(s>RKF#vOCAzjHXQocpRdHW)91c$8i3emYs_$OW0}>RF zhh#0PhweGsQH$e0wP-7>RhcI-QhhhkPCOl;qPTm>X-tiLvKn1yuwdGv