pub mod electric_spark;
pub mod flowing_light;
pub mod pulse_ripple;
pub mod rotating_halo;
pub mod smoke_wisp;
pub mod stardust_scatter;
pub mod aurora_wave;
pub mod cosmic_strings;
pub mod heartbeat_pulse;
pub mod laser_beam;
pub mod lightning_arc;
pub mod matrix_rain;
pub mod meteor_shower;
pub mod orbit_rings;
pub mod rain_drop;
pub mod silk_ribbon;
pub mod sonar_pulse;
use super::PresetEffectOptions;
use rand::Rng;
pub fn random_color(options: &PresetEffectOptions) -> [f32; 4] {
if options.particle_colors.is_empty() {
[1.0, 1.0, 1.0, 1.0]
} else {
let idx = rand::rng().random_range(0..options.particle_colors.len());
options.particle_colors[idx]
}
}
pub fn random_size(options: &PresetEffectOptions) -> f32 {
let (min, max) = options.particle_size;
rand::rng().random_range(min..=max)
}
pub fn edge_position(t: f32, width: f32, height: f32) -> (f32, f32) {
let perimeter = 2.0 * (width + height);
let pos = t * perimeter;
if pos < width {
(pos, 0.0)
} else if pos < width + height {
(width, pos - width)
} else if pos < 2.0 * width + height {
(2.0 * width + height - pos, height)
} else {
(0.0, perimeter - pos)
}
}
pub fn center(width: f32, height: f32) -> (f32, f32) {
(width / 2.0, height / 2.0)
}
pub fn circle_edge_outside(t: f32, width: f32, height: f32, gap: f32) -> (f32, f32) {
use std::f32::consts::PI;
let cx = width / 2.0;
let cy = height / 2.0;
let radius = width.min(height) / 2.0 + gap;
let angle = t * 2.0 * PI;
(cx + radius * angle.cos(), cy + radius * angle.sin())
}
pub fn outward_direction(t: f32) -> (f32, f32) {
use std::f32::consts::PI;
let angle = t * 2.0 * PI;
(angle.cos(), angle.sin())
}