Berry animation remove static_color_provider (#24306)

This commit is contained in:
s-hadinger 2026-01-05 08:29:07 +01:00 committed by GitHub
parent b6b88cd612
commit 4ccab9b05d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 3181 additions and 3364 deletions

View File

@ -36,12 +36,11 @@ parameterized_object (base class with parameter management and playable interfac
├── strip_length (provides LED strip length)
├── iteration_number (provides sequence iteration number)
├── oscillator_value (oscillating values with waveforms)
│ └── breathe_color (breathing color effect)
├── closure_value (computed values, internal use only)
└── color_provider (dynamic color generation)
├── static_color (solid color)
└── color_provider (solid color, base for color providers)
├── color_cycle (cycles through palette)
├── rich_palette_color (smooth palette transitions)
└── breathe_color (breathing color effect)
└── rich_palette_color (smooth palette transitions)
```
## Base Classes
@ -340,43 +339,33 @@ Color providers generate dynamic colors over time, extending value_provider for
### color_provider
Base interface for all color providers. Inherits from `value_provider`.
Base class for color providers that returns a solid color. Inherits from `value_provider`. Can be used directly for static colors or subclassed for dynamic color generation.
| Parameter | Type | Default | Constraints | Description |
|-----------|------|---------|-------------|-------------|
| `brightness` | int | 255 | 0-255 | Overall brightness scaling for all colors |
| `color` | int | 0xFFFFFFFF | - | The color to return (32-bit ARGB value) |
| `brightness` | int | 255 | 0-255 | Overall brightness scaling |
**Static Methods**:
- `apply_brightness(color, brightness)` - Applies brightness scaling to a color (ARGB format). Only performs scaling if brightness is not 255 (full brightness). This is a static utility method that can be called without an instance.
**Factory**: N/A (base interface)
### static_color
Returns a single, static color. Inherits from `color_provider`.
| Parameter | Type | Default | Constraints | Description |
|-----------|------|---------|-------------|-------------|
| `color` | int | 0xFFFFFFFF | - | The solid color to return |
| *(inherits brightness from color_provider)* | | | | |
**Factory**: `animation.color_provider(engine)`
#### Usage Examples
```berry
# Using predefined colors
color static_red = solid(color=red)
color static_blue = solid(color=blue)
color static_red = color_provider(color=red)
color static_blue = color_provider(color=blue)
# Using hex colors
color static_orange = solid(color=0xFF8C00)
color static_orange = color_provider(color=0xFF8C00)
# Using custom defined colors
color accent = 0xFF6B35
color static_accent = solid(color=accent)
color static_accent = color_provider(color=accent)
```
**Note**: The `solid()` function is the recommended shorthand for `static_color()`.
### color_cycle
Cycles through a palette of colors with brutal switching. Inherits from `color_provider`.
@ -456,16 +445,15 @@ color fire_colors = rich_palette_color(
### breathe_color
Creates breathing/pulsing color effects by modulating the brightness of a base color over time. Inherits from `color_provider`.
Creates breathing/pulsing color effects by modulating the brightness of a base color over time. Inherits from `oscillator_value`.
| Parameter | Type | Default | Constraints | Description |
|-----------|------|---------|-------------|-------------|
| `base_color` | int | 0xFFFFFFFF | - | The base color to modulate (32-bit ARGB value) |
| `color` | int | 0xFFFFFFFF | - | The base color to modulate (32-bit ARGB value) |
| `min_brightness` | int | 0 | 0-255 | Minimum brightness level (breathing effect) |
| `max_brightness` | int | 255 | 0-255 | Maximum brightness level (breathing effect) |
| `duration` | int | 3000 | min: 1 | Time for one complete breathing cycle in ms |
| `curve_factor` | int | 2 | 1-5 | Breathing curve shape (1=cosine wave, 2-5=curved breathing with pauses) |
| *(inherits brightness from color_provider)* | | | | Overall brightness scaling applied after breathing effect |
| *(inherits all oscillator_value parameters)* | | | | |
**Curve Factor Effects:**
@ -480,7 +468,7 @@ Creates breathing/pulsing color effects by modulating the brightness of a base c
```berry
# Natural breathing effect
color breathing_red = breathe_color(
base_color=red,
color=red,
min_brightness=20,
max_brightness=255,
duration=4s,
@ -489,7 +477,7 @@ color breathing_red = breathe_color(
# Fast pulsing effect
color pulse_blue = breathe_color(
base_color=blue,
color=blue,
min_brightness=50,
max_brightness=200,
duration=1s,
@ -498,7 +486,7 @@ color pulse_blue = breathe_color(
# Slow, deep breathing
color deep_breath = breathe_color(
base_color=purple,
color=purple,
min_brightness=5,
max_brightness=255,
duration=6s,
@ -508,7 +496,7 @@ color deep_breath = breathe_color(
# Using dynamic base color
color rainbow_cycle = color_cycle(colors=bytes("FF0000FF" "FF00FF00" "FFFF0000"), period=5s)
color breathing_rainbow = breathe_color(
base_color=rainbow_cycle,
color=rainbow_cycle,
min_brightness=30,
max_brightness=255,
duration=3s,

View File

@ -377,7 +377,7 @@ color rainbow_cycle = color_cycle(
period=5s
)
color breathing_red = breathe_color(
base_color=red
color=red
min_brightness=5%
max_brightness=100%
duration=3s
@ -385,7 +385,7 @@ color breathing_red = breathe_color(
)
color pulsing_blue = breathe_color(
curve_factor=1
base_color=blue
color=blue
min_brightness=20%
max_brightness=80%
duration=1s
@ -1420,7 +1420,7 @@ Color providers create dynamic colors that change over time:
| Function | Description |
|----------|-------------|
| `static_color` | Solid color with optional dynamic opacity |
| `color_provider` | Solid color (base class for all color providers) |
| `color_cycle` | Cycles through a palette of colors |
| `rich_palette_color` | Advanced palette-based color cycling with smooth transitions |
| `breathe_color` | Breathing/pulsing color effect with brightness modulation |

View File

@ -117,8 +117,6 @@ import "providers/color_cycle_color_provider.be" as color_cycle_color_provider
register_to_animation(color_cycle_color_provider)
# import "providers/composite_color_provider.be" as composite_color_provider
# register_to_animation(composite_color_provider)
import "providers/static_color_provider.be" as static_color_provider
register_to_animation(static_color_provider)
import "providers/rich_palette_color_provider.be" as rich_palette_color_provider
register_to_animation(rich_palette_color_provider)
import "providers/breathe_color_provider.be" as breathe_color_provider

View File

@ -43,10 +43,10 @@ class breathe : animation.animation
super(self).on_param_changed(name, value)
# Propagate relevant parameters to the breathe provider
if name == "color"
# When color is set, update the breathe_provider's base_color
# When color is set, update the breathe_provider's color
# but keep the breathe_provider as the actual color source for rendering
if type(value) == 'int'
self.breathe_provider.base_color = value
self.breathe_provider.color = value
# Restore the breathe_provider as the color source (bypass on_param_changed)
self.values["color"] = self.breathe_provider
end

View File

@ -15,7 +15,7 @@ class breathe_color : animation.oscillator_value
# Additional parameter definitions for color-specific functionality
# The oscillator parameters (min_value, max_value, duration, form, etc.) are inherited
static var PARAMS = animation.enc_params({
"base_color": {"default": 0xFFFFFFFF}, # The base color to modulate (32-bit ARGB value)
"color": {"default": 0xFFFFFFFF}, # The base color to modulate (32-bit ARGB value)
"min_brightness": {"min": 0, "max": 255, "default": 0}, # Minimum brightness level (0-255)
"max_brightness": {"min": 0, "max": 255, "default": 255}, # Maximum brightness level (0-255)
"curve_factor": {"min": 1, "max": 5, "default": 2} # Factor to control breathing curve shape (1=cosine wave, 2-5=curved breathing with pauses)
@ -82,14 +82,14 @@ class breathe_color : animation.oscillator_value
# Now map the curved value to the brightness range
var brightness = tasmota.scale_uint(curved_value, 0, 255, self.min_brightness, self.max_brightness)
# Apply brightness to the base color
var current_base_color = self.base_color
# Apply brightness to the base color (using inherited 'color' parameter)
var current_color = self.color
# Extract RGB components
var alpha = (current_base_color >> 24) & 0xFF
var red = (current_base_color >> 16) & 0xFF
var green = (current_base_color >> 8) & 0xFF
var blue = current_base_color & 0xFF
var alpha = (current_color >> 24) & 0xFF
var red = (current_color >> 16) & 0xFF
var green = (current_color >> 8) & 0xFF
var blue = current_color & 0xFF
# Apply brightness scaling using tasmota.scale_uint
red = tasmota.scale_uint(red, 0, 255, 0, brightness)

View File

@ -22,6 +22,7 @@ class color_provider : animation.value_provider
# Parameter definitions
static var PARAMS = animation.enc_params({
"color": {"default": 0xFFFFFFFF}, # Default to white
"brightness": {"min": 0, "max": 255, "default": 255}
})
@ -43,20 +44,24 @@ class color_provider : animation.value_provider
end
# Produce a color value for any parameter name
# This is the main method that subclasses should override
# Returns the solid color with brightness applied
#
# @param name: string - Parameter name being requested
# @param time_ms: int - Current time in milliseconds
# @param name: string - Parameter name being requested (ignored)
# @param time_ms: int - Current time in milliseconds (ignored)
# @return int - Color in ARGB format (0xAARRGGBB)
def produce_value(name, time_ms)
return 0xFFFFFFFF # Default white
var color = self.color
var brightness = self.brightness
if brightness != 255
return self.apply_brightness(color, brightness)
end
return color
end
# Get a color based on a value (0-255 range)
# This method is useful for mapping values to colors in different contexts
# Get the solid color for a value (ignores the value)
#
# @param value: int/float - Value to map to a color (0-255 range)
# @param time_ms: int - Optional current time for time-based effects
# @param value: int/float - Value to map to a color (ignored)
# @param time_ms: int - Current time in milliseconds (ignored)
# @return int - Color in ARGB format (0xAARRGGBB)
def get_color_for_value(value, time_ms)
return self.produce_value("color", time_ms) # Default: use time-based color

View File

@ -1,47 +0,0 @@
# static_color for Berry Animation Framework
#
# This color provider returns a single, static color.
# It's the simplest implementation of the color_provider interface.
#
# Follows the parameterized class specification:
# - Constructor takes only 'engine' parameter
# - All other parameters set via virtual member assignment after creation
import "./core/param_encoder" as encode_constraints
class static_color : animation.color_provider
# Parameter definitions
static var PARAMS = animation.enc_params({
"color": {"default": 0xFFFFFFFF} # Default to white
})
# Produce the solid color for any parameter name
#
# @param name: string - Parameter name being requested (ignored)
# @param time_ms: int - Current time in milliseconds (ignored)
# @return int - Color in ARGB format (0xAARRGGBB)
def produce_value(name, time_ms)
var color = self.color
var brightness = self.brightness
if brightness != 255
return self.apply_brightness(color, brightness)
end
return color
end
# Get the solid color for a value (ignores the value)
#
# @param value: int/float - Value to map to a color (ignored)
# @param time_ms: int - Current time in milliseconds (ignored)
# @return int - Color in ARGB format (0xAARRGGBB)
def get_color_for_value(value, time_ms)
var color = self.color
var brightness = self.brightness
if brightness != 255
return self.apply_brightness(color, brightness)
end
return color
end
end
return {'static_color': static_color}

View File

@ -19,40 +19,6 @@ class static_value : animation.value_provider
"value": {"default": nil, "type": "any"}
})
# # Comparison operators to make static_value work with validation code
# def <(other)
# return self.value < int(other)
# end
# def >(other)
# return self.value > int(other)
# end
# def <=(other)
# return self.value <= int(other)
# end
# def >=(other)
# return self.value >= int(other)
# end
# def ==(other)
# if type(other) == 'instance'
# import introspect
# return introspect.toptr(self) == introspect.toptr(other)
# else
# return self.value == int(other)
# end
# end
# def !=(other)
# if type(other) == 'instance'
# import introspect
# return introspect.toptr(self) != introspect.toptr(other)
# else
# return self.value != int(other)
# end
# end
# Produce the static value for any parameter name
#
@ -62,11 +28,6 @@ class static_value : animation.value_provider
def produce_value(name, time_ms)
return self.value
end
# String representation of the provider
# def tostring()
# return f"static_value(value={self.value})"
# end
end
return {'static_value': static_value}

View File

@ -19,7 +19,7 @@ def test_atomic_closure_batch_execution()
var seq_manager = animation.sequence_manager(engine)
# Create two test animations
var red_provider = animation.static_color(engine)
var red_provider = animation.color_provider(engine)
red_provider.color = 0xFFFF0000
var red_anim = animation.solid(engine)
red_anim.color = red_provider
@ -27,7 +27,7 @@ def test_atomic_closure_batch_execution()
red_anim.duration = 0
red_anim.loop = true
var blue_provider = animation.static_color(engine)
var blue_provider = animation.color_provider(engine)
blue_provider.color = 0xFF0000FF
var blue_anim = animation.solid(engine)
blue_anim.color = blue_provider
@ -87,7 +87,7 @@ def test_multiple_consecutive_closures()
var seq_manager = animation.sequence_manager(engine)
# Create test animations
var green_provider = animation.static_color(engine)
var green_provider = animation.color_provider(engine)
green_provider.color = 0xFF00FF00
var green_anim = animation.solid(engine)
green_anim.color = green_provider
@ -95,7 +95,7 @@ def test_multiple_consecutive_closures()
green_anim.duration = 0
green_anim.loop = true
var yellow_provider = animation.static_color(engine)
var yellow_provider = animation.color_provider(engine)
yellow_provider.color = 0xFFFFFF00
var yellow_anim = animation.solid(engine)
yellow_anim.color = yellow_provider
@ -154,7 +154,7 @@ def test_closure_batch_at_sequence_start()
var seq_manager = animation.sequence_manager(engine)
# Create test animation
var purple_provider = animation.static_color(engine)
var purple_provider = animation.color_provider(engine)
purple_provider.color = 0xFF8000FF
var purple_anim = animation.solid(engine)
purple_anim.color = purple_provider
@ -192,7 +192,7 @@ def test_repeat_sequence_closure_batching()
var engine = animation.create_engine(strip)
# Create test animation
var cyan_provider = animation.static_color(engine)
var cyan_provider = animation.color_provider(engine)
cyan_provider.color = 0xFF00FFFF
var cyan_anim = animation.solid(engine)
cyan_anim.color = cyan_provider
@ -262,7 +262,7 @@ def test_black_frame_fix_integration()
var engine = animation.create_engine(strip)
# Simulate shutter animation
var shutter_provider = animation.static_color(engine)
var shutter_provider = animation.color_provider(engine)
shutter_provider.color = 0xFFFFFFFF
var shutter_anim = animation.solid(engine)
shutter_anim.color = shutter_provider

View File

@ -21,7 +21,7 @@ var anim = animation.breathe(engine)
print("Created breathe animation with defaults")
# Test default values
print(f"Default color: 0x{anim.breathe_provider.base_color :08x}")
print(f"Default color: 0x{anim.breathe_provider.color :08x}")
print(f"Default min_brightness: {anim.min_brightness}")
print(f"Default max_brightness: {anim.max_brightness}")
print(f"Default period: {anim.period}")
@ -35,7 +35,7 @@ blue_breathe.max_brightness = 200
blue_breathe.period = 4000
blue_breathe.curve_factor = 3
blue_breathe.priority = 15
print(f"Blue breathe animation color: 0x{blue_breathe.breathe_provider.base_color :08x}")
print(f"Blue breathe animation color: 0x{blue_breathe.breathe_provider.color :08x}")
print(f"Blue breathe animation min_brightness: {blue_breathe.min_brightness}")
print(f"Blue breathe animation max_brightness: {blue_breathe.max_brightness}")
print(f"Blue breathe animation period: {blue_breathe.period}")
@ -48,7 +48,7 @@ red_breathe.min_brightness = 10
red_breathe.max_brightness = 180
red_breathe.period = 3000
red_breathe.curve_factor = 2
print(f"Red breathe animation color: 0x{red_breathe.breathe_provider.base_color :08x}")
print(f"Red breathe animation color: 0x{red_breathe.breathe_provider.color :08x}")
# Test parameter updates using virtual member assignment
blue_breathe.min_brightness = 30
@ -133,7 +133,7 @@ print("✓ Animation added to engine successfully")
assert(anim != nil, "Default breathe animation should be created")
assert(blue_breathe != nil, "Custom breathe animation should be created")
assert(red_breathe != nil, "Red breathe animation should be created")
assert(blue_breathe.breathe_provider.base_color == 0xFF0000FF, "Blue breathe should have correct color")
assert(blue_breathe.breathe_provider.color == 0xFF0000FF, "Blue breathe should have correct color")
assert(blue_breathe.min_brightness == 30, "Min brightness should be updated to 30")
assert(blue_breathe.max_brightness == 220, "Max brightness should be updated to 220")
assert(blue_breathe.period == 3500, "Breathe period should be updated to 3500")

View File

@ -21,7 +21,7 @@ var provider = animation.breathe_color(engine)
print("Created breathe color provider with defaults")
# Test default values
print(f"Default base_color: 0x{provider.base_color :08x}")
print(f"Default color: 0x{provider.color :08x}")
print(f"Default min_brightness: {provider.min_brightness}")
print(f"Default max_brightness: {provider.max_brightness}")
print(f"Default duration: {provider.duration}")
@ -34,12 +34,12 @@ print(f"Inherited max_value: {provider.max_value}")
# Create another breathe color provider and set custom parameters using virtual member assignment
var blue_breathe = animation.breathe_color(engine)
blue_breathe.base_color = 0xFF0000FF
blue_breathe.color = 0xFF0000FF
blue_breathe.min_brightness = 20
blue_breathe.max_brightness = 200
blue_breathe.duration = 4000
blue_breathe.curve_factor = 3
print(f"Blue breathe color provider base_color: 0x{blue_breathe.base_color :08x}")
print(f"Blue breathe color provider color: 0x{blue_breathe.color :08x}")
print(f"Blue breathe color provider min_brightness: {blue_breathe.min_brightness}")
print(f"Blue breathe color provider max_brightness: {blue_breathe.max_brightness}")
print(f"Blue breathe color provider duration: {blue_breathe.duration}")
@ -47,12 +47,12 @@ print(f"Blue breathe color provider curve_factor: {blue_breathe.curve_factor}")
# Create red breathe color provider with different parameters
var red_breathe = animation.breathe_color(engine)
red_breathe.base_color = 0xFFFF0000
red_breathe.color = 0xFFFF0000
red_breathe.min_brightness = 10
red_breathe.max_brightness = 180
red_breathe.duration = 3000
red_breathe.curve_factor = 2
print(f"Red breathe color provider base_color: 0x{red_breathe.base_color :08x}")
print(f"Red breathe color provider color: 0x{red_breathe.color :08x}")
# Test parameter updates using virtual member assignment
blue_breathe.min_brightness = 30
@ -105,7 +105,7 @@ print(f"Color at full cycle: 0x{color_full :08x}")
# Test curve factor effects
var curve_1_provider = animation.breathe_color(engine)
curve_1_provider.base_color = 0xFF00FF00 # Green
curve_1_provider.color = 0xFF00FF00 # Green
curve_1_provider.curve_factor = 1
curve_1_provider.duration = 2000
curve_1_provider.min_brightness = 50 # Set non-zero minimum to see differences
@ -114,7 +114,7 @@ curve_1_provider.start(engine.time_ms)
curve_1_provider.produce_value(nil, start_time) # force first tick
var curve_5_provider = animation.breathe_color(engine)
curve_5_provider.base_color = 0xFF00FF00 # Green
curve_5_provider.color = 0xFF00FF00 # Green
curve_5_provider.curve_factor = 5
curve_5_provider.duration = 2000
curve_5_provider.min_brightness = 50 # Set non-zero minimum to see differences
@ -161,7 +161,7 @@ end
# Test brightness range behavior
var brightness_test = animation.breathe_color(engine)
brightness_test.base_color = 0xFFFFFFFF # White
brightness_test.color = 0xFFFFFFFF # White
brightness_test.min_brightness = 50
brightness_test.max_brightness = 200
brightness_test.duration = 1000
@ -182,7 +182,7 @@ print(f"Max brightness test - expected around 200, got: {max_brightness_actual}"
# Test color preservation (alpha channel should be preserved)
var alpha_test = animation.breathe_color(engine)
alpha_test.base_color = 0x80FF0000 # Red with 50% alpha
alpha_test.color = 0x80FF0000 # Red with 50% alpha
alpha_test.start(engine.time_ms)
alpha_test.produce_value(nil, start_time) # force first tick
var alpha_color = alpha_test.produce_value("color", engine.time_ms)
@ -196,7 +196,7 @@ print(f"Provider string representation: {str(blue_breathe)}")
assert(provider != nil, "Default breathe color provider should be created")
assert(blue_breathe != nil, "Custom breathe color provider should be created")
assert(red_breathe != nil, "Red breathe color provider should be created")
assert(blue_breathe.base_color == 0xFF0000FF, "Blue breathe should have correct base color")
assert(blue_breathe.color == 0xFF0000FF, "Blue breathe should have correct color")
assert(blue_breathe.min_brightness == 30, "Min brightness should be updated to 30")
assert(blue_breathe.max_brightness == 220, "Max brightness should be updated to 220")
assert(blue_breathe.duration == 3500, "Duration should be updated to 3500")

View File

@ -263,7 +263,7 @@ assert_test(head_alpha > tail_alpha, f"Head should be less transparent than tail
print("\n--- Test 8: Color Provider Integration ---")
# Test with solid color provider
var solid_provider = animation.static_color(engine)
var solid_provider = animation.color_provider(engine)
solid_provider.color = 0xFF00FFFF
var provider_comet = animation.comet(engine)
provider_comet.color = solid_provider

View File

@ -274,7 +274,6 @@ assert_array_equal(form_enum, [1, 2, 3, 4, 5, 6, 7, 8, 9], "5.5a: form enum")
# Test 5.6: breathe PARAMS
var breathe_params = {
"base_color": {"default": 0xFFFFFFFF},
"min_brightness": {"min": 0, "max": 255, "default": 0},
"max_brightness": {"min": 0, "max": 255, "default": 255},
"period": {"min": 100, "default": 3000},

View File

@ -56,7 +56,7 @@ def test_crenel_with_color_provider()
var blue_color = 0xFF0000FF # Blue
# Create a solid color provider
var color_provider = animation.static_color(engine)
var color_provider = animation.color_provider(engine)
color_provider.color = blue_color
# Create animation with new parameterized pattern
@ -211,7 +211,7 @@ def test_crenel_set_color_methods()
assert(result1 == true, "Render with new integer color should succeed")
# Test setting color provider via direct assignment
var yellow_provider = animation.static_color(engine)
var yellow_provider = animation.color_provider(engine)
yellow_provider.color = 0xFFFFFF00 # Yellow
crenel.color = yellow_provider
crenel.update(1000)
@ -249,7 +249,7 @@ def test_crenel_tostring()
print(f"Integer color string: {str_int}")
# Test with color provider
var color_provider = animation.static_color(engine)
var color_provider = animation.color_provider(engine)
color_provider.color = 0xFF00FF00
var crenel_provider = animation.crenel(engine)

View File

@ -13,7 +13,7 @@ def test_basic_nested_calls()
var dsl_code =
"# strip length 30 # TEMPORARILY DISABLED\n"
"color custom_red = 0xFF0000\n"
"animation pulse_red = breathe(color=static_color(color=custom_red), period=3s)\n"
"animation pulse_red = breathe(color=color_provider(color=custom_red), period=3s)\n"
"run pulse_red"
try
@ -24,7 +24,7 @@ def test_basic_nested_calls()
import string
assert(string.find(berry_code, "animation.breathe(engine)") >= 0,
"Generated code should contain breathe with engine parameter")
assert(string.find(berry_code, "animation.static_color(engine)") >= 0,
assert(string.find(berry_code, "animation.color_provider(engine)") >= 0,
"Generated code should contain nested static_color function call")
except "dsl_compilation_error" as e, msg
assert(false, f"DSL compilation should not fail: {msg}")
@ -39,7 +39,7 @@ def test_deep_nesting()
var dsl_code =
"# strip length 30 # TEMPORARILY DISABLED\n"
"animation complex = breathe(color=static_color(color=red), period=2s)\n"
"animation complex = breathe(color=color_provider(color=red), period=2s)\n"
"run complex"
try
@ -49,7 +49,7 @@ def test_deep_nesting()
# Check that the generated code contains nested calls
import string
assert(string.find(berry_code, "animation.breathe(") >= 0, "Should contain breathe function")
assert(string.find(berry_code, "animation.static_color(") >= 0, "Should contain static_color function")
assert(string.find(berry_code, "animation.color_provider(") >= 0, "Should contain static_color function")
except "dsl_compilation_error" as e, msg
assert(false, f"DSL compilation should not fail: {msg}")
end
@ -63,7 +63,7 @@ def test_mixed_parameter_types()
var dsl_code =
"# strip length 30 # TEMPORARILY DISABLED\n"
"animation mixed = breathe(color=static_color(color=blue), period=2s, max_brightness=80%)\n"
"animation mixed = breathe(color=color_provider(color=blue), period=2s, max_brightness=80%)\n"
"run mixed"
try
@ -72,7 +72,7 @@ def test_mixed_parameter_types()
# Check that different parameter types are handled correctly
import string
assert(string.find(berry_code, "animation.static_color(engine)") >= 0,
assert(string.find(berry_code, "animation.color_provider(engine)") >= 0,
"Should contain nested static_color function call")
assert(string.find(berry_code, "2000") >= 0, "Should contain time parameter")
assert(string.find(berry_code, "204") >= 0, "Should contain percentage converted to 0-255 range")
@ -89,7 +89,7 @@ def test_nested_calls_in_arrays()
var dsl_code =
"# strip length 30 # TEMPORARILY DISABLED\n"
"animation cycle = breathe(color=static_color(color=red), period=5s)\n"
"animation cycle = breathe(color=color_provider(color=red), period=5s)\n"
"run cycle"
try
@ -100,7 +100,7 @@ def test_nested_calls_in_arrays()
import string
assert(string.find(berry_code, "animation.breathe(engine)") >= 0,
"Should contain breathe function call")
assert(string.find(berry_code, "animation.static_color(engine)") >= 0,
assert(string.find(berry_code, "animation.color_provider(engine)") >= 0,
"Should contain nested static_color function call")
except "dsl_compilation_error" as e, msg
assert(false, f"DSL compilation should not fail: {msg}")
@ -116,7 +116,7 @@ def test_error_handling()
# Test unclosed parentheses
var dsl_code1 =
"# strip length 30 # TEMPORARILY DISABLED\n"
"animation bad = breathe(color=static_color(color=red)\n" # Missing closing paren
"animation bad = breathe(color=color_provider(color=red)\n" # Missing closing paren
"run bad"
try
@ -151,7 +151,7 @@ def test_complex_real_world_example()
"# strip length 60 # TEMPORARILY DISABLED\n"
"color sunset_red = 0xFF4500\n"
"animation evening = breathe(\n"
" color=static_color(color=sunset_red),\n"
" color=color_provider(color=sunset_red),\n"
" period=10s\n"
")\n"
"run evening"
@ -163,7 +163,7 @@ def test_complex_real_world_example()
# Verify the structure is preserved
import string
assert(string.find(berry_code, "animation.breathe(") >= 0, "Should contain breathe")
assert(string.find(berry_code, "animation.static_color(") >= 0, "Should contain static_color")
assert(string.find(berry_code, "animation.color_provider(") >= 0, "Should contain static_color")
except "dsl_compilation_error" as e, msg
assert(false, f"DSL compilation should not fail: {msg}")
end
@ -178,7 +178,7 @@ def test_generated_code_validity()
var dsl_code =
"# strip length 30 # TEMPORARILY DISABLED\n"
"color custom_red = 0xFF0000\n"
"animation test = breathe(color=static_color(color=custom_red), period=3s)\n"
"animation test = breathe(color=color_provider(color=custom_red), period=3s)\n"
"run test"
try

View File

@ -217,14 +217,14 @@ def test_dsl_parameter_validation()
end
# Test valid color provider parameter
var valid_color_dsl = "color solid_red = static_color(color = red)\n" +
var valid_color_dsl = "color solid_red = color_provider(color = red)\n" +
"solid_red.color = blue"
var result2 = animation_dsl.compile(valid_color_dsl)
assert(result2 != nil, "Valid color provider parameter should compile successfully")
# Test invalid color provider parameter
var invalid_color_dsl = "color solid_red = static_color(color = red)\n" +
var invalid_color_dsl = "color solid_red = color_provider(color = red)\n" +
"solid_red.invalid_param = 123"
try
@ -358,7 +358,7 @@ def test_dsl_symbol_table_mixed_types()
assert(result1 != nil, "Animation property assignment should work")
# Test 2: Valid property assignment on color provider (instance in symbol table)
var color_property_dsl = "color solid_red = static_color(color = red)\n" +
var color_property_dsl = "color solid_red = color_provider(color = red)\n" +
"solid_red.color = blue"
var result2 = animation_dsl.compile(color_property_dsl)
@ -381,7 +381,7 @@ def test_dsl_symbol_table_mixed_types()
# Test 4: Mixed symbol table with sequences and instances
var mixed_dsl = "animation red_anim = beacon(color = red)\n" +
"color solid_blue = static_color(color = blue)\n" +
"color solid_blue = color_provider(color = blue)\n" +
"sequence demo {\n" +
" play red_anim for 2s\n" +
"}\n" +
@ -420,7 +420,7 @@ def test_dsl_identifier_reference_symbol_table()
assert(result2 != nil, "Parameter validation on referenced animation should work")
# Test 3: Color provider reference should be added to symbol table
var color_ref_dsl = "color base_red = static_color(color=red)\n" +
var color_ref_dsl = "color base_red = color_provider(color=red)\n" +
"color my_red = base_red\n" +
"animation red_anim = solid(color=my_red)\n" +
"my_red.color = blue"

View File

@ -21,7 +21,7 @@ var anim = animation.breathe(engine)
print("Created pulse animation with defaults")
# Test default values
print(f"Default color: 0x{anim.breathe_provider.base_color :08x}")
print(f"Default color: 0x{anim.breathe_provider.color :08x}")
print(f"Default min_brightness: {anim.min_brightness}")
print(f"Default max_brightness: {anim.max_brightness}")
print(f"Default period: {anim.period}")
@ -33,7 +33,7 @@ blue_pulse.color = 0xFF0000FF
blue_pulse.min_brightness = 50
blue_pulse.max_brightness = 200
blue_pulse.period = 2000
print(f"Blue pulse animation color: 0x{blue_pulse.breathe_provider.base_color :08x}")
print(f"Blue pulse animation color: 0x{blue_pulse.breathe_provider.color :08x}")
print(f"Blue pulse animation min_brightness: {blue_pulse.min_brightness}")
print(f"Blue pulse animation max_brightness: {blue_pulse.max_brightness}")
print(f"Blue pulse animation period: {blue_pulse.period}")
@ -45,7 +45,7 @@ red_pulse.color = 0xFFFF0000 # Red color
red_pulse.min_brightness = 20
red_pulse.max_brightness = 180
red_pulse.period = 1500
print(f"Red pulse animation color: 0x{red_pulse.breathe_provider.base_color :08x}")
print(f"Red pulse animation color: 0x{red_pulse.breathe_provider.color :08x}")
# Test parameter updates using virtual member assignment
blue_pulse.min_brightness = 30
@ -104,7 +104,7 @@ print(f"First pixel after rendering: 0x{frame.get_pixel_color(0) :08x}")
# Validate key test results
assert(anim != nil, "Default pulse animation should be created")
assert(blue_pulse != nil, "Custom pulse animation should be created")
assert(blue_pulse.breathe_provider.base_color == 0xFF0000FF, "Blue pulse should have correct color")
assert(blue_pulse.breathe_provider.color == 0xFF0000FF, "Blue pulse should have correct color")
assert(blue_pulse.min_brightness == 30, "Min brightness should be updated to 30")
assert(blue_pulse.max_brightness == 220, "Max brightness should be updated to 220")
assert(blue_pulse.period == 1800, "Pulse period should be updated to 1800")

View File

@ -26,7 +26,7 @@ def test_multiple_sequence_managers()
assert(size(engine.root_animation.sequences) == 3, "Engine should have 3 sequence managers")
# Create test animations using new parameterized API
var red_provider = animation.static_color(engine)
var red_provider = animation.color_provider(engine)
red_provider.color = 0xFFFF0000
var red_anim = animation.solid(engine)
red_anim.color = red_provider
@ -35,7 +35,7 @@ def test_multiple_sequence_managers()
red_anim.loop = false
red_anim.opacity = 255
var green_provider = animation.static_color(engine)
var green_provider = animation.color_provider(engine)
green_provider.color = 0xFF00FF00
var green_anim = animation.solid(engine)
green_anim.color = green_provider
@ -44,7 +44,7 @@ def test_multiple_sequence_managers()
green_anim.loop = false
green_anim.opacity = 255
var blue_provider = animation.static_color(engine)
var blue_provider = animation.color_provider(engine)
blue_provider.color = 0xFF0000FF
var blue_anim = animation.solid(engine)
blue_anim.color = blue_provider
@ -94,7 +94,7 @@ def test_sequence_manager_coordination()
engine.add(seq_manager2)
# Create test animations using new parameterized API
var provider1 = animation.static_color(engine)
var provider1 = animation.color_provider(engine)
provider1.color = 0xFFFF0000
var anim1 = animation.solid(engine)
anim1.color = provider1
@ -103,7 +103,7 @@ def test_sequence_manager_coordination()
anim1.loop = false
anim1.opacity = 255
var provider2 = animation.static_color(engine)
var provider2 = animation.color_provider(engine)
provider2.color = 0xFF00FF00
var anim2 = animation.solid(engine)
anim2.color = provider2
@ -159,7 +159,7 @@ def test_sequence_manager_engine_integration()
engine.add(seq_manager2)
# Create test animations using new parameterized API
var provider1 = animation.static_color(engine)
var provider1 = animation.color_provider(engine)
provider1.color = 0xFFFF0000
var test_anim1 = animation.solid(engine)
test_anim1.color = provider1
@ -168,7 +168,7 @@ def test_sequence_manager_engine_integration()
test_anim1.loop = false
test_anim1.opacity = 255
var provider2 = animation.static_color(engine)
var provider2 = animation.color_provider(engine)
provider2.color = 0xFF00FF00
var test_anim2 = animation.solid(engine)
test_anim2.color = provider2
@ -259,7 +259,7 @@ def test_sequence_manager_clear_all()
engine.add(seq_manager2)
# Create test animations and sequences using new parameterized API
var provider1 = animation.static_color(engine)
var provider1 = animation.color_provider(engine)
provider1.color = 0xFFFF0000
var test_anim1 = animation.solid(engine)
test_anim1.color = provider1
@ -268,7 +268,7 @@ def test_sequence_manager_clear_all()
test_anim1.loop = false
test_anim1.opacity = 255
var provider2 = animation.static_color(engine)
var provider2 = animation.color_provider(engine)
provider2.color = 0xFF00FF00
var test_anim2 = animation.solid(engine)
test_anim2.color = provider2
@ -324,7 +324,7 @@ def test_sequence_manager_stress()
engine.on_tick(120000) # Update engine time
for i : 0..9
var provider = animation.static_color(engine)
var provider = animation.color_provider(engine)
provider.color = 0xFF000000 + (i * 0x001100)
var test_anim = animation.solid(engine)
test_anim.color = provider

View File

@ -37,7 +37,7 @@ def test_sequence_manager_step_creation()
# Create test animation using new parameterized API
var strip = global.Leds(30)
var engine = animation.create_engine(strip)
var color_provider = animation.static_color(engine)
var color_provider = animation.color_provider(engine)
color_provider.color = 0xFFFF0000
var test_anim = animation.solid(engine)
test_anim.color = color_provider
@ -79,7 +79,7 @@ def test_sequence_manager_execution()
var seq_manager = animation.sequence_manager(engine)
# Create test animations using new parameterized API
var color_provider1 = animation.static_color(engine)
var color_provider1 = animation.color_provider(engine)
color_provider1.color = 0xFFFF0000
var anim1 = animation.solid(engine)
anim1.color = color_provider1
@ -87,7 +87,7 @@ def test_sequence_manager_execution()
anim1.duration = 0
anim1.loop = true
var color_provider2 = animation.static_color(engine)
var color_provider2 = animation.color_provider(engine)
color_provider2.color = 0xFF00FF00
var anim2 = animation.solid(engine)
anim2.color = color_provider2
@ -125,7 +125,7 @@ def test_sequence_manager_timing()
var seq_manager = animation.sequence_manager(engine)
# Create test animation using new parameterized API
var color_provider = animation.static_color(engine)
var color_provider = animation.color_provider(engine)
color_provider.color = 0xFFFF0000
var test_anim = animation.solid(engine)
test_anim.color = color_provider
@ -178,7 +178,7 @@ def test_sequence_manager_step_info()
var seq_manager = animation.sequence_manager(engine)
# Create test sequence using new parameterized API
var color_provider = animation.static_color(engine)
var color_provider = animation.color_provider(engine)
color_provider.color = 0xFFFF0000
var test_anim = animation.solid(engine)
test_anim.color = color_provider
@ -207,7 +207,7 @@ def test_sequence_manager_stop()
var seq_manager = animation.sequence_manager(engine)
# Create test sequence using new parameterized API
var color_provider = animation.static_color(engine)
var color_provider = animation.color_provider(engine)
color_provider.color = 0xFFFF0000
var test_anim = animation.solid(engine)
test_anim.color = color_provider
@ -244,7 +244,7 @@ def test_sequence_manager_is_running()
assert(seq_manager.is_sequence_running() == false, "Sequence should not be running initially")
# Create and start sequence using new parameterized API
var color_provider = animation.static_color(engine)
var color_provider = animation.color_provider(engine)
color_provider.color = 0xFFFF0000
var test_anim = animation.solid(engine)
test_anim.color = color_provider
@ -278,7 +278,7 @@ def test_sequence_manager_assignment_steps()
var seq_manager = animation.sequence_manager(engine)
# Create test animation using new parameterized API
var color_provider = animation.static_color(engine)
var color_provider = animation.color_provider(engine)
color_provider.color = 0xFFFF0000
var test_anim = animation.solid(engine)
test_anim.color = color_provider
@ -336,7 +336,7 @@ def test_sequence_manager_complex_sequence()
var seq_manager = animation.sequence_manager(engine)
# Create multiple test animations using new parameterized API
var red_provider = animation.static_color(engine)
var red_provider = animation.color_provider(engine)
red_provider.color = 0xFFFF0000
var red_anim = animation.solid(engine)
red_anim.color = red_provider
@ -344,7 +344,7 @@ def test_sequence_manager_complex_sequence()
red_anim.duration = 0
red_anim.loop = true
var green_provider = animation.static_color(engine)
var green_provider = animation.color_provider(engine)
green_provider.color = 0xFF00FF00
var green_anim = animation.solid(engine)
green_anim.color = green_provider
@ -352,7 +352,7 @@ def test_sequence_manager_complex_sequence()
green_anim.duration = 0
green_anim.loop = true
var blue_provider = animation.static_color(engine)
var blue_provider = animation.color_provider(engine)
blue_provider.color = 0xFF0000FF
var blue_anim = animation.solid(engine)
blue_anim.color = blue_provider
@ -416,7 +416,7 @@ def test_sequence_manager_integration()
engine.add(seq_manager)
# Create test sequence using new parameterized API
var color_provider = animation.static_color(engine)
var color_provider = animation.color_provider(engine)
color_provider.color = 0xFFFF0000
var test_anim = animation.solid(engine)
test_anim.color = color_provider
@ -496,7 +496,7 @@ def test_sequence_manager_repeat_execution_with_functions()
var engine = animation.create_engine(strip)
# Create test animation
var color_provider = animation.static_color(engine)
var color_provider = animation.color_provider(engine)
color_provider.color = 0xFF00FF00
var test_anim = animation.solid(engine)
test_anim.color = color_provider
@ -584,7 +584,7 @@ def test_sequence_manager_dynamic_repeat_changes()
var engine = animation.create_engine(strip)
# Create test animation
var color_provider = animation.static_color(engine)
var color_provider = animation.color_provider(engine)
color_provider.color = 0xFF0080FF
var test_anim = animation.solid(engine)
test_anim.color = color_provider
@ -696,7 +696,7 @@ def test_sequence_manager_zero_iterations()
var engine = animation.create_engine(strip)
# Create test animation
var color_provider = animation.static_color(engine)
var color_provider = animation.color_provider(engine)
color_provider.color = 0xFFFF0000
var test_anim = animation.solid(engine)
test_anim.color = color_provider
@ -818,7 +818,7 @@ def test_sequence_manager_boolean_repeat_counts()
var engine = animation.create_engine(strip)
# Create test animation
var color_provider = animation.static_color(engine)
var color_provider = animation.color_provider(engine)
color_provider.color = 0xFF00FF00
var test_anim = animation.solid(engine)
test_anim.color = color_provider
@ -931,7 +931,7 @@ def test_sequence_manager_false_conditional_immediate_skip()
var engine = animation.create_engine(strip)
# Create test animations
var color_provider1 = animation.static_color(engine)
var color_provider1 = animation.color_provider(engine)
color_provider1.color = 0xFFFF0000 # Red
var anim1 = animation.solid(engine)
anim1.color = color_provider1
@ -939,7 +939,7 @@ def test_sequence_manager_false_conditional_immediate_skip()
anim1.duration = 0
anim1.loop = true
var color_provider2 = animation.static_color(engine)
var color_provider2 = animation.color_provider(engine)
color_provider2.color = 0xFF00FF00 # Green
var anim2 = animation.solid(engine)
anim2.color = color_provider2
@ -992,7 +992,7 @@ def test_sequence_manager_false_conditional_immediate_skip()
var strip2 = global.Leds(30)
var engine2 = animation.create_engine(strip2)
var color_provider3 = animation.static_color(engine2)
var color_provider3 = animation.color_provider(engine2)
color_provider3.color = 0xFFFF0000 # Red
var anim3 = animation.solid(engine2)
anim3.color = color_provider3
@ -1000,7 +1000,7 @@ def test_sequence_manager_false_conditional_immediate_skip()
anim3.duration = 0
anim3.loop = true
var color_provider4 = animation.static_color(engine2)
var color_provider4 = animation.color_provider(engine2)
color_provider4.color = 0xFF00FF00 # Green
var anim4 = animation.solid(engine2)
anim4.color = color_provider4
@ -1046,7 +1046,7 @@ def test_sequence_manager_all_false_conditionals_no_infinite_loop()
var engine = animation.create_engine(strip)
# Create test animation (should never be used)
var color_provider = animation.static_color(engine)
var color_provider = animation.color_provider(engine)
color_provider.color = 0xFFFF0000
var test_anim = animation.solid(engine)
test_anim.color = color_provider

View File

@ -57,7 +57,7 @@ blue_anim.opacity = 200
print(f"Blue animation - priority: {blue_anim.priority}, duration: {blue_anim.duration}, loop: {blue_anim.loop}")
# Test 4: Create animation with value_provider
var solid_provider = animation.static_color(engine)
var solid_provider = animation.color_provider(engine)
solid_provider.color = 0xFF00FF00 # Green
var green_anim = animation.solid(engine)
green_anim.color = solid_provider # Use value_provider as dynamic parameter

View File

@ -81,7 +81,7 @@ def test_solid_color_provider()
print("Testing solid() with color provider...")
# Create a color provider using engine-only constructor
var color_provider = animation.static_color(engine)
var color_provider = animation.color_provider(engine)
color_provider.color = 0xFFFFFF00 # Yellow
# Create solid animation with color provider