use crate::fluid::hsv_to_rgb;
use rand::Rng;
#[derive(Debug, Clone)]
pub struct InputPoint {
pub id: u32,
pub x: f32,
pub y: f32,
pub prev_x: f32,
pub prev_y: f32,
pub active: bool,
pub moved: bool,
pub color: [f32; 3],
}
impl InputPoint {
fn new(id: u32, x: f32, y: f32, color: [f32; 3]) -> Self {
Self {
id, x, y,
prev_x: x, prev_y: y,
active: true, moved: false, color,
}
}
}
#[derive(Debug, Clone)]
pub struct SplatEvent {
pub x: f32,
pub y: f32,
pub dx: f32,
pub dy: f32,
pub color: [f32; 3],
}
pub struct InputManager {
pub(crate) points: Vec<InputPoint>,
pub(crate) splat_queue: Vec<SplatEvent>,
pub(crate) burst_queue: Vec<u32>,
}
impl InputManager {
pub fn new() -> Self {
Self {
points: Vec::new(),
splat_queue: Vec::new(),
burst_queue: Vec::new(),
}
}
pub fn pointer_down(&mut self, id: u32, x: f32, y: f32, color: Option<[f32; 3]>) {
let color = color.unwrap_or_else(random_color);
if let Some(p) = self.points.iter_mut().find(|p| p.id == id) {
p.active = true;
p.x = x;
p.y = y;
p.prev_x = x;
p.prev_y = y;
p.moved = false;
p.color = color;
} else {
self.points.push(InputPoint::new(id, x, y, color));
}
}
pub fn pointer_move(&mut self, id: u32, x: f32, y: f32) {
if let Some(p) = self.points.iter_mut().find(|p| p.id == id) {
p.prev_x = p.x;
p.prev_y = p.y;
p.x = x;
p.y = y;
let dx = x - p.prev_x;
let dy = y - p.prev_y;
p.moved = dx != 0.0 || dy != 0.0;
}
}
pub fn pointer_up(&mut self, id: u32) {
if let Some(p) = self.points.iter_mut().find(|p| p.id == id) {
p.active = false;
}
}
pub fn inject(&mut self, x: f32, y: f32, dx: f32, dy: f32, color: [f32; 3]) {
self.splat_queue.push(SplatEvent { x, y, dx, dy, color });
}
pub fn burst(&mut self, count: u32) {
self.burst_queue.push(count);
}
pub fn drain(&mut self) -> (&[InputPoint], Vec<SplatEvent>, Vec<u32>) {
let splats = std::mem::take(&mut self.splat_queue);
let bursts = std::mem::take(&mut self.burst_queue);
(&self.points, splats, bursts)
}
pub fn points(&self) -> &[InputPoint] {
&self.points
}
pub fn active_count(&self) -> usize {
self.points.iter().filter(|p| p.active).count()
}
}
impl Default for InputManager {
fn default() -> Self { Self::new() }
}
pub fn random_color() -> [f32; 3] {
let mut rng = rand::thread_rng();
let [r, g, b] = hsv_to_rgb(rng.gen::<f32>(), 1.0, 1.0);
[r * 0.15, g * 0.15, b * 0.15]
}