use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct PaintInformation {
pub pos: [f32; 2],
pub pressure: f32,
pub x_tilt: f32,
pub y_tilt: f32,
pub rotation: f32,
pub tangential_pressure: f32,
pub time: f32,
pub speed: f32,
pub distance: f32,
pub drawing_angle: f32,
pub motion: [f32; 2],
pub tilt_magnitude: f32,
pub tilt_direction: f32,
pub index: u32,
pub fade: f32,
}
pub const MAX_SPEED_PX_PER_SEC: f32 = 4000.0;
impl PaintInformation {
pub fn cursor_preview_dummy() -> Self {
Self {
pressure: 1.0,
..Default::default()
}
}
pub fn derive_sensors(&mut self, prev: Option<&Self>, segment_length: f32) {
self.tilt_magnitude = (self.x_tilt * self.x_tilt + self.y_tilt * self.y_tilt)
.sqrt()
.min(1.0);
self.tilt_direction = self.y_tilt.atan2(self.x_tilt);
let Some(prev) = prev else {
return;
};
let dx = self.pos[0] - prev.pos[0];
let dy = self.pos[1] - prev.pos[1];
if segment_length > 1.0e-3 {
self.drawing_angle = dy.atan2(dx);
} else {
self.drawing_angle = prev.drawing_angle;
}
self.distance = prev.distance + segment_length;
let dt = self.time - prev.time;
if dt > 0.0 {
let speed_px_per_sec = segment_length / dt;
self.speed = (speed_px_per_sec / MAX_SPEED_PX_PER_SEC).min(1.0);
} else {
self.speed = prev.speed;
}
}
}
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct StrokeRecord {
pub events: Vec<PaintInformation>,
pub color: [f32; 4],
pub brush_graph_id: String,
}
impl StrokeRecord {
pub fn new(color: [f32; 4], brush_graph_id: String) -> Self {
Self {
events: Vec::with_capacity(256),
color,
brush_graph_id,
}
}
pub fn push(&mut self, info: PaintInformation) {
self.events.push(info);
}
pub fn len(&self) -> usize {
self.events.len()
}
pub fn is_empty(&self) -> bool {
self.events.is_empty()
}
}