Berry animation native frame_buffer and optimization (#23986)
This commit is contained in:
parent
217bc7e3a5
commit
0b891392b1
@ -490,7 +490,7 @@ import animation
|
||||
def test_my_animation()
|
||||
# Create LED strip and engine for testing
|
||||
var strip = global.Leds(10) # Use built-in LED strip for testing
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test basic construction
|
||||
var anim = animation.my_animation(engine)
|
||||
@ -532,7 +532,7 @@ Test with the animation engine:
|
||||
|
||||
```berry
|
||||
var strip = global.Leds(30) # Use built-in LED strip
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var anim = animation.my_animation(engine)
|
||||
|
||||
# Set parameters
|
||||
|
||||
@ -19,7 +19,7 @@ var globs = "path,ctypes_bytes_dyn,tasmota,ccronexpr,gpio,light,webclient,load,M
|
||||
for g:string2.split(globs, ",")
|
||||
global.(g) = nil
|
||||
end
|
||||
# special case to declane animation
|
||||
# special case to declare animation
|
||||
global.animation = module("animation")
|
||||
|
||||
var prefix_dir = "src/"
|
||||
|
||||
@ -17,18 +17,20 @@
|
||||
# 2: `slew_size`, number of pixels to fade from back to fore color, can be `0`
|
||||
# 3: `beacon_size`, number of pixels of the beacon
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:BeaconAnimation,weak
|
||||
class BeaconAnimation : animation.animation
|
||||
# NO instance variables for parameters - they are handled by the virtual parameter system
|
||||
|
||||
# Parameter definitions following the new specification
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"color": {"default": 0xFFFFFFFF},
|
||||
"back_color": {"default": 0xFF000000},
|
||||
"pos": {"default": 0},
|
||||
"beacon_size": {"min": 0, "default": 1},
|
||||
"slew_size": {"min": 0, "default": 0}
|
||||
}
|
||||
})
|
||||
|
||||
# Render the beacon to the provided frame buffer
|
||||
#
|
||||
|
||||
@ -8,19 +8,21 @@
|
||||
# - curve_factor 1: Pure cosine wave (equivalent to pulse animation)
|
||||
# - curve_factor 2-5: Natural breathing with pauses at peaks (5 = most pronounced pauses)
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:BreatheAnimation,weak
|
||||
class BreatheAnimation : animation.animation
|
||||
# Non-parameter instance variables only
|
||||
var breathe_provider # Internal breathe color provider
|
||||
|
||||
# Parameter definitions following parameterized class specification
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"base_color": {"default": 0xFFFFFFFF}, # The base color to breathe (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)
|
||||
"period": {"min": 100, "default": 3000}, # Time for one complete breathe cycle in milliseconds
|
||||
"curve_factor": {"min": 1, "max": 5, "default": 2} # Factor to control breathing curve shape (1=cosine wave, 2-5=curved breathing with pauses)
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new Breathe animation
|
||||
# Following parameterized class specification - engine parameter only
|
||||
|
||||
@ -6,20 +6,22 @@
|
||||
# The comet uses sub-pixel positioning (1/256th pixels) for smooth movement and supports
|
||||
# both wrapping around the strip and bouncing off the ends.
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:CometAnimation,weak
|
||||
class CometAnimation : animation.animation
|
||||
# Non-parameter instance variables only
|
||||
var head_position # Current position of the comet head (in 1/256th pixels for smooth movement)
|
||||
|
||||
# Parameter definitions following parameterized class specification
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
# 'color' for the comet head (32-bit ARGB value), inherited from animation class
|
||||
"tail_length": {"min": 1, "max": 50, "default": 5}, # Length of the comet tail in pixels
|
||||
"speed": {"min": 1, "max": 25600, "default": 2560}, # Movement speed in 1/256th pixels per second
|
||||
"direction": {"enum": [-1, 1], "default": 1}, # Direction of movement (1 = forward, -1 = backward)
|
||||
"wrap_around": {"min": 0, "max": 1, "default": 1}, # Whether comet wraps around the strip (bool)
|
||||
"fade_factor": {"min": 0, "max": 255, "default": 179} # How quickly the tail fades (0-255, 255 = no fade)
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new Comet animation
|
||||
# Following parameterized class specification - engine parameter only
|
||||
|
||||
@ -18,19 +18,21 @@
|
||||
# 3: `low_size`, number of pixel until next pos - full cycle is 2 + 3
|
||||
# 4: `nb_pulse`, number of pulses, or `-1` for infinite
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:CrenelPositionAnimation,weak
|
||||
class CrenelPositionAnimation : animation.animation
|
||||
# NO instance variables for parameters - they are handled by the virtual parameter system
|
||||
|
||||
# Parameter definitions with constraints
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
# 'color' for the comet head (32-bit ARGB value), inherited from animation class
|
||||
"back_color": {"default": 0xFF000000}, # background color, TODO change to transparent
|
||||
"pos": {"default": 0}, # start of the pulse (in pixel)
|
||||
"pulse_size": {"min": 0, "default": 1}, # number of pixels of the pulse
|
||||
"low_size": {"min": 0, "default": 3}, # number of pixel until next pos - full cycle is 2 + 3
|
||||
"nb_pulse": {"default": -1} # number of pulses, or `-1` for infinite
|
||||
}
|
||||
})
|
||||
|
||||
# Render the crenel pattern to the provided frame buffer
|
||||
#
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
# This animation creates a realistic fire effect with flickering flames.
|
||||
# The fire uses random intensity variations and warm colors to simulate flames.
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:FireAnimation,weak
|
||||
class FireAnimation : animation.animation
|
||||
# Non-parameter instance variables only
|
||||
@ -12,14 +14,14 @@ class FireAnimation : animation.animation
|
||||
var random_seed # Seed for random number generation
|
||||
|
||||
# Parameter definitions following parameterized class specification
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
# 'color' for the comet head (32-bit ARGB value), inherited from animation class
|
||||
"intensity": {"min": 0, "max": 255, "default": 180},
|
||||
"flicker_speed": {"min": 1, "max": 20, "default": 8},
|
||||
"flicker_amount": {"min": 0, "max": 255, "default": 100},
|
||||
"cooling_rate": {"min": 0, "max": 255, "default": 55},
|
||||
"sparking_rate": {"min": 0, "max": 255, "default": 120}
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new Fire animation
|
||||
#
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
# This animation creates smooth color gradients that can be linear or radial,
|
||||
# with optional movement and color transitions over time.
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:GradientAnimation,weak
|
||||
class GradientAnimation : animation.animation
|
||||
# Non-parameter instance variables only
|
||||
@ -10,14 +12,14 @@ class GradientAnimation : animation.animation
|
||||
var phase_offset # Current phase offset for movement
|
||||
|
||||
# Parameter definitions following parameterized class specification
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"color": {"default": nil, "nillable": true},
|
||||
"gradient_type": {"min": 0, "max": 1, "default": 0},
|
||||
"direction": {"min": 0, "max": 255, "default": 0},
|
||||
"center_pos": {"min": 0, "max": 255, "default": 128},
|
||||
"spread": {"min": 1, "max": 255, "default": 255},
|
||||
"movement_speed": {"min": 0, "max": 255, "default": 0}
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new Gradient animation
|
||||
def init(engine)
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
# This animation creates pseudo-random noise patterns with configurable
|
||||
# scale, speed, and color mapping through palettes or single colors.
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:NoiseAnimation,weak
|
||||
class NoiseAnimation : animation.animation
|
||||
# Non-parameter instance variables only
|
||||
@ -11,14 +13,14 @@ class NoiseAnimation : animation.animation
|
||||
var noise_table # Pre-computed noise values for performance
|
||||
|
||||
# Parameter definitions following new specification
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"color": {"default": nil},
|
||||
"scale": {"min": 1, "max": 255, "default": 50},
|
||||
"speed": {"min": 0, "max": 255, "default": 30},
|
||||
"octaves": {"min": 1, "max": 4, "default": 1},
|
||||
"persistence": {"min": 0, "max": 255, "default": 128},
|
||||
"seed": {"min": 0, "max": 65535, "default": 12345}
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new Noise animation
|
||||
def init(engine)
|
||||
|
||||
@ -6,16 +6,18 @@
|
||||
# This version supports both RichPaletteAnimation and ColorProvider instances as color sources,
|
||||
# allowing for more flexible usage of color providers.
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:PalettePatternAnimation,weak
|
||||
class PalettePatternAnimation : animation.animation
|
||||
var value_buffer # Buffer to store values for each pixel (bytes object)
|
||||
|
||||
# Static definitions of parameters with constraints
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
# Palette pattern-specific parameters
|
||||
"color_source": {"default": nil, "type": "instance"},
|
||||
"pattern_func": {"default": nil, "type": "function"}
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new PalettePattern animation
|
||||
#
|
||||
@ -158,11 +160,11 @@ end
|
||||
#@ solidify:PaletteWaveAnimation,weak
|
||||
class PaletteWaveAnimation : PalettePatternAnimation
|
||||
# Static definitions of parameters with constraints
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
# Wave-specific parameters only
|
||||
"wave_period": {"min": 1, "default": 5000},
|
||||
"wave_length": {"min": 1, "default": 10}
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new wave pattern animation
|
||||
#
|
||||
@ -211,12 +213,12 @@ end
|
||||
#@ solidify:PaletteGradientAnimation,weak
|
||||
class PaletteGradientAnimation : PalettePatternAnimation
|
||||
# Static definitions of parameters with constraints
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
# Gradient-specific parameters only
|
||||
"shift_period": {"min": 0, "default": 0}, # Time for one complete shift cycle in ms (0 = static)
|
||||
"spatial_period": {"min": 0, "default": 0}, # Spatial period in pixels (0 = full strip)
|
||||
"phase_shift": {"min": 0, "max": 100, "default": 0} # Phase shift as percentage (0-100)
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new gradient pattern animation
|
||||
#
|
||||
@ -273,10 +275,10 @@ end
|
||||
#@ solidify:PaletteMeterAnimation,weak
|
||||
class PaletteMeterAnimation : PalettePatternAnimation
|
||||
# Static definitions of parameters with constraints
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
# Meter-specific parameters only
|
||||
"value_func": {"default": nil, "type": "function"}
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new meter pattern animation
|
||||
#
|
||||
|
||||
@ -7,13 +7,15 @@
|
||||
#
|
||||
# Follows the parameterized class specification with parameter forwarding pattern.
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:RichPaletteAnimation,weak
|
||||
class RichPaletteAnimation : animation.animation
|
||||
# Non-parameter instance variables only
|
||||
var color_provider # Internal RichPaletteColorProvider instance
|
||||
|
||||
# Parameter definitions - only RichPaletteColorProvider parameters (Animation params inherited)
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
# RichPaletteColorProvider parameters (forwarded to internal provider)
|
||||
"palette": {"type": "instance", "default": nil},
|
||||
"cycle_period": {"min": 0, "default": 5000},
|
||||
@ -21,7 +23,7 @@ class RichPaletteAnimation : animation.animation
|
||||
"brightness": {"min": 0, "max": 255, "default": 255},
|
||||
"range_min": {"default": 0},
|
||||
"range_max": {"default": 255}
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new RichPaletteAnimation
|
||||
#
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
# This animation creates a twinkling stars effect with random lights
|
||||
# appearing and fading at different positions with customizable density and timing.
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:TwinkleAnimation,weak
|
||||
class TwinkleAnimation : animation.animation
|
||||
# NO instance variables for parameters - they are handled by the virtual parameter system
|
||||
@ -14,14 +16,14 @@ class TwinkleAnimation : animation.animation
|
||||
var random_seed # Seed for random number generation
|
||||
|
||||
# Parameter definitions with constraints
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"color": {"default": 0xFFFFFFFF},
|
||||
"density": {"min": 0, "max": 255, "default": 128},
|
||||
"twinkle_speed": {"min": 1, "max": 5000, "default": 6},
|
||||
"fade_speed": {"min": 0, "max": 255, "default": 180},
|
||||
"min_brightness": {"min": 0, "max": 255, "default": 32},
|
||||
"max_brightness": {"min": 0, "max": 255, "default": 255}
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new Twinkle animation
|
||||
#
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
# This animation creates various wave patterns (sine, triangle, square, sawtooth)
|
||||
# with configurable amplitude, frequency, phase, and movement speed.
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:WaveAnimation,weak
|
||||
class WaveAnimation : animation.animation
|
||||
# Non-parameter instance variables only
|
||||
@ -11,7 +13,7 @@ class WaveAnimation : animation.animation
|
||||
var wave_table # Pre-computed wave table for performance
|
||||
|
||||
# Parameter definitions for WaveAnimation
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"color": {"default": 0xFFFF0000},
|
||||
"back_color": {"default": 0xFF000000},
|
||||
"wave_type": {"min": 0, "max": 3, "default": 0},
|
||||
@ -20,7 +22,7 @@ class WaveAnimation : animation.animation
|
||||
"phase": {"min": 0, "max": 255, "default": 0},
|
||||
"wave_speed": {"min": 0, "max": 255, "default": 50},
|
||||
"center_level": {"min": 0, "max": 255, "default": 128}
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new Wave animation
|
||||
#
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
# This animation creates bouncing effects where patterns bounce back and forth
|
||||
# across the LED strip with configurable physics and damping.
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:BounceAnimation,weak
|
||||
class BounceAnimation : animation.animation
|
||||
# Non-parameter instance variables only
|
||||
@ -14,13 +16,13 @@ class BounceAnimation : animation.animation
|
||||
var last_update_time # Last update time for physics calculation
|
||||
|
||||
# Parameter definitions following parameterized class specification
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"source_animation": {"type": "instance", "default": nil},
|
||||
"bounce_speed": {"min": 0, "max": 255, "default": 128},
|
||||
"bounce_range": {"min": 0, "max": 1000, "default": 0},
|
||||
"damping": {"min": 0, "max": 255, "default": 250},
|
||||
"gravity": {"min": 0, "max": 255, "default": 0}
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new Bounce animation
|
||||
def init(engine)
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
# This animation adds random jitter/shake effects to patterns with configurable
|
||||
# intensity, frequency, and jitter types (position, color, brightness).
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:JitterAnimation,weak
|
||||
class JitterAnimation : animation.animation
|
||||
# Non-parameter instance variables only
|
||||
@ -13,7 +15,7 @@ class JitterAnimation : animation.animation
|
||||
var current_colors # Array of current colors for each pixel
|
||||
|
||||
# Parameter definitions
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"source_animation": {"type": "instance", "default": nil},
|
||||
"jitter_intensity": {"min": 0, "max": 255, "default": 100},
|
||||
"jitter_frequency": {"min": 0, "max": 255, "default": 60},
|
||||
@ -21,7 +23,7 @@ class JitterAnimation : animation.animation
|
||||
"position_range": {"min": 0, "max": 255, "default": 50},
|
||||
"color_range": {"min": 0, "max": 255, "default": 30},
|
||||
"brightness_range": {"min": 0, "max": 255, "default": 40}
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new Jitter animation
|
||||
def init(engine)
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
# This animation creates classic plasma effects using sine wave interference
|
||||
# patterns with configurable frequencies, phases, and time-based animation.
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:PlasmaAnimation,weak
|
||||
class PlasmaAnimation : animation.animation
|
||||
# Non-parameter instance variables only
|
||||
@ -10,7 +12,7 @@ class PlasmaAnimation : animation.animation
|
||||
var time_phase # Current time-based phase
|
||||
|
||||
# Parameter definitions following parameterized class specification
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"color": {"default": nil},
|
||||
"freq_x": {"min": 1, "max": 255, "default": 32},
|
||||
"freq_y": {"min": 1, "max": 255, "default": 23},
|
||||
@ -18,7 +20,7 @@ class PlasmaAnimation : animation.animation
|
||||
"phase_y": {"min": 0, "max": 255, "default": 64},
|
||||
"time_speed": {"min": 0, "max": 255, "default": 50},
|
||||
"blend_mode": {"min": 0, "max": 2, "default": 0}
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new Plasma animation
|
||||
#
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
# This animation scales patterns up or down with configurable scaling factors,
|
||||
# interpolation methods, and center points.
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:ScaleAnimation,weak
|
||||
class ScaleAnimation : animation.animation
|
||||
# Non-parameter instance variables only
|
||||
@ -12,14 +14,14 @@ class ScaleAnimation : animation.animation
|
||||
var start_time # Animation start time
|
||||
|
||||
# Parameter definitions following parameterized class specification
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"source_animation": {"type": "instance", "default": nil},
|
||||
"scale_factor": {"min": 1, "max": 255, "default": 128},
|
||||
"scale_speed": {"min": 0, "max": 255, "default": 0},
|
||||
"scale_mode": {"min": 0, "max": 3, "default": 0},
|
||||
"scale_center": {"min": 0, "max": 255, "default": 128},
|
||||
"interpolation": {"min": 0, "max": 1, "default": 1}
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new Scale animation
|
||||
# @param engine: AnimationEngine - Required animation engine
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
# This animation shifts/scrolls patterns horizontally across the LED strip
|
||||
# with configurable speed, direction, and wrapping behavior.
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:ShiftAnimation,weak
|
||||
class ShiftAnimation : animation.animation
|
||||
# Non-parameter instance variables only
|
||||
@ -11,12 +13,12 @@ class ShiftAnimation : animation.animation
|
||||
var current_colors # Array of current colors for each pixel
|
||||
|
||||
# Parameter definitions with constraints
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"source_animation": {"type": "instance", "default": nil},
|
||||
"shift_speed": {"min": 0, "max": 255, "default": 128},
|
||||
"direction": {"min": -1, "max": 1, "default": 1},
|
||||
"wrap_around": {"type": "bool", "default": true}
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new Shift animation
|
||||
def init(engine)
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
# This animation creates random sparkles that appear and fade out over time,
|
||||
# with configurable density, fade speed, and colors.
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:SparkleAnimation,weak
|
||||
class SparkleAnimation : animation.animation
|
||||
# Non-parameter instance variables only
|
||||
@ -13,7 +15,7 @@ class SparkleAnimation : animation.animation
|
||||
var last_update # Last update time for frame timing
|
||||
|
||||
# Parameter definitions following parameterized class specification
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"color": {"default": 0xFFFFFFFF},
|
||||
"back_color": {"default": 0xFF000000},
|
||||
"density": {"min": 0, "max": 255, "default": 30},
|
||||
@ -21,7 +23,7 @@ class SparkleAnimation : animation.animation
|
||||
"sparkle_duration": {"min": 0, "max": 255, "default": 60},
|
||||
"min_brightness": {"min": 0, "max": 255, "default": 100},
|
||||
"max_brightness": {"min": 0, "max": 255, "default": 255}
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new Sparkle animation
|
||||
# @param engine: AnimationEngine - Required animation engine reference
|
||||
|
||||
@ -31,6 +31,7 @@ class be_class_FrameBufferNtv (scope: global, name: FrameBufferNtv, strings: wea
|
||||
apply_opacity, static_func(be_animation_ntv_apply_opacity)
|
||||
apply_brightness, static_func(be_animation_ntv_apply_brightness)
|
||||
fill_pixels, static_func(be_animation_ntv_fill_pixels)
|
||||
// paste_pixels, func(be_leds_paste_pixels)
|
||||
}
|
||||
@const_object_info_end */
|
||||
|
||||
|
||||
@ -603,6 +603,47 @@ extern "C" {
|
||||
|
||||
be_return_nil(vm);
|
||||
}
|
||||
|
||||
// // Leds_frame.paste_pixels(neopixel:bytes(), led_buffer:bytes(), bri:int 0..100, gamma:bool)
|
||||
// //
|
||||
// // Copy from ARGB buffer to RGB
|
||||
// int32_t be_leds_paste_pixels(bvm *vm);
|
||||
// int32_t be_leds_paste_pixels(bvm *vm) {
|
||||
// int32_t top = be_top(vm); // Get the number of arguments
|
||||
// if (top >= 2 && be_isbytes(vm, 2)) {
|
||||
// size_t src_len = 0;
|
||||
// uint32_t * src_buf = (uint32_t*) be_tobytes(vm, 1, &src_len);
|
||||
// size_t dest_len = 0;
|
||||
// uint8_t * dest_buf = (uint8_t*) be_tobytes(vm, 2, &dest_len);
|
||||
|
||||
// uint32_t bri255 = 255;
|
||||
// if (top >= 3 && be_isint(vm, 3)) {
|
||||
// bri255 = be_toint(vm, 3);
|
||||
// }
|
||||
// bool gamma = false;
|
||||
// if (top >= 4 && be_isbool(vm, 4)) {
|
||||
// gamma = be_tobool(vm, 4);
|
||||
// }
|
||||
|
||||
// size_t pixels_count = src_len / 4;
|
||||
// if (pixels_count > dest_len / 3) { pixels_count = dest_len / 3; }
|
||||
// if (pixels_count > 0) {
|
||||
// for (size_t i = 0; i < pixels_count; i++) {
|
||||
// uint32_t src_argb = ApplyBriGamma(src_buf[i], bri255, gamma);
|
||||
// uint32_t src_r = (src_argb >> 16) & 0xFF;
|
||||
// uint32_t src_g = (src_argb >> 8) & 0xFF;
|
||||
// uint32_t src_b = (src_argb ) & 0xFF;
|
||||
// dest_buf[i * 3 + 0] = src_r;
|
||||
// dest_buf[i * 3 + 1] = src_g;
|
||||
// dest_buf[i * 3 + 2] = src_b;
|
||||
// }
|
||||
// }
|
||||
// be_return_nil(vm);
|
||||
// }
|
||||
// be_raise(vm, "type_error", nullptr);
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // USE_BERRY_ANIMATION
|
||||
|
||||
@ -7,19 +7,21 @@
|
||||
# This is the unified base class for all visual elements in the framework.
|
||||
# A Pattern is simply an Animation with infinite duration (duration = 0).
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
class Animation : animation.parameterized_object
|
||||
# Non-parameter instance variables only
|
||||
var opacity_frame # Frame buffer for opacity animation rendering
|
||||
|
||||
# Parameter definitions
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"name": {"type": "string", "default": "animation"}, # Optional name for the animation
|
||||
"priority": {"min": 0, "default": 10}, # Rendering priority (higher = on top, 0-255)
|
||||
"duration": {"min": 0, "default": 0}, # Animation duration in ms (0 = infinite)
|
||||
"loop": {"type": "bool", "default": false}, # Whether to loop when duration is reached
|
||||
"opacity": {"type": "any", "default": 255}, # Animation opacity (0-255 number or Animation instance)
|
||||
"color": {"default": 0xFFFFFFFF} # Base color in ARGB format (0xAARRGGBB)
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new animation
|
||||
#
|
||||
|
||||
@ -165,9 +165,7 @@ class AnimationEngine
|
||||
return self._add_animation(obj)
|
||||
else
|
||||
# Unknown type - provide helpful error message
|
||||
import introspect
|
||||
var class_name = introspect.name(obj)
|
||||
raise "type_error", f"Cannot add object of type '{class_name}' to engine. Expected Animation or SequenceManager."
|
||||
raise "type_error", "only Animation or SequenceManager"
|
||||
end
|
||||
end
|
||||
|
||||
@ -182,8 +180,7 @@ class AnimationEngine
|
||||
elif isinstance(obj, animation.animation)
|
||||
return self.remove_animation(obj)
|
||||
else
|
||||
# Unknown type - provide helpful error message
|
||||
raise "type_error", f"Cannot remove object of type '{classname(obj)}' from engine. Expected Animation or SequenceManager."
|
||||
# Unknown type - ignore
|
||||
end
|
||||
end
|
||||
|
||||
@ -502,14 +499,8 @@ class AnimationEngine
|
||||
|
||||
# String representation
|
||||
def tostring()
|
||||
return f"AnimationEngine(running={self.is_running}, animations={size(self.animations)}, width={self.width})"
|
||||
return f"AnimationEngine(running={self.is_running})"
|
||||
end
|
||||
end
|
||||
|
||||
# Main function to create the animation engine
|
||||
def create_engine(strip)
|
||||
return animation.animation_engine(strip)
|
||||
end
|
||||
|
||||
return {'animation_engine': AnimationEngine,
|
||||
'create_engine': create_engine}
|
||||
return {'create_engine': AnimationEngine}
|
||||
@ -46,15 +46,15 @@ class EventHandler
|
||||
end
|
||||
|
||||
# Get handler info for debugging
|
||||
def get_info()
|
||||
return {
|
||||
"event_name": self.event_name,
|
||||
"priority": self.priority,
|
||||
"is_active": self.is_active,
|
||||
"has_condition": self.condition != nil,
|
||||
"metadata": self.metadata
|
||||
}
|
||||
end
|
||||
# def get_info()
|
||||
# return {
|
||||
# "event_name": self.event_name,
|
||||
# "priority": self.priority,
|
||||
# "is_active": self.is_active,
|
||||
# "has_condition": self.condition != nil,
|
||||
# "metadata": self.metadata
|
||||
# }
|
||||
# end
|
||||
end
|
||||
|
||||
#@ solidify:EventManager,weak
|
||||
|
||||
284
lib/libesp32/berry_animation/src/core/param_encoder.be
Normal file
284
lib/libesp32/berry_animation/src/core/param_encoder.be
Normal file
@ -0,0 +1,284 @@
|
||||
# Parameter Constraint Encoder for Berry Animation Framework
|
||||
#
|
||||
# This module provides functions to encode parameter constraints into a compact
|
||||
# bytes() format with type-prefixed values for maximum flexibility and correctness.
|
||||
#
|
||||
# Encoding Format:
|
||||
# ----------------
|
||||
# Byte 0: Constraint mask (bit field)
|
||||
# Bit 0 (0x01): has_min
|
||||
# Bit 1 (0x02): has_max
|
||||
# Bit 2 (0x04): has_default
|
||||
# Bit 3 (0x08): has_explicit_type
|
||||
# Bit 4 (0x10): has_enum
|
||||
# Bit 5 (0x20): is_nillable
|
||||
# Bits 6-7: reserved
|
||||
#
|
||||
# Bytes 1+: Values in order (min, max, default, enum)
|
||||
# Each value is prefixed with its own type byte, followed by the value data.
|
||||
#
|
||||
# Value Type Codes:
|
||||
# 0x00 = int8 (1 byte, signed -128 to 127)
|
||||
# 0x01 = int16 (2 bytes, signed -32768 to 32767)
|
||||
# 0x02 = int32 (4 bytes, signed integer)
|
||||
# 0x03 = string (1-byte length prefix + string bytes)
|
||||
# 0x04 = bytes (2-byte length prefix + byte data)
|
||||
# 0x05 = bool (1 byte, 0 or 1)
|
||||
# 0x06 = nil (0 bytes)
|
||||
#
|
||||
# Value Encoding (each value has: type_byte + data):
|
||||
# - min: [type_byte][value_data]
|
||||
# - max: [type_byte][value_data]
|
||||
# - default: [type_byte][value_data]
|
||||
# - enum: [count_byte][type_byte][value_data][type_byte][value_data]...
|
||||
# - explicit_type: [type_code] (only if has_explicit_type bit is set)
|
||||
#
|
||||
# Explicit Type Codes (semantic types for validation) (1 byte):
|
||||
# 0x00 = int
|
||||
# 0x01 = string
|
||||
# 0x02 = bytes
|
||||
# 0x03 = bool
|
||||
# 0x04 = any
|
||||
# 0x05 = instance
|
||||
# 0x06 = function
|
||||
|
||||
# Encode a full PARAMS map into a map of encoded constraints
|
||||
#
|
||||
# @param params_map: map - Map of parameter names to constraint definitions
|
||||
# @return map - Map of parameter names to encoded bytes() objects
|
||||
#
|
||||
# Example:
|
||||
# encode_constraints({"color": {"default": 0xFFFFFFFF}, "size": {"min": 0, "max": 255, "default": 128}})
|
||||
# => {"color": bytes("04 02 FFFFFFFF"), "size": bytes("07 00 00 FF 80")}
|
||||
def encode_constraints(params_map)
|
||||
# Nested function: Encode a single constraint map into bytes() format
|
||||
def encode_single_constraint(constraint_map)
|
||||
# Nested helper: Determine the appropriate type code for a value
|
||||
def get_type_code(value)
|
||||
var value_type = type(value)
|
||||
if value == nil return 0x06 #-NIL-#
|
||||
elif value_type == "bool" return 0x05 #-BOOL-#
|
||||
elif value_type == "string" return 0x03 #-STRING-#
|
||||
elif value_type == "instance" && isinstance(value, bytes) return 0x04 #-BYTES-#
|
||||
elif value_type == "int"
|
||||
# Use signed ranges: int8 for -128 to 127, int16 for larger values
|
||||
if value >= -128 && value <= 127 return 0x00 #-INT8-#
|
||||
elif value >= -32768 && value <= 32767 return 0x01 #-INT16-#
|
||||
else return 0x02 #-INT32-# end
|
||||
else return 0x02 #-INT32-# end
|
||||
end
|
||||
|
||||
# Nested helper: Encode a single value with its type prefix
|
||||
def encode_value_with_type(value, result)
|
||||
var type_code = get_type_code(value)
|
||||
result.add(type_code, 1) # Add type byte prefix
|
||||
|
||||
if type_code == 0x06 #-NIL-# return
|
||||
elif type_code == 0x05 #-BOOL-# result.add(value ? 1 : 0, 1)
|
||||
elif type_code == 0x00 #-INT8-# result.add(value & 0xFF, 1)
|
||||
elif type_code == 0x01 #-INT16-# result.add(value & 0xFFFF, 2)
|
||||
elif type_code == 0x02 #-INT32-# result.add(value, 4)
|
||||
elif type_code == 0x03 #-STRING-#
|
||||
var str_bytes = bytes().fromstring(value)
|
||||
result.add(size(str_bytes), 1)
|
||||
result .. str_bytes
|
||||
elif type_code == 0x04 #-BYTES-#
|
||||
result.add(size(value), 2)
|
||||
result .. value
|
||||
end
|
||||
end
|
||||
|
||||
var mask = 0
|
||||
var result = bytes()
|
||||
|
||||
# Reserve space for mask only (will be set at the end)
|
||||
result.resize(1)
|
||||
|
||||
# Helper: Convert explicit type string to type code
|
||||
def get_explicit_type_code(type_str)
|
||||
if type_str == "int" return 0x00
|
||||
elif type_str == "string" return 0x01
|
||||
elif type_str == "bytes" return 0x02
|
||||
elif type_str == "bool" return 0x03
|
||||
elif type_str == "any" return 0x04
|
||||
elif type_str == "instance" return 0x05
|
||||
elif type_str == "function" return 0x06
|
||||
end
|
||||
return 0x04 # Default to "any"
|
||||
end
|
||||
|
||||
# Check if explicit type is specified
|
||||
var explicit_type_code = nil
|
||||
if constraint_map.contains("type")
|
||||
explicit_type_code = get_explicit_type_code(constraint_map["type"])
|
||||
end
|
||||
|
||||
# Encode min value (with type prefix)
|
||||
if constraint_map.contains("min")
|
||||
mask |= 0x01 #-HAS_MIN-#
|
||||
encode_value_with_type(constraint_map["min"], result)
|
||||
end
|
||||
|
||||
# Encode max value (with type prefix)
|
||||
if constraint_map.contains("max")
|
||||
mask |= 0x02 #-HAS_MAX-#
|
||||
encode_value_with_type(constraint_map["max"], result)
|
||||
end
|
||||
|
||||
# Encode default value (with type prefix)
|
||||
if constraint_map.contains("default")
|
||||
mask |= 0x04 #-HAS_DEFAULT-#
|
||||
encode_value_with_type(constraint_map["default"], result)
|
||||
end
|
||||
|
||||
# Encode explicit type code if present (1 byte)
|
||||
if explicit_type_code != nil
|
||||
mask |= 0x08 #-HAS_EXPLICIT_TYPE-#
|
||||
result.add(explicit_type_code, 1)
|
||||
end
|
||||
|
||||
# Encode enum values (each with type prefix)
|
||||
if constraint_map.contains("enum")
|
||||
mask |= 0x10 #-HAS_ENUM-#
|
||||
var enum_list = constraint_map["enum"]
|
||||
result.add(size(enum_list), 1) # Enum count
|
||||
for val : enum_list
|
||||
encode_value_with_type(val, result)
|
||||
end
|
||||
end
|
||||
|
||||
# Set nillable flag
|
||||
if constraint_map.contains("nillable") && constraint_map["nillable"]
|
||||
mask |= 0x20 #-IS_NILLABLE-#
|
||||
end
|
||||
|
||||
# Write mask at the beginning
|
||||
result.set(0, mask, 1)
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
# Encode each parameter constraint
|
||||
var result = {}
|
||||
for param_name : params_map.keys()
|
||||
result[param_name] = encode_single_constraint(params_map[param_name])
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
# # Decode a single value from bytes according to type code
|
||||
# #
|
||||
# # @param encoded_bytes: bytes - bytes() object to read from
|
||||
# # @param offset: int - Offset to start reading from
|
||||
# # @param type_code: int - Type code for decoding
|
||||
# # @return [value, new_offset] - Decoded value and new offset
|
||||
# def decode_value(encoded_bytes, offset, type_code)
|
||||
# if type_code == 0x06 #-NIL-#
|
||||
# return [nil, offset]
|
||||
# elif type_code == 0x05 #-BOOL-#
|
||||
# return [encoded_bytes[offset] != 0, offset + 1]
|
||||
# elif type_code == 0x00 #-INT8-#
|
||||
# var val = encoded_bytes[offset]
|
||||
# # Handle signed int8
|
||||
# if val > 127
|
||||
# val = val - 256
|
||||
# end
|
||||
# return [val, offset + 1]
|
||||
# elif type_code == 0x01 #-INT16-#
|
||||
# var val = encoded_bytes.get(offset, 2)
|
||||
# # Handle signed int16
|
||||
# if val > 32767
|
||||
# val = val - 65536
|
||||
# end
|
||||
# return [val, offset + 2]
|
||||
# elif type_code == 0x02 #-INT32-#
|
||||
# return [encoded_bytes.get(offset, 4), offset + 4]
|
||||
# elif type_code == 0x03 #-STRING-#
|
||||
# var length = encoded_bytes[offset]
|
||||
# var str_bytes = encoded_bytes[offset + 1 .. offset + length]
|
||||
# return [str_bytes.asstring(), offset + 1 + length]
|
||||
# elif type_code == 0x04 #-BYTES-#
|
||||
# var length = encoded_bytes.get(offset, 2)
|
||||
# var byte_data = encoded_bytes[offset + 2 .. offset + 2 + length - 1]
|
||||
# return [byte_data, offset + 2 + length]
|
||||
# end
|
||||
#
|
||||
# return [nil, offset]
|
||||
# end
|
||||
|
||||
# # Decode an encoded constraint bytes() back into a map
|
||||
# #
|
||||
# # @param encoded_bytes: bytes - Encoded constraint as bytes() object
|
||||
# # @return map - Decoded constraint map
|
||||
# #
|
||||
# # Example:
|
||||
# # decode_constraint(bytes("07 00 00 FF 80"))
|
||||
# # => {"min": 0, "max": 255, "default": 128}
|
||||
# def decode_constraint(encoded_bytes)
|
||||
# if size(encoded_bytes) < 2
|
||||
# return {}
|
||||
# end
|
||||
#
|
||||
# var mask = encoded_bytes[0]
|
||||
# var type_code = encoded_bytes[1]
|
||||
# var offset = 2
|
||||
# var result = {}
|
||||
#
|
||||
# # Decode min value
|
||||
# if mask & 0x01 #-HAS_MIN-#
|
||||
# var decoded = decode_value(encoded_bytes, offset, type_code)
|
||||
# result["min"] = decoded[0]
|
||||
# offset = decoded[1]
|
||||
# end
|
||||
#
|
||||
# # Decode max value
|
||||
# if mask & 0x02 #-HAS_MAX-#
|
||||
# var decoded = decode_value(encoded_bytes, offset, type_code)
|
||||
# result["max"] = decoded[0]
|
||||
# offset = decoded[1]
|
||||
# end
|
||||
#
|
||||
# # Decode default value
|
||||
# if mask & 0x04 #-HAS_DEFAULT-#
|
||||
# var decoded = decode_value(encoded_bytes, offset, type_code)
|
||||
# result["default"] = decoded[0]
|
||||
# offset = decoded[1]
|
||||
# end
|
||||
#
|
||||
# # Decode enum values
|
||||
# if mask & 0x10 #-HAS_ENUM-#
|
||||
# var count = encoded_bytes[offset]
|
||||
# offset += 1
|
||||
# result["enum"] = []
|
||||
# var i = 0
|
||||
# while i < count
|
||||
# var decoded = decode_value(encoded_bytes, offset, type_code)
|
||||
# result["enum"].push(decoded[0])
|
||||
# offset = decoded[1]
|
||||
# i += 1
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Set nillable flag
|
||||
# if mask & 0x20 #-IS_NILLABLE-#
|
||||
# result["nillable"] = true
|
||||
# end
|
||||
#
|
||||
# # Add type annotation if not default int32
|
||||
# if type_code == 0x03 #-STRING-#
|
||||
# result["type"] = "string"
|
||||
# elif type_code == 0x04 #-BYTES-#
|
||||
# result["type"] = "bytes"
|
||||
# elif type_code == 0x05 #-BOOL-#
|
||||
# result["type"] = "bool"
|
||||
# elif type_code == 0x06 #-NIL-#
|
||||
# result["type"] = "nil"
|
||||
# end
|
||||
#
|
||||
# return result
|
||||
# end
|
||||
|
||||
# Export only the encode function (decode not needed - use constraint_mask/constraint_find instead)
|
||||
# Note: constraint_mask() and constraint_find() are static methods
|
||||
# in ParameterizedObject class for accessing encoded constraints
|
||||
return encode_constraints
|
||||
@ -8,22 +8,24 @@
|
||||
# through member() and setmember() methods. Subclasses should not declare instance
|
||||
# variables for parameters, but use the PARAMS system only.
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
class ParameterizedObject
|
||||
var values # Map storing all parameter values
|
||||
var engine # Reference to the animation engine
|
||||
var start_time # Time when object started (ms) (int), value is set at first call to update() or render()
|
||||
|
||||
# Static parameter definitions - should be overridden by subclasses
|
||||
static var PARAMS = {
|
||||
"is_running": {"type": "bool", "default": false} # Whether the object is active
|
||||
}
|
||||
static var PARAMS = encode_constraints(
|
||||
{"is_running": {"type": "bool", "default": false}
|
||||
}) # Whether the object is active
|
||||
|
||||
# Initialize parameter system
|
||||
#
|
||||
# @param engine: AnimationEngine - Reference to the animation engine (required)
|
||||
def init(engine)
|
||||
if engine == nil || type(engine) != "instance"
|
||||
raise "value_error", "ParameterizedObject requires an engine parameter"
|
||||
raise "value_error", "missing engine parameter"
|
||||
end
|
||||
|
||||
self.engine = engine
|
||||
@ -45,9 +47,10 @@ class ParameterizedObject
|
||||
for param_name : class_params.keys()
|
||||
# Only set if not already set (child class defaults take precedence)
|
||||
if !self.values.contains(param_name)
|
||||
var param_def = class_params[param_name]
|
||||
if param_def.contains("default")
|
||||
self.values[param_name] = param_def["default"]
|
||||
var encoded_constraints = class_params[param_name]
|
||||
# Use static method to check for default value
|
||||
if self.constraint_mask(encoded_constraints, "default")
|
||||
self.values[param_name] = self.constraint_find(encoded_constraints, "default")
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -86,7 +89,7 @@ class ParameterizedObject
|
||||
# Private method to get parameter definition from the class hierarchy
|
||||
#
|
||||
# @param name: string - Parameter name
|
||||
# @return map - Parameter definition or nil if not found
|
||||
# @return bytes - Encoded parameter constraints or nil if not found
|
||||
def _get_param_def(name)
|
||||
import introspect
|
||||
|
||||
@ -97,7 +100,7 @@ class ParameterizedObject
|
||||
if introspect.contains(current_class, "PARAMS")
|
||||
var class_params = current_class.PARAMS
|
||||
if class_params.contains(name)
|
||||
return class_params[name]
|
||||
return class_params[name] # Returns encoded bytes
|
||||
end
|
||||
end
|
||||
|
||||
@ -163,9 +166,9 @@ class ParameterizedObject
|
||||
def _resolve_parameter_value(name, time_ms)
|
||||
if !self.values.contains(name)
|
||||
# Return default if available from class hierarchy
|
||||
var param_def = self._get_param_def(name)
|
||||
if param_def != nil && param_def.contains("default")
|
||||
return param_def["default"]
|
||||
var encoded_constraints = self._get_param_def(name)
|
||||
if encoded_constraints != nil && self.constraint_mask(encoded_constraints, "default")
|
||||
return self.constraint_find(encoded_constraints, "default")
|
||||
end
|
||||
return nil
|
||||
end
|
||||
@ -188,9 +191,9 @@ class ParameterizedObject
|
||||
# @param value: any - Value to validate (may be modified for real->int conversion)
|
||||
# @return any - Validated value (potentially converted from real to int)
|
||||
def _validate_param(name, value)
|
||||
var constraints = self._get_param_def(name)
|
||||
if constraints == nil
|
||||
raise "value_error", f"Parameter '{name}' is not defined for class '{classname(self)}'"
|
||||
var encoded_constraints = self._get_param_def(name)
|
||||
if encoded_constraints == nil
|
||||
raise "attribute_error", f"'{classname(self)}' object has no attribute '{name}'"
|
||||
end
|
||||
|
||||
# Accept ValueProvider instances for all parameters
|
||||
@ -201,24 +204,21 @@ class ParameterizedObject
|
||||
# Handle nil values
|
||||
if value == nil
|
||||
# Check if nil is explicitly allowed via nillable attribute
|
||||
if constraints.contains("nillable") && constraints["nillable"] == true
|
||||
if self.constraint_mask(encoded_constraints, "nillable")
|
||||
return value # nil is allowed for this parameter
|
||||
end
|
||||
|
||||
# Check if there's a default value (nil is acceptable if there's a default)
|
||||
if constraints.contains("default")
|
||||
if self.constraint_mask(encoded_constraints, "default")
|
||||
return value # nil is acceptable, will use default
|
||||
end
|
||||
|
||||
# nil is not allowed for this parameter
|
||||
raise "value_error", f"Parameter '{name}' does not accept nil values"
|
||||
raise "value_error", f"'{name}' does not accept nil values"
|
||||
end
|
||||
|
||||
# Type validation - default type is "int" if not specified
|
||||
var expected_type = "int" # Default type
|
||||
if constraints.contains("type")
|
||||
expected_type = constraints["type"]
|
||||
end
|
||||
var expected_type = self.constraint_find(encoded_constraints, "type", "int")
|
||||
|
||||
# Get actual type for validation
|
||||
var actual_type = type(value)
|
||||
@ -235,29 +235,34 @@ class ParameterizedObject
|
||||
if actual_type == "instance" && isinstance(value, bytes)
|
||||
actual_type = "bytes"
|
||||
elif actual_type != "instance" || !isinstance(value, bytes)
|
||||
raise "value_error", f"Parameter '{name}' expects type '{expected_type}' but got '{actual_type}' (value: {value})"
|
||||
raise "value_error", f"'{name}' expects type '{expected_type}' but got '{actual_type}' (value: {value})"
|
||||
end
|
||||
elif expected_type != actual_type
|
||||
raise "value_error", f"Parameter '{name}' expects type '{expected_type}' but got '{actual_type}' (value: {value})"
|
||||
raise "value_error", f"'{name}' expects type '{expected_type}' but got '{actual_type}' (value: {value})"
|
||||
end
|
||||
end
|
||||
|
||||
# Range validation for integer values only
|
||||
if actual_type == "int"
|
||||
if constraints.contains("min") && value < constraints["min"]
|
||||
raise "value_error", f"Parameter '{name}' value {value} is below minimum {constraints['min']}"
|
||||
if self.constraint_mask(encoded_constraints, "min")
|
||||
var min_val = self.constraint_find(encoded_constraints, "min")
|
||||
if value < min_val
|
||||
raise "value_error", f"'{name}' value {value} is below minimum {min_val}"
|
||||
end
|
||||
end
|
||||
if constraints.contains("max") && value > constraints["max"]
|
||||
raise "value_error", f"Parameter '{name}' value {value} is above maximum {constraints['max']}"
|
||||
if self.constraint_mask(encoded_constraints, "max")
|
||||
var max_val = self.constraint_find(encoded_constraints, "max")
|
||||
if value > max_val
|
||||
raise "value_error", f"'{name}' value {value} is above maximum {max_val}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Enum validation
|
||||
if constraints.contains("enum")
|
||||
if self.constraint_mask(encoded_constraints, "enum")
|
||||
var valid = false
|
||||
import introspect
|
||||
var enum_list = constraints["enum"]
|
||||
var list_size = enum_list.size()
|
||||
var enum_list = self.constraint_find(encoded_constraints, "enum")
|
||||
var list_size = size(enum_list)
|
||||
var i = 0
|
||||
while (i < list_size)
|
||||
var enum_value = enum_list[i]
|
||||
@ -268,7 +273,7 @@ class ParameterizedObject
|
||||
i += 1
|
||||
end
|
||||
if !valid
|
||||
raise "value_error", f"Parameter '{name}' value {value} is not in allowed values {enum_list}"
|
||||
raise "value_error", f"'{name}' value {value} is not in allowed values {enum_list}"
|
||||
end
|
||||
end
|
||||
|
||||
@ -307,9 +312,9 @@ class ParameterizedObject
|
||||
end
|
||||
|
||||
# Fall back to parameter default from class hierarchy
|
||||
var param_def = self._get_param_def(name)
|
||||
if param_def != nil && param_def.contains("default")
|
||||
return param_def["default"]
|
||||
var encoded_constraints = self._get_param_def(name)
|
||||
if encoded_constraints != nil && self.constraint_mask(encoded_constraints, "default")
|
||||
return self.constraint_find(encoded_constraints, "default", default_value)
|
||||
end
|
||||
|
||||
return default_value
|
||||
@ -322,25 +327,13 @@ class ParameterizedObject
|
||||
# @param time_ms: int - Current time in milliseconds
|
||||
# @return any - The resolved value (static or from provider)
|
||||
def resolve_value(value, param_name, time_ms)
|
||||
if value == nil
|
||||
return nil
|
||||
end
|
||||
|
||||
if animation.is_value_provider(value)
|
||||
if animation.is_value_provider(value) # this also captures 'nil'
|
||||
return value.produce_value(param_name, time_ms)
|
||||
else
|
||||
return value
|
||||
end
|
||||
end
|
||||
|
||||
# Get parameter metadata
|
||||
#
|
||||
# @param name: string - Parameter name
|
||||
# @return map - Parameter metadata or nil if not found
|
||||
def get_param_metadata(name)
|
||||
return self._get_param_def(name)
|
||||
end
|
||||
|
||||
# Helper method to get a resolved value from either a static value or a value provider
|
||||
# This is the same as accessing obj.param_name but with explicit time
|
||||
#
|
||||
@ -362,9 +355,9 @@ class ParameterizedObject
|
||||
if time_ms == nil
|
||||
time_ms = self.engine.time_ms
|
||||
end
|
||||
if time_ms == nil
|
||||
raise "value_error", "engine.time_ms should not be 'nil'"
|
||||
end
|
||||
# if time_ms == nil
|
||||
# raise "value_error", "engine.time_ms should not be 'nil'"
|
||||
# end
|
||||
if self.start_time == nil
|
||||
self.start_time = time_ms
|
||||
end
|
||||
@ -384,9 +377,9 @@ class ParameterizedObject
|
||||
if time_ms == nil
|
||||
time_ms = self.engine.time_ms
|
||||
end
|
||||
if time_ms == nil
|
||||
raise "value_error", "engine.time_ms should not be 'nil'"
|
||||
end
|
||||
# if time_ms == nil
|
||||
# raise "value_error", "engine.time_ms should not be 'nil'"
|
||||
# end
|
||||
if self.start_time != nil # reset time only if it was already started
|
||||
self.start_time = time_ms
|
||||
end
|
||||
@ -431,6 +424,260 @@ class ParameterizedObject
|
||||
def !=(other)
|
||||
return !(self == other)
|
||||
end
|
||||
|
||||
# ============================================================================
|
||||
# STATIC METHODS FOR ENCODED CONSTRAINT ACCESS
|
||||
# ============================================================================
|
||||
# PARAMETER CONSTRAINT ENCODING
|
||||
# ==============================
|
||||
#
|
||||
# Parameter constraints are encoded into a compact bytes() format for efficient
|
||||
# storage and transmission. Each value is prefixed with its own type byte for
|
||||
# maximum flexibility and correctness.
|
||||
#
|
||||
# Byte 0: Constraint mask (bit field)
|
||||
# Bit 0 (0x01): has_min
|
||||
# Bit 1 (0x02): has_max
|
||||
# Bit 2 (0x04): has_default
|
||||
# Bit 3 (0x08): has_explicit_type
|
||||
# Bit 4 (0x10): has_enum
|
||||
# Bit 5 (0x20): is_nillable
|
||||
# Bits 6-7: reserved
|
||||
#
|
||||
# Bytes 1+: Type-prefixed values in order (min, max, default, enum)
|
||||
# Each value consists of: [type_byte][value_data]
|
||||
#
|
||||
# Value Type Codes:
|
||||
# 0x00 = int8 (1 byte, signed -128 to 127)
|
||||
# 0x01 = int16 (2 bytes, signed -32768 to 32767)
|
||||
# 0x02 = int32 (4 bytes, signed integer)
|
||||
# 0x03 = string (1-byte length prefix + string bytes)
|
||||
# 0x04 = bytes (2-byte length prefix + byte data)
|
||||
# 0x05 = bool (1 byte, 0 or 1)
|
||||
# 0x06 = nil (0 bytes)
|
||||
#
|
||||
# Explicit Type Codes (semantic types for validation) (1 byte):
|
||||
# 0x00 = int
|
||||
# 0x01 = string
|
||||
# 0x02 = bytes
|
||||
# 0x03 = bool
|
||||
# 0x04 = any
|
||||
# 0x05 = instance
|
||||
# 0x06 = function
|
||||
#
|
||||
# ENCODING EXAMPLES:
|
||||
#
|
||||
# {"min": 0, "max": 255, "default": 128}
|
||||
# => bytes("07 00 00 01 00FF 00 0080") # 8 bytes
|
||||
# Breakdown:
|
||||
# 07 = mask (has_min|has_max|has_default)
|
||||
# 00 00 = min (type=int8, value=0)
|
||||
# 01 00FF = max (type=int16, value=255)
|
||||
# 00 0080 = default (type=int8, value=128)
|
||||
#
|
||||
# {"enum": [1, 2, 3], "default": 1}
|
||||
# => bytes("0C 00 01 03 00 01 00 02 00 03") # 10 bytes
|
||||
# Breakdown:
|
||||
# 0C = mask (has_enum|has_default)
|
||||
# 00 01 = default (type=int8, value=1)
|
||||
# 03 = enum count (3 values)
|
||||
# 00 01 = enum[0] (type=int8, value=1)
|
||||
# 00 02 = enum[1] (type=int8, value=2)
|
||||
# 00 03 = enum[2] (type=int8, value=3)
|
||||
#
|
||||
# {"default": nil, "nillable": true}
|
||||
# => bytes("14 06") # 2 bytes
|
||||
# Breakdown:
|
||||
# 14 = mask (has_default|is_nillable)
|
||||
# 06 = default (type=nil, no value data)
|
||||
#
|
||||
# USAGE:
|
||||
#
|
||||
# Encoding constraints (see param_encoder.be):
|
||||
# import param_encoder
|
||||
# var encoded = param_encoder.encode_constraints({"min": 0, "max": 255, "default": 128})
|
||||
#
|
||||
# Checking if constraint contains a field:
|
||||
# if ParameterizedObject.constraint_mask(encoded, "min")
|
||||
# print("Has min constraint")
|
||||
# end
|
||||
#
|
||||
# Getting constraint field value:
|
||||
# var min_val = ParameterizedObject.constraint_find(encoded, "min", 0)
|
||||
# var max_val = ParameterizedObject.constraint_find(encoded, "max", 255)
|
||||
# ============================================================================
|
||||
# Check if an encoded constraint contains a specific field (monolithic, no sub-calls)
|
||||
#
|
||||
# This static method provides fast access to encoded constraint metadata without
|
||||
# decoding the entire constraint. It directly checks the mask byte to determine
|
||||
# if a field is present.
|
||||
#
|
||||
# @param encoded_bytes: bytes - Encoded constraint in Hybrid format
|
||||
# @param name: string - Field name ("min", "max", "default", "enum", "nillable", "type")
|
||||
# @return bool - True if field exists, false otherwise
|
||||
#
|
||||
# Example:
|
||||
# var encoded = bytes("07 00 00 FF 80") # min=0, max=255, default=128
|
||||
# ParameterizedObject.constraint_mask(encoded, "min") # => true
|
||||
# ParameterizedObject.constraint_mask(encoded, "enum") # => false
|
||||
static var _MASK = [
|
||||
"min", #- 0x01 HAS_MIN-#
|
||||
"max", #- 0x02, HAS_MAX-#
|
||||
"default", #- 0x04, HAS_DEFAULT-#
|
||||
"type", #- 0x08, HAS_EXPLICIT_TYPE-#
|
||||
"enum", #- 0x10, HAS_ENUM-#
|
||||
"nillable", #- 0x20, IS_NILLABLE-#
|
||||
]
|
||||
static var _TYPES = [
|
||||
"int", # 0x00
|
||||
"string", # 0x01
|
||||
"bytes", # 0x02
|
||||
"bool", # 0x03
|
||||
"any", # 0x04
|
||||
"instance", # 0x05
|
||||
"function" # 0x06
|
||||
]
|
||||
static def constraint_mask(encoded_bytes, name)
|
||||
if size(encoded_bytes) > 0
|
||||
var index_mask = _class._MASK.find(name)
|
||||
if (index_mask != nil)
|
||||
return (encoded_bytes[0] & (1 << index_mask))
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
# Find and return an encoded constraint field value (monolithic, no sub-calls)
|
||||
#
|
||||
# This static method extracts a specific field value from an encoded constraint
|
||||
# without decoding the entire structure. It performs direct byte reading with
|
||||
# inline type handling for maximum efficiency.
|
||||
#
|
||||
# @param encoded_bytes: bytes - Encoded constraint in Hybrid format
|
||||
# @param name: string - Field name ("min", "max", "default", "enum", "nillable", "type")
|
||||
# @param default: any - Default value if field not found
|
||||
# @return any - Field value or default
|
||||
#
|
||||
# Supported field names:
|
||||
# - "min": Minimum value constraint (int)
|
||||
# - "max": Maximum value constraint (int)
|
||||
# - "default": Default value (any type)
|
||||
# - "enum": List of allowed values (array)
|
||||
# - "nillable": Whether nil is allowed (bool)
|
||||
# - "type": Explicit type string ("int", "string", "bytes", "bool", "any", "instance", "function")
|
||||
#
|
||||
# Example:
|
||||
# var encoded = bytes("07 00 00 FF 80") # min=0, max=255, default=128
|
||||
# ParameterizedObject.constraint_find(encoded, "min", 0) # => 0
|
||||
# ParameterizedObject.constraint_find(encoded, "max", 255) # => 255
|
||||
# ParameterizedObject.constraint_find(encoded, "default", 100) # => 128
|
||||
# ParameterizedObject.constraint_find(encoded, "enum", nil) # => nil (not present)
|
||||
|
||||
static def constraint_find(encoded_bytes, name, default)
|
||||
|
||||
# Helper: Skip a value with type prefix and return new offset
|
||||
def _skip_typed_value(encoded_bytes, offset)
|
||||
if offset >= size(encoded_bytes) return 0 end
|
||||
var type_code = encoded_bytes[offset]
|
||||
|
||||
if type_code == 0x06 #-NIL-# return 1
|
||||
elif type_code == 0x05 #-BOOL-# return 2
|
||||
elif type_code == 0x00 #-INT8-# return 2
|
||||
elif type_code == 0x01 #-INT16-# return 3
|
||||
elif type_code == 0x02 #-INT32-# return 5
|
||||
elif type_code == 0x03 #-STRING-# return 2 + encoded_bytes[offset + 1]
|
||||
elif type_code == 0x04 #-BYTES-# return 3 + encoded_bytes.get(offset + 1, 2)
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
# Helper: Read a value with type prefix and return [value, new_offset]
|
||||
def _read_typed_value(encoded_bytes, offset)
|
||||
if offset >= size(encoded_bytes) return nil end
|
||||
var type_code = encoded_bytes[offset]
|
||||
offset += 1 # Skip type byte
|
||||
|
||||
if type_code == 0x06 #-NIL-# return nil
|
||||
elif type_code == 0x05 #-BOOL-#
|
||||
return encoded_bytes[offset] != 0
|
||||
elif type_code == 0x00 #-INT8-#
|
||||
var v = encoded_bytes[offset]
|
||||
return v > 127 ? v - 256 : v
|
||||
elif type_code == 0x01 #-INT16-#
|
||||
var v = encoded_bytes.get(offset, 2)
|
||||
return v > 32767 ? v - 65536 : v
|
||||
elif type_code == 0x02 #-INT32-#
|
||||
return encoded_bytes.get(offset, 4)
|
||||
elif type_code == 0x03 #-STRING-#
|
||||
var len = encoded_bytes[offset]
|
||||
return encoded_bytes[offset + 1 .. offset + len].asstring()
|
||||
elif type_code == 0x04 #-BYTES-#
|
||||
var len = encoded_bytes.get(offset, 2)
|
||||
return encoded_bytes[offset + 2 .. offset + len + 1]
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
if size(encoded_bytes) < 1 return default end
|
||||
var mask = encoded_bytes[0]
|
||||
var offset = 1
|
||||
|
||||
# Quick check if field exists
|
||||
var target_mask = _class._MASK.find(name) # nil or 0..5
|
||||
if (target_mask == nil) return default end
|
||||
target_mask = (1 << target_mask)
|
||||
|
||||
# If no match, quick fail
|
||||
if !(mask & target_mask) return default end
|
||||
|
||||
# Easy check if 'nillable'
|
||||
if target_mask == 0x20 #-IS_NILLABLE-#
|
||||
return true # since 'mask & target_mask' is true, we know we should return true
|
||||
end
|
||||
|
||||
# Skip fields before target
|
||||
if target_mask > 0x01 #-HAS_MIN-# && (mask & 0x01 #-HAS_MIN-#)
|
||||
offset += _skip_typed_value(encoded_bytes, offset)
|
||||
end
|
||||
if target_mask > 0x02 #-HAS_MAX-# && (mask & 0x02 #-HAS_MAX-#)
|
||||
offset += _skip_typed_value(encoded_bytes, offset)
|
||||
end
|
||||
if target_mask > 0x04 #-HAS_DEFAULT-# && (mask & 0x04 #-HAS_DEFAULT-#)
|
||||
offset += _skip_typed_value(encoded_bytes, offset)
|
||||
end
|
||||
if target_mask > 0x08 #-HAS_EXPLICIT_TYPE-# && (mask & 0x08 #-HAS_EXPLICIT_TYPE-#)
|
||||
offset += 1
|
||||
end
|
||||
if offset >= size(encoded_bytes) return default end # sanity check
|
||||
|
||||
# Special case for explicit_type
|
||||
if target_mask == 0x08 #-HAS_EXPLICIT_TYPE-#
|
||||
# Read explicit type code and convert to string
|
||||
var type_byte = encoded_bytes[offset] # sanity check above guarantees that index is correct
|
||||
if type_byte < size(_class._TYPES)
|
||||
return _class._TYPES[type_byte]
|
||||
end
|
||||
return default
|
||||
end
|
||||
|
||||
# Read target value
|
||||
if target_mask == 0x10 #-HAS_ENUM-#
|
||||
var count = encoded_bytes[offset]
|
||||
offset += 1
|
||||
var result = []
|
||||
var i = 0
|
||||
while i < count
|
||||
var val_and_offset =
|
||||
result.push(_read_typed_value(encoded_bytes, offset))
|
||||
offset += _skip_typed_value(encoded_bytes, offset)
|
||||
i += 1
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
# All other cases
|
||||
return _read_typed_value(encoded_bytes, offset)
|
||||
end
|
||||
end
|
||||
|
||||
return {'parameterized_object': ParameterizedObject}
|
||||
@ -413,22 +413,22 @@ class SequenceManager
|
||||
return self.is_running
|
||||
end
|
||||
|
||||
# Get current step info for debugging
|
||||
def get_current_step_info()
|
||||
if !self.is_running || self.step_index >= size(self.steps)
|
||||
return nil
|
||||
end
|
||||
# # Get current step info for debugging
|
||||
# def get_current_step_info()
|
||||
# if !self.is_running || self.step_index >= size(self.steps)
|
||||
# return nil
|
||||
# end
|
||||
|
||||
return {
|
||||
"step_index": self.step_index,
|
||||
"total_steps": size(self.steps),
|
||||
"current_step": self.steps[self.step_index],
|
||||
"elapsed_ms": self.engine.time_ms - self.step_start_time,
|
||||
"repeat_count": self.repeat_count,
|
||||
"current_iteration": self.current_iteration,
|
||||
"is_repeat_sequence": self.is_repeat_sequence
|
||||
}
|
||||
end
|
||||
# return {
|
||||
# "step_index": self.step_index,
|
||||
# "total_steps": size(self.steps),
|
||||
# "current_step": self.steps[self.step_index],
|
||||
# "elapsed_ms": self.engine.time_ms - self.step_start_time,
|
||||
# "repeat_count": self.repeat_count,
|
||||
# "current_iteration": self.current_iteration,
|
||||
# "is_repeat_sequence": self.is_repeat_sequence
|
||||
# }
|
||||
# end
|
||||
end
|
||||
|
||||
return {'SequenceManager': SequenceManager}
|
||||
@ -9,16 +9,18 @@
|
||||
# - curve_factor 1: Pure cosine wave (smooth pulsing)
|
||||
# - curve_factor 2-5: Natural breathing with pauses at peaks (5 = most pronounced pauses)
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:BreatheColorProvider,weak
|
||||
class BreatheColorProvider : 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 = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"base_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)
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new Breathe Color Provider
|
||||
# Following parameterized class specification - engine parameter only
|
||||
|
||||
@ -15,14 +15,16 @@
|
||||
# animation.brightness = provider
|
||||
#
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:ClosureValueProvider,weak
|
||||
class ClosureValueProvider : animation.value_provider
|
||||
var _closure # We keep the closure as instance variable for faster dereferencing, in addition to PARAMS
|
||||
|
||||
# Static parameter definitions
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"closure": {"type": "function", "default": nil}
|
||||
}
|
||||
})
|
||||
|
||||
# Method called when a parameter is changed
|
||||
# Copy "closure" parameter to _closure instance variable
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
# - Constructor takes only 'engine' parameter
|
||||
# - All other parameters set via virtual member assignment after creation
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:ColorCycleColorProvider,weak
|
||||
class ColorCycleColorProvider : animation.color_provider
|
||||
# Non-parameter instance variables only
|
||||
@ -18,7 +20,7 @@ class ColorCycleColorProvider : animation.color_provider
|
||||
var current_index # Current color index for next functionality
|
||||
|
||||
# Parameter definitions
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"palette": {"type": "bytes", "default":
|
||||
bytes( # Palette bytes in AARRGGBB format
|
||||
"FF0000FF" # Blue
|
||||
@ -29,7 +31,7 @@ class ColorCycleColorProvider : animation.color_provider
|
||||
"cycle_period": {"min": 0, "default": 5000}, # 0 = manual only, >0 = auto cycle time in ms
|
||||
"next": {"default": 0}, # Write `<n>` to move to next <n> colors
|
||||
"palette_size": {"type": "int", "default": 3} # Read-only: number of colors in palette
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new ColorCycleColorProvider
|
||||
#
|
||||
@ -50,10 +52,10 @@ class ColorCycleColorProvider : animation.color_provider
|
||||
def _get_palette_bytes()
|
||||
var palette_bytes = self.palette
|
||||
if palette_bytes == nil
|
||||
# Get default from PARAMS
|
||||
var param_def = self._get_param_def("palette")
|
||||
if param_def != nil && param_def.contains("default")
|
||||
palette_bytes = param_def["default"]
|
||||
# Get default from PARAMS using encoded constraints
|
||||
var encoded_constraints = self._get_param_def("palette")
|
||||
if encoded_constraints != nil && self.constraint_mask(encoded_constraints, "default")
|
||||
palette_bytes = self.constraint_find(encoded_constraints, "default", nil)
|
||||
end
|
||||
end
|
||||
return palette_bytes
|
||||
|
||||
@ -7,15 +7,17 @@
|
||||
# - Constructor takes only 'engine' parameter
|
||||
# - All other parameters set via virtual member assignment after creation
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:CompositeColorProvider,weak
|
||||
class CompositeColorProvider : animation.color_provider
|
||||
# Non-parameter instance variables only
|
||||
var providers # List of color providers
|
||||
|
||||
# Parameter definitions
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"blend_mode": {"enum": [0, 1, 2], "default": 0} # 0=overlay, 1=add, 2=multiply
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new CompositeColorProvider
|
||||
#
|
||||
|
||||
@ -19,10 +19,14 @@
|
||||
# }
|
||||
# }
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:IterationNumberProvider,weak
|
||||
class IterationNumberProvider : animation.value_provider
|
||||
# Static parameter definitions (no parameters needed)
|
||||
static var PARAMS = {}
|
||||
static var PARAMS = encode_constraints({
|
||||
|
||||
})
|
||||
|
||||
# Produce the current iteration number from the animation engine
|
||||
#
|
||||
|
||||
@ -9,6 +9,8 @@
|
||||
# - SQUARE (3): Square wave alternating between a and b
|
||||
# - COSINE (4): Smooth cosine wave from a to b
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
# Waveform constants
|
||||
var SAWTOOTH = 1
|
||||
var LINEAR = 1
|
||||
@ -30,14 +32,14 @@ class OscillatorValueProvider : animation.value_provider
|
||||
static var form_names = ["", "SAWTOOTH", "TRIANGLE", "SQUARE", "COSINE", "SINE", "EASE_IN", "EASE_OUT", "ELASTIC", "BOUNCE"]
|
||||
|
||||
# Parameter definitions for the oscillator
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"min_value": {"default": 0},
|
||||
"max_value": {"default": 100},
|
||||
"duration": {"min": 1, "default": 1000},
|
||||
"form": {"enum": [1, 2, 3, 4, 5, 6, 7, 8, 9], "default": 1},
|
||||
"phase": {"min": 0, "max": 100, "default": 0},
|
||||
"duty_cycle": {"min": 0, "max": 100, "default": 50}
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new OscillatorValueProvider
|
||||
#
|
||||
|
||||
@ -7,6 +7,8 @@
|
||||
# - Constructor takes only 'engine' parameter
|
||||
# - All other parameters set via virtual member assignment after creation
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:RichPaletteColorProvider,weak
|
||||
class RichPaletteColorProvider : animation.color_provider
|
||||
# Non-parameter instance variables only
|
||||
@ -17,14 +19,14 @@ class RichPaletteColorProvider : animation.color_provider
|
||||
var light_state # light_state instance for proper color calculations
|
||||
|
||||
# Parameter definitions
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"palette": {"type": "bytes", "default": nil}, # Palette bytes or predefined palette constant
|
||||
"cycle_period": {"min": 0, "default": 5000}, # 5 seconds default, 0 = value-based only
|
||||
"transition_type": {"enum": [animation.LINEAR, animation.SINE], "default": animation.SINE},
|
||||
"brightness": {"min": 0, "max": 255, "default": 255},
|
||||
"range_min": {"default": 0},
|
||||
"range_max": {"default": 255}
|
||||
}
|
||||
})
|
||||
|
||||
# Initialize a new RichPaletteColorProvider
|
||||
#
|
||||
|
||||
@ -7,12 +7,14 @@
|
||||
# - Constructor takes only 'engine' parameter
|
||||
# - All other parameters set via virtual member assignment after creation
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:StaticColorProvider,weak
|
||||
class StaticColorProvider : animation.color_provider
|
||||
# Parameter definitions
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"color": {"default": 0xFFFFFFFF} # Default to white
|
||||
}
|
||||
})
|
||||
|
||||
# Produce the solid color for any parameter name
|
||||
#
|
||||
|
||||
@ -11,12 +11,14 @@
|
||||
# - Constructor takes only 'engine' parameter
|
||||
# - Value is set via virtual member assignment after creation
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:StaticValueProvider,weak
|
||||
class StaticValueProvider : animation.value_provider
|
||||
# Parameter definitions
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"value": {"default": nil, "type": "any"}
|
||||
}
|
||||
})
|
||||
|
||||
# Comparison operators to make StaticValueProvider work with validation code
|
||||
def <(other)
|
||||
|
||||
@ -12,10 +12,14 @@
|
||||
# - All other parameters set via virtual member assignment
|
||||
# - No setter/getter methods for parameters
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
#@ solidify:ValueProvider,weak
|
||||
class ValueProvider : animation.parameterized_object
|
||||
# Static parameter definitions - can be overridden by subclasses
|
||||
static var PARAMS = {}
|
||||
static var PARAMS = encode_constraints({
|
||||
|
||||
})
|
||||
|
||||
# Initialize the value provider
|
||||
#
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -30,7 +30,7 @@ end
|
||||
# Test 1: Engine Creation
|
||||
print("\n--- Test 1: Engine Creation ---")
|
||||
var strip = global.Leds(20)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
assert_not_nil(engine, "Engine should be created")
|
||||
assert_equals(engine.width, 20, "Engine width should match strip length")
|
||||
@ -155,7 +155,7 @@ assert_test(render_time < 200, f"10 render cycles should be fast (took {render_t
|
||||
# Test 8: Error Handling
|
||||
print("\n--- Test 8: Error Handling ---")
|
||||
try
|
||||
var bad_engine = animation.animation_engine(nil)
|
||||
var bad_engine = animation.create_engine(nil)
|
||||
assert_test(false, "Should throw error for nil strip")
|
||||
except "value_error"
|
||||
assert_test(true, "Should throw value_error for nil strip")
|
||||
@ -167,7 +167,7 @@ var engine2 = animation.create_engine(strip)
|
||||
assert_not_nil(engine2, "Second engine should be created")
|
||||
assert_equals(engine2.width, strip.length(), "Second engine width should match strip")
|
||||
|
||||
var engine3 = animation.animation_engine(strip)
|
||||
var engine3 = animation.create_engine(strip)
|
||||
assert_not_nil(engine3, "Direct engine creation should work")
|
||||
assert_equals(engine3.width, strip.length(), "Direct engine width should match strip")
|
||||
|
||||
@ -221,7 +221,7 @@ end
|
||||
|
||||
# Create engine with dynamic strip
|
||||
var dynamic_strip = MockDynamicStrip(15)
|
||||
var dynamic_engine = animation.animation_engine(dynamic_strip)
|
||||
var dynamic_engine = animation.create_engine(dynamic_strip)
|
||||
|
||||
# Test initial state
|
||||
assert_equals(dynamic_engine.width, 15, "Engine should start with strip length 15")
|
||||
|
||||
@ -32,7 +32,7 @@ print("\n--- Test 11: Animation Opacity with Animation Masks ---")
|
||||
|
||||
# Create a fresh engine for opacity tests
|
||||
var opacity_strip = global.Leds(10)
|
||||
var opacity_engine = animation.animation_engine(opacity_strip)
|
||||
var opacity_engine = animation.create_engine(opacity_strip)
|
||||
|
||||
# Test 11a: Basic numeric opacity
|
||||
print("\n--- Test 11a: Basic numeric opacity ---")
|
||||
|
||||
@ -12,7 +12,7 @@ import animation
|
||||
|
||||
# Create animation engine for testing
|
||||
var strip = global.Leds()
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test Animation class
|
||||
assert(animation.animation != nil, "Animation class should be defined")
|
||||
@ -129,10 +129,13 @@ assert(param_anim.set_param("priority", -1) == false, "Value below min should be
|
||||
assert(param_anim.get_param("unknown", "default") == "default", "Unknown parameter should return default")
|
||||
assert(param_anim.get_param("priority", 0) == 75, "Known parameter should return current value")
|
||||
|
||||
# Test parameter metadata
|
||||
var metadata = param_anim.get_param_metadata("priority")
|
||||
assert(metadata != nil, "Metadata should exist for static parameter")
|
||||
assert(metadata["min"] == 0, "Metadata should contain correct min value")
|
||||
# Test parameter definition using _has_param and _get_param_def
|
||||
assert(param_anim._has_param("priority") == true, "Should have priority parameter")
|
||||
var param_def = param_anim._get_param_def("priority")
|
||||
assert(param_def != nil, "Parameter definition should exist for static parameter")
|
||||
# Use static methods to access encoded constraint data
|
||||
assert(param_anim.constraint_mask(param_def, "min") == 0x01, "Parameter definition should have min constraint")
|
||||
assert(param_anim.constraint_find(param_def, "min", nil) == 0, "Parameter definition should contain correct min value")
|
||||
|
||||
# Test updating multiple static parameters
|
||||
# Test individual parameter updates using existing static parameters
|
||||
|
||||
@ -14,7 +14,7 @@ var passed_count = 0
|
||||
|
||||
# Create LED strip and engine for testing
|
||||
var strip = global.Leds(10) # Use built-in LED strip for testing
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
def test_assert(condition, message)
|
||||
test_count += 1
|
||||
|
||||
@ -14,7 +14,7 @@ def test_bounce_animation_basic()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Create a simple source animation
|
||||
var source = animation.solid(engine)
|
||||
@ -42,7 +42,7 @@ def test_bounce_animation_custom()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(20)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF00FF00
|
||||
@ -79,7 +79,7 @@ def test_bounce_animation_parameters()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(15)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF0000FF
|
||||
@ -114,7 +114,7 @@ def test_bounce_animation_physics()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFFFFFF00
|
||||
@ -154,7 +154,7 @@ def test_bounce_animation_update_render()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFFFF00FF
|
||||
@ -203,7 +203,7 @@ def test_bounce_constructors()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(15)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF00FFFF
|
||||
@ -243,7 +243,7 @@ def test_bounce_animation_gravity()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFFFFFFFF
|
||||
@ -278,7 +278,7 @@ def test_bounce_tostring()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(12)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF888888
|
||||
|
||||
@ -13,7 +13,7 @@ print("Imported animation module")
|
||||
|
||||
# Create LED strip and animation engine following specification
|
||||
var strip = global.Leds(10) # Use global.Leds() for testing as per specification
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
print("Created LED strip and animation engine")
|
||||
|
||||
# Create a breathe animation with engine-only parameter
|
||||
|
||||
@ -13,7 +13,7 @@ print("Imported animation module")
|
||||
|
||||
# Create LED strip and animation engine following specification
|
||||
var strip = global.Leds(10) # Use global.Leds() for testing as per specification
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
print("Created LED strip and animation engine")
|
||||
|
||||
# Create a breathe color provider with engine-only parameter
|
||||
|
||||
@ -4,13 +4,15 @@
|
||||
import animation
|
||||
import animation_dsl
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
# Test class that uses bytes parameter
|
||||
class BytesTestClass : animation.parameterized_object
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"data": {"type": "bytes", "default": nil, "nillable": true},
|
||||
"required_data": {"type": "bytes"},
|
||||
"name": {"type": "string", "default": "test"}
|
||||
}
|
||||
})
|
||||
|
||||
def init(engine)
|
||||
super(self).init(engine)
|
||||
@ -76,14 +78,16 @@ def test_bytes_type_validation()
|
||||
success = obj.set_param("data", "invalid")
|
||||
assert(success == false, "Method setting with invalid type should fail")
|
||||
|
||||
# Test 5: Parameter metadata
|
||||
var metadata = obj.get_param_metadata("data")
|
||||
assert(metadata["type"] == "bytes", "Data parameter should have bytes type")
|
||||
assert(metadata["nillable"] == true, "Data parameter should be nillable")
|
||||
# Test 5: Parameter definition
|
||||
assert(obj._has_param("data") == true, "data parameter should exist")
|
||||
var param_def = obj._get_param_def("data")
|
||||
assert(obj.constraint_find(param_def, "type", nil) == "bytes", "Data parameter should have bytes type")
|
||||
assert(obj.constraint_mask(param_def, "nillable") == 0x20, "Data parameter should be nillable")
|
||||
|
||||
var req_metadata = obj.get_param_metadata("required_data")
|
||||
assert(req_metadata["type"] == "bytes", "Required data should have bytes type")
|
||||
assert(req_metadata.find("nillable", false) == false, "Required data should not be nillable")
|
||||
assert(obj._has_param("required_data") == true, "required_data parameter should exist")
|
||||
var req_param_def = obj._get_param_def("required_data")
|
||||
assert(obj.constraint_find(req_param_def, "type", nil) == "bytes", "Required data should have bytes type")
|
||||
assert(obj.constraint_mask(req_param_def, "nillable") == 0x00, "Required data should not be nillable")
|
||||
|
||||
print("✓ All bytes type validation tests passed!")
|
||||
end
|
||||
|
||||
@ -10,7 +10,7 @@ import animation
|
||||
|
||||
# Create a real engine for testing using global.Leds()
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Create a test class
|
||||
class ColorCycleAnimationTest
|
||||
|
||||
@ -167,16 +167,17 @@ def test_palette_size_parameter_metadata()
|
||||
var engine = MockEngine()
|
||||
var provider = animation.color_cycle(engine)
|
||||
|
||||
# Test 1: Parameter should exist in metadata
|
||||
var metadata = provider.get_param_metadata("palette_size")
|
||||
assert(metadata != nil, "palette_size should have metadata")
|
||||
# Test 1: Parameter should exist
|
||||
assert(provider._has_param("palette_size") == true, "palette_size parameter should exist")
|
||||
var param_def = provider._get_param_def("palette_size")
|
||||
assert(param_def != nil, "palette_size should have parameter definition")
|
||||
|
||||
# Test 2: Check parameter definition
|
||||
assert(metadata.contains("type"), "palette_size metadata should have type")
|
||||
assert(metadata["type"] == "int", f"palette_size type should be 'int', got '{metadata['type']}'")
|
||||
# Test 2: Check parameter definition using static methods
|
||||
assert(provider.constraint_mask(param_def, "type") == 0x08, "palette_size definition should have type")
|
||||
assert(provider.constraint_find(param_def, "type", nil) == "int", f"palette_size type should be 'int', got '{provider.constraint_find(param_def, 'type', nil)}'")
|
||||
|
||||
assert(metadata.contains("default"), "palette_size metadata should have default")
|
||||
assert(metadata["default"] == 3, f"palette_size default should be 3, got {metadata['default']}")
|
||||
assert(provider.constraint_mask(param_def, "default") == 0x04, "palette_size definition should have default")
|
||||
assert(provider.constraint_find(param_def, "default", nil) == 3, f"palette_size default should be 3, got {provider.constraint_find(param_def, 'default', nil)}")
|
||||
|
||||
print("✓ Parameter metadata tests passed!")
|
||||
end
|
||||
|
||||
@ -39,7 +39,7 @@ end
|
||||
|
||||
# Create LED strip and animation engine following specification
|
||||
var strip = global.Leds(30) # Use global.Leds() for testing as per specification
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
print("Created LED strip and animation engine")
|
||||
|
||||
# Test 1: Basic Construction
|
||||
@ -188,7 +188,7 @@ print("\n--- Test 6: Wrap Around vs Bounce ---")
|
||||
|
||||
# Create smaller strip for faster testing
|
||||
var small_strip = global.Leds(10)
|
||||
var small_engine = animation.animation_engine(small_strip)
|
||||
var small_engine = animation.create_engine(small_strip)
|
||||
|
||||
# Test wrap around
|
||||
var wrap_comet = animation.comet_animation(small_engine)
|
||||
|
||||
@ -0,0 +1,336 @@
|
||||
# Constraint Encoding Test Suite
|
||||
#
|
||||
# Comprehensive tests for encode_constraints() and ParameterizedObject static methods:
|
||||
# - constraint_mask()
|
||||
# - constraint_find()
|
||||
#
|
||||
# Tests all PARAMS patterns found in the Berry Animation Framework codebase.
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
# Test counter
|
||||
var test_count = 0
|
||||
var pass_count = 0
|
||||
var fail_count = 0
|
||||
|
||||
# Test helper function
|
||||
def assert_equal(actual, expected, test_name)
|
||||
test_count += 1
|
||||
if actual == expected
|
||||
pass_count += 1
|
||||
print(f"✓ Test {test_count}: {test_name}")
|
||||
return true
|
||||
else
|
||||
fail_count += 1
|
||||
print(f"✗ Test {test_count}: {test_name}")
|
||||
print(f" Expected: {expected}")
|
||||
print(f" Actual: {actual}")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# Test helper for array equality
|
||||
def assert_array_equal(actual, expected, test_name)
|
||||
test_count += 1
|
||||
if size(actual) != size(expected)
|
||||
fail_count += 1
|
||||
print(f"✗ Test {test_count}: {test_name}")
|
||||
print(f" Expected size: {size(expected)}, Actual size: {size(actual)}")
|
||||
return false
|
||||
end
|
||||
var i = 0
|
||||
while i < size(actual)
|
||||
if actual[i] != expected[i]
|
||||
fail_count += 1
|
||||
print(f"✗ Test {test_count}: {test_name}")
|
||||
print(f" Mismatch at index {i}: expected {expected[i]}, got {actual[i]}")
|
||||
return false
|
||||
end
|
||||
i += 1
|
||||
end
|
||||
pass_count += 1
|
||||
print(f"✓ Test {test_count}: {test_name}")
|
||||
return true
|
||||
end
|
||||
|
||||
print("=" * 70)
|
||||
print("CONSTRAINT ENCODING TEST SUITE")
|
||||
print("=" * 70)
|
||||
|
||||
# ============================================================================
|
||||
# TEST GROUP 1: Basic Integer Constraints (min/max/default)
|
||||
# ============================================================================
|
||||
print("\n--- Test Group 1: Basic Integer Constraints ---")
|
||||
|
||||
# Test 1.1: Simple min/max/default (int8 range)
|
||||
var params_1_1 = {"min": 0, "max": 255, "default": 128}
|
||||
var encoded_1_1 = encode_constraints({"test": params_1_1})["test"]
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_1_1, "min"), 0x01, "1.1a: has min")
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_1_1, "max"), 0x02, "1.1b: has max")
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_1_1, "default"), 0x04, "1.1c: has default")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_1_1, "min", nil), 0, "1.1d: min value")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_1_1, "max", nil), 255, "1.1e: max value")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_1_1, "default", nil), 128, "1.1f: default value")
|
||||
|
||||
# Test 1.2: Only default (no min/max)
|
||||
var params_1_2 = {"default": 0xFFFFFFFF}
|
||||
var encoded_1_2 = encode_constraints({"test": params_1_2})["test"]
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_1_2, "min"), 0x00, "1.2a: no min")
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_1_2, "max"), 0x00, "1.2b: no max")
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_1_2, "default"), 0x04, "1.2c: has default")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_1_2, "default", nil), 0xFFFFFFFF, "1.2d: default value")
|
||||
|
||||
# Test 1.3: Min only
|
||||
var params_1_3 = {"min": 1, "default": 1000}
|
||||
var encoded_1_3 = encode_constraints({"test": params_1_3})["test"]
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_1_3, "min"), 0x01, "1.3a: has min")
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_1_3, "max"), 0x00, "1.3b: no max")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_1_3, "min", nil), 1, "1.3c: min value")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_1_3, "default", nil), 1000, "1.3d: default value")
|
||||
|
||||
# Test 1.4: Negative values
|
||||
var params_1_4 = {"min": -128, "max": 127, "default": 0}
|
||||
var encoded_1_4 = encode_constraints({"test": params_1_4})["test"]
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_1_4, "min", nil), -128, "1.4a: negative min")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_1_4, "max", nil), 127, "1.4b: positive max")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_1_4, "default", nil), 0, "1.4c: zero default")
|
||||
|
||||
# Test 1.5: Large int32 values
|
||||
var params_1_5 = {"min": 0, "max": 25600, "default": 2560}
|
||||
var encoded_1_5 = encode_constraints({"test": params_1_5})["test"]
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_1_5, "max", nil), 25600, "1.5a: large max")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_1_5, "default", nil), 2560, "1.5b: large default")
|
||||
|
||||
# ============================================================================
|
||||
# TEST GROUP 2: Enum Constraints
|
||||
# ============================================================================
|
||||
print("\n--- Test Group 2: Enum Constraints ---")
|
||||
|
||||
# Test 2.1: Simple enum with positive values
|
||||
var params_2_1 = {"enum": [1, 2, 3, 4, 5, 6, 7, 8, 9], "default": 1}
|
||||
var encoded_2_1 = encode_constraints({"test": params_2_1})["test"]
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_2_1, "enum"), 0x10, "2.1a: has enum")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_2_1, "default", nil), 1, "2.1b: default value")
|
||||
var enum_2_1 = animation.parameterized_object.constraint_find(encoded_2_1, "enum", nil)
|
||||
assert_array_equal(enum_2_1, [1, 2, 3, 4, 5, 6, 7, 8, 9], "2.1c: enum values")
|
||||
|
||||
# Test 2.2: Enum with negative values
|
||||
var params_2_2 = {"enum": [-1, 1], "default": 1}
|
||||
var encoded_2_2 = encode_constraints({"test": params_2_2})["test"]
|
||||
var enum_2_2 = animation.parameterized_object.constraint_find(encoded_2_2, "enum", nil)
|
||||
assert_array_equal(enum_2_2, [-1, 1], "2.2a: enum with negative values")
|
||||
|
||||
# Test 2.3: Enum with min/max/default
|
||||
var params_2_3 = {"min": 0, "max": 3, "enum": [0, 1, 2, 3], "default": 0}
|
||||
var encoded_2_3 = encode_constraints({"test": params_2_3})["test"]
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_2_3, "min"), 0x01, "2.3a: has min")
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_2_3, "max"), 0x02, "2.3b: has max")
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_2_3, "enum"), 0x10, "2.3c: has enum")
|
||||
var enum_2_3 = animation.parameterized_object.constraint_find(encoded_2_3, "enum", nil)
|
||||
assert_array_equal(enum_2_3, [0, 1, 2, 3], "2.3d: enum values")
|
||||
|
||||
# ============================================================================
|
||||
# TEST GROUP 3: Type Annotations
|
||||
# ============================================================================
|
||||
print("\n--- Test Group 3: Type Annotations ---")
|
||||
|
||||
# Test 3.1: Bool type
|
||||
var params_3_1 = {"type": "bool", "default": false}
|
||||
var encoded_3_1 = encode_constraints({"test": params_3_1})["test"]
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_3_1, "type"), 0x08, "3.1a: has type")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_3_1, "type", nil), "bool", "3.1b: type is bool")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_3_1, "default", nil), false, "3.1c: default is false")
|
||||
|
||||
# Test 3.2: String type
|
||||
var params_3_2 = {"type": "string", "default": "animation"}
|
||||
var encoded_3_2 = encode_constraints({"test": params_3_2})["test"]
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_3_2, "type"), 0x08, "3.2a: has type")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_3_2, "type", nil), "string", "3.2b: type is string")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_3_2, "default", nil), "animation", "3.2c: default string")
|
||||
|
||||
# Test 3.3: Int type (explicit)
|
||||
var params_3_3 = {"type": "int", "default": 3}
|
||||
var encoded_3_3 = encode_constraints({"test": params_3_3})["test"]
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_3_3, "type"), 0x08, "3.3a: has type")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_3_3, "type", nil), "int", "3.3b: type is int")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_3_3, "default", nil), 3, "3.3c: default int")
|
||||
|
||||
# Test 3.4: Any type
|
||||
var params_3_4 = {"type": "any", "default": 255}
|
||||
var encoded_3_4 = encode_constraints({"test": params_3_4})["test"]
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_3_4, "type"), 0x08, "3.4a: has type")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_3_4, "type", nil), "any", "3.4b: type is any")
|
||||
|
||||
# Test 3.5: Instance type
|
||||
var params_3_5 = {"type": "instance", "default": nil}
|
||||
var encoded_3_5 = encode_constraints({"test": params_3_5})["test"]
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_3_5, "type"), 0x08, "3.5a: has type")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_3_5, "type", nil), "instance", "3.5b: type is instance")
|
||||
|
||||
# Test 3.6: Function type
|
||||
var params_3_6 = {"type": "function"}
|
||||
var encoded_3_6 = encode_constraints({"test": params_3_6})["test"]
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_3_6, "type"), 0x08, "3.6a: has type")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_3_6, "type", nil), "function", "3.6b: type is function")
|
||||
|
||||
# Test 3.7: Bytes type
|
||||
var params_3_7 = {"type": "bytes", "default": bytes("FF0000FF")}
|
||||
var encoded_3_7 = encode_constraints({"test": params_3_7})["test"]
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_3_7, "type"), 0x08, "3.7a: has type")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_3_7, "type", nil), "bytes", "3.7b: type is bytes")
|
||||
# Note: bytes comparison would need special handling
|
||||
|
||||
# ============================================================================
|
||||
# TEST GROUP 4: Nillable Constraints
|
||||
# ============================================================================
|
||||
print("\n--- Test Group 4: Nillable Constraints ---")
|
||||
|
||||
# Test 4.1: Nillable with nil default
|
||||
var params_4_1 = {"default": nil, "nillable": true}
|
||||
var encoded_4_1 = encode_constraints({"test": params_4_1})["test"]
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_4_1, "nillable"), 0x20, "4.1a: has nillable")
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_4_1, "default"), 0x04, "4.1b: has default")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_4_1, "nillable", false), true, "4.1c: nillable is true")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_4_1, "default", 999), nil, "4.1d: default is nil")
|
||||
|
||||
# Test 4.2: Nillable without explicit default
|
||||
var params_4_2 = {"nillable": true}
|
||||
var encoded_4_2 = encode_constraints({"test": params_4_2})["test"]
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_4_2, "nillable"), 0x20, "4.2a: has nillable")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_4_2, "nillable", false), true, "4.2b: nillable is true")
|
||||
|
||||
# Test 4.3: Non-nillable (default behavior)
|
||||
var params_4_3 = {"default": 0}
|
||||
var encoded_4_3 = encode_constraints({"test": params_4_3})["test"]
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_4_3, "nillable"), 0x00, "4.3a: no nillable flag")
|
||||
|
||||
# ============================================================================
|
||||
# TEST GROUP 5: Real-World PARAMS from Codebase
|
||||
# ============================================================================
|
||||
print("\n--- Test Group 5: Real-World PARAMS ---")
|
||||
|
||||
# Test 5.1: BeaconAnimation PARAMS
|
||||
var beacon_params = {
|
||||
"color": {"default": 0xFFFFFFFF},
|
||||
"back_color": {"default": 0xFF000000},
|
||||
"pos": {"default": 0},
|
||||
"beacon_size": {"min": 0, "default": 1},
|
||||
"slew_size": {"min": 0, "default": 0}
|
||||
}
|
||||
var beacon_encoded = encode_constraints(beacon_params)
|
||||
assert_equal(animation.parameterized_object.constraint_find(beacon_encoded["color"], "default", nil), 0xFFFFFFFF, "5.1a: beacon color")
|
||||
assert_equal(animation.parameterized_object.constraint_find(beacon_encoded["beacon_size"], "min", nil), 0, "5.1b: beacon_size min")
|
||||
|
||||
# Test 5.2: CometAnimation PARAMS
|
||||
var comet_params = {
|
||||
"tail_length": {"min": 1, "max": 50, "default": 5},
|
||||
"speed": {"min": 1, "max": 25600, "default": 2560},
|
||||
"direction": {"enum": [-1, 1], "default": 1},
|
||||
"wrap_around": {"min": 0, "max": 1, "default": 1},
|
||||
"fade_factor": {"min": 0, "max": 255, "default": 179}
|
||||
}
|
||||
var comet_encoded = encode_constraints(comet_params)
|
||||
assert_equal(animation.parameterized_object.constraint_find(comet_encoded["tail_length"], "max", nil), 50, "5.2a: tail_length max")
|
||||
assert_equal(animation.parameterized_object.constraint_find(comet_encoded["speed"], "max", nil), 25600, "5.2b: speed max")
|
||||
var direction_enum = animation.parameterized_object.constraint_find(comet_encoded["direction"], "enum", nil)
|
||||
assert_array_equal(direction_enum, [-1, 1], "5.2c: direction enum")
|
||||
|
||||
# Test 5.3: Animation base class PARAMS
|
||||
var animation_params = {
|
||||
"name": {"type": "string", "default": "animation"},
|
||||
"priority": {"min": 0, "default": 10},
|
||||
"duration": {"min": 0, "default": 0},
|
||||
"loop": {"type": "bool", "default": false},
|
||||
"opacity": {"type": "any", "default": 255},
|
||||
"color": {"default": 0xFFFFFFFF}
|
||||
}
|
||||
var animation_encoded = encode_constraints(animation_params)
|
||||
assert_equal(animation.parameterized_object.constraint_find(animation_encoded["name"], "type", nil), "string", "5.3a: name type")
|
||||
assert_equal(animation.parameterized_object.constraint_find(animation_encoded["name"], "default", nil), "animation", "5.3b: name default")
|
||||
assert_equal(animation.parameterized_object.constraint_find(animation_encoded["loop"], "type", nil), "bool", "5.3c: loop type")
|
||||
assert_equal(animation.parameterized_object.constraint_find(animation_encoded["opacity"], "type", nil), "any", "5.3d: opacity type")
|
||||
|
||||
# Test 5.4: GradientAnimation PARAMS (with nillable)
|
||||
var gradient_params = {
|
||||
"color": {"default": nil, "nillable": true},
|
||||
"gradient_type": {"min": 0, "max": 1, "default": 0},
|
||||
"direction": {"min": 0, "max": 255, "default": 0}
|
||||
}
|
||||
var gradient_encoded = encode_constraints(gradient_params)
|
||||
assert_equal(animation.parameterized_object.constraint_mask(gradient_encoded["color"], "nillable"), 0x20, "5.4a: color nillable")
|
||||
assert_equal(animation.parameterized_object.constraint_find(gradient_encoded["color"], "default", 999), nil, "5.4b: color default nil")
|
||||
|
||||
# Test 5.5: OscillatorValueProvider PARAMS (large enum)
|
||||
var oscillator_params = {
|
||||
"min_value": {"default": 0},
|
||||
"max_value": {"default": 100},
|
||||
"duration": {"min": 1, "default": 1000},
|
||||
"form": {"enum": [1, 2, 3, 4, 5, 6, 7, 8, 9], "default": 1},
|
||||
"phase": {"min": 0, "max": 100, "default": 0}
|
||||
}
|
||||
var oscillator_encoded = encode_constraints(oscillator_params)
|
||||
var form_enum = animation.parameterized_object.constraint_find(oscillator_encoded["form"], "enum", nil)
|
||||
assert_array_equal(form_enum, [1, 2, 3, 4, 5, 6, 7, 8, 9], "5.5a: form enum")
|
||||
|
||||
# Test 5.6: BreatheAnimation 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},
|
||||
"curve_factor": {"min": 1, "max": 5, "default": 2}
|
||||
}
|
||||
var breathe_encoded = encode_constraints(breathe_params)
|
||||
assert_equal(animation.parameterized_object.constraint_find(breathe_encoded["period"], "min", nil), 100, "5.6a: period min")
|
||||
assert_equal(animation.parameterized_object.constraint_find(breathe_encoded["curve_factor"], "max", nil), 5, "5.6b: curve_factor max")
|
||||
|
||||
# ============================================================================
|
||||
# TEST GROUP 6: Edge Cases and Special Scenarios
|
||||
# ============================================================================
|
||||
print("\n--- Test Group 6: Edge Cases ---")
|
||||
|
||||
# Test 6.1: Empty constraints (only default)
|
||||
var params_6_1 = {"default": 42}
|
||||
var encoded_6_1 = encode_constraints({"test": params_6_1})["test"]
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_6_1, "min"), 0x00, "6.1a: no min")
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_6_1, "max"), 0x00, "6.1b: no max")
|
||||
assert_equal(animation.parameterized_object.constraint_mask(encoded_6_1, "enum"), 0x00, "6.1c: no enum")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_6_1, "default", nil), 42, "6.1d: default value")
|
||||
|
||||
# Test 6.2: Zero values
|
||||
var params_6_2 = {"min": 0, "max": 0, "default": 0}
|
||||
var encoded_6_2 = encode_constraints({"test": params_6_2})["test"]
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_6_2, "min", nil), 0, "6.2a: zero min")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_6_2, "max", nil), 0, "6.2b: zero max")
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_6_2, "default", nil), 0, "6.2c: zero default")
|
||||
|
||||
# Test 6.3: Single-element enum
|
||||
var params_6_3 = {"enum": [42], "default": 42}
|
||||
var encoded_6_3 = encode_constraints({"test": params_6_3})["test"]
|
||||
var enum_6_3 = animation.parameterized_object.constraint_find(encoded_6_3, "enum", nil)
|
||||
assert_array_equal(enum_6_3, [42], "6.3a: single-element enum")
|
||||
|
||||
# Test 6.4: Default not found (should return provided default)
|
||||
var params_6_4 = {"min": 0, "max": 100}
|
||||
var encoded_6_4 = encode_constraints({"test": params_6_4})["test"]
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_6_4, "default", 999), 999, "6.4a: missing default returns fallback")
|
||||
|
||||
# Test 6.5: Field not found (should return provided default)
|
||||
assert_equal(animation.parameterized_object.constraint_find(encoded_6_4, "nonexistent", 777), 777, "6.5a: nonexistent field returns fallback")
|
||||
|
||||
# ============================================================================
|
||||
# SUMMARY
|
||||
# ============================================================================
|
||||
print("\n" + "=" * 70)
|
||||
print("TEST SUMMARY")
|
||||
print("=" * 70)
|
||||
print(f"Total tests: {test_count}")
|
||||
print(f"Passed: {pass_count}")
|
||||
print(f"Failed: {fail_count}")
|
||||
if fail_count == 0
|
||||
print("\n✓ ALL TESTS PASSED!")
|
||||
else
|
||||
print(f"\n✗ {fail_count} TEST(S) FAILED")
|
||||
raise "test_failed"
|
||||
end
|
||||
print("=" * 70)
|
||||
@ -28,7 +28,7 @@ def run_tests()
|
||||
|
||||
# Create engine and strip for testing
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test 1: Basic construction with new parameterized pattern
|
||||
var crenel = animation.crenel_position_animation(engine)
|
||||
|
||||
@ -12,7 +12,7 @@ def test_crenel_with_integer_color()
|
||||
|
||||
# Create engine and strip for testing
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var frame = animation.frame_buffer(10)
|
||||
var red_color = 0xFFFF0000 # Red
|
||||
@ -51,7 +51,7 @@ def test_crenel_with_color_provider()
|
||||
|
||||
# Create engine and strip for testing
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var frame = animation.frame_buffer(10)
|
||||
var blue_color = 0xFF0000FF # Blue
|
||||
@ -94,7 +94,7 @@ def test_crenel_with_dynamic_color_provider()
|
||||
|
||||
# Create engine and strip for testing
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var frame = animation.frame_buffer(10)
|
||||
|
||||
@ -144,7 +144,7 @@ def test_crenel_with_generic_value_provider()
|
||||
|
||||
# Create engine and strip for testing
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var frame = animation.frame_buffer(10)
|
||||
|
||||
@ -186,7 +186,7 @@ def test_crenel_set_color_methods()
|
||||
|
||||
# Create engine and strip for testing
|
||||
var strip = global.Leds(5)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var frame = animation.frame_buffer(5)
|
||||
|
||||
@ -233,7 +233,7 @@ def test_crenel_tostring()
|
||||
|
||||
# Create engine and strip for testing
|
||||
var strip = global.Leds(5)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test with integer color
|
||||
var crenel_int = animation.crenel_position_animation(engine)
|
||||
|
||||
@ -210,23 +210,6 @@ def test_animation_engine_event_integration()
|
||||
introspect.contains(engine, "resume")
|
||||
end
|
||||
|
||||
# Test 12: Event Metadata Handling
|
||||
def test_event_metadata_handling()
|
||||
var manager = animation.event_manager
|
||||
var received_metadata = nil
|
||||
|
||||
var metadata = {"interval": 1000, "repeat": true}
|
||||
var handler = manager.register_handler("metadata_test", def(data)
|
||||
received_metadata = data
|
||||
end, 0, nil, metadata)
|
||||
|
||||
# Check handler info includes metadata
|
||||
var handler_info = handler.get_info()
|
||||
|
||||
return handler_info["metadata"]["interval"] == 1000 &&
|
||||
handler_info["metadata"]["repeat"] == true
|
||||
end
|
||||
|
||||
# Run all tests
|
||||
def run_all_tests()
|
||||
print("=== Event System Test Suite ===")
|
||||
@ -243,7 +226,6 @@ def run_all_tests()
|
||||
run_test("Event Handler Deactivation", test_event_handler_deactivation)
|
||||
run_test("Event Queue Processing", test_event_queue_processing)
|
||||
run_test("Animation Engine Event Integration", test_animation_engine_event_integration)
|
||||
run_test("Event Metadata Handling", test_event_metadata_handling)
|
||||
|
||||
print("=== Test Results ===")
|
||||
print(f"Total tests: {test_count}")
|
||||
|
||||
@ -7,7 +7,7 @@ print("=== Fire Animation Test ===")
|
||||
|
||||
# Create engine and LED strip for testing
|
||||
var strip = global.Leds(30) # Use built-in LED strip for testing
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test 1: Basic Fire Animation Creation
|
||||
print("\n1. Testing basic fire animation creation...")
|
||||
@ -148,7 +148,7 @@ print("\n10. Testing edge cases...")
|
||||
|
||||
# Very small strip
|
||||
var tiny_strip = global.Leds(1)
|
||||
var tiny_engine = animation.animation_engine(tiny_strip)
|
||||
var tiny_engine = animation.create_engine(tiny_strip)
|
||||
var tiny_fire = animation.fire_animation(tiny_engine)
|
||||
tiny_fire.intensity = 180
|
||||
tiny_fire.priority = 1
|
||||
@ -161,7 +161,7 @@ print("Tiny fire (1 pixel) created and rendered successfully")
|
||||
|
||||
# Zero intensity
|
||||
var dim_strip = global.Leds(10)
|
||||
var dim_engine = animation.animation_engine(dim_strip)
|
||||
var dim_engine = animation.create_engine(dim_strip)
|
||||
var dim_fire = animation.fire_animation(dim_engine)
|
||||
dim_fire.intensity = 0
|
||||
dim_fire.priority = 10
|
||||
|
||||
@ -11,7 +11,7 @@ def test_gradient_creation()
|
||||
|
||||
# Create LED strip and engine for testing
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test default gradient (rainbow linear)
|
||||
var gradient = animation.gradient_animation(engine)
|
||||
@ -47,7 +47,7 @@ def test_gradient_parameters()
|
||||
print("Testing GradientAnimation parameters...")
|
||||
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var gradient = animation.gradient_animation(engine)
|
||||
gradient.color = 0xFFFFFFFF
|
||||
gradient.name = "test"
|
||||
@ -80,7 +80,7 @@ def test_gradient_updates()
|
||||
print("Testing GradientAnimation updates...")
|
||||
|
||||
var strip = global.Leds(5)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var gradient = animation.gradient_animation(engine)
|
||||
gradient.color = 0xFF00FF00
|
||||
gradient.movement_speed = 100
|
||||
@ -109,7 +109,7 @@ def test_gradient_rendering()
|
||||
print("Testing GradientAnimation rendering...")
|
||||
|
||||
var strip = global.Leds(5)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var gradient = animation.gradient_animation(engine)
|
||||
gradient.color = 0xFFFF0000
|
||||
gradient.movement_speed = 0
|
||||
@ -141,7 +141,7 @@ def test_gradient_factory_methods()
|
||||
print("Testing GradientAnimation factory methods...")
|
||||
|
||||
var strip = global.Leds(20)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test rainbow linear factory
|
||||
var rainbow_linear = animation.gradient_rainbow_linear(engine)
|
||||
@ -170,7 +170,7 @@ def test_gradient_position_calculations()
|
||||
print("Testing GradientAnimation position calculations...")
|
||||
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test linear gradient with different directions
|
||||
var linear_gradient = animation.gradient_animation(engine)
|
||||
@ -212,7 +212,7 @@ def test_gradient_color_refactoring()
|
||||
print("Testing GradientAnimation color refactoring...")
|
||||
|
||||
var strip = global.Leds(5)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test with static color
|
||||
var static_gradient = animation.gradient_animation(engine)
|
||||
@ -250,7 +250,7 @@ def test_gradient_virtual_parameters()
|
||||
print("Testing GradientAnimation virtual parameters...")
|
||||
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var gradient = animation.gradient_animation(engine)
|
||||
gradient.name = "test"
|
||||
|
||||
@ -283,7 +283,7 @@ def test_gradient_tostring()
|
||||
import string
|
||||
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test with static color
|
||||
var static_gradient = animation.gradient_animation(engine)
|
||||
|
||||
@ -5,7 +5,7 @@ print("Testing gradient rainbow with light_state HSV conversion...")
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test rainbow gradient (nil color)
|
||||
var rainbow_gradient = animation.gradient_animation(engine)
|
||||
|
||||
@ -5,7 +5,7 @@ print("Testing basic GradientAnimation functionality...")
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(5)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test basic creation
|
||||
var gradient = animation.gradient_animation(engine)
|
||||
|
||||
@ -12,7 +12,7 @@ def test_jitter_animation_basic()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Create a simple source animation
|
||||
var source = animation.solid(engine)
|
||||
@ -39,7 +39,7 @@ def test_jitter_animation_custom()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(20)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF00FF00
|
||||
@ -70,7 +70,7 @@ def test_jitter_animation_parameters()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(15)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF0000FF
|
||||
@ -110,7 +110,7 @@ def test_jitter_animation_types()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFFFFFF00
|
||||
@ -144,7 +144,7 @@ def test_jitter_animation_update_render()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFFFF00FF
|
||||
@ -182,7 +182,7 @@ def test_jitter_animation_random()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF00FFFF
|
||||
@ -211,7 +211,7 @@ def test_jitter_constructors()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(15)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFFAAAAAA
|
||||
@ -262,7 +262,7 @@ def test_jitter_animation_color_effects()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF808080
|
||||
@ -290,7 +290,7 @@ def test_jitter_tostring()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(12)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF666666
|
||||
|
||||
@ -12,7 +12,7 @@ def test_bounce_animation_basic()
|
||||
|
||||
# Create engine and source animation
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFFFF0000
|
||||
|
||||
@ -37,7 +37,7 @@ def test_scale_animation_basic()
|
||||
|
||||
# Create engine and source animation
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF00FF00
|
||||
|
||||
@ -62,7 +62,7 @@ def test_jitter_animation_basic()
|
||||
|
||||
# Create engine and source animation
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF0000FF
|
||||
|
||||
@ -87,7 +87,7 @@ def test_motion_effects_custom()
|
||||
print("Testing motion effects with custom parameters...")
|
||||
|
||||
var strip = global.Leds(20)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFFFFFF00
|
||||
|
||||
@ -156,7 +156,7 @@ def test_motion_effects_update_render()
|
||||
print("Testing motion effects update and render...")
|
||||
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFFFF00FF
|
||||
var frame = animation.frame_buffer(10)
|
||||
@ -223,7 +223,7 @@ def test_motion_effects_constructors()
|
||||
print("Testing motion effects constructor functions...")
|
||||
|
||||
var strip = global.Leds(30)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF00FFFF
|
||||
|
||||
@ -279,7 +279,7 @@ def test_motion_effects_tostring()
|
||||
print("Testing motion effects string representations...")
|
||||
|
||||
var strip = global.Leds(12)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFFFFFFFF
|
||||
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
# Test for nillable parameter attribute
|
||||
import animation
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
print("Testing nillable parameter attribute...")
|
||||
|
||||
# Create a test class with nillable and non-nillable parameters
|
||||
class TestParameterizedClass : animation.parameterized_object
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"nillable_param": {"type": "int", "nillable": true},
|
||||
"non_nillable_param": {"type": "int"} # No default, no nillable
|
||||
}
|
||||
})
|
||||
|
||||
def init(engine)
|
||||
super(self).init(engine)
|
||||
@ -17,7 +19,7 @@ end
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(5)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test nillable parameter
|
||||
var test_obj = TestParameterizedClass(engine)
|
||||
|
||||
@ -12,7 +12,7 @@ def test_noise_animation_basic()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test with default parameters
|
||||
var noise_anim = animation.noise_animation(engine)
|
||||
@ -32,7 +32,7 @@ def test_noise_animation_custom()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(20)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test with custom parameters
|
||||
var noise_anim = animation.noise_animation(engine)
|
||||
@ -64,7 +64,7 @@ def test_noise_animation_parameters()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(15)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var noise_anim = animation.noise_animation(engine)
|
||||
|
||||
@ -91,7 +91,7 @@ def test_noise_animation_update_render()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var noise_anim = animation.noise_animation(engine)
|
||||
noise_anim.color = 0xFFFF0000
|
||||
@ -133,7 +133,7 @@ def test_noise_constructors()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(15)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test noise_rainbow
|
||||
var rainbow_noise = animation.noise_rainbow(engine)
|
||||
@ -164,7 +164,7 @@ def test_noise_tostring()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(12)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var noise_anim = animation.noise_animation(engine)
|
||||
noise_anim.scale = 75
|
||||
@ -188,7 +188,7 @@ def test_noise_integer_color_conversion()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(5)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var noise_anim = animation.noise_animation(engine)
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ import string
|
||||
|
||||
# Create a real engine for testing using global.Leds()
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test the EASE_IN waveform
|
||||
def test_ease_in_waveform()
|
||||
|
||||
@ -8,7 +8,7 @@ import string
|
||||
|
||||
# Create a real engine for testing using global.Leds()
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test the ELASTIC waveform
|
||||
def test_elastic_waveform()
|
||||
|
||||
@ -6,13 +6,15 @@
|
||||
import animation
|
||||
import global
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
# Test that parameters accept ValueProviders and integers only
|
||||
def test_parameter_accepts_value_providers()
|
||||
print("Testing parameter validation with ValueProviders...")
|
||||
|
||||
# Create engine for testing
|
||||
var strip = global.Leds()
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Create a test animation using new constructor pattern
|
||||
var test_anim = animation.animation(engine)
|
||||
@ -48,7 +50,7 @@ def test_loop_boolean_validation()
|
||||
|
||||
# Create engine for testing
|
||||
var strip = global.Leds()
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Create a test animation
|
||||
var test_anim = animation.animation(engine)
|
||||
@ -77,7 +79,7 @@ def test_range_validation()
|
||||
|
||||
# Create engine for testing
|
||||
var strip = global.Leds()
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Create a test animation
|
||||
var test_anim = animation.animation(engine)
|
||||
@ -96,7 +98,7 @@ def test_range_validation_with_providers()
|
||||
|
||||
# Create engine for testing
|
||||
var strip = global.Leds()
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Create a test animation
|
||||
var test_anim = animation.animation(engine)
|
||||
@ -123,18 +125,18 @@ def test_type_validation()
|
||||
|
||||
# Create engine for testing
|
||||
var strip = global.Leds()
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Create a test class with different parameter types
|
||||
class TestClass : animation.parameterized_object
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"int_param": {"default": 42}, # Default type is "int"
|
||||
"explicit_int_param": {"type": "int", "default": 10},
|
||||
"string_param": {"type": "string", "default": "hello"},
|
||||
"bool_param": {"type": "bool", "default": true},
|
||||
"instance_param": {"type": "instance", "default": nil},
|
||||
"any_param": {"type": "any", "default": nil}
|
||||
}
|
||||
})
|
||||
|
||||
def init(engine)
|
||||
super(self).init(engine)
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
|
||||
import animation
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
# Create a mock engine for testing
|
||||
class MockEngine
|
||||
var time_ms
|
||||
@ -24,11 +26,11 @@ def test_parameterized_object_basic()
|
||||
class TestObject : animation.parameterized_object
|
||||
# No instance variables for parameters - they're handled by the virtual system
|
||||
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"test_value": {"min": 0, "max": 100, "default": 50},
|
||||
"test_name": {"type": "string", "default": "test"},
|
||||
"test_enum": {"enum": [1, 2, 3], "default": 1}
|
||||
}
|
||||
})
|
||||
|
||||
def init(engine, value, name)
|
||||
super(self).init(engine) # This initializes parameters with defaults
|
||||
@ -93,10 +95,10 @@ def test_parameter_hierarchy()
|
||||
|
||||
# Create a base class with some parameters
|
||||
class BaseClass : animation.parameterized_object
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"base_param": {"type": "string", "default": "base_value"},
|
||||
"shared_param": {"type": "string", "default": "base_default"}
|
||||
}
|
||||
})
|
||||
|
||||
def init(engine)
|
||||
super(self).init(engine)
|
||||
@ -105,10 +107,10 @@ def test_parameter_hierarchy()
|
||||
|
||||
# Create a child class with additional parameters
|
||||
class ChildClass : BaseClass
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"child_param": {"min": 0, "max": 10, "default": 5},
|
||||
"shared_param": {"type": "string", "default": "child_default"} # Override parent default
|
||||
}
|
||||
})
|
||||
|
||||
def init(engine)
|
||||
super(self).init(engine)
|
||||
@ -142,9 +144,9 @@ def test_value_provider_as_parameter()
|
||||
|
||||
# Create a simple test class
|
||||
class TestClass : animation.parameterized_object
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"dynamic_value": {"min": 0, "max": 100, "default": 50}
|
||||
}
|
||||
})
|
||||
|
||||
def init(engine)
|
||||
super(self).init(engine)
|
||||
@ -191,11 +193,11 @@ def test_parameter_metadata()
|
||||
print("Testing parameter metadata...")
|
||||
|
||||
class TestClass : animation.parameterized_object
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"range_param": {"min": 0, "max": 100, "default": 50},
|
||||
"enum_param": {"enum": [1, 2, 3], "default": 1},
|
||||
"simple_param": {"type": "string", "default": "test"}
|
||||
}
|
||||
})
|
||||
|
||||
def init(engine)
|
||||
super(self).init(engine)
|
||||
@ -204,17 +206,19 @@ def test_parameter_metadata()
|
||||
|
||||
var obj = TestClass(mock_engine)
|
||||
|
||||
# Test getting single parameter metadata
|
||||
var range_meta = obj.get_param_metadata("range_param")
|
||||
assert(range_meta != nil, "Should get range parameter metadata")
|
||||
assert(range_meta["min"] == 0, "Should have min constraint")
|
||||
assert(range_meta["max"] == 100, "Should have max constraint")
|
||||
assert(range_meta["default"] == 50, "Should have default value")
|
||||
# Test getting single parameter definition
|
||||
assert(obj._has_param("range_param") == true, "range_param should exist")
|
||||
var range_def = obj._get_param_def("range_param")
|
||||
assert(range_def != nil, "Should get range parameter definition")
|
||||
assert(obj.constraint_find(range_def, "min", nil) == 0, "Should have min constraint")
|
||||
assert(obj.constraint_find(range_def, "max", nil) == 100, "Should have max constraint")
|
||||
assert(obj.constraint_find(range_def, "default", nil) == 50, "Should have default value")
|
||||
|
||||
var enum_meta = obj.get_param_metadata("enum_param")
|
||||
assert(enum_meta != nil, "Should get enum parameter metadata")
|
||||
assert(enum_meta.contains("enum"), "Should have enum constraint")
|
||||
assert(enum_meta["default"] == 1, "Should have default value")
|
||||
assert(obj._has_param("enum_param") == true, "enum_param should exist")
|
||||
var enum_def = obj._get_param_def("enum_param")
|
||||
assert(enum_def != nil, "Should get enum parameter definition")
|
||||
assert(obj.constraint_mask(enum_def, "enum") == 0x10, "Should have enum constraint")
|
||||
assert(obj.constraint_find(enum_def, "default", nil) == 1, "Should have default value")
|
||||
|
||||
print("✓ Parameter metadata test passed")
|
||||
end
|
||||
@ -224,9 +228,9 @@ def test_virtual_member_errors()
|
||||
print("Testing virtual member error handling...")
|
||||
|
||||
class TestClass : animation.parameterized_object
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"valid_param": {"min": 0, "max": 100, "default": 50}
|
||||
}
|
||||
})
|
||||
|
||||
def init(engine)
|
||||
super(self).init(engine)
|
||||
@ -275,9 +279,9 @@ def test_undefined_parameter_behavior()
|
||||
import string # Import once at the top of the function
|
||||
|
||||
class TestClass : animation.parameterized_object
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"defined_param": {"min": 0, "max": 100, "default": 50}
|
||||
}
|
||||
})
|
||||
|
||||
def init(engine)
|
||||
super(self).init(engine)
|
||||
@ -354,10 +358,11 @@ def test_undefined_parameter_behavior()
|
||||
obj.defined_param = 75
|
||||
assert(obj.defined_param == 75, "Defined parameter assignment should still work")
|
||||
|
||||
# Test get_param_metadata for undefined parameter
|
||||
print(" Testing metadata for undefined parameter...")
|
||||
var undefined_meta = obj.get_param_metadata("undefined_param")
|
||||
assert(undefined_meta == nil, "Metadata for undefined parameter should be nil")
|
||||
# Test _has_param and _get_param_def for undefined parameter
|
||||
print(" Testing parameter definition for undefined parameter...")
|
||||
assert(obj._has_param("undefined_param") == false, "_has_param for undefined parameter should return false")
|
||||
var undefined_def = obj._get_param_def("undefined_param")
|
||||
assert(undefined_def == nil, "_get_param_def for undefined parameter should be nil")
|
||||
|
||||
# Test get_param_value for undefined parameter
|
||||
print(" Testing get_param_value for undefined parameter...")
|
||||
@ -372,9 +377,9 @@ def test_engine_requirement()
|
||||
print("Testing engine parameter requirement...")
|
||||
|
||||
class TestClass : animation.parameterized_object
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"test_param": {"default": 42}
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
# Test that nil engine raises error
|
||||
@ -398,9 +403,9 @@ def test_equality_operator()
|
||||
print("Testing equality operator...")
|
||||
|
||||
class TestClass : animation.parameterized_object
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"test_param": {"default": 42}
|
||||
}
|
||||
})
|
||||
|
||||
def init(engine)
|
||||
super(self).init(engine)
|
||||
|
||||
@ -12,7 +12,7 @@ def test_plasma_animation_basic()
|
||||
|
||||
# Create LED strip and engine for testing
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test with default parameters
|
||||
var plasma_anim = animation.plasma_animation(engine)
|
||||
@ -36,7 +36,7 @@ def test_plasma_animation_custom()
|
||||
|
||||
# Create LED strip and engine for testing
|
||||
var strip = global.Leds(20)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test with custom parameters using virtual member assignment
|
||||
var plasma_anim = animation.plasma_animation(engine)
|
||||
@ -71,7 +71,7 @@ def test_plasma_animation_parameters()
|
||||
|
||||
# Create LED strip and engine for testing
|
||||
var strip = global.Leds(15)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var plasma_anim = animation.plasma_animation(engine)
|
||||
plasma_anim.name = "param_test"
|
||||
@ -102,7 +102,7 @@ def test_plasma_animation_update_render()
|
||||
|
||||
# Create LED strip and engine for testing
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var plasma_anim = animation.plasma_animation(engine)
|
||||
plasma_anim.color = 0xFFFF0000
|
||||
@ -146,7 +146,7 @@ def test_plasma_constructors()
|
||||
|
||||
# Create LED strip and engine for testing
|
||||
var strip = global.Leds(15)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test plasma_rainbow
|
||||
var rainbow_plasma = animation.plasma_rainbow(engine)
|
||||
@ -170,7 +170,7 @@ def test_plasma_tostring()
|
||||
|
||||
# Create LED strip and engine for testing
|
||||
var strip = global.Leds(12)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var plasma_anim = animation.plasma_animation(engine)
|
||||
plasma_anim.freq_x = 55
|
||||
|
||||
@ -13,7 +13,7 @@ print("Imported animation module")
|
||||
|
||||
# Create LED strip and engine for testing
|
||||
var strip = global.Leds(10) # Use global.Leds() for testing as per specification
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
print("Created engine and LED strip")
|
||||
|
||||
# Create a pulse animation with new constructor (engine only)
|
||||
|
||||
@ -11,7 +11,7 @@ print("Imported animation module")
|
||||
|
||||
# Create LED strip and engine for testing (following specification)
|
||||
var strip = global.Leds(10) # Use global.Leds() for testing as per specification
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
print("Created test engine with 10 LEDs")
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ def test_scale_animation_basic()
|
||||
|
||||
# Create LED strip and engine using global.Leds
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Create a simple source animation
|
||||
var source = animation.solid(engine)
|
||||
@ -38,7 +38,7 @@ def test_scale_animation_custom()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(20)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF00FF00
|
||||
@ -67,7 +67,7 @@ def test_scale_animation_parameters()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(15)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF0000FF
|
||||
@ -104,7 +104,7 @@ def test_scale_animation_modes()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFFFFFF00
|
||||
@ -155,7 +155,7 @@ def test_scale_animation_interpolation()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF808080
|
||||
@ -184,7 +184,7 @@ def test_scale_animation_sine()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF000000
|
||||
@ -217,7 +217,7 @@ def test_scale_animation_update_render()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFFFF00FF
|
||||
@ -257,7 +257,7 @@ def test_scale_constructors()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(15)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF00FFFF
|
||||
@ -296,7 +296,7 @@ def test_scale_tostring()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(12)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF444444
|
||||
|
||||
@ -34,7 +34,7 @@ def test_sequence_manager_step_creation()
|
||||
|
||||
# Create test animation using new parameterized API
|
||||
var strip = global.Leds(30)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var color_provider = animation.static_color(engine)
|
||||
color_provider.color = 0xFFFF0000
|
||||
var test_anim = animation.solid(engine)
|
||||
@ -183,10 +183,6 @@ def test_sequence_manager_step_info()
|
||||
var engine = animation.create_engine(strip)
|
||||
var seq_manager = animation.SequenceManager(engine)
|
||||
|
||||
# Test step info when not running
|
||||
var step_info = seq_manager.get_current_step_info()
|
||||
assert(step_info == nil, "Step info should be nil when not running")
|
||||
|
||||
# Create test sequence using new parameterized API
|
||||
var color_provider = animation.static_color(engine)
|
||||
color_provider.color = 0xFFFF0000
|
||||
@ -206,14 +202,6 @@ def test_sequence_manager_step_info()
|
||||
engine.run() # Start the engine
|
||||
engine.on_tick(30000) # Update engine time
|
||||
|
||||
# Get step info
|
||||
step_info = seq_manager.get_current_step_info()
|
||||
assert(step_info != nil, "Step info should not be nil when running")
|
||||
assert(step_info["step_index"] == 0, "Step info should show correct step index")
|
||||
assert(step_info["total_steps"] == 2, "Step info should show correct total steps")
|
||||
assert(step_info["current_step"]["type"] == "play", "Step info should show correct step type")
|
||||
assert(step_info["elapsed_ms"] >= 0, "Step info should show elapsed time")
|
||||
|
||||
print("✓ Step info tests passed")
|
||||
end
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ def test_shift_animation_basic()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Create a simple source animation
|
||||
var source = animation.solid(engine)
|
||||
@ -37,7 +37,7 @@ def test_shift_animation_custom()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(20)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF00FF00
|
||||
@ -68,7 +68,7 @@ def test_shift_animation_parameters()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(15)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF0000FF
|
||||
@ -100,7 +100,7 @@ def test_shift_animation_update_render()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFFFFFF00
|
||||
@ -144,7 +144,7 @@ def test_shift_constructors()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(15)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFFFF00FF
|
||||
@ -183,7 +183,7 @@ def test_shift_tostring()
|
||||
|
||||
# Create LED strip and engine
|
||||
var strip = global.Leds(12)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var source = animation.solid(engine)
|
||||
source.color = 0xFF00FFFF
|
||||
|
||||
@ -11,7 +11,7 @@ print("Imported animation module")
|
||||
|
||||
# Create LED strip and engine for testing (following specification)
|
||||
var strip = global.Leds(10) # Use global.Leds() for testing as per specification
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
print("Created test engine with 10 LEDs")
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ import animation
|
||||
|
||||
# Create test engine (following specification)
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
def test_unified_solid_function()
|
||||
print("Testing unified solid() function...")
|
||||
|
||||
@ -12,7 +12,7 @@ def test_sparkle_animation_basic()
|
||||
|
||||
# Create LED strip and engine for testing
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test with default parameters
|
||||
var sparkle_anim = animation.sparkle_animation(engine)
|
||||
@ -35,7 +35,7 @@ def test_sparkle_animation_custom()
|
||||
|
||||
# Create LED strip and engine for testing
|
||||
var strip = global.Leds(20)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test with custom parameters using new parameterized pattern
|
||||
var sparkle_anim = animation.sparkle_animation(engine)
|
||||
@ -70,7 +70,7 @@ def test_sparkle_animation_parameters()
|
||||
|
||||
# Create LED strip and engine for testing
|
||||
var strip = global.Leds(15)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var sparkle_anim = animation.sparkle_animation(engine)
|
||||
sparkle_anim.name = "param_test"
|
||||
@ -102,7 +102,7 @@ def test_sparkle_animation_update_render()
|
||||
|
||||
# Create LED strip and engine for testing
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var sparkle_anim = animation.sparkle_animation(engine)
|
||||
sparkle_anim.color = 0xFFFF0000
|
||||
@ -153,7 +153,7 @@ def test_sparkle_constructors()
|
||||
|
||||
# Create LED strip and engine for testing
|
||||
var strip = global.Leds(15)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test sparkle_white
|
||||
var white_sparkle = animation.sparkle_white(engine)
|
||||
@ -185,7 +185,7 @@ def test_sparkle_tostring()
|
||||
|
||||
# Create LED strip and engine for testing
|
||||
var strip = global.Leds(12)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var sparkle_anim = animation.sparkle_animation(engine)
|
||||
sparkle_anim.density = 75
|
||||
|
||||
@ -12,7 +12,7 @@ def test_static_value_provider_interface()
|
||||
|
||||
# Create engine for testing
|
||||
var strip = global.Leds()
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var provider = animation.static_value(engine)
|
||||
|
||||
@ -34,7 +34,7 @@ def test_static_value_provider_types()
|
||||
|
||||
# Create engine for testing
|
||||
var strip = global.Leds()
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test with integer
|
||||
var int_provider = animation.static_value(engine)
|
||||
@ -60,7 +60,7 @@ def test_universal_get_methods()
|
||||
|
||||
# Create engine for testing
|
||||
var strip = global.Leds()
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var provider = animation.static_value(engine)
|
||||
provider.value = 99
|
||||
@ -96,7 +96,7 @@ def test_comparison_operators()
|
||||
|
||||
# Create engine for testing
|
||||
var strip = global.Leds()
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var provider = animation.static_value(engine)
|
||||
provider.value = 50
|
||||
@ -118,7 +118,7 @@ def test_parameterized_object_integration()
|
||||
|
||||
# Create engine for testing
|
||||
var strip = global.Leds()
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var provider = animation.static_value(engine)
|
||||
|
||||
@ -144,7 +144,7 @@ def test_value_changes()
|
||||
|
||||
# Create engine for testing
|
||||
var strip = global.Leds()
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var provider = animation.static_value(engine)
|
||||
|
||||
@ -170,7 +170,7 @@ def test_string_representation()
|
||||
|
||||
# Create engine for testing
|
||||
var strip = global.Leds()
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var provider = animation.static_value(engine)
|
||||
provider.value = 42
|
||||
|
||||
@ -49,7 +49,7 @@ def test_basic_functionality()
|
||||
for length : test_lengths
|
||||
# Create mock strip and engine
|
||||
var strip = MockStrip(length)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Create StripLengthProvider
|
||||
var provider = animation.strip_length(engine)
|
||||
@ -75,7 +75,7 @@ def test_string_representation()
|
||||
print(" Testing string representation...")
|
||||
|
||||
var strip = MockStrip(42)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var provider = animation.strip_length(engine)
|
||||
|
||||
var str_repr = str(provider)
|
||||
@ -106,7 +106,7 @@ def test_integration()
|
||||
print(" Testing integration with animation system...")
|
||||
|
||||
var strip = MockStrip(20)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var provider = animation.strip_length(engine)
|
||||
|
||||
# Test that it's recognized as a value provider
|
||||
@ -128,7 +128,7 @@ def test_engine_consistency()
|
||||
print(" Testing consistency with engine properties...")
|
||||
|
||||
var strip = MockStrip(100)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var provider = animation.strip_length(engine)
|
||||
|
||||
# Test that provider returns same value as engine properties
|
||||
|
||||
@ -47,6 +47,7 @@ def run_all_tests()
|
||||
|
||||
# Core framework tests
|
||||
"lib/libesp32/berry_animation/src/tests/frame_buffer_test.be",
|
||||
"lib/libesp32/berry_animation/src/tests/constraint_encoding_test.be", # Tests parameter constraint encoding/decoding
|
||||
"lib/libesp32/berry_animation/src/tests/nillable_parameter_test.be",
|
||||
"lib/libesp32/berry_animation/src/tests/parameterized_object_test.be", # Tests parameter management base class
|
||||
"lib/libesp32/berry_animation/src/tests/bytes_type_test.be", # Tests bytes type validation in parameterized objects
|
||||
|
||||
@ -13,7 +13,7 @@ print("=== Comprehensive Twinkle Animation Test ===")
|
||||
# Test 1: Basic Twinkle Animation Creation
|
||||
print("\n1. Testing basic twinkle animation creation...")
|
||||
var strip = global.Leds(30)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var twinkle = animation.twinkle_animation(engine)
|
||||
twinkle.color = 0xFFFFFFFF
|
||||
twinkle.density = 128
|
||||
@ -384,7 +384,7 @@ print("\n16. Testing edge cases...")
|
||||
|
||||
# Very small strip
|
||||
var tiny_strip = global.Leds(1)
|
||||
var tiny_engine = animation.animation_engine(tiny_strip)
|
||||
var tiny_engine = animation.create_engine(tiny_strip)
|
||||
var tiny_twinkle = animation.twinkle_classic(tiny_engine)
|
||||
tiny_twinkle.density = 200
|
||||
tiny_twinkle.start()
|
||||
|
||||
@ -5,13 +5,15 @@
|
||||
|
||||
import animation
|
||||
|
||||
import "./core/param_encoder" as encode_constraints
|
||||
|
||||
# Test the basic ValueProvider interface
|
||||
def test_value_provider_interface()
|
||||
print("Testing ValueProvider interface...")
|
||||
|
||||
# Create engine for testing
|
||||
var strip = global.Leds()
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var provider = animation.value_provider(engine)
|
||||
|
||||
@ -32,14 +34,14 @@ def test_custom_value_provider()
|
||||
|
||||
# Create engine for testing
|
||||
var strip = global.Leds()
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Create a simple time-based provider using new API
|
||||
class TimeBasedProvider : animation.value_provider
|
||||
# Parameter definitions
|
||||
static var PARAMS = {
|
||||
static var PARAMS = encode_constraints({
|
||||
"multiplier": {"default": 1}
|
||||
}
|
||||
})
|
||||
|
||||
def init(engine)
|
||||
super(self).init(engine)
|
||||
@ -71,7 +73,7 @@ def test_is_value_provider()
|
||||
|
||||
# Create engine for testing
|
||||
var strip = global.Leds()
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var base_provider = animation.value_provider(engine)
|
||||
|
||||
@ -89,7 +91,7 @@ def test_parameterized_object_integration()
|
||||
|
||||
# Create engine for testing
|
||||
var strip = global.Leds()
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
var provider = animation.value_provider(engine)
|
||||
|
||||
@ -113,7 +115,7 @@ def test_lifecycle_methods()
|
||||
|
||||
# Create engine for testing
|
||||
var strip = global.Leds()
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Create a provider that tracks start calls
|
||||
class LifecycleProvider : animation.value_provider
|
||||
|
||||
@ -12,7 +12,7 @@ def test_wave_animation_basic()
|
||||
|
||||
# Create engine and animation
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var wave_anim = animation.wave_animation(engine)
|
||||
|
||||
assert(wave_anim != nil, "WaveAnimation should be created")
|
||||
@ -34,7 +34,7 @@ def test_wave_animation_custom()
|
||||
|
||||
# Create engine and animation with custom parameters
|
||||
var strip = global.Leds(20)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var wave_anim = animation.wave_animation(engine)
|
||||
|
||||
# Set custom parameters using virtual member access
|
||||
@ -69,7 +69,7 @@ def test_wave_animation_parameters()
|
||||
print("Testing WaveAnimation parameter changes...")
|
||||
|
||||
var strip = global.Leds(15)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var wave_anim = animation.wave_animation(engine)
|
||||
|
||||
# Test parameter changes using virtual member access
|
||||
@ -96,7 +96,7 @@ def test_wave_animation_update_render()
|
||||
print("Testing WaveAnimation update and render...")
|
||||
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var wave_anim = animation.wave_animation(engine)
|
||||
|
||||
# Set parameters
|
||||
@ -141,7 +141,7 @@ def test_wave_types()
|
||||
print("Testing different wave types...")
|
||||
|
||||
var strip = global.Leds(10)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var frame = animation.frame_buffer(10)
|
||||
|
||||
# Test each wave type
|
||||
@ -172,7 +172,7 @@ def test_wave_constructors()
|
||||
print("Testing wave constructor functions...")
|
||||
|
||||
var strip = global.Leds(30)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
|
||||
# Test wave_rainbow_sine
|
||||
var rainbow_wave = animation.wave_rainbow_sine(engine)
|
||||
@ -203,7 +203,7 @@ def test_wave_tostring()
|
||||
print("Testing WaveAnimation string representation...")
|
||||
|
||||
var strip = global.Leds(12)
|
||||
var engine = animation.animation_engine(strip)
|
||||
var engine = animation.create_engine(strip)
|
||||
var wave_anim = animation.wave_animation(engine)
|
||||
|
||||
# Set parameters
|
||||
|
||||
@ -621,8 +621,8 @@
|
||||
#define USE_LIGHT_ARTNET_MCAST 239,255,25,54 // Multicast address used to listen: 239.255.25.54
|
||||
|
||||
#define USE_BERRY_ANIMATE // Legacy tentative for LED animation framework, DEPRECATED
|
||||
// #define USE_BERRY_ANIMATION // New animation framework with dedicated language (ESP32x only, experimental, 117k not yet optimized)
|
||||
// #define USE_BERRY_ANIMATION_DSL // DSL transpiler for new animation framework (not mandatory if DSL is transpiled externally, +59k not optimized yet)
|
||||
// #define USE_BERRY_ANIMATION // New animation framework with dedicated language (ESP32x only, experimental, 94k not yet optimized)
|
||||
// #define USE_BERRY_ANIMATION_DSL // DSL transpiler for new animation framework (not mandatory if DSL is transpiled externally, +98k not optimized yet)
|
||||
|
||||
// -- Counter input -------------------------------
|
||||
#define USE_COUNTER // Enable inputs as counter (+0k8 code)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user